Land green pull requests one at a time, and stop when main breaks #134

Merged
nectenda-agent merged 1 commit from worktree-agent-merge-queue into main 2026-09-23 20:06:55 +01:00
Collaborator

The merge queue: launchd runs one step every two minutes, landing green PRs on protected main one at a time. It never edits code.

  • Outdated PRs are rebased in the queue's own scratch worktree, pushed with --force-with-lease against the head it saw, and merged only after checks pass again, never in the same step as the rebase.
  • A conflict or red checks send the card back to Ready as merge-conflict.
  • Risky PRs are held in Review, with a comment naming the head commit. Moving the card back to Merging approves that commit only.
  • After a merge, main's push run must pass before the card is Done. A failure pauses the queue until main's head is green again, whether from a fix or a green re-run of the same commit.
  • slot.sh and the launchd wrapper fast-forward the main checkout first, only when it is clean and on main.

53 tests; each queue rule was mutation-checked in both directions.

Changelog

NONE

The merge queue: launchd runs one step every two minutes, landing green PRs on protected main one at a time. It never edits code. - Outdated PRs are rebased in the queue's own scratch worktree, pushed with `--force-with-lease` against the head it saw, and merged only after checks pass again, never in the same step as the rebase. - A conflict or red checks send the card back to Ready as `merge-conflict`. - Risky PRs are held in Review, with a comment naming the head commit. Moving the card back to Merging approves **that commit only**. - After a merge, main's push run must pass before the card is Done. A failure pauses the queue until main's head is green again, whether from a fix or a green re-run of the same commit. - `slot.sh` and the launchd wrapper fast-forward the main checkout first, only when it is clean and on main. 53 tests; each queue rule was mutation-checked in both directions. ## Changelog NONE
Land green pull requests one at a time, and stop when main breaks
All checks were successful
Release note / release-note (pull_request) Successful in 14s
CI / e2e (pull_request) Successful in 5m28s
CI / build (pull_request) Successful in 5m29s
CI / promote (pull_request) Has been skipped
CI / build (push) Successful in 4m38s
CI / e2e (push) Successful in 4m48s
CI / promote (push) Successful in 30s
3ab29213ec
The merge queue: launchd runs one step of it every two minutes. It takes
the first card in Merging, finds its pull request by the `Task: NEC-n`
line, and lands it fast-forward-only. It never edits code.

Why a queue at all: with fast-forward-only merges and outdated branches
blocked, main is always a commit CI tested, whoever merges. What goes
wrong without one is throughput. Every merge makes every other green pull
request outdated, so N landing at once would cost about N²/2 CI runs on
the runner that is the bottleneck. Rebasing only the one about to merge
costs about two each.

- Outdated: it rebases in a scratch worktree of its own, never a slot's,
  pushes with --force-with-lease against the head it saw, and waits for
  checks again. It never merges in the same step it rebased.
- A conflict, or red checks, sends the card back to Ready as
  merge-conflict, where the next free slot takes it first.
- Risky pull requests are held in Review, with a comment naming the
  head commit. Moving the card back to Merging approves that commit and
  no other; new commits are held again. A label could not do that.
- After a merge, main's push run must pass before the card is Done. If
  it fails, the queue pauses until main's head is green again: a fix on
  top, or the same commit passing on a re-run. The first version only
  resumed on a newer commit, and mutation-checking that rule showed it
  would have stayed paused after a green re-run.

The slot launcher and this job both fast-forward the main checkout
before running, but only when it is clean and on main, so a fix to the
loop reaches it without ever moving anybody's work. The skill's bounced
card now starts from the remote branch (reset --keep), since the queue
may have rebased it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015k9tkUtbU3wBpCHAHq7Qas
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Nectenda/nectenda!134
No description provided.