Home Merge Halt
Dirty Home Checkout Halt
Gantry now reports Git refusing a final merge as a resumable home checkout stop.
1 milestones 2 tasks
2 plan 3 execute 3 review
8h 12m total 9m 8s per task
This run tightened the last handoff from a completed run branch back into the operator's home branch. The defect was narrow but load-bearing: Git can refuse the merge before creating merge state when the home checkout already has staged or dirty work, and that condition must not be described as a conflict for an agent or a person to resolve. The decomposition kept the change in a single milestone. First it changed the merge outcome contract so the low-level Git wrapper could say that the merge never began; then it routed that result through live finalization and offline merge commands as a stop the operator can clear and resume.
How this walkthrough is structured
Feature
What did the run build and ship?
Gantry now preserves Git's refusal, named paths, and resumable run state when the home checkout blocks final landing.
Build
How did Gantry structure the work?
The run treated the defect as a contract split followed by presentation work, with the only recorded stress appearing at the final integration boundary rather than inside the child sprints.
Milestone 1
Merge Stop
2 tasks 8 agents 37m 29s wall time
The current tree still has a separate blocked merge result flowing from the worktree layer into run finalization and the merge command. A dirty or staged home checkout is treated as an operator setup blocker, while markerless conflicts continue to travel the conflict path. The stop text says Git did not start a merge and that Gantry changed nothing in the home checkout. Tests in the finish suite exercise the live retry path and the offline command path against real Git repositories.
The milestone held the full dirty-home merge-back defect as one coherent unit. Its boundary was the distinction between a merge that never started and a merge that started but needs conflict handling, plus the operator surfaces that consume that distinction. That was still small enough for a fresh agent because the brief named the contract, the live stop, the offline path, and the out-of-scope preflight behavior in one place. The child sprints completed without local retry, while the overall run later met pressure around final merge and resolution before landing.
Blocked Merge Classification
3 agents 21m 3s wall time
The worktree merge code now checks for merge state after a failed Git merge and returns a blocked result when no merge is in progress. That result carries Git's diagnostic and a defensively parsed path list from common overwrite refusals. If merge state exists but ordinary unmerged paths are absent, the code still reports a conflict and aborts the shared checkout after classification. The tests cover both cases with real repositories, so the distinction is anchored in Git behavior rather than mocked output.
This sprint owned the low-level classification work. The brief asked it to change the final merge-back primitive, not any user-facing copy, so the agent could focus on Git state: success, conflict in progress, or refusal before merge state exists. Its gate and review stayed green in the run facts, which fits a bounded contract change with focused scratch-repository coverage. The important boundary was preserving the existing markerless-conflict path while adding the blocked-before-start branch.
Resumable Home Stop
2 agents 9m 8s wall time
The finalization path now decorates a blocked home merge as its own stop card, including named paths when Git provided them and falling back to Git's reason when it did not. Long path lists use the same inline-or-externalized detail mechanism used elsewhere, and the command-line offline merge path prints the shared blocked-home message. The tests assert that the home branch tip, run branch, worktree, and staged home changes remain available for retry. They also check that the blocked copy does not reuse conflict-resolution instructions.
This sprint consumed the classification contract and moved it into operator-facing behavior. Its scope was presentation and resumability: live finalization had to stop with the right retry command, and offline partial merge had to report the same blocker instead of collapsing it into conflict or generic failure. The run facts show it passed through execution, gate, and review without recovery, so the prior sprint's result was a stable dependency. Its boundary explicitly excluded preflight cleanup or any attempt to alter the operator's staged work.