| name | merge-pr |
| description | Phase 4 of the PLEXI ship pipeline. Takes an approved PR number, squash-merges to alpha, closes the issue, and cleans up. Input: PR number. Output: merged alpha. |
| risk | medium |
| source | local |
| date_added | 2026-05-20 |
Merge PR
Phase 4 of the ship pipeline. Input: approved PR number. Output: clean alpha with the PR merged. Version bumps happen later at release-batch or promotion time.
Labels are the live state. On success, all pipeline:* labels are removed when the issue closes. On failure, remove all pipeline:* labels and in progress, add ready.
Stint timing closure. Close linked stint tasks with stint done <task-id> after the script exits 0.
Pane slots. Source .agents/skills/_lib/pipeline-slots.sh and publish pipeline_slots_set merge "$ISSUE" "$PR_NUMBER" <status> "" <last-error> at status changes.
Entry: /merge-pr <pr-number>
Step 0 — Set CWD and Flip Pane Status
cd "$(git rev-parse --show-toplevel)"
plexi${PLEXI_CHANNEL:+-$PLEXI_CHANNEL} pane name "#<n> · merging"
pipeline_slots_set merge "$ISSUE" "$PR_NUMBER" merging "" ""
Labels are already correct when invoked inline from validate-pr. No label edit needed here.
Step 1 — Run the Merge Script
just merge-pr <PR_NUMBER>
Handles: rebase, squash-merge, alpha sync, artifact cleanup, issue close, ship log.
If it exits non-zero, read the error and recover with sub-steps:
| Error | Recovery |
|---|
| Rebase conflict | Resolve in worktrees/$BRANCH, then: just merge-rebase $BRANCH → just merge-squash $PR → continue below |
| PR already merged | just merge-sync && just merge-cleanup $PR $BRANCH && just merge-close $ISSUE $PR |
| Dirty root worktree | Commit or restore changed files, re-run just merge-pr $PR |
>1 unexpected commits on local alpha | Investigate before proceeding; do not force-reset blindly |
could not resolve GitHub issue or stint tasks | Only if the PR genuinely has nothing to close (standalone follow-up): just merge-pr $PR no-issue. Otherwise fix the PR body's closing keyword first. |
Available sub-steps:
just merge-rebase <BRANCH>
just merge-squash <PR>
just merge-sync
just merge-cleanup <PR> <BRANCH>
just merge-close <ISSUE> <PR>
Step 2 — Close Linked Stint Tasks
rg -l 'gh_issue: .*"<issue>"|gh_issue: .*\[<issue>\]' .stint/tasks
stint done <task-id>
If estimate was off >2x, add one sentence to the task body explaining why. If no linked task exists, note it in the ship log.
Do not run a full whats-next audit here. stint list + stint status + git log + gh pr list followed by a rewrite of WHATS_NEXT.md costs four commands and a regenerated file on every merge; in a babysitter queue that repeats per batch and the intermediate rewrites are all thrown away by the next one.
Run /whats-next once at the end of a session (or after a batch of merges lands) instead. If you are merging a single PR interactively and want the file current, invoking /whats-next yourself afterward is the cheap path — it is the same work, done once.
Step 3 — Unblock Downstream Issues
gh issue-ext blocking list $ISSUE --json number,title,state 2>/dev/null
For each open blocked issue, check if all blockers are now closed. If so:
gh issue edit <n> --remove-label "blocked" --add-label "ready"
Step 4 — Complete and Close Pane
git status
Output exactly this block — nothing after it, no RECOMMENDATION:
[COMPLETE]
| | |
|---|---|
| PR | #<n> — <title> |
| Issue | #<issue> — <title> / no-issue |
| Alpha | <short-sha> |
| Stint | <task-id> closed / none |
plexi${PLEXI_CHANNEL:+-$PLEXI_CHANNEL} pane name "#<n> · done"
pipeline_slots_set merge "$ISSUE" "$PR_NUMBER" done "" ""
plexi pane close
Soft exit (deferred threads): use needs-you pane status instead of done; do not call plexi pane close.
Rules
- CWD must be repo root for all commands
just install is the user's responsibility post-merge
- Never pass
--delete-branch to gh pr merge — git refuses to delete a branch checked out by a worktree
- Never commit directly to alpha, beta, or main
- Alpha must be clean when this skill exits
- Never close a linked stint task until
just merge-pr exits 0
- On unrecoverable failure: set pane to
blocked, run pipeline_slots_set merge "$ISSUE" "$PR_NUMBER" blocked "" "<error summary>", comment on issue, remove in progress + all pipeline:* labels, add ready, exit