skip to content
Replays

Recovery Stop Engine

Stop handling became a verified recovery path instead of a recoverability guess.

Gantry milestones

3 milestones 10 tasks 22 agents

4 plan 9 execute 15 review

131k peak context

127k median execute

Stop handling became a verified recovery path instead of a recoverability guess.

5h 24m total 15m 59s per task

1h 22m execute 1h 25m review

148 edits 874 commands

codex harness

This run rebuilt how Gantry treats a stopped build. The plan separated ownership acquisition from in-process recovery, made step and stop journals carry facts rather than guesses, taught halt hooks to trust a passing check, and preserved dirty takeover state before any reset. Its later work collapsed ordinary stops into a single recovery state, made headless status derive from the outcome, and removed blocker-flow friction that implied Gantry knew more about external terminals than it did.

How this walkthrough is structured

Feature

What did the run build and ship?

The current tree still carries the run's recovery engine: acquired contexts are reused, journaled stops are factual, halt hooks resolve through checks, takeover discards are parked, and user-facing stop outcomes are outcome based.

Build

How did Gantry structure the work?

The cut staged stop recovery from internal contracts through verified takeover mechanics and then surface cleanup, with the only recorded stress landing at the foundation milestone boundary rather than inside an individual sprint.

Milestone 1

Stop Engine Basics

3 tasks 8 agents 1h 20m wall time 141k peak context

The foundation is still visible in the domain, history, pattern interpreter, and run driver. Stop records now carry operator-pause fact, position, report, and generated-card fields without emitting a recoverability classification, while legacy history with the removed field still decodes. The interpreter records terminal step detail for abnormal exits, and the build driver has a separate acquired-run boundary. Later work has changed surrounding files, but the core contracts this milestone introduced remain active.

This milestone was the preparatory refactor, not the user-visible recovery change. It gave the child sprints three contracts to establish: acquire a run once, close every journaled step, and remove the stop-level recoverability classification. The children passed their focused work cleanly, but the milestone-level gate later went red and had to be repaired before the foundation could stand. That locates the pressure at composition, where the new contracts met the existing engine rather than in a single isolated edit.

One-Time Acquisition

1 agents 32m 7s wall time 84k peak context

The current driver still names an acquired run context and threads it through execution after startup. Resume-time acquisition remains the place where a pre-existing dirty checkout can be handled, while the support loop operates against the already held run services. Tests around finish and recovery still assert that support answers re-enter the verified path rather than acquiring from scratch. The contribution is not a visible command; it is the internal division that keeps recovery from repeating takeover behavior.

This sprint was asked to split taking ownership of a run from re-entering it after a support decision. That was a narrow but load-bearing change: a fresh worker could focus on the run-entry boundary without also deciding recovery policy. Its gate and review stayed green, so later recovery work could assume that Proceed reused an acquired context. The sprint's boundary mattered because acquisition-time cleanup became unreachable from an in-process support-loop re-entry.

Guard Step Journals

2 agents 15m 59s wall time 127k peak context

The pattern interpreter still centralizes stop detail and emits terminal descriptions for non-happy exits. Its tests cover hook failures, halted branches, and recovery ladders against the journaled shape. That means a hook block that exits early is no longer invisible to history readers or operator surfaces. Some surrounding diagram files touched by the sprint have since been rewritten, but the interpreter-side terminal-record behavior remains standing.

This sprint made the interpreter close a step record whenever it had opened one. The brief deliberately covered happy paths, degraded exits, halts, operator pauses, and missing-output failures, so the worker had a compact invariant instead of a broad display task. The sprint completed cleanly after its own gate, giving the halt-hook work a reliable event stream to diagnose from. Its boundary was the step lifecycle, not the policy that would later consume those records.

Stop Record Contract

2 agents 23m 54s wall time 141k peak context

The StopReason type now has an operator-pause flag and no stop-level recoverability field. History encoding omits the old classification, while compatibility tests still decode legacy records that contain it. Headless and TUI surfaces read the same operator-pause fact instead of rebuilding a recoverability taxonomy. The separate stop operation result still has resumability where it describes the stop command itself, preserving the distinction the brief required.

This sprint narrowed stop records to facts true when the stop happened. The brief kept operation-level resumability separate so the worker did not have to remove every use of the word from the program, only the stop classification that had become a guess. It passed through the focused gate and review, then fed the later single-stop runtime work. The cut was small enough for one worker because encode, decode, replay, and presentation all pointed at the same domain shape.

Milestone 2

Verified Safe Takeover

4 tasks 11 agents 1h 37m wall time 131k peak context

The current tree still contains both halves of the mechanism. Pattern documentation and build pattern config state that a passing halt-hook check resolves the halt unless handover intent is explicit. The run and worktree code parks takeover discards on Gantry refs, records the recovery reference, and the reclamation command enumerates those refs through the existing worktree cleanup surface. This milestone left both runtime behavior and operator-facing documentation, though later files have continued to evolve around it.

This milestone moved from foundations to the concrete incident mechanics. Its child sprints were ordered so verified halt recovery came before dirty-work preservation, and dirty-work preservation came before reclaiming parked discard refs. The run facts show the milestone stayed green at both child and milestone review boundaries. That made the recovery mechanism a sequence of proved behaviors rather than a late sweep over all stop handling.

Verified Halt Outcome

2 agents 22m 18s wall time 128k peak context

The shipped build pattern documents the hook outcome channel and says a green hook check can resolve without a file. The interpreter still treats a verified missing outcome as resolved, routes explicit handover to a resumable stop with its report, and preserves the original halt for invalid or unverified output. The troubleshoot prompt also states that prose is not consumed as the handover signal. The feature is both runtime behavior and a documented pattern contract.

This sprint made the hook gate the proof of repair for a halted pattern. Its brief was precise about precedence: no disposition plus a green hook check should resume, while explicit handover should still stop because it records operator intent. The worker could hold that as a pattern-interpreter rule and a prompt contract update. The sprint stayed green, and the milestone review later made only a small follow-up around stale hook outputs before the whole recovery milestone landed.

Proceed Keeps Changes

2 agents 18m 49s wall time 109k peak context

Finish tests still cover automatic and interactive recovery through the same verified path, and the run driver keeps acquisition cleanup outside support-loop Proceed. Dirty work present when the operator proceeds is meant to survive into the next gate, not be reset as stale owner state. The current code also keeps takeover reset available at acquisition time, so this sprint did not remove the legitimate cleanup path. Its contribution is a behavioral guard around when reset may run.

This sprint focused on the non-takeover path that had caused destructive recovery. The brief depended on the acquisition split already being in place, so the worker only had to prove that Proceed reused the acquired run and let the next gate judge the dirty tree. Its checks stayed green. That kept the later parking work scoped to genuine takeover reset instead of mixing it with support-loop re-entry.

Park Takeover Discards

2 agents 25m 38s wall time 115k peak context

The worktree code still builds a parked project reset by writing the dirty project tree to a Gantry discarded-state ref before restoring the checkout to HEAD. The run driver records a support card naming the reset target and the recovery ref, and tests verify tracked edits, added files, and stray directories are reachable from that parked state. Map runs are explicitly left out of this reset path because their units own artifact files differently. The live feature is a recoverable receipt for takeover cleanup.

This sprint handled the remaining destructive case: a genuine takeover of dirty interrupted work. The brief gave the worker a concrete contract, park the pre-reset state on a recoverable ref and put the location in the reset receipt. It stayed green because the acquisition boundary from earlier sprints made the target narrow. The unit's edge was deliberately sharp: Proceed must not discard, takeover may reset only after preserving what it is about to remove.

Reclaim Parked Discards

2 agents 20m 55s wall time 131k peak context

Artifact reclamation now enumerates parked discarded-state refs under the Gantry namespace and folds them into worktree and build-directory cleanup planning. The CLI documentation says those commands delete eligible parked refs after confirmation and retain refs that fail the age filter. The reporting model carries selected, skipped, and failed parked-ref cases alongside ordinary checkout cleanup. No separate recovery verb was introduced.

This sprint gave parked discard refs a lifecycle without adding a new recovery command. The brief was intentionally mechanical: find the refs through the existing worktree-space cleanup path, apply age eligibility, remove eligible refs, and report skipped ones in the same style. It completed green after the parking shape existed, so the worker did not have to revisit how refs were created. The boundary was cleanup integration, not recovery semantics.

Milestone 3

Final Stop State

3 tasks 9 agents 34m 57s wall time 129k peak context

The current tree presents stops as ordinary stops plus the operator-pause variant. Headless exit status is outcome based, title and status surfaces read the pause fact, and blocker prompts still default to stopping unless the operator explicitly answers otherwise. Some planning documents from this phase were archived or replaced after the run, but the runtime and TUI changes remain in source and tests. The result is a single stop model across engine and surface code.

This milestone finished the runtime semantics and then cleaned the surfaces that still reflected the old model. Its sprints were ordered from engine decision, to headless and copy, to blocker-flow polish. The run stayed green through its child gates and milestone review, so the final phase reads as a set of small consumers of the earlier contracts. The cut worked because the risky recovery mechanics had already been isolated before presentation was touched.

Single Stop Recovery

2 agents 5m 53s wall time 68k peak context

The run driver now spends a single automatic recovery allowance for ordinary stops and bypasses that path for operator pauses. Finish tests cover self-healing recovery, failed recovery, repeated stops in one process, abort handling, and the interactive backstop choice. Blocker prompts still resolve to stop-run as the safe default when no explicit operator action chooses another path. The behavior stands as runtime policy, not just copied wording.

This sprint consumed the stop-record contract and applied it to the recovery decision. The worker was asked to make every ordinary stop eligible for the same bounded automatic attempt while keeping operator pause outside recovery. Its green boundary matters because the next sprint could derive exit status from outcome rather than from a removed classification. The brief also kept non-interactive execution from launching or assuming an external investigation.

Outcome Based Surfaces

2 agents 13m 51s wall time 129k peak context

Headless output now has a stopped-exit helper that treats operator pause as success and ordinary stops as failure, while completed and already-complete outcomes remain successful. The CLI reference documents that contract for scripted callers. TUI, status, and title code read the operator-pause flag for their visible variant rather than rebuilding a stop taxonomy. The old label split is no longer the product contract.

This sprint moved the completed stop model onto script and operator surfaces. Its brief asked the worker to derive headless process status from what happened to the run, keep operator pause visible, and stop exposing resumable versus non-resumable labels. The work stayed green and was narrow because recovery eligibility had already been decided in the prior sprint. Documentation and tests were part of the same unit because callers depend on both behavior and command reference.

Blocker Flow Polish

2 agents 6m 49s wall time 94k peak context

The TUI state now records that an external investigation was launched as ordinary blocker-card fact. Tests show Proceed and Stop answer the pending blocker directly afterward, with no local confirmation modal, while launching another investigation path or opening a shell remains a separate explicit action. The prompt default still resolves to stop-run when cancelled or answered non-interactively. The archived plan documents reflect the completed cleanup, though one configuration guide passage still carries older wording about the removed confirmation.

This final sprint deliberately stayed out of recovery architecture. The brief asked for the extra confirmation after an external investigation launch to disappear, while keeping the launcher interactive-only and preserving stop as the safe default. It landed green and did not need a re-plan. That made it a surface cleanup riding on the new stop semantics rather than another engine change.