Prove the Merge Before It Lands
Merge-back that integrates and tests the combined tree before the main branch ever moves.
Every Gantry run ends by merging the work it built back into the project's main branch. That merge used to lean on git: if the combined text carried no conflict markers, it was treated as done and the main branch advanced. But two changes can be textually compatible and still contradict each other in behaviour — one edits a function the other now calls a different way — and git sees nothing wrong. A clean merge could still leave the main branch broken.
This job rebuilt the merge so it proves itself. Before the main branch moves, Gantry pulls the current main tip into the run's throwaway worktree, runs the full test suite on that combined tree, and advances the main branch only once it passes. When the combined tree fails — even with no textual conflict — an agent is brought in to reconcile the two lines of work by meaning rather than by text. It gets a single attempt; if it cannot produce a passing, marker-free tree, the run stops with the main branch left exactly where it was and the worktree standing for a person to pick up.
Build
The plan separated a correctness guarantee from the repair behaviour that only matters once that guarantee can fail, then carried the guaranteed path across every merge surface — and the two hard pieces each went red at the gate before they landed.
The decomposition splits on what can be grounded before what. The first piece proves: the main branch moves only for an integrated tree that passed its tests, with a master-mutation lock held across the whole read-tip, integrate, gate, land sequence so no concurrent run can shift the target underneath it. That is a correctness property a single agent could build and test with no resolver in existence. The second piece repairs: treat a textually clean but test-red integration as reconciliation work, hand it to one resolver pass, land the result only if it comes back green. Repair only means anything once proving is there to fail, so ordering it second let each piece be grounded before the next leaned on it.
The two later pieces widened rather than deepened. One carried the same integrate-in-worktree, gate, resolve-on-red, land-only-green sequence through the other engine-owned landings — partial merge and a live-owned merge command — while keeping offline merge conservative, since offline has no live agent to repair with and must report and stop instead. The last updated the resolver and adjudicator prompts and the operator docs to describe reconciliation-by-meaning and the untouched-main guarantee.
The stress sat squarely on the two correctness pieces. The proving foundation went red at its gate after its review and needed a repair before it could land; the semantic resolver went red immediately after it was built and was sent back once before passing. The two widening pieces — spreading the sequence across surfaces, and the prompt-and-docs pass — stayed green throughout. Nothing forced a re-plan and no sprint was retried from scratch: the boundaries the plan drew held, and the difficulty showed up exactly where the plan had concentrated the new correctness, not in the mechanical work of propagating it.
Feature
Gantry's merge-back stopped ending at git's textual verdict; a single shared path now integrates the current main, runs the real gate on the combined tree, and advances the main branch only for a proven-green result — with a lock spanning the whole sequence.
Before this job, a Gantry run's finish trusted a clean textual merge and moved the main branch on that basis. A combined tree that compiled and merged without markers but failed its tests could still land, and there was no point in the flow where the integration was actually exercised before it became the main branch.
What stands now is a single conflict-safe merge core that every engine-owned landing routes through. The finalize path and the engine-owned partial-merge path both call it; the live merge command reuses the exact same core rather than growing a second implementation of the sequence. That core reads the current main tip, integrates it into the disposable worktree, and gates the combined tree there; the main branch is mutated only afterward, and only for a green result. A per-checkout lock is held across that entire critical section — from reading the tip through the merge and the post-merge re-gate — so a second run sharing the checkout cannot move the main branch between the proof and the landing. The offline merge path, which has no live agent, keeps its conservative behaviour: it reports the conflict and stops rather than attempting agent-driven repair.
Standing in the tree at today's HEAD, the design still holds. The merge core and its surrounding module remain the center of the finalize flow, and its own documentation spells out the integrate-then-gate-then-land order and the lock ordering that keeps it deadlock-free. The finalize file has been heavily built on since — much of its introduced code has been rewritten by later work — but the shape is intact and present, and the live partial-merge path still shares the one core. The plan document that drove the job has since been tidied away, which is housekeeping rather than any retreat from the behaviour it specified.