|
| 1 | +# /prm — PR, CI green, then merge |
| 2 | + |
| 3 | +The end-of-task shortcut for "PR CI green then merge" — three keystrokes instead |
| 4 | +of the sentence. It watches the feature PR's checks, merges the moment they are |
| 5 | +genuinely green, and finishes the ship (Mind record, issue comment, cleanup). |
| 6 | + |
| 7 | +Shared routing context: `PyAutoBrain/skills/COMMANDS.md`. |
| 8 | +gh mechanics + snippets: [`reference.md`](reference.md). |
| 9 | + |
| 10 | +## Principle: compose, don't recompute |
| 11 | + |
| 12 | +Every rule here already has an owner. The merge gates belong to |
| 13 | +[`../ship_library/ship_library.md`](../ship_library/ship_library.md) and |
| 14 | +[`../ship_workspace/ship_workspace.md`](../ship_workspace/ship_workspace.md) |
| 15 | +(library-first gate, issue completion, Mind state); the verdict belongs to GitHub |
| 16 | +Actions. `/prm` only sequences them. It never re-runs the readiness gate, never |
| 17 | +edits code to make a check pass, and never opens a PR — that is `/ship_*`. |
| 18 | + |
| 19 | +## Usage |
| 20 | + |
| 21 | +``` |
| 22 | +/prm # the PR for the current branch / current task |
| 23 | +/prm 380 # PR #380 in the current or inferred repo |
| 24 | +/prm PyAutoArray#42 # or Jammy2211/PyAutoArray#42, or the full PR URL |
| 25 | +/prm --no-wait # judge CI once and report; merge only if already green |
| 26 | +``` |
| 27 | + |
| 28 | +## Environment: runs anywhere gh is authenticated |
| 29 | + |
| 30 | +Local CLI, mobile Claude Code chat, and Codex all work — every step is `gh`, no |
| 31 | +checkout required. Detect which you are in: |
| 32 | + |
| 33 | +- **Local** — `$PYAUTO_ROOT` (default `~/Code/PyAutoLabs`) holds the sibling |
| 34 | + repos. Branch detection and post-merge worktree cleanup are available. |
| 35 | +- **Remote (mobile/codex)** — no multi-repo checkout. Resolve the PR from the |
| 36 | + argument or by listing candidates (below), and **skip the local-only cleanup** |
| 37 | + with a one-line note. Never `cd` into a repo that isn't there. |
| 38 | + |
| 39 | +## The routine |
| 40 | + |
| 41 | +### 1. Resolve the target PR(s) |
| 42 | + |
| 43 | +In order: explicit argument → current branch (`gh pr view --json` in the repo you |
| 44 | +are in) → the claimed task in `PyAutoMind/active.md` (its `library-pr:` / |
| 45 | +`workspace-pr:` entries; on mobile read it with `gh api`) → `gh pr list` across |
| 46 | +the claimed repos. If more than one candidate survives, **list them numbered and |
| 47 | +ask once** — never guess which PR to merge. Report each target as |
| 48 | +`owner/repo#N — title — branch` before doing anything. |
| 49 | + |
| 50 | +A task that shipped both a library and a workspace PR is **one** `/prm` run over |
| 51 | +both, merged in gate order (step 4). |
| 52 | + |
| 53 | +### 2. Judge CI honestly — every run, every leg |
| 54 | + |
| 55 | +A head sha triggers **two** runs of each workflow (`push` and `pull_request`), |
| 56 | +each with its own matrix legs. One green row is not "CI green". Enumerate every |
| 57 | +run for the head sha and every job inside it (snippets in `reference.md`), and |
| 58 | +treat any run that is not `completed` as *not ready* — not "green so far". |
| 59 | +`mergeStateStatus=UNSTABLE` is the tell that something is still pending or red. |
| 60 | + |
| 61 | +Also read `mergeable` and `mergeStateStatus`: `CONFLICTING` / `BEHIND` / |
| 62 | +`BLOCKED` stops the run with the reason, whatever the checks say. |
| 63 | + |
| 64 | +### 3. Wait, or stop |
| 65 | + |
| 66 | +- **Pending** — poll every ~90s, one compact line per poll (`3/4 legs done`). |
| 67 | + Cap at ~30 min; then report where it stands and stop rather than spinning. |
| 68 | + Under `--no-wait`, skip the loop: report and stop. |
| 69 | +- **Red** — **fetch the failing job's log immediately** (GitHub purges the blob; |
| 70 | + once purged you can never name what broke), quote the failing step, and stop. |
| 71 | + Do not merge, do not re-run, do not "wait for the flake to pass". Offer the |
| 72 | + next door: `/bug` for a real failure, or a named re-run if the user judges it a |
| 73 | + known flake — their call, not yours. |
| 74 | +- **No checks configured** — say so explicitly and ask before merging. |
| 75 | + |
| 76 | +### 4. Merge |
| 77 | + |
| 78 | +Green on every leg → merge, in this order: |
| 79 | + |
| 80 | +1. **Library PR first.** The workspace PR may not merge until its upstream |
| 81 | + library PR is `MERGED` — the library-first gate |
| 82 | + ([`../ship_workspace/reference.md`](../ship_workspace/reference.md)). Refuse |
| 83 | + otherwise; there is no `--auto`-flag workaround. |
| 84 | +2. `gh pr merge <n> --merge` per PR (add `-R owner/repo` when you have no |
| 85 | + checkout), then confirm the resulting state is `MERGED` — a queued or |
| 86 | + auto-merge state is not a merge. Do **not** pass `--delete-branch`: it deletes |
| 87 | + the local branch too, which fails or orphans a task worktree. Branch deletion |
| 88 | + belongs to the post-merge cleanup in step 5. |
| 89 | + |
| 90 | +Never force, never override a protection, never rewrite history. If a merge is |
| 91 | +refused by GitHub, report the reason verbatim and stop. |
| 92 | + |
| 93 | +### 5. Finish the ship |
| 94 | + |
| 95 | +Hand back to the ship skills' completion steps — do not re-invent them: |
| 96 | + |
| 97 | +- Post the "Shipped" comment on the issue (templates: `../ship_library/reference.md` |
| 98 | + → "Issue comments + Mind state"). |
| 99 | +- Write the dated completion record — `PyAutoMind/scripts/lifecycle.py record` |
| 100 | + (also refreshes the index and prunes the `active.md` entry) — and push Mind. |
| 101 | +- **Ask before closing the issue.** Merging is what `/prm` was typed for; closing |
| 102 | + is a separate decision the human makes. |
| 103 | +- **Local only:** offer the post-merge cleanup (worktree removal, local branch |
| 104 | + deletion) per the ship skills; on mobile/codex note it as still pending. |
| 105 | + |
| 106 | +## Notes |
| 107 | + |
| 108 | +- `/prm` merges an **existing** PR. No PR yet → `/ship_library` or |
| 109 | + `/ship_workspace` first; `/prm` will say so rather than opening one. |
| 110 | +- It never bypasses the Heart readiness gate — that gate ran at ship time, and a |
| 111 | + red Heart is not something a merge shortcut may re-judge. |
| 112 | +- Under a `--auto` workflow run, merge stays human: `/prm` is a human-typed door |
| 113 | + and is never invoked by the autonomous queue. |
0 commit comments