| name | prp-review-agents |
| description | Multi-agent PR review — spawns parallel specialized agents for deep code review. |
| metadata | {"short-description":"Multi-agent PR review"} |
Agent Mode Detection
If your input context contains [WORKSPACE CONTEXT] (injected by a multi-agents framework),
you are running as a sub-agent. Apply these optimizations:
- Skip Phase 1 context extraction if a
pr-context-*.md file path is provided in
the context files — use it directly (the upstream commit_pr agent already gathered this).
- Skip CLAUDE.md reading — already loaded by parent session.
- Skip PR metadata fetch if PR number and diff are available in context files.
- Skip Validation Phase if context file already contains validation results
(from
/prp-implement or /prp-ralph).
All agent dispatches and result aggregation run unchanged —
these are where quality comes from.
PRP Review Agents — Parallel Multi-Agent PR Code Review
Input
PR number and optional aspects: $ARGUMENTS
Format: <pr-number> [aspects: comments|tests|errors|types|code|security|deps|docs|perf|a11y|simplify|all] [--since-last-review] [--metrics]
Mission
Perform a deep, comprehensive PR code review by spawning specialized Agent subprocesses in parallel. Each agent runs in its own isolated context window with fresh memory, enabling deep file exploration beyond the diff.
This command differs from /prp-review (single-session sequential passes) by spawning actual Agent subprocesses via the Agent tool. Each agent gets:
- Fresh context window — no context pollution from other review aspects
- Deep exploration — agents can Read files outside the diff (.env, scripts, config, related code)
- Specialized focus — each agent type has purpose-built instructions (OWASP for security, error tracing for silent-failure-hunter, etc.)
Report only high-confidence issues (80%+ certain).
Phase 0: Context Detection (Token Optimization)
Before gathering PR information, check if context was pre-generated by /prp-implement or /prp-ralph:
If --context <path> argument provided: Validate the path is under .prp-output/ and does not contain .. segments. Reject absolute paths. Then verify the ## PR Diff section in the file contains actual content (not empty). If empty, WARN and fall through to Phase 1. Otherwise use the context file directly.
If no --context argument, auto-detect:
BRANCH=$(git branch --show-current)
CONTEXT_FILE=".prp-output/reviews/pr-context-${BRANCH}.md"
test -f "$CONTEXT_FILE" && echo "FOUND" || echo "NOT_FOUND"
| Result | Action |
|---|
| FOUND | Read the context file. Use file list, implementation summary, and validation status from it. Skip Phase 1 context extraction. If --since-last-review flag present, still proceed through Phase 0.5. Display: "Token optimization: Using pre-generated context from pr-context-{BRANCH}.md — skipping context extraction." |
| NOT_FOUND | Proceed to Phase 0.5 (if --since-last-review) then Phase 1 to extract context. |
When context file is found, extract from it:
- Files Changed — use directly instead of
gh pr diff --name-only
- Implementation Summary — provide to each agent as background
- Validation Status — skip re-running validation if results are present
- Review Focus Areas — prioritize these in agent prompts
Phase 0.5: Incremental Review Detection
Only when --since-last-review flag is provided. Skip this phase otherwise.
Detect Previous Review
First, resolve the PR number if not already known (from $ARGUMENTS or gh pr view --json number -q '.number').
REVIEW_FILE=$(ls -t .prp-output/reviews/pr-${NUMBER}-agents-review.md 2>/dev/null | head -1)
| Result | Action |
|---|
| Review file found | Extract timestamp from file (look for **Reviewed**: line or file modification time) |
| No review file | WARN: "No previous review found for PR #{NUMBER}. Running full review instead." Proceed to Phase 1. |
Get Changed Files Since Last Review
git log --since="{TIMESTAMP}" --name-only --pretty=format:"" | sort -u
| Result | Action |
|---|
| No changes since timestamp | "No new changes since last review at {TIMESTAMP}. Nothing to re-review." EXIT. |
| Changes found | Display: "Incremental review: {N} files changed since {TIMESTAMP}" |
Incremental Context
When in incremental mode:
- Create context with ONLY changed files' diff:
git diff {BASE}...HEAD -- {changed-files}
- Include unchanged files that import/use changed code (for cross-file context)
- Load previous review findings for merge later
Finding Merge (After Agents Complete)
After incremental review completes, merge with previous review:
- Resolved: Previous issues where file:line region no longer matches in current diff — mark as "Resolved"
- Remaining: Previous issues still present in current code — keep
- New: Issues from current review not in previous — add as "New"
Display delta summary:
Incremental Review Delta:
- New issues: {N}
- Resolved: {M}
- Remaining from previous: {K}
CHECKPOINT: Incremental mode active. Reviewing {N} changed files only.
Phase 1: Context Extraction (Token Optimization)
Purpose: Extract PR context ONCE, share with all agents. Saves 60-70% tokens vs each agent reading diff independently.
Skip this phase if Phase 0 found an existing context file.
1.1 Identify the PR
- If PR number provided:
gh pr view <number>
- If no number:
gh pr view (current branch's PR)
- If
gh pr view fails (no PR for this branch): STOP — "No open PR found for branch {BRANCH}. Create a PR first with gh pr create, or pass a PR number explicitly."
- Get PR branch name and changed files
1.2 Check PR State
| State | Action |
|---|
MERGED | STOP: "PR already merged. Nothing to review." |
CLOSED | WARN: "PR is closed. Review anyway? (historical analysis)" |
DRAFT | NOTE: "Draft PR — focusing on direction, not polish" |
OPEN | PROCEED with review |
- Never push to main without explicit user approval
1.3 Gather Context
Extract all context in ONE pass:
gh pr view {NUMBER} --json number,title,body,author,headRefName,baseRefName,state,additions,deletions,changedFiles
REVIEWED_HEAD_SHA=$(gh pr view {NUMBER} --json headRefOid -q '.headRefOid')
printf '%s' "$REVIEWED_HEAD_SHA" | grep -qE '^[0-9a-f]{40}$' || \
{ echo "FATAL: could not capture reviewed head SHA ('$REVIEWED_HEAD_SHA')" >&2; exit 1; }
if [ -x .prp/scripts/prp-diff.sh ]; then
.prp/scripts/prp-diff.sh {NUMBER}
fi
gh pr diff {NUMBER}
gh pr diff {NUMBER} --name-only
Also read:
CLAUDE.md — project rules and conventions
- Implementation report (if exists):
ls -t .prp-output/reports/*-report*.md 2>/dev/null | head -1
- Related plan (if referenced in implementation report)
1.4 Create Context File
mkdir -p .prp-output/reviews
Context File Path: .prp-output/reviews/pr-context-{BRANCH}.md
---
pr: {NUMBER}
branch: "{BRANCH}"
extracted: {ISO_TIMESTAMP}
files_changed: {N}
---
# PR Review Context: #{NUMBER} — {TITLE}
## PR Metadata
- **Author**: {author}
- **Branch**: {head} → {base}
- **State**: {state}
- **Size**: +{additions}/-{deletions} across {changedFiles} files
## Project Guidelines (from CLAUDE.md)
{relevant sections from CLAUDE.md}
## Changed Files
{list from gh pr diff --name-only}
## PR Diff
{full diff output}
## Implementation Context
{implementation report summary, if found — otherwise "No implementation report found"}
After writing the context file, verify it was created:
test -f "$CONTEXT_FILE" || echo "FATAL: Could not create context file at $CONTEXT_FILE"
If the file was not created, STOP — do not spawn agents without a context file.
CHECKPOINT: Context file created and verified. All agents will read from this file.
Phase 1.5: Large PR Detection
Check PR size after context extraction.
Size Check
Calculate total changes from PR metadata: additions + deletions.
| Size | Action |
|---|
| <=500 lines | Proceed normally — standard review |
| 501-1000 lines | Large PR strategy — phased review by risk tier |
| >1000 lines | Large PR strategy + recommend splitting |
File Risk Categorization
When large PR detected, categorize each changed file:
| Tier | Category | Examples | Review Depth |
|---|
| Tier 1 (Critical) | Security, auth, payment, encryption, permissions | auth/, middleware/, crypto, *.key | Full depth — all applicable agents |
| Tier 2 (Business Logic) | API endpoints, services, business rules, data processing | services/, controllers/, api/, routes/ | Full depth — all applicable agents |
| Tier 3 (Support) | Utils, helpers, shared components, configuration | utils/, helpers/, components/shared/, config/ | Core agents only (code-reviewer, security-reviewer) |
| Tier 4 (Low Risk) | Tests, documentation, config files, generated code | test/, docs/, *.config.*, *.generated.* | Core agents only (code-reviewer) |
Phased Review Strategy
Phase A: Review Tier 1-2 files (critical + business logic)
|- All applicable agents dispatched
|- Full depth analysis
|- Priority findings reported first
Phase B: Review Tier 3-4 files (support + low risk)
|- Core agents only
|- Quick scan for obvious issues
|- Lower priority findings
Coverage Map
Include in review summary:
### File Coverage Map
| File | Tier | Agents Run |
|------|------|------------|
| `src/auth/login.ts` | 1 (Critical) | code, security, errors |
| `src/api/users.ts` | 2 (Business) | code, security, errors |
| `src/utils/format.ts` | 3 (Support) | code, security |
| `tests/auth.test.ts` | 4 (Low Risk) | code |
Split Recommendation
If PR >1000 lines, display:
Large PR detected ({N} lines). Consider splitting into smaller PRs for better review quality.
Suggested splits based on file categories:
- PR 1: {Tier 1-2 files} ({N} lines)
- PR 2: {Tier 3-4 files} ({M} lines)
CHECKPOINT: Large PR strategy applied. Files categorized by risk tier.
Per-File Review Checklist
For EVERY changed file, the relevant agent should check against these 7 categories:
- Correctness: Logic errors, edge cases, error handling
- Type Safety: No implicit
any, return types declared, type guards
- Pattern Compliance: Codebase patterns, naming conventions, imports
- Security: Input validation, secrets exposure, injection vulnerabilities
- Performance: N+1 queries, unnecessary async, memory leaks
- Completeness: Tests for new code, docs updated, TODOs addressed
- Maintainability: Readability, over/under-engineering, magic numbers
Issue Severity Definitions
Agents use different severity systems internally. Map all findings to these unified levels for result aggregation:
| Level | Criteria | Examples | Aggregation Category |
|---|
| Critical | Blocking — must fix, security/data risk | Security vulnerabilities, data loss, crashes | Critical |
| High | Should fix before merge — correctness/safety | Type safety violations, logic errors, silent failures | Important |
| Medium | Should consider — quality/consistency | Pattern inconsistencies, missing edge cases | Suggestions |
| Low | Nice to have — polish | Style preferences, minor optimizations | Suggestions |
Implementation report check: Documented deviations are intentional — only flag undocumented deviations.
Agent Aspect Mapping
| Aspect | Agent (subagent_type) | When to Run |
|---|
code | code-reviewer | Always — general quality and guidelines |
security | security-reviewer | Always — OWASP Top 10, vulnerabilities |
errors | silent-failure-hunter | Always — silent failures, error handling |
deps | dependency-analyzer | When package files changed |
docs | docs-impact-agent | When production code changed (skip for test/config-only) |
tests | pr-test-analyzer | When test files or tested code changed |
comments | comment-analyzer | When comments/docstrings added |
types | type-design-analyzer | When types added/modified |
perf | performance-analyzer | When performance-sensitive patterns detected |
a11y | accessibility-reviewer | When UI/frontend files changed |
simplify | code-simplifier | After all agents pass — polish |
all | All applicable | Default if no aspects specified |
Aspect Selection Logic
Always run (core agents):
code-reviewer — Core quality check
security-reviewer — Security vulnerabilities (OWASP Top 10)
silent-failure-hunter — Silent failures, error path tracing
Run based on changes (conditional agents):
- Package files changed (package.json, lock files, requirements.txt) →
dependency-analyzer
- Production code changed (not test/config-only) →
docs-impact-agent
- Test files changed →
pr-test-analyzer
- Comments/docstrings added →
comment-analyzer
- Types added/modified →
type-design-analyzer
Run when explicitly requested (overrides auto-detection):
- User passes
perf → always run performance-analyzer regardless of file types
- User passes
a11y → always run accessibility-reviewer regardless of file types
Run last (after all other agents complete):
code-simplifier — Final polish
Conditional Agent Dispatch
Auto-detect file types from PR diff and dispatch specialist agents automatically.
File-Type to Agent Mapping
| File Pattern | Agent | Trigger |
|---|
.tsx, .jsx, .vue, .svelte, .css, .scss, .html | accessibility-reviewer | UI/frontend files changed |
.sql, imports from prisma, drizzle, knex, sequelize, typeorm | performance-analyzer | Database patterns detected |
router, endpoint, controller, handler, api/ path | performance-analyzer | API endpoint patterns detected |
for.*await, Promise.all, .map(, setInterval, setTimeout | performance-analyzer | Async/loop patterns detected |
Detection Logic
Scan changed files from PR diff:
If UI files detected (.tsx/.jsx/.vue/.svelte/.css/.scss/.html):
Auto-add: accessibility-reviewer
If performance-sensitive patterns detected:
DB imports (prisma, drizzle, knex, sequelize, typeorm, .sql files)
API patterns (router, endpoint, controller, handler, api/ path)
Async/loop patterns (for.*await, Promise.all, .map(, setInterval)
Auto-add: performance-analyzer
Auto-dispatch Display
When agents are auto-dispatched, display to user:
Auto-dispatching: accessibility-reviewer (3 .tsx files detected)
Auto-dispatching: performance-analyzer (DB query patterns in 2 files)
Note: Conditional dispatch adds to existing agents — it does NOT replace the always-run core agents.
Phase 2: Spawn Parallel Agent Subprocesses
CRITICAL: You MUST use the Agent tool to spawn these as separate subprocesses. Each agent runs in its own context window with fresh memory. Do NOT attempt to run these as sequential passes in this session — that defeats the purpose of this command. If you want single-session sequential passes, use /prp-review instead.
2.1 Prepare Agent Context
Before spawning agents, prepare the shared context information:
CONTEXT_PATH = ".prp-output/reviews/pr-context-{BRANCH}.md"
PR_NUMBER = {extracted from Phase 1}
PROJECT_GUIDELINES = {relevant sections from CLAUDE.md}
CHANGED_FILES = {list from context file}
2.2 Core Agents (Always — Spawn ALL in Parallel)
Spawn these 3 agents simultaneously in a SINGLE message with multiple Agent tool calls:
Agent 1 — Code Quality:
Agent(
subagent_type="code-reviewer",
description="Review PR #{NUMBER} code quality",
prompt="Review PR #{NUMBER} for project guideline compliance, bugs, and quality issues.
Read the PR context file at: {CONTEXT_PATH}
This file contains the PR diff, changed files list, and project guidelines.
IMPORTANT: Also read the actual source files for deep exploration beyond the diff.
Check imports, callers, and related code to understand full impact.
Focus areas:
- Logic errors, off-by-one, null handling, race conditions
- Naming conventions, import organization, dead code
- Pattern compliance with existing codebase
- Per-file checklist: Correctness, Type Safety, Pattern Compliance, Completeness, Maintainability
EXHAUSTIVE PATTERN SWEEP: When you identify a recurring bug class (e.g., missing
type guard, falsy-value blind spot, unguarded interpolation), grep/search ALL
files changed in this PR for ALL instances of that pattern before reporting.
A bug is 'recurring' if you observe 2+ instances of the same structural defect.
List every occurrence — not just the ones you noticed first. This prevents
whack-a-mole re-review cycles where the same pattern is found piecemeal.
Report findings as structured markdown:
## Findings
| Severity | Issue | File:Line | Suggestion |
|----------|-------|-----------|------------|
Use severity levels: Critical, High, Medium, Low
Only report issues with 80%+ confidence.
Also note Strengths — what is done well.
After your Findings table, add a Pattern Sweep Results section:
## Pattern Sweep Results
| Pattern | Files Swept | Instances Found |
|---------|-------------|-----------------|
If sweep performed but 0 additional instances found, still include the row with '0 additional instances'.
If no recurring patterns detected, state: 'No recurring patterns detected — sweeps not performed.'"
)
Agent 2 — Security:
Agent(
subagent_type="security-reviewer",
description="Review PR #{NUMBER} security",
prompt="Review PR #{NUMBER} for security vulnerabilities.
Read the PR context file at: {CONTEXT_PATH}
This file contains the PR diff, changed files list, and project guidelines.
IMPORTANT: Go beyond the diff. Read actual source files:
- Check .env files for exposed secrets
- Read config files for insecure defaults
- Trace authentication flows end-to-end
- Check file permissions and access controls
- Look at related files not in the diff that may be affected
Focus on OWASP Top 10:
- Injection (SQL, NoSQL, OS command, LDAP)
- Broken authentication and session management
- Sensitive data exposure (secrets in logs, responses, error messages)
- SSRF (server-side request forgery via user-controlled URLs)
- Input validation gaps
- Unsafe deserialization
Report ONLY vulnerabilities with clear attack vectors — not theoretical issues.
Report findings as structured markdown:
## Findings
| Severity | Issue | File:Line | Attack Vector | Remediation |
|----------|-------|-----------|---------------|-------------|
Use severity levels: Critical, High, Medium, Low"
)
Agent 3 — Error Handling:
Agent(
subagent_type="silent-failure-hunter",
description="Hunt silent failures PR #{NUMBER}",
prompt="Hunt for silent failures and inadequate error handling in PR #{NUMBER}.
Read the PR context file at: {CONTEXT_PATH}
This file contains the PR diff, changed files list, and project guidelines.
IMPORTANT: Go beyond the diff. Read the actual source files:
- Trace every error path from throw to catch
- Read bash scripts and check exit codes, PIPESTATUS usage
- Verify error propagation — does the error reach the right handler?
- Check what happens when external calls fail (API, DB, filesystem)
- Look for fallback logic that may mask failures
Zero tolerance for:
- Empty catch blocks
- Catch blocks without logging or re-throw
- Generic catch(e) without specific handling
- Async operations without .catch() or try/catch
- Shell scripts without set -e or proper exit code checking
- Functions that return default values on error instead of propagating
EXHAUSTIVE PATTERN SWEEP: When you identify a recurring error-handling anti-pattern
(e.g., silent fallback, swallowed exception, missing exit code check), grep/search
ALL files changed in this PR for ALL instances of that pattern before reporting.
A pattern is 'recurring' if you observe 2+ instances of the same structural defect.
List every occurrence — not just the ones you noticed first. This prevents
whack-a-mole re-review cycles where the same pattern is found piecemeal.
Report findings as structured markdown:
## Findings
| Severity | Issue | File:Line | Error Path | Fix |
|----------|-------|-----------|------------|-----|
Use severity levels: Critical, High, Medium, Low
After your Findings table, add a Pattern Sweep Results section:
## Pattern Sweep Results
| Pattern | Files Swept | Instances Found |
|---------|-------------|-----------------|
If sweep performed but 0 additional instances found, still include the row with '0 additional instances'.
If no recurring patterns detected, state: 'No recurring patterns detected — sweeps not performed.'"
)
2.3 Conditional Agents (Spawn in Parallel — Based on File Analysis)
After determining which conditional agents are needed (from Aspect Selection Logic above), spawn them in a SINGLE message alongside or after the core agents:
If dependency files changed — dependency-analyzer:
Agent(
subagent_type="dependency-analyzer",
description="Analyze dependencies PR #{NUMBER}",
prompt="Analyze dependencies in PR #{NUMBER} for security and health.
Read the PR context file at: {CONTEXT_PATH}
Check for:
- Known CVEs in direct and transitive dependencies
- Outdated packages with available security patches
- Abandoned or deprecated dependencies (no updates >2 years)
- License compliance issues (copyleft in proprietary projects)
- Package.json/lock file consistency
Include exact remediation commands (npm audit fix, version bumps, alternatives).
Report findings as structured markdown:
## Findings
| Severity | Package | Issue | Remediation |
|----------|---------|-------|-------------|
Use severity levels: Critical, High, Medium, Low"
)
If UI/frontend files changed — accessibility-reviewer:
Agent(
subagent_type="accessibility-reviewer",
description="Review accessibility PR #{NUMBER}",
prompt="Review UI code in PR #{NUMBER} for WCAG 2.1 compliance.
Read the PR context file at: {CONTEXT_PATH}
Also read the actual source files for full component context.
Check:
- Keyboard navigation: All interactive elements focusable and operable
- Screen reader support: Proper semantic HTML, meaningful alt text
- Color contrast: 4.5:1 for normal text, 3:1 for large text
- ARIA usage: Correct roles, states, and properties
- Form labels: All inputs have associated labels
- Focus management: Proper focus order, visible focus indicators
Report issues with affected user groups.
Report findings as structured markdown:
## Findings
| Severity | Issue | File:Line | Affected Users | Fix |
|----------|-------|-----------|----------------|-----|
Use severity levels: Critical, High, Medium, Low"
)
If performance-sensitive patterns detected — performance-analyzer:
Agent(
subagent_type="performance-analyzer",
description="Analyze performance PR #{NUMBER}",
prompt="Analyze PR #{NUMBER} for performance issues.
Read the PR context file at: {CONTEXT_PATH}
Also read the actual source files for full context.
Focus on:
- N+1 queries: DB calls inside loops, missing batch/join
- Sequential awaits: await in loops that could be Promise.all
- Memory leaks: Event listeners not cleaned up, growing caches
- Unbounded operations: Missing pagination, unlimited array operations
- Unnecessary re-renders: Missing memoization, inline object creation in render
Report only issues with measurable impact. Include quantified impact estimate.
Confidence threshold 80%+.
Report findings as structured markdown:
## Findings
| Severity | Issue | File:Line | Impact Estimate | Fix |
|----------|-------|-----------|-----------------|-----|
Use severity levels: Critical, High, Medium, Low"
)
If types added/modified — type-design-analyzer:
Agent(
subagent_type="type-design-analyzer",
description="Analyze type design PR #{NUMBER}",
prompt="Analyze type design in PR #{NUMBER}.
Read the PR context file at: {CONTEXT_PATH}
Also read the actual source files for full type context.
Rate on 4 dimensions (1-10 each):
- Encapsulation: Are internals properly hidden?
- Invariant Expression: Do types enforce business rules?
- Usefulness: Do types help consumers avoid mistakes?
- Enforcement: Are types strict enough to catch errors at compile time?
Check for: any escape hatches, overly broad union types, missing discriminants.
Focus on new or modified types only.
Report findings as structured markdown:
## Findings
| Severity | Issue | File:Line | Dimension | Fix |
|----------|-------|-----------|-----------|-----|
## Type Quality Scores
| Type | Encapsulation | Invariant | Usefulness | Enforcement |
|------|---------------|-----------|------------|-------------|
Use severity levels: Critical, High, Medium, Low"
)
If production code changed (not test/config-only) — docs-impact-agent:
Agent(
subagent_type="docs-impact-agent",
description="Review docs impact PR #{NUMBER}",
prompt="Review PR #{NUMBER} and update any documentation affected by code changes.
Read the PR context file at: {CONTEXT_PATH}
Also read CLAUDE.md, README.md, and docs/ directory.
Check:
- Are new features or changed behaviors documented?
- Are removed features still referenced in docs?
- Are API changes reflected in documentation?
- Are configuration changes noted?
If you find stale docs, make the fixes, commit and push to the PR branch.
Display what was updated.
Report findings as structured markdown:
## Findings
| Severity | Issue | File:Line | Fix |
|----------|-------|-----------|-----|
## Documentation Updates Made
| File | Change |
|------|--------|
Use severity levels: Critical, High, Medium, Low"
)
If comments/docstrings added or changed — comment-analyzer:
Agent(
subagent_type="comment-analyzer",
description="Analyze comments PR #{NUMBER}",
prompt="Analyze code comments in PR #{NUMBER} for accuracy, completeness, and long-term value.
Read the PR context file at: {CONTEXT_PATH}
Also read the actual source files to verify comments match code behavior.
Check:
- Do comments accurately describe what the code does?
- Are complex algorithms or business logic explained?
- Are there stale comments that will become wrong when code changes?
- Are JSDoc/TSDoc parameter types and descriptions accurate?
Report findings as structured markdown:
## Findings
| Severity | Issue | File:Line | Fix |
|----------|-------|-----------|-----|
Use severity levels: Critical, High, Medium, Low"
)
If test files or tested code changed — pr-test-analyzer:
Agent(
subagent_type="pr-test-analyzer",
description="Analyze test coverage PR #{NUMBER}",
prompt="Analyze test coverage for PR #{NUMBER}.
Read the PR context file at: {CONTEXT_PATH}
Also read the actual test files and the code they test.
Focus on:
- Behavioral coverage — are critical paths tested?
- Edge cases — are error paths and boundary conditions covered?
- Test quality — meaningful assertions, not just snapshot tests?
- Flaky patterns — timing dependencies, shared state, non-deterministic order?
Rate each recommendation by criticality (1-10): 10 = must-have, 1 = nice-to-have.
Report findings as structured markdown:
## Findings
| Severity | Issue | File:Line | Criticality | Fix |
|----------|-------|-----------|-------------|-----|
Use severity levels: Critical, High, Medium, Low"
)
2.4 Fallback: Sequential Passes
If the Agent tool is NOT available (e.g., running in a tool that doesn't support subagent spawning):
Fall back to /prp-review which performs all 11 review passes sequentially in a single session. Display:
Agent tool not available — falling back to single-session sequential review.
For parallel agent review, use Claude Code or another tool that supports the Agent tool.
Running: /prp-review {NUMBER}
Phase 3: Result Collection
After all agents complete, collect their outputs. Each agent returns a markdown report with findings.
For each agent result:
- Parse the findings table
- Map severity to unified levels (Critical → Critical, High → Important, Medium/Low → Suggestions)
- Extract file:line references
- Note the source agent for each finding
If an agent returns no findings: Note as clean — "No {aspect} issues found."
If an agent fails or times out: Note the failure and proceed with available results. Display:
WARNING: {agent-type} agent failed/timed out. {aspect} review incomplete.
Consider running /prp-review {NUMBER} {aspect} for a single-session {aspect} review.
CRITICAL: If any core agent (code-reviewer, security-reviewer, silent-failure-hunter) fails, the final verdict MUST be at minimum NEEDS FIXES with caveat: "Review incomplete — {agent-type} did not complete. Verdict may be optimistic." A READY TO MERGE verdict is never valid when a core agent is missing.
Phase 4: Result Deduplication
Before categorizing, deduplicate findings across agents.
Dedup Rules
Two findings are considered duplicates when BOTH conditions are met:
- Same file region: Same file AND within +/-5 lines of each other
- Same category: Both about the same concern (e.g., both about error handling, both about security)
NOT duplicates (do not merge):
- Different files, even if description is similar
- Same file region but different categories (e.g., security issue + code quality issue at same line)
Merge Strategy
When duplicates found:
- Keep the most detailed description (longest/most specific)
- Use the highest severity from any contributing agent
- List all contributing agents in the "Agent" column: e.g.,
code-reviewer, silent-failure-hunter
- Combine remediation suggestions if they differ
Example
BEFORE dedup:
| Agent | Issue | Location |
|---|
| code-reviewer | Empty catch block swallows error | api.ts:45 |
| silent-failure-hunter | Catch block has no logging or re-throw | api.ts:47 |
AFTER dedup:
| Agent | Issue | Location |
|---|
| code-reviewer, silent-failure-hunter | Empty catch block swallows error — no logging or re-throw | api.ts:45-47 |
Phase 5: Validation (Run After Agents Complete)
Run automated checks to catch issues that code review alone may miss.
Skip if context file contains concrete validation results (actual PASS/FAIL with counts — not template placeholders like checkmarks without details).
Run Validation Suite
npm run type-check || bun run type-check || npx tsc --noEmit
npm run lint || bun run lint
npm test || bun test
npm run build || bun run build
Capture for each: pass/fail status, error count, warning count, specific failures.
Change-Type Specific Validation
| Change Type | Additional Validation |
|---|
| New API endpoint | Test with curl/httpie |
| Database changes | Check migration exists |
| Config changes | Verify .env.example updated |
| New dependencies | Check package.json/lock file consistency |
Phase 6: Result Aggregation & Verdict
After deduplication, categorize all findings:
Categories
| Category | Description | Action |
|---|
| Critical | Must fix before merge | Block merge |
| Important | Should fix | Address before merge |
| Suggestions | Nice to have | Consider |
| Strengths | What's good | Acknowledge |
Verdict Decision Logic
| Condition | Verdict |
|---|
| No critical/important issues AND all validation passes | READY TO MERGE |
| Important issues OR validation warnings (fixable) | NEEDS FIXES |
| Critical issues OR validation failures | CRITICAL ISSUES |
Note: If validation fails, verdict is at least NEEDS FIXES regardless of agent findings.
Summary Format
## PR Review Summary (Multi-Agent)
### Agents Dispatched
| Agent | Status | Findings |
|-------|--------|----------|
| code-reviewer | Completed | {N} issues |
| security-reviewer | Completed | {N} issues |
| silent-failure-hunter | Completed | {N} issues |
| {conditional agents...} | ... | ... |
### Critical Issues (X found)
| Agent | Issue | Location |
|-------|-------|----------|
| security-reviewer | Description | `file.ts:line` |
### Important Issues (X found)
| Agent | Issue | Location |
|-------|-------|----------|
| silent-failure-hunter | Description | `file.ts:line` |
### Suggestions (X found)
| Agent | Suggestion | Location |
|-------|------------|----------|
| code-reviewer | Description | `file.ts:line` |
### Strengths
- Well-structured error handling
- Good test coverage for critical paths
### Validation Results
| Check | Status | Details |
|-------|--------|---------|
| Type Check | {PASS/FAIL} | {notes} |
| Lint | {PASS/WARN} | {count} warnings |
| Tests | {PASS/FAIL} | {count} passed |
| Build | {PASS/FAIL} | {notes} |
### File Coverage Map
| File | Tier | Agents Run |
|------|------|------------|
| `src/auth/login.ts` | 1 (Critical) | code, security, errors |
### Verdict
[READY TO MERGE / NEEDS FIXES / CRITICAL ISSUES]
### Recommended Actions
1. Fix critical issues first
2. Address important issues
3. Consider suggestions
4. Re-run review after fixes
Note: Agent column may list multiple agents for deduplicated findings (e.g., code-reviewer, silent-failure-hunter).
Output
Report Frontmatter
Include this frontmatter at the top of the review file:
---
pr: {NUMBER}
title: "{TITLE}"
author: "{AUTHOR}"
reviewed: {ISO_TIMESTAMP}
verdict: {READY TO MERGE / NEEDS FIXES / CRITICAL ISSUES}
agents: [{list of agents that ran}]
---
Save Local Review
Save aggregated review to .prp-output/reviews/pr-{NUMBER}-agents-review.md before posting to GitHub.
Note: Uses -agents-review suffix (distinct from -review-claude-code.md used by single-session /prp-review) to prevent overwriting.
mkdir -p .prp-output/reviews
Emit safe-merge review marker (agent-devops#785 gap A)
Append a machine-readable, SHA-bound marker as the last line of the review file, before posting to GitHub. Because the same file is used both as the local artifact and as the --body-file for the GitHub post, the marker lands in both places. This lets safe-merge satisfy its review gate across worktrees / different-cwd repos and for -R cross-repo merges (where it currently skips review entirely).
Trust model (read this): the marker is an integrity/consistency signal for an honest reviewer, NOT an authenticity boundary. A process that can write this file can write a matching body+marker; the marker does not, by itself, prove a review happened. It does not raise the trust level above the pre-existing local-file-presence gate — it only makes that same signal portable across repos and SHA-bound. safe-merge is responsible for re-deriving counts from the body, re-checking the head SHA at merge time, and blocking on any inconsistency. Emit honestly.
Emit for every verdict (READY / NEEDS FIXES / CRITICAL) — safe-merge must see blocks too, and cross-checks the marker against the body.
Strict grammar (safe-merge matches the whole last line, expects exactly one marker, rejects anything off-grammar → fail-closed):
<!-- safe-merge-review: verdict=(READY_TO_MERGE|NEEDS_FIXES|CRITICAL_ISSUES) critical=<int> important=<int> agents=<csv-of [a-z0-9-] tokens, no spaces> head=<40-hex-sha> -->
Field rules:
verdict — map the aggregated verdict: READY TO MERGE→READY_TO_MERGE, NEEDS FIXES→NEEDS_FIXES, CRITICAL ISSUES→CRITICAL_ISSUES. The verdict field is authoritative for block/pass: safe-merge blocks on NEEDS_FIXES/CRITICAL_ISSUES regardless of counts (so a CRITICAL_ISSUES caused by a validation/build failure with zero agent-critical findings — see the Verdict Decision Logic — is legitimately critical=0 and still blocks).
critical / important — MUST equal the integers in the body headings ### Critical Issues (N found) / ### Important Issues (N found). safe-merge recomputes them from the body and BLOCKS on mismatch. Only enforced invariant: READY_TO_MERGE ⟹ critical=0 AND important=0. (No critical>0 requirement for CRITICAL_ISSUES — a blocking verdict already blocks.)
agents — comma-separated [a-z0-9-] tokens, no spaces. Do NOT emit verdict=READY_TO_MERGE unless all three core agents (code-reviewer, security-reviewer, silent-failure-hunter) are present in the aggregation — mirrors the Phase 3 rule "READY TO MERGE is never valid when a core agent is missing." If a core agent is missing, the verdict is at least NEEDS_FIXES.
head — use $MARKER_HEAD derived below (never a fresh gh pr view). Default is $REVIEWED_HEAD_SHA captured in Phase 1.3 at diff-gather time, so a push during review invalidates the marker. The ONLY sanctioned exception is the artifacts-commit re-bind in "Commit artifacts BEFORE the marker" below — a docs-only advance of HEAD by this workflow's own artifact commit, mechanically verified.
Commit artifacts BEFORE the marker (head re-bind, prp-framework#121)
safe-merge matches the GitHub-side marker's head= against the PR HEAD at merge time. Flows that commit review artifacts to the PR branch (run-all, ARTIFACT-REPORT) advance HEAD past $REVIEWED_HEAD_SHA with that very commit — a marker bound to the pre-artifacts SHA is then guaranteed to block, and the tempting escape (--skip-review-check) defeats the gate. Fixed ordering:
- Write the review artifact (verdict + counts final; no marker line yet).
- If this flow commits artifacts to the PR branch →
git add/commit/push them NOW (review file, fix summaries, reports, archived plan).
- Derive the marker head with the docs-only guard:
MARKER_HEAD=""
CURRENT_HEAD=$(git rev-parse HEAD 2>/dev/null)
if ! printf '%s' "$CURRENT_HEAD" | grep -qE '^[0-9a-f]{40}$'; then
echo "FATAL: could not resolve local HEAD ('$CURRENT_HEAD') — marker NOT emitted" >&2
elif ! printf '%s' "$REVIEWED_HEAD_SHA" | grep -qE '^[0-9a-f]{40}$'; then
echo "FATAL: REVIEWED_HEAD_SHA missing/invalid ('$REVIEWED_HEAD_SHA') — marker NOT emitted; re-run Phase 1.3" >&2
elif [ "$CURRENT_HEAD" = "$REVIEWED_HEAD_SHA" ]; then
MARKER_HEAD="$REVIEWED_HEAD_SHA"
else
DIFF_OUTPUT=$(git diff --no-renames "$REVIEWED_HEAD_SHA".."$CURRENT_HEAD" --name-only 2>&1)
DIFF_EC=$?
if [ "$DIFF_EC" -ne 0 ]; then
echo "FATAL: git diff $REVIEWED_HEAD_SHA..$CURRENT_HEAD failed (exit $DIFF_EC) — cannot verify docs-only advance, refusing to re-bind:" >&2
echo "$DIFF_OUTPUT" >&2
else
NON_ARTIFACT=$(printf '%s\n' "$DIFF_OUTPUT" | grep -v '^\.prp-output/' || true)
if [ -z "$NON_ARTIFACT" ]; then
MARKER_HEAD="$CURRENT_HEAD"
else
echo "FATAL: code changed since review ($REVIEWED_HEAD_SHA -> $CURRENT_HEAD):" >&2
echo "$NON_ARTIFACT" >&2
echo "Marker NOT emitted — re-run the review against the new head." >&2
fi
fi
fi
- Emit the marker (below) with
head=$MARKER_HEAD, append to the artifact, then post to GitHub. The local file's marker may lag one docs-only commit behind its own blob — the GitHub-side post (what safe-merge reads for head-matching) carries the current-head binding.
- Flows that never commit artifacts to the branch:
MARKER_HEAD stays $REVIEWED_HEAD_SHA — behavior unchanged.
Do NOT commit again after emitting the marker (that re-invalidates it). If a later fix round changes code, the next review round re-runs this whole sequence.
Extract the counts mechanically from the file you just wrote (don't retype from memory — that drifts, and a drift makes safe-merge block):
REVIEW_FILE=".prp-output/reviews/pr-{NUMBER}-agents-review.md"
CRIT=$(grep -oiP '###\s+Critical Issues\s+\(\K\d+' "$REVIEW_FILE" | head -1); CRIT="${CRIT:-0}"
IMP=$(grep -oiP '###\s+Important Issues\s+\(\K\d+' "$REVIEW_FILE" | head -1); IMP="${IMP:-0}"
AGENTS_CSV=$(printf '%s' "$AGENTS_CSV" | tr 'A-Z' 'a-z' | tr -cd 'a-z0-9,-')
case "$VERDICT_TOKEN" in
READY_TO_MERGE|NEEDS_FIXES|CRITICAL_ISSUES) ;;
*) echo "FATAL: bad VERDICT_TOKEN ('$VERDICT_TOKEN') — marker NOT emitted" >&2; VERDICT_TOKEN="" ;;
esac
if ! printf '%s' "$MARKER_HEAD" | grep -qE '^[0-9a-f]{40}$'; then
echo "FATAL: MARKER_HEAD missing/invalid ('$MARKER_HEAD') — marker NOT emitted; re-run Phase 1.3 / the re-bind block" >&2
elif [[ -z "$VERDICT_TOKEN" ]]; then
:
else
printf '\n<!-- safe-merge-review: verdict=%s critical=%s important=%s agents=%s head=%s -->\n' \
"$VERDICT_TOKEN" "$CRIT" "$IMP" "$AGENTS_CSV" "$MARKER_HEAD" \
>> "$REVIEW_FILE"
fi
Post to GitHub
Self-review detection: Before posting a formal review, check if the current GitHub user is the PR author:
PR_AUTHOR=$(gh pr view {NUMBER} --json author --jq '.author.login')
CURRENT_USER=$(gh api user --jq '.login')
If PR_AUTHOR == CURRENT_USER: skip gh pr review (GitHub blocks self-approval) and fall back to gh pr comment directly. This is expected in single-user repos where all agents share the same GitHub identity.
| Condition | Action |
|---|
| READY TO MERGE | gh pr review {NUMBER} --approve --body-file .prp-output/reviews/pr-{NUMBER}-agents-review.md |
| NEEDS FIXES or CRITICAL ISSUES | gh pr review {NUMBER} --request-changes --body-file .prp-output/reviews/pr-{NUMBER}-agents-review.md |
| Draft PR | gh pr comment {NUMBER} --body-file .prp-output/reviews/pr-{NUMBER}-agents-review.md (comment only — no formal review on drafts) |
If gh pr review fails (e.g., permission denied, fork PR restrictions):
- Log the actual error message from
gh
- Display: "WARNING: Could not post formal review (error: {message}). Falling back to PR comment — formal approve/request-changes not applied."
- Fall back to:
gh pr comment {NUMBER} --body-file .prp-output/reviews/pr-{NUMBER}-agents-review.md
Review Metrics Collection
Append Metrics After Every Review
After publishing to GitHub, append one JSONL line to .prp-output/reviews/review-metrics.jsonl:
{"timestamp":"2026-03-14T10:30:00Z","pr_number":163,"branch":"feature/auth","review_type":"agents","verdict":"NEEDS_FIXES","total_issues":5,"critical":1,"important":2,"suggestions":2,"agents_run":["code-reviewer","security-reviewer","silent-failure-hunter"],"conditional_agents":["accessibility-reviewer"],"incremental":false,"large_pr":false,"lines_changed":342,"files_changed":8}
Fields:
timestamp — ISO 8601 review completion time
pr_number — PR number reviewed
branch — Branch name
review_type — Always "agents" for this command (distinguishes from single-session "single")
verdict — READY_TO_MERGE / NEEDS_FIXES / CRITICAL_ISSUES
total_issues — Total findings count
critical, important, suggestions — Counts by severity
agents_run — List of all agents that ran
conditional_agents — List of agents added by conditional dispatch
incremental — Whether --since-last-review was used
large_pr — Whether large PR strategy was applied
lines_changed, files_changed — PR size metrics
mkdir -p .prp-output/reviews
echo '{...}' >> .prp-output/reviews/review-metrics.jsonl || echo "WARNING: Failed to append review metrics. Review results are saved, but metrics tracking is incomplete."
--metrics Flag: Aggregate Summary
When --metrics flag provided (without PR number), display aggregate summary and EXIT:
cat .prp-output/reviews/review-metrics.jsonl
Display:
## Review Metrics Summary
**Total Reviews**: {N}
**Period**: {earliest timestamp} — {latest timestamp}
### Verdicts
| Verdict | Count | % |
|---------|-------|---|
| READY TO MERGE | {N} | {%} |
| NEEDS FIXES | {N} | {%} |
| CRITICAL ISSUES | {N} | {%} |
### Issues by Severity
| Severity | Total | Avg per Review |
|----------|-------|---------------|
| Critical | {N} | {avg} |
| Important | {N} | {avg} |
| Suggestions | {N} | {avg} |
### Agent Contribution
| Agent | Times Run | Issues Found |
|-------|-----------|-------------|
| code-reviewer | {N} | {total} |
| security-reviewer | {N} | {total} |
| silent-failure-hunter | {N} | {total} |
| ... | ... | ... |
### Review Type Breakdown
| Type | Count | Avg Issues |
|------|-------|------------|
| agents (parallel) | {N} | {avg} |
| single (sequential) | {N} | {avg} |
If no metrics file exists: "No review metrics found. Metrics will be collected after your first review."
Update Implementation Report
After posting to GitHub, update the implementation report to close the feedback loop.
Find Implementation Report
BRANCH=$(gh pr view <PR_NUMBER> --json headRefName -q '.headRefName')
ls -t .prp-output/reports/*-report*.md 2>/dev/null | head -1
Append Review Outcome
If implementation report exists, append the following section to the end of the report:
---
## Review Outcome (Agents)
**Reviewed**: {ISO_TIMESTAMP}
**PR**: #{NUMBER}
**Verdict**: {READY TO MERGE / NEEDS FIXES / CRITICAL ISSUES}
**Review File**: `.prp-output/reviews/pr-{NUMBER}-agents-review.md`
**Agents Run**: {list}
| Category | Count |
|----------|-------|
| Critical | {N} |
| Important | {N} |
| Suggestions | {N} |
{If NEEDS FIXES or CRITICAL ISSUES: list of top issues to address}
If no implementation report found: Note in review output: "Implementation report not found — skipped update." (PR may not have been created via PRP workflow.)
Update PRD (if applicable)
If implementation report references a Source PRD:
| Verdict | PRD Update |
|---|
| READY TO MERGE | Change phase status from complete to reviewed |
| NEEDS FIXES | Add note: "Review: {N} issues to address" |
| CRITICAL ISSUES | Add note: "Blocked: {brief reason}" |
Usage Examples
/prp-review-agents 163 # Full multi-agent review
/prp-review-agents 163 security errors # Only security + error handling agents
/prp-review-agents # Current branch's PR
/prp-review-agents 42 code docs # Only code and docs agents
/prp-review-agents 42 perf a11y # Performance + accessibility agents
/prp-review-agents 163 --since-last-review # Incremental re-review
/prp-review-agents --metrics # View review metrics
Edge Cases
| Situation | Action |
|---|
| PR has 500+ changed files | Apply Large PR Strategy (Phase 1.5) — tier-based review |
gh pr diff returns empty | STOP — "No changes to review. Verify the branch is pushed and the correct base branch is set. Run gh pr diff {NUMBER} manually to diagnose." |
| No PR found for current branch | STOP — "No open PR found for branch. Create a PR first with gh pr create, or pass a PR number explicitly." |
--context path with empty diff | WARN and fall through to Phase 1 for fresh context extraction |
| No CLAUDE.md or conventions file | Proceed — rely on codebase patterns from diff |
| PR is a revert commit | Focus on: was the revert correct? Any side effects? |
| PR modifies only generated files | Skip most agents, note "generated code" in review |
| Review artifact already exists | Overwrite with new review (timestamp in frontmatter tracks versions) |
--metrics with no metrics file | Display "No review metrics found" and EXIT |
--metrics with PR number | Display metrics first, then proceed with review |
| Agent tool not available | Fall back to /prp-review (single-session sequential) |
| Agent times out or fails | Note failure, proceed with available results; if core agent failed, force verdict to NEEDS FIXES minimum |
Critical Reminders
- Spawn agents, don't simulate. Use the Agent tool with subagent_type. Do NOT run passes sequentially in this session.
- Understand before judging. Agents must read full context, not just the diff.
- Be specific. Include file:line references and concrete fix suggestions.
- Prioritize. Use severity levels honestly — not everything is critical.
- Be constructive. Offer solutions, not just problems.
- Acknowledge good work. If something is done well, say so.
- Run validation. Don't skip automated checks.
- Check patterns. Read existing similar code to understand expectations.
- Think about edge cases. What happens with null, empty, very large, concurrent?
- Check implementation report. Documented deviations are intentional, not issues.
Success Criteria
- AGENTS_SPAWNED: Core agents (code-reviewer, security-reviewer, silent-failure-hunter) spawned via Agent tool
- PARALLEL_EXECUTION: Core agents launched in a single message (parallel, not sequential)
- CONTEXT_SHARED: All agents read from shared pr-context-{BRANCH}.md file
- DEEP_EXPLORATION: Agents read actual source files beyond the diff
- CONDITIONAL_DISPATCHED: Specialist agents triggered by file types (accessibility, performance, deps, types)
- RESULTS_COLLECTED: All agent outputs collected and parsed
- ISSUES_DEDUPLICATED: Duplicate findings merged across agents
- ISSUES_CATEGORIZED: Findings organized by unified severity levels
- PR_UPDATED: Formal review posted to GitHub (approve/request-changes)
- METRICS_COLLECTED: Review metrics appended to JSONL with review_type="agents"
- RECOMMENDATION_CLEAR: Verdict with rationale
- FALLBACK_AVAILABLE: Graceful fallback to /prp-review when Agent tool unavailable