# Фикс гонки печати: оркестратор «наставник → судья» (строгая последовательность)

## Цель

Печать способа-B (frozen-plan / frozen-artifact) не встаёт за одну церемонию: наставник и судья
зарегистрированы как ДВА отдельных PostToolUse Write-хука, Claude Code гонит их параллельно,
судья читает mentor-GO/вердикт наставника раньше, чем наставник их дописал (~30с) → `mentorApproved`
ложно false → судья пропускает суд/печать. Дизайн заложил «судья строго ПОСЛЕ наставника» — это
надо обеспечить по-настоящему.

## Границы (что НЕ трогаем)

- Логика M1-M7 — байт-в-байт: как судят наставник и судья, freeze-gate, печать, пол M5, escape M6,
  расписки M1, стена M2. Ноль правок решающей логики.
- `tools/enforce-mentor-on-plan-write.mjs` и `tools/enforce-judge-gate.mjs` — **не меняются**; их
  `main()` лишь перестают быть зарегистрированными в settings.json.
- Меняем только ОРКЕСТРАЦИЮ (как запускаются), не РЕШЕНИЯ.

## Решение D1 — оркестратор «наставник→судья» {#D1}

Новый файл `tools/enforce-mentor-then-judge.mjs` — тонкая обёртка, единственный PostToolUse Write-хук
вместо двух. Читает событие один раз, переиспользует экспортируемые функции машин КАК ЕСТЬ:
`runMentorOnPlanWrite` (из enforce-mentor-on-plan-write) и `runJudgeTurn` (из enforce-judge-gate).
Сначала до конца отрабатывает логику наставника (он пишет mentor-GO + вердикт + журнал — реальный
I/O-wiring повторяет mentor `main()`), затем — логику судьи (он читает УЖЕ свежий mentor-GO/вердикт,
в том же процессе, строго после). I/O-инъекции (ключи, журнал, печать, deps) повторяют существующие
`main()` обеих машин — без изменения самих машин.

## Решение D2 — exit-семантика: круг L1 первым {#D2}

Наставник **NO-GO/degraded** → оркестратор отдаёт exit-2 с замечанием наставника, и **судья НЕ
запускается** (круг L1: сначала наставник доволен, потом несёт судье — как в Р3). Наставник **GO** →
оркестратор запускает судью, и наружу идёт exit судьи (GO → allow + печать встала; NO-GO → замечание
судьи через тот же exit-2 канал). Счётчики L1/L2, карточка арбитража, finish-грант — внутри
переиспользуемых функций, не дублируются.

## Решение D3 — машины байт-в-байт + регистрация владельцем {#D3}

Машинные файлы не редактируются. В `settings.json` (шаг владельца) два блока PostToolUse Write
(`enforce-mentor-on-plan-write` + `enforce-judge-gate`) заменяются ОДНИМ блоком → `enforce-mentor-then-judge`,
таймаут ~120с (вмещает два LLM-вызова последовательно). До регистрации оркестратор инертен (старые
хуки работают как раньше — гонка остаётся, но ничего не ломается).

## Критерий приёмки

- `runMentorThenJudge(event, deps)` (чистое ядро оркестратора): наставник NO-GO → block с замечанием
  наставника, судья НЕ вызван; наставник GO → судья вызван ПОСЛЕ, его решение отдано наружу.
- Машинные файлы enforce-mentor-on-plan-write.mjs / enforce-judge-gate.mjs не изменены (git diff пуст).
- Регрессия tools-only зелёная (база 3901 + новые тесты оркестратора), 0 регрессий.
- После регистрации владельцем: одна церемония spec→plan печатает frozen-artifact + frozen-plan без prime+catch (ручная проверка владельца).

```verified-context-json
[{"id":"1","kind":"EXTRACTED","claim":"логика наставника экспортируется как runMentorOnPlanWrite","ref":"tools/enforce-mentor-on-plan-write.mjs:101","anchor":"export async function runMentorOnPlanWrite"},
{"id":"2","kind":"EXTRACTED","claim":"логика судьи экспортируется как runJudgeTurn","ref":"tools/enforce-judge-gate.mjs:278","anchor":"export async function runJudgeTurn"},
{"id":"3","kind":"EXTRACTED","claim":"судья пропускает суд без mentor-GO (skip no_mentor_go) — корень гонки","ref":"tools/enforce-judge-gate.mjs:114","anchor":"skip: 'no_mentor_go'"}]
```
