# A1 — Активация судьи М4 на Гейт-2 (под фактически собранный код)

**Дата:** 2026-06-09 · **Эпик:** «роутер-наставник» · **Ветка:** `worktree-brainrepo` · commit-not-push.
**Код A1:** коммиты `0c6f084f..e8958155` (+ spec/plan `cfca7ecf`). Реализация — `tools/enforce-judge-gate.mjs`.
Это **implementation-specific** дополнение к общему runbook `2026-06-09-router-mentor-activation-A1-A6-A7.md` §A1.

> До твоих рубильников хук **инертен, $0** (нет флага/ключа → `judgeGateMode==='inert'` → allow без прогона).

---

## Что включается (твои 🔴-шаги по порядку)

1. **HMAC-ключ судьи** в keychain (нужен, чтобы `judgeActive` стал true):
   - service `router-mentor-judge`, account `default` (точно — `tools/judge-key-config.mjs`).
   - назначение — подпись под-прогонов судьи (отдельный домен от транспорта). Без него судья инертен.
2. **Транспорт-ключ** `ROUTER_LLM_KEY` (env, **тот же, что у классификатора**) — уже есть, если работает router-classifier.
   - **Важно (Δ-C):** если флаг+HMAC включены, но `ROUTER_LLM_KEY` отсутствует — судья НЕ блокирует всё подряд,
     а уходит в **degraded-allow + WARN** (`judge_unavailable` в логе). Это специально (урок v4-over-block).
3. **Флаги** (env, строго):
   - `ROUTER_MENTOR_JUDGE_ENABLED=1` (ровно `1`; иначе inert).
   - `ROUTER_MENTOR_JUDGE_MODE=shadow` (дефолт; опечатка → безопасный shadow). Block — отдельным шагом ниже.
4. **Регистрация ОБЁРТКИ** `enforce-judge-gate` в `.claude/settings.json` как **PreToolUse**, matcher `Write`
   (Гейт-2 судит только запись плана; хук сам отфильтрует не-план → allow). Команда: `node tools/enforce-judge-gate.mjs`.
   - Регистрировать **обёртку**, не движок (`judge-engine`/`judge-orchestrator` без `main()`/транспорта — у них нет рубильника $0).
   - Зеркаль формат существующих PreToolUse `enforce-*` записей в settings.json.
5. **Перезапуск** сессии.

## ✅ Проверка (shadow, 1-2 дня)

- Создай план через `Write` в `docs/superpowers/plans/*.md` (или сделай любой) → судья прогонится, но **НЕ заблокирует**.
- Лог вердиктов: `~/.claude/runtime/judge-verdicts.jsonl` (читаешь ты — runtime мне закрыт):
  - `{"kind":"verdict","functionName":"gate2","decision":"GO|NO-GO",...}` — судья отработал.
  - `{"kind":"judge_unavailable",...}` — судья не смог (нет `ROUTER_LLM_KEY` / транспорт упал). Если их много — проверь `ROUTER_LLM_KEY`.
- **На что смотреть:** нет ли ложных NO-GO на нормальных планах (over-block-калибровка, как у v4-судьи). На обычные тулы
  (не-Write / не-план) судья молчит и денег не тратит ($0).

## Перевод в боевой

- После чистого shadow: `ROUTER_MENTOR_JUDGE_MODE=block` → перезапуск.
- Теперь NO-GO на запись плана **блокирует** запись (Гейт-2 приёмка). degraded-allow (судья недоступен) по-прежнему пропускает.

## ↩ Откат

- `ROUTER_MENTOR_JUDGE_MODE=shadow` (если был block) ИЛИ снять `ROUTER_MENTOR_JUDGE_ENABLED` → inert, $0.

## Границы A1 (что НЕ входит — следующие фазы)

- **A6** (журнал М1) и **A7** (наставник М3 live-wiring) — отдельно; A7 требует живых A1+A6 (см. общий runbook).
- A1 судит **только план реализации (Гейт-2) на Write**. Гейт-1 (спека) / Гейт-3 (результат) / A2 — не в A1.
- **Спенд:** inert=$0 / shadow=метеренный (LLM-вызов за каждую запись плана) / block=метеренный.
- **Отложено (documented):** дедуп по content-hash + per-session budget-cap (Write-only уже ограничивает частоту).
