# Router-mentor — Handoff к следующей сессии (E/G закрыт · Блок B отбрейнстормлен)

**Дата:** 2026-06-09 · **Кодовая фраза эпика:** «роутер-наставник».
**Ветка:** `worktree-brainrepo` · **commit-not-push** (origin не тронут).
**Сделано прошлой сессией:** (1) E/G warm-up batch ЗАКРЫТ; (2) Блок B (вшивка) прошёл brainstorming + adversarial-разбор — дизайн Классов 1+2 готов и представлен (ждёт «ок» → spec). R-08 отделён в свой будущий spec.

---

## === ПРОМТ ДЛЯ НОВОЙ СЕССИИ (скопировать целиком) ===

роутер-наставник. Продолжаем подбирать хвосты эпика. Прошлая сессия закрыла разогрев E/G (commit-not-push) и отбрейнстормила Блок B (вшивка). НЕ приступай к коду сразу — прочитай состояние, подними согласованную цепочку скилов, действуй по ней. Всё инлайн, субагенты/Task/Workflow ЗАПРЕЩЕНЫ.

ДЕРЕВО: `c:\моя\проекты\портал crm\Документация\.claude\worktrees\brainrepo`, ветка `worktree-brainrepo`. Git — ТОЛЬКО PowerShell (`git -C "<wt>" ...`). Сверь верх: `git -C "<wt>" log -10 --oneline` (ожидаемый верх — этот handoff `2026-06-09-router-mentor-blockB-handoff`; под ним `2900554d` T7 E/G).
ПРОЧИТАЙ ПЕРВЫМИ: `docs/superpowers/plans/2026-06-09-router-mentor-blockB-handoff.md` (этот файл — полный дизайн Блока B + квирки) + `docs/superpowers/plans/2026-06-08-router-mentor-loose-ends-registry.md` (реестр, E/G помечен ✅).
ДАЛЬШЕ: спроси владельца, что берём. **Рекомендация — закончить Блок B Классы 1+2** (дизайн §«Дизайн Блока B» ниже уже утверждён по структуре): подними `superpowers:writing-plans` → spec уже спроектирован, пиши план по 4 пунктам → TDD-исполнение (`superpowers:executing-plans`, инлайн). Альтернативы: R-08 (иерархические волны стены М2 — свой spec + adversarial-разбор), мелочи Блока G/C, либо передать на этап 3-4 владельцу (активация).
ЦЕПОЧКА СКИЛОВ (что сработало): для дизайна — brainstorming → audit-context-building → sharp-edges → variant-analysis (adversarial «не пробьёт ли дыр в машинах») → writing-plans → executing-plans (инлайн TDD: наблюдаемый RED до prod-правки `tools/*.mjs`) → verification-before-completion → regression. НЕ requesting-code-review. Скилы инлайн, coverage `direct:<role>`/`chain:<...>`.
ЖЁСТКОЕ: commit-not-push (пуш ТОЛЬКО по слову «пуш» через `finishing-a-development-branch`); 1-я строка ответа «экономия:…», 2-я «coverage:…»; CLAUDE.md в worktree НЕ трогать (чужая зона); жёсткие стены М2/М5/М4/М6 не ослаблять; нормативку не двигать.
СТАРТ: реестр + этот handoff → выбор хвоста у владельца → цепочка скилов → действуй. Кодовая фраза: «роутер-наставник».

## === КОНЕЦ ПРОМТА ===

---

## Что закрыто прошлой сессией: E/G warm-up batch ✅

7 атомарных коммитов `cfc4e0a8..2900554d` (commit-not-push), регрессия tools-only **3189 passed / 2 skipped / 0 failed**. Спек+план `docs/superpowers/{specs,plans}/2026-06-08-router-mentor-eg-warmup-batch*` (`62d3352d`/`0774a41f`/`f8015939`).

| Таск | Что | Коммит |
|---|---|---|
| T1 (P3) | release-класс `classifyTask` не ловит голый `commit` | `cfc4e0a8` |
| T2 (P2) | PII count по единому конвейеру sanitize, overlap раз (SE-2) | `84f75abb` |
| T3 (P1) | узкий `stripPastedContext` (fenced+blockquote) — 4-й FP-класс, FP-смещение гейта сохранено (SE-1) | `5ae0b135` |
| T4 (P4) | деталь-рендер доски + `escapeCell` anti-injection (SE-3) | `cf9f803d` |
| T5 (P5) | docstring `node-graph` + 2 пиннинг-инварианта (reviewer no-op уже был задокументирован) | `553ddea4` |
| T6 (P6) | DOC-1 escape-awareness callout в M7 spec §10 | `a85d7f9d` |
| T7 | E/G помечен ✅ в реестре хвостов | `2900554d` |

Жёсткие стены не тронуты; единственный затронутый гейт (observer routing-gate) сохранил FP-смещение.

---

## Дизайн Блока B (вшивка) — Классы 1+2 (отбрейнстормлен, готов к writing-plans)

**Решение владельца по структуре:** делаем «весь B», но **сплит** — этот spec = Классы 1+2 (R-09/R-24/R-30/reconcile); **R-08 (волны стены М2) — отдельным spec следующим проходом** (он меняет sealed-формат плана, самая рискованная M2-работа).

**Все 4 пункта — observation-only: гейт-решения НЕ меняют, hard-wall mains НЕ трогают.** Реюз паттерна `guardBoardBlock` (pure `compute*Block` + fail-quiet wiring в `status-md-generator.main()` через `inputs.*Block`, try/catch→null).

1. **R-09 — блок «Очередь обучения роутера» в STATUS.** `loadQueue({path})` (фикс. runtime-путь, напр. `~/.claude/runtime/router-learning-queue.json`) → `statusSignal`/`renderApprovalSection` ([tools/router-learning-queue.mjs](../../../tools/router-learning-queue.mjs): exports `makeQueueEntry`/`enqueue`/`pendingCount`/`applyApprovalBatch`/`renderApprovalSection`/`statusSignal`/`saveQueue`/`loadQueue`). Пустая/нет файла → «очередь пуста». Read-only.
2. **R-24 — блок «Покрытие дверей» в STATUS.** `auditDoors({tools, matcher, seeds})` + `auditExempt({exempt, isMutating})` ([tools/door-coverage.mjs](../../../tools/door-coverage.mjs)). matcher — из уже-читаемого `.claude/settings.json` манифеста (status-md-generator.main уже читает его для guardBoardBlock, ~стр. 583); tools — канонический список мутирующих инструментов (Edit/Write/MultiEdit/NotebookEdit/Bash/Task/Skill/MCP-писатели); seeds — `SEED_SKILLS`/`SEED_TOOLS` из `enforce-supreme-gate.mjs`. Read-only.
3. **R-30 — блок «Целостность журналов» в STATUS (reframe).** Вместо хирургии mains машин М1/М5/М6: `verifyChain(entries, headSig, {key})` ([tools/action-journal.mjs:53](../../../tools/action-journal.mjs)) вызывается живьём **в read-only STATUS-генераторе** sweep'ом по journal-файлам в `~/.claude/runtime/` → блок ok / broken-at. Требование «verifyChain живьём» выполнено observation-only, без новых block-путей, без понижения fail-CLOSE. (key — `resolveReceiptKey()`; journal-файлы грузить через `loadJournal`/прямой парс.)
4. **enforce-reconcile.main() reader.** Реальный парс журнала намерений в `main()` ([tools/enforce-reconcile.mjs](../../../tools/enforce-reconcile.mjs): чистые `reconcileAction`/`findOrphanIntents` ГОТОВЫ, main — намеренный каркас) → WARN в stderr, **НИКОГДА не блок** (PostToolUse). Изолирован, **инертен** до регистрации хука владельцем (после пола М5, owner-шаг A3).

**Границы (не пробить машины):** п.1-3 — только `status-md-generator` (вывод, не гейт); п.4 — только `enforce-reconcile.main` (инертен). Стена М2 / пол М5 / судья М4 / escape М6 НЕ трогаются.

**Карта порядка активации (для владельца, НЕ активировать):** STATUS-блоки (1-3) живы сразу — post-commit генератор уже зарегистрирован, read-only безопасно; reconcile-reader (4) инертен до регистрации PostToolUse `enforce-reconcile` владельцем.

**TDD:** каждый `compute*Block` (`computeLearningQueueBlock` / `computeDoorCoverageBlock` / `computeJournalIntegrityBlock`) — pure, RED→GREEN в изоляции; wiring в `status-md-generator.main` — fail-quiet (паттерн `guardBoardBlock`, см. [tools/status-md-generator.mjs:42-67](../../../tools/status-md-generator.mjs) + main ~580-587). Регрессия ≥ **3189**.

**Статус дизайна:** структура утверждена владельцем (сплит 1+2 / R-08 отдельно; R-30 как STATUS-surface). Финальное «ок» на детали дизайна не было дано (сессия ушла в переезд) → новая сессия: либо подтвердить и сразу `writing-plans`, либо короткий re-confirm развилок выше.

### R-08 — для отдельного будущего spec (НЕ в этом)
**Критическая находка (зафиксировать в том spec):** `step-pointer.mjs` — **только навигация** (стек уровней index/length), он НЕ определяет, откуда под-шаги и НЕ проверяет `под-действие ⊆ scope родителя`. Инвариант стены М2 — `actionMatchesStep(step, action)` где `step` из **подписанного** плана ([enforce-supreme-gate.mjs:130-166](../../../tools/enforce-supreme-gate.mjs)). Развилка:
- **ОПАСНО:** контроллер на лету создаёт под-шаги (неподписанные) → обход М2.
- **БЕЗОПАСНО:** под-шаги из **подписанного иерархического плана** (sealed владельцем); `step-pointer` навигирует по запечатанному дереву; каждый лист — подписанный шаг. Инвариант сохранён. Это меняет формат плана (`plan-lock` seal/verify) + step-модель стены — собственный adversarial-разбор обязателен.

---

## Остальные хвосты эпика (карта, из реестра)

| Блок | Что осталось | Кто |
|---|---|---|
| **B** вшивка | R-08 (иерархические волны стены М2 — свой spec) — после Классов 1+2 | Claude код + владелец порядок |
| **A** активация | live-wiring судьи М4 / Фаза 8 переезд §10 / регистрация М1-М6 в settings.json / увольнение v4-зоопарка / push | владелец (рубильник) |
| **C** контракты | R-06 K4 Write-исключение / R-10 G6 адаптер чужого скила (НЕ построен) / М4 think-layer 4 пункта / М6 FIX-5 (подпись escape, осознанно нет) / М1 атомарность журнала / М2 контракты T1-T9 | частично Claude / владелец |
| **F** архитектурные | enforce-hole-3 confidence trust-level (вариант C, Stage 4) / остаточный предел ~0.5% | решение владельца |
| **G** периферия | Фаза 2 observer (LLM agent-судья качества) / embedding-index defer / `observer-self-assessment-api.test.mjs:258` pre-existing fail | Claude/владелец |
| **H3** | few-shot память роутера | владелец → Claude |

**Машины М1–М7:** код собран (TDD), всё на `worktree-brainrepo`, commit-not-push, НЕ активированы. Критический путь: Этап 1 H ✅ → Этап 2 B (вшивка, Claude) → Этап 3 shadow-обкатка (владелец) → Этап 4 A активация+Фаза 8+push (владелец).

---

## Квирки сессии (подтверждены, экономят время новой сессии)

- **vitest:** `npx vitest run --root "<wt>/app" --config "<wt>/app/vitest.config.tools.mjs" <фильтр> --reporter dot` — БЕЗ `cd app`, с явным `--root` на worktree (`cd` в `.claude`-путь режет router-гейт). После первого Bash cwd залипает в `app/` — дальше без `cd`.
- **git** — PowerShell, `git -C "<wt>"`, литеральные пути.
- **PowerShell-гейт режет тело коммита:** `>` и `>=` принимаются за redirect; отдельные слова (`distinct`/`polya`/`razdelnye` — латиница-не-в-whitelist) за cmdlet → **короткие single `-m` ASCII-сообщения**, без редких слов; стейдж отдельным `git add`-вызовом. Длинные двух-`-m` русские сообщения иногда проходят, иногда нет — не рисковать.
- **`enforce-tdd-real-test-verifier`:** КАЖДАЯ правка `*.test.mjs` через Edit должна сама содержать `expect`+`it`, ссылаясь на prod-файл. Импорт-only правка отклоняется → класть новый импорт + тесты ОДНОЙ правкой (ESM-импорты хойстятся — можно top-level import в конце файла).
- **`.scratch/*.txt` для commit-msg** триггерит тот же verifier → коммитить `git commit -m`, не `-F scratch`.
- **TDD-gate на comment-only правке `.mjs`:** наблюдаемого RED нет (поведение не меняется) — честно: пиннинг-тест пинит документируемый инвариант (GREEN), не фабриковать фальш-RED; если gate жёстко блокирует — фиксировать deferred, не обходить обманом. (В E/G comment-edit node-graph прошёл без блока.)
- **node -e / python -c / bash -c** — hard-blacklist гейта; разовые проверки — через vitest-тест.
- **Список файлов** — через Grep (Glob ломается на junction worktree).
- **Память харнесса** (`~/.claude/.../memory/`) — пишется ТОЛЬКО при активном `claude-md-management` + coverage `direct:memory-sync`; в этом worktree CLAUDE.md off-limits → знание фиксировать в `docs/superpowers/plans/*` (git).
- **Чужая грязь дерева** (observer-jsonl авто-регенерат / `.scratch/` / чужие планы Фаз 4-7 / `patch-*.mjs` / `setup-nm.mjs`) — НЕ коммитить; стейджить свои файлы поимённо.
- **«Can't find lefthook in PATH»** — ШУМ, игнор.
