Stop Recovery Redesign
Typed Stop Recovery
A stop model redesign that made recovery, replay, and retry read from typed records.
6 milestones 0 tasks
91 plan 62 execute 66 review
23h 50m total
This run rebuilt Gantry's stop path from the pattern contract down to the bundled recovery routes. The cut started with `on_stop` and the stop-class vocabulary, then gave runtime stops one `StopRecord`, added structured evidence, made replay admission depend on strict records, dispatched hooks through the typed state, and removed the old recovery vocabulary from shipped patterns and references.
The record shows a run that was itself stopped and resumed while building stop recovery. That matters here: the work under stress was the same work the run was changing, so the later milestones had to stand on typed records, replay admission, and recorded evidence rather than on older prose-derived stop handling.
How this walkthrough is structured
Feature
What did the run build and ship?
The current tree has `on_stop` in the bundled patterns, typed `StopRecord` data in the identity journal, structured stop evidence, replay admission checks, and harness-neutral transient retry classification.
Build
How did Gantry structure the work?
The decomposition put the language contract before runtime state, then made evidence, replay admission, hook dispatch, and cleanup depend on the typed stop record already in place.
Milestone 1
Format Contract
`manual/spec.md` now names `on_stop` as the header hook and describes the accepted hook-table shapes. The loader model in `src/engine/pattern_language.rs` resolves hook handlers by stop class, while the reference dataset exports the same hook contract and stop-class rows. The retired `stop_handler` spelling is no longer the current public contract.
This opening milestone carried the public contract before any runtime behavior depended on it. Its brief was small enough for a fresh worker because it was confined to the pattern language, reference vocabulary, and mirrored format documentation. The ledger stayed green, which fits a foundation slice whose risk was vocabulary drift rather than stateful execution.
Milestone 2
Typed Stop Record
`src/engine/run/identity_journal.rs` carries `StopRecord` with route, position, route-specific data, and evidence. `src/engine/run/interpreter.rs` returns stopped outcomes through typed routes for pattern, operator, and engine stops, and engine stops carry a `StopClass`. Old display compatibility remains isolated from the new runtime shape.
This milestone replaced several terminal encodings with one runtime stop shape and one durable journal record. The work came under stress at the runtime ending step, which stopped once and then passed on retry. That failure localizes the difficult boundary: converting live interpreter exits while preserving compatibility for old records.
Milestone 3
Evidence Rendering
`src/engine/run/generic_pattern.rs` assembles stop evidence from declared outputs, replayed outputs, generated gate and review summaries, and engine facts. `src/engine/environment.rs` renders recorded stops and near-stops into worker preambles, so retries read the stop record rather than old recovery rows. Missing declared outputs are represented as owed evidence instead of as inspected paths.
This milestone made recorded stop facts rich enough for every surface to consume. Its stop-surface work stopped twice before the milestone was completed, and the ledger records a hand correction after a plan-change misfire. The stress sits exactly where several readers had to stop reconstructing a stop independently and trust one evidence package.
Milestone 4
Replay And Resume Admission
`src/engine/run/generic_pattern.rs` now reads strict step replay records, rejects records that predate the strict format, and admits agent replay only through accepted session boundaries. Gate replay is reopened by a green resume baseline and closed by a red one. Replayed committed boundaries are checked against `HEAD` ancestry before the frame is trusted.
This milestone depended on the typed stop and evidence work already built, then narrowed replay to frame-local decisions. Its ledger stayed green, which matches a cut that could be held by one concern: admission to replay, not hook recovery. The run-level record still shows later merge and gate stress, but this milestone's own boundary did not need a retry.
Milestone 5
On Stop Recovery
`src/engine/run/interpreter.rs` dispatches matching `on_stop` hooks for engine stops and returns `ReenterAfterStop` when the handler completes. `record` and `merge` stops do not dispatch through the hook table, and recurrence is keyed by stop class plus position. Hook attempts leave visible records, while the original stop condition is re-derived before execution continues.
This milestone put `on_stop` dispatch on top of the typed record and replay work. The interpreter reentry slice stopped once, then came back as run-level stop reentry and passed on retry. That retry shows the hard part was not declaring hooks; it was re-entering execution after a stop without reusing stale stop facts.
Milestone 6
Corpus Deletions And Retry
`config/patterns/build.toml` and `config/patterns/sprint.toml` declare `on_stop` and route recovery through recorded stop facts. `docs/reference/disposition-naming.md` records that live runtime endings are completion or typed stops, with old disposition names kept as compatibility labels. `src/engine/harness/transient.rs` classifies offline and spawn-side transient failures through the shared retry matcher.
This final milestone was the integration and cleanup pass. It could be medium-sized because the runtime rules were already standing: migrate bundled patterns, remove old stop and recovery vocabulary, and tighten retry classification. The milestone stayed green, so the last boundary was propagation rather than another semantic redesign.