---
name: review-perps-pr
description: >-
  Pre-flight self-review gate for perps PRs. A perps dev runs it on their OWN PR to drive a
  looping double-agentic cross-review — two different model CLIs (Claude, Codex, Cursor)
  review independently because each catches different issues — until all APPROVE the same
  commit with zero findings. Reviewers are deliberately strict: every perps anti-pattern and
  every nit is a blocker. Loops fix → re-review until the PR meets perps standard, then says
  it is ready for an external human reviewer. Use for "review my perps PR", "cross review my
  perps branch", "is my perps PR ready", or self-review before requesting review. Self-gate:
  does not push, merge, or open the PR.
maturity: stable
---

# Review Perps PR — Cross-Review Self-Gate

Perps dev runs this on their OWN PR before requesting a human reviewer. Drives a looping
**double-agentic** cross-review: ≥2 different model CLIs review independently (each catches a
different bug class), you fix, re-review, until all APPROVE the same SHA with **zero**
findings. Self-gate: never pushes, merges, or opens the PR.

## Reviewer bar

Every perps anti-pattern AND every nit = **BLOCKER**. APPROVE only at zero findings.
"APPROVE with N nits" is a FAIL — forward them as work. Require ≥2 distinct providers; one
alone is advisory, not a passed gate.

## Step 0 — ask first (use AskUserQuestion), if not already given

- **Target** — branch/PR (default: current branch)
- **Reviewers** — `claude,codex` (default) / `claude,cursor` / all three (min 2)
- **Autonomy** — auto-fix+loop (default) / per-round approval / advisory (dev fixes)
- **Rounds** — default 3, cap 5

Echo the resolved contract in one line, then loop.

## Reviewer CLIs — install all (company allows it; each finds different bugs)

| CLI | one-shot review | install |
|---|---|---|
| Claude | `claude -p "<prompt>"` | `npm i -g @anthropic-ai/claude-code` |
| Codex | `codex exec "<prompt>"` | `npm i -g @openai/codex` |
| Cursor | `cursor-agent --print --mode ask --output-format text --workspace <wt> "<prompt>"` | `curl https://cursor.com/install -fsSL \| bash`, then `cursor-agent login` |

Missing a CLI → recommend installing it; don't silently drop to one reviewer. For a long
loop, run each CLI as a live tmux pane instead of one-shot, and `/clear` between rounds.

## Safety (env rules — bypass agents ignore prompt-level "read-only"; this broke a repo once)

1. Reviewers run in an **isolated read-only worktree pinned at the SHA**, never the live
   checkout: `git worktree add /tmp/perps-review-<sha> <sha>`. A reviewer `git checkout` on
   the live tree detaches HEAD and orphans your fix commits.
2. Fixes are **local commits only — never push**. This skill pushes/merges/opens nothing.
3. After every round: `git symbolic-ref -q HEAD` must show the branch (not detached) and the
   branch must point at the latest fix SHA — else STOP and report.

## Perps standard (reviewers must load and enforce as blockers)

From the perps `knowledge/` dir: **review-antipatterns** (core checklist), architecture,
connection-architecture, caching-architecture, formatting-rules, mobile-extension-map,
shared-package-analysis, feature-flags, screens. Check both repos when a shared util/screen
changes.

## Reviewer prompt (force a fresh full review every round)

```
Fresh full review of perps changes in <PR/branch> at <SHA> vs <base>. No prior context.
Load perps knowledge (review-antipatterns + the rest). You gate this before any human sees it.
Every perps anti-pattern AND every nit (naming, magic number, missing testID, weak test,
.toFixed, fallback-display vs 0) = BLOCKER. APPROVE only if nothing is left to improve.
Return:
VERDICT: APPROVE | REQUEST_CHANGES
COMMIT: <sha>
BLOCKERS: - <file:line> — <issue> — <fix>
NITS:     - ...        (any entry ⇒ VERDICT must be REQUEST_CHANGES)
EVIDENCE: - <files/commands inspected>
```

Reviewers run independently — don't show one's findings to another until both have a verdict.

## Loop

1. Capture HEAD SHA; make the read-only worktree at it.
2. Run all reviewers independently on that SHA.
3. Any non-empty BLOCKERS/NITS from any reviewer = work (even on APPROVE).
4. All APPROVE, zero findings, same SHA, validation green → Exit GREEN.
5. Else consolidate findings (reviewer, file:line, fix). Per autonomy: auto-fix / ask dev / hand off.
6. Fix as local commits → run validation → new SHA → verify branch state → reset reviewers → repeat.

## Validation each round (show results; no "fixed" without proof)

Lint + typecheck + `jest` on touched perps paths. If `app/controllers/perps/` changed:
`scripts/perps/validate-core-sync.sh` (controller must stay platform-agnostic for the
`@metamask/perps-controller` publish).

## Pause / escalate

Round cap hit with findings open · reviewers disagree on product/scope · same blocker
survives a round · a fix expands scope · HEAD detached or branch lags · only one provider
available.

## Exit

**GREEN** — report approved SHA, all reviewers APPROVE / 0 findings, validation pass, round
count, branch on-track and unpushed → "ready to request an external human reviewer" (this
skill pushed nothing). **Not green** — list open findings, current SHA, and what the dev must
decide or do. Don't claim ready.
