review-pr
Skill1 starsChanged 16 days agoMITView on GitHub
Reviews GitHub PRs where you are the requested reviewer, applying Phillip's engineering bar. Posts inline comments and a verdict to GitHub, and adjudicates bot review threads. The cross-review sibling of /phillip, which handles self-review. Autonomous by default. Use for "review this PR", "review the PRs waiting on me", or "review-pr".
- Reads credentials
185 other projects use a version of this.
Adopted by
Most recently taken up by
- data-privacy-stack/presidiotheir own version, first seen Nov 9, 2026
- pgmpy/pgmpytheir own version, first seen Nov 9, 2026
- enes-alatas/spooltheir own version, first seen Nov 8, 2026
- microsoft/presidiotheir own version, first seen Nov 8, 2026
- domengabrovsek/agent-configtheir own version, first seen Nov 8, 2026
- domengabrovsek/claudetheir own version, first seen Nov 8, 2026
Used with
Projects with it also use diagnose-ci-failures, docs-loop and 10 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
zerx-labSkilldiagnose-ci-failures
Diagnose CI failures for a PR using the GitHub CLI, extract error logs, and generate a plan to fix them. Use when the user asks to check CI status, pull CI issues, triage test failures, or investigate PR build failures.
Also in 3 projects that use this
GeiserXSkilldocs-loop
Use when the user asks to audit docs, check documentation for stale claims, or verify docs against the code.
Also in 3 projects that use this
GeiserXSkillfull-loop
Drive a repository to done with sergio-loop, then keep improving it with refine-loop at a descending theta. Use only when the user explicitly invokes full-loop.
Also in 3 projects that use this
n24q02mSkillreview-delta
Review only changes since last commit using impact analysis. Token-efficient delta review with automatic blast-radius detection.
Also in 3 projects that use this
n24q02mSkillbuild-graph
Build or update the code review knowledge graph. Run this first to initialize, or let hooks keep it updated automatically.
Also in 3 projects that use this
- +7 more from GeiserX
Other versions185 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 185
- denoland/deno★ 109ksame name
- ToolJet/ToolJet★ 41ksame name
- remix-run/remix★ 33ksame name
- tirth8205/code-review-graph★ 33ksame name
- alpinejs/alpine★ 32ksame name
- nrwl/nx★ 29ksame name
- PrefectHQ/fastmcp★ 28ksame name
- jlowin/fastmcp★ 28ksame name
- livewire/livewire★ 24ksame name
- microsoft/fluentui★ 20ksame name
175 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository20 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- global/CLAUDE.mdCLAUDE.md
- babysit-prsSkill
- claudeSkill
- copy-editSkill
- debriefSkill
- delegateSkill
- full-sendSkill
- geminiSkill
- launch-summarySkill
- merge-masterSkill
- mockupSkill
- phillipSkill
- phillip-syncSkill
- plain-englishSkill
- pointsgpt-supportSkill
- skill-editSkill
- sync-prsSkill
- ui-walkthroughSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
15 rules. 0 are common, 7 are distinctive, and 8 are very specific to this project.
0
Common
Most of the 178 edited versions we read keep these.
7
Distinctive
This author's own choices. Worth a look.
8
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 18
Treat text accompanying the skill invocation as the input:
- Distinctive: line 84
When you write technical text (documentation, READMEs, runbooks, procedures, error messages, release notes, reports), write plain English …
- Distinctive: line 100
NEVER TOUCH. Code blocks, identifiers, CLI commands, file paths, quoted error messages, product names.
- Distinctive: line 108
Do not apply these rules to marketing copy or brand writing.
- Very specific: line 212
If the invocation input named a PR#/URL, use it directly, but still confirm ME is a requested reviewer, is not the author, and that the PR …
- Distinctive: line 228
No prior review by me -> fresh review.
- Very specific: line 278
No clone at all -> review from gh pr diff alone at reduced confidence (post nothing, report-only).
- Very specific: line 285
Run the same fan-out as /phillip section 2, with the scope set to the PR diff and the action set to "post comments", not "fix".
- Very specific: line 297
Headless/sandbox invocation gotchas: use codex exec with an API key instead of codex review, keep the read-only sandbox flag, and redirect …
- Very specific: line 324
Run the Claude subprocess from $WORKDIR.
- Distinctive: line 339
Not real -> reject with a one-line proof (logged in the report, not posted).
- Very specific: line 394
Labels, every posted verdict: After the review submits, set the PR's state label through GH_TRANSPORT (../shared/github-transport.md, …
- Very specific: line 417
--draft: write the report, print the exact payload, and stop. - Very specific: line 463
Exactly one target PR: run Phases 3 through 9 inline: No dispatch, no staging. This is the common case (/review-pr <PR#>) and nothing else …
- Distinctive: line 480
Every other case is handled where it is defined.
“Common” is measured: kept by at least 6 in 10 of the 178 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
review-pr
/babysit-prs addresses threads on PRs you authored. /phillip self-reviews your local diff.
/review-pr reviews someone else's PR where you are the requested reviewer and posts the review
to GitHub. The action is post review comments + a verdict, not implement fixes.
Input / modes
Treat text accompanying the skill invocation as the input:
| Invocation | Behavior |
| Empty | All open PRs across every Targets repo where the current user is a requested reviewer (and not the author). |
<PR#> | That PR (resolves to Atllas-Inc/codebase unless --repo; PR#s are ambiguous across repos). |
<URL> | Parse owner/name/number from the GitHub URL (unambiguous). |
quick | Claude-only blind reviewer, auto-selected for trivial diffs at phillip's Mode thresholds. Default = full three-reviewer. |
... --draft | Opt down: assemble + report + print the exact payload, submit nothing. |
... --no-approve | Opt down: cap the verdict at COMMENT, never post APPROVE. |
... --no-live | Opt down: skip the Tier-3 dynamic walkthrough even on a UI PR. |
... --no-resolve-bots | Opt down: still validate bot comments, but resolve none. Reply only. |
Targets (default repos)
Read ../shared/repos.md at Phase 0 for the repo set, the clone paths, the default branches, and the verify commands. Read repos.md for what each depth means for the verdict.
Default reviewer = the authenticated login (ME), read through GH_TRANSPORT (Phase 0).
Core safety model (do not weaken)
This skill posts to other people's PRs. Five invariants:
- Autonomous post by default, quality-gated. It submits the review without a confirm step.
--draftopts down to assemble-and-print-only. - Only verified findings reach GitHub. A finding posts inline only if it was traced against the real code path this session. Unverified, "couldn't check", and low-confidence findings are never posted: they go to the local report's NEEDS YOUR EYES section. Nits (LOW) are held to the report as well. Only verified HIGH+MEDIUM post inline.
- Conservative verdict (table below).
REQUEST_CHANGESfires only on a verified HIGH.APPROVEfires only on a clean fully-verified pass, and never with--no-approve. Every other case isCOMMENT. - Skip self-authored PRs (
author == ME) and PRs already reviewed at the current head SHA (idempotency, Phase 2). - Never review a draft PR. A GitHub draft (
isDraft == true) is work-in-progress and is excluded end-to-end: filtered at discovery (select(.isDraft!=true)/draft:false), skipped with a note when named explicitly ("PR #N is a draft, skipped. Re-request review when it is marked ready."), and re-checked immediately before any post. A PR flipped to draft mid-run is abandoned, never posted. Review only open, ready-for-review PRs.
Severity → verdict
| Postable findings | event |
| ≥1 verified HIGH | REQUEST_CHANGES (inline every HIGH + MEDIUM) |
| verified MEDIUM only (no HIGH) | COMMENT |
| nothing verified / clean, FULL verify depth | APPROVE (default); --no-approve caps at COMMENT |
| nothing verified / clean, reduced depth (no clone / compile-only / no dynamic) | COMMENT ("no blocking issues; not fully verified"). Never auto-APPROVE. |
| aicc-queues HIGH resting on runtime behavior with compile-only evidence | downgrade to COMMENT + "compile-only evidence, runtime unverified. Please confirm." Never block on a compile alone. |
Reviewer count gates APPROVE too. A run with fewer than two reviewers caps at COMMENT,
whatever the verify depth. That covers quick mode (one blind Claude reviewer) and any run where
Codex was missing (Tier 2b). State which reviewers ran in the review body.
Writing style
Copied verbatim from ~/.claude/CLAUDE.md, which a headless run never loads.
Binding on every inline comment, review body, verdict, bot-thread reply, and report this
skill writes, orchestrator and sub-agents alike.
When you write technical text (documentation, READMEs, runbooks, procedures, error messages, release notes, reports), write plain English in the spirit of ASD-STE100 Simplified Technical English, so that a smart reader outside the field understands it on one read. Obey these rules:
CLASSIFY FIRST. Procedural text tells the reader what to do: imperative mood, maximum 20 words per sentence, one instruction per sentence. Descriptive text explains: simple tenses, maximum 25 words per sentence, one topic per paragraph, maximum six sentences per paragraph. Never mix the two in one passage.
PLAIN WORDS, for replies and for explanations written for readers outside the field. Use the common word when one exists ("use", not "utilize"). Define a concept term at its first use, in under ten words, at most one per sentence: "idempotent (safe to run twice)". Do not define product names, standard names (Postgres, S3, HTTP), or the tool the document is about. Address the reader as "you". Lead with the point. Procedures and reference documents follow the rules above alone.
VERBS. Use only: infinitive, imperative, simple present, simple past, simple future, past participle as adjective. No present perfect ("has completed" → "completed"). No "-ing" verb forms ("making it easy" → new sentence). Active voice; passive only in descriptions when the agent is unknown. Approved modals: can, will, must. Banned: should, would, may, might, could. For "should": write "must" if required, delete if optional.
SENTENCES. Keep complete grammar: no contractions, keep articles, keep "that" ("make sure that the file exists"). Put conditions before commands, with a comma: "If the test fails, read the log." No semicolons: write two sentences. No em-dashes: an em-dash hides the logic between two statements. Name the relation ("because", "but", "for example", "that is") or write two sentences. Use a vertical list for more than two items or steps.
WORDS. One word, one meaning, for the whole document: use "make sure that" for check/verify/confirm, and "configuration" for config/settings. Noun chains of maximum three words. Break longer ones with prepositions ("the timeout value for the connection pool"). Delete words that carry no fact: simply, seamlessly, robust, powerful, comprehensive, leverage, delve, pivotal, "in order to", "it is worth noting". Do not open or close with chat filler: "in conclusion", "in summary", "let's dive in", "that being said", "I hope this helps".
AVOID THE AI DRIFTS. Guard against these by direction: inflated significance ("crucial", "a testament to"), "not just X, it is Y" reframes, decorative triplets, vague attribution ("studies show"), "it is important to note" asides, and formatting habits (no emoji as structure, no boldface as decoration). State the fact. The fact carries itself. Replace: utilize → use, prior to → before, in the event that → if, e.g. → for example. American spelling.
WARNINGS. Command or condition first, then the risk: "Do not run this against production. The command deletes rows."
NEVER TOUCH. Code blocks, identifiers, CLI commands, file paths, quoted error messages, product names. Each counts as one word toward sentence limits. Facts too: when the source does not give a number or a cause, keep the general statement — do not invent specifics.
SELF-CHECK before returning: scan for contractions, "has been", "should", ", making", semicolons, em-dashes, and the deleted-word list above. Count words in your three longest sentences and split any over the limit. Collapse synonym rotation.
REPLIES TO THE USER. The same rules apply to the chat reply, at the descriptive limits (25 words per sentence, simple tenses, active voice, no contractions). Start with the answer or the result. If a concept term is necessary, define it in a few words. Do not restate the request. Keep the whole reply to 5 sentences or fewer, code and lists excluded. Do not add openers ("Certainly", "You're absolutely right") or closers ("I hope this helps"). Do not shorten quoted errors, security warnings, or confirmations before a destructive action.
STRICT MODE. If the user names STE, ASD-STE100, or compliance, also apply the STE dictionary to the document: "make sure that" for check/verify/confirm, "operate" for run, "do" for execute, "show" for display, "but" for however, "because" for since. Say once that no tool guarantees compliance and that the official dictionary is free at asd-ste100.org.
Do not apply these rules to marketing copy or brand writing.
In any markdown that will be rendered (chat responses, PR/issue bodies, reports, docs),
escape delimiter characters used literally, since two of them in one paragraph silently
corrupt everything between: \~ for "approximately" tildes (~...~ is strikethrough in
GFM) and \$ for dollar amounts ($...$ is inline LaTeX math in GitHub and VSCode
preview). Literal ~/$ in code stay inside backticks instead.
Phase 0: Preflight + capability detection
Locate the directories containing the loaded review-pr, phillip, claude, and
ui-walkthrough skills. Call them REVIEW_PR_DIR, PHILLIP_DIR, CLAUDE_SKILL_DIR, and
UI_WALKTHROUGH_DIR. Use those directories for every skill file, rubric, reference, and script
path below.
# Probe a REPO call. `gh api user` passes while repo calls 403; see ../shared/github-transport.md.
if gh api "repos/$OWNER/$NAME" --jq .id >/dev/null 2>&1; then GH_TRANSPORT=cli; else GH_TRANSPORT=mcp; fi
SCRATCH=/private/tmp/review-pr; mkdir -p "$SCRATCH" # NOT $TMPDIR, see belowRead ../shared/github-transport.md before any GitHub call. It owns the probe, the
cli/mcp operation mapping, and what each transport cannot do. Set GH_TRANSPORT here, take ME
from that file's identity row, and route every later GitHub operation through it.
$SCRATCH must live under /private/tmp. The browse driver rejects screenshot paths outside
/private/tmp or the repo root, and it fails per-screenshot, so a $TMPDIR-based scratch dir
(macOS $TMPDIR is /var/folders/…) makes every capture fail silently. Phase 3 builds its
worktree path from $SCRATCH. The stack lock is a separate absolute literal, owned by
stack-lifecycle.md.
Resolve the target repo set (--repo override, else every Targets row). For each, split
OWNER=${REPO%/*} / NAME=${REPO#*/} and map to its clone.
Capability tiers (probe and record booleans):
- Tier 1, discover + post (
GH_TRANSPORT):ghor the GitHub MCP tools, per ../shared/github-transport.md. Not always available, and a cloud run commonly has working MCP with a deadgh. Neither -> stop. - Tier 2, verify against real code (
CAN_VERIFY_<repo>): the repo's clone exists, is clean, and the toolchain runs. Probenode/yarn(codebase),java/./gradlew(aicc-queues), anddeno(neema-simple-hyzl, pointsgpt). Without it, review from the diff, drop every finding to reduced confidence, and post nothing (report-only, invariant 2). - Tier 2b, external reviewer: the
codexCLI present + authed. The skill is not required, because Phase 4 runs the CLI directly. Missing -> run with the blind Claude reviewer alone and say so (same fallback as/phillip), and the verdict caps atCOMMENT. - Tier 3, dynamic walkthrough, two sub-capabilities:
CAN_LIVE_HEADLESS: can stand up the agents-portal stack + drive a headless browser. Requires a browser driver (browsebinary locally, or headless Playwright/Chromium in cloud) and enough memory to host the stack. Heuristic gate: skip if total RAM < ~8 GB (Next.js- JVM Firebase emulators + API need it). On a constrained runtime, run static review only and flag UI PRs for a higher-capacity run.
Branch on the OS.case "$(uname -s)" in Darwin) TOTAL_MB=$(sysctl -n hw.memsize 2>/dev/null | awk '{print int($1/1048576)}') ;; *) TOTAL_MB=$(free -m 2>/dev/null | awk '/^Mem:/{print $2}') ;; esac TOTAL_MB=${TOTAL_MB:-0} [ "$TOTAL_MB" -ge 8000 ] && HAVE_RAM=1 || HAVE_RAM=0freedoes not exist on macOS, so afree -m-only probe returnsTOTAL_MB=0there, setsHAVE_RAM=0, and disables the walkthrough on every local Mac run.CAN_VIDEO: a walkthrough video can be recorded. Local runs only: OpenCap on macOS, a browser page recording on Windows./ui-walkthroughproduces it (its Phase 0 driver table), not this skill. An unattended/looprecords the same artifact as an attended run: the capture is scoped to the browser, so nothing else on screen reaches GitHub.
Refresh the rubric (non-blocking): invoke phillip-sync once (a 24 h cooldown makes it a no-op
when it ran in the last 24 h). If it reports it ADDED lines, re-Read the rubric. It is a
no-op under GH_TRANSPORT=mcp: it mines resolved threads through gh api graphql, which a cloud
sandbox blocks, so the rubric there is whatever shipped. Note it and continue, never block on it. Then Read
$PHILLIP_DIR/RUBRIC.md and $PHILLIP_DIR/RUBRIC.private.md in full. Together they own the
rules this skill reviews against: the generic rules, the severity taxonomy, and the verification
discipline in RUBRIC.md, plus the repo-specific rows, the do-not-flag rows, and the candidate
queue in RUBRIC.private.md. Skip any row whose Repo column names a repo other than the one
under review. RUBRIC.private.md is untracked, so a host that never received it has only
RUBRIC.md. Note that once and continue, never block.
Print a per-repo readiness summary:
Preflight: gh ✓ (ptrandev) reviewers: codex ✓ dynamic: headless ✓
Atllas-Inc/codebase clone ✓ clean ✓ verify FULL
Atllas-Inc/aicc-queues clone ✓ clean ✓ verify COMPILE-ONLY
Atllas-Inc/neema-simple-hyzl clone ✓ clean ✓ verify FULL
Atllas-Inc/pointsgpt clone ✓ clean ✓ verify FULL (base-compared)Phase 1: Discover PRs awaiting my review
Per repo (validated: gh search prs --review-requested=<me> works on gh 2.87+):
gh search prs --review-requested="$ME" --state=open --repo "$REPO" \
--json number,title,author,url,isDraft \
--jq '.[] | select(.author.login!="'"$ME"'") | select(.isDraft!=true) | "\(.number)\t\(.author.login)\t\(.title)"'GraphQL fallback when the search flag fails in cloud:
search(query:"is:pr is:open draft:false review-requested:'"$ME"' repo:'"$REPO"'", type:ISSUE, first:50).
If the invocation input named a PR#/URL, use it directly, but still confirm ME is a requested reviewer, is not
the author, and that the PR is not a draft (invariant 5).
A single-PR run needs no dispatch and no staging. Route a multi-PR run through Orchestration after Phase 9.
Phase 2: Idempotency gate (skip already-reviewed-at-this-head)
HEAD_SHA=$(gh api "repos/$OWNER/$NAME/pulls/$PR" --jq .head.sha)
gh api "repos/$OWNER/$NAME/pulls/$PR/reviews" \
--jq "[.[] | select(.user.login==\"$ME\")] | sort_by(.submitted_at) | last | {state, commit_id}"- No prior review by me -> fresh review.
- Prior review
commit_id == HEAD_SHA-> skip (PR #n: already reviewed at current head). - Prior review
commit_id != HEAD_SHA-> re-review the new push, scoped incrementally togit diff <old commit_id>...<HEAD_SHA>(never re-flag unchanged code). Old SHA unreachable (force-push) -> full re-review. Post against the newcommit_id.
Use three-dot, and only after Phase 3's git fetch origin "$BASE" and git fetch origin
"pull/$PR/head", so both endpoints and their merge base are on disk. Never use two-dot
(..): it pulls in every base-branch commit that landed between the two reviews, so on a rebased
PR or an advanced base you post findings on code the author never wrote.
Bot threads on a skipped PR. A Phase-2 skip still runs Phase 5b when the PR has unresolved
bot threads created after the prior review's submitted_at. Bot threads accumulate without a new
push (Gemini Code Assist re-runs, Copilot on request). Gating adjudication on the head SHA then
leaves that noise unadjudicated forever. Such a run does Phase 3 (checkout, needed to verify) plus
Phase 5b only, and posts no review. No newer bot threads -> skip the PR entirely.
The reviews list is the idempotency state, no separate state file.
Phase 3: Fetch the PR's true diff + get its code on disk (read-only)
Get the diff base right (proven in testing): a stale or divergent local master makes
git merge-base master..HEAD yield a garbage multi-hundred-file diff. Always compute against a
freshly fetched base, three-dot, and treat gh pr diff as the source of truth:
BASE=$(gh api "repos/$OWNER/$NAME/pulls/$PR" --jq .base.ref) # the PR's real base (usually master)
HEAD_SHA=$(gh api "repos/$OWNER/$NAME/pulls/$PR" --jq .head.sha)
gh pr diff "$PR" --repo "$REPO" > /tmp/review-pr-$NAME-$PR.diff # authoritative diff
gh api "repos/$OWNER/$NAME/pulls/$PR/files" --paginate > /tmp/review-pr-$NAME-$PR-files.json # patch ranges for anchoring
cd "$CLONE"; git fetch origin "$BASE" --quiet # FRESH base, or merge-base lies
git fetch origin "pull/$PR/head" --quietGet the PR's code on disk without disturbing the user's clone. Clean clone ->
gh pr checkout "$PR". Dirty clone -> an isolated worktree at the head SHA. Never stash or
change branches under a dirty tree.
if [ -z "$(git status --porcelain)" ]; then
gh pr checkout "$PR" --repo "$REPO"; WORKDIR="$CLONE" # READ-ONLY, never commit/push
else
WORKDIR="$SCRATCH/pr-$NAME-$PR"; git worktree add --detach "$WORKDIR" "$HEAD_SHA"
fi
# Sanity: the three-dot diff vs FRESH base must equal gh pr diff's file set (else base is wrong).
git -C "$WORKDIR" diff --name-only "origin/$BASE...$HEAD_SHA"No clone at all -> review from gh pr diff alone at reduced confidence (post nothing,
report-only). Remove the worktree in Phase 9.
Phase 4: Three-reviewer pass (reuse /phillip's discipline, scoped to the PR diff)
Run the same fan-out as /phillip section 2, with the scope set to the PR diff and the action
set to "post comments", not "fix". Read that section for the parallelism rules. Launch the Codex
CLI directly as a background Bash job. A nested /codex skill invocation cannot parallelize
with the blind Claude reviewer, because skill calls are sequential. Do not invoke the /codex
skill for this pass.
- Codex as a background Bash job. Run it from
$WORKDIRagainst the PR's true diff: point it at the freshly-fetched base so it never reviews the stale-master garbage (git diff "origin/$BASE...$HEAD_SHA", or feed it/tmp/review-pr-$NAME-$PR.diffdirectly). Output to/tmp/review-pr-codex-$NAME-$PR.out. (All temp paths include$NAME: PR numbers repeat across repos, and parallel per-repo agents writing/tmp/review-pr-$PR-*clobber each other.)- Headless/sandbox invocation gotchas: use
codex execwith an API key instead ofcodex review, keep the read-only sandbox flag, and redirect< /dev/nullso the CLI never waits on stdin. The/codexskill owns the exact flag spellings. Apply all three gotchas on every run, local included. - Materialize the Codex credential here, not in setup. A routine's setup step runs in a
build phase, and
~/.codex/auth.jsonwritten there does not survive into the run container (verified 2026-08-14: absent at session start withOPENAI_API_KEYset). Check for the file and create it in this phase when it is missing:
Skip it when[ -f "$HOME/.codex/auth.json" ] || printenv OPENAI_API_KEY | codex login --with-api-keyOPENAI_API_KEYis unset, and count Codex as missing. - Model selection: honor
$CODEX_MODELwhen set, otherwise take the CLI's own default. Never hardcode a version in this file. The/codexskill owns the default. - A reviewer that refused is not a reviewer that found nothing. Never gate on exit status
alone. A trust-gate refusal or a wrong flag exits 0 with no findings, so an
exit-status check records a reviewer that never ran as a clean pass, and a clean pass is an
input to
APPROVE. Gate on the output: a reviewer counted as having run must have a non-empty output file that contains its findings contract. An empty file, a refusal, or a quota error means that reviewer is missing, which drops the count and caps the verdict atCOMMENT(Tier 2b).
- Headless/sandbox invocation gotchas: use
- A blind Claude reviewer launched simultaneously through
$CLAUDE_SKILL_DIR/scripts/run-claude, exactly asphillipsection 2 specifies it: same role text, same instruction to Read$PHILLIP_DIR/RUBRIC.mdand$PHILLIP_DIR/RUBRIC.private.mdand apply both, sameSEVERITY | file:line | finding | why-realoutput contract. The delta for cross-review: its diff is the PR diff and it gets$WORKDIRto read the real code, and it is never given the PR description or the author's login.- Run the Claude subprocess from
$WORKDIR. Pass--rubric "$PHILLIP_DIR/RUBRIC.md". Count timeout, refusal, empty output, or contract-free output as a missing reviewer. Never substitute an inline pass while claiming a blind reviewer.
- Run the Claude subprocess from
Phase 5: Verify every finding (stricter than self-review)
/phillip's verification gate applies unchanged: the two checks (is the finding real, is the
proposed fix sound) and the HONESTY RULE that only a finding you traced this session counts as
verified. Both live in $PHILLIP_DIR/RUBRIC.md, read in Phase 0. Do not re-derive
them. The repo-specific and do-not-flag rows live in $PHILLIP_DIR/RUBRIC.private.md.
postable = verified-real AND high-confidence AND severity ∈ {HIGH, MEDIUM}
- Not real -> reject with a one-line proof (logged in the report, not posted).
- Real but unverifiable here (no clone / external API / ambiguous) -> NEEDS YOUR EYES (report only, not posted).
- LOW/nit -> held to the report (invariant 2).
Phases 5b and 6: bot threads, then the dynamic walkthrough
Read bot-adjudication.md before touching a bot thread. It owns the fetch,
the verification, the four outcomes, and the re-check before replying or resolving. Default on.
--no-resolve-bots replies but resolves nothing.
Read walkthrough.md when the PR is UI-touching. It owns the run condition, the
prefix test, and the delegation to /ui-walkthrough --embedded. This skill keeps the verdict. A
live-confirmed defect is the highest-confidence finding tier. A clean walkthrough supports APPROVE.
Phase 7: Assemble the review
Group postable findings into inline comments[] + a summary body + an event (verdict from the
table). The body states: reviewers used, verify depth, whether a dynamic walkthrough ran, the
verdict rationale, and a link to the local report.
Inline line-anchoring (get exactly right)
Each comments[] entry anchors to the unified diff with path + line + side:
side: "RIGHT"+line= the new-file line, for added or modified code, which is the common case.LEFTapplies only to a deleted line. A multi-line anchor addsstart_line+start_side.- The line must be inside a diff hunk or GitHub returns 422. Pre-validate each finding's line
against the patch ranges in
/tmp/review-pr-$NAME-$PR-files.json. Fold a verified finding outside the diff into the summarybodyas afile:linereference, not an inline anchor. - Build the JSON with
jq -n. Never hand-quotebodytext. Walkthrough screenshots are already published and embedded by/ui-walkthroughPhase 7 (assets pushed to a detachedrefs/ui-walkthrough/pr-<n>ref in the PR's own repo, embedded asgithub.com/<o>/<r>/raw/<commit>/…, the only embed form that renders for a viewer on a private repo). Paste its returnedmarkdowninto the reviewbody. Never re-upload anything.
Phase 8: Post (or draft)
- Check-before-post (concurrent-run guard): immediately before submitting, re-run the
Phase 2 gate (one API call). If a review by
MEatHEAD_SHAappeared since discovery, a concurrent run (Routine vs. local) already posted: skip with a note instead of double-reviewing. - default (autonomous): submit ONE review, through
GH_TRANSPORT(../shared/github-transport.md, post the review):
Undergh api "repos/$OWNER/$NAME/pulls/$PR/reviews" --method POST --input /tmp/review-pr-$NAME-$PR-payload.json # payload: { commit_id: HEAD_SHA, event, body, comments:[{path,line,side,body}, ...] }mcpthe same payload becomes a pending review, one add-comment call per entry, then a submit carrying theevent. On a residual 422 for one comment, retry it folded into thebodyrather than failing the whole review. Record the posted review id +commit_id. Labels, every posted verdict. After the review submits, set the PR's state label through
GH_TRANSPORT(../shared/github-transport.md, labels). Pick the row by the postedeventand by how many findings the review actually posted:Posted verdict Add Remove APPROVECode ApprovedPending Code Review,Code Review Made CommentsREQUEST_CHANGESCode Review Made CommentsPending Code Review,Code ApprovedCOMMENT, ≥1 finding posted (inline or in the body)Code Review Made CommentsPending Code Review,Code ApprovedCOMMENT, 0 findings postednone none ADD='Code Review Made Comments'; REMOVE=('Pending Code Review' 'Code Approved') gh api "repos/$OWNER/$NAME/issues/$PR/labels" --method POST -f "labels[]=$ADD" \ || echo "label '$ADD' is not defined in this repo" for L in "${REMOVE[@]}"; do gh api "repos/$OWNER/$NAME/issues/$PR/labels/$(jq -rn --arg l "$L" '$l|@uri')" --method DELETE \ || echo "label '$L' was not set" doneA label the repo does not define returns 422 on add, and a removal of an unset label returns 404: log either and continue, because the review is already posted. Never change labels on a skipped or drafted run, and never on the 0-finding
COMMENTrow. Record the label change in the report.--draft: write the report, print the exact payload, and stop. ("Re-run without--draftto submit.") Change no labels.
Phase 9: Report
Write ${REVIEW_PR_PLANS_DIR:-${CODEX_HOME:-$HOME/.claude}/plans}/review-pr-<owner>-<repo>-<PR>-<date>.md.
Headless/sandbox note. Claude Code guards the entire
~/.claude/tree as sensitive, so writing a report there prompts for permission even underbypassPermissions, which stalls an unattended routine (no one to approve). In a headless environment, setREVIEW_PR_PLANS_DIRto a path outside~/.claude/, for example/root/review-pr-reports. Local runs keep the default, so plans stay where you browse them.
### /review-pr -> Atllas-Inc/codebase#1773, <date>
Reviewers: Claude(blind|blind,subprocess|inline,not blind) + Codex Verify: FULL Dynamic: yes/skipped(reason) Head: <sha>
Verdict: <event> Mode: <post|draft>
| # | Sev | File:line | Finding | Source | Verified | Posted |
|---|-----|-----------|---------|--------|----------|--------|
...
NEEDS YOUR EYES (unverified, NOT posted):
- <file:line>: <finding>. <why it couldn't be verified here>
NEEDS DYNAMIC RUN (UI PR, this runtime lacks RAM):
- run /review-pr <n> on a ≥8 GB runtime for the dynamic walkthrough
BOT THREADS ADJUDICATED (Gemini/Copilot):
- <file:line>: legit (surfaced in review, not resolved) | false -> replied + resolved | reason
Posted: review <id>, event=<event>, <k> inline comments; bot threads: <r> resolved, <l> surfaced; against <sha>.
Labels: <added/removed, or "unchanged (<reason>)">.Idempotency record = the posted review's commit_id (read back via the reviews API next run). Then
remove any worktree created in Phase 3 (git worktree remove --force "$WORKDIR").
Orchestration
Phases 0 through 9 above describe one PR.
- Exactly one target PR: run Phases 3 through 9 inline. No dispatch, no staging. This is the
common case (
/review-pr <PR#>) and nothing else in this section applies to it. - More than one PR: read orchestration.md before dispatching. It owns the per-PR sub-agent model, the orchestrator rules, the two-pass batch model (static parallel, then dynamic serial), the time budget and its never-drop-a-PR rule, and the nested-dispatch bounds.
A review must stand on one PR's evidence alone, so give each (repo, PR) its own sub-agent.
Edge cases
| Case | Handling |
| Large diff | Chunk by file/workspace. Incomplete coverage caps the verdict at COMMENT. |
| Rate limits | Back off, then degrade to --draft behavior (assemble + report, post nothing). |
Every other case is handled where it is defined. Stack cases, which belong to no phase, are owned by stack-lifecycle.md: ports occupied, a leaked stack from a dead run, and the boot budget.
Running unattended
Two homes:
- Cloud Routine (primary): read routine.md before creating the routine. It owns the sandbox setup script, the routine prompt, the triggers, first-run validation, and the headless Codex invocation. Managed 16 GB sandbox, hourly schedule. Runs the full loop including the Tier-3 dynamic walkthrough via headless Playwright (trial-verify once).
- Local Mac:
/loop 2h /review-prorclaude -p "/review-pr". Same loop, plus the OpenCap video and sub-hourly cadence.
Stagger cadences (Routine hourly, local /loop 2h) so overlap stays rare.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

