You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A multi-model adversarial + consensus pull request review skill for opencode and Claude Code.
Four different model families independently review your PR, then an adjudicator deduplicates, resolves disagreements, validates fixes against the surrounding code, and ranks every finding on a 0–5 severity scale. You get one action plan and one question: which fixes to apply.
Why multi-model adversarial review
Models from the same family share blind spots. A single reviewer (or three same-family variants) will miss the same class of bugs. This skill deliberately dispatches diverse model families — DeepSeek, Kimi, Qwen, and GPT — so their disagreements surface real issues that any one model would miss. The adjudicator then merges their findings into a single, confidence-scored plan.
What it does
Resolves the PR from a URL, number, or the current branch/worktree (auto-detection, no arg needed).
Fetches the diff via gh and ingests existing reviewer comments — CodeRabbit, architecture-reviewer, Gemini, and human reviewers. Unresolved findings become prior context so adversaries validate/refute them rather than rediscovering (or missing) them.
Gathers context — pulls the related Linear story (if a ticket ID is on the PR/branch) and any linked Notion/plan docs, then classifies the PR's surface area (web / mobile / distributed) to apply the right lens.
Dispatches 4 adversary models in parallel, each with a unique review lens, all against the 7 Engineering Concerns rubric.
Adjudicates consensus — dedupes by agreement, resolves conflicts by reading the actual code, validates against the Linear story/plan, and runs a controlled-entropy check (reads ±30 lines around each proposed fix to ensure it won't ripple).
Presents a severity-ranked action plan (0 = critical → 5 = optional), each finding with: concern, location, why, proposed fix, blast radius, confidence, and which adversaries/reviewers flagged it.
Asks one question — fix critical+high, fix through medium, adjust the plan, or report only. Fixes are applied in parallel, then committed and pushed automatically.
The 7 Engineering Concerns
Every adversary reviews against these (adapted from Luxury Presence's engineering framework):
Concern
One-line test
Correctness
Is the spec itself right? Does the solution match what the code actually does?
Maintainability & extensibility
Can the next change be made safely and cheaply?
Security
Can only the right principals do or see this? (IDOR, vacuous auth, unauth endpoints)
Performance
Is the access pattern right for the read/write shape, and does it survive N× load?
Reliability & failure modes
What happens when a dependency is slow, down, or half-done?
Testability & verifiability
Can this code prove itself correct without a human reading every line?
Operability
Can we run this as a team and with agents? Do we know if something is actually failing?
Requirements
opencode or Claude Code with skill support
gh CLI, authenticated (gh auth login)
Python 3 (for the adversary helper script — stdlib only, no pip packages)
A litellm-compatible gateway with the adversary models deployed (see below)
Optional: Anthropic provider configured in opencode (for Opus 5 adjudication — the skill works without it)
Installation
1. Install the skill
Clone or download this gist, then place the files in your skills directory:
# For opencode (global skills)
mkdir -p ~/.claude/skills/pr-code-review
# Place SKILL.md and adversary.py in that directory# Verify
ls ~/.claude/skills/pr-code-review/
# → SKILL.md adversary.py
chmod +x ~/.claude/skills/pr-code-review/adversary.py
2. Configure the litellm gateway
The adversary helper (adversary.py) calls models via a litellm-compatible OpenAI gateway. It reads the URL and API key from your opencode config at ~/.config/opencode/opencode.json:
Non-LP users: The default gateway URL in adversary.py is LP-specific (https://litellm.luxurycoders.com/v1). Edit the LITELLM_URL constant at the top of adversary.py to point at your own gateway, and update the model IDs in SKILL.md section 6b to match models you have deployed. The skill degrades gracefully — if a model is unavailable, it's skipped and the review proceeds with the rest (minimum 2 adversaries required).
3. (Optional) MCP integrations
The skill can pull Linear and Notion context if you have those MCP servers configured. Both are optional — if absent or unauthorized, the review proceeds without them:
Linear MCP — retrieves the related story's acceptance criteria for PR-accuracy validation
If any adversary is unavailable, it's skipped (minimum 2 must succeed). The adjudicator runs with file access so it can perform the controlled-entropy check — a stateless API call can't read your surrounding code.
Optional: Claude Opus 5 adjudication
By default, the orchestrator model adjudicates inline. If you have the Anthropic provider configured in opencode, you can optionally dispatch a real anthropic/claude-opus-5 subagent for stronger adjudication. The skill auto-detects whether Anthropic is configured and degrades gracefully if not — no prompts, no warnings.
To enable, add custom agents to ~/.config/opencode/opencode.json (see SKILL.md section 11 for the full config). The four adversary agents work with litellm alone; the pr-review-opus adjudicator requires Anthropic.
Customization
Models / lenses — edit the table in SKILL.md section 6b and the adversary.py calls to use different models or lenses
Gateway URL — edit LITELLM_URL in adversary.py
7 Concerns rubric — edit SKILL.md section 5 to match your team's engineering principles
Surface-area detection — edit SKILL.md section 3c to match your repo's path conventions
Severity scale — edit SKILL.md section 7, step 5
Files
File
Purpose
SKILL.md
The skill definition — opencode/Claude Code reads this to run the review
adversary.py
Helper script that calls one litellm model with the review prompt (stdlib only)
README.md
This file
How a review flows
PR URL/number/branch
│
▼
Resolve PR (gh) ──► Fetch diff + reviewer comments
│
▼
Gather context (Linear, Notion, surface area)
│
▼
Build review payload (diff + context + 7 Concerns + existing findings)
│
▼
Dispatch 4 adversaries in parallel ──► each returns JSON findings
│
▼
Adjudicate: dedupe by agreement, resolve conflicts (read code),
validate vs Linear/plan, controlled-entropy check (±30 lines)
│
▼
Ranked action plan (S0–S5) ──► ONE question: which fixes to apply
│
▼
Apply fixes in parallel → commit → push
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Comprehensive multi-model adversarial + consensus PR review. Invoke with /pr-code-review <PR URL> or when the user asks for "code review on this PR", "review this PR", "adversarial PR review", "multi-model PR review", "consensus review on this PR", or similar. Dispatches 4 adversary models (DeepSeek-v4-pro, Kimi-k3, Qwen3.7-plus, GPT-5.6-sol) for independent findings, then consensus adjudication with full file access for controlled-entropy validation. Claude Opus 5 is used for adjudication when Anthropic is configured; otherwise the orchestrator model adjudicates inline. Reviews against the 7 Engineering Concerns, retrieves Linear + Notion context, ranks findings 0-5 severity (0 = most severe), and produces an action plan.
Comprehensive PR review: 4 adversary models independently surface findings, then consensus adjudication with full file access for controlled-entropy validation. Reviews against LP's 7 Engineering Concerns, is surface-area-aware, context-informed (Linear + Notion), and produces a severity-ranked action plan.
Opus 5 is optional. Adjudication runs inline on the orchestrator model by default. When Anthropic is configured in opencode (see step 2b), the skill can dispatch a real anthropic/claude-opus-5 subagent for adjudication instead. If Anthropic is not configured, the skill degrades gracefully — no errors, no blocking prompts.
Model roster
Diversity of model family is the point — same-family models share blind spots.
The adjudicator runs with file access so it can perform the controlled-entropy check (reading ±30 lines around each proposed fix) — a stateless API call can't do this. By default the orchestrator model does adjudication inline. When Anthropic is configured, step 2b may dispatch a real Opus 5 subagent for stronger adjudication.
If an adversary model is unavailable via litellm, its call errors and is skipped — the review proceeds with the remaining adversaries (minimum 2 for adversarial value; if fewer than 2 succeed, tell the user and stop).
1. Parse input
Argument
Action
GitHub PR URL
Parse owner/repo/number
Bare number
Current repo: gh pr view <num> --json ...
Blank — resolve from current branch/worktree (try in order, stop at first hit):
gh pr view --json number,headRefName,baseRefName,url,title -q . — looks up the PR for the current branch in the current repo's default remote.
If that fails (no PR for the branch, or worktree/remote mismatch), determine the repo from the worktree's remote:
git rev-parse --show-toplevel → git -C <root> remote get-url origin → parse owner/repo.
Then gh pr list --repo OWNER/REPO --head <current-branch> --state open --json number,title,url -q '.[0]'.
If the current branch name looks like a worktree-generated name (e.g. feature/x@2, contains a worktree suffix), strip the suffix and retry with the base branch name.
If still nothing, check git branch --show-current — if on a default branch (main/master/develop), tell the user they're on a default branch and ask them to check out a PR branch or pass a PR URL/number.
Only after all of the above fail: stop and ask the user for a PR URL or number.
Report which method resolved the PR so the user can sanity-check.
gh pr diff <NUM> --repo OWNER/REPO — capture full diff
If diff exceeds ~120K chars, truncate to changed hunks + file headers for the API payload (keep the full diff for local controlled-entropy checks in step 7). Note the truncation.
2a. Ingest existing reviewer comments
From the JSON in step 1, extract all reviewer feedback already on the PR. Group by source:
CodeRabbit — reviewThreads + comments where author login is coderabbitai (or body contains the CodeRabbit signature). Capture each as {file, line, severity-if-tagged, text}.
architecture-reviewer — comments/reviews from github-actions[bot] / the architecture-reviewer workflow, or comments containing architecture-reviewer / architecture-bypass. Capture {file, line, check, text, not-code-fixable?}.
Other bot reviewers (Gemini, Claude, etc.) — capture similarly.
Human reviewers — capture all unresolved review threads and review bodies.
For every captured item, tag its state: unresolved (no reply / thread open) vs addressed (has a reply or the thread is resolved). Drop addressed items — they're done.
The unresolved set is prior context for the adversaries and the adjudicator, not the final word:
Each adversary's prompt includes the unresolved reviewer findings so it can validate, refute, or build on them (an adversary that agrees with a CodeRabbit finding AND finds new evidence → higher confidence; an adversary that refutes it with code evidence → flag as skip-wrong).
The adjudicator (step 7) treats unresolved reviewer findings as input findings to dedupe against the adversaries' findings, with source: coderabbit / architecture-reviewer / etc. noted.
This catches the case where a bot flagged a real issue that the PR author hasn't addressed yet — the adversarial review confirms it and ranks it, rather than re-discovering it from scratch or missing it.
2b. Detect Anthropic configuration (for optional Opus 5 adjudication)
Check whether the Anthropic provider is configured in opencode, so the skill knows whether real Opus 5 adjudication is available:
Read ~/.config/opencode/opencode.json (and ~/.config/opencode/opencode.jsonc if present).
Check if anthropic is in enabled_providers OR if an anthropic/* model is present in provider.anthropic.models OR if a custom agent pinned to anthropic/claude-opus-5 exists under an agent key.
Store the result as opus5_available: true|false.
If opus5_available: false: adjudication (step 7) runs inline on the orchestrator model. Do NOT prompt the user about Opus 5, do NOT block, do NOT warn — the review is fully functional without it. The only place Opus 5 is mentioned is a single line in the final report's reviewer list: Adjudicator: orchestrator (inline).
If opus5_available: true: the skill MAY dispatch a real Opus 5 subagent for adjudication (step 7) per the upgrade path in section 11. Default to inline adjudication unless the user has explicitly opted in (via the custom-agent config in section 11) — inline is more reliable because it guarantees file access without an extra dispatch round-trip.
3. Gather context
3a. Linear story
Search PR body + branch name for a Linear ticket ID (regex [A-Z]+-\d+, e.g. MMC-123).
If found → retrieve via mcp-hub_linear-get-issue with includeRelations: true, includeCustomerNeeds: true. Extract: title, description, acceptance criteria, labels, project, related issues.
If NOT found → do not ask the user. Silently record linear: none and continue. The review proceeds without Linear context; the final report notes "Linear: none" so the user can see it wasn't attached. (The user can paste a ticket ID in a follow-up turn if they want a re-run with context.)
3b. Notion / plan docs
If PR body or Linear story links to a Notion doc → fetch via mcp-hub_notion-notion-fetch.
If user points to a doc → fetch it.
If Notion MCP returns an auth error → tell the user: Connect Notion: https://mcp.luxurypresence.com/oauth/authorize/1e0148abea2044d7a2367f072c964569 and skip. Do not block the review.
3c. Surface area detection
Classify from changed file paths:
Signal in paths
Surface
Extra lens
auggie-platform, dashboard, home-search, websites, SSR
Full-stack web
Read-path optimization, white-label constraints (nothing hardcoded per client)
Multiple surfaces → note all; each applies its lens.
4. Build the review payload
Assemble a single review prompt containing:
PR title, body, labels
Surface area classification
Linear story context (acceptance criteria especially)
Notion / plan doc summary (if retrieved)
The full diff (or truncated hunks for very large PRs)
Unresolved reviewer findings from step 2a (CodeRabbit, architecture-reviewer, Gemini, humans) — framed as: "These issues were already flagged by existing reviewers and are NOT yet addressed. Validate each (confirm/refute with code evidence), and independently surface any NEW issues they missed."
The 7 Engineering Concerns rubric (section 5)
Write this prompt to /tmp/pr-review-prompt.txt using the Write tool.
5. The 7 Engineering Concerns rubric
Embed this verbatim in the review prompt (it goes to every adversary):
Review this diff against these 7 concerns. Each has a one-line test.
1. CORRECTNESS — Is the spec itself right? Do we have the real problem, the third party's actual semantics, or a solution that matches what the code actually does?
2. MAINTAINABILITY & EXTENSIBILITY — Can the next change be made safely and cheaply? (Over half of all review energy goes here: structure, coupling, duplication, boundaries. Is this a script or something meant to be extended?)
3. SECURITY — Can only the right principals do or see this? Have we identified the actors? (Watch for: IDOR — caller reaching someone else's object by supplying its ID; vacuous auth checks that can never fail; unauthenticated endpoints. Security comments are rare but never shallow.)
4. PERFORMANCE — Is the access pattern right for the read/write shape, and does it survive N× load? (The winning argument is arithmetic or a dashboard link, not opinion.)
5. RELIABILITY & FAILURE MODES — What happens when a dependency is slow, down, or half-done? How do error states impact customers?
6. TESTABILITY & VERIFIABILITY — Can this code prove itself correct without a human reading every line?
7. OPERABILITY — Can we run this as a team and with agents? Do we know if something is actually failing and can solve it in minutes?
SURFACE-AREA LENS (apply the matching one(s)):
- WEB: read-path decisions, white-label constraints (nothing hardcoded per client), presentation layer.
- MOBILE: contract changes hit shipped binaries — last quarter's app sends last quarter's query. OTA vs native. Deep-link/push.
- DISTRIBUTED: idempotency (assume at-least-once delivery), backpressure, partial-failure, data-store access patterns.
6. Adversarial review — dispatch models
Each adversary is called via the litellm gateway so it truly runs on its own model family. The helper script is at ~/.claude/skills/pr-code-review/adversary.py.
6a. Verify the helper exists
If ~/.claude/skills/pr-code-review/adversary.py is missing, stop and tell the user the skill installation is incomplete.
6b. Run all 4 adversaries in parallel
python3 ~/.claude/skills/pr-code-review/adversary.py \
"fireworks/models/deepseek-v4-pro" \
"Focus on logic correctness, edge cases, data flow. Trace how data moves through the diff." \
/tmp/pr-review-prompt.txt /tmp/pr-review-deepseek.json &
python3 ~/.claude/skills/pr-code-review/adversary.py \
"fireworks/kimi-k3" \
"Focus on cross-file impact, long-range dependencies. What does this change break downstream?" \
/tmp/pr-review-prompt.txt /tmp/pr-review-kimi.json &
python3 ~/.claude/skills/pr-code-review/adversary.py \
"fireworks/qwen3.7-plus" \
"Focus on maintainability, extensibility, coupling, boundaries. Can the next change be made safely?" \
/tmp/pr-review-prompt.txt /tmp/pr-review-qwen.json &
python3 ~/.claude/skills/pr-code-review/adversary.py \
"gpt-5.6-sol" \
"Focus on security (IDOR, vacuous auth, unauthenticated endpoints) and reliability/failure modes." \
/tmp/pr-review-prompt.txt /tmp/pr-review-gpt.json &wait
Read all 4 result files. Note any that errored — skip them in consensus. If fewer than 2 succeeded, tell the user and stop.
7. Consensus adjudication
Adjudication mode is determined by opus5_available from step 2b:
opus5_available: false (default for users without Anthropic): Adjudicate inline on the orchestrator model. Skip to step 7a. Do not mention Opus 5 anywhere except the single reviewer-list line in section 8.
opus5_available: true AND a pr-review-opus custom agent is configured (section 11): Optionally dispatch the Opus 5 subagent to produce an adjudication pass, then the orchestrator applies the controlled-entropy check (the subagent's reply is reasoning input; the orchestrator still reads the files). If the dispatch fails or times out, fall back to inline silently.
opus5_available: true but no custom agent configured: Adjudicate inline (same as false). The difference is the user could set up the agent later.
7a. Adjudicate (inline, always runs)
Read all adversary findings. As the adjudicator:
Dedupe — same finding from multiple adversaries, OR an adversary finding that matches an existing reviewer comment (CodeRabbit / architecture-reviewer / human) → merge. Note agreement count and sources (e.g. "3/4 adversaries + CodeRabbit" → very high confidence). An existing-reviewer finding that no adversary touched is still kept, but flagged low-confidence unless the adjudicator validates it by reading the code.
Resolve conflicts — if adversaries disagree (one says fix, one says fine), read the actual code at the cited file:line using the Read tool. Decide with evidence. Cite the evidence.
Validate against context — does the PR satisfy the Linear story's acceptance criteria? Does it match the Notion plan/RFC? Flag mismatches as correctness findings (severity 0-1).
Controlled-entropy check (critical) — for each proposed fix, use the Read tool to read the file at the cited line, ±30 lines of context. Verify the fix doesn't ripple. If the fix would require changes elsewhere, note the blast radius and adjust severity up if the fix itself is risky. A fix that creates more entropy than the issue it fixes → downgrade or mark needs-human.
Final severity ranking (0-5, 0 = most severe):
0 — Critical: security hole, data loss, prod-breaking, correctness violation vs spec
1 — High: likely bug, significant failure-mode gap, missing test for critical path
2 — Medium: maintainability/coupling that will hurt the next change, perf concern under load
3 — Low: improvement, minor edge case, testability gap
If the working tree is dirty with unrelated changes, stage only the files touched by the fix agents (git add <file>...) rather than git add -p to avoid sweeping in unreviewed work.
Current approach (no config changes needed, works without Anthropic): Adversaries are called via the litellm gateway (https://litellm.luxurycoders.com/v1) using the API key from ~/.config/opencode/opencode.json. The helper script adversary.py handles this. Adjudication is done inline by the orchestrator (it has file access for controlled-entropy checks). This is the default and requires zero Anthropic configuration.
If gpt-5.6-sol is not available via litellm: the call errors and is skipped — the review proceeds with the other 3 adversaries. The same applies to any unavailable model.
Optional: use the actual Claude Opus 5 model for adjudication. This requires the Anthropic provider to be configured in opencode. The skill detects this in step 2b (opus5_available). If Anthropic is NOT configured, this upgrade path is silently skipped — do not prompt the user or mention Opus 5. If Anthropic IS configured, the user can opt in by adding the pr-review-opus custom agent below.
Upgrade path — custom opencode agents for native multi-model subagents with file access:
This is optional and only fully works when Anthropic is configured. The adversary agents (pr-review-deepseek, pr-review-kimi, pr-review-qwen, pr-review-gpt) work with litellm alone. The pr-review-opus adjudicator requires Anthropic.
Configure custom agents in ~/.config/opencode/opencode.json under an agent key, each pinned to a model:
"agent": {
"pr-review-deepseek": { "model": "litellm/fireworks/models/deepseek-v4-pro", "prompt": "Adversarial PR reviewer focused on logic correctness, edge cases, data flow." },
"pr-review-kimi": { "model": "litellm/fireworks/kimi-k3", "prompt": "Adversarial PR reviewer focused on cross-file impact and long-range dependencies." },
"pr-review-qwen": { "model": "litellm/fireworks/qwen3.7-plus", "prompt": "Adversarial PR reviewer focused on maintainability, extensibility, coupling, boundaries." },
"pr-review-gpt": { "model": "litellm/gpt-5.6-sol", "prompt": "Adversarial PR reviewer focused on security and reliability/failure modes." }
}
Then optionally add the Opus 5 adjudicator only if Anthropic is configured:
When pr-review-opus is present and opus5_available: true, step 7 dispatches it for the adjudication pass (the orchestrator still applies the controlled-entropy file-read check on top of its output). When it's absent or Anthropic isn't configured, step 7 adjudicates inline — no degradation in correctness, only in adjudicator model strength.
Offer to set this up via the customize-opencode skill if the user wants the upgrade — and check enabled_providers for anthropic before proposing the pr-review-opus agent.