/swarm-pr-review

SkillMonitoring & ops

Run 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.

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 — blocking dispatch_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/Task tool, 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 exact pr_head_sha in 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)ProfileLane dispatchLedger persistenceCompletion gate
OpenCode + swarm pluginAdispatch_lanes_async / collect_lane_resultswrite_pr_review_artifact, write_pr_review_trigger_evalcomplete_pr_workflow
Claude CodeBparallel Agent/Task subagentsledger files in the session task workspacePre-Synthesis Gate checklist
OpenAI CodexBparallel subagents (fresh context)ledger files in working notesPre-Synthesis Gate checklist
ZCodeBparallel subagents (fresh context)ledger files in working notesPre-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:

  • council
  • independent review
  • N-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:

  1. explicit user-provided PR URL, PR number, commit, branch, or file scope,
  2. current feature branch diff vs the remote-tracking base ref (origin/main, origin/master; a local main/master only as a last resort — it is only as fresh as the last fetch and yields a different merge base),
  3. staged changes,
  4. latest commit,
  5. 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:

  1. Resolve and retain the authoritative full pr_head_sha from PR metadata.
  2. Verify the working tree is clean with git status --porcelain. If it is dirty at all — tracked changes, untracked files, or both — call prepare_pr_workflow_checkout (Profile A). The tool supports self-discovery: call it with no paths argument 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 explicit paths only 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 issue git stash through shell. Treat the controller's Git-state result as final for this attempt: clean proceeds, stashable permits exactly one checkout-preparation call, and recovery-required or indeterminate means report the typed required_action, abort/clear any already-active gate, and stop. Retry only when the controller explicitly returns retryable: true; never fight an unmerged index or in-progress Git operation with repeated stash attempts.
  3. 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 example git fetch origin main. Skipping this is the single most common cause of a rejected dispatch: the merge base is recomputed against base_ref, and a local main/refs/heads/main that was never refreshed resolves to a different commit than origin/main for the same base_sha.
  4. Prove the full commit exists locally with git cat-file -e <full_pr_head_sha>^{commit}.
  5. Check out the exact PR filesystem with git switch --detach <full_pr_head_sha>. Do not use --track FETCH_HEAD: FETCH_HEAD is not a remote-tracking branch.
  6. Confirm git rev-parse HEAD equals the full pr_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. Include base_ref only as the live ref used to recompute base_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 gh is not installed, the web fetch tool against the equivalent api.github.com REST 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

CategoryAction
Human review with file:line evidenceAdd as candidate finding with source: existing-review — still needs reviewer validation
Bot/automated finding with specific code referenceAdd as candidate finding with source: bot-review — high false-positive rate, treat as unverified
General feedback / style preferenceAdd as advisory obligation
Resolved/outdated commentSkip — note in report under "Ingested Resolved Comments"
Requested changes not yet addressedAdd 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:

ValueMeaningAction
MERGEABLENo conflicts detectedProceed — check mergeStateStatus below
CONFLICTINGMerge conflicts existRecord the blocker, keep the review read-only, and hand conflict resolution to swarm-pr-feedback
UNKNOWNGitHub still computingWait 30s, re-check

mergeStateStatus field — overall branch state:

ValueAction
CLEANAll checks pass, no conflicts — proceed to Phase 0
BEHINDBranch behind base — note in report; non-blocking if merge queue handles it
DIRTYMerge conflicts exist — keep reviewing, but record the conflict as a first-class blocker in the ledger and handoff artifact
BLOCKEDExternal 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:

  1. 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 (or gh_evidence with target: "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.
  2. 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.
  3. Record explicit next action for the handoff artifact:

    • CONFLICT-### | mechanical | likely resolvable during pr-feedback
    • CONFLICT-### | semantic | requires focused fix + validation during pr-feedback
    • STALE-### | behind base by policy when the branch is only stale, not conflicted
  4. Document in report: List the branch-state facts, why they matter to the review, and what swarm-pr-feedback must 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_REVIEW as 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