Parallel PR Review
Overview
Review many open PRs at once by fanning out one read-only review subagent per PR (or per stack), each producing a structured verdict, then synthesizing a cross-PR summary and posting reviews. The reviewer (you) stays in the loop holding conclusions; subagents absorb the per-diff reading.
Core principle: one agent per independent unit of review, a consistent rubric and output format across all of them, then a synthesis pass that finds what no single PR review can see.
When to Use
- "Review the open PRs" / "anything new to review?" / recurring review loops
- A batch of PRs from one author, or a stacked series (PR based on another PR's branch)
- Any time reading every diff yourself would blow context
When NOT to use: a single PR (just review it directly); a PR you authored mid-task (use normal self-review).
Workflow
Enumerate + triage. List PRs with the metadata that drives decisions:
gh pr list --state open --limit 100 --json number,title,author,additions,deletions,baseRefName,mergeable \
--jq 'sort_by(.number) | reverse[] | "#\(.number) @\(.author.login) +\(.additions)/-\(.deletions) base:\(.baseRefName) \(.mergeable) \(.title)"'
base != main ⇒ stacked PR (review with its stack, note merge order).
CONFLICTING ⇒ flag; have the agent diagnose cause + resolution. Re-check: some "conflicting" clears after an upstream rebase.
- Compare against PRs already reviewed in prior passes — only review what's new (and re-check any that grew).
Group. One agent per PR for standalone changes; one agent per stack (review each stacked PR's own gh pr diff, in dependency order). Give security-sensitive PRs (contracts, crypto/keys, auth/attestation, money/billing, DoS bounds) their own dedicated agent with an adversarial prompt. For large or structural PRs (big refactors, new modules, files crossing ~1k lines), add a dedicated maintainability-lens agent (see Maintainability lens below).
Fan out review subagents in parallel — all in one message so they run concurrently. Use a code-review agent type; each gets the prompt template below. Tell them not to modify files.
Synthesize. Collect verdicts into one table; then write the cross-cutting section: recurring bug classes, themes spanning PRs, "already rebased/clean now," and which PRs to land first.
Post (only when asked) — see Posting.
Clean up review branches subagents fetched (see Cleanup).
Subagent prompt template
Give each agent: the PR number(s), how to get the diff (gh pr diff <n>), an instruction to read surrounding context with Read/Grep, and a fixed rubric:
Focused [adversarial, if security] code review of PR #<n> in <repo path>.
Get the diff: `gh pr diff <n>`. Read surrounding context with Read/Grep on the
actual changed files. Do NOT modify any files.
Review priorities, in order:
1. Correctness — real bugs, races, wrong-key/off-by-one, missed cases.
2. Security — <adversarial angle for this PR: spoofable identity, replay,
unbounded growth/DoS, fail-open, key reuse, double-pay, TOCTOU>.
3. Privacy/logging — <repo's logging rule, e.g. "log ids/counts/sizes/durations/
error-types only, never prompts/completions/keys/raw bytes">.
4. Tests — are they non-vacuous (would fail on a real regression)? CI-runnable
(not #[ignore]/feature-gated off)? Deterministic (no port/timing flake)?
5. Structural quality (behavior-preserving) — would a cleaner reframing DELETE
categories of complexity, not just polish? Flag: ad-hoc conditionals/special
cases bolted onto unrelated flows; feature-specific logic leaking into a
general module; thin wrappers adding indirection without clarity; unnecessary
casts / `any` / optional params muddying contracts; copy-paste instead of an
extracted helper; a bespoke helper duplicating an existing canonical utility;
a file pushed past ~1k lines without strong reason. Propose the restructuring,
not the incremental tidy. Must not change semantics; outranked by 1-2.
6. [stacked/conflicting] Diagnose the conflict: git fetch origin; git log
--oneline origin/main -20; name the colliding PR and the resolution.
Output: one-line summary, VERDICT (APPROVE / APPROVE WITH NITS / REQUEST CHANGES),
then numbered findings `severity [file:line] — issue → suggested fix`.
Be precise and skeptical; distinguish real bugs from speculation.
Tailor priority 2 per PR — that targeting is what makes the reviews sharp (e.g. "is the owner-proof replayable?", "is this per-deployment map bounded + pruned on undeploy?", "does the validity check use a spoofable clock?").
Output format (consistent across all agents)
- Verdict:
APPROVE / APPROVE WITH NITS / REQUEST CHANGES (add REJECT/CLOSE for superseded/duplicate PRs).
- Findings:
severity [file:line] — issue → fix, severities Critical / Important / Low / Nit, plus Praise/Good for verified-correct load-bearing code.
- Demand non-vacuity checks on test PRs: a test that would pass even with the bug present is a finding, not coverage. Agents can prove it by mutation ("deleting X makes it fail").
Maintainability lens (thermo-nuclear)
Rubric priority 5 is bug-and-risk review's structural complement: it audits behavior-preserving quality. Run it on every PR; for large/structural PRs give it a dedicated agent (as security PRs get a dedicated adversarial agent).
- Bias to deletion ("code judo"). The win is a restructuring that makes whole branches / helpers / conditionals disappear — not "a bit cleaner." Reject incremental polish when dramatic simplification is available. Prefer removing pieces over redistributing complexity.
- Flag in impact order: (1) structural regressions; (2) missed dramatic simplifications; (3) spaghetti/branching growth (ad-hoc conditionals, scattered special cases); (4) boundary/type-contract problems (casts,
any, optional params); (5) file-size/decomposition (a PR pushing a file past ~1k lines without strong reason); (6) modularity/abstraction (feature logic in general modules, thin wrappers, bespoke helpers duplicating canonical utilities); (7) legibility.
- Approval bar: no structural regression, no obvious missed simplification, no unjustified file growth, no new spaghetti, no hacky abstraction obscuring intent.
- Guardrails: every structural finding must be semantics-preserving and must cite the concrete restructuring; correctness and security still outrank it; don't let it become style-nitpicking (a formatter's job). Adapted from cursor-team-kit's
thermo-nuclear-code-quality-review.
Posting
Post only when the user asks. Default to review comments, not formal approve/request-changes, when reviewing someone else's PRs — a comment carries the verdict in its body without flipping GitHub's merge-blocking state unilaterally.
# write each body to a file (heredocs survive markdown/newlines safely), then:
gh pr review <n> --comment --body-file /tmp/reviews/<n>.md
- Loop over PRs; print OK/FAILED per PR so a failed post is visible.
- For a superseded/duplicate PR, post a "close as superseded by #X" conversational comment (
gh pr comment) instead of a review.
- Surface big cross-cutting observations as their own
gh pr comment so they're actionable, not buried in a long review body.
Cleanup
Subagents fetch/checkout PR branches. Afterward, return the repo to a clean main:
git worktree list # ensure no stray worktrees
git branch --format='%(refname:short)' # find leftover PR branches
Before deleting a leftover branch, confirm its commits exist on a remote (no local-only work lost):
git branch -r --contains "$(git rev-parse <branch>)" # must print an origin/... ref
git branch -D <branch> # then safe to delete
Common Mistakes
- One mega-agent for all PRs → shallow, context-blown. One unit of review per agent.
- Generic rubric → generic findings. Tailor the security angle per PR.
- Reviewing stacked PRs against the wrong base → use each PR's own
gh pr diff, note merge order.
- Trusting
mergeable/reviews blindly → conflicts clear on rebase; "1 review" is often the author's own. Re-check.
- Accepting test PRs at face value → require a non-vacuity argument.
- Formal approve/request-changes on someone else's PRs without being asked → use
--comment.
jq choking on PR JSON → review bodies contain newlines; query non-body fields, or use --jq server-side.
- Leaving fetched branches behind → always run Cleanup.
1---2name: parallel-pr-review3description: Use when asked to "review the open PRs", review a batch or stack of pull requests, or run a recurring PR-review pass on a repo — especially with many PRs, stacked branches, conflicts, or security-sensitive changes. Covers grouping, fan-out to review subagents, verdict synthesis, and posting.4---5
6# Parallel PR Review
7
8## Overview
9
10Review many open PRs at once by fanning out one read-only review subagent per PR (or per stack), each producing a structured verdict, then synthesizing a cross-PR summary and posting reviews. The reviewer (you) stays in the loop holding conclusions; subagents absorb the per-diff reading.
11
12**Core principle:** one agent per independent unit of review, a consistent rubric and output format across all of them, then a synthesis pass that finds what no single PR review can see.
13
14## When to Use
15
16- "Review the open PRs" / "anything new to review?" / recurring review loops
17- A batch of PRs from one author, or a stacked series (PR based on another PR's branch)
18- Any time reading every diff yourself would blow context
19
20**When NOT to use:** a single PR (just review it directly); a PR you authored mid-task (use normal self-review).
21
22## Workflow
23
241. **Enumerate + triage.** List PRs with the metadata that drives decisions:
25 ```
26 gh pr list --state open --limit 100 --json number,title,author,additions,deletions,baseRefName,mergeable \
27 --jq 'sort_by(.number) | reverse[] | "#\(.number) @\(.author.login) +\(.additions)/-\(.deletions) base:\(.baseRefName) \(.mergeable) \(.title)"'
28 ```
29 - `base != main` ⇒ **stacked PR** (review with its stack, note merge order).
30 - `CONFLICTING` ⇒ flag; have the agent diagnose cause + resolution. Re-check: some "conflicting" clears after an upstream rebase.
31 - Compare against PRs already reviewed in prior passes — only review what's new (and re-check any that grew).
32
332. **Group.** One agent per PR for standalone changes; one agent per **stack** (review each stacked PR's own `gh pr diff`, in dependency order). Give **security-sensitive** PRs (contracts, crypto/keys, auth/attestation, money/billing, DoS bounds) their own dedicated agent with an adversarial prompt. For **large or structural** PRs (big refactors, new modules, files crossing ~1k lines), add a dedicated **maintainability-lens** agent (see Maintainability lens below).
34
353. **Fan out** review subagents in parallel — all in one message so they run concurrently. Use a code-review agent type; each gets the prompt template below. Tell them **not to modify files**.
36
374. **Synthesize.** Collect verdicts into one table; then write the cross-cutting section: recurring bug classes, themes spanning PRs, "already rebased/clean now," and which PRs to land first.
38
395. **Post** (only when asked) — see Posting.
40
416. **Clean up** review branches subagents fetched (see Cleanup).
42
43## Subagent prompt template
44
45Give each agent: the PR number(s), how to get the diff (`gh pr diff <n>`), an instruction to read surrounding context with Read/Grep, and a fixed rubric:
46
47```
48Focused [adversarial, if security] code review of PR #<n> in <repo path>.
49Get the diff: `gh pr diff <n>`. Read surrounding context with Read/Grep on the
50actual changed files. Do NOT modify any files.
51
52Review priorities, in order:
531. Correctness — real bugs, races, wrong-key/off-by-one, missed cases.
542. Security — <adversarial angle for this PR: spoofable identity, replay,
55 unbounded growth/DoS, fail-open, key reuse, double-pay, TOCTOU>.
563. Privacy/logging — <repo's logging rule, e.g. "log ids/counts/sizes/durations/
57 error-types only, never prompts/completions/keys/raw bytes">.
584. Tests — are they non-vacuous (would fail on a real regression)? CI-runnable
59 (not #[ignore]/feature-gated off)? Deterministic (no port/timing flake)?
605. Structural quality (behavior-preserving) — would a cleaner reframing DELETE
61 categories of complexity, not just polish? Flag: ad-hoc conditionals/special
62 cases bolted onto unrelated flows; feature-specific logic leaking into a
63 general module; thin wrappers adding indirection without clarity; unnecessary
64 casts / `any` / optional params muddying contracts; copy-paste instead of an
65 extracted helper; a bespoke helper duplicating an existing canonical utility;
66 a file pushed past ~1k lines without strong reason. Propose the restructuring,
67 not the incremental tidy. Must not change semantics; outranked by 1-2.
686. [stacked/conflicting] Diagnose the conflict: git fetch origin; git log
69 --oneline origin/main -20; name the colliding PR and the resolution.
70
71Output: one-line summary, VERDICT (APPROVE / APPROVE WITH NITS / REQUEST CHANGES),
72then numbered findings `severity [file:line] — issue → suggested fix`.
73Be precise and skeptical; distinguish real bugs from speculation.
74```
75
76Tailor priority 2 per PR — that targeting is what makes the reviews sharp (e.g. "is the owner-proof replayable?", "is this per-deployment map bounded + pruned on undeploy?", "does the validity check use a spoofable clock?").
77
78## Output format (consistent across all agents)
79
80- **Verdict:** `APPROVE` / `APPROVE WITH NITS` / `REQUEST CHANGES` (add `REJECT/CLOSE` for superseded/duplicate PRs).
81- **Findings:** `severity [file:line] — issue → fix`, severities Critical / Important / Low / Nit, plus `Praise`/`Good` for verified-correct load-bearing code.
82- Demand **non-vacuity checks** on test PRs: a test that would pass even with the bug present is a finding, not coverage. Agents can prove it by mutation ("deleting X makes it fail").
83
84## Maintainability lens (thermo-nuclear)
85
86Rubric priority 5 is bug-and-risk review's structural complement: it audits **behavior-preserving** quality. Run it on every PR; for large/structural PRs give it a **dedicated agent** (as security PRs get a dedicated adversarial agent).
87
88- **Bias to deletion ("code judo").** The win is a restructuring that makes whole branches / helpers / conditionals _disappear_ — not "a bit cleaner." Reject incremental polish when dramatic simplification is available. Prefer removing pieces over redistributing complexity.
89- **Flag in impact order:** (1) structural regressions; (2) missed dramatic simplifications; (3) spaghetti/branching growth (ad-hoc conditionals, scattered special cases); (4) boundary/type-contract problems (casts, `any`, optional params); (5) file-size/decomposition (a PR pushing a file past ~1k lines without strong reason); (6) modularity/abstraction (feature logic in general modules, thin wrappers, bespoke helpers duplicating canonical utilities); (7) legibility.
90- **Approval bar:** no structural regression, no obvious missed simplification, no unjustified file growth, no new spaghetti, no hacky abstraction obscuring intent.
91- **Guardrails:** every structural finding must be semantics-preserving and must cite the concrete restructuring; correctness and security still outrank it; don't let it become style-nitpicking (a formatter's job). Adapted from cursor-team-kit's `thermo-nuclear-code-quality-review`.
92
93## Posting
94
95Post only when the user asks. Default to **review comments**, not formal approve/request-changes, when reviewing someone else's PRs — a comment carries the verdict in its body without flipping GitHub's merge-blocking state unilaterally.
96
97```bash
98# write each body to a file (heredocs survive markdown/newlines safely), then:
99gh pr review <n> --comment --body-file /tmp/reviews/<n>.md
100```
101
102- Loop over PRs; print OK/FAILED per PR so a failed post is visible.
103- For a superseded/duplicate PR, post a "close as superseded by #X" **conversational** comment (`gh pr comment`) instead of a review.
104- Surface big cross-cutting observations as their own `gh pr comment` so they're actionable, not buried in a long review body.
105
106## Cleanup
107
108Subagents fetch/checkout PR branches. Afterward, return the repo to a clean `main`:
109
110```bash
111git worktree list # ensure no stray worktrees
112git branch --format='%(refname:short)' # find leftover PR branches
113```
114
115Before deleting a leftover branch, confirm its commits exist on a remote (no local-only work lost):
116
117```bash
118git branch -r --contains "$(git rev-parse <branch>)" # must print an origin/... ref
119git branch -D <branch> # then safe to delete
120```
121
122## Common Mistakes
123
124- **One mega-agent for all PRs** → shallow, context-blown. One unit of review per agent.
125- **Generic rubric** → generic findings. Tailor the security angle per PR.
126- **Reviewing stacked PRs against the wrong base** → use each PR's own `gh pr diff`, note merge order.
127- **Trusting `mergeable`/`reviews` blindly** → conflicts clear on rebase; "1 review" is often the author's own. Re-check.
128- **Accepting test PRs at face value** → require a non-vacuity argument.
129- **Formal approve/request-changes on someone else's PRs without being asked** → use `--comment`.
130- **`jq` choking on PR JSON** → review bodies contain newlines; query non-body fields, or use `--jq` server-side.
131- **Leaving fetched branches behind** → always run Cleanup.