Oracle review of PR #3943 surfaced that endTaskTimer never fires for real Prometheus plans because their canonical path is .sisyphus/plans/ and the snapshot capture was nested inside the !isSisyphusPath branch intended for direct-work warning suppression. Move the snapshot/path tracking out of the warning gate so all plan-file edits are snapshotted regardless of .sisyphus prefix. Keep the warning branch isSisyphus-gated so Atlas does not yell at legitimate plan edits.
Regression test now uses a real .sisyphus/plans/ path and fails against HEAD before the fix.
picocolors emits ANSI escape codes when FORCE_COLOR is set (GitHub
Actions default), so the literal toContain('status: active') assertion
fails against the wrapped 'status: \x1b[36mactive\x1b[39m' output.
Reuse the existing stripAnsi helper from src/cli/doctor/format-shared.ts
in the test before assertion.
Reproduced locally with FORCE_COLOR=1 bun test src/cli/boulder/formatter.test.ts.
Inserts blocking Oracle verification todos (plan-1b / plan-2b /
plan-6b in the canonical, plan-1b / plan-2b / plan-5b in the gpt and
gemini variants) between each major Prometheus phase. Each gate is a
single task(subagent_type=oracle) invocation that must return
VERDICT: GO; NO-GO is a directive to fix the cited issues and rerun on
the same Oracle session, not a license to skip.
Adds a new 'Oracle Verification (Phase Gates)' section to
plan-generation.ts with the concrete invocation prompts for each gate:
phase 1 verifies interview completeness, phase 2 verifies the generated
plan, phase 3 verifies plan readiness for execution before /start-work
handoff.
Also adds a plan-generation.test.ts smoke suite (9 cases) that pins
the new todo ids, the section name, the GO/NO-GO format, the
'fix the cited issues' fallback, and the relative ordering.
Drops 'Maximum 3 retries' / 'document and move on' across every Atlas
variant (default, opus-4-7, gpt, kimi, gemini). New text forbids the
'false positive' excuse explicitly and instructs Atlas to keep iterating
on the same task_id, attaching a diagnosis plan, until verification
passes — and to spawn a different-angle subagent only when the original
loops.
Adds a shared <boulder_completion_response> section composed by
shared-prompt.ts. When the hook injects the BOULDER COMPLETE nudge,
Atlas now knows to print TOTAL ELAPSED + per-task elapsed times in the
exact summary shape, confirm boulder.json state, and only mark
pass-final-wave after the Final Wave reviewers approve.
Three correctness fixes on top of the dispatch-before-commit invariant:
- ralph-loop-event-handler.ts: after idleSettleMs, also require state ownership and non-verification-pending to match the event source before dispatching. Applied to both the session.idle and session.error retry paths.
- verification-failure-handler.ts: if incrementIteration fails after a successful continuation injection, clear the loop state and emit a warning toast instead of returning success.
- session-reset-strategy.ts: catch thrown session.create errors so they route through the typed session_creation_rejected path instead of surfacing as an unhandled rejection.
Three additional invariant tests addressing the gaps surfaced by Cubic and the post-implementation review:
- idle path must not dispatch when state ownership changes during the idleSettleMs window
- verification-failure path must treat incrementIteration failure as a loud failure, not a success
- reset strategy must surface session.create rejections as session_creation_rejected even when the SDK throws instead of returning an error envelope
Split the verification-failure restart into clearVerificationState (clears\nthe verification flags so we cleanly transition back to the main loop)\nfollowed by injectContinuationPrompt, with incrementIteration only on\nsuccessful injection. On rejection: clear the loop state and emit a loud\nwarning toast. Mirrors the dispatch-before-commit contract enforced for\nthe idle and session.error paths.
Reorder the session.idle and session.error retry paths so the durable\niteration counter and the progress toast advance only when continueIteration\nreturns dispatched. On dispatch_rejected or session_creation_rejected,\nclear the loop state and emit a loud failure toast instead of silently\nlogging while the loop appears to make progress.\n\nAdds an explicit settle-window state check so a session.deleted firing\nduring the idleSettleMs sleep no longer feeds dispatch against a cleared\nloop. Keeps idleSettleMs intact for the original idle-settle race.
Replace silent returns in continueIteration with a discriminated union\n(dispatched | session_creation_rejected | dispatch_rejected). Wraps\ninjectContinuationPrompt in try/catch so reset-strategy createIterationSession\nreturning null and promptAsync rejections both surface as typed failures\nthe caller can react to.
Lock the contract that durable iteration state and visible UI must only\nadvance when the continuation dispatch is semantically accepted. Adds 4\npermanent invariant tests covering the idle, session.error retry, and\nverification-failure orchestration paths, plus the reset-strategy\nsilent-null path.
Extract isCmuxCompatEnvironment to shared module and fix
interactive_bash to resolve cmux executables with the __tmux-compat
prefix, matching all other tmux command paths in the codebase.