# Coding Standards

> Coding standards for writing, editing, and reviewing code. Routes to language/framework-specific rules (Next.js, NestJS, Laravel, vanilla JS/TS, NativeScript, React Native/Expo, C#/.NET, Node Express/Fastify, Cocos Creator, Vue/Nuxt, Spring Boot, Django, FastAPI, Flask, Go HTTP) PLUS universal clean-code rules (functions, naming, objects/data, formatting, error handling, SOLID/KISS/DRY, universal structural rules) that apply to every language. Consult before any code change. Use when the user says "write a component", "add an endpoint", "refactor this", "review this diff/PR", or "is this clean?". Make sure to consult this skill for ANY code authoring or review task, even when the user does not explicitly ask for "standards" — every write/edit/review must comply.

- Skill: `willey-labs/coding-standards` (Agent Skill, multi-file: 132 files)
- Install (CLI): `npx skillmds@latest add willey-labs/coding-standards`
- Raw SKILL.md: https://api.skillmd.com/api/skills/willey-labs/coding-standards/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- License: MIT
- Author: willey-labs (https://skillmd.com/u/willey-labs)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/willey-labs/coding-standards

---


# Coding Standards

Every line you write, edit, or review must comply with these rules. They come in two sets, and you
apply **common + exactly one framework** on every task:

- **Universal rules** (`references/common/`) — clean-code principles that govern the *inside* of every
  function, class, and module, regardless of language.
- **Per-framework rules** (`references/<framework>/`) — folder layout and framework patterns that govern
  the *outside*: where files live and what folders mean.

All paths in this document are relative to this SKILL.md file, so they resolve wherever the skill is
installed.

The flow: **bootstrap (once) → skip exclusions → pick a mode → detect framework → resolve structure →
pick execution shape → open a task list → run the branch**. Steps 0–6 are that sequence; Step 7 is the
branch (7a pipeline, 7b inline).

---

## Step 0 — Bootstrap the enforcement hooks (once per session, only if needed)

Run the fast read-only check first (single absolute-path command, no `cd`/`&&` — it matches the
pre-approved permission rule, so it won't prompt):

```bash
python3 <skill-dir>/bootstrap.py --verify
```

Exit 0 → hooks are wired; go to Step 1. Non-zero → run the full install and act on its output:

```bash
python3 <skill-dir>/bootstrap.py --auto-install
```

- `Wired` / `Updated` / `Install OK` → tell the user to **restart the session** so hooks activate.
  **Until they do, the PreToolUse hooks are NOT active in *this* session** (Claude Code reads
  `settings.json` at session start), so a Write here won't be blocked. This is the unenforced-first-session
  gap. Close it: for any code you write or review in this session, run the linter yourself over the touched
  files as a compensating check before reporting done —
  `python3 <skill-dir>/hooks/review-files.py <file> …` works immediately, no restart needed — and fix what
  it finds. Tell the user write-time blocking starts next session; this session is covered by the manual
  linter pass.
- `Blocking issues:` → surface it verbatim and **stop** until the user resolves it.
- `cannot determine install scope` → the skill is outside a `.claude/skills/` tree; point at `README.md`
  and continue without write-time blocking — the rules still apply, and `review-files.py` still runs as a
  manual linter over what you touch.

The install self-detects project vs global scope and auto-installs the skill's required packages. Flags,
the venv/PEP-668 fallback, and the readiness breakdown live in `references/bootstrap.md` — read it only
if bootstrap misbehaves.

---

## Step 1 — Skip excluded files (always)

Some files are owned by third-party tooling, not the user — editing them breaks the upgrade path or churns
generated code. A file is excluded if **any** of these hold:

1. Its path matches a built-in default (installed deps, generated code, build output, lock files, ORM
   migrations, shadcn `components/ui/**`, the skill's own `.coding-standards/**` reports). Full list:
   `hooks/_exclusions.py` → `DEFAULT_EXCLUSIONS`.
2. Its first 10 lines carry a generation marker (`@generated`, `DO NOT EDIT`, `Code generated by`, …).
3. It matches a pattern in the project's `.coding-standards-ignore` (gitignore-style, at the repo root,
   seeded by bootstrap).

Check by inspection: the path against the default list, the marker in the file you're reading anyway,
the ignore file if one exists. Review and fix scope you don't filter by hand — `hooks/review-files.py`
skips excluded files itself, and the write-time hooks exit silently on them.

Refuse to modify an excluded file. If the user explicitly asks to edit one, warn that the file is
tool-owned and changes will be lost on regeneration, then proceed only after consent.

---

## Step 2 — Pick a mode (only on contextless activation)

**Skip this** if the user's message already names a task — "write X", "refactor Y", "review this PR",
"is this clean?", "what does FN-005 mean?". Those phrases *are* the mode; go to Step 3.

**Trigger it** only when the skill activated with no clear task: bare `/coding-standards`, "what does this
skill do?", or a message too generic to infer mode. Ask with `AskUserQuestion`, using the exact
mode-picker payload in `references/activation.md` — the labels are what the routing below matches on.

Route the answer:

- **Write code that follows these rules** → Write mode, full flow.
- **Check existing code against these rules** → ask *what* to check (file, folder, diff, PR). Once the user
  answers, the scope is known — so **build the whole-workflow task list now, before any reviewing starts**
  (Step 6), with *resolve + record structure* as item 1, and fold any extra targets the user named in as
  more items.
- **Show me the rules** → resolve framework + structure silently, load references, present a one-screen
  rule index. No structure question, no run-mode question — nothing is written.

There is no picker entry for **Fix** — it's triggered by phrasing ("fix the findings" / "apply the
review", or "continue the fix" / "resume the fix" to pick up a non-done milestone plan), which routes
straight to Fix mode.

Ask at most once per session; once mode is set, it stays set. Never ask when the user already named a
task.

---

## Step 3 — Detect the framework

Look at the file you're acting on and match the signals below. **Stop at the first match whose "owns file
types" includes the extension of the file you're editing.** A row whose file types don't include the
current file is skipped even if its repo-level signal is present — so editing a `.php` file in a
Laravel + Inertia/Vue repo resolves to `laravel`, not `vue-nuxt`, and a `Component.vue` in the same repo
resolves to `vue-nuxt`. This is the rule; the "more specific" note below only breaks ties *within* one
language.

| Framework key | Owns file types | Detection signals (any of these) |
|---|---|---|
| `nextjs` | `.ts .tsx .js .jsx` | `next.config.{js,ts,mjs}` at repo root **or** `next` in `package.json` deps **or** the file lives under `app/` or `pages/` next to that config |
| `react-native` | `.ts .tsx .js .jsx` | `expo`, `react-native`, or `@expo/*` in `package.json` **or** `app.json` with `"expo"` key **or** `metro.config.js` |
| `nativescript` | `.ts .js .xml` | `nativescript.config.{js,ts}` or `nativescript` in `package.json` **or** a `.xml` file paired with a `.ts` page |
| `cocos-creator` | `.ts .js` | `assets/` + `settings/` + (`library/` or `temp/` in `.gitignore`) at repo root **or** `cc` / `cocos-creator` import **or** `.scene` / `.prefab` files |
| `vue-nuxt` | `.vue .ts .js` | `vue` or `nuxt` in `package.json` **or** `nuxt.config.{ts,js}` **or** `.vue` files |
| `nestjs` | `.ts` | `@nestjs/*` in `package.json` **or** `*.module.ts` / `*.controller.ts` / `*.service.ts` with NestJS decorator imports |
| `node-express` | `.ts .js` | `express` or `fastify` in `package.json` **and** no NestJS |
| `laravel` | `.php` | `composer.json` with `laravel/framework` **or** an `artisan` file at root **or** `.php` under `app/` |
| `csharp` | `.cs` | `*.csproj`, `*.sln`, `*.cs` files |
| `spring-boot` | `.java .kt` | `pom.xml` with `spring-boot-starter-*` **or** Gradle with the Spring Boot plugin **or** `@SpringBootApplication` |
| `django` | `.py` | `manage.py` + a settings module **or** `django` in `pyproject.toml` / `requirements.txt` |
| `fastapi` | `.py` | `fastapi` in deps **or** `from fastapi import FastAPI` **and** not Django |
| `flask` | `.py` | `flask` in deps **or** `from flask import Flask` **and** not Django/FastAPI |
| `go-http` | `.go` | `go.mod` + a router (`gin`, `echo`, `fiber`, `chi`, `mux`) or net/http handler routing |
| `unsupported` | (any) | A framework/ecosystem the skill recognizes but has **no structure reference** for. Web: Angular (`@angular/core` / `angular.json`), Svelte / SvelteKit (`.svelte`, `svelte` in `package.json`, `svelte.config.*`), Astro (`astro` dep / `astro.config.*` / `.astro`), Remix (`@remix-run/*`), Ember, SolidStart, Qwik. Game engines: Unity (`Assets/` + `ProjectSettings/`), Godot (`project.godot`). Other ecosystems not yet covered in v5: Ruby/Rails, Rust, Swift/iOS, Flutter/Dart, Android native. … |
| `vanilla-js` | `.ts .js` | Plain `.ts` / `.js` that fits none of the above **and is not one of the recognized-unsupported frameworks** (libraries, CLIs, scripts, browserless projects) |

- **If two rows of the SAME language could apply** (e.g. a `.ts` that's both Next.js and vue-nuxt-eligible),
  pick the more specific one (a `.tsx` in a Next.js repo is `nextjs`, not `react-native`). The file-type
  gate above already separates different languages — this only breaks within-language ties.
- **Monorepos** pick the framework **per file**, not per repo — walk up from the file until a signal
  matches whose file types include the file. `apps/web/...` → `nextjs`; `apps/api/...` → `nestjs`.
- **Engine/ecosystem override (checked FIRST):** if the project shows a game-engine marker — Unity
  (`Assets/` + `ProjectSettings/`) or Godot (`project.godot`) — route to `unsupported`, even though a
  `.cs` would otherwise match `csharp`. The `csharp` row's vertical-slice web layout is wrong advice for a
  Unity project, so the engine signal wins. `common/` line rules still apply; structure review is declined.
- **Plain libraries** with no framework signal default to `vanilla-js` (JS/TS) or `common/` only (Python).
- **Recognized but unsupported** (the `unsupported` row): **say so and do NOT fall back to `vanilla-js`** —
  imposing vanilla-js's business-folder + barrel layout on an Angular or SvelteKit app actively fights the
  framework's own conventions, which is worse than declining. Instead: apply all of `common/` (it's
  universal — the line-level rules and the write-time hooks still enforce on the language), keep the
  project's **existing** layout for placement, and tell the user the skill has no structure reference for
  this framework yet so structural/placement review is limited to `common/structure.md` (ST-*), not a
  framework-specific shape. Skip the Step 4 structure question (there's no catalog to offer).
- **If you can't tell**, ask once — don't guess across frameworks.

---

## Step 4 — Resolve the project structure (the outer shell)

This resolves the **outer folder layout** — where the top folders sit and what they're called. It decides
*placement* only; the inside of every folder still follows `common/structure.md` (business → feature →
sub-feature → unit), whichever shell is chosen. Follow what the project already uses (the framework's
scaffold, or the layout that's there); the choice is remembered in a `.coding-standards-structure` file
so the user is asked at most once.

**Comprehend the structure once, then trust the record.** When `.coding-standards-structure` does **not**
exist, comprehend the structure (build and confirm the map, `references/structure-map.md`) and record the
resolved layout in it. When it **does** exist, follow it and do **not** re-derive or propose restructuring
— ordinary write/review runs check code *against* the recorded structure, they never re-open it. Re-run
the full structure comprehension (then update the record) **only** when the user explicitly asks to
restructure or review the structure — "restructure this", "review the structure", "show me the structure
tree". A normal task ("add X", "review this PR", "is this clean?") is not that request.

The decision in brief:

1. **File exists** at the framework project root → read it and follow it (a `follows: <standard>` target,
   or a described custom layout). No question. If the file is non-canonical — carries comments, a `hooks:`
   block, or any rule toggle — **normalise it in place** (keep only the `follows:` line / `layout:` body),
   write it back, and report it.
2. **No file, folders match a standard** → use that standard's reference, and **record it** — write
   `follows: <standard>` plus the full `layout:` tree, so later runs follow it instead of re-comprehending. No question.
3. **No file, custom layout** → ask the user once with `AskUserQuestion` (recommended structure first,
   "keep current" last), then write the file recording their choice.

The file records **placement only** — a `follows:` line and/or a full `layout:` tree (the actual solved
structure; a project may carry both). It never carries rule toggles: every rule is always enforced,
deep-import is derived from whether a barrel exists, and the ST-008 size/folder checks run at fixed
thresholds. `block-structure-file-violations.py` enforces this.

Read `references/structure-resolution.md` before acting on case 3, a monorepo, or a non-canonical file.
It has the full mechanics: monorepo file placement (the sub-project root, not the repo root), the question
shapes, what "keep current" does and doesn't exempt, the self-heal normalisation, and the messy-project
fallback.

The resolved structure replaces `references/<framework>/structure.md` in the Step 7b load list, and the
pipeline passes it to Worker 1 as `STRUCTURE`. For "Show me the rules" / pure Q&A, resolve silently —
don't ask or write a file.

---

## Step 5 — Pick the execution shape (orchestrator pipeline vs inline)

Two shapes for Write and Review. Resolve Step 4 first — structure is always the first question, run-mode
the second.

| Trigger | Shape |
|---|---|
| Single-file edit (≤30 lines), single-function refactor, or rule Q&A | **Inline** — you do it yourself. Steps 6 → 7b. |
| 2+ files, a new feature, a diff/PR review, `--thorough`, or the `/coding-standards` command | **Orchestrator pipeline** — you dispatch workers. Steps 6 → 7a. |
| `Agent` tool unavailable in this host (Cursor, Codex, OpenCode) | **Inline** regardless of scope — flag it in the routing line. |
| Apply review findings ("fix the findings", "continue the fix" / "resume the fix") | **Orchestrator pipeline, `MODE: fix`, always.** No run-mode question. |

The choice is made one of two ways:

**A) Invoked via `/coding-standards` or the Step 2 picker, and `Agent` is available** → ask the run-mode
question with the exact payload in `references/activation.md`. "Multiple agents" → pipeline (7a);
"Single agent" → inline (7b). Ask at most once per session; reuse the answer afterward.

**B) Plain message (no command)** → decide from the table.

### Announce the routing — one line, before the substantive work

Once mode, framework, structure, and shape are resolved, emit a single line so the user sees the route:

```
coding-standards: framework=nextjs · structure=route-colocated (matched) · shape=pipeline (2+ files)
```

Name the shape's trigger (the table row, or "user choice"), and mark how structure resolved — `(matched)`,
`(file)`, or `(asked)`. Pure rule Q&A skips the line; there's nothing to route.

---

## Step 6 — Track the run with a task list

On any real work — writing, editing, refactoring, or reviewing — open the task list **up front, the moment
the scope is known**: for the Step 2 picker path, right after the "what to review / write" answer; for a
plain message ("review this PR"), as soon as you've identified the files. Open it **before Steps 3–4**, so
framework detection and *resolve + record structure* land on the list as the **first tracked items**, not
pre-work that runs before any list exists. The list is what makes the standards visible — the user sees
each stage applied instead of trusting it happened. Use the host's task-list tool (`TodoWrite`,
`TaskCreate`/`TaskUpdate`, …); skip the list only if the host has none, and skip it for pure rule Q&A —
there's no multi-step work to track.

Build the **whole** workflow at once, then extend it with any extra targets the user named. Track the work
the user cares about (fold in real file/feature names), keep exactly one item `in_progress`, and complete
it before starting the next. A typical review list: **resolve + record structure → detect framework →
load rules → review → run hooks → write report**. A typical write list: **resolve + record structure →
detect framework → read existing code → load rules → draft → rewrite the draft → sweep the rules → write
the files**. The first item, *resolve + record structure*, may be
marked `completed` **only when `.coding-standards-structure` exists** at the resolved project root —
resolved one of three ways: matched a standard, asked-and-recorded, or a skip-reason logged (recognized-
unsupported framework, or below the scope threshold). Having run a structure-comprehension agent is **not**
completion; the file on disk is. The pipeline and Fix shapes add their worker/ledger stages — see
`orchestrator-pipeline.md`. A milestone-driven fix adds one item per milestone at plan approval — a display
mirror only; the plan file on disk stays the source of truth.

---

## Step 7a — Pipeline branch: orchestrate the workers

You (the main agent) become the **orchestrator**: you coordinate three sequential workers and do the final
Write yourself, so the hooks fire exactly once on the complete code. **Read
`references/orchestrator-pipeline.md` and follow it** — that's the full protocol (worker roster,
Write/Review/Fix pipeline shapes, dispatch loop, validation, retry/fallback, summary).

Invariants, true even before you open the reference:

- **Comprehend before you check.** Above the scope threshold *and* when the structure isn't already
  recorded in `.coding-standards-structure` (or the user explicitly asked to restructure / review the
  structure — see Step 4), build and confirm the structure map (`references/structure-map.md`) before
  dispatching Worker 1; pass it as `STRUCTURE_MAP`. When a record already exists and no such request was
  made, skip the map and pass the recorded structure as `STRUCTURE` — don't re-open the layout.
  Cross-feature structure (duplication, mislabeled nesting, split features, themed-cluster promotion) is
  found by diffing the real tree against the map — a per-file worker cannot see it.
- **Workers never call `Write`/`Edit`.** They emit code/findings as JSON; only you write to disk.
- **Sequential, not parallel.** Worker 1 (Structure) → Worker 2 (Quality) → Worker 3 (Failure); each one's
  output is the next one's input.
- **No retries past 2.** Twice-failed validation or unparseable JSON → fall back to inline.

---

## Step 7b — Inline branch: load the references, then apply

Before writing or reviewing any code, read these fully — once per session, not once per task:

1. **All eight `common/` files** (always): `functions.md`, `naming.md`, `objects-and-data.md`,
   `formatting.md`, `comments.md`, `error-handling.md`, `code-principles.md`, `structure.md`.
2. **The resolved structure** (from Step 4) — a `structures/<name>.md` variant or
   `references/<framework>/structure.md`.

Read them fully because the judgement lives in the worked examples, not the rule names. Recalling "keep
functions small" misapplies FN-001; the examples show where the line actually sits.

Then apply each rule at its scope: **common governs the inside of code; the resolved structure governs the
outside** (file placement, folder names, public APIs). When the two seem to conflict, that scope split is
the answer — a framework entry file is both thin (the framework rule) *and* the function it exports is
short (the common rule).

---

## Modes: Write, Review, Fix

### Write

Writing gets the same rule-by-rule walk as reviewing. Most `common/` rules have no write-time hook, so a
rule you don't name is a rule you don't apply. Seed these steps into the Step 6 task list. Step 1 runs once
per area, not once per file.

1. **Read the existing code.** Open the 2-3 files closest to where the new code lands: those in the
   destination folder, else the nearest comparable feature in the same language. Note the project's verb
   for each recurring operation, what an entry file exports, how a feature divides into units, which domain
   error types exist, how imports are ordered. **A rule beats the project's convention; the project's
   convention beats the default you would otherwise reach for.** An existing file that breaks a rule stays
   as it is; a write task does not reorganize what is already there. In a genuinely new area you set the
   vocabulary, so keep it consistent across every file you write.
2. **Load the references** (Step 7b): all eight `common/` files plus the resolved structure.
3. **Draft it.** Get the behavior right first. A messy first draft is permitted (FN-012).
4. **Rewrite the draft.** Reread each file as its first reader: split the function you excused at 25 lines,
   replace the name you settled for, delete the parameter nobody needs.
5. **Sweep the rules one at a time.** Walk `common/` against what you wrote and file each rule under
   applied, already met, or not applicable with a reason. Re-read the reference for any rule you had not
   considered before this step. Report the buckets in your reply, not in the file.
6. **Fix what you find now.** A violation ships fixed or does not ship. Never pair one with a `TODO`.

**Write no comments by default** (`comments.md`). Say it in the names and the shape of the code. A sentence
earns a place in the file only when it carries what the code cannot — a constraint, a rationale, an external
reference, a sharp edge. Never narrate the code, never narrate your edit, and never leave the conversation
behind in the file: no `as requested`, no `I think`, no `we could also`, no untracked `TODO`, no emoji, no
`Note:` preamble. If a thought belongs in the reply to the user, put it there and leave the file clean.

A separate model judges the comments a turn wrote before that turn can end (`hooks/judge-comments.py`),
so a comment that doesn't earn its place comes back as a fix to apply, not a note to ignore. Write it
right the first time and the judge stays silent — it costs one short model call per turn that touched
code, and none at all on a turn whose files gained no comments.

**Always author and modify code through the `Write` / `Edit` / `MultiEdit` tools — never by shell
redirection** (`> file`, `>>`, `tee`, `sed -i`, `cat <<EOF > file`). The enforcement hooks fire **only** on
Write/Edit/MultiEdit; a file written through the shell silently bypasses every one of them. This is a real
hole in the enforcement perimeter, and the only thing closing it for shell writes is this instruction — so
honor it. If some tool genuinely must generate a source file outside the Write path, run
`python3 <skill-dir>/hooks/review-files.py <file>` over the result and fix what it reports.

### Review

Walk the rules systematically — don't freelance. Seed the Step 6 list first, the moment you know what's
in scope and **before** you start reviewing; the numbered steps map onto it, and step 0 is the list's
first item.

0. **Resolve + record the structure — the first task item, done only when `.coding-standards-structure`
   exists.** Above the scope threshold, and only when it isn't already recorded: if
   `.coding-standards-structure` already records the structure and the user didn't ask to restructure /
   review the structure, **skip this** — follow the recorded structure and review code against it; don't
   re-open the layout. Otherwise build the structure map (`references/structure-map.md`) over the tree,
   confirm it with the user once, persist it to `.coding-standards/structure-map.md`, and record the
   resolved layout in `.coding-standards-structure`. Hand the map to the structure worker as
   `STRUCTURE_MAP`: cross-feature findings (duplication, misnested peers, split features, themed-cluster
   promotion) are diffs against it, which a per-file pass can't see. Skipped below the threshold — say that
   cross-feature structural checks were not run.
1. **Scope + resolve structure.** List each file in the diff; detect its framework (Step 3) and resolve
   structure (Step 4).
2. **Load references.** Every `common/` file, plus the resolved structure for each framework in the diff.
3. **Judgement pass** — the rules regex/AST *can't* catch (FN-001 length nuance, FN-009 CQS, OD-003
   Demeter, EH-002 boundaries, the CM-* comment-prose rules, the `structure.md` rules). Per rule, report `PASS`, a finding as
   `file.tsx:42 — <rule> — <what's wrong>`, or `SKIPPED — <why it doesn't apply>`.
4. **Run the hooks as a linter** (deterministic pass, LAST — don't skip). The `block-*.py` hooks only fire
   on Write/Edit, so a review must invoke them explicitly:
   ```bash
   python3 <skill-dir>/hooks/review-files.py <file> [<file> ...]
   # diff:   git diff --name-only | python3 <skill-dir>/hooks/review-files.py --stdin
   # pipeline: add --json and parse per file
   ```
   It applies the same write-time contract (`any`, Hungarian, 4+/5+ args, swallowed errors, junk-drawer
   paths, deep imports, the TS/Python AST checks) and skips excluded files. `review-files.py` self-selects
   an interpreter that can load the TS/JS grammars (its bundled venv if the launching `python3` lacks them)
   and flags the gap loudly if none can — it never silently reports a TS file clean. **Every finding it
   returns is a violation to fix:** the *existence* of the finding is deterministic and never re-litigated
   (an `any` is an `any`). For the ST-008 decl-count block, the *remedy* is the reviewer's judgement — a
   cohesive split, OR a recorded exemption (`.coding-standards-ignore` + reason, logged `accepted`) when the
   file is one cohesive job the proxy miscounts. A split that creates scatter or copies a sibling's
   machinery is itself an ST-008 + DP-007 violation, not a fix.
5. **Merge, write the report, summarize.** Combine judgement + linter findings into one list, ordered by
   file then rule code. **There are no severity tiers — every finding is a violation to fix.** A finding's
   only non-fix exit is at Fix time: `accepted` (the reviewer judged it is not a violation here — reason
   required) or `deferred` (a real breach left open). At review time the call is binary: a rule breaks
   (file it) or it doesn't (it's a pass, not a soft "consider"). Persist the merged result to a report file
   per `references/review-report.md` (`.coding-standards/reviews/<timestamp>.md`, gitignored) and tell the
   user the path — every review writes one, inline included. The report's **`Structure baseline:` field is
   mandatory** and names the recorded `.coding-standards-structure` (or declares `NOT RECORDED` with a
   reason) — see `references/review-report.md`. Above the scope threshold (defined once in
   `orchestrator-pipeline.md` → Fix mode), trim the chat output to the shape in `review-report.md`; the
   report file always holds everything.
6. **Verify the structure baseline, then never silently skip a rule.** After writing the report, run
   `python3 <skill-dir>/hooks/check-review-report.py <report.md>` (pass `--root <sub-project>` in a
   monorepo). Exit `2` means the report asserts a structure with no `.coding-standards-structure` behind it
   — the structure step (Step 4 / step 0) was skipped: resolve + record it and rewrite the report before
   reporting done. Exit `1` is a declared skip — surface the reason. This is the back-stop for the
   task-list item: the report can't read as complete while claiming a baseline that was never written. And
   if you didn't check a rule, say so — a review with hidden gaps is worse than one that admits its scope.

### Fix

Triggered by "fix the findings" / "apply the review" / fixes requested right after a Review — or by
"continue the fix" / "resume the fix" to pick up a non-done milestone plan. Fix mode **always runs as
the orchestrator pipeline** (`MODE: fix`) — it's inherently multi-file: it fans out one fix-agent per
file, tracked by a completeness ledger so nothing is silently half-fixed. Don't offer a "single agent"
option; if `Agent` is unavailable, run the documented sequential-batch fallback and say so.

Every finding ends `fixed` (violation removed), `accepted` (judged not a violation — reason required), or
`deferred` (real breach, not fixed — an open breach). A run with open breaches reports
`done-with-open-breaches`, never `done`, until the user resolves them — see `references/fix-plan.md`.

The input is the most recent `.coding-standards/reviews/<ts>.md`; if none exists, run Review first.
Everything else — the ledger, the per-file fan-out, the scope threshold, and the milestone-driven plan
file for big fixes (`references/fix-plan.md`) — lives in `references/orchestrator-pipeline.md` under
"Fix mode".

---

## Finding a rule on demand

Rules are organized by the kind of question you're asking (functions, naming, objects/data, formatting,
comments, error handling, principles, structure), not by language. The full question→file index is in
`references/rule-index.md` — use it for "what does FN-005 mean?" lookups or when unsure which reference owns
a concern. During real work Step 7 already loads everything, so the index is just for targeted lookups.

---

## On conflict — the simpler *correct* design wins

When two designs are **both correct** and pull apart on other principles, **DP-006 (KISS)** breaks the
tie: the simpler one wins, even if it mildly bends DRY or another rule. KISS is a tiebreaker, not a trump
card — it never overrides correctness, a real requirement, or SOLID. You cannot invoke it to skip a class
per variant you were handed (OD-002), swallow an error, or ship a silent fallback. Adding a pattern
(Strategy, Visitor, a fifth layer of indirection) just to satisfy a rule? Stop — the simple version is
usually right. Defending a god-file or a duplicated `switch` as "simple" to avoid the structure? Also stop
— that's not simpler, just smaller.

---

## What this skill does NOT cover

- **Performance tuning** — use a profiler; clean code is fast *enough* by default.
- **Security review** — use a dedicated security skill (e.g. `security-review`). Clean-code review catches
  some bug classes but is not a security audit.
- **Test design** — tests follow the same clean-code rules, but TDD/BDD/mutation strategy is out of scope.
- **UI/UX visual review** — a separate domain (`web-design-guidelines`, `design-taste-frontend`). These
  frameworks cover *code* organization, not visual design.

If the user asks for any of these, say so and point them at the right tool.

