Stop Recovery Projection
Stopped Runs Read From Projection
The monitor, status, controls, and cleanup paths moved onto shared run state.
1 milestones 6 tasks 13 agents
2 plan 6 execute 7 review
192k peak context
161k median execute
2h 54m total 16m 20s per task
59m 46s execute 1h 33m review
136 edits 753 commands
codex harness
This run rebuilt the front-end side of stop recovery around a single projected view of a run. The work started with shared phase and stop derivation, then carried that model through controls, process accounting, whole-tree status, TUI rendering, and cold stopped-run actions.
The result is still visible in the current tree: run-state projection owns phase and stop facts, TUI controls ask one action predicate, process rosters carry launch origin, status folds nested run records, and cold stopped runs expose actions instead of dead instructions.
How this walkthrough is structured
Feature
What did the run build and ship?
The current tree still routes stopped-run display, controls, status, and cleanup through shared projection, action, roster, and fold code.
Build
How did Gantry structure the work?
The run was cut as one milestone whose sprints established shared projection contracts first, then made every front-end surface consume them without any recorded red gate or re-plan.
Milestone 1
Project Run State
6 tasks 15 agents 2h 45m wall time 230k peak context
The milestone left a cross-cutting front-end architecture rather than a single feature file. The live tree shows that run projection, TUI state, TUI rendering, process roster, process view, and status integration all still participate in stopped-run recovery. Later edits have touched some of those files, but the shared read path remains the visible shape of the work.
The milestone carried the whole front-end stop-recovery plan, but its brief split the risk into contracts rather than screens. A fresh agent could treat the milestone as an integration target because the child sprints each owned one shared answer: state, actions, roster, rollups, rendering, or cold actions. The recorded run stayed green through planning, review, and the milestone gate, so the boundary pressure was in keeping the contracts aligned rather than in recovering a failed cut.
Shared Run State
2 agents 21m 12s wall time 163k peak context
Run projection now carries the coarse phase, current stop, and historical stop, and the TUI state exposes those facts through `run_phase` and `current_stop`. Headless and TUI code both read the projection instead of maintaining their own stopped verdict. The test suite still includes the cold-stop supersession case where later live activity turns an old stop into history while the visible run becomes running again.
This sprint was the foundation: front-ends were told to stop preserving writable phase and recoverability answers and to derive them from the folded run view. That made it small enough for one agent because the contract was narrow even though several consumers depended on it. The sprint had no recorded repair or re-plan; it passed through review and a second gate with the later work able to lean on the same projection facts.
Unified Action Contract
2 agents 1h 12m wall time 230k peak context
The TUI module now has `RunActionFact` and `run_action`, with shared enabled state and disabled reasons for status, shell, merge, pause, resume, prompt, stop, abort, detach, and blocker actions. Rendering and state dispatch both consult that predicate, so a disabled reason and a click guard come from the same code path. Tests in the TUI state module still exercise menu and control agreement around those facts.
This sprint took the next dependency: once phase and stop facts were shared, run controls needed one availability answer. The brief kept the work at the predicate boundary, so menus, buttons, registry entries, and dispatch guards could be changed without asking the agent to redesign the whole TUI. It also stayed green, which means the contract was established before later cold-stop behavior depended on it.
Run Process Roster
2 agents 16m 20s wall time 161k peak context
`process_roster` still records structured process attribution, origin orchestration directories, launch times, and reap records in an append-only roster. Cleanup and reporting replay both the run-root roster and legacy nested roster paths, while launch requests carry the origin directory that spawned the group. Current status coverage uses an incident-shaped nested fixture to prove that legacy nested live groups are still reported.
This sprint moved process ownership to the run boundary. Its brief was broad in call sites but crisp in invariant: new launches append to the run-root roster, and compatibility cleanup still reads older nested rosters. The run facts record no recovery, so the stress stayed inside a mechanical propagation of the roster request through launch sites and cleanup readers.
Whole Pattern Rollups
2 agents 16m 20s wall time 183k peak context
The projection model now exposes a task tree, display roots, per-level counts, position, progress, final disposition, and capabilities. The status integration test still builds nested milestone ledgers with duplicate completion rows and verifies that public status reports the folded sprint progress and live process picture. In the live tree, TUI progress and stats adopt that same `RunView` instead of recounting root-only ledgers.
This sprint made the projection answer the whole-run question after roster ownership was unified. The brief gave the agent a concrete fold contract: nested progress, activity, live groups, playhead, and duplicate ledger rows all had to collapse into one run view. Review appears more involved here, but the recorded outcomes stayed green and no re-plan was needed, so the correction stayed within the sprint boundary.
Projection-Backed TUI
2 agents 9m 17s wall time 145k peak context
`AppState` now keeps a live projection and refreshed `RunView`, and rendering reads that view for sidebar and status presentation. Stage, gate, review, and agent events still fold into cards after a cold stopped seed, while the old stop becomes historical context. The standing test for cold stopped projection proves the feed grows, the current stop clears, and the sidebar counts come from the folded projection.
This sprint was deliberately late because it replaced presentation reads after the shared projection and whole-tree fold already existed. The brief kept it to rendering rules: feed activity must continue after a journaled stop is superseded, while sidebar, title, and progress read projection facts. The sprint stayed green, showing the earlier contracts gave the TUI agent enough stable surface to change display behavior without reopening state semantics.
Cold Stopped Actions
2 agents 18m 45s wall time 192k peak context
Cold stopped runs now reuse the blocker action identities through `run_action`: proceed maps to resume in place, shell opens from the surfaced worktree, harness investigation can launch from the stop seed, and stop cleanup is present only when process work remains. TUI state records pending actions for cold harness launch and cleanup, while rendering shows stop messages with the same button-row machinery as live blockers. Tests still cover the cold action availability for proceed, shell, and cleanup.
The last sprint consumed every earlier contract and made stopped runs actionable without a live engine prompt. Its boundary was the user-facing action set, not the engine stop semantics, so it could add cold dispatch paths while leaving the archived stop meaning alone. It completed without recorded recovery, which fits a final sprint that mostly wired proven facts into controls and pending TUI actions.