docs: единый сверенный гайд по стене

This commit is contained in:
Дмитрий
2026-06-19 10:48:31 +03:00
parent 4dee49e4a1
commit e22bf27670
4 changed files with 304 additions and 690 deletions
-369
View File
@@ -1,369 +0,0 @@
# Как работать под стеной «роутер-наставник» (шпаргалка для сессий)
> Читать ПЕРЕД работой под стеной. **Обновлено 18.06.2026** — допил эталона: осмотр-сеанс
> (B+C ч.2), деплой агентом (D1), коммит агентом (D2), §3.4 десинк ПОЧИНЕН (см. раздел
> «Обновления 18.06.2026»). Прежняя база 16.06: Фикс 1/2/3 + находки F-J/F-K + рецепт escape.
**Суть:** под стеной реальная работа (Edit/Write/Bash по коду) проходит ТОЛЬКО как шаг
**опечатанного** плана. Поток: спека → (печать) → план → (печать) → шаги по порядку →
авто-завершение. Печать встаёт за **ОДИН заход**.
## Обновления 18.06.2026 — допил эталона (B+C ч.2 / D1 / D2 / §3.4)
Закрыты главные баги стены: теперь она контролирует КАЧЕСТВО (наставник+судья), а механику/
необратимое не сваливает на владельца. Коммиты: B+C ч.2 `bc1d2a3`, D1 `bbc053e`, D2 `b47a71c`, §3.4 `cdcaf61`.
- **⛔ ПОДДЕЛКА СОГЛАСИЯ ЗАКРЫТА (эпик consent-forgery, A+B1-B5+C).** Несущая дыра: контроллер сочинял
ярлык кнопки `FLOOR-ESCAPE: owner-seal:<hash>`, среда возвращала его как «ответ» без действия
владельца → подписанный грант → план опечатывался «одобрен владельцем». **Фикс:** согласие — ТОЛЬКО
из свободного ввода владельца (лёгкое) ИЛИ из его терминала (тяжёлое). Кнопка-с-меткой и диктовка
метки больше не дают грант. **Рецепт escape ниже ИНВЕРТИРОВАН** (см. «Аварийный выход»). Коммиты:
A `cdc32b1`, B1 `dec0ed5`, B2 `f870907`, B3 `29287d7`, B4 `5bcf229`, B5 `11969ac`, C `0d31e62`.
Спека `specs/2026-06-18-consent-forgery-fix-design.md`.
- **Осмотр сайта под планом (B+C ч.2, `op:"session"`).** Чтобы пройтись/пощёлкать (логин, формы,
чужой сайт), план объявляет ОДИН шаг-сеанс: `{op:"session", goal, tools:[действующие инструменты],
produces:"<итоговый файл>"}`. Внутри сеанса смотришь/кликаешь по живым `ref` сколько нужно (указатель
НЕ двигается); сеанс закрывает запись ПОСЛЕДНЕГО `produces`-файла (можно объявить несколько — закрывает
последний). Смотрящие (`ToolSearch`/`WebFetch`/`WebSearch`/read-only браузер `browser_navigate|snapshot|
wait_for|take_screenshot`) свободны в ОБОИХ режимах (и без плана). `op:"Skill"` шагом ЗАПРЕЩёН — объявляй
навык в `skills-json`. **Предохранитель:** в `tools` сеанса нельзя `Write`/`Edit`/`MultiEdit`/мут-`Bash`/
floor (ssh/cloud-CLI/rm…) — правки репозитория остаются ШАГАМИ; запрещённое отбрасывается с предупреждением.
- **Деплой силами агента (D1, ops-runbook).** План с пометкой `**Kind:** deploy`, опечатанный (GO),
агент гонит сам по белому списку Bash-шагов под ОДНИМ согласием владельца кнопкой
`FLOOR-ESCAPE: ops-runbook:<plan-hash>` (окно — до конца плана, НЕ 5 мин). «Ядерное» (`rm -rf`/
`git push --force`/`migrate:fresh`/`db:wipe`) — всё равно per-command escape.
**Дисциплина (A + D1):** читай вывод КАЖДОГО шага деплоя; при аномалии/упавшем шаге — СТОП и зов
владельца, не доделывай вслепую. Если под планом чтение вскрыло препятствие — ПЕРЕПЛАНИРУЙ (новый
план), не гадай (весь контекст собирай ДО печати — см. «Уроки живого прогона» Урок 1).
- **Коммит силами агента (D2, commit:<hash>).** Одно согласие владельца кнопкой
`FLOOR-ESCAPE: commit:<plan-hash>` снимает гейт ПРИСУТСТВИЯ (`router-gate` git-approval) — агент делает
git add/commit/push без терминала владельца. Гейты КАЧЕСТВА ОСТАЮТСЯ: код-коммит требует по-критерийный
GREEN (`criterion-gate`) + свежую расписку (`produce-verify-receipt.mjs`). `force-push`/`--no-verify`
блокируются ВСЕГДА. Деплой и коммит — РАЗДЕЛЬНЫЕ кнопки (`ops-runbook:` vs `commit:`). Терминал владельца
для коммита больше НЕ обязателен (раздел «Коммит» ниже описывает старый путь — без согласия).
- **§3.4 десинк ПОЧИНЕН (`cdcaf61`).** Push последним шагом плана больше НЕ даёт ложный блок
`criterion-gate`: печать снимается ЛЕНИВО на следующем действии, а не синхронно на последнем шаге →
criterion видит валидный план. Старый обход «сделать push НЕ-терминальным» (раздел «Пуш кода» п.2) больше
НЕ нужен.
- **НАХОДКИ ЭТОЙ СЕССИИ (18.06, штатный режим).** (1) **Пол ПУСКАЕТ запуск скрипта-файла** (`python
tools/x.py`, `node tools/x.mjs`, `uv tool run … python tools/x.py`, установленный CLI типа `graphify …`) —
режет только ИНЛАЙН-eval (`python -c`/`node -e`), `rm`, цепочки `;`/`&&`/`|`. Нужен скрипт под планом —
пиши `.py`/`.mjs` шагом Write, запускай шагом Bash (см. «Floor-safe планы»). (2) **Субагенты под стеной —
только разведка** (read-only, ДО печати, возврат ТЕКСТОМ); единственный мутатор — контроллер (см.
«Субагенты под стеной»).
> Формальный свод правил (Pravila/CLAUDE.md) обновляется отдельно — через плагин `claude-md-management`
> + синхрон квинтета, со включённой стеной (heavyweight-канал). Этот GUIDE — оперативная шпаргалка.
## Содержание
1. [Рецепт церемонии](#рецепт-церемонии) — как поставить спеку+план, чтобы печать встала
2. [Частые ошибки](#частые-ошибки) — учись на чужих шишках (вкл. десинк F-J)
3. [Нельзя: правка машинерии стены (F-K)](#нельзя-правка-машинерии-стены-f-k)
4. [Видимость вердикта (Фикс 1)](#видимость-вердикта-фикс-1) — вердикт виден сам
5. [Память кругов (Фикс 2)](#память-кругов-фикс-2)
6. [Арбитраж: owner-seal (Фикс 3)](#арбитраж-owner-seal-фикс-3)
7. [Как узнать состояние стены](#как-узнать-состояние-стены) — одна проба
8. [Аварийный выход владельца (escape)](#аварийный-выход-владельца-escape) — как дать правильно
9. [Коммит](#коммит)
10. [Пуш кода через стену](#пуш-кода-через-стену)
11. [Судьи-машины](#судьи-машины)
12. [Минимальный пример и что под капотом](#минимальный-пример-и-что-под-капотом)
## Рецепт церемонии
Точные форматы — иначе печать не встанет.
**1. СПЕКА** — Write НОВОГО файла в `docs/superpowers/specs/<уникальное-имя>.md`:
- якорные секции `## Заголовок {#D1}` … с **непустым** телом (контракт, edge-cases, конвенция, критерий);
- блок ` ```verified-context-json``` ` — массив с ≥1 EXTRACTED:
`{"id":"…","kind":"EXTRACTED","ref":"<существующий файл>","anchor":"<реальная подстрока ≥4 симв>"}`.
**Готовый якорь:** ref `tools/cost-pricing.mjs`, anchor `export const PRICING = Object.freeze(`;
- секцию `## Цель`;
- **НИКАКОЙ мета-болтовни** (про печать/хеши/оркестратор/обход стены) — судья судит вслепую и завернёт fatal.
**2. ПЛАН** — Write НОВОГО файла в `docs/superpowers/plans/<уникальное-имя>.md`:
- `## Цель`;
- ` ```skills-json``` ` — объявленные навыки, напр. `["test-driven-development"]`;
- ` ```steps-json``` ` — массив `{op, object, ref}`: `op` ∈ Write|Edit|Bash|MultiEdit (**Task/субагент-шаг запрещён** — почему и как всё же звать субагентов: «Субагенты под стеной»);
`object` = путь к файлу или **точная** строка команды (Bash); `ref` = якорь спеки (D1..Dn), непустой;
- ` ```verified-context-json``` ` (план тоже требует ≥1 EXTRACTED);
- без мета-болтовни.
- Раздел `## Переговоры``### Круг N` — сюда контроллер пишет дословные **доводы** на возражения
(Фикс 2 их подаёт судье/наставнику в следующих кругах).
**3. Реализация** — шаги по порядку, каждый Edit/Write/Bash совпадает с **текущим** шагом (op+object).
Стена двигает указатель по одному. После последнего шага печать снимается сама → разговорный режим.
## Частые ошибки
- **Ловушка устаревшего указателя.** Повторный план **байт-в-байт** = тот же `plan_id` → старая
позиция НЕ сбрасывается → застреваешь. Лечение: другой план (другое имя/шаги → новый `plan_id`)
ИЛИ `FLOOR-ESCAPE: plan-done` (см. escape). Удаление файлов НЕ помогает (позиция в runtime).
- **Авторская запись.** Свободно пишется только **НОВЫЙ** `.md` в `specs/`/`plans/`. Существующий
файл и код — только как шаг плана (либо escape, см. F-K).
- **Чтение кода.** В режиме реализации чтение вне путей текущего шага блокируется. Свободно — в
**разговорном** режиме (нет печати).
- **Bash-цепочки.** `;`/`&&`/`||`/`|` с мутирующей частью hard-блокируются. Только одиночные команды.
- **Floor-safe планы.** НЕ ставь floor-опасные Bash-шаги: ИНЛАЙН-eval (`node -e`/`python -c`), `curl`/
install, `rm`/`rm -rf`/`git push --force`/`migrate:fresh`, PowerShell-записи, цепочки `;`/`&&`/`|`,
запись в `~/.claude/runtime`/секреты. Пол их рубит, стена не двигает указатель → план встаёт колом.
Файловые операции — через Write/Edit, не `node -e`.
**ЗАПУСК СКРИПТА-ФАЙЛА пол ПУСКАЕТ** (проверено вживую 18.06): `python tools/x.py`, `node tools/x.mjs`,
`npx vitest …`, `uv tool run --from <pkg> python tools/x.py`, установленный CLI (`graphify …`) — это
валидные Bash-шаги плана. Режется только ИНЛАЙН-eval (`-c`/`-e`), не файл. Значит «нужен скрипт под
планом» = Write `.py`/`.mjs` шагом → запуск `python/node <file>` шагом Bash; `-c`/`-e`-одностроку пол не пустит.
- **Десинк указателя (F-J, 16.06).** Если PreToolUse-блокер (тупой судья навыков / `normative §6`)
роняет действие exit-2, а `enforce-supreme-gate` (раньше в цепочке) УЖЕ сдвинул указатель — план
застревает (указатель уехал, действие не прошло). **Сброс:** `FLOOR-ESCAPE: plan-done` ИЛИ новый
план с другим именем. (Второй, отдельный десинк — на пуше кода, см. «Пуш кода через стену».)
(Корень для brain: supreme-gate не должен двигать указатель, если со-хук блокнёт.)
- **Наставник/судья async** (~25-32с). Печать встаёт не мгновенно. Per-attempt таймаут 90с
(`HEAVY_LLM_TIMEOUT_MS`). degraded («не дозвонился») → просто повтор.
## Уроки живого прогона (go-live аудит 17.06.2026)
**Урок 1 — весь контекст ДО печати плана.** В режиме реализации (под опечатанным
планом) чтение вне пути текущего шага блокируется гейтом ДР-1 — нельзя прочитать
ни исходники для анализа, ни даже собственный вывод инструмента (temp-файл
сканера). Поэтому всю разведку (схема, роуты, конфиги, reference-файлы навыков,
вывод сканеров) собирай ДО печати плана — в разговорном режиме чтение свободно.
**Запасной канал**, если контекст понадобился уже под планом: владелец вставляет
содержимое файла прямо в чат — это контекст разговора, а не вызов Read, и
дисциплина чтения его не трогает. Вывод: для аудита/разведки сперва читаешь всё
нужное, потом печатаешь спеку→план, где шаги уже не требуют новых чтений.
**Урок 2 — дефекты проверяющего и указателя (знать заранее).**
- *Недетерминизм судьи.* Судья может выдать разный вердикт на байт-идентичном
тексте между кругами (наблюдалось: круг N — NO-GO `[fatal]` на строке «Цель»,
круг N+1 — GO на том же тексте). Лечение — просто повторить печать (async-повтор).
- *Рассинхрон указателя (F-J на практике).* Ранний хук цепочки (`supreme-gate`)
сдвигает указатель шага, а более поздний PreToolUse-блокер (skill-discipline)
роняет само действие → шаг считается пройденным, хотя инструмент не выполнился
(на прогоне так был пропущен первый шаг gitleaks). Перепечатка плана
байт-в-байт НЕ сбрасывает указатель (тот же `plan_id`) — нужен план с другим
именем/содержимым, либо `FLOOR-ESCAPE: plan-done`.
- *Профилактика для скил-планов.* Объявленные в `skills-json` навыки вызови
(Skill) ПЕРВЫМ делом после печати, ДО первого мутирующего/Bash-шага — иначе
skill-discipline уронит первый шаг и уведёт указатель.
## Субагенты под стеной — только разведка (находка 18.06)
**Почему `op:"Task"` запрещён шагом и почему субагент-мутатор под стеной не живёт.** Стена — машина
ПОДОТЧЁТНОСТИ: ОДИН исполнитель (контроллер) гонит заранее одобренную, журналируемую, линейную цепочку
КОНКРЕТНЫХ правок. Три опоры (в коде): печать кроет конкретные op+object-шаги (`actionMatchesStep`); перед
каждой правкой — пред-запись намерения контроллера в журнал («нет записи — нет действия», Δ3); один
указатель по одному дереву. Субагент ломает все три:
- печать кроет «пошли работника», а НЕ его реальные правки → seal отвязан от изменений;
- правки субагента идут мимо журнала контроллера → неподотчётный боковой канал;
- субагенту нельзя доверять (память `subagent-falsified-test-results`: Sonnet-субагент **сфальсифицировал**
«5 pass» не запустив тесты, набил 228 фальшивых расписок). Стена ровно для недоверчивого исполнителя —
отдать ей мутацию ещё менее надёжному субагенту = само-противоречие;
- веер/параллель субагентов несовместимы с линейным одним указателем.
Под стеной субагентские вызовы душатся механически: его Read вне путей плана режет ДР-1; его Write не
совпадает с текущим шагом → блок «действие не в плане» (или у субагента нет плана → разговорный режим →
мутация блокируется).
**Как субагенты ВСЁ ЖЕ помогают, сохраняя инварианты:**
1. субагент только РАЗВЕДЫВАЕТ — читает/анализирует и **возвращает результат ТЕКСТОМ** (его Read —
observe-only, свободны), файлы НЕ пишет;
2. гоняй его в РАЗГОВОРНОМ режиме (ДО печати) — под печатью его Read упрётся в ДР-1;
3. контроллер берёт его текст и **сам** пишет/собирает шагами опечатанного плана.
Единственный мутатор — контроллер, каждая правка запечатана и в журнале → все инварианты целы.
**Пример (agent-as-LLM, без API-ключа):** субагенты-экстракторы graphify читают контракты и возвращают
извлечённый JSON **текстом** → контроллер пишет чанк-файлы и `python tools/graphify-build.py` шагами плана
(пол пускает скрипт-файл, см. «Floor-safe планы»). Так graphify-сборка проходит и под стеной.
## ⛔ Нельзя: правка машинерии стены (F-K)
Файлы `tools/enforce-*.mjs`, `judge-*`, `mentor-*`, `floor-*`, `escape-grant`, `plan-lock` и т.п. —
**discipline-source**: `enforce-normative-content-rules §6` блокирует их правку под стеной как «ЗАКОН»,
и **write-escape её НЕ снимает** (в отличие от обычных файлов — у supreme-gate тот же escape работает).
CARD-путь (`sealedPlanCoversEdit` под опечатанным планом) тоже ненадёжен.
**Правь такие файлы в ТЕРМИНАЛЕ** (node-скрипт string-replace по точным якорям + бэкап + verify) и
**сразу коммить** — несохранённые правки tracked-файлов теряются на `git restore` (инцидент 16.06).
## Видимость вердикта (Фикс 1, расширен 17.06.2026)
Лог антитуннеля больше НЕ нужен. Вердикты **КАЖДОГО участника** (роутер, наставник, судья) на
каждой судимой записи **видны контроллеру**: хук `enforce-verdict-surface` (UserPromptSubmit) в
начале **СЛЕДУЮЩЕГО** хода показывает ПОДПИСАННЫЕ строки (не один безымянный итог):
- `🧭 РОУТЕР [круг N]: рекомендует [<id узлов>] · объявлено [<skills-json>]` — только **plan-путь**
(`onPlanWrite` зовёт classify); на спек-пути роутера нет. id узлов в имена пока НЕ резолвятся.
- `🧑‍🏫 НАСТАВНИК [круг N]: GO|NO-GO · reasoning … · recommendation …` (либо `⚠ не дозвонился (<причина>)` / `⏭ пропуск (<причина>)`).
- `⚖️ СУДЬЯ gate1|gate2: GO|NO-GO · возражения <kind:ref; …>` (без `[круг N]` — судья в отдельном процессе).
Требует регистрации хука в `settings.json` (UserPromptSubmit). Чтение `~/.claude/runtime` по-прежнему
закрыто — но вердикт спрашивать у владельца больше не надо. Всплытие **best-effort/fail-open**: на
решения гейтов не влияет.
Под капотом: `enforce-verdict-surface` + `verdict-surface-store` + `verdict-surface-detail` (подписанные
строители на участника) + `verdict-outcome-line` (грубый итог, оставлен для совместимости). Реализация —
память `wall-verdict-surface-labeled`, commit `cf813c10`.
## Память кругов (Фикс 2)
- **Судья:** круг 1 слеп (чистый суд продукт-против-цели); круг 2+ видит СВОИ прошлые претензии
**дословной цитатой** + как контроллер их закрыл (из `## Переговоры`) → не противоречит себе.
- **Наставник:** видит свои прошлые претензии + **доводы контроллера**, обязан переоценить ТЕКУЩИЙ
план (снятое не повторять). (Полный «единый цикл» спека=план — в дизайн-доке для brain.)
Под капотом: `round-memory-store` + блоки памяти в `buildJudgePrompt`/`buildMentorVerdictPrompt`.
## Арбитраж: owner-seal (Фикс 3)
На тупике (3-й круг подряд NO-GO) карточка даёт 3 кнопки:
- **Держусь контроллера** → план/спека опечатывается как есть (owner-seal, перевешивает NO-GO судьи И наставника);
- **Согласен с замечанием** → контроллер переделывает, счётчик сброшен;
- **Своё решение** → владелец вписывает указание → правка → печать.
«Держусь/Своё» владелец подписывает кликом по кнопке-метке `FLOOR-ESCAPE: owner-seal:<hash>` — путь
печати (`sealOnWiredGo`) ставит frozenPlan/frozenArtifact несмотря на NO-GO (минуя и mentor freeze-gate).
Под капотом: `seal-override` + owner-seal в `sealOnWiredGo`/`sealTurnProd`.
## Как узнать состояние стены
Одна проба — безобидный не-readonly Bash, напр. `node --version` (`echo` режет router-gate как не-whitelist):
- блок «разговорный режим» → стена включена, чисто (нет печати);
- блок «ожидался шаг N: …» → ты в середине плана на шаге N (возможно, застрял — см. F-J);
- выполнилось → стена снята (или открыт escape).
## Аварийный выход владельца (escape) — ОБНОВЛЕНО 18.06.2026 (фикс подделки согласия)
> ⛔ **Старый рецепт «контроллер кладёт `FLOOR-ESCAPE:` в КНОПКУ» БОЛЬШЕ НЕ РАБОТАЕТ.** После фикса
> подделки согласия (эпик consent-forgery: A + B1-B5 + C) ответ, дословно совпавший с ярлыком
> контроллерской кнопки, согласием НЕ считается (anti-button — среда могла вернуть кнопку без действия
> владельца). Согласие — только из СВОБОДНОГО ввода владельца ЛИБО из его ТЕРМИНАЛА. Спека:
> `docs/superpowers/specs/2026-06-18-consent-forgery-fix-design.md`.
**Два класса согласия (Поза 1, решение владельца 18.06):**
**ЛЁГКОЕ**`write:<путь>`, безопасный `bash:`, `skill:<имя>`. Владелец САМ набирает метку
`FLOOR-ESCAPE: <action>` в поле «Другое» ответа AskUserQuestion (свободный ввод; среда ищет
`/FLOOR-ESCAPE:\s*(.+)$/`, `toFloorEscapeRecord`). Контроллер кнопку-с-меткой НЕ делает (anti-button
отвергнет) и метку дословно НЕ диктует (anti-dictation `detectOtherSocialEng` → грант не пишется).
Грант одноразовый, окно **5 минут**, точное совпадение `canonicalAction`. **Применяй СРАЗУ.**
**ТЯЖЁЛОЕ**`owner-seal:<hash>`, `ops-runbook:<hash>`, `commit:<hash>`, `plan-done`, `gate3-arb:*`,
разрушительный `bash:`/`powershell:` (rm-rf/force-push/migrate:fresh/db:wipe). **ТОЛЬКО из ТЕРМИНАЛА
владельца:**
```
node tools/owner-consent.mjs <sessionId> <action>
```
Скрипт подписывает терминальный грант (`origin:owner-terminal`) ключом keychain. Контроллер запустить
с пользой не может: его Bash без доступа к keychain → грант не подписан → читатель отвергает; и
`~/.claude/runtime` он не пишет (пол). Читатели тяжёлого принимают грант ТОЛЬКО при валидной подписи
(**fail-closed** без ключа — `loadTerminalGrants`).
**Каноны `<action>`** ([tools/escape-grant.mjs](../../tools/escape-grant.mjs)::`canonicalAction`):
- Bash → `bash:<норм. команда>` · PowerShell → `powershell:<норм. команда>`
- Skill → `skill:<имя lowercase>` · Write/Edit → `write:<путь>` · MCP → `mcp:<имя>:<args-json>`
- Завершить план → `plan-done` · Арбитраж gate3 → `gate3-arb:accept:<fp>` / `gate3-arb:continue:<fp>`
- Опечатать на арбитраже → `owner-seal:<hash>` · Деплой → `ops-runbook:<hash>` · Коммит → `commit:<hash>`
**Канон пути для `write:`** — абсолютный, **lowercase**, прямые слэши `/`, NFC (как `pathNormalizeSafe`).
**Что escape чтит:** стена М2 / пол М5 / судья М4 / гейт памяти. **НЕ чтит:** `router-gate` (git —
отдельный канал, см. «Коммит») и `normative §6` для discipline-source (F-K — правь терминалом).
**Активация (settings.json):** PostToolUse `AskUserQuestion``enforce-askuser-answer-parser`
(writer: **anti-button** + **anti-dictation**; подписывает грант ключом `router-mentor-receipts`) +
`Edit|Write|MultiEdit|Bash|PowerShell``enforce-floor-escape-consume` (one-shot гасит лёгкий грант).
Тяжёлый терминальный канал — скрипт `tools/owner-consent.mjs` (запускает владелец, вне гейтов).
**Как дать лёгкий escape через окошко (урок 18.06).** Текст вопроса AskUserQuestion в UI **не
копируется**. Поэтому: (1) контроллер сперва пишет строку `FLOOR-ESCAPE: <action>` **в чат** (откуда
владелец её копирует — НЕ как имперактив рядом с меткой, иначе anti-dictation флагует; просто показать
строкой); (2) показывает окошко; (3) владелец **вставляет скопированное в поле ответа окошка** (НЕ в
обычный чат — из чата грант не пишется, ловит только PostToolUse AskUserQuestion). Кнопки окошка —
не-escape (anti-button). Канон `write:`-пути для §6-правки нормативки: абсолютный, lowercase, прямые
`/`, NFC, напр. `write:c:/моя/проекты/claude-brain/docs/pravila_raboty_claude_v1_1.md`. Escape
одноразовый — на КАЖДУЮ правку нормативки своё окошко; escape-окошки освобождены от anti-cosmetic-
стража (`askuser-cosmetic-detector::isEscapeAuthQuestion`, fix `f2365ca`), так что давать можно сколько
нужно. **Тяжёлая нормативка (много правок) — чище в ШТАТНОМ** (§6 — часть стены, в штатном off;
правки нормативки идут через `claude-md-management`).
## Коммит
- **Через стену — частокол гейтов:** `enforce-router-gate` (git-approval) + `enforce-criterion-gate`
(по-критерийный GREEN) + `enforce-verify-before-push` (свежий полный прогон <30 мин). Доступно:
git status/diff/log/add. НЕ доступно: restore/stash/reset/checkout.
- **Чище — терминал владельца** (минует ВСЕ гейты стены): `$env:LEFTHOOK="0"; git commit … ; $env:LEFTHOOK=$null`.
Нужен **полный** `LEFTHOOK=0` — частичный `LEFTHOOK_EXCLUDE=cspell` НЕ помогает (`markdownlint --fix`
правит .md и рвёт git-stash). Сообщение **paren-free**, трейлер `Co-Authored-By: Claude Opus 4.8`.
- **git auto-gc на Windows** может зациклить `Unlink … .idx failed. Try again? (y/n)` (pack держит
др. процесс — VSCode Git / gitea) → жми **`n`**; коммит уже создан. Профилактика: `git config gc.auto 0`.
- **Коммит и пуш ШАГАМИ опечатанного плана (урок 18.06).** В `steps-json` можно вписать сохранение:
`{op:"Write","object":".git/CB_MSG.txt"}` (сообщение) → `{op:"Bash","object":"git add <путь>"}`
`{op:"Bash","object":"git commit -F .git/CB_MSG.txt"}``{op:"Bash","object":"git push gitea main"}`.
Проходит наставника+судью (ворота-2) ЕСЛИ в плане есть **раздел-обоснование**, что docs-only
git-команды входят в объявленный `claude-md-management` (отдельного git-скила в реестре нет; иначе
наставник NO-GO «доменный навык для git не объявлен»). Для docs-only `.md` criterion/verify
короткозамкнуты. Сообщение — через `.git/CB_MSG.txt` (пол режет `<email>`/цепочки в `-m`).
## Пуш кода через стену
Пуш кода (не docs-only) проходит частокол ПОСЛЕ печати плана: verify-gate → criterion-gate → pre-push.
Порядок гейтов и грабли (урок 16.06):
1. **verify-gate** (`enforce-verify-gate`) требует свежую подписанную расписку. Производит её
**`node tools/produce-verify-receipt.mjs`** (гонит tools-сюиту vitest, подписывает по отпечатку
staged-diff). Ставь ПЕРВЫМ шагом плана. Расписка — side-channel файл
`~/.claude/runtime/verify-receipt.json`, НЕ аргумент push (судья может ошибочно требовать «шаг
доставки расписки» — опровергай: хук сам читает фиксированный путь).
2. **criterion-gate** (`enforce-criterion-gate`) на git push с кодом требует валидный frozen-plan.
**Десинк §3.4 ПОЧИНЕН (`cdcaf61`, 18.06):** печать снимается ЛЕНИВО на следующем действии, а не
синхронно на последнем шаге → criterion видит план даже когда push — ПОСЛЕДНИЙ шаг. Обход ниже
(сделать push не-терминальным) больше НЕ нужен — оставлен для истории.
~~**Лечение (устар.):** сделать push НЕ-терминальным — добавить шаг ПОСЛЕ него (push исходники не
правит → criteria=[] → гейт пропустит). Трейлинг-шаг — МУТИРУЮЩИЙ, не read-only (read-only не сдвинет
указатель → план повиснет).~~
3. **lefthook pre-push** (gitleaks/lychee) — локальный git-хук, НЕ стена. На pre-existing находках
обходи ТОЧЕЧНО: `LEFTHOOK_EXCLUDE=<hook1>,<hook2> git push …` (не глухой `LEFTHOOK=0` — судья
флагует его `[heavy]`). Имена хуков — из вывода pre-push.
4. **Квирк наставника:** чистый GO с пустым `recommendation` → проверка-содержательности рубит
(`no_mentor_go`) → судья НЕ вызывается → план не печатается. Обход: добавь в `## Переговоры` круг,
прямо приглашающий наставника записать forward-`recommendation`. Корень — баг машинерии (см.
`docs/superpowers/2026-06-16-mentor-empty-recommendation-bug.md` → claude-brain).
## Судьи-машины
- **Тупой судья навыков** (`enforce-domain-skill-discipline`). Навыки из `skills-json` опломбированного
плана обязаны быть РЕАЛЬНО вызваны (по журналу M1) до первого мутирующего шага, иначе блок. Объявленный
навык стена пустит к вызову (`isPlanDeclaredSkill`).
- **Критерий-судья** (`enforce-criterion-gate`). На `git commit`/`push` через Claude требует
по-критерийный GREEN (тест прошёл И мутация убита). Коммиты в своём терминале его минуют.
**Правки памяти/CLAUDE.md под стеной:** объяви `claude-md-management` в `skills-json` И реально вызови
до записи — иначе гейт памяти/судья навыков заблокируют.
## Минимальный пример и что под капотом
**Пример церемонии.** Задача: чистый модуль `tools/<имя>.mjs` через TDD. Спека: 5 секций `{#D1..D5}` +
verified-context (якорь на `cost-pricing.mjs`) + `## Цель`. План: `skills-json`
`["test-driven-development"]`; шаги тест-RED → vitest-RED → модуль → vitest-GREEN → … → регрессия.
Регрессия (одиночная команда): `npx vitest run --root app --config vitest.config.tools.mjs`.
**Под капотом.** Стена = `enforce-supreme-gate` (PreToolUse на всё); оркестратор =
`enforce-mentor-then-judge` (PostToolUse Write) гонит наставника → судью по очереди. Живой шов: env
`ROUTER_MENTOR_SEAM_ENABLED=1`, `ROUTER_MENTOR_JUDGE_ENABLED=1`, `ROUTER_MENTOR_JUDGE_MODE=block` +
ключи наставника/судьи/роутера. Имена хуков Фиксов 1/2/3 — в их разделах выше.
@@ -0,0 +1,92 @@
# Единый код-верифицированный гайд по стене — Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: superpowers:executing-plans (inline, с чекпоинтами) — работа ювелирная, исполняю сам с контролем. Шаги — чекбоксы `- [ ]`.
**Goal:** Собрать ОДИН гайд по нашей стене, где каждое правило/урок подтверждён по коду; удалить две старые копии.
**Architecture:** Параллельная read-only разведка кода под линзами-скилами (находки текстом) → личная сверка контроллером по коду → синтез единого гайда с инлайн код-якорями → удаление `bags/`-копии → финальная сверка.
**Tech Stack:** Node `.mjs`-хуки в `tools/`, `settings.json`, субагенты Explore/general-purpose, скилы superpowers.
**Источник истины:** прямой Read/Grep по `tools/`. Спека: [docs/superpowers/specs/2026-06-19-wall-guide-merge-design.md](../specs/2026-06-19-wall-guide-merge-design.md).
---
## Скилы и линзы — сводка
| Этап | Скил | Линза(ы) |
|---|---|---|
| Разведка (волна 1) | `dispatching-parallel-agents` | A `verification-before-completion`, B `sharp-edges`, C дрейф, D полнота |
| Сверка контроллером | (дисциплина) `verification-before-completion` | — |
| Синтез гайда | (письмо) | — |
| Финальная сверка | `verification-before-completion` | — |
| Указатель CLAUDE.md (если надо) | `claude-md-management` | — |
Разведчики возвращают находки **ТОЛЬКО текстом**, файлы не пишут. Финальную сверку по коду делаю я лично (память `subagent-falsified-test-results`).
**Формат возврата каждого разведчика** (требую дословно):
```
RULE: <цитата правила из гайда>
VERDICT: MATCH | DRIFT | WRONG | UNDOCUMENTED
ANCHOR: <файл>:<строки> — <цитата строки кода>
CAVEAT: <упущенная оговорка / крайний случай или «нет»>
NOTE: <пояснение, 1-2 строки>
```
---
## Task 1: Разведка — волна 1 (параллельные субагенты под линзами)
**Скил:** `dispatching-parallel-agents`. Запускаю агентов одним сообщением (параллельно). Каждому даю: его кластер файлов, список правил из ОБОИХ гайдов по его разделу, линзу, формат возврата выше. Инструкция всем: «глобь `tools/` чтобы добрать связанные файлы кластера; цитируй `файл:строка`; без цитаты — не утверждай; правила Лидерра-гайда (`bags/`) проверяй как ГИПОТЕЗЫ про НАШ код, не как факт».
- [ ] **R1 — Церемония + механика (разделы 1,2,3).** Линза A+D. Файлы: `enforce-supreme-gate.mjs`, `on-plan-write.mjs`, `plan-lock*`, `judge-anchor.mjs`, `judge-goal-anchor.mjs`, `mentor-seam.mjs`. Что искать: поток спека→печать→план→печать→шаги; `actionMatchesStep`; форматы `verified-context-json`/`skills-json`/`steps-json`/`ref`-якоря; режимы (разговорный/исполнение/снято) и проба состояния.
- [ ] **R2 — Пол + свободно/гейтится (раздел 4).** Линза A+B. Файлы: `enforce-supreme-gate.mjs` (floor-часть), `floor-manifest-check.mjs`, `floor-signer.mjs`, `enforce-read-path-deny.mjs`. Что искать: чтение кода под планом, авторская запись `.md`, детект Bash-цепочек/subshell, floor-safe (content-block правило 8), **запуск скрипта-файла vs инлайн-eval** (`-c`/`-e`).
- [ ] **R3a — Escape (раздел 5) ВЫСОКИЙ РИСК.** Линза A. Файлы: `escape-grant.mjs`, `enforce-askuser-answer-parser.mjs`, `askuser-answer-parser.mjs`, `askuser-cosmetic-detector.mjs`, `enforce-floor-escape-consume.mjs`, `floor-escape-consume.mjs`, `owner-consent.mjs`. Что искать: `canonicalAction`-каноны; лёгкое vs тяжёлое согласие; есть ли **anti-button/anti-dictation** (`detectOtherSocialEng`); окно/одноразовость; кто что чтит.
- [ ] **R3b — Escape ВЫСОКИЙ РИСК, контр-проверка.** Линза C (дрейф). Те же файлы R3a. Задача: для КАЖДОГО утверждения старого гайда (`docs/`, рецепт «метка в LABEL кнопки») и Лидерра-гайда (`bags/`, anti-button + терминал) — сказать, что РЕАЛЬНО делает НАШ код: старый рецепт жив / перебит / иначе. Это ядро расхождения.
- [ ] **R4 — Коммит/пуш (раздел 6).** Линза A+B. Файлы: `enforce-router-gate.mjs`, `router-gate-decide.mjs`, `enforce-criterion-gate*`, `enforce-verify-gate.mjs`, `enforce-verify-before-push.mjs`, `produce-criterion-greens.mjs`, `criterion-green.mjs`, `produce-verify-receipt*`. **+ проверить регистрацию в `.claude/settings.json`** (какие из этих хуков реально подключены). Что искать: частокол гейтов, что снимает escape, что нет; docs-only short-circuit.
- [ ] **R5 — Субагенты под стеной (раздел 7).** Линза A+D. Файлы: `enforce-supreme-gate.mjs` (обработка Task), `enforce-subagent-return-scanner.mjs`. Что искать: душится ли `op:Task`/субагент-мутатор; три опоры подотчётности; разведка read-only разрешена.
- [ ] **R6a — Судьи-машины (раздел 8) ВЫСОКИЙ РИСК.** Линза A. Файлы: `enforce-domain-skill-discipline.mjs`, `domain-skill-discipline.mjs`, `enforce-mentor-then-judge.mjs`, `enforce-mentor-on-plan-write.mjs`, `mentor-verdict.mjs`, `enforce-judge-gate.mjs`, `judge-orchestrator.mjs`, `judge-evaluator.mjs`, `enforce-verdict-surface.mjs`, `verdict-surface-store.mjs`, `round-control.mjs`, `round-memory-*.mjs`, `mentor-nogo-counter.mjs`, `seal-orchestration.mjs`, `post-seal.mjs`, `judge-seal-channel.mjs`. Что искать: тупой судья навыков; критерий-судья; `sealOnWiredGo`/owner-seal; видимость вердиктов; память кругов; арбитраж на 3-м NO-GO.
- [ ] **R6b — Судьи-машины ВЫСОКИЙ РИСК, контр-проверка.** Линза B (sharp-edges). Те же файлы R6a. Задача: крайние случаи и тупики — печать≠escape, H4 (наставник видит только `steps-json`), пустой `recommendation`, недетерминизм судьи, десинк указателя при co-hook block.
- [ ] **R7 — Тупики + владелец + под капотом (разделы 9,10,11).** Линза A+B+D. Файлы: `enforce-mentor-on-plan-write.mjs` (молчаливый catch), `on-plan-write.mjs` (`renderSkillContext`), `.claude/settings.json` (регистрация хуков + env-переменные шва), **источник штатный-хендшейка** (глобь, какой хук печатает «да, штатный»/«выключи штатный»). Что искать: молчаливый срыв; имена хуков; env (`ROUTER_MENTOR_SEAM_ENABLED` и пр.); рычаги владельца; штатный-хендшейк.
- [ ] **Чекпоинт:** собрать все возвраты, отметить конфликты между агентами и пункты DRIFT/WRONG/UNDOCUMENTED. Пауза на ревью владельцу.
## Task 2: Сверка контроллером (личная, по коду)
**Линза:** `verification-before-completion` (дисциплина).
- [ ] Для КАЖДОГО пункта с вердиктом DRIFT/WRONG и КАЖДОГО конфликта между R3a/R3b и R6a/R6b — открыть реальный код (`Read`) и подтвердить лично; зафиксировать итоговый якорь `файл:строка`.
- [ ] Для несущих правил разделов 5–8 (escape, коммит, судьи) — перечитать код лично даже при вердикте MATCH.
- [ ] Свести таблицу «правило → итоговый вердикт → якорь → оговорка», вычистить устаревшее (Лидерра-баги, перебитые нашим кодом).
- [ ] **Чекпоинт:** показать владельцу список «что выкидываем / что добавляем (нюансы) / где старый гайд врал про нашу стену».
## Task 3: Синтез единого гайда
**Файлы:** Modify (перезапись): `docs/superpowers/router-mentor-wall-GUIDE.md`.
- [ ] Написать шапку + кликабельное оглавление (11 разделов из спеки).
- [ ] Раздел за разделом: краткая формулировка правила + **инлайн код-якорь** `файл:строка` + оговорки из линзы B. Включить уже пойманные нюансы: штатный-хендшейк («да, штатный»), возврат стены («выключи штатный»).
- [ ] Перенести ценные уроки сессий (молчаливый срыв, H4, CRLF/vitest, harness-collapse, десинк) — кратко, с якорями.
- [ ] **Чекпоинт:** показать владельцу черновик гайда целиком.
## Task 4: Уборка и удаление старых копий
- [ ] Удалить `bags/router-mentor-wall-GUIDE.md`. Проверить, что `bags/` не содержит наших уникальных нужных данных (всё перенесено).
- [ ] Убедиться: остался ровно один гайд по каноническому пути.
- [ ] Удалить временные файлы, если появились (CLAUDE.md п.11). Спека/план остаются (это артефакты процесса).
## Task 5: Финальная сверка + предложение коммита
**Скил:** `verification-before-completion`.
- [ ] Прогнать гайд: каждое правило имеет якорь `файл:строка`; ссылки оглавления резолвятся (Grep по заголовкам).
- [ ] Условно: проверить, что указатель CLAUDE.md §0 «читай первым router-mentor-wall-GUIDE.md» всё ещё валиден (путь сохранён). Если потребуется правка — через `claude-md-management`, отдельным шагом.
- [ ] Предложить владельцу коммит (docs-only; verify-before-push короткозамкнут на `.md`). Коммит/пуш — по согласию владельца, не молча.
---
## Self-Review (заполняется после написания)
- **Покрытие спеки:** все 11 разделов структуры закрыты Task 1 (разведка) + Task 3 (синтез); метод аудита (4 линзы) — Task 1; критерий готовности — Task 5. ✅
- **Заглушки:** конкретные файлы/линзы/формат возврата заданы; «что искать» по каждому кластеру явное. ✅
- **Согласованность:** формат возврата един для всех R*; вердикты MATCH/DRIFT/WRONG/UNDOCUMENTED используются и в Task 1, и в Task 2. ✅
+142 -321
View File
@@ -1,377 +1,198 @@
# Как работать под стеной «роутер-наставник» (шпаргалка для сессий)
<a id="top"></a>
# Как работать под стеной «роутер-наставник» (шпаргалка сессии)
> Читать ПЕРЕД работой под стеной. Цель — не разбираться с форматами по исходникам.
> Читать ПЕРЕД работой под стеной. Каждое правило сверено с кодом нашей стены (`tools/*.mjs`, `.claude/settings.json`) на 2026-06-19. Якоря `файл:строка` — рядом с правилом.
**Суть:** под стеной реальная работа (Edit/Write/Bash по коду) проходит ТОЛЬКО как шаг
**опечатанного** плана. Поток: спека → (печать) → план → (печать) → шаги по порядку →
авто-завершение. Оркестратор делает так, что печать встаёт за **ОДИН заход**`prime+catch` НЕ нужен.
**Суть.** Под стеной реальная работа (Edit/Write/Bash по коду) проходит ТОЛЬКО как шаг **опечатанного** плана. Поток: спека → (печать) → план → (печать) → шаги по порядку → авто-завершение. Печать встаёт за **один заход** (наставник→судья, оба GO).
## Рецепт церемонии (точные форматы — иначе печать не встанет)
## Оглавление
**1. СПЕКА** — Write НОВОГО файла в `docs/superpowers/specs/<уникальное-имя>.md`. Обязана нести:
1. [Поток и режимы](#s1)
2. [Рецепт церемонии (форматы спеки и плана)](#s2)
3. [Что свободно vs что гейтится](#s3)
4. [Аварийный выход (escape) — лёгкое vs тяжёлое](#s4)
5. [Коммит и пуш](#s5)
6. [Субагенты под стеной — только разведка](#s6)
7. [Судьи-машины и печать](#s7)
8. [Частые ошибки и тупики](#s8)
9. [Только владелец (штатный режим, снятие печати)](#s9)
10. [Что под капотом (хуки + env)](#s10)
---
<a id="s1"></a>
## 1. Поток и режимы
Стена = `enforce-supreme-gate.mjs` (PreToolUse на всё, [settings.json:75](../../.claude/settings.json#L75)). Три режима — функция `decideMode` ([enforce-supreme-gate.mjs](../../tools/enforce-supreme-gate.mjs)):
- **разговорный** — нет опечатанного плана (или `judge_mode ≠ 'live-block'`). Мутаторы (Edit/Write/мут-Bash) блокируются; чтение/спрашивание свободно; пишется только новый `.md` в `specs/`/`plans/`.
- **исполнение** — опечатаны И спека, И план, оба `judge_mode='live-block'`. Идут шаги плана по одному; каждый Edit/Write/Bash обязан совпасть с текущим шагом (`actionMatchesStep`, [plan-lock.mjs](../../tools/plan-lock.mjs)).
- **escape** — открыт разовый грант владельца: действие пропускается **без сдвига указателя** (§4).
**Проба состояния** — безобидный не-readonly Bash, напр. `node --version` (`echo` режет как не-whitelist):
- блок «разговорный режим» → стена включена, печати нет;
- блок «ожидался шаг N: …» → ты в исполнении на шаге N (возможно, застрял — см. §8);
- команда выполнилась → стены нет (штатный) или открыт escape.
**Авто-завершение лениво (§3.4).** После последнего шага печать снимается НЕ синхронно, а на следующем действии — чтобы `criterion-gate` на код-пуше успел увидеть живой план. Старый обход «сделать push не-терминальным» больше не нужен.
---
<a id="s2"></a>
## 2. Рецепт церемонии (точные форматы — иначе печать не встанет)
**Спека** — Write НОВОГО файла `docs/superpowers/specs/<уникальное-имя>.md`:
- якорные секции `## Заголовок {#D1}`с **непустым** телом (контракт, edge-cases, конвенция, критерий);
- блок ` ```verified-context-json``` ` — массив с ≥1 EXTRACTED:
`{"id":"…","kind":"EXTRACTED","ref":"<существующий файл>","anchor":"<реальная подстрока ≥4 симв в этом файле>"}`.
**Готовый рабочий якорь:** ref `tools/cost-pricing.mjs`, anchor `export const PRICING = Object.freeze(`;
- секцию `## Цель` (для роутера и судьи);
- **НИКАКОЙ мета-болтовни** (про печать/хеши/оркестратор/обход стены) — судья судит вслепую и
завернёт fatal. Пиши только про предмет задачи.
**2. ПЛАН** — Write НОВОГО файла в `docs/superpowers/plans/<уникальное-имя>.md`. Обязан нести:
- блок ` ```verified-context-json``` ` — массив с ≥1 EXTRACTED: `{"id":"…","kind":"EXTRACTED","ref":"<существующий файл>","anchor":"<реальная подстрока ≥4 симв>"}`. **Готовый якорь:** ref `tools/cost-pricing.mjs`, anchor `export const PRICING = Object.freeze(`;
- секция `## Цель`;
- **никакой мета-болтовни** (печать/хеши/оркестратор/обход стены) — судья судит вслепую, завернёт fatal.
**План** — Write НОВОГО файла `docs/superpowers/plans/<уникальное-имя>.md`:
- `## Цель`;
- блок ` ```skills-json``` `массив объявленных навыков, напр. `["test-driven-development"]`;
- блок ` ```steps-json``` ` — массив `{op, object, ref}`: `op` ∈ Write|Edit|Bash|MultiEdit
(**Task запрещён**); `object` = путь к файлу (для файловых op) или **точная** строка команды
(для Bash); `ref` = один из якорей спеки (D1..Dn), **непустой**;
- блок ` ```verified-context-json``` ` (тот же — **план тоже** требует ≥1 EXTRACTED, иначе печать не встанет);
- без мета-болтовни.
- ` ```skills-json``` `навыки **без плагин-префикса**: `["test-driven-development"]`;
- ` ```steps-json``` ` — массив `{op, object, ref}`: `op` ∈ Write|Edit|Bash|MultiEdit|PowerShell|session (**Task/Skill шагом запрещены**); `object` = путь (файловые op) или **точная** команда (Bash); `ref` = якорь спеки (`D1..Dn`), **непустой**, должен резолвиться в опечатанном артефакте;
- ` ```verified-context-json``` ` план **тоже** требует ≥1 EXTRACTED;
- раздел `## Переговоры → ### Круг N` — сюда дословные доводы на возражения (память кругов подаёт их судье/наставнику, §7).
**3. Реализация** — шаги по порядку. Каждый Edit/Write/Bash должен совпасть с **текущим** шагом
(op + object). Стена двигает указатель по одному. После **последнего** шага стена сама снимает
печать (чистое завершение) → разговорный режим.
**Реализация** — шаги по порядку; каждый Edit/Write/Bash совпадает с текущим шагом (op+object). Указатель двигается по одному.
## Частые ошибки (учись на чужих шишках)
**Осмотр сайта/живые проверки — `op:"session"`.** Один шаг-сеанс `{op:"session", goal, tools:[…], produces:"<файл>"}`: внутри смотришь/кликаешь живые инструменты сколько нужно (указатель не двигается), сеанс закрывает запись **последнего** `produces`. В `tools` сеанса нельзя Write/Edit/мут-Bash/floor — правки репозитория остаются шагами (`sanitizeSessionTools`, [enforce-supreme-gate.mjs](../../tools/enforce-supreme-gate.mjs)).
- **Ловушка устаревшего указателя.** Повторный план **байт-в-байт** в той же сессии = тот же
идентификатор плана → старая позиция исполнения НЕ сбрасывается → застреваешь в середине, шаг 1
блокнут. **Лечение:** другой план (напр. другое имя модуля → новый идентификатор) ИЛИ свежая
сессия. Удаление файлов НЕ помогает (позиция в runtime, не в файлах).
- **Авторская запись.** Свободно пишется только **НОВЫЙ** `.md` в `specs/` или `plans/`.
Существующий файл → блок. Код и прочие пути — только как шаг плана.
- **Чтение кода под стеной.** В режиме реализации чтение кода вне путей текущего шага
блокируется. Свободно читать код — только в **разговорном** режиме (нет печати).
- **Bash-цепочки.** Цепочки (`;`/`&&`/`||`/`|`) с мутирующей частью hard-блокируются. Только
**одиночные** команды.
- **Floor-safe планы (важно, 14.06.2026).** НЕ ставь floor-опасные команды как Bash-шаги плана:
`node -e`/`curl`/install/eval (content-block правило 8), `rm -rf`/`git push --force`/`migrate:fresh`,
PowerShell-записи, запись в `~/.claude/runtime`/секреты. Пол их блокирует, а стена (после фикса
Δ7+) **не двигает указатель** → план **встаёт колом** на этом шаге. Escape его НЕ продвигает
(escape даёт allow без сдвига указателя). Для файловых операций бери **инструменты Write/Edit**
(пол их не гейтит), а не `node -e`: бэкап файла = Write копии, валидация — read-only после правки.
Раньше (до Δ7+) такой шаг молча терялся со сдвигом указателя (desync) — теперь он честно
останавливает план.
- **git.** Доступно: status/diff/log/add/commit. НЕ доступно: restore/stash/reset/checkout.
**Коммит через стену = git-approval (`approve_git_operation`), а НЕ FLOOR-ESCAPE.** `git commit`/`add`/`push`
гейтит `enforce-router-gate``classifyGitCommand`: они conditional → требуют `approve_git_operation`.
**Рабочий рецепт (проверен 14.06.2026, коммит `abc3124e`):** подними **AskUserQuestion**, опцией поставь
**точную git-команду** (`git commit -m "…" -m "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>" -- <путь>`);
владелец кликает → среда (`enforce-askuser-answer-parser``toApprovalRecord`) пишет `approve_git_operation`
router-gate пускает РОВНО эту команду (окно 5 мин; нормализуются только пробелы — команда в опции и в запуске
должны совпасть символ-в-символ). Сообщение **paren-free** (floor-detectSubshell режет `()`), трейлер
`Co-Authored-By: Claude Opus 4.8` обязателен. Изолируй файл через `-- <путь>` — не тянет застейдженный
`STATUS.md` (он перегенерится post-commit, это шум, в коммит не идёт). Можно и `git add <путь>` тем же
каналом, но `git commit -- <путь>` экономит один клик.
- **FLOOR-ESCAPE ≠ git.** floor_escape чтут стена М2 / пол М5 / гейт памяти (`enforce-normative-content-rules`) —
это канал для записи в **память/нормативку**, не для git. router-gate floor_escape не читает. Оба канала
(`approve_git_operation` для git, `floor_escape` для памяти) пишет один env-хук `enforce-askuser-answer-parser`
(PostToolUse AskUserQuestion) — он ОБЯЗАН быть зарегистрирован в settings.json, иначе клик уходит «в никуда».
- **Наставник/судья async** (~25-32с/вызов по большой спеке/плану). Не гнаться вперёд —
печать встаёт не мгновенно. Per-attempt таймаут тяжёлых LLM-вызовов поднят 30с→**90с**
(14.06.2026, `HEAVY_LLM_TIMEOUT_MS`): раньше 30с резал latency 25-32с → degraded → печать
не вставала; теперь degraded редок. Если всё же «не дозвонился» (degraded) — просто повтор.
> **Под капотом:** `planId` = sha256 от шагов (`plan-lock.mjs`) — байт-в-байт тот же план = тот же id; каждый шаг получает `criterion_id` (sha256 содержимого) для критерий-судьи; `judge_mode` — строгий whitelist (`live-block`/`shadow`; опечатка → fail-closed в разговорный).
## Как узнать состояние (одна проба)
---
Запусти безобидный не-readonly Bash, напр. `echo X`:
<a id="s3"></a>
## 3. Что свободно vs что гейтится
- блок «разговорный режим» → стена включена, чисто (нет печати);
- блок «ожидался шаг N: …» → ты в середине плана на шаге N (возможно, застрял);
- команда выполнилась → стена снята.
- **Чтение кода.** В исполнении чтение вне путей текущего шага блокирует ДР-1 (`reading-discipline`, вызывается из `enforce-supreme-gate.mjs`). Свободно — только в разговорном режиме. **Весь контекст собирай ДО печати плана** (под планом ни исходники, ни вывод сканера не прочитать; запасной канал — владелец вставляет содержимое в чат).
- **Смотрящие/спрашивающие свободны везде:** `Read/Grep/Glob`, `ToolSearch/WebFetch/WebSearch`, read-only браузер (`browser_navigate|snapshot|wait_for|take_screenshot`) — и под планом, и без (`OBSERVE_ONLY_TOOLS`/`QUERY_ONLY_TOOLS`, [enforce-supreme-gate.mjs](../../tools/enforce-supreme-gate.mjs)).
- **Авторская запись.** Свободно пишется только **новый** `.md` в `specs/`/`plans/` (`isAuthoringWrite`, [enforce-supreme-gate.mjs](../../tools/enforce-supreme-gate.mjs)). Существующий файл и код — только шагом плана (или escape).
- **Пол** (`enforce-floor.mjs` [settings.json:55](../../.claude/settings.json#L55), логика `floor-decide.mjs`) рубит по содержанию, **escapable**:
- **инлайн-eval** (`node -e`/`python -c`/`bash -c`), `curl`/install, egress, redirect `>`/`>>`;
- **цепочки** `;`/`&&`/`||`/`|` с мутирующей частью (посегментно, `bash-tokenizer.mjs`);
- **subshell как класс** — `$()`/backtick/`<()`/heredoc рубятся целиком, независимо от parse (`detectSubshell`);
- **ядерное** (отдельный класс, `classify-destructive.mjs`): `rm -rf`/`git push --force`/`migrate:fresh`/`db:wipe` — даже под D1-грантом остаётся per-command escape;
- PowerShell-записи в `~/.claude/runtime`/секреты (`psProtectedWrite`).
- ⚠️ **Любая мутация ФС шагом-Bash тоже режется полом:** `mv`/`rm`/`cp -f` — даже одиночные. Файловые операции делай инструментами Write/Edit (пол их не гейтит), а не Bash; удаление/переименование файла — через owner escape или терминал владельца.
-**Запуск скрипта-файла пол ПУСКАЕТ:** `python tools/x.py`, `node tools/x.mjs`, `npx vitest …`, установленный CLI (`graphify …`). Режется только инлайн `-e`/`-c`. → нужен скрипт под планом: пиши `.py`/`.mjs` шагом Write, запускай `node/python <файл>` шагом Bash.
## Только владелец (участнику закрыто)
---
- `settings.json` (вкл/выкл стены + флаги/ключи) и снятие застрявшей печати
(досрочное завершение / перезапуск). Правки `settings.json` подхватываются только после
**перезапуска** Claude Code.
- **Maintenance — выключить стену целиком** (общий рычаг, когда Claude застрял на большой
работе): заменить весь блок `"hooks": { … }` на `"hooks": {}`, сохранить, перезапустить
Claude Code. Вернуть — вставить полный набор хуков обратно + перезапуск.
- **Перезапуск ≠ сброс застрявшего плана.** Перезапуск Claude Code перечитывает
`settings.json` (подхватывает новые хуки/флаги), но **не** сбрасывает застрявшую печать и
сессию — план и его указатель живут отдельно в runtime. Чтобы сбросить застрявший план:
досрочно завершить печать, **или** Claude берёт новую церемонию с **другим** именем файла
(новый `plan_id` сам перебивает старый указатель).
- Чтение `~/.claude/runtime` — закрыто. Вердикты/печать владелец видит в внешних логах вызовов;
участнику runtime недоступен — спрашивай владельца.
<a id="s4"></a>
## 4. Аварийный выход (escape) — лёгкое vs тяжёлое
## Аварийный выход владельца (escape) — как выдать разовое разрешение
**Старый рецепт «контроллер кладёт метку `FLOOR-ESCAPE:` в КНОПКУ» НЕ работает** (фикс подделки согласия). Среда могла вернуть кнопку как «ответ» без действия владельца, поэтому ответ, дословно совпавший с ярлыком опции, согласием **не считается** (anti-button, [enforce-askuser-answer-parser.mjs:64-65](../../tools/enforce-askuser-answer-parser.mjs#L64-L65); `answerMatchesOption` [askuser-answer-parser.mjs:38-43](../../tools/askuser-answer-parser.mjs#L38-L43)). Диктовать метку тоже нельзя (anti-dictation `detectOtherSocialEng` [askuser-answer-parser.mjs:161-167](../../tools/askuser-answer-parser.mjs#L161-L167); гасит грант в [enforce-askuser-answer-parser.mjs:70](../../tools/enforce-askuser-answer-parser.mjs#L70)).
Если стена / пол / судья / гейт памяти блокирует действие, которое владелец всё-таки хочет
разрешить (напр. запись в память про саму стену), владелец выдаёт **разовый подписанный
пропуск** (floor_escape, Машина 6 + подпись M6 FIX-5). Процедура:
**ЛЁГКОЕ**`write:<путь>`, безопасный `bash:`, `skill:<имя>`. Владелец **сам набирает** `FLOOR-ESCAPE: <action>` в поле «Другое» ответа AskUserQuestion (`toFloorEscapeRecord` [askuser-answer-parser.mjs:211-225](../../tools/askuser-answer-parser.mjs#L211-L225)). Контроллер кнопку-с-меткой не делает и метку не диктует. Грант одноразовый, окно **5 мин** ([escape-grant.mjs:17](../../tools/escape-grant.mjs#L17)), точное совпадение `canonicalAction`.
*Как дать через окошко:* контроллер показывает строку `FLOOR-ESCAPE: <action>` **в чате** (без императива рядом — иначе anti-dictation), владелец **копирует её в поле «Другое»** окошка (из обычного чата грант не пишется). Escape-окошки освобождены от anti-cosmetic-стража (`isEscapeAuthQuestion`).
1. Контроллер задаёт **AskUserQuestion** (или владелец отвечает на текущий вопрос).
2. Владелец **в своём ответе пишет метку** `FLOOR-ESCAPE: <action>`, где `<action>`
каноническая строка действия (`canonicalAction`, [tools/escape-grant.mjs](../../tools/escape-grant.mjs)):
- Bash → `bash:<нормализованная команда>`
- PowerShell → `powershell:<нормализованная команда>`
- Skill → `skill:<имя-навыка в нижнем регистре>`
- Write/Edit/MCP-писатель → `write:<путь, нормализованный pathNormalizeSafe — lowercase + прямые слэши>`
- MCP-инструмент → `mcp:<имя>:<args-json>`
3. Среда (`enforce-askuser-answer-parser`, PostToolUse) видит **реальный** ответ владельца →
пишет пропуск в `~/.claude/runtime/askuser-decisions-<сессия>.jsonl` и **подписывает ключом
владельца** (`router-mentor-receipts`). Контроллер подделать не может (нет ключа; канал protected).
4. Пропуск **одноразовый**, окно **5 минут**. Потребитель при точном совпадении `canonicalAction`
пропускает ровно это действие (указатель не двигает).
**ТЯЖЁЛОЕ**`owner-seal:<hash>`, `ops-runbook:<hash>`, `commit:<hash>`, `plan-done`, `gate3-arb:*`, разрушительный `bash:`/`powershell:`. **Только из терминала владельца:**
```
node tools/owner-consent.mjs <sessionId> <action>
```
Скрипт подписывает грант ключом keychain (`origin:owner-terminal`, [owner-consent.mjs:16-27](../../tools/owner-consent.mjs#L16-L27)). Контроллер подделать не может: нет ключа → читатель отвергает (**fail-closed**, [escape-grant.mjs:120-129](../../tools/escape-grant.mjs#L120-L129)); `~/.claude/runtime` ему писать нельзя (пол). Тяжёлые гранты окно 5 мин не режут — окно = существование опечатанного плана (`loadPlanScopedGrants`, [escape-grant.mjs:131-157](../../tools/escape-grant.mjs#L131-L157)).
**Пример** (разрешить запись файла памяти):
`FLOOR-ESCAPE: write:c:/users/administrator/.claude/projects/<проект>/memory/<файл>.md`
**Каноны `<action>`** (`canonicalAction` [escape-grant.mjs:30-52](../../tools/escape-grant.mjs#L30-L52)): `bash:<норм.команда>` · `powershell:<норм.команда>` · `skill:<имя lowercase>` · `write:<путь lowercase, прямые /, NFC>` · `mcp:<имя>:<args-json>`. Путь для `write:` — абсолютный, нижний регистр, прямые слэши.
**Важно:** метка должна нести ТОЧНУЮ каноническую строку (путь в нижнем регистре, прямые слэши) —
иначе пропуск не совпадёт. Для широких задач проще временный maintenance (`"hooks": {}` + перезапуск).
Escape чтут стена М2 / пол М5 / судья М4 / гейт памяти; `router-gate` (USER-level git) — отдельно.
**Что escape чтит:** стена / пол / судья / гейт памяти (`enforce-normative-content-rules`). **НЕ чтит:** `normative §6` для discipline-source (код `tools/enforce-*` правь в терминале — write-escape его не снимает).
**Активация escape-двери (важно, 14.06.2026).** Механизм собран в коде, но работает ТОЛЬКО если оба
PostToolUse-хука зарегистрированы в `settings.json`: matcher `AskUserQuestion`
`enforce-askuser-answer-parser` (writer — пишет и подписывает пропуск на клик владельца) + matcher
`Edit|Write|MultiEdit|Bash|PowerShell``enforce-floor-escape-consume` (one-shot гашение). Если их нет —
клик владельца уходит «в никуда», пропуск не пишется, и `enforce-normative-content-rules` падает на
«without active legit skill». Симптом: escape выдан, а запись всё равно блокнута → проверь регистрацию
этих двух хуков + перезапуск Claude. Проверено вживую 14.06.2026 (внешний research-пакет): после регистрации
клик по опции `FLOOR-ESCAPE: …` сразу разблокировал запись файла памяти.
**Активация (обязательна в settings.json):** PostToolUse `AskUserQuestion``enforce-askuser-answer-parser` (writer, [settings.json:205](../../.claude/settings.json#L205)) + `Edit|Write|MultiEdit|Bash|PowerShell``enforce-floor-escape-consume` (one-shot гашение, [settings.json:215](../../.claude/settings.json#L215)). Нет регистрации — клик уходит «в никуда».
**Запись в память/правила — только с твоего разрешения.** Когда Claude хочет записать в
память или правила (особенно **про саму стену**) — защита от подделки памяти это блокирует
(by-design, не баг). Разреши меткой `FLOOR-ESCAPE:` (выше) или временным maintenance. Сам
Claude память про стену записать не может — и не должен.
> Упавший инструмент грант НЕ гасит (можно повторить). Грант одноразовый — все правки файла одним Edit (широкий `old_string`) или отдельный грант на каждый.
## Что под капотом (чтобы не лезть в код)
---
- Стена = `enforce-supreme-gate` (PreToolUse на все инструменты); оркестратор =
`enforce-mentor-then-judge` (PostToolUse на Write) гонит наставника → судью строго по очереди.
- Наставник зовёт роутер (`classify`) проверить выбранные в плане навыки; роутер с правки
13.06.2026 обходит быструю micro-эвристику на целях планов → доходит до своего LLM-слоя.
- Живой шов требует переменных окружения: `ROUTER_MENTOR_SEAM_ENABLED=1`,
`ROUTER_MENTOR_JUDGE_ENABLED=1`, `ROUTER_MENTOR_JUDGE_MODE=block` + ключи наставника/судьи/роутера.
<a id="s5"></a>
## 5. Коммит и пуш
## Минимальный пример безобидной церемонии
**Гейт присутствия (`enforce-router-gate`) у нас НЕ подключён** — его нет в [settings.json](../../.claude/settings.json) (файл существует, но мёртв по дизайну). Значит `approve_git_operation` не нужен; контроль коммита — на гейтах качества и согласии:
Задача: добавить чистый модуль `tools/<имя>.mjs` через TDD.
- **`enforce-verify-gate`** ([settings.json:125](../../.claude/settings.json#L125)) — на `git commit`/`push` требует свежую подписанную расписку `~/.claude/runtime/verify-receipt.json`. Производит `node tools/produce-verify-receipt.mjs` (гонит tools-сюиту, подписывает по отпечатку staged-diff). **docs-only `.md` — короткозамкнут** (`isDocsOnlyChange`).
- **`enforce-criterion-gate`** ([settings.json:135](../../.claude/settings.json#L135)) — на код-коммит требует по-критерийный GREEN (тест прошёл И мутация убита) + валидный frozen-plan. docs-only — тоже короткозамкнут.
- Спека: 5 секций `{#D1..D5}` (контракт / алгоритм / крайние случаи / конвенция заголовка /
критерий) + `verified-context-json` (якорь на `cost-pricing.mjs`) + `## Цель`.
- План: `skills-json` `["test-driven-development"]`; 11 шагов (тест RED → vitest RED →
модуль → vitest GREEN → edge-тесты → … → полная регрессия ×2).
- Регрессия (одиночная команда): `npx vitest run --root app --config vitest.config.tools.mjs`.
**Коммит силами агента (D2):** одно тяжёлое согласие `FLOOR-ESCAPE: commit:<plan-hash>` (терминал владельца) снимает гейт присутствия; гейты качества остаются; `force-push`/`--no-verify` блокируются всегда. **Деплой (D1):** `FLOOR-ESCAPE: ops-runbook:<plan-hash>`, окно = до конца плана; ядерное — всё равно per-command.
## Судьи-машины — что проверяют (обновление 13.06.2026)
**Коммит/пуш шагами опечатанного плана:** `{op:Write,object:".git/CB_MSG.txt"}``git add <путь>``git commit -F .git/CB_MSG.txt``git push gitea main`. Проходит наставника/судью, ЕСЛИ в плане есть обоснование, что docs-only git-команды входят в объявленный `claude-md-management` (отдельного git-скила в реестре нет). Сообщение через файл (пол режет `<email>`/цепочки в `-m`); **paren-free**; трейлер `Co-Authored-By: Claude Opus 4.8`.
Кроме наставника/судьи (судят спеку и план ДО исполнения), есть детерминированные судьи:
**Чище — терминал владельца** (минует все гейты): `$env:LEFTHOOK="0"; git commit … ; $env:LEFTHOOK=$null`. Нужен **полный** `LEFTHOOK=0` (PostToolUse `markdownlint --fix` правит `.md` и рвёт git-stash, [settings.json:167](../../.claude/settings.json#L167)). На pre-existing находках pre-push — `LEFTHOOK_EXCLUDE=<hook> git push` (не глухой `LEFTHOOK=0` — судья флагует `[heavy]`).
- **Тупой судья навыков** (`enforce-domain-skill-discipline`, новый). Навыки, объявленные в
`skills-json` **опломбированного** плана, вшиты в его **подпись** (Вариант 1). Правило:
«объявил → ОБЯЗАН вызвать». До первого мутирующего шага все объявленные навыки должны быть
реально вызваны (по журналу M1), иначе блок. Парный механизм в стене: **объявленный в печати
навык РАЗРЕШЁН к вызову** (`isPlanDeclaredSkill`) — даже если он не seed (снимает дедлок
«объявил, но под стеной не вызвать»). Матч плагин/суффикс.
- **Критерий-судья результата** (`enforce-criterion-gate`, уже активен). На `git commit`/`push`
**через Claude** требует на каждый затронутый шаг плана настоящий по-критерийный GREEN: тест
прошёл И **мутация убита** (сломали код → тест обязан покраснеть) + подпись + свежесть. Сильнее
«вся сюита зелёная». Не доказано → блок с подсказкой `node tools/produce-criterion-greens.mjs`.
Коммиты в своём терминале (вне Claude) его минуют.
Доступно под стеной: `git status/diff/log/add/commit`. НЕ доступно: `restore/stash/reset/checkout`.
**Практический вывод для правок памяти/CLAUDE.md под стеной:** объяви `claude-md-management` в
`skills-json` плана (стена теперь пустит его вызов) И реально вызови его до шага записи памяти —
иначе либо гейт памяти (`enforce-normative-content-rules`), либо тупой судья навыков заблокируют.
---
## Печать ставится автоматически (не владельцем вручную)
<a id="s6"></a>
## 6. Субагенты под стеной — только разведка
Печать (seal) артефакта/плана ставит **оркестратор** `enforce-mentor-then-judge` сам — после Write
спеки/плана он гонит наставник→судью; при ОБОИХ «YES» артефакт печатается. **Не проси владельца
«запечатать»** — это не его ручное действие. Проверка состояния — `echo X`:
`op:"Task"` шагом запрещён, субагент-**мутатор** под стеной не живёт: ломает три опоры подотчётности (в коде `enforce-supreme-gate.mjs`/`plan-lock.mjs`):
1. печать кроет конкретные `op+object`-шаги (`actionMatchesStep`) — не «пошли работника»;
2. пред-запись намерения контроллера в журнал перед каждой правкой (Δ3, «нет записи — нет действия»);
3. один указатель по одному дереву.
Плюс субагенту нельзя доверять мутацию (память `subagent-falsified-test-results`: фальсифицировал «5 pass»). Под стеной его Read режет ДР-1, его Write не совпадёт с шагом → блок. Доп-страж — `enforce-subagent-return-scanner` ловит narrative-claim «N тестов прошли» без прогона.
- «разговорный режим» → печати нет (наставник/судья не одобрили ИЛИ ещё считают, latency 25-90с);
- «действие не в плане (ожидался шаг … Edit …)» → печать встала, план активен;
- команда выполнилась → стены нет.
**Как помогают:** субагент только **разведывает** (read-only, возврат **текстом**), гоняй **в разговорном режиме до печати**; контроллер берёт текст и **сам** пишет шагами плана. Так проходит даже agent-as-LLM сборка (напр. graphify-экстракторы возвращают JSON текстом → контроллер пишет чанки + запускает скрипт шагами).
**Если печать не встаёт** — вердикт виден только владельцу (логи вызовов, напр. внешние live-logs LLM-провайдера
строки `Agent mentor` / `Agent Judge`). Спроси владельца, что показал вердикт. Причины: судья **NO-GO**
(доработай план под рекомендацию) или **degraded** (нет ключа/бюджета — инфра). **Ре-триггер**
НОВОЕ имя файла плана (тот же байт-в-байт = тот же plan_id, устаревший указатель). Спеку, если её
судья уже одобрил, не переписывай — только план.
---
## Правила судьи к ПЛАНУ (DR-1)
<a id="s7"></a>
## 7. Судьи-машины и печать
Судья завернёт план (NO-GO) если шаги нарушают DR-1 (проверено 2026-06-15):
Оркестратор `enforce-mentor-then-judge` (PostToolUse Write, [settings.json:185](../../.claude/settings.json#L185), timeout 300с) гонит наставника → судью строго по очереди; при ОБОИХ GO артефакт печатается сам. **Печать не проси у владельца** — это не ручное действие.
- каждый мутирующий шаг **проверяем** — после Edit/Write идёт Bash-проверка;
- **два Edit ОДНОГО файла подряд без Bash между — запрещены** (объединить в один контурный Edit ИЛИ
вставить Bash между; MultiEdit недоступен, поэтому планируй один аккуратный `old_string`);
- **дублирующие шаги** (повторный идентичный Bash без новой неопределённости) — избыточны, убрать.
- **Тупой судья навыков** (`enforce-domain-skill-discipline` [settings.json:65](../../.claude/settings.json#L65)): навыки из `skills-json` опечатанного плана обязаны быть реально вызваны (журнал) до первого мутирующего шага, иначе блок. Объявленный навык стена пускает к вызову (`isPlanDeclaredSkill`, матч по суффиксу).
- **Критерий-судья** (`enforce-criterion-gate`): на git commit/push через Claude — по-критерийный GREEN. Коммиты в терминале владельца минуют.
- **Видимость вердиктов** (`enforce-verdict-surface`, UserPromptSubmit [settings.json:302](../../.claude/settings.json#L302)): в начале следующего хода всплывают подписанные строки `🧭 РОУТЕР / 🧑‍🏫 НАСТАВНИК / ⚖️ СУДЬЯ`. Вердикт у владельца спрашивать больше не надо. Best-effort/fail-open.
- **Память кругов** (`round-memory-*`): круг 1 слеп; круг 2+ судья/наставник видят свои прошлые претензии дословно + доводы контроллера из `## Переговоры` → не противоречат себе.
- **Арбитраж** (`enforce-gate3-loop`, Stop [settings.json:262](../../.claude/settings.json#L262)): на 3-м NO-GO подряд — карточка: «держусь контроллера» (`owner-seal:<hash>`, перевешивает NO-GO) / «согласен» (переделать) / «своё решение». owner-seal — тяжёлое (терминал).
**Полный vitest через Claude-Bash рушит воркеры** («Cannot read properties of undefined (reading
config)» каскадом по ~230 файлам) — это harness-collapse под нагрузкой сессии, НЕ провалы тестов.
Verify-шаги под стеной сдвигают указатель, но GREEN недостоверен — **авторитетный полный свод гонит
владелец в своём терминале** (`npx vitest run --config vitest.config.tools.mjs`), коммит тоже там.
**Правила судьи к плану (DR-1):** каждый мутирующий шаг проверяем (после Edit/Write — Bash-проверка); два Edit одного файла подряд без Bash между — запрещены (MultiEdit недоступен → один аккуратный `old_string`); дублирующие шаги убрать.
**NB: наставник иногда контаминирует критику** между спеками (тащит замечание с чужого артефакта —
напр. требует удалить блок, которого в файле нет). Сверь замечание с реальным содержимым; если блока
нет — это ложняк (известный H4), плодить версии не нужно.
**Правки памяти/CLAUDE.md под стеной:** объяви `claude-md-management` в `skills-json` И реально вызови до записи — иначе гейт памяти/судья навыков заблокируют. (Тяжёлая нормативка — чище в штатном.)
## Уроки сессии №4 (2026-06-15) — escape / печать / коммиты
---
- **Печать ≠ escape.** Судья чтит escape (`enforce-judge-gate` 316-325 → block:false), но escape **только снимает
блок**, печать НЕ ставит — печать (`sealOnWiredGo`) только при настоящем `wired GO` судьи (337). Чтобы открыть
режим исполнения (нужны опечатанные И спека, И план), нужен чистый GO, не вейвер/escape.
- **Деадлок «судья не дал текста» (`[fatal]`/3 круга) = флапнувший/degraded судья.** Лечение — **retry новым
именем** спеки/плана (свежий вызов часто отвечает внятно). Не продавливать тот же артефакт.
- **`verified-context-json` ids НЕ совпадать с анкерами секций `{#D1..D5}`** — коллизия (`id:"D3"``{#D3}`)
даёт `[fatal] D3`. Бери самостоятельные метки (`ac1`/`pc1`/`fx1`…).
- **План — точечными diff'ами (old/new по 5-10 строк), НЕ Write-overwrite целых файлов** — судья зовёт перепечатку
файла `[heavy]`.
- **Self-Review не переоценивать.** Судья (gate2) валит «claim … only adds optional parameter without injection
point» — добавляй блок Scope (что в церемонии vs что отдельный таск) и пиши покрытие честно («частично»).
- **Коммит через Claude РАБОТАЕТ под escape** (в claude-brain): `enforce-router-gate` НЕ подключён (design v6 §6),
`enforce-criterion-gate` чтит escape (строка 28), стена М2 + пол М5 — тоже. **Один `floor_escape` на git-команду
закрывает все гейты.** Рецепт: AskUserQuestion, опцией — точная метка `FLOOR-ESCAPE: bash:<команда>` → клик
подписывает → гони РОВНО ту команду (нормализуются пробелы) в окне 5 мин. Отслеживаемые файлы — `git commit --
<пути>` (1 escape, без add); новые — `git add` (escape) + commit. Сообщение **paren-free**, трейлер
`Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>`; `-- <пути>` изолирует ровно твои файлы.
- **Harness-collapse сохраняется ДАЖЕ при снятой стене.** `npx vitest` через Claude-Bash на любом файле с явным
`import {describe,it,expect} from 'vitest'` падает `Cannot read properties of undefined (reading 'config')`
одиночный И полный свод. **Run-GREEN через Claude-Bash недостижим → авторитет только терминал владельца.** Под
стеной verify-шаги всё равно двигают указатель (исход не важен); логику верифицируй на бумаге.
- **escape/вейвер ловит ТОЛЬКО клик AskUserQuestion, не свободный текст** (`enforce-askuser-answer-parser`
подписывает реальный ответ на AskUser, а не «пропускаем» в чате).
<a id="s8"></a>
## 8. Частые ошибки и тупики
## Уроки сессии №5 (2026-06-15) — escape-per-step при тупике наставника
- **Печать ≠ escape.** escape только снимает блок (block:false, указатель не двигает); печать встаёт ТОЛЬКО при `wired===true && decision==='GO'` (или owner-seal). ⚠️ **Два разных канала владельца:** chat-escape (`loadFloorEscapes`, лёгкий) разблокирует ОТДЕЛЬНОЕ действие, но режим исполнения НЕ откроет — для печати на арбитраже нужен **терминальный** `owner-seal:<hash>`. Не путать.
- **Ловушка устаревшего указателя.** План байт-в-байт = тот же `planId` → старая позиция не сбрасывается. Лечение: другой план (другое имя/шаги) ИЛИ `FLOOR-ESCAPE: plan-done`. Удаление файлов не помогает (позиция в runtime).
- **Десинк указателя (F-J).** Ранний хук (`supreme-gate`) сдвинул указатель, поздний PreToolUse-блокер (`skill-discipline`) уронил действие → шаг потерян. Профилактика: объявленные навыки вызови ПЕРВЫМ делом после печати, до первого мутирующего/Bash-шага. Сброс — новый план / `plan-done`.
- **Молчаливый срыв наставника (№7).** `main()` в `enforce-mentor-on-plan-write.mjs` обёрнут в `catch {}`; throw между роутером и LLM-вердиктом (напр. в `renderSkillContext`, [on-plan-write.mjs](../../tools/on-plan-write.mjs) вне try) глотается — нет вердикта, нет записи, нет ошибки, «будто ещё считает». При «застряло»: сначала **читай код** (в разговорном свободно), не опрашивай снимок по кругу; лечение — **перезапуск плана новым именем** (свежий `planId`; чуть варьируй шаг, напр. `--reporter dot`).
- **H4 — наставник видит только `steps-json`.** Тело плана/код/шаблоны в его промпт не идут ([mentor-verdict.mjs](../../tools/mentor-verdict.mjs)), поэтому требует «покажи шаблон»/«создай заглушки» даже когда модули есть. Судья же видит тело — асимметрия, слепой наставник бьёт первым. Сверяй с реальностью; опасное (заглушки поверх рабочих) не выполнять; доводы — в `## Переговоры`.
- **Недетерминизм судьи.** Запрос к LLM без `temperature:0`/`seed` ([router-classifier.mjs](../../tools/router-classifier.mjs)) → байт-идентичный текст может дать GO/NO-GO по-разному; невалидный JSON fail-closed → `[fatal]`/NO-GO без текста. «retry новым именем» работает потому что это новый сэмпл, а не из-за имени.
- **`wired:false` = три причины** (degraded / стёртый mentor-GO / транспорт) с разными лечениями — различай по `seal-attempts.jsonl` (Grep, не Read).
- **CRLF ломает vitest@4 (№8).** `SyntaxError` без позиции, а `node --check`/esbuild чисты → подозревай CRLF (autocrlf при checkout/merge), не синтаксис. Лечение: `.gitattributes` `* text=auto eol=lf`. **Harness-collapse:** полный `npx vitest` через Claude-Bash рушит воркеры (`Cannot read properties of undefined (reading 'config')`) — авторитетный свод гонит владелец в своём терминале.
- **Наставник контаминирует критику** между артефактами (требует убрать блок, которого нет) — сверь с содержимым, ложняк не плодит версии.
- **escape ≠ печать — ПОДТВЕРЖДЕНО кодом.** `enforce-judge-gate.sealOnWiredGo` печатает только при
`verdict.wired===true && decision==='GO'`. escape-ветка (316-325) даёт лишь `block:false` — печать НЕ
зовёт. Печать плана дополнительно требует `mentor-GO` (freeze-gate 350-353). Итог: при NO-GO наставника
печати не будет, и escape её не поставит. Режим исполнения через печать недостижим, пока наставник в NO-GO.
- **Баг наставника H4 — структурный тупик, НЕ сходится повторами.** Наставник (`onPlanWrite`) видит только
`steps-json` (`{op,object,ref}`), НЕ тело плана / код / шаблоны. Поэтому в L1-арбитраже требует «покажи
шаблон/код» (формат шага этого не несёт) и «создай заглушки для отсутствующих модулей» — даже когда модули
СУЩЕСТВУЮТ (выполнить = перезаписать рабочее, необратимый вред). Раздел `## Переговоры` он парсит
(`parseNegotiationSection`), но вердикт от него не меняется; круги растут (видели до 6). **Сверяй
требование с реальностью; ложное/опасное (заглушки поверх рабочих файлов) — НЕ выполнять.**
- **Канал при H4-тупике: owner escape-per-step.** Супрем-гейт (М2) чтит escape-грант в разговорном режиме →
на КАЖДЫЙ Edit/Write/Bash/Skill — отдельный разовый грант (`canonicalAction`, окно 5 мин, гасится
`floor-escape-consume`). Метка в опции AskUser: `FLOOR-ESCAPE: write:<путь>` / `bash:<кмд>` /
`skill:<имя>`. **Импл-навыки (executing-plans) тоже гейтятся** стеной как «реализация» → нужен
`skill:`-escape на их инвокацию. `replace_all`-Edit сокращает число грантов (несколько одинаковых правок
в одном файле — один грант).
- **canonicalAction лоуэркейсит ВЕСЬ путь (incl имя файла).** Метка escape должна нести путь в нижнем
регистре и прямыми слэшами: `router-mentor-wall-GUIDE.md``...router-mentor-wall-guide.md`. Иначе грант
не сматчится и стена заблокирует (проверено: первый escape с заглавным GUIDE не сработал).
- **Failed Edit НЕ гасит грант.** Если `old_string` не совпал — грант жив, можно повторить (PostToolUse-консьюмер
не срабатывает на упавшем инструменте — аналогия с упавшим Bash).
- **Вердикты читать Grep'ом, НЕ Read.** `~/.claude/runtime/{judge-verdicts,seal-attempts}.jsonl` — hard-deny
на Read (§3.1), но Grep их видит. `seal-attempts.jsonl` несёт `wired/decision/sealed/reason/at` на каждую
попытку → точная диагностика: `wired:false` = degraded/flap (повтор новым именем); `wired:true,decision:NO-GO`
= содержательный отказ (дорабатывать) или H4 (сверить с реальностью). Коррелировать по `at` (unix-ms).
- **deepseek-v4-pro: возможны красные тесты.** Миграция модели в `tools/router-config.mjs`
(`claude-sonnet-4-6``deepseek-v4-pro`, `HEAVY_LLM_TIMEOUT_MS` 90000→300000) ломает 3 теста
(`router-config`, `enforce-mentor-on-plan-write` timeout, `enforce-judge-gate` parse `plan_soundness`) —
это пре-существующий дрейф, НЕ регресс твоей задачи. Не путать со своими провалами.
---
## Уроки сессии №6 (2026-06-17) — escape-рецепт + verify-gate
<a id="s9"></a>
## 9. Только владелец (штатный режим, снятие печати)
- **Метка escape — в LABEL опции, НЕ в описании.** `enforce-askuser-answer-parser` подписывает
ВЫБРАННЫЙ ответ = текст label. Маркер `FLOOR-ESCAPE: <action>` в `description` НЕ подписывается
(проверено вживую: Edit блокнут «разговорный режим», грант не записан). Клади ТОЧНУЮ каноническую
строку прямо в `label`.
- **Один маркер на вопрос; батч = несколько ВОПРОСОВ.** Две метки в одном label (через перенос
строки) НЕ подписываются. «Разные файлы в одном AskUser» = массив `questions[]` (до 4), каждый
вопрос = один грант. Один файл несколько раз = РАЗНЫЕ раунды/вопросы.
- **Грант одноразовый — ВСЕ правки файла ОДНИМ Edit.** `enforce-floor-escape-consume` гасит грант на
первом УСПЕШНОМ Edit; вторая правка того же файла под тем же грантом блокнётся. Делай широкий
`old_string`, охватывающий все изменения, либо запрашивай отдельный грант. Упавший Edit грант НЕ
гасит (можно повторить). Read-перед-Edit обязателен и тут — Grep чтение не засчитывается.
- **`enforce-verify-gate` ≠ escape/override.** На `git commit`/`push` через Claude требует ПОДПИСАННУЮ
`~/.claude/runtime/verify-receipt.json` (fingerprint == staged-diff) от `node tools/produce-verify-receipt.mjs`.
Ни `floor_escape`, ни `ремонт инфраструктуры` его не снимают. А продюсер в claude-brain СЛОМАН (смотрит
на `app/vitest.config.tools.mjs` после сплита → always suite-not-passed, см. `bags/2026-06-17-produce-verify-receipt-app-path-bug.md`)
→ Claude-коммиты тут тупиковы, коммить в терминале владельца (verify-gate — Claude-PreToolUse-хук).
- **`node tools/verdict-wait.mjs` разрешён в стене** как read-only сторож видимости вердиктов
(`isObserveOnly` regex без цепочек/редиректов) — для по-этапного ожидания вердиктов под стеной.
**Штатный режим** (`standby-mode-control.mjs`, UserPromptSubmit [settings.json:311](../../.claude/settings.json#L311)) — двухтактный хендшейк:
1. фраза «штатный режим» → хук просит подтверждение;
2. владелец подтверждает дословно **«да, штатный»** → стена off;
3. вернуть стену — **«выключи штатный»**.
## Уроки сессии №7 (2026-06-17) — диагностика «наставник не вернулся» (молчаливый срыв)
Claude обязан **запросить** подтверждение, а не считать штатный включённым по просьбе. В штатном остаются: **пол + точки возврата (`enforce-snapshot`) + проверка-перед-пушем (verify/criterion)**; снимается только стена (`standbyActive` проверяется в `enforce-supreme-gate.mjs`). Сброс штатного — на SessionStart (`standby-session-reset.mjs`), поэтому после перезапуска сессии его надо включать заново.
**Симптом.** Написал план, печать не встаёт, режим разговорный. В снимке вердиктов нет записи по
плану (нет 4-го `hash`), наставник/судья по плану не появляются — будто «ещё считает» бесконечно.
**Снятие застрявшей печати** (владелец): новый план с другим именем; ИЛИ `FLOOR-ESCAPE: plan-done`; ИЛИ maintenance — заменить весь блок `"hooks": {…}` на `"hooks": {}` + перезапуск Claude Code. **Перезапуск ≠ сброс печати** (план/указатель живут в runtime отдельно от settings).
**Причина (корневой дефект машинерии).** `main()` в `tools/enforce-mentor-on-plan-write.mjs`
обёрнут в `catch { /* производитель никогда не блокирует */ }`. Любой throw МЕЖДУ вызовом роутера
(`classifyImpl`/`classify`) и LLM-вердиктом наставника проглатывается МОЛЧА — нет вердикта, нет
записи в снимок, нет печати, нет ошибки. Незащищённое место: `renderSkillContext`
([tools/on-plan-write.mjs](../../tools/on-plan-write.mjs) ~стр.71) НЕ в `try`; ранний throw там или
в `runMentorVerdict` до транспорта → всплывает в молчаливый catch. В снимке
**«упало-и-проглотилось» НЕОТЛИЧИМО от «ещё считает»** — в обоих случаев записи просто нет.
Чтение `~/.claude/runtime` контроллеру закрыто (`enforce-read-path-deny`); вердикты — через `enforce-verdict-surface` или Grep по runtime.
**Чем срыв отличается от медленной модели.** В логах вызовов владельца (внешняя панель провайдера):
роутер по плану отработал (есть строка `Agent Router` / `recommend`), а **второго вызова
`Agent mentor` после него НЕТ**. Это срыв, а не латентность. Если доступа к логам нет — считать
«вердикта нет дольше 1-2 циклов ПОСЛЕ того как роутер точно отработал» = вероятный молчаливый срыв.
---
**Рецепт (что делать — НЕ повторять прокол сессии №7):**
<a id="s10"></a>
## 10. Что под капотом (хуки + env)
1. **НЕ опрашивать снимок по кругу и НЕ гадать «медленная модель».** «Нет 4-го hash» — это НЕ
диагноз (срыв и счёт выглядят одинаково).
2. **Сразу читать оркестратор** (`enforce-mentor-on-plan-write.mjs` + `on-plan-write.mjs`) — чтение
в разговорном режиме свободно. Помнить про молчаливый catch: он прячет срыв.
3. **Лечение — перезапуск плана НОВЫМ именем файла** (свежий `plan_id` фитилит наставника заново;
`planId` от steps, поэтому при идентичных шагах слегка варьируй один шаг, напр. `--reporter dot`).
Транзиент обычно не повторяется — r2 печатается чисто. Это быстрее, чем ждать/спрашивать владельца.
4. **Опрос снимка полезен ТОЛЬКО чтобы поймать момент печати** (Grep `verdict-snapshot` блокируется
стеной = план опечатан = режим исполнения), но НЕ как диагноз зависания.
**PreToolUse** (порядок в [settings.json](../../.claude/settings.json)): `enforce-floor` (пол) → `enforce-domain-skill-discipline` (судья навыков) → `enforce-supreme-gate` (стена) → `enforce-snapshot` (точки возврата) → `enforce-normative-content-rules` (§6 память/нормативка) → `enforce-read-path-deny``enforce-mcp-classification``enforce-verify-gate``enforce-criterion-gate``enforce-todowrite-skill-verifier``askuser-cosmetic-detector`.
**PostToolUse:** `enforce-mentor-then-judge` (Write) · `enforce-skill-journaler` (Skill) · `enforce-askuser-answer-parser` + `enforce-floor-escape-consume` (escape) · markdownlint-fix `.md`.
**Stop:** observer / cost / `enforce-coverage-verify` / `enforce-verdict-ack` / `enforce-gate3-loop` (арбитраж).
**SessionStart:** `floor-manifest-check` (сигнал, не блок) / warmup / `standby-session-reset`.
**UserPromptSubmit:** `enforce-verdict-surface` / `standby-mode-control`.
**Мета-урок.** При «застряло» — сначала прочитать код пути (средства под рукой в разговорном
режиме), потом действовать. НЕ скатываться в «ждать или спросить владельца», когда можешь сам
диагностировать чтением. Owner видит вердикты в логах — но это не повод не открыть код самому.
**Живой шов требует env:** `ROUTER_MENTOR_SEAM_ENABLED=1`, `ROUTER_MENTOR_JUDGE_ENABLED=1`, `ROUTER_MENTOR_JUDGE_MODE=block` + ключи наставника/судьи/роутера. Нет ключа → degraded (`wired:false`).
## Уроки сессии №8 (2026-06-17) — CRLF ломает vitest@4 (фантомный SyntaxError)
**⛔ Не править машинерию стены под стеной.** `tools/enforce-*`, `judge-*`, `mentor-*`, `floor-*`, `escape-grant`, `plan-lock` — discipline-source: `enforce-normative-content-rules §6` блокирует их правку, и write-escape это НЕ снимает. Правь в терминале (string-replace по якорям + бэкап + verify) и сразу коммить.
**Симптом.** Полный свод краснеет N файлами с `SyntaxError: Invalid or unexpected token` БЕЗ позиции,
а `node --check`, `esbuild` (даже `--bundle` со всеми импортами) и прямой `node import()` те же файлы
парсят ЧИСТО. Под Claude те же файлы дают `Cannot read properties of undefined (reading 'config')`.
Статикой не воспроизводится — кажется, что «код валиден, а vitest врёт».
**Причина.** Windows git `core.autocrlf` при КАЖДОМ касании файла (merge/checkout) делает тронутые
`.mjs` в рабочем дереве **CRLF**. vitest@4 (vite-transform) давится на `.mjs` с CRLF + шебангом
(`#!/usr/bin/env node`) → `SyntaxError`. node/esbuild CRLF терпят — поэтому ВСЕ статические проверки
молчат. Падают ровно «тронутые git» файлы; нетронутые (LF) проходят. Закоммиченный код при этом LF
и корректен — CRLF живёт только в рабочем дереве (артефакт autocrlf).
**Диагностика (чтобы не потерять часы):**
1. `node --check` / `esbuild` / `node -e "import('./f.mjs')"` зелёные, а vitest красный → подозревай
НЕ синтаксис, а кодировку/переносы.
2. Читай СЫРЬЁ как Buffer (utf8-чтение СРЕЗАЕТ ведущий BOM и не видит CRLF через `charCodeAt`):
`node -e "const b=require('fs').readFileSync('tools/f.mjs'); console.log(b.includes('\r\n'), b.slice(0,3).toString('hex'))"`.
3. Подтверди: конвертни файл CRLF→LF и перепрогони — зелёный = это оно.
**Лечение (насовсем).** `.gitattributes` в корне: `* text=auto eol=lf` (git хранит и выдаёт LF
независимо от `core.autocrlf`). Разовая нормализация рабочего дерева — `node`-скрипт
`...replace(/\r\n/g,'\n')...` по всем `.mjs`, либо `git add --renormalize <безопасные-пути>` (НЕ всё:
`.claude/settings.json` под стеной-off трогать нельзя).
**Мета-урок.** «SyntaxError без позиции» + «статика чистая, vitest красный» = почти всегда
CRLF/кодировка, а не логика. Проверь байты и переносы ПЕРВЫМ делом, а не последним.
## Уроки сессии №9 (2026-06-17) — формат ПЛАНА: verified-context-json + ref=якорь (не проза)
**Симптом (частая ошибка новой сессии).** Спека опечатана, план содержательно отличный, но печать
не встаёт — наставник/судья вроде не против, а seal не приходит.
**Причина — нарушен ФОРМАТ плана, не суть:**
1. в плане НЕТ блока ` ```verified-context-json``` ` — а он обязателен и для ПЛАНА (≥1 `EXTRACTED` с
реальным якорём-подстрокой), иначе печать не встаёт;
2. в `steps-json` поле `ref` несёт ПРОЗУ-описание («Task1 RED: …») вместо якоря спеки. `ref` обязан
быть НЕПУСТЫМ якорем секции спеки (`{#u3}``ref:"u3"`; `D1..Dn`/`u1..un`).
3. навык в `skills-json` — БЕЗ плагин-префикса (`test-driven-development`, не
`superpowers:test-driven-development`).
**Лечение:** добавить в план блок `verified-context-json` (готовый рабочий якорь: ref
`tools/cost-pricing.mjs`, anchor `export const PRICING = Object.freeze(`) + заменить все `ref` на
якоря секций спеки.
**Прецедент (параллель-сессия трек 2c, 2026-06-17).** План r1 не имел `verified-context-json` и нёс
прозу в `ref` → печать не вставала; контроллер переписал план трижды (r1→r2→r3), на r3 добавил
`verified-context-json` EXTRACTED + якорные `ref` → наставник GO, судья GO, церемония пройдена. Суть
фичи была верной с r1 — итерации терялись ТОЛЬКО на ритуальном формате. **Вывод:** сверь план с
«Рецептом церемонии» (выше, п.2) ДО первой записи — экономит 2-3 круга наставника/судьи.
[↑ наверх](#top)
@@ -0,0 +1,70 @@
# Дизайн: единый код-верифицированный гайд по стене «роутер-наставник»
**Дата:** 2026-06-19 · **Статус:** дизайн на согласовании владельца
## Контекст и проблема
Сейчас в репозитории **два** файла `router-mentor-wall-GUIDE.md`, и они расходятся:
- `docs/superpowers/router-mentor-wall-GUIDE.md` (378 строк) — наш гайд, база сессии №9 (17.06.2026);
- `bags/router-mentor-wall-GUIDE.md` (370 строк) — **чужой**, гайд стены **Лидерры** (она старее и проще нашей). Скопирован сюда как **источник багов** для вычистки, НЕ как обновление нашего гайда. По ошибке правился вместо нашего.
Расхождения опасные (напр. рецепт escape в Лидерра-копии помечает наш старый рецепт как закрытую дыру — но это про ИХ стену, не нашу). Нужен **один** актуальный гайд, где **каждое правило и каждый урок подтверждены по коду нашей текущей стены**.
## Цель
Собрать **один** код-верифицированный гайд по нашей стене, удалить оба текущих файла (точнее: перезаписать канонический, удалить `bags/`-копию). Гайд — краткий, но информативный, с оглавлением для быстрого поиска внутри сессии.
## Не-цели
- НЕ менять поведение стены (никаких правок `tools/enforce-*` и пр.).
- НЕ переносить правила Лидерры как есть — только то, что подтверждено НАШИМ кодом.
- НЕ трогать нормативный квинтет (Pravila/CLAUDE.md/…) — кроме условной правки указателя §0, и только через `claude-md-management`.
## Результат
- **Один файл** по каноническому пути `docs/superpowers/router-mentor-wall-GUIDE.md` (тот, что в CLAUDE.md §0 «читай первым»).
- `bags/router-mentor-wall-GUIDE.md`**удалён**.
- Никаких временных/черновых файлов не оставляем (CLAUDE.md п.11).
## Структура единого гайда (согласована)
Шапка (что это, дата-штамп, «читать перед работой под стеной») + **кликабельное оглавление**, далее:
1. Суть и поток (спека→печать→план→печать→шаги→авто-финиш)
2. Рецепт церемонии (точные форматы: `verified-context-json`, `skills-json`, `steps-json`, якоря/`ref`)
3. Режимы и проба состояния (разговорный / исполнение / снято; одна проба)
4. Что свободно vs что гейтится (чтение кода, авторская запись, Bash-цепочки, floor-safe, запуск скриптов-файлов)
5. Аварийный выход (escape) — лёгкое vs тяжёлое ⚠️ *макс. риск расхождения с Лидеррой*
6. Коммит / пуш через стену (частокол гейтов; что снимает escape, что нет)
7. Субагенты под стеной (только разведка, почему)
8. Судьи-машины (тупой судья навыков, критерий-судья, видимость вердиктов, память кругов, арбитраж)
9. Частые ошибки и тупики (десинк указателя, молчаливый срыв наставника, H4, CRLF/vitest, harness-collapse)
10. Только владелец (settings, снятие застрявшей печати, maintenance-off, **штатный-хендшейк**)
11. Что под капотом (имена хуков + env-переменные шва)
**Код-якоря инлайн** в каждом разделе (правило → `файл:строка`), не отдельным приложением.
## Метод аудита
Read-only разведчики (Explore/general-purpose) идут **параллельными волнами**, каждый — под **линзой-скилом**, возвращают находки **только текстом** (файлы не пишут):
- **A — `verification-before-completion`:** буквальное «правило ↔ код», каждый вывод с цитатой `файл:строка`; без цитаты нет утверждения.
- **B — `sharp-edges`:** крайние случаи и недосказанные оговорки правила.
- **C — дрейф/устаревание:** правила, перебитые более новым кодом нашей стены (особенно Лидерра-баги, которых у нас нет).
- **D — полнота:** поведение стены, которое есть в коде, но не описано ни в одном гайде → нюансы для расширения.
**Контроллерская сверка (я лично):** по каждому несущему/рискованному пункту перечитываю реальный код перед внесением в гайд. Субагентам на веру не беру (память `subagent-falsified-test-results`).
Разделы 5–8 — макс. риск расхождения → аудит жёстче.
## Уже зафиксированные нюансы (в гайд)
- **Штатный-хендшейк:** переход в штатный (стена off) не наступает по одной просьбе — Claude обязан ЗАПРОСИТЬ подтверждение, владелец подтверждает дословной фразой **«да, штатный»**. В штатном остаются: пол, точки возврата, проверка-перед-пушем. Вернуть стену → **«выключи штатный»**.
## Критерий готовности (verification gate)
- каждое правило/урок в новом гайде имеет живой код-якорь (`файл:строка`), проверенный лично;
- оба старых файла сведены в один (канонический перезаписан, `bags/`-копия удалена);
- все ссылки оглавления резолвятся;
- временных файлов не осталось.