# LLM-first router overhaul — Implementation Plan v1.2 (фазы 1+2+3)

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Заменить regex-первичный router + §12 hard-rule на LLM-first классификатор (Sonnet 4.6 + памятка) с §17 universal skill-coverage, inheritance для коротких prompt'ов, и автоматический evidence loop (self-assessment + Opus reviewer subagent) для последующей дистилляции эмпирических regex-правил.

**Architecture:** Prefilter (regex) → LLM-classifier (Sonnet 4.6) → embedding → §17 gate (warn-only) → execution → self-assessment (Stop-hook) → Opus reviewer subagent (в /brain-retro). Гранулярные flag-переключатели. Schema эпизода bumps v4.0→v4.3 поэтапно. §12 + routing-docs архивируются. Economy-mode система (0%/5%/100%) **сохраняется** — снимается только §12 skill-discipline.

**Tech Stack:** Node.js ESM (`.mjs`), Vitest, Anthropic API (Sonnet 4.6 classifier + Opus 4.7 reviewer/self-assessment), `@xenova/transformers` (local embedding), Claude Code hooks + agents + skills, lefthook, markdownlint/cspell/gitleaks.

**Source spec:** `docs/superpowers/specs/2026-05-24-llm-first-router-overhaul-design.md` v2.3.

**v1.1 changelog (после 0%-аудита плана v1.0):** Task 1 = **«Откат мозга»** (полная инфра + snapshot user-level + dry-run + end-to-end smoke ДО любой деструкции). Закрыты 9 пробелов аудита: G3 (economy vs skill-discipline в user hooks), G5 (parser fwd-compat в откате), G8/G9 (C1/C2 ordering), G11 (accuracy-runner import), G14 (registry-to-classification-map), G16 (reviewer файл — create, не keep), user-level rollback, episodes preservation.

**Тайминг:** реализация — после закрытия Биллинга v2 Спек C. Перед стартом — refresh check (Task 0).

**Scope:** implementation-фазы 1+2+3 (~3.5-4.5 недели). Фаза 4 (distillation) — отдельный план через ~6 месяцев.

---

## ✅ DECISION POINT — ПОДТВЕРЖДЁН заказчиком 2026-05-25

**Решение:** economy-mode система **СОХРАНЯЕТСЯ**, §12 skill-discipline **СНИМАЕТСЯ** (default плана подтверждён). Task 2 исполняется как описано.

**Economy-mode vs §12 skill-discipline в `~/.claude/settings.json`** (user-level, вне репо). 6 Python-хуков в `~/.claude/hooks/`:

| хук | категория | действие в этом плане |
|---|---|---|
| `economy-mode.py` | economy (0%/5%/100%) | **СОХРАНИТЬ**, отредактировать stale-упоминание §12 |
| `economy-self-check.py` | economy | СОХРАНИТЬ |
| `economy-postcompact.py` | economy | СОХРАНИТЬ |
| `economy-state-guard.py` | смешанный (economy + §12 bypass-detect) | **ОТРЕДАКТИРОВАТЬ** — убрать §12-часть, оставить economy |
| `skill-marker.py` | §12 skill-discipline | **СНЯТЬ** (archive) |
| `skill-check.py` | §12 skill-discipline | **СНЯТЬ** (archive) |

**Default этого плана:** economy-система сохраняется (активно используется), §12-enforcement (`skill-marker.py`+`skill-check.py`+§12-часть `state-guard`) снимается. Если хочешь иначе — скорректировать Task 2 до старта.

---

## File structure (что создаём / меняем)

### Создаются (новые файлы)

| Файл | Ответственность |
|---|---|
| `docs/adr/ADR-016-section17-universal-skill-coverage.md` | ADR: §17 заменяет §12 |
| `docs/archive/llm-bootstrap-2026-05/` (+ подпапки + ROLLBACK.md) | Архив §12, routing-docs, memory, user-hooks snapshot |
| `tools/test-rollback.mjs` | Откат: git-tracked + user-level + flags; dry-run/execute |
| `tools/router-classifier-regex-fallback.mjs` | Сохранённый старый regex Layer 1 (fallback) |
| `tools/router-config.mjs` | Model IDs + константы (INHERITANCE_MAX_AGE_MIN, etc.) |
| `tools/router-embedding.mjs` | Local embedding (Xenova) |
| `tools/router-embedding-warmup.mjs` | SessionStart pre-warm |
| `tools/brain-retro-opus-reviewer.mjs` | **CREATE** (не существует) — direct-API fallback handler для reviewer |
| `tools/brain-retro-sanity-generator.mjs` | top-5 candidate sanity questions |
| `.claude/skills/self-retrospect/SKILL.md` | Opt-in self-retrospect skill |
| `docs/observer/.self-retrospect-counter.json` | Counter для self-retrospect threshold |
| `~/.claude/runtime/*.json` (9 flag-файлов) | Granular flag-переключатели |

### Модифицируются (существующие)

| Файл | Что |
|---|---|
| `tools/router-classifier.mjs` | Prefilter (3 группы + manual override + anchor) + Sonnet classifier + памятка |
| `tools/router-accuracy-runner.mjs` | **import classifyByRegex → из regex-fallback** (G11) |
| `tools/router-prehook.mjs` | Удалить ENFORCEMENT_TYPES; inheritance logic; cost tracking |
| `tools/router-tool-gate.mjs` | §17 enforcement logic + mode |
| `tools/observer-stop-hook.mjs` | execution_trace + chain_gaps + self_assessment + inheritance copy + timeout |
| `tools/observer-transcript-parser.mjs` | handle schema v4.0-v4.3; **forward-compat для отката (G5)** |
| `tools/missed-activations.mjs` | source → nodes.yaml; §17 definition |
| `tools/registry-to-classification-map.mjs` | **neutralize/archive** — map deprecated (G14) |
| `tools/brain-retro-analyzer.mjs` | v4.* факторы + inheritance анализ |
| `tools/status-md-generator.mjs` | cost + anomaly + self-retrospect + reviewer ratio |
| `tools/l1-watcher.mjs` | source Tooling §3.3 → nodes.yaml |
| `tools/cross-ref-checker.mjs` | cross-refs list §12→§17 |
| `.claude/agents/reviewer-agent.md` | verify (уже создан) |
| `.claude/skills/brain-retro/SKILL.md` | новые шаги + description |
| `.claude/skills/brain-retro/references/aggregation-template.md` | под расширенную процедуру |
| `.claude/settings.json` (project) | Stop-hook timeout 15s; SessionStart hook |
| `~/.claude/settings.json` (user) | снять skill-marker/skill-check; отредактировать economy-state-guard (G3) |
| `~/.claude/hooks/economy-mode.py` | убрать stale «§12» текст (G3) |
| `docs/registry/nodes.yaml` | +`capabilities:` per узел |
| `docs/Pravila_raboty_Claude_v1_1.md` | −§12, +§17, §16.4 |
| `CLAUDE.md`, `docs/Plugin_stack_rules_v1.md`, `docs/Tooling_v8_3.md` | cross-refs §12→§17, §3.3/R15 архив |

---

## Phase 0 — Pre-flight (~0.5 дня)

### Task 0: Refresh check + worktree

**Files:** none (verification only)

- [ ] **Step 1: Pre-flight git sync (Pravila §15.2)**

Run:

```bash
git fetch origin && git log HEAD..origin/main --oneline
```

Expected: понять, не разошлась ли база. Если untracked commits — rebase до начала.

- [ ] **Step 2: Verify spec актуален (node count)**

Run:

```bash
node -e "const fs=require('fs'); const y=fs.readFileSync('docs/registry/nodes.yaml','utf8'); console.log('nodes:', (y.match(/^  - id:/gm)||[]).length)"
```

Expected: ~84. Если изменилось >5 узлов — re-read spec §18.3 + поправить Task 9 count.

- [ ] **Step 3: Verify Sonnet 4.6 model ID**

Run:

```bash
node -e "fetch('https://api.anthropic.com/v1/models',{headers:{'x-api-key':process.env.ANTHROPIC_API_KEY,'anthropic-version':'2023-06-01'}}).then(r=>r.json()).then(d=>console.log(d.data.filter(m=>m.id.includes('sonnet')).map(m=>m.id)))"
```

Expected: список Sonnet IDs. Записать точный `claude-sonnet-4-6-<YYYYMMDD>` для Task 8.

- [ ] **Step 4: Confirm DECISION POINT (economy vs skill-discipline)**

Подтвердить: economy сохраняем, §12-skill-discipline снимаем. Без подтверждения — не стартовать Task 2.

- [ ] **Step 5: Create isolated worktree (Pravila §15.1)**

Используй `superpowers:using-git-worktrees`. Ветка `feat/llm-first-router`.

---

## Phase 1 — Откат мозга + foundation + archive (~1 неделя)

### Task 1: ⭐ ОТКАТ МОЗГА — полная инфраструктура + верификация (FIRST, до любой деструкции)

**Цель:** прежде чем что-либо ломать — установить и **доказать** работающий механизм полного отката (git-tracked + user-level + runtime flags). Если этот таск не зелёный — дальше не идём.

**Files:**

- Create: `tools/test-rollback.mjs`, `tools/test-rollback.test.mjs`
- Create: `docs/archive/llm-bootstrap-2026-05/` (+ подпапки), `ROLLBACK.md`
- Create: snapshots — `nodes-yaml-archive/`, `settings-snapshot/`, `runtime-flags-snapshot/`, `user-hooks/`

- [ ] **Step 1: Git tag pre-overhaul state**

```bash
git tag brain-pre-llm-bootstrap && git tag --list brain-pre-llm-bootstrap
```

Expected: тег на текущем HEAD (покрывает все git-tracked файлы).

- [ ] **Step 2: Create archive structure**

```bash
mkdir -p docs/archive/llm-bootstrap-2026-05/{pravila-12,routing-docs,tooling-when-to-use,memory,settings-snapshot,nodes-yaml-archive,runtime-flags-snapshot,user-hooks}
```

- [ ] **Step 3: Snapshot ALL non-git-tracked state (закрывает user-level rollback gap + G3)**

```bash
node -e "const fs=require('fs'),os=require('os'),p=require('path'); const A='docs/archive/llm-bootstrap-2026-05'; const us=p.join(os.homedir(),'.claude','settings.json'); if(fs.existsSync(us)) fs.copyFileSync(us, A+'/settings-snapshot/user-settings.json.pre-overhaul'); const hd=p.join(os.homedir(),'.claude','hooks'); if(fs.existsSync(hd)){for(const f of fs.readdirSync(hd)) fs.copyFileSync(p.join(hd,f), A+'/user-hooks/'+f);} const rd=p.join(os.homedir(),'.claude','runtime'); if(fs.existsSync(rd)){for(const f of fs.readdirSync(rd).filter(x=>x.endsWith('-mode.json'))) fs.copyFileSync(p.join(rd,f), A+'/runtime-flags-snapshot/'+f);} fs.copyFileSync('docs/registry/nodes.yaml', A+'/nodes-yaml-archive/nodes.yaml.pre-overhaul'); fs.copyFileSync('.claude/settings.json', A+'/settings-snapshot/project-settings.json.pre-overhaul'); console.log('snapshots written')"
```

Expected: «snapshots written». Verify: `ls docs/archive/llm-bootstrap-2026-05/{settings-snapshot,user-hooks,runtime-flags-snapshot}` непусто.

- [ ] **Step 4: Write failing test for test-rollback.mjs**

```javascript
// tools/test-rollback.test.mjs
import { describe, it, expect } from 'vitest';
import { planRollback } from './test-rollback.mjs';

describe('planRollback', () => {
  it('restores git-tracked via tag + lists user-level snapshots', () => {
    const plan = planRollback();
    expect(plan.gitTag).toBe('brain-pre-llm-bootstrap');
    expect(plan.userLevelRestores.some(r => r.to.includes('settings.json'))).toBe(true);
  });
  it('resets runtime flags to snapshot (not hardcoded)', () => {
    expect(planRollback().flagStrategy).toBe('restore-snapshot-delete-new');
  });
  it('lists episodes as PRESERVED not reverted (G5/G6)', () => {
    expect(planRollback().preserve.some(x => x.includes('episodes'))).toBe(true);
  });
});
```

- [ ] **Step 5: Run test to verify it fails**

Run: `npx vitest run tools/test-rollback.test.mjs`
Expected: FAIL — `planRollback is not exported`.

- [ ] **Step 6: Implement test-rollback.mjs (execFileSync — no shell, no injection)**

```javascript
// tools/test-rollback.mjs
#!/usr/bin/env node
import { existsSync, copyFileSync, readdirSync, rmSync } from 'fs';
import { join } from 'path';
import { homedir } from 'os';
import { execFileSync } from 'child_process';
import { fileURLToPath } from 'url';

const ARCHIVE = 'docs/archive/llm-bootstrap-2026-05';

export function planRollback() {
  return {
    gitTag: 'brain-pre-llm-bootstrap',
    gitStrategy: 'git checkout brain-pre-llm-bootstrap -- <tracked paths>',
    userLevelRestores: [
      { from: `${ARCHIVE}/settings-snapshot/user-settings.json.pre-overhaul`, to: '~/.claude/settings.json' },
      { from: `${ARCHIVE}/user-hooks/*`, to: '~/.claude/hooks/' },
    ],
    flagStrategy: 'restore-snapshot-delete-new',
    preserve: ['docs/observer/episodes-*.jsonl', 'docs/observer/notes/*'],
    parserNote: 'после отката parser остаётся forward-compatible к v4 эпизодам (read-only graceful skip) — Task 15 (G5)',
  };
}

function dryRun() {
  const plan = planRollback();
  let ok = true;
  const base = `${ARCHIVE}/settings-snapshot/user-settings.json.pre-overhaul`;
  if (!existsSync(base)) { console.error('MISSING snapshot:', base); ok = false; }
  try { execFileSync('git', ['rev-parse', plan.gitTag], { stdio: 'pipe' }); }
  catch { console.error('MISSING git tag:', plan.gitTag); ok = false; }
  console.log(ok ? '[dry-run] OK — rollback ready' : '[dry-run] FAIL — see above');
  return ok;
}

function execRollback() {
  const usFrom = `${ARCHIVE}/settings-snapshot/user-settings.json.pre-overhaul`;
  if (existsSync(usFrom)) copyFileSync(usFrom, join(homedir(), '.claude', 'settings.json'));
  const hooksDir = `${ARCHIVE}/user-hooks`;
  if (existsSync(hooksDir)) for (const f of readdirSync(hooksDir)) copyFileSync(join(hooksDir, f), join(homedir(), '.claude', 'hooks', f));
  const rd = join(homedir(), '.claude', 'runtime');
  const snapDir = `${ARCHIVE}/runtime-flags-snapshot`;
  const snapFlags = existsSync(snapDir) ? readdirSync(snapDir) : [];
  for (const f of readdirSync(rd).filter(x => x.endsWith('-mode.json'))) {
    if (!snapFlags.includes(f)) rmSync(join(rd, f));
  }
  for (const f of snapFlags) copyFileSync(join(snapDir, f), join(rd, f));
  console.log('[execute] user-level + flags restored. Now run: git checkout brain-pre-llm-bootstrap -- . && npm install');
}

const isMain = process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1];
if (isMain) {
  const mode = process.argv[2];
  if (mode === '--dry-run') process.exit(dryRun() ? 0 : 1);
  else if (mode === '--execute') execRollback();
  else console.log('usage: test-rollback.mjs --dry-run | --execute');
}
```

- [ ] **Step 7: Run test to verify it passes**

Run: `npx vitest run tools/test-rollback.test.mjs`
Expected: PASS (3 tests).

- [ ] **Step 8: Write ROLLBACK.md**

Write `docs/archive/llm-bootstrap-2026-05/ROLLBACK.md`: пошагово — (1) `node tools/test-rollback.mjs --execute` (user-level + flags), (2) `git checkout brain-pre-llm-bootstrap -- .` (git-tracked), (3) `npm install` (deps revert, G4), (4) smoke. Явно: **episodes-*.jsonl НЕ откатываются** (G6); **parser forward-compat** к v4 (G5). Manifest from→to.

- [ ] **Step 9: ⭐ END-TO-END SMOKE — доказать что откат работает ДО деструкции**

```bash
echo "rollback-smoke-test" > docs/observer/.rollback-smoke && git add -A && git commit -m "test: rollback smoke marker (TEMP)"
node -e "require('fs').writeFileSync(require('path').join(require('os').homedir(),'.claude','runtime','smoke-test-mode.json'),'{}')"
node tools/test-rollback.mjs --dry-run
node tools/test-rollback.mjs --execute
git checkout brain-pre-llm-bootstrap -- . ; git reset --soft brain-pre-llm-bootstrap
node -e "const fs=require('fs'),os=require('os'),p=require('path'); console.log('marker:', fs.existsSync('docs/observer/.rollback-smoke')?'STILL THERE (FAIL)':'gone (OK)'); console.log('smoke-flag:', fs.existsSync(p.join(os.homedir(),'.claude','runtime','smoke-test-mode.json'))?'STILL THERE (FAIL)':'deleted (OK)')"
```

Expected: marker gone, smoke-flag deleted, router-gate-mode.json = warn-only. Если хоть один FAIL — **СТОП**, чинить test-rollback.mjs до продолжения.

- [ ] **Step 10: Re-commit rollback infra (clean)**

```bash
git add tools/test-rollback.mjs tools/test-rollback.test.mjs docs/archive/llm-bootstrap-2026-05/ && git commit -m "feat(brain): rollback infra + snapshots + e2e-verified BEFORE any destruction (phase 1 task 1)"
```

**Exit Task 1:** откат мозга установлен, протестирован end-to-end, доказан. Дальше любая деструкция обратима за ~1 час.

### Task 2: Снять §12 skill-discipline, сохранить economy (G3, DECISION POINT)

**Files:**

- Modify: `~/.claude/settings.json` (user), `~/.claude/hooks/economy-state-guard.py`, `~/.claude/hooks/economy-mode.py`
- Archive: `skill-marker.py`, `skill-check.py` (snapshot уже в Task 1)

- [ ] **Step 1: Baseline — economy hooks работают**

Run: `python "$HOME/.claude/hooks/economy-mode.py" < /dev/null; echo "exit: $?"`
Expected: exit 0 (или graceful). Зафиксировать baseline.

- [ ] **Step 2: Снять skill-marker.py + skill-check.py из user settings**

Удалить из `~/.claude/settings.json` блоки `PreToolUse Skill → skill-marker.py` и `PreToolUse Edit|Write|MultiEdit → skill-check.py`. Оригиналы в snapshot.

- [ ] **Step 3: economy-state-guard.py — убрать §12-часть**

Прочитать `economy-state-guard.py`, удалить только §12 skill-discipline логику (Bash-bypass-detect skill-enforcement), сохранить economy-state. Если чисто economy — no-op.

- [ ] **Step 4: economy-mode.py — актуализировать «§12»→«§17»**

В `economy-mode.py` инжект-текст «§12 hard rule НЕ override-ится» → «§17 universal skill-coverage».

- [ ] **Step 5: Verify economy работает + §12 enforcement снят**

Run: `python "$HOME/.claude/hooks/economy-mode.py" < /dev/null; echo "exit: $?"`
Expected: exit 0, economy-директива генерится. skill-check больше не блокирует Edit без skill.

- [ ] **Step 6: Commit (project-side note)**

```bash
git add docs/archive/llm-bootstrap-2026-05/ && git commit -m "chore(brain): archive §12 skill-discipline hooks, keep economy (phase 1 task 2)"
```

### Task 3: Inventory discipline-metrics.mjs (closes B4)

**Files:** none (decision → commit message)

- [ ] **Step 1: Read what it measures**

Run: `node -e "console.log(require('fs').readFileSync('tools/discipline-metrics.mjs','utf8').slice(0,2000))"`

- [ ] **Step 2: Decide keep/remove**

only-§12 → archive; общий path_type → keep. Решение в commit.

- [ ] **Step 3: Apply + commit**

```bash
git commit -m "chore(brain): discipline-metrics.mjs — <keep|archive> (phase 1 task 3)"
```

### Task 4: Archive §12 + routing-docs + memory + registry-map (G14)

**Files:**

- Modify: `docs/Pravila_raboty_Claude_v1_1.md`
- Move: routing-off-phase.md, router-procedure.md, observer-classification-map.json, registry-to-classification-map.mjs, 2 memory files

- [ ] **Step 1: Extract Pravila §12 to archive**

§12 (12.1-12.4) → `archive/.../pravila-12/Pravila_section_12.md`, удалить из Pravila.

- [ ] **Step 2: Move routing-docs + classification-map**

```bash
git mv docs/routing-off-phase.md docs/archive/llm-bootstrap-2026-05/routing-docs/
git mv docs/router-procedure.md docs/archive/llm-bootstrap-2026-05/routing-docs/
git mv tools/observer-classification-map.json docs/archive/llm-bootstrap-2026-05/routing-docs/
```

- [ ] **Step 3: Neutralize registry-to-classification-map.mjs (G14)**

Run: `grep -rn "registry-to-classification-map" lefthook.yml package.json .claude/ 2>&1 || echo "no refs"`
Expected: найти ссылки. Затем `git mv tools/registry-to-classification-map.mjs docs/archive/llm-bootstrap-2026-05/routing-docs/` + убрать его вызовы из lefthook.yml.

- [ ] **Step 4: Move 2 memory files**

```bash
git mv memory/feedback_superpowers_hard_rule.md docs/archive/llm-bootstrap-2026-05/memory/
git mv memory/feedback_feature_via_writing_plans.md docs/archive/llm-bootstrap-2026-05/memory/
```

Удалить их строки из `memory/MEMORY.md`.

- [ ] **Step 5: Verify lint + commit**

Run: `npx -y markdownlint-cli2 docs/Pravila_raboty_Claude_v1_1.md`
Expected: 0 errors.

```bash
git add -A && git commit -m "chore(brain): archive §12 + routing-docs + classification-map + 2 memory (phase 1 task 4)"
```

### Task 5: Add Pravila §17 + ADR-016

**Files:**

- Modify: `docs/Pravila_raboty_Claude_v1_1.md`
- Create: `docs/adr/ADR-016-section17-universal-skill-coverage.md`

- [ ] **Step 1: Add §17 to Pravila**

§17 из spec §6 (Acknowledgment/Cancellation exempt; Continuation НЕ exempt — D1). Обновить §16.4 + §0/§1 cross-refs + §9 changelog.

- [ ] **Step 2: Create ADR-016**

Status/Context/Decision/Consequences/Boundaries + `## Enforcement` секция (adr-judge).

- [ ] **Step 3: Verify + commit**

Run: `npx -y markdownlint-cli2 docs/adr/ADR-016-section17-universal-skill-coverage.md`
Expected: 0 errors.

```bash
git add -A && git commit -m "feat(brain): Pravila §17 + ADR-016 (phase 1 task 5)"
```

### Task 6: Normative cross-refs §12→§17 + adapt C1/C2 EARLY (closes G8/G9)

**Files:**

- Modify: `CLAUDE.md`, `docs/Plugin_stack_rules_v1.md`, `docs/Tooling_v8_3.md`, `tools/cross-ref-checker.mjs`, `tools/l1-watcher.mjs`

- [ ] **Step 1: Archive §3.3 / R15 / Tooling «когда брать»**

CLAUDE.md §3.3 → archive + pin на nodes.yaml; §5 п.11 →§17. PSR_v1 R15 → archive, R10.1 pin, R0.4.A §12→§17. Tooling §4.X «когда брать» → archive, §0 pin, §3.X router-procedure cross-refs убрать. NB: CLAUDE.md прямой Edit — worktree-эксцепшн §5 п.10.

- [ ] **Step 2: Adapt C1 + C2 СРАЗУ (G8/G9)**

`cross-ref-checker.mjs` — обновить ожидаемые cross-refs (§12→§17, убрать §3.3). `l1-watcher.mjs` — source §3.3 → nodes.yaml. Иначе pre-commit в Task 7+ упадёт.

- [ ] **Step 3: Verify checkers green**

Run: `node tools/cross-ref-checker.mjs && node tools/l1-watcher.mjs`
Expected: OK / 0 drift.

- [ ] **Step 4: Commit**

```bash
git add -A && git commit -m "chore(brain): cross-refs §12→§17 + C1/C2 adapted early (phase 1 task 6)"
```

### Task 7: Phase-1 flags + rollback re-verify

**Files:**

- Create: `~/.claude/runtime/skill-discipline-mode.json`=off

- [ ] **Step 1: Set phase-1 flags**

```bash
node -e "const fs=require('fs'),os=require('os'),p=require('path'); fs.writeFileSync(p.join(os.homedir(),'.claude','runtime','skill-discipline-mode.json'),JSON.stringify({mode:'off'})); console.log('skill-discipline off')"
```

(router-gate-mode остаётся warn-only.)

- [ ] **Step 2: Rollback dry-run (после деструкции)**

Run: `node tools/test-rollback.mjs --dry-run`
Expected: OK.

- [ ] **Step 3: Commit**

```bash
git add -A && git commit -m "chore(brain): phase-1 flags + rollback re-verified (phase 1 task 7)"
```

**Phase 1 exit:** откат доказан; §12 нет; §17 + ADR-016; economy сохранён; C1/C2 адаптированы; ничего не enforce'ится.

---

## Phase 2 — Classifier + памятка + inheritance + §17 (~1-1.5 недели)

### Task 8: router-config.mjs + nodes.yaml capabilities

**Files:**

- Create: `tools/router-config.mjs`
- Modify: `docs/registry/nodes.yaml`

- [ ] **Step 1: Create router-config.mjs**

```javascript
// tools/router-config.mjs
export const CLASSIFIER_MODEL = 'claude-sonnet-4-6-YYYYMMDD'; // verified Task 0 step 3
export const REVIEWER_MODEL = 'claude-opus-4-7';
export const INHERITANCE_MAX_AGE_MIN = 30;
export const REVIEWER_MAX_NEIGHBOR_EPISODES = 10;
```

- [ ] **Step 2: Fill capabilities (delegate to subagent)**

Каждому из ~84 узлов `capabilities:` (1-2 предложения, без «когда выбирать»). schema.json permissive (G12 verified).

Run: `node -e "const y=require('fs').readFileSync('docs/registry/nodes.yaml','utf8'); const n=(y.match(/^  - id:/gm)||[]).length, c=(y.match(/^    capabilities:/gm)||[]).length; console.log('nodes',n,'caps',c); process.exit(n===c?0:1)"`
Expected: n===c, exit 0.

- [ ] **Step 3: Commit**

```bash
git add tools/router-config.mjs docs/registry/nodes.yaml && git commit -m "feat(brain): router-config + nodes.yaml capabilities (phase 2 task 8)"
```

### Task 9: Prefilter — 3 группы + manual override + anchor (TDD)

**Files:**

- Modify: `tools/router-classifier.mjs`
- Test: `tools/router-classifier.test.mjs`

- [ ] **Step 1: Write failing tests**

```javascript
import { prefilter } from './router-classifier.mjs';
describe('prefilter', () => {
  it('manual override priority over continuation', () => {
    const r = prefilter('делай через TDD', { prevState: null });
    expect(r.task_type).toBe('manual_override');
    expect(r.requested_node).toContain('test-driven-development');
  });
  it('continuation inherits within 30 min', () => {
    const prevState = { classification: { task_type: 'feature', recommendedNode: '#19' }, timestamp: new Date().toISOString() };
    const r = prefilter('делай', { prevState });
    expect(r.source).toBe('prefilter_inherited');
    expect(r.task_type).toBe('feature');
  });
  it('continuation falls through when >30 min', () => {
    const old = new Date(Date.now() - 31 * 60000).toISOString();
    expect(prefilter('делай', { prevState: { classification: { task_type: 'feature' }, timestamp: old } }).task_type).toBe('conversation');
  });
  it('acknowledgment is conversation', () => { expect(prefilter('спасибо', {}).task_type).toBe('conversation'); });
  it('cancellation flags previous rejected', () => { expect(prefilter('нет', { prevState: { task_id: 'abc' } }).previous_rejected).toBe(true); });
  it('anchor saves "делай аудит" → null', () => { expect(prefilter('делай аудит', {})).toBeNull(); });
  it('micro keyword → micro', () => { expect(prefilter('поправь typo в строке', {}).task_type).toBe('micro'); });
  it('content prompt → null', () => { expect(prefilter('добавь endpoint для экспорта сделок', {})).toBeNull(); });
});
```

- [ ] **Step 2: Run to verify fail**

Run: `npx vitest run tools/router-classifier.test.mjs -t prefilter`
Expected: FAIL.

- [ ] **Step 3: Implement prefilter**

`CONTINUATION_PATTERNS`, `ACKNOWLEDGMENT_PATTERNS`, `CANCELLATION_PATTERNS`, `MANUAL_OVERRIDE_RE`, `ANCHOR_NOUNS` (28), `ANCHOR_IMPERATIVES` (10), `MICRO_KEYWORDS` (spec §4.1). `prefilter(prompt, {prevState})` — проверки 1-7. `requested_node` fuzzy. Возраст `<= INHERITANCE_MAX_AGE_MIN`.

- [ ] **Step 4: Run to verify pass**

Run: `npx vitest run tools/router-classifier.test.mjs -t prefilter`
Expected: PASS (8 tests).

- [ ] **Step 5: Commit**

```bash
git add tools/router-classifier.mjs tools/router-classifier.test.mjs && git commit -m "feat(router): prefilter 3 groups + manual override + anchor (phase 2 task 9)"
```

### Task 10: Sonnet 4.6 classifier + памятка + fallback module + accuracy-runner (TDD, closes G11)

**Files:**

- Modify: `tools/router-classifier.mjs`, `tools/router-accuracy-runner.mjs`
- Create: `tools/router-classifier-regex-fallback.mjs`
- Test: `tools/router-classifier.test.mjs`

- [ ] **Step 1: Write failing tests**

```javascript
describe('buildClassifierPrompt', () => {
  it('includes 4 памятка when enrichment on', () => {
    const p = buildClassifierPrompt('добавь фичу', { nodes: [], chains: {} }, { enrichment: true });
    expect(p).toContain('ПАТТЕРН 1'); expect(p).toContain('ПАТТЕРН 4');
  });
  it('omits памятка when off', () => { expect(buildClassifierPrompt('x', { nodes: [], chains: {} }, { enrichment: false })).not.toContain('ПАТТЕРН 1'); });
});
describe('parseClassifierResponse', () => {
  it('accepts null recommended_chain_id', () => {
    expect(parseClassifierResponse('{"task_type":"feature","recommended_node":"x","recommended_chain":["x"],"recommended_chain_id":null,"alternatives_considered":[],"no_skill_found":false}').recommended_chain_id).toBeNull();
  });
  it('returns null on malformed', () => { expect(parseClassifierResponse('nope')).toBeNull(); });
});
```

- [ ] **Step 2: Run to verify fail**

Run: `npx vitest run tools/router-classifier.test.mjs -t 'buildClassifierPrompt|parseClassifierResponse'`
Expected: FAIL.

- [ ] **Step 3: Extract regex to fallback module**

Скопировать `classifyByRegex` + `TASK_TYPE_KEYWORDS` + хелперы → `tools/router-classifier-regex-fallback.mjs` (export `classifyByRegex`).

- [ ] **Step 4: Fix router-accuracy-runner.mjs import (G11)**

`tools/router-accuracy-runner.mjs:11`: `from './router-classifier.mjs'` → `from './router-classifier-regex-fallback.mjs'`.

Run: `node tools/router-accuracy-runner.mjs 2>&1 | head -3`
Expected: работает.

- [ ] **Step 5: Implement classifier**

`buildClassifierPrompt(prompt, registry, {enrichment=true})` (spec §4.2). `parseClassifierResponse`. `classify()`: prefilter→если null escalate to Sonnet. Удалить `shouldEscalate`, `HARD_KEYWORD_STEMS`; `classifyByRegex` re-export из fallback. Fallback chain Sonnet→Haiku→regex→degraded.

- [ ] **Step 6: Run to verify pass + commit**

Run: `npx vitest run tools/router-classifier.test.mjs`
Expected: PASS.

```bash
git add tools/router-classifier.mjs tools/router-classifier-regex-fallback.mjs tools/router-accuracy-runner.mjs tools/router-classifier.test.mjs && git commit -m "feat(router): Sonnet classifier + памятка + fallback + accuracy-runner fix (phase 2 task 10)"
```

### Task 11: Adapt missed-activations to nodes.yaml + §17 (TDD, closes A5)

**Files:**

- Modify: `tools/missed-activations.mjs`
- Test: `tools/missed-activations.test.mjs`

- [ ] **Step 1: Write failing test**

```javascript
describe('detectMissedActivations §17', () => {
  it('flags direct on non-conversation with recommended_node', () => {
    expect(detectMissedActivations([{ schema_version: 4, classifier_output: { task_type: 'feature', recommended_node: '#19', no_skill_found: false }, execution_trace: { actual_node_invoked_first: 'direct' } }]).totalMissed).toBe(1);
  });
  it('does not flag conversation', () => {
    expect(detectMissedActivations([{ schema_version: 4, classifier_output: { task_type: 'conversation', recommended_node: null } }]).totalMissed).toBe(0);
  });
});
```

- [ ] **Step 2-4: Fail → implement → pass**

`detectMissedActivations(episodes)` (drop classificationMap/dormancy). §17 definition. v2/v3 legacy на nodes.yaml triggers. Run `npx vitest run tools/missed-activations.test.mjs`.

- [ ] **Step 5: Commit**

```bash
git add tools/missed-activations.mjs tools/missed-activations.test.mjs && git commit -m "feat(brain): missed-activations on nodes.yaml + §17 (phase 2 task 11)"
```

### Task 12: Embedding layer (TDD, closes 3.3)

**Files:**

- Create: `tools/router-embedding.mjs`, `tools/router-embedding-warmup.mjs`
- Test: `tools/router-embedding.test.mjs`

- [ ] **Step 1: Install dep**

Run: `npm i @xenova/transformers`

- [ ] **Step 2: Write failing test**

```javascript
import { shouldEmbed, encodeBase64, decodeBase64 } from './router-embedding.mjs';
describe('embedding', () => {
  it('shouldEmbed skips conversation/micro/manual_override', () => {
    expect(shouldEmbed('conversation')).toBe(false);
    expect(shouldEmbed('micro')).toBe(false);
    expect(shouldEmbed('manual_override')).toBe(false);
    expect(shouldEmbed('feature')).toBe(true);
  });
  it('base64 roundtrip', () => {
    const v = new Float32Array([0.1, -0.5, 0.9]);
    expect(Array.from(decodeBase64(encodeBase64(v)))).toEqual(Array.from(v));
  });
});
```

- [ ] **Step 3-5: Fail → implement → pass**

`shouldEmbed`, `encodeBase64`, `decodeBase64`, `embed(prompt)` (lazy Xenova, fallback null). `router-embedding-warmup.mjs`. Run `npx vitest run tools/router-embedding.test.mjs`.

- [ ] **Step 6: Commit**

```bash
git add tools/router-embedding.mjs tools/router-embedding-warmup.mjs tools/router-embedding.test.mjs package.json package-lock.json && git commit -m "feat(router): local embedding + warmup (phase 2 task 12)"
```

### Task 13: §17 enforcement (TDD, closes D1)

**Files:**

- Modify: `tools/router-tool-gate.mjs`
- Test: `tools/router-tool-gate.test.mjs`

- [ ] **Step 1: Write failing tests**

```javascript
describe('§17 shouldBlock', () => {
  const base = { classification: { task_type: 'feature', no_skill_found: false }, skillInvokedThisTurn: false };
  it('warn-only never blocks', () => { expect(shouldBlock('Edit', base, '', { mode: 'warn-only' })).toBe(false); });
  it('enforce blocks direct on feature', () => { expect(shouldBlock('Edit', base, '', { mode: 'enforce' })).toMatchObject({ block: true }); });
  it('enforce passes conversation', () => { expect(shouldBlock('Edit', { ...base, classification: { task_type: 'conversation' } }, '', { mode: 'enforce' })).toBe(false); });
  it('enforce passes when skill invoked', () => { expect(shouldBlock('Edit', { ...base, skillInvokedThisTurn: true }, '', { mode: 'enforce' })).toBe(false); });
  it('enforce blocks no_skill_found', () => { expect(shouldBlock('Edit', { ...base, classification: { task_type: 'feature', no_skill_found: true } }, '', { mode: 'enforce' })).toMatchObject({ reason: 'no_skill_found_block' }); });
  it('continuation-inherited feature NOT exempt (D1)', () => { expect(shouldBlock('Edit', { ...base, classification: { task_type: 'feature' } }, '', { mode: 'enforce' })).toMatchObject({ block: true }); });
});
```

- [ ] **Step 2-4: Fail → implement → pass**

`NON_BLOCKING_TASK_TYPES = ['conversation','micro','manual_override']` (continuation НЕ входит — D1). `shouldBlock` spec §4.4. Mode hot-reload. Run `npx vitest run tools/router-tool-gate.test.mjs`.

- [ ] **Step 5: Commit**

```bash
git add tools/router-tool-gate.mjs tools/router-tool-gate.test.mjs && git commit -m "feat(router): §17 enforcement, continuation not exempt (phase 2 task 13)"
```

### Task 14: prehook inheritance + cost (TDD, closes B1/B5)

**Files:**

- Modify: `tools/router-prehook.mjs`
- Test: `tools/router-prehook.test.mjs`

- [ ] **Step 1: Write failing tests**

```javascript
describe('inheritance state', () => {
  it('writes inheritance block on continuation', () => {
    const s = buildStateFromClassification({ task_type: 'feature', source: 'prefilter_inherited' }, { sessionId: 's', promptHash: 'h', inheritedFrom: 'prev', ageMin: 5 });
    expect(s.inheritance.inherited_from_task_id).toBe('prev');
    expect(s.inheritance.inheritance_age_minutes).toBe(5);
  });
  it('no ENFORCEMENT_TYPES', async () => { expect((await import('./router-prehook.mjs')).ENFORCEMENT_TYPES).toBeUndefined(); });
});
```

- [ ] **Step 2-4: Fail → implement → pass**

Удалить `ENFORCEMENT_TYPES` + `isEnforcementRequired`. `buildStateFromClassification` +inheritance. `main()`: prefilter с prevState (до перезаписи); continuation → наследовать. Cost → state. Run `npx vitest run tools/router-prehook.test.mjs`.

- [ ] **Step 5: Commit**

```bash
git add tools/router-prehook.mjs tools/router-prehook.test.mjs && git commit -m "feat(router): prehook inheritance + cost, drop ENFORCEMENT_TYPES (phase 2 task 14)"
```

### Task 15: Parser v4.0 fwd-compat + warmup hook + phase-2 flags (closes G5)

**Files:**

- Modify: `tools/observer-transcript-parser.mjs`, `tools/registry-load.mjs`, `tools/registry-render.mjs`, `.claude/settings.json`

- [ ] **Step 1: Parser v4.0 + forward-compat (G5)**

Write новых эпизодов с `classifier_output` + `environment.classifier_model` + `degraded_mode`. Read — handle v1/v2/v3/v4 + **graceful skip неизвестных future-версий** (для отката, G5).

- [ ] **Step 2: Adapt registry-load/render для capabilities**

- [ ] **Step 3: Register SessionStart warmup**

`.claude/settings.json` +SessionStart → `node tools/router-embedding-warmup.mjs`.

- [ ] **Step 4: Integration smoke**

Run: `npx vitest run tools/ && npx -y markdownlint-cli2 "docs/**/*.md"`
Expected: PASS / 0 errors.

- [ ] **Step 5: Flip phase-2 flags**

```bash
node -e "const fs=require('fs'),os=require('os'),p=require('path'); const d=p.join(os.homedir(),'.claude','runtime'); const f={'router-classifier-mode':'llm-first','prompt-enrichment-mode':'on','inheritance-mode':'on','embedding-mode':'on'}; for(const[k,v]of Object.entries(f)) fs.writeFileSync(p.join(d,k+'.json'),JSON.stringify({mode:v})); console.log('phase-2 flags on')"
```

- [ ] **Step 6: Commit**

```bash
git add tools/ .claude/settings.json && git commit -m "feat(router): parser v4.0 fwd-compat + warmup + phase-2 flags (phase 2 task 15)"
```

**Phase 2 exit:** новый router работает, эпизоды v4.0, §17 warn-only, accuracy-runner чинён, registry-map нейтрализован.

---

## Phase 3 — Evidence loop (~1.5-2 недели)

### Task 16: Stop-hook execution_trace + chain_gaps + inheritance copy + timeout (TDD)

**Files:**

- Modify: `tools/observer-stop-hook.mjs`, `.claude/settings.json`
- Test: `tools/observer-stop-hook.test.mjs`

- [ ] **Step 1: Write failing test**

```javascript
describe('execution_trace v4.1', () => {
  it('builds chain_gaps when incomplete', () => {
    const t = buildExecutionTrace({ recommended_chain: ['a','b','c'], invoked: ['a'] });
    expect(t.chain_gaps[0].executed_steps).toBe(1);
    expect(t.chain_gaps[0].expected_steps).toBe(3);
  });
  it('copies inheritance from state (B5)', () => {
    expect(buildEpisode({ state: { inheritance: { inherited_from_task_id: 'x' } } }).inheritance.inherited_from_task_id).toBe('x');
  });
});
```

- [ ] **Step 2-4: Fail → implement → pass**

`buildExecutionTrace` + `chain_gaps`. `buildEpisode` copies `inheritance.*` (B5). schema_minor→1. `.claude/settings.json` Stop timeout 5s→15s. Run `npx vitest run tools/observer-stop-hook.test.mjs`.

- [ ] **Step 5: Commit**

```bash
git add tools/observer-stop-hook.mjs tools/observer-stop-hook.test.mjs .claude/settings.json && git commit -m "feat(observer): execution_trace + chain_gaps + inheritance copy, timeout 15s (phase 3 task 16)"
```

### Task 17: Self-assessment in Stop-hook (TDD)

**Files:**

- Modify: `tools/observer-stop-hook.mjs`
- Test: `tools/observer-stop-hook.test.mjs`

- [ ] **Step 1: Write failing test**

```javascript
describe('self_assessment', () => {
  it('marks pending when API skipped', () => { expect(buildSelfAssessment({ apiResult: null }).self_assessment_pending).toBe(true); });
  it('parses valid', () => {
    const sa = buildSelfAssessment({ apiResult: '{"summary":"x","confidence_in_choice":0.8,"what_could_be_better":null,"lesson_learned":null}' });
    expect(sa.confidence_in_choice).toBe(0.8); expect(sa.self_assessment_pending).toBe(false);
  });
});
```

- [ ] **Step 2-4: Fail → implement → pass**

`buildSelfAssessment`. API к `REVIEWER_MODEL` (Opus) spec §4.5 в timeout-budget. Cost → `task_cost.self_assessment_*`. schema_minor→2. Run `npx vitest run tools/observer-stop-hook.test.mjs`.

- [ ] **Step 5: Flip flag + commit**

```bash
node -e "require('fs').writeFileSync(require('path').join(require('os').homedir(),'.claude','runtime','self-assessment-mode.json'),JSON.stringify({mode:'on'}))"
git add tools/observer-stop-hook.mjs tools/observer-stop-hook.test.mjs && git commit -m "feat(observer): self_assessment + retroactive fallback (phase 3 task 17)"
```

### Task 18: CREATE brain-retro-opus-reviewer.mjs + verify reviewer-agent (TDD, closes G16)

**Files:**

- Create: `tools/brain-retro-opus-reviewer.mjs` (**не существует — G16**), `tools/brain-retro-opus-reviewer.test.mjs`
- Modify: `.claude/agents/reviewer-agent.md` (verify)

- [ ] **Step 1: Verify reviewer-agent.md (создан commit 49aa4ba7)**

Read `.claude/agents/reviewer-agent.md` — verify frontmatter (tools, model=opus), 8-dim, adaptive v2/v3/v4. Обновить system prompt если изменился чек-лист. НЕ создавать (A3).

- [ ] **Step 2: Write failing test**

```javascript
import { buildReviewPrompt, parseReview } from './brain-retro-opus-reviewer.mjs';
describe('reviewer fallback handler', () => {
  it('v3 omits alternatives', () => { expect(buildReviewPrompt({ schema_version: 3 })).not.toContain('alternatives_considered'); });
  it('parses 8-dim review', () => {
    expect(parseReview('{"node_quality":"correct","chain_quality":"n/a","gap_assessment":"n/a","agent_self_assessment_accuracy":"accurate","error_root_cause":"n/a","alternative_better":null,"outcome_reviewed":"success","reasoning":"x"}').node_quality).toBe('correct');
  });
});
```

- [ ] **Step 3-4: Fail → implement → pass**

**CREATE** `tools/brain-retro-opus-reviewer.mjs` (G16 — файл не существует): `buildReviewPrompt(episode)` adaptive, `parseReview`, `reviewViaDirectApi(episode)` к Opus. Это direct-API fallback для reviewer subagent (spec §4.6). Run `npx vitest run tools/brain-retro-opus-reviewer.test.mjs`.

- [ ] **Step 5: Commit**

```bash
git add tools/brain-retro-opus-reviewer.mjs tools/brain-retro-opus-reviewer.test.mjs .claude/agents/reviewer-agent.md && git commit -m "feat(brain): CREATE reviewer fallback handler + verify subagent (phase 3 task 18)"
```

### Task 19: Sanity-generator + brain-retro v2 + self-retrospect skill

**Files:**

- Create: `tools/brain-retro-sanity-generator.mjs`, `.claude/skills/self-retrospect/SKILL.md`, `docs/observer/.self-retrospect-counter.json`, `docs/observer/sanity-checks/.gitkeep`
- Modify: `.claude/skills/brain-retro/SKILL.md`, `references/aggregation-template.md`
- Test: `tools/brain-retro-sanity-generator.test.mjs`

- [ ] **Step 1: Write failing test**

```javascript
import { generateCandidateQuestions } from './brain-retro-sanity-generator.mjs';
describe('sanity questions', () => {
  it('bugfix question when >10 bugfix', () => { expect(generateCandidateQuestions(Array(11).fill({ classifier_output: { task_type: 'bugfix' } })).some(q => /баг/i.test(q))).toBe(true); });
  it('max 5', () => { expect(generateCandidateQuestions([]).length).toBeLessThanOrEqual(5); });
});
```

- [ ] **Step 2-4: Fail → implement → pass**

`generateCandidateQuestions(episodes)` (spec §4.7). Run `npx vitest run tools/brain-retro-sanity-generator.test.mjs`.

- [ ] **Step 5: Update brain-retro SKILL.md**

Description → «раз в 1-2 недели» (3.1). New steps 5/6/9/11 (sanity + PII filter + reviewer Task() + opt-in self-retrospect + cost report) spec §4.7. Update `references/aggregation-template.md`.

- [ ] **Step 6: Create self-retrospect skill**

`.claude/skills/self-retrospect/SKILL.md` (spec §4.8).

- [ ] **Step 7: Init counter + sanity dir**

```bash
node -e "require('fs').writeFileSync('docs/observer/.self-retrospect-counter.json',JSON.stringify({last_run_at:null,episodes_since_last:0},null,2))"
node -e "require('fs').mkdirSync('docs/observer/sanity-checks',{recursive:true}); require('fs').writeFileSync('docs/observer/sanity-checks/.gitkeep','')"
```

- [ ] **Step 8: Coverage announcement — §4.9 (новое v1.2)**

Реализовать coverage-announcement (spec §4.9):

1. В `~/.claude/hooks/economy-mode.py` добавить строку-напоминание в per-turn инжект: «аннотируй покрытие задач (skill/node/hook/direct) в прозе + TodoWrite» (economy-mode сохраняется per DECISION POINT). Snapshot economy-mode уже в archive (Task 1) — откат через него.
2. Добавить подпункт-конвенцию в Pravila §17: «каждая non-conversation задача аннотируется coverage-пометкой (skill/node/hook/direct) в прозе + TodoWrite; источник — classifier_output».
3. Создать memory feedback `memory/feedback_coverage_announcement.md` + строку в MEMORY.md.
4. Создать flag `~/.claude/runtime/coverage-annotation-mode.json` = `on`.

Verify: `python "$HOME/.claude/hooks/economy-mode.py" < /dev/null` содержит coverage-напоминание; flag присутствует.

- [ ] **Step 9: Commit**

```bash
git add tools/brain-retro-sanity-generator.* .claude/skills/ docs/observer/.self-retrospect-counter.json docs/observer/sanity-checks/.gitkeep memory/ docs/Pravila_raboty_Claude_v1_1.md && git commit -m "feat(brain): sanity-generator + brain-retro v2 + self-retrospect + coverage announcement (phase 3 task 19)"
```

### Task 20: analyzer v4 + status-md + schema v4.3 + final flags

**Files:**

- Modify: `tools/brain-retro-analyzer.mjs`, `tools/status-md-generator.mjs`, `tools/observer-stop-hook.mjs`
- Test: `tools/brain-retro-analyzer.test.mjs`

- [ ] **Step 1: Write failing test**

```javascript
describe('analyzer v4', () => {
  it('aggregates inheritance', () => { expect(analyze([{ schema_version: 4, inheritance: { inherited_from_task_id: 'x' } }]).inheritanceCount).toBe(1); });
  it('aggregates review.node_quality', () => { expect(analyze([{ schema_version: 4, review: { node_quality: 'correct' } }]).reviewQuality.correct).toBe(1); });
});
```

- [ ] **Step 2-4: Fail → implement → pass**

`analyzer` +inheritance +review distribution +cost. `status-md-generator` +Cost/anomaly/self-retrospect/reviewer-ratio (spec §9.4). Run `npx vitest run tools/brain-retro-analyzer.test.mjs`.

- [ ] **Step 5: Schema v4.3 + cost-daily**

Parser writes `prompt_embedding_base64` + `outcome_reviewed` + extended task_cost (schema_minor→3). Stop-hook updates `~/.claude/runtime/cost-daily.json`.

- [ ] **Step 6: Flip final flags**

```bash
node -e "const fs=require('fs'),os=require('os'),p=require('path'); const d=p.join(os.homedir(),'.claude','runtime'); const f={'reviewer-mode':'subagent','self-retrospect-mode':'on','sanity-check-mode':'mandatory'}; for(const[k,v]of Object.entries(f)) fs.writeFileSync(p.join(d,k+'.json'),JSON.stringify({mode:v})); console.log('phase-3 flags on')"
```

- [ ] **Step 7: Full smoke**

Run: `npx vitest run tools/ && npx -y markdownlint-cli2 "docs/**/*.md" && ./bin/gitleaks.exe protect --staged`
Expected: PASS, 0 leaks.

- [ ] **Step 8: Commit**

```bash
git add tools/ docs/observer/ && git commit -m "feat(brain): analyzer v4 + status-md + schema v4.3 + phase-3 flags (phase 3 task 20)"
```

### Task 21: Phase 3 verification + rollback re-proof

**Files:** none (verification)

- [ ] **Step 1: Verify all 9 flags**

Run: `node -e "const fs=require('fs'),os=require('os'),p=require('path'); const d=p.join(os.homedir(),'.claude','runtime'); ['router-classifier-mode','router-gate-mode','self-assessment-mode','reviewer-mode','self-retrospect-mode','embedding-mode','sanity-check-mode','prompt-enrichment-mode','inheritance-mode'].forEach(f=>console.log(f, fs.existsSync(p.join(d,f+'.json'))?'OK':'MISSING'))"`
Expected: all 9 OK.

- [ ] **Step 2: Rollback dry-run (после всех фаз)**

Run: `node tools/test-rollback.mjs --dry-run`
Expected: OK.

- [ ] **Step 3: brain-retro e2e smoke (manual)**

Invoke `/brain-retro` крошечный период — verify sanity-questions, reviewer subagent spawn (или fallback), cost report. Document.

- [ ] **Step 4: Final regression + DoD**

Run: `npx vitest run tools/` (GREEN) + verify spec §16 DoD. Document each ✅.

- [ ] **Step 5: Finishing the branch**

Используй `superpowers:finishing-a-development-branch`.

**Phase 3 exit:** полный evidence pipeline, episode v4.3, reviewer subagent, self-retrospect, откат доказан повторно. Bootstrap начинается.

---

## Self-review (выполнено при написании v1.1)

**1. Spec coverage:** все 8 слоёв → задачи (Слой 1 Task 9, Слой 2 Task 10, Слой 3 Task 12, Слой 4 Task 13, Слой 5 Task 16-17, Слой 6 Task 18, Слой 7-8 Task 19). §17 → Task 5+13. Архив §7 → Task 4+6. Контролёры §9 → Task 6 (C1/C2) + Task 20 (C4). 16 находок v2.2 + 9 находок аудита плана — каждая «closes X».

**2. Placeholder scan:** код-шаги реальны. `claude-sonnet-4-6-YYYYMMDD` — резолвится Task 0/8. nodes.yaml capabilities — subagent.

**3. Type consistency:** `planRollback()` / `prefilter()` / `buildClassifierPrompt()` / `parseClassifierResponse()` / `shouldBlock()` / `detectMissedActivations()` / `shouldEmbed()` / `buildStateFromClassification()` / `buildExecutionTrace()` / `buildSelfAssessment()` / `buildReviewPrompt()` / `parseReview()` / `generateCandidateQuestions()` / `analyze()` — консистентны.

**Аудит-fixes inline:** Task 1 rollback FIRST + e2e proof; Task 2 economy vs §12 (G3); Task 4 registry-map (G14); Task 6 C1/C2 early (G8/G9); Task 10 accuracy-runner (G11); Task 15 parser fwd-compat (G5); Task 18 reviewer CREATE not keep (G16); rollback covers user-level + episodes preserved.

---

**Версия плана:** 1.2 от 2026-05-25 (v1.1 → v1.2: DECISION POINT подтверждён economy-keep/§12-remove; Task 19 +step 8 coverage announcement §4.9).
**Источник:** spec v2.3.
**Фаза 4 (distillation):** отдельный план через ~6 месяцев.
