Goal
A short list of findings a senior engineer would hold the merge for. Three questions drive every finding:
- Does this code do what it says, clearly?
- What can be deleted, consolidated, or refactored away?
- What edge case slips through?
Precision over coverage: three real problems beat thirty nits. The run is read-only until the user approves fixes.
Scope
From the argument, settle exactly what "the changes" are, and pin a single BASE SHA plus the one diff command the whole run uses. Three target shapes:
- PR —
gh pr diff <n>for the changes; BASE = the merge-base with the PR's base branch. Skim the PR's existing review threads and don't re-raise what's settled there. - Commit range / branch vs main —
git diff main...HEAD(three-dot: compares against the merge-base, so unrelatedmaincommits don't pollute the diff). A given range likeA..Bworks too. - Uncommitted —
git diff HEAD, plus untracked files fromgit status --shortread in full —git diffnever shows them.
If the target is genuinely ambiguous (committed work and uncommitted changes both present), state which you're reviewing and why.
Done when: one BASE SHA and the exact diff command (with the untracked-files read for the uncommitted shape) are pinned and stated, before finding starts.
Find
Find candidates yourself, on this thread — no finder subagents. Read the diff through two lenses, matching the driving questions:
- Correctness & contract — questions 1 and 3.
- Simplicity & deletion — question 2.
Honor any focus in the argument (e.g. "especially simplicity") by weighting the lenses — but a focus never suppresses a correctness finding. Each candidate carries file:line, the claim, why it matters, and the smallest fix.
Rubric
Read VOCABULARY.md for the working language: the deletion test, spaghetti growth, the seam, the redundant test. The bar every candidate is judged against:
- The three driving questions are the only sources of findings. Never raise what a compiler, type-checker, formatter, or linter already catches, nor a matter of taste.
- A deletion or consolidation finding passes the deletion test: the complexity it removes concentrates rather than reappearing across callers.
- Never cut required behavior. Trust-boundary validation, data-loss and error paths, security checks, and accessibility are never "unnecessary surface", however simple their removal would make the code.
Validate
Dispatch one heavy-tier subagent (see Subagent tiers) to adversarially validate the whole candidate list in a single pass. Hand it pointers — the BASE SHA, the diff command, each candidate's file:line and claim — never your characterization of the code or a defense of a finding; it runs the diff and reads the cited code itself, forming its own view. Tell it to work its lookups in rounds: a round's frontier is every lookup whose answer it does not need before issuing the next one, and the whole frontier goes out as one batch in a single turn, every return read before it composes the next round.
Its job is to refute: for each candidate, decide whether the claim holds and default to REFUTED when the evidence is thin, the complexity a cut targets turns out to be load-bearing, or the call is a matter of taste. Every candidate leaves this step carrying a CONFIRMED or REFUTED verdict with its code evidence; only CONFIRMED findings ship.
Report
Render the validated review — findings first, ordered by severity, then the refuted receipt so the filter stays visible:
## Review — <target>
1. `<file:line>` — <what's wrong> · **fix:** <smallest fix>
<!-- if none: "No validated findings — the diff is clean." -->
Refuted: <n> candidate(s) killed in validation.
Then offer the next step: apply the small fixes in-session on the user's approval, and recommend /crank-lite plan for any finding that implies design work rather than a spot fix. Make no edits without approval.
Subagent tiers
Resolve the tier once per run and reuse it. The source of truth is a subagent model preference stated in the user instructions already loaded this session (user- and project-level CLAUDE.md / AGENTS.md); it is binding: map the tier onto it, even when it names a weaker model than the fallback below. The block below is a fallback only, for a session whose loaded instruction files state no such preference: