| name | pr-captain-merge |
| description | Captain-only. Merge a PR safely — true merge commit (never squash, never rebase), branch protection respected, --principal-approved gate for --admin override. Prevents the "accidentally squashed via the wide GitHub UI button" failure mode that has burned the fleet. |
| agency-skill-version | 2 |
| when_to_use | Captain on master in main checkout, after PR has passed CI and principal has approved (verbally or via GitHub review). Invoked by captain directly or as a step within /pr-captain-land. NEVER from a worktree. Intended for explicit invocation — runtime precondition in underlying `agency/tools/pr-merge` refuses from wrong context. |
| argument-hint | <pr-number> [--principal-approved] [--delete-branch] [--dry-run] |
| paths | [] |
| required_reading | ["agency/REFERENCE-GIT-MERGE-NOT-REBASE.md","agency/REFERENCE-SAFE-TOOLS.md","agency/REFERENCE-CODE-REVIEW-LIFECYCLE.md"] |
pr-captain-merge
Captain's safe wrapper for merging PRs on GitHub. Always a true merge commit (no squash, no rebase). Respects branch protection by default. --principal-approved is the only way to engage --admin override.
Name pattern: pr- prefix groups with the PR skill family (autocomplete /pr<tab> shows the full kit), captain- qualifier makes captain-only scope visible at a glance.
Why this exists
Raw gh pr merge is too easy to misuse:
- GitHub's UI nudges toward squash (the wide button)
- The
--squash flag is one keystroke away from --merge
--admin bypasses branch protection silently
- Without discipline, the captain shipped 4 squash merges in one day (pre-v2 incident)
pr-captain-merge is the gate — skill-level enforcement plus the underlying agency/tools/pr-merge tool that does the actual work.
Required reading
Before running, Read the files in required_reading: frontmatter. GIT-MERGE-NOT-REBASE.md explains why we never squash or rebase. SAFE-TOOLS.md covers the safe-tool family this skill composes.
Usage
/pr-captain-merge <pr-number>
/pr-captain-merge <pr-number> --principal-approved
/pr-captain-merge <pr-number> --delete-branch
/pr-captain-merge <pr-number> --dry-run
Preconditions
- Captain is on master in main checkout. Not in a worktree.
- PR number is known. Captain has verified PR is not in draft.
- CI has passed (or deploy-preview flake is understood and ignored).
- Principal has approved — either via GitHub review OR verbally in this conversation.
- For
--principal-approved: the principal's authorization is in THIS conversation. Do not infer from prior sessions.
If any precondition is missing, STOP. Ask the principal to resolve, or use the non-approved path and let branch protection block.
Flow / Steps
Step 1: Pre-flight
- Confirm the PR number (ask if missing).
- Confirm you're not on the PR's branch — captain merges from master or any non-PR branch.
- If you're going to use
--principal-approved, confirm the principal has authorized in THIS conversation. Don't infer from history.
- Check for pending post-merge (C#372 Fix B). Run
./agency/tools/post-merge-state check. If exit 1, STOP — a prior PR was merged but its release hasn't been cut yet. Run /pr-captain-post-merge <pending-PR> first, then re-invoke this skill. New work cannot start while a prior PR is in pending state. Exit 0 → continue.
Step 2: Invoke the tool
./agency/tools/pr-merge <N>
Or with explicit principal approval (only when they verbally OK'd in-session):
./agency/tools/pr-merge <N> --principal-approved
Tool enforces:
--merge always (never --squash, never --rebase)
- Branch protection respected by default
--admin only when --principal-approved flag is present
Step 3: Handle the outcome
On success (exit 0): report merge URL + next-step recommendation (sync master via ./agency/tools/_sync-main-ref, or wait for /pr-captain-post-merge).
On branch-protection block (exit 3): tool prints the gate. Two resolutions:
- Ask principal to
gh pr review <N> --approve in GitHub UI, then re-run.
- If principal authorized in this conversation but not GitHub UI, re-run with
--principal-approved.
On merge conflict (exit 1): resolve locally first:
gh pr checkout <N>
./agency/tools/git-safe merge-from-master --remote
# resolve conflicts
./agency/tools/git-safe add <files>
./agency/tools/git-captain merge-continue
./agency/tools/git-push <branch>
# then retry
/pr-captain-merge <N>
Step 4: Post-merge (handoff or chain)
After successful merge:
- Sync local master:
./agency/tools/_sync-main-ref
- If release PR: run
/pr-captain-post-merge (or /pr-captain-post-merge once refactored) to create GitHub release + fleet notification.
- Notify affected agents:
/dispatch create --type master-updated --to <agent>
- Notify cross-repo collaborators:
/collaborate if relevant
Failure modes
- CI failing: do NOT merge. Address the failure; restart from
/pr-prep or captain's diagnosis.
- Merge conflicts on agent's branch: sent back for agent to resolve. Captain doesn't resolve agent's conflicts.
- Principal-approved flag without in-conversation authorization: DO NOT PASS. Ask the principal explicitly; wait for their OK; then pass the flag. Captain attests to something real.
- Squash or rebase attempted: blocked by tool. No way in the skill to request.
What this does NOT do
- Does not write commits — merge happens server-side at GitHub.
- Does not delete the local branch — that's captain's next decision (or
/pr-captain-post-merge).
- Does not auto-tag a release — explicit
gh release create afterward (or via /pr-captain-post-merge).
- Does not push — merge is server-side; no local push.
- Does not squash, does not rebase — blocked by the underlying tool (
agency/tools/pr-merge).
Why never squash, never rebase
Both rewrite history. The-agency framework is built on visible, append-only history:
- Branch commits are individually meaningful (QGRs, fixes, version bumps)
- Merge commits create a permanent record of integration
git log --graph shows the actual flow
- Bisecting works against real commits, not synthetic squash blobs
Cost: heavier git log output. Benefit: you can SEE what happened and WHY, which is essential when fleet agents and adopters all have to read the same history.
Captain-only — three-layer defense
Defense in depth against accidental invocation from the wrong context:
paths: [] (intentionally empty) — no file-path auto-activation; universally discoverable for the captain but scoped out of worktree contexts.
- Name contains
captain- — any reader sees scope in the skill listing.
- Runtime precondition — underlying
agency/tools/pr-merge checks caller context before engaging --admin.
(Historically disable-model-invocation: true was a fourth layer. That flag was removed 2026-04-20 because the captain session IS the principal's session — DMI was blocking the captain from invoking captain-* skills. See REFERENCE-SKILL-CONVENTIONS.md §1.)
Status
active — ships as of agency-skill-version 2 adoption 2026-04-19. Replaces v1 pr-merge skill.
Related
/pr-captain-land — composite skill that calls this as its merge step
/pr-prep — the QG-before-PR-create (agent-side)
/pr-submit — agent hands branch to captain for landing
/pr-captain-post-merge (TBD refactored to /pr-captain-post-merge) — release + fleet-notify after merge
agency/tools/pr-merge — the underlying safe-merge tool
claude/hookify/hookify.block-raw-gh-pr-merge.md — hookify rule that blocks bare gh pr merge
agency/REFERENCE-GIT-MERGE-NOT-REBASE.md — the discipline rationale
- the-agency#296 — PR lifecycle ownership (the-agency direction)
- the-agency#298 — skill refactor recommendation (the methodology)
OFFENDERS WILL BE FED TO THE — CUTE — ATTACK KITTENS!