--- name: adversarial-review description: >- Run the cross-model adversarial review gate on a pull request: a *different* model from the one that wrote the code reviews the open PR adversarially and posts its findings as PR comments, before the change is declared done. Covers reviewer selection (the fallback chain), the auditable PR-comment protocol, the bundled headless-Gemini harness (`tools/agy-review`, typed exits), and the one-time machine setup headless reviewers need. Also covers reviewing a numeric or engineering contract (a physical model, sizing or pricing calculation, tolerance table — anything whose units mean something), where findings carry counterexamples, fixes carry recomputations, and each counterexample becomes a permanent test vector. Use for any complex change — more than one layer touched, a new pattern introduced, or unattended/production consequences — in any repo, driven by any coding agent (Claude Code, Codex, or another CLI agent). --- # adversarial-review A change is not done when its author believes it works — it is done when a **different model** has tried to break it and failed, on the record. Self-review shares the author's blind spots; the gate exists to put a second, adversarial intelligence between "looks right" and "merged". The reference deployment's history shows why this is worth the round-trips: reviewers have caught data-loss paths, dedup bypasses that would have spammed a human every run, silent-failure windows, and — reviewing this very skill's harness — eleven real defects the author had just written. **When the gate applies:** any *complex* build — it touches more than one layer, introduces a new pattern, or has unattended/production runtime consequences. Trivial mechanical edits don't need it. When in doubt, it applies. ## The rules 1. **Reviewer ≠ author, by model.** Select by model *diversity* first, availability second. If Claude wrote the code, Gemini, Codex or MiniMax reviews it; if Codex wrote it, Gemini, Claude or MiniMax reviews it. Same-model review is a genuine last resort — and must be disclosed on the PR so the weaker gate is visible. 2. **PR-anchored.** Review the *open PR*, not a local diff: the merge-base diff (`main...HEAD`) is exactly the author's change, and the PR description is the stated intent the reviewer can check it against. (A quick local-diff pass is fine while iterating pre-push; the auditable gate before merge is the PR review.) 3. **Findings live on the PR.** The review lands as PR comments naming which reviewer ran and its verdict (APPROVE / CHANGES-REQUESTED) with findings as `file:line` + severity + why it is a real defect. The author replies on the PR addressing every finding — fixed, rebutted with evidence, or accepted-with-rationale — so the whole gate is auditable later. 4. **Iterate to convergence, judged by whether a fix removes a *cause* — not by the finding count, and not by diff size.** Fix, push, re-review. Rounds often shrink (11 findings → 3 → 0), but not always: one gate ran 5 → 2 → 2 → 4 → 0 and the count carried no signal. The useful question is what a fix *did*. Consolidating a decision that lived in two places, or deleting a special case, ends a whole class of finding; bolting another guard beside the existing ones ends one instance and leaves the next reviewer more surface to reason about. In that gate the converging round's fix happened to delete 83 lines — but plenty of correct fixes legitimately **add** code (a missing liveness signal per `silent-failure-design`, input validation, a counterexample folded in as a permanent test vector), and **nothing here licenses stripping a safeguard to make a diff look convergent.** The tell for symptom-patching is not size but **repetition**: successive rounds adding guards to the same area, each needing its own reasoning about how it interacts with the last. 5. **Verify a finding's *premise* before acting on it — a CHANGES-REQUESTED is not automatically right.** Rebutting a premise takes **empirical proof** — a caller search, an execution trace, test output — never an opinion that the finding seems wrong, and the proof goes in the PR reply under rule 3. This rule raises the evidence bar on the author; it is not licence to dismiss an inconvenient finding. With no proof to hand, treat the finding as correct. The mirror of "an APPROVE is not a pass". A reviewer reasons from the diff and can be wrong about the code around it, and its remedy is then wrong in a way that *looks* rigorous. In the run above, a finding argued a function must avoid `resolve()` because it "runs on the 60-second health poll". It did not — its only caller was the weekly backup job, which one `grep` for callers would have shown. The optimisation added to satisfy it caused **three** real defects in the next round; deleting it converged immediately. Check the premise whenever the remedy **adds** complexity: that is precisely when being wrong is expensive. 6. **Watch for fix-induced findings, and treat a run of them as a signal.** Three of thirteen findings in that gate existed *only* because of earlier fixes. Once you see the second one, stop patching and look for the shared root — twice it was the same shape, one decision living in two places and drifting. The remedy is a single home, which is a deletion, not a guard. 7. **Point the harness at the PR you think you are reviewing.** Deriving a review invocation by copying a previous one and substituting the number is how a reviewer ends up auditing a different, already- merged PR while its instructions describe yours — a review that *appears* to have run, on the wrong thing. Read back the resolved PR number before launching, and treat the verdict as void if the posted comment is not on your PR. 8. **A dead reviewer is a *done* reviewer.** A hang, timeout, rate-wall, or silent exit means that leg of the chain is finished for this round: advance to the next reviewer. Never retry in place, and never skip the gate because a tool misbehaved. 9. **Re-assert your working branch** after any review tool runs — review CLIs can check out or strand the branch under you. The bundled `agy-review` harness removes this hazard at source by running the reviewer in an isolated worktree (see *The headless-reviewer contract*), but the rule still holds for the Codex leg and any CLI you drive raw in the live tree. 10. **Scope and shape are findings.** The PR description is the stated intent (rule 2), and the diff is checked against it in both directions: a hunk that does not trace to the intent — a drive-by improvement, a reformat of passing lines — is a finding, and so is structure the change does not need — speculative abstraction, configurability without a second caller, handling for scenarios that cannot occur. The authoring-side rules live in implementation-discipline; this is the gate holding a diff to them, where they are defects to name, not taste differences. And since no leg of the chain reads this page, name the lens when you delegate — a label/prompt line such as: "also flag, by reading the diff, any hunk that does not trace to the PR's stated intent, and any abstraction or error handling the change does not need". ## The fallback chain Pick the first *available* reviewer whose model differs from the author's. Four concrete legs — Gemini, Claude, Codex, MiniMax — each eligible whenever the author is **not** that model; order the eligible ones by diversity first, then window economics (lead with the idle separate-subscription pools — Antigravity, then MiniMax; conserve the walled Codex bucket and the Max window Claude shares with interactive work). The recurring case is a **Claude-authored** change, whose order is therefore Gemini → MiniMax → Codex (Claude itself is ineligible): the two idle separate budgets spend first, Codex — which walls for days — last. A **Codex-** or **Gemini-authored** change has Claude as a first-class leg, not the last resort — do not reach past it to a same-model reviewer. MiniMax adds a genuinely different model family (a fourth vendor, separately trained): it differs from *any* author, so it is eligible on every review and is never the *only* thing between an author and a same-model gate. Diversity here is the eligibility gate — a reviewer must differ from the author — while the *order* among the eligible legs is window economics, which is why the idle Antigravity pool still leads and MiniMax follows it rather than jumping the queue. 1. **Gemini** — the idle-pool lead; ineligible only when Gemini authored the change. Via the bundled harness: `tools/agy-review [--repo owner/name] [--label focus]` (path relative to this skill's directory — from a clone of this repo that is `plugins/coding/skills/adversarial-review/tools/agy-review`), run from inside a checkout of the repo under review. It pre-flights the known silent killers, bounds the run, and verifies success by the *posted PR comment*, never the CLI's exit code. `--model "