# Zereight Review

> Comprehensive code review skill for practical PR feedback. Use for feature, bugfix, and refactor reviews. Prioritizes correctness, edge cases, dual-path symptom fixes vs delete-a-path alternatives, logic invariants, async state, flow ownership, ponytail simplicity, motion craft, test quality, OWASP, and actionable feedback.

- Skill: `zereight/zereight-review` (Agent Skill, multi-file: 15 files)
- Install (CLI): `npx skillmds@latest add zereight/zereight-review`
- Raw SKILL.md: https://api.skillmd.com/api/skills/zereight/zereight-review/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: zereight (https://skillmd.com/u/zereight)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/zereight/zereight-review

---


# zereight-review

Prioritize **correctness and risk** over style nitpicks.
Default tone: concise, direct, actionable.

**Navigation PR rule (non-negotiable):** No navigation/back-stack finding
without **symbol + production caller(s) + path tag + terminal step** (hop vs
`push`/`replace`/`navigateToDestination`). See
`references/navigation-review-gate.md`.

## Mandatory Review Ensemble -- NON-NEGOTIABLE

When the user invokes `zereight-review`, `$zereight-review`, or asks to use the
Zereight review skill, do not complete the review from a single reviewer pass.
You must run a multi-skill, subagent-based review ensemble first, then synthesize
the results.

Required instruction sources to load before reviewing:

- Nearest repo `AGENTS.md`
- `/Users/tao.exe/.codex/instructions.md`
- `/Users/tao.exe/.codex/AGENTS.md`
- `codegraph-review-routing` when CodeGraph MCP is available or the review needs impact/call-chain context
- `code-review`
- `code-review-expert`
- `code-reviewer`
- `agent-skills:code-review-and-quality`
- `agent-skills:using-agent-skills`
- `thermo-nuclear-code-quality-review`
- `ponytail-review` (`/Users/tao.exe/.cursor/skills/ponytail-review/SKILL.md`)
- `review-animations` (`/Users/tao.exe/.claude/skills/review-animations/SKILL.md` + `STANDARDS.md`)
- `references/flow-ownership-review.md` (this skill — screen role, data owner, RN preload vs upstream prepare)
- `references/async-effect-cancellation.md` (this skill — generation token vs boolean for async effect cleanup)
- `references/direction-alternative-gate.md` (this skill — symptom-fix vs reorder vs delete-a-path; 1-line PRs in scope)
- `references/navigation-review-gate.md` (this skill — caller context, hop vs terminal nav diff, path tags, scenario matrix, author observation, echo dedup)
- `references/test-review-gate.md` (this skill — test necessity, duplication/placement, slop, axis-linked gaps; RNTL lens when RN component tests)
- `references/problem-map-output.md` (this skill — **문제 지도** final-output template: 어디/뭐/언제/유저영향/우선순위)

Required subagent review passes:

| Subagent pass | Builtin agent | Model (required) | Required basis | Review focus |
| --- | --- | --- | --- | --- |
| Baseline full-diff reviewer | `reviewer` | session (`inherit`) | `code-review` | finding-first output, severity, full diff coverage, `comment-worthy` / `no comment` |
| Regression and contract reviewer | `reviewer` | session (`inherit`) | `code-review-expert` + `references/navigation-review-gate.md` when nav scope | behavioral regressions, API/prop contracts, hidden state and edge-case risk; **per-caller** stack findings with path tags — no whole-PR nav broadcast |
| File coverage reviewer | `worker` | session (`inherit`) | `code-reviewer` | every changed file and hunk, missing tests, maintainability risks |
| Quality gate reviewer | `worker` | session (`inherit`) | `agent-skills:code-review-and-quality` | correctness, reliability, maintainability, security, test quality |
| Thermo-nuclear maintainability reviewer | `reviewer` | session (`inherit`) | `thermo-nuclear-code-quality-review` | code judo / structural simplification, 1k-line boundary, spaghetti branching, abstraction quality, layer boundaries |
| Flow ownership & screen-role reviewer | `reviewer` | session (`inherit`) | `references/flow-ownership-review.md` + repo data layering (`CLAUDE.md`) | data owner vs orchestration owner; upstream prepare vs target-owned fetch; `navigation.preload`; nav-param growth; requirement-change blast radius; loading UI on async gap |
| Ponytail simplicity reviewer | `reviewer` | session (`inherit`) | `ponytail-review` + `references/direction-alternative-gate.md` | yagni, duplicate orchestration, dual hook paths, shrink/delete, **sibling-path grep on target-swap** — **correctness/security out of scope** |
| Motion craft reviewer | `reviewer` | session (`inherit`) | `review-animations` + `STANDARDS.md` | motion-only hunks; Ten Non-Negotiable Standards; Before/After/Why table + Block/Approve verdict; RN map transform/opacity=spring interruptibility=GPU; **not** general logic |
| Test quality reviewer | `worker` | session (`inherit`) | `references/test-review-gate.md` + consolidate-test-suites + testing-anti-patterns + test-writing (+ `zereight-react-native-testing` when RN component tests) | test-only hunks; necessity (one invariant per test), duplication/placement (one owning layer), slop (mock-behavior, prod pollution, overspec), axis-linked gaps; **never 🟠 for missing tests alone** |
| Agent orchestration reviewer | `delegate` | session (`inherit`) | `agent-skills:using-agent-skills` | whether the work was split correctly and whether any review lens is missing (thermo-nuclear, flow ownership, ponytail, motion craft, React/RN, test quality) |
| React/RN specialist reviewer | `reviewer` | session (`inherit`) | `zereight-react-native-optimizer` + react-doctor JSON + `references/navigation-review-gate.md` when nav scope | effect/render/list/animation/native perf regressions; **Skia GPU readback loops** (`makeImageSnapshot` + `readPixels` in rAF/effect); reconcile react-doctor diagnostics with diff evidence; nav findings split by caller/path |
| Zereight coordinator | (parent) | session (parent) | this skill + `references/direction-alternative-gate.md` + `references/navigation-review-gate.md` when nav scope | three-dot diff, RED-team, verification, **A/B/C direction table**, caller/scenario gates, author observation reconcile, echo dedup, final synthesis |

**Flow ownership pass rule:** Spawn when the PR changes any navigable screen,
navigator, route params, or multi-step handoff (`*Screen`, `*-screen.tsx`,
`*navigator*`, `navigation-type.ts`, guide→detail flows). Mark
`skipped (not a screen/flow PR)` when the diff is assets/locales/tests-only or
has no navigation/screen boundary change.

**Ponytail pass rule:** Spawn when the diff has substantial logic in
`*.ts` / `*.tsx` (same scope as react-doctor). Skip for assets/locales/tests-only.
Do not promote ponytail `delete`/`yagni` to 🟠+ without user-facing risk evidence.
**1-line target-swap is in scope** (`CLIENTS.A`→`B`, mock↔real, dual upsert).
Do **not** accept `Lean already. Ship` until the pass greps the sibling
identifier's production callers. Inject `references/direction-alternative-gate.md`
into the ponytail prompt.

**React/RN pass rule:** Spawn when the PR changes any `*.ts` / `*.tsx` outside
`**/*.test.*`, `**/__snapshots__/**`, `**/locales/**` only. If the PR is
assets/locales/tests-only, mark the pass `skipped (not React/RN logic PR)` in
`검증 결과` — do not spawn.

**Motion craft pass rule:** Spawn when the three-dot diff touches **motion
code** in `*.ts` / `*.tsx` / `*.css` (exclude `**/*.test.*`,
`**/__snapshots__/**`, `**/locales/**` only). Treat as in scope when **any**
changed hunk matches one or more:

- `react-native-reanimated`, `useAnimatedStyle`, `useAnimatedReaction`,
  `useSharedValue`, `withSpring`, `withTiming`, `withDecay`, `useDerivedValue`,
  `useAnimatedScrollHandler`, `scheduleOnUI`, `scheduleOnRN` in animation paths
- `@gorhom/bottom-sheet` animation config, `footerComponent`, attached footer /
  sheet open-close positioning
- Reanimated layout/entering/exiting, `@shopify/react-native-skia` canvas motion
  (craft only — GPU readback loops stay with React/RN pass)
- CSS/JS `transition`, `@keyframes`, `animation:`, Framer Motion / GSAP usage
- Scroll-driven UI motion (opacity/transform/gradient toggles tied to scroll),
  modal/drawer/toast open-close springs

Mark `skipped (not a motion PR)` when the diff is assets/locales/tests-only or
has no motion hunks after grep. **Do not** use motion pass for pure API/types/
business-logic refactors with zero animation surface.

**Motion vs React/RN split:** React/RN pass owns Reanimated correctness, list
perf, effect anti-patterns, and **Skia GPU readback**. Motion craft pass owns
**feel** (justified motion, frequency, easing/duration, interruptibility,
physicality, reduced-motion, cohesion) and outputs the skill's Block/Approve
verdict. Overlap on scroll→setState: RN pass = perf/thread; motion pass =
instant toggle vs fade, cohesion.

**Test pass rule:** Spawn when the three-dot diff touches test files
(`**/*.test.*`, `**/__tests__/**`, `**/__snapshots__/**`, test-dir
helpers/fixtures). Mark `skipped (no test hunks)` otherwise — a logic PR
with zero test changes does **not** spawn this pass; file coverage keeps a
one-line "missing tests" note. Inject `references/test-review-gate.md`
into the test prompt. Do not promote slop or gaps to 🟠+ without a proven
user-facing defect in the production diff; missing tests alone never reach 🟠.

## Ensemble model policy — MANDATORY

Zereight review subagents **always use the current session (parent) model**.
Do **not** hard-pin `composer-2.5`. Do **not** skip passes with
`skipped (model unavailable — composer-2.5 not exposed)`.

Override only when the user explicitly names a different model in the **same**
turn (e.g. “composer로 리뷰”, “fast로”).

**Canonical model id (default = session):**
- Cursor `Task` / `cursor_worker`: `inherit` (parent session model)
- Pi `subagent`: same model id as the parent session, or omit `model` so the
  runtime inherits the parent (prefer explicit parent id when the tool requires
  `model`)
- Coordinator (parent synthesis): current session model (no switch)

| Model | Use for |
| --- | --- |
| session / `inherit` | **All** ensemble passes (`reviewer`, `worker`, `delegate`) and coordinator synthesis |

### Runtime mapping — session model is non-negotiable

Every spawn must follow the **parent session model**. Do not pin a different
Composer tier, Grok, Claude, or fast variant unless the user asked for it in
this turn.

| Runtime | Required `model` on spawn | Forbidden (unless user asked this turn) |
| --- | --- | --- |
| Cursor `Task` / `cursor_worker` | `inherit` | Pinning `composer-2.5`, `composer-2.5-fast`, or another slug instead of session |
| Pi `subagent` | parent session model id (or omit to inherit) | Pinning a different provider/tier than the parent |
| Coordinator (parent synthesis) | Same session as the invoking turn | Switching models mid-review without user request |

**PROCESS VIOLATION:** skipping ensemble passes because `composer-2.5` is not
on the runtime whitelist, or refusing to spawn when `inherit` / parent model
is available.

**If a pinned override the user requested is rejected** (whitelist / schema):
fall back to session `inherit` / parent model and note it in `검증 결과`
(e.g. `requested composer-2.5 → fell back to inherit`). Never skip the whole
ensemble solely for model-id mismatch.

**Spawn checklist (every pass):**

1. Default: Cursor Task `model: "inherit"`; Pi = parent session model.
2. Do **not** skip for missing `composer-2.5`.
3. Only pass a non-`inherit` slug when the user named that model this turn.
4. Log actual models in `검증 결과` (e.g. `reviewer ×4 (inherit / <parent>)`).

**No model cascade on quota errors:** Do **not** configure or use
`fallbackModels` to hop providers on failure. On **429**, rate-limit, or quota
failure for a subagent spawn, **skip that pass** — do not retry the same pass
on another model. Continue synthesis from completed passes and note which axes
were skipped.

User-level overrides may live in `~/.pi/agent/settings.json` under
`subagents.agentOverrides`. Still prefer session/`inherit` on every spawn so
review passes match the model the user is already talking to.

Execution rules:

- Spawn separate subagents for the required review passes whenever the runtime
  supports subagents. Give each subagent the exact PR/range, target branch,
  repository path, the relevant instruction sources, and the **session model**
  (`inherit` / parent) from the table above.
- Every subagent must follow the repo `AGENTS.md` and global Codex instructions
  in addition to its review skill.
- Do not return the final review until every required pass has either completed,
  is explicitly skipped with a logged reason (429, not RN scope, etc.), or the
  user approved single-pass fallback per **Ensemble gate — MANDATORY** below.
- **PROCESS VIOLATION:** delivering a final review without spawning the full
  ensemble when subagent spawning is available (Pi `subagent`, Cursor `Task`,
  `cursor_worker`) and the user did not explicitly approve single-pass fallback.
- All review subagents must use Pi builtin agents (`reviewer`, `worker`,
  `delegate`) with session/`inherit` model. On Pi, if omitting `model` would
  default the builtin `worker` to Claude while the parent is not Claude, pass
  the parent model id explicitly.
- **Do not** route review passes through a different provider than the parent
  session unless the user explicitly requests that provider this turn.
- If a subagent fails with provider/model/quota errors (including **429**),
  **do not** retry on another model and **do not** use `fallbackModels`. Mark
  that pass as skipped, record the error briefly, and continue synthesis from
  completed passes — do not block the final review.

**Parallel spawn example (pi-subagents / `subagent` tool — parent session model):**

```json
{
  "tasks": [
    {
      "agent": "reviewer",
      "task": "Baseline full-diff review. Skill: code-review. Use parent session model. PR: ..."
    },
    {
      "agent": "reviewer",
      "task": "Regression and contract review. Skill: code-review-expert. Use parent session model. PR: ..."
    },
    {
      "agent": "worker",
      "task": "File coverage review. Skill: code-reviewer. Use parent session model. PR: ..."
    },
    {
      "agent": "worker",
      "task": "Quality gate review. Skill: code-review-and-quality. Use parent session model. PR: ..."
    },
    {
      "agent": "reviewer",
      "task": "Thermo-nuclear maintainability review. Skill: thermo-nuclear-code-quality-review + zereight-review references/direction-alternative-gate.md. Dual-path 1-line workarounds: prefer reorder or delete unused client, not extract dual-write helper. Use parent session model. PR: ..."
    },
    {
      "agent": "reviewer",
      "task": "Flow ownership & screen-role review. Read references/flow-ownership-review.md in zereight-review skill. Use parent session model. PR: ..."
    },
    {
      "agent": "reviewer",
      "task": "Ponytail simplicity review. Skill: ponytail-review + zereight-review references/direction-alternative-gate.md. On target-swap / dual-client hunks, grep sibling callers before Lean already. Use parent session model. PR: ..."
    },
    {
      "agent": "reviewer",
      "task": "Motion craft review. Skill: review-animations + STANDARDS.md (/Users/tao.exe/.claude/skills/review-animations/). Motion hunks only. Output Part 1 Before/After/Why table + Part 2 Block/Approve. Use parent session model. PR: ..."
    },
    {
      "agent": "reviewer",
      "task": "React/RN specialist review. Skill: zereight-react-native-optimizer. Include react-doctor JSON. Use parent session model. PR: ..."
    },
    {
      "agent": "worker",
      "task": "Test quality review. Read references/test-review-gate.md in zereight-review skill. Test hunks only: necessity, duplication/placement, slop, gaps. Use parent session model. PR: ..."
    }
  ],
  "concurrency": 10
}
```

Then spawn orchestration separately:

```json
{
  "agent": "delegate",
  "task": "Orchestration review: verify all ensemble axes were covered including direction-alternative A/B/C table. Use parent session model. ..."
}
```

(If the Pi tool requires an explicit `model`, set it to the **same id as the
parent session**, not a hard-coded Composer slug.)

**Parallel spawn example (Cursor `Task` tool — session inherit):**

```json
{
  "subagent_type": "generalPurpose",
  "model": "inherit",
  "description": "Baseline full-diff review",
  "prompt": "Skill: code-review. Use the parent session model (inherit). PR: ..."
}
```

Repeat for each ensemble pass (baseline, regression, file coverage, quality,
thermo-nuclear, **flow ownership**, **ponytail**, **motion craft**, React/RN, **test quality**)
with `model: "inherit"` on every `Task` call. Spawn orchestration `delegate`
after worker/reviewer passes. Never skip the ensemble because `composer-2.5`
is missing from the whitelist.

**Final synthesis must list models used**, e.g.
`reviewer ×7 (inherit / <parent>), worker ×3 (inherit / <parent>), delegate (inherit / <parent>)`.
If any pass ran on a different model than the session without a same-turn user
request, add `PROCESS VIOLATION: <pass> used <actual-model> (expected inherit/session)`.

## Ensemble gate — MANDATORY

Zereight-review **always** runs the full ensemble before synthesis. Treat
single-pass review as an exception, not the default.

**Required execution order (after PR Identity Gate succeeds):**

1. **PR Axis Gate** (A/B/C) — record in `검증 결과` before findings
2. react-doctor preflight (React/RN PRs — see below)
3. rnsec preflight (`rnsec` CLI for React Native security scope)
4. SonarLint preflight (`sonarlint-ls-cli` local scan, diff-scoped — no auth)
5. fuck-u-code preflight (`fuck-u-code` CLI + bounded `analyze`)
6. **Motion scope gate** — grep diff for motion triggers (see **Motion craft pass
   rule**). Record in `검증 결과` as `motion scope: yes — <triggers>` or
   `motion scope: no`. No CLI; scope only decides whether to spawn motion pass.
7. **Test scope gate** — grep diff for test files (`**/*.test.*`,
   `**/__tests__/**`, `**/__snapshots__/**`; see **Test pass rule**). Record
   in `검증 결과` as `test scope: yes — <files>` or `test scope: no`. No CLI;
   scope only decides whether to spawn the test pass.
8. **Direction Alternative Gate** — load `references/direction-alternative-gate.md`.
   On logic PRs, draft A (PR) / B (reorder) / C (delete a path) **before**
   trusting ensemble Approve. Grep sibling identifiers. Read existing PR
   comments as competing hypotheses, not as things to refute. Record the table
   in `검증 결과`. 1-line / single-file does **not** skip this gate.
9. **Navigation & caller-context gates** (when nav scope — see
   `references/navigation-review-gate.md`):
   - **Caller Context Gate** — grep production callers per changed nav symbol;
     fill caller table before any 🟠 navigation finding.
   - **Navigation Diff Gate** — separate **hop** vs **terminal** step
     (`push`/`replace`/`navigateToDestination`); never compare hop `navigate`
     with terminal `push` on a different target.
   - **Path tags** — tag findings (`resume-from-stem`, `in-flow-continuous`,
     `post-fr-success`, …); record in `검증 결과`.
   - **Scenario Matrix Gate** — before 🟠 stack/back findings; UNVERIFIED → max 🟡.
   Skip only when zero navigation hunks; record `navigation gate: skipped`.
10. Spawn all ensemble passes in parallel (or sequential if runtime limits concurrency)
11. Spawn orchestration `delegate` pass after worker/reviewer passes complete
12. Coordinator synthesis + `검증 결과` (re-check Axis Gate, Direction
    Alternative Gate, **caller/scenario gates**, **author observations**,
    **echo dedup** before Approve; do not promote “all passes agree” without
    per-path evidence)

**Subagent spawning counts as available** when any of these exist in the runtime:
Pi `subagent` tool, Cursor `Task` tool, `cursor_worker`, or equivalent multi-agent spawn.

**Single-pass fallback — DISALLOWED by default.** Use only when **all** of:

1. Subagent spawning is unavailable in the current runtime (none of the above).
2. User explicitly approved fallback in the **same** or immediately prior message:
   `single pass`, `fallback`, `앙상블 스킵`, `서브에이전트 없이`.
3. You record in `검증 결과`: `ensemble skipped (user-approved single-pass fallback)`.

When single-pass fallback is active, still:

- Load all reviewer instruction sources sequentially (including
  `thermo-nuclear-code-quality-review`, `references/flow-ownership-review.md`,
  `ponytail-review`, `review-animations` + `STANDARDS.md` when motion scope,
  `zereight-react-native-optimizer` when React/RN scope,
  `references/test-review-gate.md` when test scope, and
  `references/direction-alternative-gate.md` on logic PRs,
  `references/navigation-review-gate.md` when nav scope).
- Cover every ensemble axis in one pass (including flow ownership, ponytail,
  motion craft when in scope, test quality when in scope, and the Direction
  Alternative A/B/C table).
- Run react-doctor, rnsec, SonarLint, and fuck-u-code prefights when applicable.

**If subagent spawning IS available:** spawn every required pass. Partial
completion is allowed only per **Ensemble model policy** (429/quota → skip that
pass, note in synthesis). Completing the review from one coordinator pass alone
= **PROCESS VIOLATION**.

## Subagent Failure Budget — MANDATORY

Subagent claims are not primary evidence. A claim becomes a finding only
after current-turn primary evidence (diff, file contents, tests, CI logs,
rtk-grepped source, or reproducible output) confirms it.

Rules:

1. A subagent failure or stuck verification is not a blocker — it is a
   signal to move on.
2. If a verification path (e.g., live API call, official docs fetch) fails
   once, retry at most once **only when** the result is necessary for a
   P0/P1 decision.
3. If the same verification path fails 2 times total, stop pursuing it
   immediately. Do not try a third approach.
4. If 2+ subagent/verification attempts fail for the same claim, treat
   the claim as **unusable** for review purposes. Either discard it or
   note it as unverified residual risk — never as a blocker.
5. Never spend more than one bounded verification pass on any P2/🟡 Minor
   or lower concern.
6. When verification fails without logs, state "unverified; not used as
   blocker" and continue producing the final review.
7. Do not block the final review waiting for a subagent or verification
   to complete. Synthesize from what is already available, mark any gaps,
   and deliver.
8. **Exception:** **PR Identity Gate** hard stop overrides rules 1–7. When
   both mcporter and local API fail to fetch Bitbucket PR metadata, stop the
   entire review — do not synthesize findings from local git or subagents.
9. **Ensemble agreement ≠ evidence.** N subagents repeating the same claim
   only proves a shared premise. If that premise is “base branch is correct”
   on an axis-B PR, discard or demote until API/PRD/GIF/spec confirms it.
   Coordinator must re-check the PR Axis Gate before promoting any 🟠+.

- Keep raw diff output out of the conversation context when possible. Prefer
  context-mode indexing/search for large diffs, and use three-dot diff against
  the target branch.

## Tool transport — mcporter for MCP, CLI scanners (MANDATORY)

Use the right transport; do not route every tool through MCP.

| Need | Invocation |
| --- | --- |
| Bitbucket/Jira/Confluence/internal MCP tools | Shell `mcporter call <server>.<tool> ...` |
| MCP server inventory/schema | Shell `mcporter list` / `mcporter list <server> --schema` |
| fuck-u-code static analysis | Shell `fuck-u-code analyze ...` from global `eff-u-code` npm package |
| React Native security scan | Shell `rnsec scan ...` |
| SonarLint static analysis | Shell `sonarlint-ls-cli` (`scan.sh analyze --files <PR-changed-files>`) — local SLOOP backend, no server/auth/token; **not** SonarQube CLI (`sonar`) or `sonar-scanner`. Scope: `.ts/.tsx/.js/.jsx/.py/.java` only — Kotlin/Swift/Objective-C have no bundled analyzer (verified: silent zero findings, not an error) |

For MCP-backed tools, do **not** trust Cursor/Codex native MCP panel lists as
source of truth; use `mcporter` from shell.

For **fuck-u-code**, do **not** use MCP at all. Never call `mcp_call_tool`,
`mcporter list fuck-u-code`, or `mcporter call fuck-u-code.*`. The expected
binary after `npm install -g eff-u-code` is `fuck-u-code`; verify with:

```bash
command -v fuck-u-code
fuck-u-code --version
```

`Unknown MCP server 'fuck-u-code'` only means no MCP server is configured; it is
not a blocker. Use the CLI instead.

State **`fuck-u-code preflight run (CLI)`** in the final review when the CLI
analysis runs. State **`fuck-u-code preflight skipped (CLI unavailable — <reason>)`**
only when the `fuck-u-code` binary is missing or the CLI command fails.

For **rnsec**, use the CLI only. Verify with:

```bash
command -v rnsec
rnsec --version
```

State **`rnsec preflight run (CLI)`** when the scan runs. State
**`rnsec preflight skipped (CLI unavailable — <reason>)`** only when the binary
is missing or the CLI command fails.

For **SonarLint**, use **`sonarlint-ls-cli`** (local SLOOP backend via
`sonarlint-language-server`, no SonarQube/SonarCloud server, no token, no
project key). Verify prerequisites:

```bash
command -v curl
command -v python3
command -v git
```

State **`sonarlint preflight run (local CLI)`** when the diff-scoped scan runs.
State **`sonarlint preflight skipped (CLI unavailable — <reason>)`** when
`curl`/`python3`/`git` is missing or the scan fails after retry.

**Out of default preflight (do not use):**

- SonarQube CLI (`sonar`) / `sonar auth login` / SonarCloud project key — not
  needed; this preflight never leaves the machine.
- Legacy `sonar-scanner` — requires separate install + `sonar-project.properties`.
- Sonar MCP — Cursor/IDE integration only, not shell preflight.

Review preflight safeguards:

- Before broad file reading, use context-mode to reduce the diff to changed
  files/symbols and high-risk hunks. If CodeGraph MCP is available, run a
  bounded impact pass for changed symbols that need surrounding context:
  callers, usages, call chains, affected screens/hooks/navigation/API
  boundaries, and hotspot/coupling candidates. Treat CodeGraph output only as
  candidate discovery; every finding still needs current-turn primary evidence
  from the diff, file contents, tests, logs, or context-mode search.
- Do not use CodeGraph for Bitbucket/Jira/Confluence/internal connector reads;
  those remain mcporter-first with schema inspection. Do not use CodeGraph for
  large diff/log processing; those remain context-mode. Do not use CodeGraph as
  durable memory; agentmemory remains curated and verified only.
- If CodeGraph output is `_truncated`, stale, unresolved, or conflicts with file
  evidence, do not cite it as review evidence. Narrow the query once or fall
  back to context-mode plus file evidence.
- RTK command rewrites can fail silently for simple read commands such as
  `rtk rewrite "sed ..."`. If that happens, do not stall the review. Use the
  repo-approved RTK form when the hook provides one, prefer `rtk grep` /
  `rtk git` for searched or git commands, and keep direct file reads narrowly
  bounded when reading required instruction or skill files.
- If the nearest repo `AGENTS.md` is missing, do not treat that as permission to
  ignore repo instructions. Use any AGENTS instructions supplied in the current
  conversation as the repo instruction source, state that fallback, and continue.
- **MANDATORY: Run unnecessary-effect preflight for Effect PRs BEFORE ensemble
  synthesis.** Detect scope: any added/touched `useEffect` / `useBankXEffect` /
  `useBackgroundEffect` (or repo-equivalent wrappers) in `*.ts` / `*.tsx`,
  excluding `**/*.test.*`, `**/__snapshots__/**`, `**/locales/**`,
  `**/*.stories.*`. Follow `references/unnecessary-effect-preflight.md`
  (mapped harness run + fix / keep+justify / block triage). Unjustified keeps
  block the lint-introduction PR. Feed counts into the React/RN ensemble pass
  prompt. Silence without a `검증 결과` row = **PROCESS VIOLATION** (same
  discipline as react-doctor silence).
- **MANDATORY: Run react-doctor for React/RN PRs BEFORE ensemble synthesis.**
  Detect React/RN scope: any changed `*.ts` / `*.tsx` outside `**/*.test.*`,
  `**/__snapshots__/**`, `**/locales/**` only.
  - If **not** React/RN scope (assets/locales/tests-only): state
    `react-doctor skipped (not a React/RN logic PR)` in `검증 결과` and continue.
  - If React/RN scope, run from **PR review worktree** or confirm primary
    workspace `HEAD` equals PR source commit (network required):
    ```bash
    npx react-doctor@latest --json --no-score -y \
      --diff refs/remotes/origin/<destination>
    ```
    Run inside review worktree when primary workspace is on another branch.
    Wrong-branch scan → note in `검증 결과`; do not cite diagnostics as PR findings.
    Use PR metadata destination branch. When git refs are unavailable, use
    `--diff origin/develop` or the PR's known target branch. As a last resort,
    scan bounded parent path(s) of changed files (same parent-path rule as
    fuck-u-code — **never** full-workspace scan).
  - Parse JSON output; cross-check diagnostics against PR diff hunks and changed
    files only. Feed the JSON summary into the React/RN ensemble pass prompt.
  - Retry once on network/npx/timeout failure. After two failures, state
    `react-doctor preflight skipped (<reason>)` with exact command + error excerpt.
  - **PROCESS VIOLATION** on React/RN logic PRs if you skip react-doctor without
    a `검증 결과` row (same discipline as fuck-u-code silence).
  - Never promote react-doctor diagnostics to 🟠 Major or higher without
    file-content evidence from the current turn.
- **MANDATORY: Run rnsec for React Native security scope BEFORE ensemble
  synthesis.** Detect scope: any changed `*.ts` / `*.tsx` outside tests/locales,
  or RN/native/config files such as `package*.json`, `app.json`, `app.config.*`,
  `android/**`, `ios/**`, `*.plist`, `*.gradle`, `Podfile`, or
  `AndroidManifest.xml`.
  - If not RN security scope: state `rnsec skipped (not React Native security scope)`
    in `검증 결과` and continue.
  - If in scope, run in the review worktree/root:
    ```bash
    rnsec scan --path "<review-worktree>" --json \
      --changed-files refs/remotes/origin/<destination>
    ```
    Use PR metadata destination branch. If git refs are unavailable, run once
    without `--changed-files` in the review worktree and filter results to PR
    changed files before reporting.
  - Parse JSON output; report only issues touching changed files or clearly
    introduced by changed config. Feed the summary into the security/quality
    review pass prompts.
  - Retry once on timeout/CLI failure. After two failures, state
    `rnsec preflight skipped (CLI — <reason>)` with exact command + error excerpt.
  - Never promote rnsec diagnostics to 🟠 Major or higher without current-turn
    file-content/diff evidence and a concrete exploit or user-data impact.
- **MANDATORY: Run SonarLint local preflight (`sonarlint-ls-cli`) BEFORE
  ensemble synthesis.** Run in the review worktree only; do not scan the
  primary workspace. This replaces the old SonarQube CLI (`sonar`) preflight —
  fully local, no auth, no SonarCloud project key, diff-scoped only.
  - **Availability gate** (all must pass to run; otherwise skip with reason):
    ```bash
    command -v curl && command -v python3 && command -v git
    ```
    If any is missing: state
    `sonarlint preflight skipped (CLI unavailable — <missing tool> not in PATH)`
    and continue.
  - **Diff-scoped file list** — PR changed files only, supported extensions
    (`.ts .tsx .js .jsx .py .java`), excluding `**/*.test.*`, `**/__snapshots__/**`,
    `**/locales/**`:
    ```bash
    mapfile -t SONARLINT_FILES < <(git diff --name-only --diff-filter=ACMR \
      "refs/remotes/origin/<destination>...HEAD" -- '*.ts' '*.tsx' '*.js' '*.jsx' '*.py' '*.java' \
      | grep -vE '\.test\.|__snapshots__|/locales/')
    ```
    Use PR metadata destination branch. If git refs are unavailable, fall back
    to `git diff --name-only <base>...HEAD` with the PR's known target branch.
    If `SONARLINT_FILES` is empty, state
    `sonarlint skipped (no PR-changed .ts/.tsx/.js/.jsx/.py/.java files)` and continue.
  - **Kotlin / Swift / Objective-C are NOT in scope for this preflight —
    verified empirically, do not attempt to add them.** The bundled
    `sonarlint-vscode` analyzer set (`~/.sonarlint-ls/analyzers/*.jar`) has no
    Kotlin analyzer at all, and `sonarcfamily.jar` (Swift/Objective-C/C/C++) is
    shipped as `.jar.asc` — license-locked, inert without a paid Connected
    Mode. Feeding these files through the scanner does not error, it silently
    returns **zero findings**, which reads as false-clean and is worse than
    skipping. If the PR touches `.kt/.kts/.swift/.m/.mm/.h`, review those files
    manually in the ensemble passes and state
    `sonarlint scope note (.kt/.swift/.m/.mm — no local analyzer, reviewed manually)`
    in `검증 결과`; do not claim SonarLint coverage for them.
  - **One-time upstream bugfix (idempotent, local cache only):** upstream
    `sonarlint-ls-cli`'s `scan.py` hardcodes `languageId: "python"` for every
    file, which makes non-Python files fail as `ParsingError`. Patch the
    cached copy once per machine before the first scan:
    ```bash
    SCAN_PY="$HOME/.sonarlint-ls/sonarlint-ls-cli/scan.py"
    if [ -f "$SCAN_PY" ] && ! grep -q LANGUAGE_ID_BY_SUFFIX "$SCAN_PY"; then
      python3 - "$SCAN_PY" <<'PYEOF'
import pathlib, sys
p = pathlib.Path(sys.argv[1])
src = p.read_text()
src = src.replace(
    "ERRORS = False\n",
    "ERRORS = False\n\n"
    "LANGUAGE_ID_BY_SUFFIX = {\n"
    '    ".py": "python", ".js": "javascript", ".jsx": "javascript",\n'
    '    ".mjs": "javascript", ".cjs": "javascript", ".ts": "typescript",\n'
    '    ".tsx": "typescriptreact", ".java": "java",\n'
    "}\n\n"
    "def get_language_id(file):\n"
    '    return LANGUAGE_ID_BY_SUFFIX.get(pathlib.Path(file).suffix, "python")\n',
    1,
)
src = src.replace('"languageId": "python",', '"languageId": get_language_id(file),')
p.write_text(src)
PYEOF
    fi
    ```
    If `~/.sonarlint-ls/sonarlint-ls-cli/scan.py` does not exist yet, the first
    `scan.sh` invocation below bootstraps it (clone + venv); re-run this patch
    check once after bootstrap, before trusting non-Python results. Java
    analysis works standalone (bundled `sonarjava.jar`, verified with real
    findings e.g. `java:S2259` nullability) and logs a harmless
    `sonarlint/getJavaConfig Method Not Found` warning — ignore it, it does not
    block diagnostics.
  - **Run the scan** (noisy style-only rules disabled by default — this repo's
    prettier/eslint conventions already own semicolons/trailing commas):
    ```bash
    SONARLINT_DISABLE_RULES="${SONARLINT_DISABLE_RULES:-typescript:S1438,typescript:S1537,javascript:S1438,javascript:S1537}"
    curl -s https://raw.githubusercontent.com/vincentfenet/sonarlint-ls-cli/refs/heads/master/scan.sh \
      | bash -s -- analyze --disable-rules "$SONARLINT_DISABLE_RULES" --files "${SONARLINT_FILES[@]}"
    ```
  - Parse stdout lines (`<file>:<line>:<col> - <message> (<rule>)`). Filter to
    lines that fall inside PR diff hunks — lines outside changed hunks are
    ⚪ Info (pre-existing), not PR regressions.
  - Treat SonarLint output as **candidate discovery only**. Promote to
    🟠 Major or higher only with current-turn file/diff evidence (e.g. real
    `any` usage introducing type-safety risk, genuine high complexity in a
    changed function — not just the rule firing).
  - Retry once on timeout/bootstrap failure (first run downloads a ~200MB
    `sonarlint-vscode` VSIX and clones the CLI repo). After two failures, state
    `sonarlint preflight skipped (CLI — <reason>)` with exact command + error
    excerpt.
- **MANDATORY: Check fuck-u-code CLI availability BEFORE any preflight or
  ensemble step.** Run **`command -v fuck-u-code`** (binary installed by
  `npm install -g eff-u-code`). Do NOT use MCP for this gate. Do NOT call
  `mcporter list fuck-u-code`, `mcporter call fuck-u-code.*`, or `mcp_call_tool`.
  - If the CLI exists AND the PR has substantial logic changes (not just
    locales/styles/tests/assets-only), run the bounded static analysis below
    via **`fuck-u-code analyze`**.
  - If the CLI is missing or fails: state
    "`fuck-u-code preflight skipped (CLI unavailable — <reason>)`" and
    continue. Do NOT block the review.
  - If the CLI exists but you skip analysis without a PR-scoped reason:
    **PROCESS VIOLATION**. The preflight line must be either
    **`fuck-u-code preflight run (CLI)`** or **`skipped (reason)`**. Silence is
    not permitted.
  1. From the three-dot diff or PR metadata, extract the list of changed files.
     Filter to `*.ts`, `*.tsx` only; exclude `**/*.test.*`, `**/__snapshots__/**`,
     `**/locales/**`, `dist/`, `node_modules/`.
  2. Determine the common parent path(s) of the changed files (typically 1-2).
     Never scan the entire workspace — only the bounded paths. If changed
     files span multiple disjoint paths, run the analysis for each path.
  3. Invoke `analyze` through the CLI:
     ```bash
     fuck-u-code analyze "<common-parent-path>" \
       --format json \
       --top 15 \
       --exclude "**/*.test.*" "**/__snapshots__/**" "**/locales/**" "dist/**" "node_modules/**"
     ```
  4. From the JSON output, extract `files[].path`, `files[].score`, and
     `files[].metrics[]`. Keep only files that appear in both the PR diff AND
     the worst-scoring list.
  5. Read the full content of those files (not just the diff) to understand
     whether the PR is introducing new complexity/duplication or inheriting
     existing legacy. Check: does the new code worsen the metrics?
  6. If the PR inherits existing legacy (file was already bad before this PR),
     note it as ⚪ Info — do not block. If the PR introduces new hotspots
     (complexity/duplication without justification), report as 🟡 Minor.
  7. Never promote fuck-u-code scores to primary findings without file-content
     evidence. Never cite fuck-u-code score alone as 🟠 Major or higher.
  8. On CLI failure (timeout, unavailable, schema mismatch), skip preflight with
     "`fuck-u-code preflight skipped (CLI — <reason>)`" and continue. Do not
     retry more than once.
  9. The `ai-review` subcommand is excluded from the default pipeline — it sends
     code to external APIs and duplicates the zereight ensemble.
- When spawning review subagents, do not combine `fork_context=true` with an
  explicit `agent_type` if the runtime rejects that combination. Retry by
  spawning role-specific agents without `fork_context` and put the exact PR
  range, repository path, target branch, and required instruction sources in
  each agent prompt.
- Never use ambiguous branch names such as `origin/develop` for review diffs if
  local refs can shadow remote refs. Resolve and use full refs:
  `refs/remotes/origin/<target>...refs/remotes/origin/<source>`. If an
  ambiguous ref caused an unexpectedly large diff, discard that result and
  restart scoping from the full-ref three-dot diff.

Synthesis rules:

- Merge findings from all subagents into one final review (including
  thermo-nuclear structural/maintainability findings).
- Map thermo-nuclear **presumptive blockers** (1k-line explosion, spaghetti
  special-case growth, missed code-judo simplification, boundary leaks) into
  zereight severity when primary evidence confirms: structural regression with
  user-facing risk → 🟠 Major; maintainability-only → 🟡 Minor or 🛠️ refactor;
  decomposition opportunity with no behavior risk → 🔵 Trivial. Do not promote
  thermo tone alone without file/line evidence.
- De-duplicate overlapping findings and keep the strongest, most concrete file
  and line reference.
- If reviewers disagree, state the disagreement briefly and choose the outcome
  supported by code evidence.
- Preserve whole-diff coverage by listing changed files as `comment-worthy` or
  `no comment`.
- Lead with actionable findings ordered by severity. Keep summaries secondary.

## RED Team Mindset -- MANDATORY

You are an adversary, not a rubber stamp. Your job is to break the code, not confirm it works.

- **Think like an attacker**: For every change, ask "How can this fail? How can this be exploited? What input breaks this?"
- **Never trust the happy path**: Code that works for expected inputs is the baseline, not 

…(truncated)
