From rp1-dev
Orchestrates map-reduce PR reviews: splits changes into units, parallel sub-reviews, synthesizes findings, posts deduplicated comments. Supports CI/CD, visual diffs, confidence gating.
npx claudepluginhub rp1-run/rp1This skill is limited to using the following tools:
§ROLE: Map-reduce PR review orchestrator. 6 phases, local + CI modes, comment deduplication.
Orchestrates map-reduce PR reviews: splits changes into units, runs sub-reviews, synthesizes cross-file findings with confidence gating, deduplicates comments, supports CI/CD GitHub posting.
Conducts deep PR reviews using 6-7 parallel specialized agents for code quality, security, testing, frontend/backend architecture. Use for thorough pull request analysis before merging.
Reviews GitHub pull requests end-to-end using gh CLI: analyzes diffs, commits, CI/CD checks; provides blocking/suggestion/nit/praise feedback and submits review. Use for assigned PRs, self-reviews, or post-merge audits.
Share bugs, ideas, or general feedback.
§ROLE: Map-reduce PR review orchestrator. 6 phases, local + CI modes, comment deduplication.
Extract these parameters from the user's input:
| Parameter | Required | Default | Description |
|---|---|---|---|
TARGET | No | current branch | PR number, PR URL, branch name, or empty for current branch |
BASE_BRANCH | No | from PR or main | Diff base branch |
SKIP_VISUAL | No | false | Set true if user says "skip-visual" or "no visual" |
Environment values (resolve via shell):
RP1_ROOT: !rp1 agent-tools rp1-root-dir (extract data.root from JSON response)stateDiagram-v2
[*] --> split
split --> review : split_complete
review --> synthesize : review_complete
synthesize --> post : synthesis_complete
post --> [*] : done
On each phase transition, report via:
rp1 agent-tools work update \
--project "$(pwd)" \
--feature {FEATURE_ID} \
--workflow pr-review \
--run-id {RUN_ID} \
--step {CURRENT_STATE} \
--status started
RUN_ID as a UUID at workflow start; derive FEATURE_ID from the PR branch or numberState Progression Protocol:
--step with --status started when you enter that state→ [*] transitions): report --status completed when the step's work finishesExample sequence:
--step split --status started # entering split phase
--step review --status started # split done, entering review phase
--step synthesize --status started # review done, entering synthesize phase
--step post --status started # synthesize done, entering post phase
--step post --status completed # post done, workflow complete
§ARCH
P-1 (seq): Config Load -> CI Detection -> Early Exit Check
P0 (seq): Input Resolution -> Intent Model
P0.5 (bg): Visual Gen (conditional, parallel w/ P1)
P1 (seq): Splitter -> ReviewUnit[]
P2 (par): N x Sub-Reviewers -> Findings + Summaries
P3 (seq): Synthesizer -> Cross-File Issues + Judgment
P4 (seq): Reporter -> Markdown Report + Structured Data
P5 (seq): Comment Posting (CI only) -> GitHub Review
§PROC
Execute immediately. No approval prompts.
Load config: Read .rp1/config/pr-review.yaml if exists:
enabled: boolean # default: false
review_drafts: boolean # default: true
ai_harness: string # "claude-code" | "opencode", default: "claude-code"
add_comments: boolean # default: true
collapse_summary: boolean # default: false
verdict: string # "approve" | "request_changes" | "comment" | "auto", default: "auto"
max_comments: integer # default: 25
bot_marker: string # default: "<!-- rp1-review -->"
visualize: boolean # default: false
ci_platform: string # "github" | "buildkite" | "gitlab", default: "github"
Missing file -> use defaults.
Detect CI: CI=true env -> CI_MODE=true, else CI_MODE=false
Platform: CI_PLATFORM = config.ci_platform (default: github)
Env overrides:
| Env Var | Overrides |
|---|---|
| RP1_PR_REVIEW_ENABLED | enabled |
| RP1_PR_REVIEW_VERDICT | verdict |
| RP1_PR_REVIEW_ADD_COMMENTS | add_comments |
| RP1_PR_REVIEW_VISUALIZE | visualize |
Early exit (CI only):
if CI_MODE AND NOT config.enabled -> Output config instructions, EXIT
Build CI_CONTEXT (GitHub only):
GITHUB_EVENT_PATH -> pr_number, action, is_draftGITHUB_REPOSITORY -> owner, repoGITHUB_TOKEN, GITHUB_HEAD_REF, GITHUB_BASE_REFStore: {"pr_number": N, "owner": "...", "repo": "...", "token": "...", "head_ref": "...", "base_ref": "...", "is_draft": false}
Draft check (CI only):
if CI_MODE AND CI_CONTEXT.is_draft AND NOT config.review_drafts -> Skip, EXIT
Skip if CI_MODE=true.
git status --porcelaingit stash push -m "rp1-pr-review-auto-stash", set STASHED=true
Abort: Exit "Review cancelled."pr_branch, base_branch (BASE_BRANCH if provided), pr_numbergh pr view {{pr_number}} --json title,body,url 2>/dev/nullproblem_statement, body -> expected_changes, acceptance_criteria
Parse fails -> mode="ci_minimal", problem_statement="Review PR #{{pr_number}}"Resolve target:
| Input | Detection | Resolution |
|---|---|---|
| Empty | No TARGET | 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 |
gh pr view {{branch}} --json title,body,headRefName,baseRefName,url 2>/dev/null
2a. Get repo URL: gh repo view --json url --jq '.url' 2>/dev/null -> GITHUB_URL (empty if fails)
Build Intent Model:
full): title -> problem_statement, parse body, fetch linked issuesuser_provided): use descriptionbranch_only): problem_statement="Review changes on {{branch}}"Add: git log {{base}}..{{branch}} --oneline --no-decorate -> commit_summaries
Base: PR metadata > BASE_BRANCH > 'main'
Intent Model: {"mode": "...", "problem_statement": "", "expected_changes": "", "should_not_change": "", "acceptance_criteria": [], "commit_summaries": []}
Skip conditions:
NOT config.visualizeDetect (local):
git diff --stat {{base}}..{{branch}}
git diff --numstat {{base}}..{{branch}}
VISUAL_WARRANTED = file_count > 5 OR any file > 200 lines OR multiple dirs OR arch files
Spawn (if warranted):
OUTPUT_MODE = CI_MODE ? "markdown" : "html"
Background mode: local=true, CI=false
{% dispatch_agent "rp1-dev:pr-visualizer" %} Generate PR visualization. PR_BRANCH: {{pr_branch}} BASE_BRANCH: {{base_branch}} REVIEW_DEPTH: quick OUTPUT_MODE: {{OUTPUT_MODE}} {% enddispatch_agent %}
CI: capture VISUAL_CONTENT | Local: store VISUAL_TASK_ID, continue
{% dispatch_agent "rp1-dev:pr-review-splitter" %} Split PR diff into review units. PR_BRANCH: {{pr_branch}} BASE_BRANCH: {{base_branch}} THRESHOLD: 100 Return JSON with units array. {% enddispatch_agent %}
Parse units, store counts. Fail -> Abort w/ error.
CRITICAL: Spawn ALL sub-reviewers in SINGLE message.
For each unit: git diff {{base}}..{{branch}} -- {{unit.path}}
Build file_list
Spawn N sub-reviewers (one msg):
{% dispatch_agent "rp1-dev:pr-sub-reviewer" %} 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. {% enddispatch_agent %}
Aggregate findings + summaries
<50% fail -> continue | >=50% fail -> abort
Prep summary: {"critical": N, "high": N, "medium": N, "low": N, "needs_human_review": N, "details": [...]}
Spawn:
{% dispatch_agent "rp1-dev:pr-review-synthesizer" %} 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. {% enddispatch_agent %}
Extract: intent_achieved, intent_gap, cross_file_findings, judgment, rationale
Fail -> 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"
git rev-parse {{branch}} -> HEAD_SHA
Spawn:
{% dispatch_agent "rp1-dev:pr-review-reporter" %} Generate markdown report. PR_INFO: {% raw %}{{stringify({branch, title, base, github_url: GITHUB_URL, head_sha: HEAD_SHA})}}{% endraw %} INTENT_JSON: {{stringify(intent_model)}} JUDGMENT_JSON: {% raw %}{{stringify({judgment, rationale, intent_achieved, intent_gap})}}{% endraw %} 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. {% enddispatch_agent %}
Fail -> output findings inline
Store REPORTER_FINDINGS for P5 (CI mode)
Skip if CI_MODE=false.
Fetch existing:
echo '{"owner":"{{CI_CONTEXT.owner}}","repo":"{{CI_CONTEXT.repo}}","pr_number":{{CI_CONTEXT.pr_number}}}' | \
rp1 agent-tools github-pr fetch-comments
Parse -> existing_bot_comments, existing_human_comments
Transform findings to deduplicator fmt:
[{"id": "f1", "path": "...", "line": N, "line_end": N, "body": "...", "severity": "...", "dimension": "..."}]
Deduplicate:
{% dispatch_agent "rp1-dev:pr-comment-deduplicator" %} Deduplicate PR comments. NEW_COMMENTS: {{stringify(new_comments)}} EXISTING_BOT_COMMENTS: {{stringify(existing_bot_comments)}} EXISTING_HUMAN_COMMENTS: {{stringify(existing_human_comments)}} BOT_MARKER: {{config.bot_marker}} Return JSON with to_post, to_react, to_augment, duplicates_skipped. {% enddispatch_agent %}
Post:
{% dispatch_agent "rp1-dev:pr-comment-poster" %} Post PR review to GitHub. OWNER: {{CI_CONTEXT.owner}} REPO: {{CI_CONTEXT.repo}} PR_NUMBER: {{CI_CONTEXT.pr_number}} DEDUP_OUTPUT: {{stringify(dedup_output)}} CONFIG: {% raw %}{{stringify({verdict: config.verdict, bot_marker: config.bot_marker, max_comments: config.max_comments, add_comments: config.add_comments})}}{% endraw %} VISUAL_CONTENT: {{VISUAL_CONTENT or ""}} FINDINGS_SUMMARY: {% raw %}{{stringify({critical: N, high: N, medium: N, low: N, total: N})}}{% endraw %} Return JSON with success, review, reactions, replies, summary, errors. {% enddispatch_agent %}
Parse: REVIEW_URL, COMMENTS_POSTED, REACTIONS_ADDED, POSTING_ERRORS
If STASHED=true: git stash pop
CI Mode:
{{EMOJI}} PR Review Complete (CI Mode)
Judgment: {{JUDGMENT}}
{{RATIONALE}}
Findings: Critical={{critical}}, High={{high}}, Medium={{medium}}, Low={{low}}
GitHub Review: {{REVIEW_URL}}
Comments Posted: {{COMMENTS_POSTED}}
Duplicates Skipped: {{dedup_output.duplicates_skipped}}
Reactions Added: {{REACTIONS_ADDED}}
{{IF POSTING_ERRORS}}Errors: {{POSTING_ERRORS}}{{/IF}}
Local Report: {{REPORT_PATH}}
Local Mode:
{{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->check, request_changes->warning, block->stop
§ERR
| Error | Action |
|---|---|
| CI not enabled | Exit w/ config instructions |
| Draft PR skipped | Exit w/ message |
| Dirty git (local) | Prompt stash/abort |
| Unknown branch | Ask user (local) or fail (CI) |
| 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 |
| fetch-comments fails | Skip P5, warn |
| Deduplicator fails | Post all (no dedup) |
| Poster fails | Output error, report still generated |
§OUT
<thinking> tags