Skip to content

Add a merge skill - #31

Merged
koomen merged 7 commits into
mainfrom
merge-queue-skill
Aug 16, 2026
Merged

Add a merge skill#31
koomen merged 7 commits into
mainfrom
merge-queue-skill

Conversation

@koomen

@koomen koomen commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Adds .claude/skills/merge/SKILL.md/merge 28, or /merge for the current branch's PR.

  1. Rebase onto latest main in a worktree, force-push with lease. Rebase, never merge-from-main — a merge commit would mean fable reviewed a tree that never existed. Conflicts that aren't mechanical get handed back rather than guessed at.
  2. Adversarial review — two parallel claude-fable-5 subagents, one on defects (correctness, security, regressions), one on AGENTS.md invariant conformance. Both are told to hunt for reasons not to land it. The driver writes the fixes; the reviewers are a different model, because a model reviewing its own fixes is not an adversarial review.
  3. Triage, then fix — findings are confirmed against real control flow before acting, since adversarial reviewers over-report. Fix, bun run ci, push, re-review. Three rounds, then it stops and reports.
  4. Merge once ci is green on the pushed head.

Asks for approval once up front, then runs through to the merge without further prompting.

No labels, no queue, no CI credentials — it runs in your session with the auth you already have.

🤖 Generated with Claude Code

@koomen koomen changed the title Add a merge-queue skill Add a merge queue that runs in GitHub Actions Jul 24, 2026
@koomen
koomen force-pushed the merge-queue-skill branch from 7ed4c2d to d9ef2df Compare July 24, 2026 19:23
@koomen koomen changed the title Add a merge queue that runs in GitHub Actions Add a merge skill Jul 24, 2026
koomen and others added 4 commits August 16, 2026 13:45
Lands one PR: rebase onto latest main, review it adversarially with two
fable subagents (defects, and AGENTS.md invariant conformance), triage
and fix the findings, gate on `ci`, merge.

Rebase rather than merge-from-main, so the tree fable reviews is the tree
that lands. The driver writes the fixes and the reviewers run on fable —
a model reviewing its own fixes is not an adversarial review. Findings
are confirmed against real control flow before acting, since adversarial
reviewers over-report. Three fix rounds, then it stops and reports.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Round-1 adversarial review found the runbook would fail in practice.
Fixed, in order of severity:

- Pin the reviewed SHA and merge with `--match-head-commit`, so a commit
  pushed after the review cannot land unreviewed. Re-check that main has
  not moved before merging.
- Reorder cleanup: a branch checked out in a worktree cannot be deleted,
  so `--delete-branch` failed on every run. Remove the worktree first,
  then delete the branch explicitly.
- Fetch the PR branch, not just main; `git worktree add` needs the ref.
- `bun install` in the worktree before `bun run ci` — a fresh worktree
  has no node_modules.
- Give the reviewers the checkout directory. A subagent starts in the
  session cwd, so a reviewer that is not told where to look diffs the
  wrong tree and reports nothing.
- Handle the branch already being checked out, including in the primary
  checkout, where `git worktree add` refuses outright.
- Require the PR base to be main; rebasing a stacked PR onto main would
  rewrite it and split the review target from the merge destination.
- Only remove a worktree this skill created; a reused one may be a
  long-lived checkout the user is sitting in.
- Derive the worktree path from the repo root instead of hardcoding a
  home directory into a shared repo file.
- Use the `fable` model alias; the Agent tool takes sonnet|opus|haiku|fable,
  not a full model ID.
- Defer to the check-invariants skill instead of restating it, per the
  standing rule against duplication that can drift.
- Note that `gh pr checks` errors rather than waits before a run registers.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Round-2 review found the worktree and cleanup machinery was generating
most of the failure modes, several of them added by round 1. Cut the
machinery rather than patching each bug.

- Stop creating worktrees. `git worktree add` fails when the branch is
  checked out, `--show-toplevel` returns the linked worktree's own root
  rather than the primary one (so the path nested wrongly), and removing
  a worktree you are standing in breaks every later command. Use the
  checkout the branch already lives in.
- Stop deleting local branches and worktrees. Deleting a checked-out
  branch fails, and the checkout may be one the user lives in. Delete
  the remote branch and report what local state remains.
- Never carry shell variables across steps. Each Bash call is a fresh
  shell, so `$WT` and `$REVIEWED` were empty by the time they were used
  — which silently neutered `--match-head-commit`. Print and substitute
  literals instead.
- Reconcile the local branch against origin/<branch> before rebasing.
  Round 1 added a fetch of the branch, which makes `--force-with-lease`
  compare against the ref it just updated — so a stale local branch
  would force-push away remote-only commits and the lease would pass.
- Resolve the two contradictions the check-invariants deference created:
  give lens 2 an explicit diff base and findings format that override
  that skill, so both lenses review the same tree and report the same
  shape.
- Reject fork PRs at preflight rather than failing at the fetch.
- Say one lens per reviewer, not both lenses to both.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Rebase in a detached scratch worktree off origin/<branch> instead of
hunting for and mutating existing checkouts, drop the fork/stacked-PR
preflight and approval ceremony, and collapse the review to one fable
agent carrying both lenses. Keep the agent-facing guards: gate
integrity, mechanical-conflicts-only, author/reviewer split, the
3-round cap, and --match-head-commit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@koomen
koomen force-pushed the merge-queue-skill branch from 02a8b08 to 429e053 Compare August 16, 2026 20:45
koomen and others added 3 commits August 16, 2026 13:53
Guard the rebase->push and checks->merge fences with &&, pin the push
lease to the fetched SHA (shared-ref worktrees defeat the expect-less
form), preflight local branches that are ahead of origin and leftover
worktree paths, pin the check-invariants diff base to origin/main, and
cd out before removing the scratch worktree.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Chain the remote-branch delete onto merge success so a
--match-head-commit refusal never deletes an unmerged PR's branch,
prescribe the step-3 fast-forward push (stop on rejection, never
re-lease), make the reviewer explicitly read-only, run the fetch before
the preflights that depend on it, and carve the final cleanup out of
the cd-into-worktree rule.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Guard the leftover-worktree removal against discarding a crashed run's
unpushed commits, and widen the cd-rule carve-out to everything after
the step-4 cleanup.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@koomen
koomen merged commit a7fbd20 into main Aug 16, 2026
1 check passed
@koomen
koomen deleted the merge-queue-skill branch August 16, 2026 21:06
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.

1 participant