/swarm-pr-review
SkillMonitoring & opsRun a graph-guided, tool-augmented PR review using context packing, parallel exploration, mandatory repository-agnostic risk-family coverage with dispatch scaled to diff size and risk, independent reviewer validation, critic challenge, and metrics writeback. Use for deep pull request review with low false-positive tolerance and high recall in any repository, on any agent harness (structured lane controller, native parallel subagents, or single-context sequential passes).
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the /swarm-pr-review skill
What this skill tells your AI
The instructions your AI receives, as published by zaxbyhub/opencode-swarm in evaluation-fixtures/pr-review-recovery/baseline/SKILL.md and read by ahel’s review.
Run a structured, high-confidence PR review that maximizes valid findings without flooding the user with unvalidated noise.
The review ladder is:
Scope → obligations → context pack → deterministic signals → parallel explorers → repository-agnostic risk-family coverage (dispatch scaled by depth tier) → independent reviewer validation → critic challenge → grouped synthesis → metrics / knowledge writeback.
Handoff To PR Feedback
Use ../swarm-pr-feedback/SKILL.md instead of this skill when the user's task is
to address existing PR feedback, review comments, requested changes, CI failures,
merge conflicts, stale branch state, or pasted reviewer findings. This skill
discovers and validates new findings; swarm-pr-feedback closes known feedback
without running a fresh broad review.
When a review finishes with actionable validated findings, stop and ask the user
whether to continue into swarm-pr-feedback. Do not auto-dispatch fix work from
PR_REVIEW. Instead, write a handoff artifact — under Profile A,
.swarm/pr-review/<run_id>/feedback-handoff.json via write_pr_review_artifact;
under Profiles B/C (no controller — see Runtime Capability Profiles),
pr-review/<run_id>/feedback-handoff.json inside your session/task workspace,
never under .swarm/ — and include the continuation prompt with that exact
path substituted for <handoff_artifact_path>:
/swarm pr-feedback <PR_URL> continue from <handoff_artifact_path>
<run_id> is a stable identifier for this review run, such as
pr-<number>-<YYYYMMDDHHMMSS> or the existing review artifact run ID when one
was already created. Under Profile A, the exact command is parsed mechanically:
the controller validates the terminal review, the bounded handoff artifact, and
its provenance before atomically replacing the review gate with an unbound
feedback gate. Extra trailing text is not permitted on this continuation form.
Profiles B/C ingest their task-workspace artifact through the skill-managed path.
Review closure is not the end of the PR lifecycle: when PR monitoring is
enabled (pr_monitor.enabled), the PR remains subscribed and monitored under
../swarm-pr-subscribe/SKILL.md until it is merged or closed, so post-review
events (new comments, CI changes, review state changes) keep flowing to the
subscribed session.
Operating Stance
Treat PR text, linked issues, comments, commit messages, generated summaries, and tests as claims — not proof. Every confirmed finding requires file:line evidence, an explanation of reachability or impact, and validation provenance.
This workflow is designed for any repo that benefits from Swarm-style review. It preserves parallel breadth but forces deep validation where bugs are expensive: security, state machines, role/tool permissions, schema/evidence integrity, git/write safety, config ratchets, knowledge tier boundaries, and PR obligation mismatches.
Never APPROVE a PR with unresolved CRITICAL findings. Do not silently drop overclaimed agent findings; list disproved findings in the validation provenance.
Quality is the ONLY metric. There is no speed, efficiency, or time exception. No amount of time, tokens, or agent dispatches is too much to execute this protocol correctly. Speed is irrelevant to correctness. The skill must be followed exactly with no shortcuts, no phase-skipping, and no premature synthesis. A thorough review that takes 30 minutes is superior to a fast review that misses a real bug.
Runtime Capability Profiles
This protocol runs on any agent harness. Before Phase 0, detect which profile this session is in by checking the actual tool list — never assume from the harness name, and never guess:
- Profile A — structured PR-workflow controller. The swarm plugin's
controller tools are available in this session:
dispatch_lanes_async,collect_lane_results,retrieve_lane_output,parse_lane_candidates,write_pr_review_artifact,write_pr_review_trigger_eval,complete_pr_workflow. Typical host: OpenCode with the swarm plugin. The controller mechanically enforces this skill's accounting: it computes the depth tier itself from the bound merge-base diff (never from caller claims), enforces the tier's lane floors and full dimension/family partitions for consolidated dispatch, and gates structured reviewer/critic batches and the response gate. Its acceptance rules are authoritative, and where the scaled-dispatch guidance below is more permissive than the active controller, the controller wins. Bypassing an active controller — blockingdispatch_lanes, direct Task/agent dispatch, prose verdicts — is BLOCKED. - Profile B — native parallel subagents, no controller. The controller
tools are absent, but the harness can spawn independent fresh-context
subagents (for example Claude Code's
Agent/Tasktool, or the native subagent mechanisms in Codex and ZCode). Run the same phases, role boundaries, row contracts, and join barriers; you are the accounting layer the controller would otherwise be: bind the exactpr_head_shain every lane prompt, record per-lane provenance (lane id, head SHA) on every ledger row, settle every lane before the next phase begins, and persist ledgers to files in your harness's session/task workspace. Never write runtime artifacts under.swarm/— that directory belongs to the plugin controller. - Profile C — single context, no subagents. The harness cannot spawn independent subagents in-session. Execute the same phases as strictly separated sequential passes — candidate generation, then reviewer validation, then critic challenge — re-deriving rather than restating earlier reasoning in each pass, with the same ledger rows and per-family attestations. Disclose in the validation provenance that reviewer/critic independence was procedural (separate passes in one context), not contextual.
| Harness (typical) | Profile | Lane dispatch | Ledger persistence | Completion gate |
|---|---|---|---|---|
| OpenCode + swarm plugin | A | dispatch_lanes_async / collect_lane_results | write_pr_review_artifact, write_pr_review_trigger_eval | complete_pr_workflow |
| Claude Code | B | parallel Agent/Task subagents | ledger files in the session task workspace | Pre-Synthesis Gate checklist |
| OpenAI Codex | B | parallel subagents (fresh context) | ledger files in working notes | Pre-Synthesis Gate checklist |
| ZCode | B | parallel subagents (fresh context) | ledger files in working notes | Pre-Synthesis Gate checklist |
Verify each row against your own current tool list before relying on it; a harness may gain or lose capabilities between versions. OpenCode, Claude Code, Codex, and ZCode can all spawn fresh-context subagents in current versions — run Profile B wherever the session actually exposes that capability, and reserve Profile C for sessions that genuinely lack a subagent mechanism; never assign a harness to Profile C by name alone. The absence of the controller is NOT a BLOCKED condition — Profiles B and C are first-class execution paths, not degraded fallbacks. BLOCKED is reserved for bypassing an active controller and for coverage gaps that remain unclosable after bounded retries on any profile.
Review Modes
Default layered workflow
Always run the default layered workflow (mechanically enforced under Profile A). Explorers produce only candidates. The orchestrator does not confirm or disprove candidates.
Council mode — opt in only
Council mode applies only when the user explicitly says one of:
councilindependent reviewN-agent review/council[COUNCIL MODE][MODE: PR_REVIEW … council=true]assume all work is wrong
Council mode supplements the default mechanical workflow; it never replaces or weakens it. Even when council mode is triggered, first complete the base-dimension coverage (the tier-floored base dispatch under Profile A — the exact-six wave at depth tier L), micro-lane ledger persistence, and every repository-agnostic risk-family evaluation at the same exact pr_head_sha. Route supplementary council output into the candidate ledger before independent reviewer classification. If the council request arrives after classification has begun, run the council as an additional candidate pass and dispatch a new structured reviewer batch for those candidates before synthesis.
Anti-Self-Review Rule
The main thread / orchestrator MUST NOT classify, confirm, disprove, or judge explorer candidates in the default workflow.
The orchestrator may:
- determine scope,
- build or request the context pack,
- launch explorers and the full risk-family micro coverage (every family evaluated; lane count per depth tier and profile),
- extract candidates from lane artifacts via
parse_lane_candidates(Profile A) or by collecting the structured[CANDIDATE]rows from lane reports (Profiles B/C), - filter, group, and chunk candidates for reviewer dispatch,
- route candidates to reviewers,
- route reviewer-confirmed findings to critics,
- group validated findings,
- prepare the final report.
The orchestrator MUST NOT:
- re-read a candidate's target code to decide if it is valid,
- silently downgrade or discard an explorer candidate,
- treat tool output as a confirmed finding,
- report a finding that no reviewer validated,
- classify or judge candidates based on preview text alone — always use the structured parser output (Profile A) or the verbatim-collected
[CANDIDATE]rows (Profiles B/C).
If the orchestrator catches itself validating code, it must stop and delegate validation to a reviewer subagent.
Exception: in explicit Council mode only, the main thread may act as the independent reviewer as described in the Council Mode section. Prefer a reviewer subagent when available.
Scope Detection
Determine review scope using this priority:
- explicit user-provided PR URL, PR number, commit, branch, or file scope,
- current feature branch diff vs the remote-tracking base ref (
origin/main,origin/master; a localmain/masteronly as a last resort — it is only as fresh as the last fetch and yields a different merge base), - staged changes,
- latest commit,
- user-specified files or directories.
Record:
- base ref,
- head ref,
- commit range,
- changed files,
- deleted files,
- generated files,
- lockfiles,
- test files,
- docs/config/schema files,
- whether the working tree is dirty.
If scope cannot be determined, review the narrowest safe scope available and state the limitation.
Pre-flight git ref availability
Before launching explorers (Phase 3), perform this exact standalone sequence:
- Resolve and retain the authoritative full
pr_head_shafrom PR metadata. - Verify the working tree is clean with
git status --porcelain. If it is dirty at all — tracked changes, untracked files, or both — callprepare_pr_workflow_checkout(Profile A). The tool supports self-discovery: call it with nopathsargument to auto-discover and preserve every dirty path in one step, including untracked files; an already-clean tree returns a no-op (nothing is stashed, no receipt is written). Pass explicitpathsonly when you already have the exact, bounded list of dirty tracked files and want the older exact-match contract. Without the controller (Profiles B/C), do not blind-stash over dirty state: surface tracked changes to the user, or abort. Do not issuegit stashthrough shell. Treat the controller's Git-state result as final for this attempt:cleanproceeds,stashablepermits exactly one checkout-preparation call, andrecovery-requiredorindeterminatemeans report the typedrequired_action, abort/clear any already-active gate, and stop. Retry only when the controller explicitly returnsretryable: true; never fight an unmerged index or in-progress Git operation with repeated stash attempts. - Fetch the PR head as one standalone command, for example
git fetch origin refs/pull/<N>/head. Do not compose fetch and checkout. 3a. Fetch the base branch as its own standalone command, for examplegit fetch origin main. Skipping this is the single most common cause of a rejected dispatch: the merge base is recomputed againstbase_ref, and a localmain/refs/heads/mainthat was never refreshed resolves to a different commit thanorigin/mainfor the samebase_sha. - Prove the full commit exists locally with
git cat-file -e <full_pr_head_sha>^{commit}. - Check out the exact PR filesystem with
git switch --detach <full_pr_head_sha>. Do not use--track FETCH_HEAD:FETCH_HEADis not a remote-tracking branch. - Confirm
git rev-parse HEADequals the fullpr_head_sha, bind that exact head (Profile A: through the first PR-review controller call; Profiles B/C: record it at the top of the findings ledger and repeat it in every lane prompt), and finish this before dispatching explorer lanes.
Explorer agents read files from the working tree, not from git history. Passing
the commit range in a prompt cannot substitute for this checkout because
Read / Glob / Grep operate on the filesystem.
- Explicitly pass the verified merge-base range (
base_sha...pr_head_sha) in every explorer delegation so explorers inspect exactly the bound PR diff. Includebase_refonly as the live ref used to recomputebase_sha; do not substitute a two-dot branch-tip range.
If refs cannot be fetched or checked out, state the limitation in the context pack.
Shell rules under the PR_REVIEW gate
The gate accepts one command per tool call — never compose commands with
&&, ;, |, redirects (>, >>, <), or $(...)/` substitution.
A single leading cd <dir> && prefix and a trailing 2>&1 suffix are
tolerated, but only on read-only commands. State-transition verbs — git fetch, git checkout, git switch, git branch, and gh pr checkout —
must always run bare: no cd prefix, no 2>&1 suffix.
Allowed read-only git subcommands: status, log, show, diff,
rev-parse, merge-base, ls-files, grep, blame, cat-file,
for-each-ref, branch --list (listing only — mutation flags are blocked),
remote -v, and config --get.
Prefer tools over raw shell for state that a single read-only command cannot cover cleanly:
pr_workflow_status— observe local HEAD, branch, dirty-file state, remotes, and gate state in one read-only call.gh_evidence— bounded PR/issue/run metadata without a shell round-trip.- If
ghis not installed, the web fetch tool against the equivalentapi.github.comREST URL is the degraded read-only path.
Phase 0A: Existing PR Signal Ingestion
When reviewing a PR, ingest and triage every existing signal BEFORE starting Phase 0. These are candidate generators and obligation sources, not pre-confirmed findings.
PR title and body compliance check
Before deeper analysis, discover whether the repository defines a PR
publication contract (for example a local commit-pr skill, CONTRIBUTING
guidance, a PR template, or a CI check such as pr-standards). If it does,
verify the PR against that contract and record any gap as an advisory ledger
item. If it does not, do not invent opencode-swarm-specific title/body
sections; still verify that the PR text is not misleading about what the diff
does or proves.
At minimum, check:
- required title/body/linked-issue structure from the discovered repository contract,
- issue-closing, migration, release-note, invariant, or test-plan claims made in the PR text,
- whether those claims are supported by the actual diff and the current issue state.
Issue-closing claim-integrity check: if the PR body uses an issue-closing
keyword such as Closes #<issue-number>, verify (a) the issue is currently open
(gh issue view <N> --json state when the host is GitHub), and (b) the diff
addresses the issue's acceptance criteria (read the issue, map each criterion
to changed files/symbols, and inspect the diff for those areas). If the issue
is already closed by another merged PR, do NOT re-close it — the duplicate
closing reference is misleading. If the issue is open but the diff does not
address the acceptance criteria, mark the claim as UNVERIFIED — claim integrity in the validation provenance and surface the unresolved gap to the
user before synthesis.
Contract non-compliance is a ledger item (advisory unless the repository explicitly makes it blocking). If the PR is from an external contributor, note the compliance gap for the maintainer to address before merge.
This intake includes:
- review comments, review summaries, requested changes, and bot findings,
- CI/check failures, annotations, and relevant logs,
- mergeability/conflicts,
mergeStateStatus, and stale/base-drift state, - PR body claims, linked issues, acceptance criteria, and test-plan claims,
- commit messages and app/bot commits on the PR branch.
When thread resolution state matters, prefer GraphQL review-thread inspection.
If GraphQL is unavailable, keep the signal and mark
resolution_state: UNKNOWN; do not drop it from scope.
Step 1 — Fetch all PR feedback surfaces
The commands below are GitHub examples. On GitLab, Bitbucket, Gerrit, or another code host, use the host's API/connector/CLI to enumerate the same full surface, including pagination and unresolved-thread state. Host choice never reduces the intake ledger.
# Issue comments (general PR thread)
gh api --paginate repos/{owner}/{repo}/issues/{PR_NUMBER}/comments
# Review comments (inline code comments)
gh api --paginate repos/{owner}/{repo}/pulls/{PR_NUMBER}/comments
# Review summaries (approve/request-changes/comment events)
gh api --paginate repos/{owner}/{repo}/pulls/{PR_NUMBER}/reviews
--paginate requests every REST page. These three calls are gate-allowed as
written; do not pipe any of them through --jq, jq, or another filter under
the PR_REVIEW gate — piped commands are blocked (fail-closed on |). To
separate bot/automated reviews (Copilot, Codex, CodeRabbit, etc.) from human
ones, apply the same predicate in context to the JSON already returned above
— user.type == "Bot" or a user.login match against
bot|copilot|coderabbit|codex (case-insensitive) — instead of re-fetching
with a shell-side --jq filter. gh_evidence with target: "pr" and
fields: "comments" is the sanctioned read-only tool path for the same PR
comment data when a tool call is preferred over a raw shell command. gh pr view --json comments,reviews is convenience-only because those fields have
item caps; never use it as the authoritative "all signals" intake.
Step 2 — Classify each comment
| Category | Action |
|---|---|
| Human review with file:line evidence | Add as candidate finding with source: existing-review — still needs reviewer validation |
| Bot/automated finding with specific code reference | Add as candidate finding with source: bot-review — high false-positive rate, treat as unverified |
| General feedback / style preference | Add as advisory obligation |
| Resolved/outdated comment | Skip — note in report under "Ingested Resolved Comments" |
| Requested changes not yet addressed | Add as HIGH-priority obligation |
Step 3 — Merge into review pipeline
All ingested comments become candidate findings or obligations. They follow the same Phase 3-8 pipeline as freshly discovered findings. Ingested findings are NOT pre-confirmed — they still require independent reviewer validation per the Anti-Self-Review Rule.
Comment-ledger output:
[INGESTED] | source | category | file:line (if applicable) | original_author | status: PENDING_VALIDATION / SKIPPED_OUTDATED / ADVISORY
Anti-patterns
- ✗ Ignoring bot reviews because "bots produce false positives" — they also catch real issues
- ✗ Pre-confirming human review comments without independent validation — even senior reviewers make mistakes
- ✗ Skipping inline review comments and only reading the summary — inline comments contain the evidence
Phase 0B: Mergeability and Branch-State Intake
Before investing effort in review lanes, verify the PR is mergeable and record
branch-state signals. PR_REVIEW remains read-only: do not resolve conflicts,
commit, push, rebase, merge, or reset from this mode. Instead, carry current
mergeability, stale-head, and branch-drift facts into the review ledger and the
feedback handoff artifact.
Step 1 — Check merge state
The field names and values below are GitHub-specific examples. On another code host, record the equivalent mergeability, conflict, required-check, base-drift, and stale-head signals and preserve the same read-only behavior.
gh pr view <PR_NUMBER> --json mergeable,mergeStateStatus
The response has two independent fields. Handle each:
mergeable field — whether GitHub can compute mergeability:
| Value | Meaning | Action |
|---|---|---|
MERGEABLE | No conflicts detected | Proceed — check mergeStateStatus below |
CONFLICTING | Merge conflicts exist | Record the blocker, keep the review read-only, and hand conflict resolution to swarm-pr-feedback |
UNKNOWN | GitHub still computing | Wait 30s, re-check |
mergeStateStatus field — overall branch state:
| Value | Action |
|---|---|
CLEAN | All checks pass, no conflicts — proceed to Phase 0 |
BEHIND | Branch behind base — note in report; non-blocking if merge queue handles it |
DIRTY | Merge conflicts exist — keep reviewing, but record the conflict as a first-class blocker in the ledger and handoff artifact |
BLOCKED | External blocker (branch protection, failing required check) — investigate and record the blocker |
Step 2 — Record conflicts and blockers (when CONFLICTING or DIRTY)
When the PR has merge conflicts:
-
Determine the PR's base branch and verify the state, as separate standalone commands — never with
$(...)command substitution, which the PR_REVIEW gate blocks:- Read the base ref:
gh pr view <PR_NUMBER> --json baseRefName(orgh_evidencewithtarget: "pr",fields: "baseRefName"). - Fetch it by its literal value, substituted for
<base-ref>:git fetch origin <base-ref>. - Re-check merge state:
gh pr view <PR_NUMBER> --json mergeable,mergeStateStatus,baseRefName,headRefName.
- Read the base ref:
-
Capture the affected scope without changing the branch:
- List the files or subsystems implicated by the conflict if GitHub exposes them, or note that the exact conflict set is still unknown.
- Identify whether the conflict appears mechanical (lockfile / generated output / simple overlap) or semantic (logic changed on both sides). This is triage signal for the follow-on feedback run, not permission to resolve it here.
-
Record explicit next action for the handoff artifact:
CONFLICT-### | mechanical | likely resolvable during pr-feedbackCONFLICT-### | semantic | requires focused fix + validation during pr-feedbackSTALE-### | behind base by policywhen the branch is only stale, not conflicted
-
Document in report: List the branch-state facts, why they matter to the review, and what
swarm-pr-feedbackmust verify before it edits code.
Conflict resolution anti-patterns
- ✗ Accepting "ours" or "theirs" for all conflicts without reading them
- ✗ Resolving semantic conflicts without understanding both sides
- ✗ Pushing resolution without running tests on the merged result
- ✗ Treating
PR_REVIEWas the place to fix branch state — this mode stays read-only
Phase 0B-bis: Pre-Handoff Parallel Work Snapshot
Shortened here. Read the whole file on GitHub.
Signals
- GitHub stars
- 467
- Forks
- 51
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
swarm-pr-review- Source
- github.com/zaxbyhub/opencode-swarm