docs: wall-GUIDE — операт. заметки допила (B+C ч.2/D1/D2/§3.4)

bags/router-mentor-wall-GUIDE.md: новый раздел «Обновления 18.06.2026» —
осмотр-сеанс op:"session", деплой агентом (ops-runbook:<hash>), коммит агентом
(commit:<hash>, гейты качества остаются), §3.4 десинк помечен ПОЧИНЕН. Дисциплины
A/D1 (читать вывод→стоп на аномалии; под планом препятствие→перепланируй, не гадай).
Устаревший обход §3.4 в «Пуш кода» помечен снятым. Формальный свод (Pravila/CLAUDE.md)
— отдельно, через claude-md-management со включённой стеной (отмечено в GUIDE).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Дмитрий
2026-06-18 14:59:29 +03:00
parent a5830a8a1c
commit bd03df7f2b
+289
View File
@@ -0,0 +1,289 @@
# Как работать под стеной «роутер-наставник» (шпаргалка для сессий)
> Читать ПЕРЕД работой под стеной. **Обновлено 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`.
- **Осмотр сайта под планом (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) больше
НЕ нужен.
> Формальный свод правил (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-шаги: `node -e`/`curl`/install/eval, `rm -rf`/
`git push --force`/`migrate:fresh`, PowerShell-записи, запись в `~/.claude/runtime`/секреты. Пол их
рубит, стена не двигает указатель → план встаёт колом. Файловые операции — через Write/Edit, не `node -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 уронит первый шаг и уведёт указатель.
## ⛔ Нельзя: правка машинерии стены (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)
Разовое подписанное разрешение на ОДНО действие под стеной. Владелец даёт его **в ответе на
AskUserQuestion**: в ответе должна **буквально** присутствовать метка `FLOOR-ESCAPE: <action>`
среда ищет её регэкспом в конце ответа (`/FLOOR-ESCAPE:\s*(.+)$/`, см.
[tools/askuser-answer-parser.mjs](../../tools/askuser-answer-parser.mjs)::`toFloorEscapeRecord`).
Каноны `<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` (резерв-метка) · Опечатать на арбитраже → `owner-seal:<hash>` (Фикс 3)
**Канон пути для `write:`** — абсолютный, **lowercase**, прямые слэши `/`, NFC (ровно как даёт
`pathNormalizeSafe`). Пример: `write:c:/моя/проекты/портал crm/документация/docs/superpowers/router-mentor-wall-guide.md`.
Грант одноразовый, окно **5 минут**, точное посимвольное совпадение `canonicalAction` с действием
инструмента. **Применяй escape СРАЗУ** (иначе окно истечёт).
### Как дать escape ПРАВИЛЬНО (иначе клик уходит «в никуда») — урок 16.06
-**Контроллер делает САМУ кнопку AskUserQuestion = строкой `FLOOR-ESCAPE: <action>`**, владелец
её осознанно выбирает. Тогда ответ = текст кнопки = содержит метку → среда подписывает грант.
Это и есть «контроллер спрашивает — владелец выбирает — но ответ сформулирован верно».
-**Обычная кнопка** («Разрешаю», «Ок», «Да») — её текст НЕ содержит `FLOOR-ESCAPE:` → грант НЕ
пишется → стена держит. (Грабли: 3 клика подряд впустую, прежде чем поняли причину.)
-**Контроллер уговаривает владельца вписать метку в свободное поле ответа** — защита
`detectOtherSocialEng` (`askuser-answer-parser.mjs`) ловит такие фразы-подсказки как соц-инженерию
и флагует. Не диктуй текст в свободное поле — **давай метку готовой кнопкой**.
**Что escape чтит:** стена М2 / пол М5 / судья М4 / гейт памяти (память/нормативка). **НЕ чтит:**
`router-gate` (git — отдельный канал, см. «Коммит») и `normative §6` для discipline-source (F-K — правь терминалом).
**Активация (обязательна в settings.json):** PostToolUse `AskUserQuestion``enforce-askuser-answer-parser`
(writer, подписывает грант ключом `router-mentor-receipts`) + `Edit|Write|MultiEdit|Bash|PowerShell`
`enforce-floor-escape-consume` (one-shot, гасит грант). Без них клик уходит «в никуда».
## Коммит
- **Через стену — частокол гейтов:** `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`.
## Пуш кода через стену
Пуш кода (не 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 — в их разделах выше.