Intent-aware map-reduce PR review with confidence gating and holistic synthesis
Conducts comprehensive PR reviews with intent-aware analysis, cross-file synthesis, and confidence-gated judgments.
/plugin marketplace add rp1-run/rp1/plugin install rp1-run-rp1-dev-plugins-dev@rp1-run/rp1[target] [base-branch] [skip-visual]§ROLE: Map-reduce PR review orchestrator coordinating 4 phases across subagents.
§IN
| Param | Pos | Default | Purpose |
|---|---|---|---|
| TARGET | $1 | current branch | PR#, URL, branch, or empty |
| BASE_BRANCH | $2 | from PR or 'main' | Diff base |
| SKIP_VISUAL | $3 | (none) | skip-visual disables viz |
| RP1_ROOT | env | .rp1/ | Artifact root |
<target>$1</target> <base_branch>$2</base_branch> <skip_visual>$3</skip_visual> <rp1_root>{{RP1_ROOT}}</rp1_root>
§ARCH
P0 (seq): Input Resolution → Intent Model
P0.5 (bg): Visual Gen (conditional, parallel w/ P1)
P1 (seq): Splitter → ReviewUnit[]
P2 (par): N × Sub-Reviewers → Findings + Summaries
P3 (seq): Synthesizer → Cross-File Issues + Judgment
P4 (seq): Reporter → Markdown Report
§PROC
DO NOT ask approval. Execute immediately.
git status --porcelain
If non-empty (dirty state):
AskUserQuestion:
question: "I see uncommitted changes on this branch. How shall we proceed?"
options:
- label: "Stash and continue"
description: "Stash, review, restore"
- label: "Abort"
description: "Cancel to preserve working state"
Handle choice:
git stash push -m "rp1-pr-review-auto-stash" → set STASHED=trueResolve target → branch:
| Input | Detection | Resolution |
|---|---|---|
| Empty | No $1 | git branch --show-current |
| PR# | Numeric | gh pr view {{target}} --json headRefName,baseRefName,title,body |
| PR URL | /pull/ | Extract #, fetch above |
| Branch | Non-numeric | Use directly, check PR exists |
gh pr view {{branch}} --json title,body,headRefName,baseRefName,url 2>/dev/null
2a. Get GitHub repo info (for code links):
gh repo view --json url --jq '.url' 2>/dev/null
Store as GITHUB_URL. If fails, set to empty (links will be omitted in report).
Build Intent Model:
full):
title → problem_statementbody → expected_changes, acceptance_criteriagh issue view {{#}} --json title,bodyAskUserQuestion:
question: "No open PR for this branch. What is the purpose of your current changes?"
options:
- label: "Quick description"
- label: "Skip"
User provides (mode: user_provided): problem_statement = description
Skip (mode: branch_only): problem_statement = "Review changes on {{branch}}"
Add commits: git log {{base}}..{{branch}} --oneline --no-decorate → commit_summaries
Base branch: PR metadata > $2 > 'main'
Intent Model:
{"mode": "full|user_provided|branch_only", "problem_statement": "", "expected_changes": "", "should_not_change": "", "acceptance_criteria": [], "commit_summaries": []}
Get stats:
git diff --stat {{base}}..{{branch}}
git diff --numstat {{base}}..{{branch}}
Detection:
VISUAL_WARRANTED = file_count > 5
OR any file > 200 lines
OR multiple dirs
OR arch files (*.config, schema.*, migrations/*)
Skip if: $3 == "skip-visual" OR trivial (≤3 files, same dir, <100 lines)
If warranted:
Task tool:
subagent_type: rp1-dev:pr-visualizer
run_in_background: true
prompt: "Generate PR visualization.
PR_BRANCH: {{pr_branch}}
BASE_BRANCH: {{base_branch}}
REVIEW_DEPTH: quick"
Store VISUAL_TASK_ID. Continue immediately.
Spawn splitter:
Task tool:
subagent_type: rp1-dev:pr-review-splitter
prompt: "Split PR diff into review units.
PR_BRANCH: {{pr_branch}}
BASE_BRANCH: {{base_branch}}
THRESHOLD: 100
Return JSON with units array."
Parse units array, store total/filtered counts
Fail → Abort: "ERROR: Failed to split PR diff. Check branches/git status."
CRITICAL: Spawn ALL sub-reviewers in SINGLE message w/ multiple Task calls.
For each unit: git diff {{base}}..{{branch}} -- {{unit.path}}
Build file_list from all units
Spawn N sub-reviewers (one msg):
Task tool:
subagent_type: rp1-dev:pr-sub-reviewer
prompt: "Analyze review unit across 5 dimensions.
UNIT_JSON: {{stringify(unit_with_diff)}}
INTENT_JSON: {{stringify(intent_model)}}
PR_FILES: {{stringify(file_list)}}
Return JSON with findings and summary."
Collect: aggregate findings + summaries, track success/fail
<50% fail → continue | ≥50% fail → abort w/ error
Prepare summary:
{"critical": N, "high": N, "medium": N, "low": N, "needs_human_review": N, "details": ["HIGH: unsanitized exec in auth.ts:67"]}
Spawn synthesizer:
Task tool:
subagent_type: rp1-dev:pr-review-synthesizer
prompt: "Perform holistic verification.
INTENT_JSON: {{stringify(intent_model)}}
FILE_LIST: {{stringify(file_list)}}
SUMMARIES_JSON: {{stringify(all_summaries)}}
FINDINGS_SUMMARY: {{stringify(findings_summary)}}
Return JSON with intent_achieved, cross_file_findings, judgment, rationale."
Extract: intent_achieved, intent_gap, cross_file_findings, judgment, rationale
Fail → continue w/ findings-only judgment: Critical→block, High→request_changes, else→approve
Merge findings: unit + cross_file, dedupe by (path, lines, dimension), keep highest severity
Stats: {critical: N, high: N, medium: N, low: N}
Review ID: PR# → pr-{{number}} | else → sanitized branch (/ → -)
If VISUAL_TASK_ID: check completion → VISUAL_PATH or "none"
Get HEAD commit SHA for code links:
git rev-parse {{branch}}
Store as HEAD_SHA.
Spawn reporter:
Task tool:
subagent_type: rp1-dev:pr-review-reporter
prompt: "Generate markdown report.
PR_INFO: {{stringify({branch, title, base, github_url: GITHUB_URL, head_sha: HEAD_SHA})}}
INTENT_JSON: {{stringify(intent_model)}}
JUDGMENT_JSON: {{stringify({judgment, rationale, intent_achieved, intent_gap})}}
FINDINGS_JSON: {{stringify(merged_findings)}}
CROSS_FILE_JSON: {{stringify(cross_file_findings)}}
STATS_JSON: {{stringify(stats)}}
VISUAL_PATH: {{VISUAL_PATH or "none"}}
OUTPUT_DIR: {{RP1_ROOT}}/work/pr-reviews
REVIEW_ID: {{review_id}}
Return JSON with path."
Fail → output findings inline as fallback
If STASHED=true: git stash pop → "Restored stashed changes"
Output:
{{EMOJI}} PR Review Complete
Judgment: {{JUDGMENT}}
{{RATIONALE}}
Findings:
- Critical: {{critical}}
- High: {{high}}
- Medium: {{medium}}
- Low: {{low}}
Report: {{REPORT_PATH}}
{{IF VISUAL_PATH != "none"}}Visual: {{VISUAL_PATH}}{{/IF}}
{{IF STASHED}}Restored stashed changes{{/IF}}
Emoji: approve→✅ | request_changes→⚠️ | block→🛑
§ERR
| Error | Action |
|---|---|
| Dirty git | Prompt stash/abort |
| Unknown branch | Ask user |
| gh unavailable | git-only mode |
| Visual fails | Continue w/o (non-blocking) |
| Splitter fails | Abort w/ error |
| >50% reviewers fail | Abort |
| Synthesizer fails | Findings-only judgment |
| Reporter fails | Inline output |
§OUT CRITICAL - Keep Output Concise: