skip to content
Replays

Autonomy-First Merge-Back Conflict Handling

Try to resolve the merge conflict without a human, and ask only when that fails.

Gantry milestones

0 milestones 3 sprints 9 agents

2 plan 3 execute 3 review 1 fix

174k peak context

99k median execute

Try to resolve the merge conflict without a human, and ask only when that fails.

48m 54s total 11m 54s per sprint

1m 35s plan 20m 36s execute 7m 46s review

36 edits 271 commands

codex harness

Gantry already had machinery for resolving merge-back conflicts in a disposable worktree, but an attached run did not always reach it. When an interactive run hit a conflict while landing finished work back on main, the operator could be asked for a recovery directive before the autonomous resolver had tried the integration. Headless runs had a different path, so the same conflict could be treated differently depending on whether someone was watching.

This job made the conflict path autonomy-first. Every run now tries the resolver, checks any remaining residue, proves the integrated tree with the real gate, and lands only a clean result. Human help remains available for attached runs, but only after that path fails, and every stop path keeps main out of the partial merge.

How this walkthrough is structured

Feature

What did the run build and ship?

The tree still carries one merge-back conflict path that tries autonomous repair before any interactive choice, with tests and UI state around the fallback.

Build

How did Gantry structure the work?

The cut established the visible fallback contract first, concentrated the only red gate in the engine rewrite, and finished by wiring the assistant path as a last resort.

Milestone 1

Autonomy-First Merge-Conflict Resolution

At the current tree, the milestone's policy is still described and implemented in the finish-and-merge code. `resolve_conflict` integrates main into the run worktree, runs the autonomous resolver for real conflict markers, classifies and repairs residue, re-runs the gate, and reaches the interactive fallback only if that work cannot produce a clean integration. The domain and TUI still carry prompt events and blocker actions for answering that fallback, and the engine tests still cover the conflict path. Some wording has moved from a generic assistant label toward the Gantry Agent, but the behavior remains the same shape.

The milestone scope was the whole policy change: conflict handling had to become shared by interactive and headless runs, while the interactive-only decision surface stayed behind a failed autonomous attempt. That was larger than a single fresh agent should hold because it touched engine control flow, terminal prompt shape, assistant routing, and the invariant around main restoration. The plan split those concerns so the user-facing contract existed before the engine used it, and so the assistant directive loop came after the resolver-first path was already in place. The run did not re-plan or retry a sprint, but the core engine sprint did need a fix after its gate went red.

Fallback Choice Surface

The fallback surface still exists through the shared prompt and blocker machinery. `PromptNeeded` carries the run-level ask, blocker prompts route into the assistant transcript rather than a normal modal, and inline actions answer the original prompt id. The visible labels have since grown with the broader Gantry Agent interface, but there is still a stop action and a Gantry-handled investigation action that map to distinct engine answers. That makes this sprint's contribution visible as an interface contract rather than a one-off screen.

This sprint was scoped to the last-resort surface, not the decision that would invoke it. A fresh agent could stay in the domain and front-end boundary: define the labelled actions, render them, and dispatch distinct answers while leaving existing recovery directive prompts alone. That made the later engine work safer to take on because the prompt contract had tests before any merge-back flow depended on it. The run facts show no local stress here; the sprint landed without a repair.

Autonomous Resolve First

The autonomy-first path is still the live implementation. `resolve_conflict` creates the integration inside the disposable worktree, calls the resolver before fallback, runs residue classification and adjudication, checks the worktree with the configured gate, and merges into the home branch only after the branch is cleanly integrable. Headless runs still give up terminally after autonomous failure, while interactive runs can take the fallback route. The tests around interactive autonomous resolution and restoration remain in the finish test module, although later changes have expanded the conflict machinery around them.

This was the load-bearing engine slice: every conflict path had to try autonomous repair before human input, then prove the result against the real gate while keeping main recoverable on any give-up. It was a bounded piece for a fresh agent because the fallback surface already existed and the brief named the engine invariants directly. The gate went red here and only here, then a fix pass brought the sprint through, which locates the run's difficulty in the shared merge-back control flow rather than in the UI. No review re-plan followed.

Assistant Fallback Loop

The assistant fallback remains in `fallback_or_give_up` and `console_resolve`. Choosing the Gantry-handled option routes the unresolved integration through the console path, waits for a prompt answer, and then returns to the grounding loop so conflict markers, residue, gate status, and clean integration are checked again. Stop, cancelled, or ineffective answers still flow to the same give-up behavior after aborting any stray main merge. The sprint's most durable artifact is the test coverage for these assistant fallback paths in the merge-finish tests.

The final sprint was intentionally narrower than the engine rewrite. Its job was to connect the existing directive-driven recovery workflow to the fallback choice, with the new rule that the route is reachable only after autonomous resolution fails. Because the previous sprint already owned resolver-first behavior and stop safety, this agent could focus on the assistant-guided loop and its success, cancellation, and failure tests. The boundary stayed green, so no extra recovery or re-plan was needed.