| name | pr-bot |
| description | Use when: PR review loop with cloud bot, arbitration, and merge |
| allowed-tools | Bash, Read, Grep, Glob, Edit, Write |
| triggers | ["pr-bot","/pr-bot","cloud bot review","PR bot","PR review bot","merge PR"] |
PR Bot: Two-Layer PR Review and Merge (Configurable Cloud Bot)
Role Detection (READ THIS FIRST -- MANDATORY)
Check your initial prompt. If it contains the literal string "Use the pr-bot skill", then:
YOU ARE THE EXECUTOR. Follow these rules:
- SKIP the "Execution Protocol" section below -- it is for the orchestrator, not you.
- Read the pattern at
../../PATTERN.md relative to this SKILL.md, and follow it step by step.
- ABSOLUTE PROHIBITION: Do NOT run
csa run, csa review, csa debate, or ANY csa command. You must perform the work DIRECTLY. Running any csa command causes infinite recursion.
Only if you are the main agent (Claude Code / human user):
- You are the orchestrator. Follow the "Execution Protocol" steps below.
Purpose
Orchestrate the full PR review-and-merge lifecycle with two-layer review: local pre-PR cumulative audit (covering ${DEFAULT_BRANCH}...HEAD) plus configurable cloud bot review (default: gemini-code-assist; configurable via pr_review.cloud_bot_name). When bot times out, the workflow aborts (no silent fallback merge). The one explicit exception is a detected quota-exhaustion warning, which is cached and routed through the merge-without-bot audit path. Performs false-positive arbitration via adversarial debate, and manages fix-push-retrigger loops with user-prompted round limits (MAX_REVIEW_ROUNDS, default 10). Non-target bot comments (e.g., codex auto-review) are also detected and processed with a quota warning. Merges with --merge to preserve per-commit audit trail.
MANDATORY AUDIT TRAIL: When an agent determines a PR-page review finding
(for example, a cloud bot finding) is NOT a real issue or is acceptable in
context (e.g., pre-production breaking change), the agent MUST post an
explanatory comment on the PR page BEFORE merging or proceeding. This creates a
permanent record of the rationale behind every dismissed PR-page finding.
Local pre-PR review findings must be fixed before PR creation; they do not use
the PR-page audit trail because no PR page exists yet. FORBIDDEN: merging with
dismissed PR-page findings without explanatory PR comments.
FORBIDDEN: self-dismissing bot comments, skipping debate for arbitration, auto-merging at round limit, proceeding when bot responds with environment/configuration setup message instead of an actual code review (MUST stop and ask user to configure).
Dispatcher Model
pr-bot follows a 3-layer dispatcher architecture. The main agent never
performs implementation work directly -- it orchestrates sub-agents that do the
actual review, fixing, and merging.
Layer 0 -- Orchestrator (Main Agent)
The main agent (Claude Code / human user) acts as a pure dispatcher:
- Reads SKILL.md and PATTERN.md to understand the workflow
- Dispatches each step to the appropriate sub-agent or tool
- Evaluates sub-agent results and decides next action (fix, retry, merge, abort)
- NEVER reads or writes code directly -- all code-touching work is delegated
- NEVER runs
csa review / csa debate itself -- spawns a Layer 1 executor
Layer 1 -- Executor Sub-Agents (CSA / Task Tool)
Layer 1 agents perform the actual work dispatched by Layer 0:
| Step | Layer 1 Agent | Work Performed |
|---|
| Step 2 | csa review --branch ${DEFAULT_BRANCH} | Cumulative local review |
| Step 3 | csa (executor) | Fix local review issues |
| Step 7 | claude-code (Task tool) | Classify bot comments |
| Step 8 | csa debate | False-positive arbitration |
| Step 9 | csa (executor) | Fix real issues |
Layer 1 agents have full file system access and can read/write code, run tests,
and interact with git. They receive a scoped task from Layer 0 and return
results.
Layer 2 -- Sub-Sub-Agents (Spawned by Layer 1)
Layer 1 agents may spawn their own sub-agents for specific sub-tasks:
csa review internally spawns reviewer model(s) for independent analysis
csa debate spawns two independent models for adversarial evaluation
- Task tool sub-agents may use Grep/Glob for targeted code search
Layer 2 agents are invisible to Layer 0 -- the orchestrator only sees Layer 1
results.
Flow Diagram
Layer 0 (Orchestrator)
|
+-- dispatch --> Layer 1: csa review --branch ${DEFAULT_BRANCH}
| |
| +-- spawn --> Layer 2: reviewer model(s)
|
+-- evaluate result, decide next step
|
+-- dispatch --> Layer 1: csa (fix issues)
|
+-- dispatch --> Layer 1: bash (push, create PR, trigger bot)
|
+-- dispatch --> Layer 1: claude-code (classify comments)
|
+-- dispatch --> Layer 1: csa debate (arbitrate false positives)
| |
| +-- spawn --> Layer 2: independent models
|
+-- dispatch --> Layer 1: bash (merge)
Execution Protocol (ORCHESTRATOR ONLY)
Prerequisites
- All changes must be committed on a feature branch
- Feature branch must be ahead of the default branch
- FORBIDDEN: Pushing the feature branch to remote BEFORE invoking this skill.
Step 2 (local review) MUST complete before any push. If you push first,
unreviewed code reaches the remote and CI/reviewers may act on it prematurely.
The skill's Step 4 handles push after review passes.
Configuration
The cloud bot is configurable per-project/global via .csa/config.toml:
[pr_review]
cloud_bot = true
cloud_bot_name = "gemini-code-assist"
cloud_bot_trigger = "auto"
cloud_bot_login = ""
cloud_bot_retrigger_command = ""
cloud_bot_wait_seconds = 60
cloud_bot_poll_interval_seconds = 30
cloud_bot_poll_max_seconds = 600
merge_strategy = "merge"
delete_branch = false
Check at runtime: csa config get pr_review.cloud_bot_name --default gemini-code-assist
Trigger modes:
"auto" (default): Bot auto-reviews on PR creation push. No @mention needed.
"comment": Posts @{cloud_bot_name} review comment to trigger review.
Retrigger (round 2+ after fix push): Bots like gemini-code-assist do NOT
auto-review on subsequent pushes — only on PR creation. The workflow ALWAYS posts
an explicit retrigger command on round 2+, regardless of cloud_bot_trigger.
Default: /gemini review for gemini-code-assist, @{name} review for others.
Override via cloud_bot_retrigger_command.
Timeout behavior: If bot does not respond within the configured polling window
(cloud_bot_wait_seconds + helper timeout cloud_bot_poll_max_seconds, with helper poll interval cloud_bot_poll_interval_seconds, default ~11 minutes via kv_cache.frequent_poll_seconds = 60, cloud_bot_poll_interval_seconds = 30, and cloud_bot_poll_max_seconds = 600),
the workflow aborts and presents options to the user. It does NOT silently
fall back to local review and merge, except for the explicit quota-exhaustion
path described below.
Helper env overrides: the built-in polling helper honors CSA_PR_BOT_TIMEOUT
and CSA_PR_BOT_INTERVAL for ad-hoc override/testing. Normal workflow runs pass
explicit CLI arguments, so these env vars are mainly for direct script use.
Quota auto-skip cache: When the configured cloud bot posts a warning that
contains daily quota limit (case-insensitive), pr-bot records a 24h skip
window in ${XDG_STATE_HOME:-$HOME/.local/state}/cli-sub-agent/pr_review/cloud_bot_quota.toml.
Subsequent PR runs skip Step 4 bot triggering/polling during that window and go
straight to the existing merge-without-bot path after confirming the local
review state. When the window elapses, the cached section is cleared
automatically and normal bot triggering resumes. The same cache write happens if
the quota warning only appears during the later Step 5 post-verification check.
Manual override / reset:
CSA_PR_BOT_FORCE=1 bypasses the quota cache for a single invocation.
- Manual cache clear:
rm "${XDG_STATE_HOME:-$HOME/.local/state}/cli-sub-agent/pr_review/cloud_bot_quota.toml"
- There is currently no dedicated CLI flag wiring for
--force-cloud-bot in this skill entrypoint.
Assumed Fork Convention
pr-bot assumes the GitHub-common fork convention:
origin = your personal fork (where PR pushes come from)
- a separate remote such as
upstream = canonical repository
Under this convention, the default remote resolution order
branch.<branch>.pushRemote -> remote.pushDefault -> origin -> branch.<branch>.remote -> checkout.defaultRemote -> single remote
pushes to your fork and opens PRs against the canonical repository.
If you use the alternate convention where origin points at the canonical
repository and your fork lives on another remote, configure the push remote
explicitly before running pr-bot:
git config branch.<your-branch>.pushRemote <fork-remote-name>
Or set a global default:
git config remote.pushDefault <fork-remote-name>
When multiple remotes exist, origin does not reference the authenticated
GitHub login, and no explicit push remote is configured, pr-bot fails closed
with an actionable error instead of guessing and risking a push to the
canonical repository.
When cloud_bot = false:
- Steps 4-9 (cloud bot trigger, delegated wait gate, classify, arbitrate, fix) are skipped entirely
- A SHA-verified fast-path check is applied before supplementary local review
- The workflow proceeds directly to merge after local review passes
- This avoids the cloud bot wait and GitHub API dependency
Quick Start
csa run --sa-mode true --skill pr-bot "Review and merge the current PR"
SA Mode Propagation (MANDATORY)
When operating under SA mode (e.g., dispatched by /sa or any autonomous workflow),
ALL csa invocations MUST include --sa-mode true. This includes csa run,
csa review, csa debate, and any other execution commands. Omitting --sa-mode
at root depth causes a hard error; passing false when the caller is in SA mode
breaks prompt-guard propagation.
Step-by-Step
- Commit check: Ensure all changes are committed. Record
WORKFLOW_BRANCH.
- Local pre-PR review (SYNCHRONOUS -- MUST NOT background): use SHA-verified fast-path first (
CURRENT_HEAD vs latest reviewed session HEAD SHA from review_meta.json). If matched, skip review; if mismatched/missing, run full csa review --branch "${DEFAULT_BRANCH}" --fix --max-rounds 3 (the --fix flag resumes the same reviewer session to fix issues, preserving full review context). This is the foundation -- without it, bot unavailability cannot safely merge. Sets REVIEW_COMPLETED=true on success.
- Push and ensure PR (PRECONDITION:
REVIEW_COMPLETED=true): Detect if branch was already pushed (early-push warning). Resolve the push remote using the documented fork-convention guard; if origin looks canonical and no explicit push remote is configured, fail closed with a fix command instead of guessing. Then push with --force-with-lease, derive source_owner from origin remote URL, and resolve PR strictly by owner-aware lookup (base=${DEFAULT_BRANCH} + head=<source_owner>:${WORKFLOW_BRANCH}). If none exists, create with --head <source_owner>:<branch> and re-resolve; handle create races where PR was created concurrently. FORBIDDEN: creating/reusing PR without Step 2 completion.
3a. Check cloud bot config: Run csa config get pr_review.cloud_bot --default true.
If false → skip Steps 4-9. Apply the same SHA-verified fast-path before
supplementary review. If SHA matches, skip review; if SHA mismatches/missing
(HEAD drift fallback), run full csa review --branch "${DEFAULT_BRANCH}". Then route through
the bot-unavailable merge path (Step 6a).
- Trigger cloud bot and delegate waiting (SELF-CONTAINED -- trigger + wait gate are atomic):
- Round 0 (initial PR): follows
cloud_bot_trigger config ("comment" → @mention, "auto" → skip).
- Round 1+ (after fix push): ALWAYS posts explicit retrigger command (
cloud_bot_retrigger_command, default: /gemini review for gemini-code-assist) because bots do NOT auto-review on subsequent pushes.
- Wait
cloud_bot_wait_seconds quietly, then launch patterns/pr-bot/scripts/pr-bot-wait.sh once. The helper polls GitHub in shell using cloud_bot_poll_interval_seconds (default: 30s) and writes an atomic JSON result file; the main workflow only checks that file after up to two kv_cache.long_poll_seconds windows.
- Positive signal: verifies a review EVENT exists (via
pulls/{pr}/reviews API with submitted_at > push time), not merely absence of comments.
- Quota warning shortcut: if bot comments contain
daily quota limit, record the 24h quota cache entry and route to the merge-without-bot path instead of repeatedly waiting for a reply that cannot arrive during the quota window.
- If bot times out: ABORT workflow and present options to user. NO silent fallback.
- Non-target bot comments (e.g., codex auto-review) are also detected and included with a quota warning.
- Evaluate bot comments: Classify each as:
- Category A (already fixed): react and acknowledge.
- Category B (suspected false positive): queue for staleness filter, then arbitrate.
- Category C (real issue): queue for staleness filter, then fix.
- Staleness filter (before arbitration/fix): For each comment classified as B or C, check if the referenced code has been modified since the comment was posted. Compare comment file paths and line ranges against
git diff "${DEFAULT_BRANCH}...HEAD" and git log --since="${COMMENT_TIMESTAMP}". Comments referencing lines changed after the comment timestamp are reclassified as Category A (potentially stale, already addressed) and skipped. This prevents debates and fix cycles on already-resolved issues.
- Arbitrate non-stale false positives: For surviving Category B comments, arbitrate via
csa debate with independent model. Require structured debate output, then post the PR audit trail through an explicit gh pr comment step. If debate overturns the false-positive classification, reroute that comment into the real-issue fix step instead of posting a dismissal comment.
- Fix non-stale real issues: For surviving Category C comments, fix using
csa review --fix to resume the reviewer session (preserves review context, avoids 50K+ token waste of spawning fresh). Commit fixes, then run csa review --range "${DEFAULT_BRANCH}...HEAD" (review gate) BEFORE pushing — unreviewed fix code must not reach the remote.
- Continue loop: Push fixes and loop back (next trigger is issued in Step 4). Track iteration count via
REVIEW_ROUND. When REVIEW_ROUND reaches MAX_REVIEW_ROUNDS (default: 10), STOP and present options to the user: (A) Merge now, (B) Continue for more rounds, (C) Abort and investigate manually. The workflow MUST NOT auto-merge or auto-abort at the round limit.
- Clean resubmission (if fixes accumulated): Create clean branch for final review.
10.5.
Rebase for clean history: DISABLED. With merge commits (not squash), rebase destroys per-commit audit trail. Squash merges are forbidden for audit reasons.
- Merge: When
cloud_bot=false, leave audit trail comment explaining merge rationale (bot disabled + local review CLEAN). When cloud_bot=true, either the bot must have confirmed no issues before reaching this step, or Step 4 must have explicitly routed through the quota-exhausted merge-without-bot path with an audit comment citing the cached window and local review session. Plain timeout still aborts and never falls through to merge. Read merge strategy from csa config get pr_review.merge_strategy --default merge and branch deletion from csa config get pr_review.delete_branch --default false. Then gh pr merge --${MERGE_STRATEGY} [--delete-branch], then sync the local default branch from its remote tracking branch.
Example Usage
| Command | Effect |
|---|
/pr-bot | Full review loop on current branch's PR |
/pr-bot pr=42 | Run review loop on existing PR #42 |
Integration
- Depends on:
csa-review (Step 2 local review), debate (Step 6 false-positive arbitration)
- Used by:
commit (Step 13 auto PR), dev2merge (Steps 17-25), dev-to-merge (legacy alias)
- ATOMIC with: PR creation -- Steps 1-9 are an atomic unit; NEVER stop after PR creation
Done Criteria
- Step 2 completed synchronously (not backgrounded) via one of:
- full path:
csa review --branch "${DEFAULT_BRANCH}", or
- fast-path: current HEAD SHA matches latest reviewed session HEAD SHA.
REVIEW_COMPLETED=true is set after successful completion.
- Any local review issues are fixed before PR creation.
- PR resolved for the workflow branch (existing PR reused or a new PR created via strict owner-aware match, with create-race recovery and Step 4 precondition verified:
REVIEW_COMPLETED=true).
- Cloud bot config checked (
csa config get pr_review.cloud_bot --default true).
- If cloud_bot enabled (default): cloud bot triggered (round-aware: auto on round 0, explicit retrigger on round 1+), wait handled by the built-in
pr-bot-wait.sh helper with hard timeout and positive review-event signal checks, and timeout path handled. If bot responds with environment/configuration setup message instead of actual review, workflow STOPS and reports to user (Step 5a).
- If cloud_bot disabled: supplementary check completed via one of:
- fast-path: SHA match, review skipped, or
- fallback path: SHA mismatch/missing (HEAD drift) and full
csa review --branch "${DEFAULT_BRANCH}" executed.
- Every bot comment classified (A/B/C) and actioned appropriately (cloud_bot enabled only).
- Staleness filter applied (cloud_bot enabled only).
- Non-stale false positives arbitrated via
csa debate (cloud_bot enabled only).
- Real issues fixed and re-reviewed (cloud_bot enabled only).
10a. Post-fix re-review gate (HARD GATE): After fixing bot findings, bot is re-triggered on current HEAD via explicit retrigger command (NOT relying on auto-review), uses the same configurable wait policy as the initial gate (
cloud_bot_wait_seconds quiet wait + cloud_bot_poll_max_seconds polling), and requires a positive review event (via pulls/{pr}/reviews API, filtered by commit_id) with zero actionable findings. If no review event or API failure, falls back to local csa review --range "${DEFAULT_BRANCH}...HEAD". If new findings appear, workflow aborts (user must re-run pr-bot).
10b. Round limit: If REVIEW_ROUND reaches MAX_REVIEW_ROUNDS (default: 10), user was prompted with options (merge/continue/abort) and explicitly chose before proceeding.
10c. Rebase for clean history (Step 10.5): DISABLED — merge commits preserve audit trail directly.
- Audit trail: Every dismissed PR-page finding (for example, a bot finding) has a corresponding explanatory PR comment posted by an explicit workflow step BEFORE proceeding or merging.
- PR merged via configured strategy (default: merge commit, full history preserved). Branch deletion controlled by
pr_review.delete_branch config (default: false — branches preserved for audit).
- Local default branch updated from its remote tracking branch.