Checkpoint a Gantry Run Without Ending It
Bank a long run's finished work to master, then resume the rest.
In a normal Gantry build, the finished code reaches the shared `master` branch exactly once, in the step that also disposes of the run's scratch worktree and marks it done. For a build that takes hours, that leaves no checkpoint: you cannot bank the units already completed and continue from there, so an interruption costs everything the run had built. This job adds `gantry merge <name>`, which commits whatever a run has finished so far, merges just that to `master`, and — instead of ending the run — leaves its worktree and ledger in place so `gantry resume` can pick it up and drive the rest to the ordinary final merge. The partial merge travels the same careful, conflict-aware route the everyday finish takes, so banking work partway is as trustworthy as landing it at the close.
Build
The feature was cut into a contract-first stack — command, engine, command line, docs — and the one place it fought back was the engine's partial merge, where a re-plan redrew how the shared merge core could be reached from a second caller.
The work was split into a dependency-ordered stack: a new engine command, the engine behaviour that acts on it, the command-line verb that sends it, and the documentation. The first piece — a `MergePartial` command and the code that carries it faithfully across the attach transport — was landed alone, with nothing yet handling it, so the type and its wire codec could be proven by a round-trip test before any behaviour depended on them. Every later piece then built on a contract that was already stable and tested.
The difficulty concentrated in the second piece: teaching a live map engine to react to the command by draining its worker pool, merging the finished units, and stopping in a resumable state rather than tearing the run down. Its brief insisted the partial merge reuse the exact conflict-aware path a normal finish takes — never a hand-rolled merge — so the reusable core had to be lifted out of the existing finish routine first. That sprint's execute step ran a second time before it landed, and the review that followed forced a re-plan of the remaining work.
What the re-plan redrew was the interface between the engine's merge and the offline command that would later reuse it. The plan had assumed the shared core could be a standalone function both callers invoke; the code showed it was a method bound to a worktree context, backed by new helpers that decide when there is nothing new to land. The next sprint's brief records the correction in plain detail — the offline verb can only reuse the core by assembling the same context the engine holds, not by calling a free function. The one boundary this run had to redraw under load was precisely the one between proving the merge and reaching it from two different callers.
Feature
Gantry used to write a run's output to master only at the finish, as it disposed of the worktree. This job added a command that lands a run's completed units mid-build and leaves it resumable, driving both the live and offline cases through one shared, conflict-aware merge routine.
Before this job, a build reached `master` only in the terminal routine that also removes the worktree and reports the run complete. Nothing could land the units a long run had already produced and keep going; a mid-build checkpoint meant either waiting for the entire run or throwing it away.
The design is one command, `gantry merge <name>`, with two ways to reach the merge. While the run is still owned by a live process, the command rides the attach transport to that engine, which performs the merge itself and streams the result back to the operator. When the owner is gone, the command rebuilds the run's worktree context on disk and runs the merge directly, bailing cleanly if it would conflict rather than half-applying. Both routes pass through a single shared merge core — the same conflict-aware routine the final finish runs — so a partial merge lands with identical bookkeeping, then keeps the worktree, branch, and ledger intact for `gantry resume` to continue.
Standing in the tree today, the command and its shared core are still here, though the code around them has been rearranged. The single engine source file where the core first landed no longer exists: it was broken into a build module, and the merge core and its resumable caller now sit in that module's finish file. The reach has also widened — the verb was restricted to map runs when it shipped, and the current reference describes it for map, goal, and loop runs alike. The documentation the last sprint wrote into the project's top-level guide has since moved into the dedicated command-line reference, as that guide was reduced to a short index.