Resume Any Job Type Where It Stopped
Teaching a flagless resume to route every driver, not just the layouts it already recognised.
Gantry runs are long, and a run can be interrupted partway — a crash, a stop, a reboot — and then picked up again with `gantry resume`. For that to work, the resumed run has to remember what kind of build it was and work out how far it had already got. Resume already did this for the ordinary sprint and milestone builds, but it was broken for two of Gantry's other build styles: design runs and map fan-outs.
Two things were wrong. The check that decides "is there anything here to resume?" recognised only the sprint and milestone layouts on disk, so it stopped a design or map run as unresumable before the run ever chose how to proceed. And the run never wrote down what kind of build it was, so a resume with no command-line flags forgot it had been a design or map run and set off down the wrong path.
This job made resume a general rule: every job type Gantry can start, it can resume — keyed off each build's own committed state on disk, rather than a hard-coded layout or a flag the user has to remember to repeat.
Build
The cut refused to fix one tangled symptom in one place: persist the kind first, then teach the guard to ask per-driver, then prove each driver skips finished work — an ordered chain where each piece was landable and testable before the next leaned on it.
The handover described a single symptom — flagless resume broken for design and map runs — with two independent causes: a resumability check that fired before the router and knew only two on-disk layouts, and a job kind that was never persisted, so a bare resume fell back to the wrong driver family. Either alone left resume broken, so both had to land. The decomposition's move was to refuse to fix them together.
Persisting the kind came first, because the second fix depends on it: the guard can only be rephrased as "does the selected driver have state on disk?" once the selected driver is known, and knowing it across a resume requires the kind to survive on disk. So the first sprint wrote a per-run job pin and a precedence function — explicit flag over persisted file over triage over the build-family default — plus a legacy fallback that infers the kind from an older run's committed layout, since a real stranded design run with no pin had to resume through it. The second sprint then moved the guard to after the route decision and gave each driver its own resumability signal. The third verified the part routing alone does not cover: that a resumed run finishes only the remainder.
That third piece is where the plan spent its care ahead of time. The sharpest hazard was not routing but a resumed redesign re-running its clean-slate step and blanking pages a prior session had already built — destroying work rather than resuming it. The brief named that hazard up front and quarantined it in its own sprint with its own regression test, rather than leaving it to surface as a gate failure. The run bears the cut out: every sprint passed its gate and review on the first attempt, nothing forced a re-plan, and the strict dependency order meant each fix was grounded against the Rust suite before the next built on it.
Feature
Resume used to mis-handle design and map runs — stopped as unresumable, or quietly routed to the wrong driver. Now a durable per-run job pin, a legacy-layout inference fallback, and a driver-aware resumability check make resume universal, and all three still stand at HEAD.
Before this job, `gantry resume` was reliable only for sprint and milestone builds. A design or map run resumed with no flags was either stopped as unresumable by a layout-blind guard or quietly routed to the wrong driver, because nothing on disk recorded what kind of run it had been. The fix moved the run's identity into the artifacts instead of the invocation: a small per-run `job.toml` pin written at setup carrying the resolved kind and any design parameters, a resolution function that ranks an explicit flag over that pin over triage over the default, an inference path that reconstructs the kind from an older run's committed layout when no pin exists, and a resumability check that asks the selected driver — not a fixed layout — whether it has state to resume.
Standing in the tree today, all of that is present and has grown. The "nothing to resume" stop is now phrased against the chosen driver — its named driver has no state on disk — exactly the driver-aware rewrite the job set out to make. Per-driver resumability has since been generalised into a `DriverServices` trait whose members report their own legacy footprint and payload, so newer drivers join the same resume contract this job established.
The one visible drift is where the code lives, not whether it survives. The work landed in `src/engine/build.rs`; that file no longer exists at HEAD — the build engine was later split into a `build/` module directory, and the resume logic moved into `build/job.rs` and `build/mod.rs` intact. The pin, the legacy fallback, the driver-aware guard, and their tests were relocated by a larger reorganisation, not undone.