skip to content
Replays

Teaching the Merge Resolver to Prove It Dropped Nothing

The finish step now checks a resolution actually carried main's changes, and repairs the ones it didn't.

Gantry milestones

0 milestones 4 sprints

The finish step now checks a resolution actually carried main's changes, and repairs the ones it didn't.

1h 36m total 20m 14s per sprint

45.7M tokens in 308.2k tokens out

$45.18 nominal cost

This job addressed a specific merge failure mode in Gantry's finish step: a conflict resolution could keep the run branch, discard main's concurrent change, and still look clean enough to land. The plan was to make the integration auditable, then compare main's actual delta with the resolved tree before the old gate and integrability checks were trusted.

The build split that work by responsibility. One piece made every integration visible in history and events, one added git operations that could be tested without orchestration, one wired those operations into automatic repair for unambiguous drops, and one reserved agent judgment for the ambiguous residue while keeping the existing give-up path as the only human stop.

How this walkthrough is structured

Feature

What did the run build and ship?

Gantry now checks what main contributed against the resolved tree, restores missing hunks when the branch never touched that region, and sends only ambiguous overlap to a repair agent.

Build

How did Gantry structure the work?

The run kept the merge repair problem bounded by layering audit output, git-only primitives, orchestration decisions, and the ambiguous repair agent, with no sprint needing retry or re-plan.

Milestone 1

make conflict resolution preserve both sides, and prove it

The standing system now treats merge resolution as something to verify against git, not as an agent claim to accept. Main's folded commits can be named, main's hunks can be compared with the resolved tree, missing content can be repaired or adjudicated, and the old grounding remains the final authority. Later edits have changed the surrounding finish code and tests, but the capability described by the milestone is still present in the current tree.

The milestone brief carried the whole design instead of delegating intent to scattered tickets. Its boundary was the merge finish path, but it divided that path into auditability, mechanical delta analysis, deterministic self-heal, and adjudication, so each agent could work from a narrow contract. The run facts show no recovery, red gate, or review re-plan inside that structure; the notable property of the cut is that the risky semantic behavior was not assigned until the supporting evidence paths existed.

Reconciliation Log

The current tree still has the reconciliation record in the event model, including conflicted files, folded commits, and class counts. Commit messages are still enriched through the helper that appends the home-branch commits folded into integrate and merge commits. Headless output, history replay, attach encoding, and the TUI activity feed still know how to render or persist that event, so an integration is no longer silent in the observable run stream.

This first sprint was asked to make integrations observable before any classifier existed. That made it a suitable clean-context task: add a domain event, carry it through attach, history, headless, and TUI projections, and enrich commit messages while leaving the merge decision unchanged. The gate and review stayed green, which fits the cut: it was a wide plumbing change, but not yet the semantic repair logic.

Delta Analysis

The worktree layer still owns the merge-base, main-delta, overlap, survival, and re-apply operations. Those methods operate through git and keep the main checkout read-only, matching the original boundary that orchestration should not hand-roll repository state. Their fixture tests remain visible in the worktree test module, although later changes have moved plenty of surrounding test scaffolding.

This sprint isolated the git facts the later classifier would need, and explicitly avoided calling them from the finish flow. That was the right size for a fresh agent because the acceptance surface was fixture-driven: parse main's delta, compare branch overlap, detect survival in a resolved tree, and try a clean hunk re-apply. It passed without repair, so the next sprint inherited tested primitives instead of also owning diff parsing and shell behavior.

Automated Repair

The finish path now classifies main's delta before it trusts the ordinary resolution checks. If main's added content is present, the hunk costs nothing; if it is absent and the branch did not rewrite the region, Gantry applies the patch and commits the restored change in the worktree. A failed deterministic apply is routed to the ambiguous residue instead of becoming its own stop, and the reconciliation event reports the classifier's tally.

With the git surface already in place, this sprint could focus on the decision table inside finish. Its job was to classify each hunk after integration, dismiss carried changes, deterministically re-apply dropped changes from untouched regions, and report the resulting tally through the reconciliation event. The run stayed green here too; the lack of a fix stage matters because the hard edge was controlled by prior fixture coverage rather than discovered during orchestration wiring.

Adjudication Layer

Ambiguous dropped-or-superseded hunks are now passed to an adjudicator-repairer under the resolve stage. The prompt names the residue and asks for repair in the worktree, with large region lists externalized to a worktree file when needed. The tests still exercise the intended boundary: only the ambiguous region reaches that agent, a successful repair merges after the normal gate, and an unrepaired red tree uses the existing give-up route.

The final sprint took only the ambiguous case left over from the classifier. Its brief was bounded by residue, not by the whole merge: hand those hunks to a fresh build-role agent, then send the result through the same existing grounding and give-up behavior. It completed cleanly, and no review re-plan followed, so the job ended with the human halt surface unchanged rather than adding a second conflict policy.