Skip to content

fix: gate merge phase on "branch ahead of main", not "this iteration's commits"#649

Open
a9a4k wants to merge 1 commit into
mattpocock:mainfrom
a9a4k:fix/merge-gate-on-branch-ahead-of-main
Open

fix: gate merge phase on "branch ahead of main", not "this iteration's commits"#649
a9a4k wants to merge 1 commit into
mattpocock:mainfrom
a9a4k:fix/merge-gate-on-branch-ahead-of-main

Conversation

@a9a4k
Copy link
Copy Markdown

@a9a4k a9a4k commented May 14, 2026

The bug

The parallel-planner and parallel-planner-with-review templates (and the repo's own .sandcastle/run.ts) filter which branches to hand to the merger by checking entry.outcome.value.commits.length > 0 — i.e. only branches whose this iteration's implementer added new commits.

This silently strands any branch that was already advanced by a previous iteration whose merger never landed it. The next iteration's implementer reruns, finds the fix already in place, produces zero new commits, the orchestrator filters the branch out, and the merger never sees it. The branch then sits ready-to-merge forever.

I hit this deterministically on a downstream project — the same branch was skipped across three consecutive merger cycles even though git log main..<branch> showed it was one commit ahead the whole time.

The fix

Replace the in-memory commits.length check with git rev-list --count main..<branch>. Now any branch ahead of main reaches the merger, regardless of which iteration produced the commits.

Per ADR 0009 (templates do not share code), the branchIsAheadOfMain helper is copied into each template that needs it rather than extracted.

Also replaces the misleading inline comment "An agent that ran successfully but made no commits has nothing to merge" — that's the precise assumption this PR refutes.

Changes

  • .sandcastle/run.ts (self-driving config)
  • src/templates/parallel-planner/main.mts
  • src/templates/parallel-planner-with-review/main.mts
  • .changeset/merge-gate-on-branch-ahead-of-main.md (patch)

Verification

  • npm run typecheck: clean
  • npm run build: clean
  • npm test: 34 pre-existing failures unchanged (confirmed identical on clean main; macOS path-resolution noise unrelated to this change)

…s commits"

The `parallel-planner` and `parallel-planner-with-review` templates (and
the repo's own self-driving `.sandcastle/run.ts`) filtered which branches
to hand to the merger by checking the implementer's `commits.length` from
the current iteration. This is wrong when a previous iteration's
implementer wrote the fix but the merger never landed it: every
subsequent iteration's implementer re-runs, finds the fix already in
place, produces zero new commits, and the orchestrator filters the
branch out before the merger ever sees it. The branch then sits
ready-to-merge forever.

Now asks git directly via `git rev-list --count main..<branch>` — any
branch ahead of `main` reaches the merger, regardless of which iteration
produced the commits. Per ADR 0009 the `branchIsAheadOfMain` helper is
copied into each template that needs it rather than extracted into a
shared module.

The misleading comment "An agent that ran successfully but made no
commits has nothing to merge" is replaced — that's the precise
assumption this PR refutes.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 14, 2026

@TESTPERSONAL is attempting to deploy a commit to the Matt Pocock's projects Team on Vercel.

A member of the Team first needs to authorize it.

@mattpocock
Copy link
Copy Markdown
Owner

Super smart find, thank you

@a9a4k
Copy link
Copy Markdown
Author

a9a4k commented May 27, 2026

Thanks for building it. Was super nice to work with

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants