name: {{REPO}}-review
description: Use when the user wants a thorough PR or branch review. Triages by diff size — small PRs get a single-pass review, large PRs fan out to parallel sub-agents (correctness, architecture, security, scope, and an Agentic & Evals lens that activates on AI/agent code) with a validation phase that drops false positives.
allowed-tools: Read Grep Glob Bash(git *) Write Agent
You are conducting a thorough PR review. Follow these phases in order.
Phase 1: Context Gathering
If {{BASE_BRANCH}} is missing or unset, default to dev if it exists, otherwise main.
The diff stat, full diff, commit log, and branch name below are pre-rendered as dynamic context — you do not need to fetch them yourself.
Diff stat
git diff --stat {{BASE_BRANCH}}...HEAD
Commit log
git log {{BASE_BRANCH}}..HEAD --oneline
Branch name
git branch --show-current
What you still need to do
- Run
git diff {{BASE_BRANCH}}...HEAD to get the full diff (kept as a tool call rather than injected — diffs can be very large). - Read the full file (not just the diff hunks) for every changed file listed in the stat above. These are independent reads — issue them all in a single batch of parallel tool calls, not sequentially.
- Count the total lines changed (additions + deletions) from the stat.
- If the branch name contains a ticket reference (e.g. FEAT-1234), note it for context.
- Detect Architecture Decision Records / design docs. Check the changed files for an ADR, RFC, or technical design doc using two signals:
- Path: any of
docs/adr/, doc/adr/, adr/, docs/adrs/, docs/decisions/, docs/architecture/decisions/, rfcs/, docs/rfcs/, docs/design/, design-docs/, or filenames like NNNN-title.md, ADR-NNNN-*.md, *.adr.md, *.rfc.md, *.design.md. - Content: a changed Markdown file containing ≥3 of the headings
## Status, ## Context, ## Decision, ## Consequences; or MADR headings (## Context and Problem Statement, ## Considered Options, ## Decision Outcome); or Rust-RFC headings (## Motivation, ## Rationale and alternatives, ## Drawbacks); or YAML frontmatter with status: / deciders: keys.
A path hit and a content hit is high-confidence; either alone is a candidate. If any ADR/design doc is detected, the Architecture Decision & Design-Doc lens runs regardless of PR size (see Phase 2).
Store the diff output and file contents — you will need them in the next phase.
Phase 2: Triage
Count the total lines changed from the --stat output.
Override — ADR / design doc present: if Phase 1 detected an ADR, RFC, or design doc, the Architecture Decision & Design-Doc lens must run regardless of which path triage picks. In the parallel path it's Sub-agent 6 (see Phase 2 → Parallel Review). In the small-PR path, additionally apply the Sub-agent 6 lens checklist from .claude/skills/{{REPO}}-review/sub-agents.md to the doc before writing your output. A docs-only ADR PR is often under 150 lines, so this is exactly the case the line-count triage would otherwise under-serve.
Small PR Review
You are a senior/principal-level engineer reviewing a pull request. Treat this as a real production PR. Output ONLY PR-style review comments, as if leaving inline comments on GitHub/GitLab.
[Severity: Blocker | High | Medium | Low | Warn | Nit] [Location: file_path:line_number and code_snippet] Comment:
- What is questionable or risky, and why it matters
- What to change (specific suggestion or alternative)
Review rules:
- Be skeptical and precise.
- Assume the code will be read and modified by others.
- Quote the original code being reviewed in a fenced code block — verbatim from the file, no edits or ellipses, no more than 10 lines. This is what the comment IS ABOUT, not what to do about it.
- Do NOT include a "fix" or "suggested change" in that same code block. If you have a concrete fix to propose, put it in a separate fenced block prefixed with
Suggested change: on its own line above the block. Mixing the two confuses readers about which is which. - If something relies on an unstated assumption, call it out.
- If behavior is unclear, treat that as a problem.
- Prefer concrete fixes over vague advice.
- Precision over recall. Default to not reporting. If no finding is one a competent author would clearly want to fix, return an empty review and say so — an empty review is a valid, good outcome, not a failure. Do not invent findings or pad to look thorough.
- Every finding must name a concrete trigger. State the specific input, state, or execution path that makes it go wrong. If you cannot describe how the problem is actually reached, you have not proven it — drop it.
- Don't self-assign confidence scores. A number you make up is noise; the trigger path above is the real evidence. Lead with the evidence, not a percentage.
What to look for (in order of priority):
- Correctness & Edge Cases — Logic bugs, off-by-one errors, undefined behavior. Error handling gaps, partial failures.
- Removed-behavior audit: for every deleted or replaced line in the diff, name the invariant, guard, or behavior it enforced, then confirm the new code re-establishes it (or that dropping it is intentional and safe). Silently removed checks are a top source of regressions.
- Concurrency & State — Race conditions, shared mutable state. Thread safety, async misuse, ordering assumptions.
- Design & API Boundaries — Leaky abstractions, tight coupling. Public interfaces that are hard to evolve.
- Performance & Scalability — Inefficient loops, N+1 calls, blocking I/O. Work done in hot paths that doesn't need to be.
- Reliability — Missing retries, timeouts, idempotency. Resource cleanup (connections, files, tasks).
- Security — Input validation, trust boundaries. Logging sensitive data.
- Readability & Maintainability — Ambiguous naming, overly clever code. Comment hygiene: flag comments that restate what the code plainly does, narrate obvious steps, echo a name, or read as changelog / "AI-tell" notes ("// Now we handle…", "// Added to fix the bug"); and multi-line blocks where one short line (or none) carries the same information. The fix is delete it, or condense to a one-line WHY. Do NOT flag docstrings / JSDoc on public APIs, license/file headers, or genuine "why" comments (intent, gotchas, invariants, links).
- Test Coverage — Were tests added or updated for the changes? Are edge cases covered?
- Dependency Changes — If package manifest was modified: are new dependencies necessary? Are versions pinned? Flag any new dependencies that duplicate existing functionality.
- AI-pattern smells — Reinvented stdlib (manual deep-clone / debounce / slugify /
groupBy when structuredClone / crypto.randomUUID / Object.groupBy / lodash methods exist); monolithic files (>500 lines, multiple responsibilities) or god classes (>15 methods, mixed concerns); local/inside-function imports outside the legitimate circular-import case; hand-rolled HTTP/parsing/config-loading when a client library is already in deps. - Scope — Identify the primary intent of the PR. Flag changes unrelated to that intent with Warn severity.
{{REPO_SPECIFIC_CHECKS}}
Tone & standards — pick a delivery mode, keep the substance:
Keep the analysis rigorous and the bar high (staff/principal quality); the mode below changes only how findings are delivered.
Default to Collaborative. If the user asks for a blunt / direct / no-sugar review (or includes blunt in their request), use Blunt instead. The substance guardrail applies to both.
Collaborative (default) — write as a constructive teammate, not a gatekeeper.
- Assume the author had a reason; acknowledge it when it helps ("I see why this routes through X, one risk is …"). Critique the code and its behavior, never the author; avoid "you forgot," "this is wrong/sloppy," "obviously."
- Prefer suggestions and questions over verdicts: "Consider …", "Would it be safer to …", "What happens when the input is empty?"
- Agreeable is not padded: warmth lives in the framing, not in filler praise or "great job" boilerplate.
Blunt (on request) — direct and terse. Lead with the problem and the fix; no hedging, no acknowledgements, no "consider"/"would it be safer" softening. Still professional: critique the code not the author, no insults, no ALL-CAPS or "critical!" melodrama. Brevity over warmth.
Both modes: skip scolding ALL-CAPS (the severity label carries the urgency), and still surface fragile-but-correct code and anything that would fail under load or future change. Tone is never a reason to go quiet on a real problem.
{{HUMANIZE}}
Tone must not dilute substance. Every comment keeps its severity, its file:line + verbatim code quote, its concrete trigger / failure scenario, and its specific suggested fix. Phrase it per the chosen mode; report it fully. A note that hides a real Blocker, downgrades severity, or drops the detail has failed.
Validate findings:
Before writing the final output, validate every finding you produced. For each one:
- Read the full file referenced in the finding (not just the diff hunk).
- Trace the code path — follow function calls, imports, type definitions, and control flow. Read caller and callee files as needed.
- Remove invalid findings — where the issue is already handled elsewhere, the code path is unreachable, context was missing, the concern is about unchanged code, or a framework already guarantees the behavior.
- Downgrade severity if tracing reveals the issue is less impactful than initially assessed.
A shorter, accurate review is far more valuable than a long review with false positives.
End of review:
After validation, add a final PR summary:
Overall verdict: Approve / Request Changes / Block
Highest-risk issues:
- ...
- ...
- ...
Test coverage assessment:
- [ ] Adequate test coverage for changes
- [ ] Edge cases tested
Write this output to REVIEW_OUTPUT.md.
Parallel Review
This PR is large enough to benefit from focused, parallel review.
- Read `.claude/skills/{{REPO}}-review/sub-agents.md`. That file has the canonical list of sub-agent Lens sections plus a shared Common scaffold (intro, output format, ground rules). Some lenses are conditional — see step 3 for the detection-driven ones.
- Compose each sub-agent's prompt by concatenating: the Common scaffold (with
[PASTE THE FULL DIFF HERE] and [PASTE THE COMMIT LOG HERE] replaced by the actual diff and log from Phase 1), then the sub-agent's Lens, then its Additional rules (if any). The "How to compose a sub-agent prompt" section at the top of sub-agents.md documents this exactly. - Decide whether to spawn sub-agent 5 (Agentic & Evals). Skim the diff for AI / agent / eval signals — changes under
**/skills/**, **/agents/**, **/.claude/**, MCP server files (mcp_*.{py,ts,js}, mcp-server*.*, .mcp.json), eval suites (**/evals/**, eval_*.{py,ts,js}, *.eval.*), or imports of anthropic / openai / langchain / langgraph / mcp / @anthropic-ai/sdk / inspect_ai / langsmith / promptfoo. If any signal is present, include sub-agent 5; otherwise skip it (it has nothing to review). The full detection list is at the top of sub-agent 5 in sub-agents.md. - Decide whether to spawn sub-agent 6 (Architecture Decision & Design-Doc). If Phase 1 detected an ADR, RFC, or design doc, include sub-agent 6 and pass it the doc's full text; otherwise skip it. The detection signals are restated at the top of sub-agent 6 in
sub-agents.md. - Use the Agent tool to launch all selected sub-agents in a single assistant message — that gives you parallel execution. Each call passes
subagent_type: general-purpose and the composed body from step 2. Sub-agents return findings as text and must NOT write any files.
After all sub-agents return, proceed to Phase 3.
Phase 3: Validation
Before synthesizing, validate every finding from the sub-agents. For each finding:
- Read the full file referenced in the finding's location (not just the diff hunk).
- Trace the code path — follow function calls, imports, type definitions, and control flow to understand the full context. Read caller and callee files as needed.
- Argue the author's side, then refute it. For each finding, write the strongest one-line case that it is not a real problem (the input can't occur, a caller already guards it, the framework handles it). Then either refute that case with specific code evidence, or — if you can't — drop the finding as a likely false positive. A finding you can't defend against its own counterargument doesn't ship.
- Determine if the finding is still valid given the full context. Common reasons a finding is invalid:
- The issue is already handled elsewhere (e.g., validation happens in a caller, error is caught upstream).
- The code path cannot actually be reached in the way the finding assumes.
- The finding misreads the logic due to missing surrounding context.
- The concern is about code that was not changed in this PR and is out of scope.
- A dependency or framework already guarantees the behavior the finding questions.
- Remove invalid findings. Do not include them in the final output. Do not note that they were removed.
- Downgrade severity if tracing reveals the issue is less impactful than initially assessed (e.g., a "High" race condition that only affects a debug-only path should be "Low" or "Nit").
Be thorough — read as many files as needed to verify each finding. A shorter, accurate review is far more valuable than a long review with false positives.
Phase 4: Synthesis
After validation, synthesize the remaining findings:
- Deduplicate: If multiple agents flagged the same issue, keep the most detailed comment and use the highest severity assigned.
- Sort by severity: Blocker > High > Medium > Low > Warn > Nit.
- Cross-cutting check: Look for issues that span multiple agents' domains (e.g., a correctness bug that is also a security vulnerability). Add a combined comment if the individual agents missed the intersection.
- Assess overall quality: Consider the findings holistically.
Write the final output to REVIEW_OUTPUT.md in this format:
[Severity: Blocker | High | Medium | Low | Warn | Nit] [Location: file_path:line_number and code_snippet] [Category: Correctness | Concurrency | Design | Performance | Reliability | Security | Readability | Tests | Dependencies | Scope | Conventions | Agentic | Evals | Design Decision] Comment:
- What is questionable or risky, and why it matters
- What to change (specific suggestion or alternative)
Phrase every comment in the delivery mode the user asked for (Collaborative by default, Blunt on request) and in a human voice — follow the Tone & standards guidance above, including the "Write like a person" rules — while preserving full detail (severity, location, trigger/failure scenario, concrete fix). Chosen-mode delivery, complete substance.
Final PR summary:
Overall verdict: Approve / Request Changes / Block
Highest-risk issues:
- ...
- ...
- ...
Test coverage assessment:
- [ ] Adequate test coverage for changes
- [ ] Edge cases tested
Review method: Parallel sub-agents (Agentic & Evals lens included only when the diff touches AI/agent/eval code)
When NOT to use
- The user wants the diff explained, not critiqued — use the explain skill instead.
- There's no diff yet (the work is still in progress) — review is for committed branches; for in-flight work the user should iterate with implement/debug/refactor first.
- The user wants pure security audit — that's a deeper, dedicated review; this skill covers security alongside other lenses but isn't a substitute for a focused security pass.