# Двухуровневые переговоры + арбитраж владельца (роутер-наставник) — дизайн (v2, якорный)

**Дата:** 2026-06-12. **Кодовая фраза:** «роутер-наставник».
**Статус:** ДИЗАЙН утверждён владельцем. v2 = тот же дизайн + явные якоря `{#id}` на разделах (нужно для печати артефакта: секции собираются только из якорей `## … {#id}`).
**Подход:** №1 — переиспользование живых кирпичей, TDD. **Ветка:** `main`.
**Первоисточник:** `2026-06-01-router-discipline-plan-anchor-design-notes.md` (D16/D23/D24/D30/D34/В5, R-COMM) + роадмап `2026-06-12-router-mentor-roadmap.md`.

---

## 1. Зачем (проблема) {#problem}

Двухуровневые переговоры с арбитражем:

- **L1 (контроллер ↔ наставник):** готовлю план → наставник даёт замечания → обсуждаем → договорились → к судье. Не договорились за 3 круга → эскалация владельцу.
- **L2 (судья):** замечание судьи → правлю → снова к наставнику → судье. До 3 раз. После 3 отказов → владельцу замечание судьи + моя позиция → владелец арбитр (моя позиция / судьи / своё).
- **Эскалация = арбитраж:** владельцу показывают обе стороны.

Не хватает 4 вещей: (1) контроллер видит замечания; (2) интерактивное обсуждение с наставником; (3) эскалация как арбитраж; (4) счётчики на обоих уровнях (живёт только судейский).

## 2. Три неизменных принципа {#principles}

- **П1.** Замечание доходит до контроллера **в тексте блок-сообщения хука** (read-deny не ослабляем).
- **П2.** Позиция контроллера живёт **в разделе «## Переговоры» план-файла** (видна владельцу, новый канал записи не нужен).
- **П3.** Решение владельца пишется в **защищённый журнал одобрений** (escape-grant / waivers), ворота читают его; со слов Claude не принимается.
- **R-COMM:** только по-русски, простыми словами, не вводить владельца в заблуждение.

## 3. Архитектура — две петли, два счётчика {#architecture}

L1 (контроллер↔наставник): круги, потолок 3 → арбитраж с наставником. L2 (контроллер↔судья): отказы судьи NO-GO, потолок 3 → арбитраж с судьёй. Связь: наставник GO → к судье; судья NO-GO → правка → снова к наставнику (счётчик L1 сбрасывается) → судье (L2 +1). Внешний пинг-понг ограничен потолком судьи (≤3). Счётчики независимы.

## 4. Поток L1 (контроллер ↔ наставник) {#l1-flow}

Пишу план (`writing-plans`, семя) → хук наставника выносит вердикт. GO → счётчик L1 сброшен, к судье. NO-GO → замечание в блок-сообщении → на круге: правлю план ИЛИ пишу «не согласен, потому что X» в раздел «Переговоры» → пере-запись → наставник читает весь план и пересматривает (+1 круг). Круги в `mentor-journal`. 3 круга без согласия → арбитраж. Счётчик L1 = managed-счётчик `round-control` + новый `bumpMentorNoGo` (зеркало `bumpJudgeNoGo`).

## 5. Поток L2 (судья) + вложенность {#l2-flow}

Наставник GO → судье (`enforce-judge-gate`). GO судьи → план запечатан, исполняю. NO-GO → замечание судьи в блок-сообщении → правлю → пере-запись возвращает к наставнику (новый круг L1) → наставник GO → снова судье (L2 +1, живой `bumpJudgeNoGo`). 3 отказа → арбитраж с судьёй. Активация L2 — Фаза 8 (тестируется при судье inert).

## 6. Арбитраж: карточка + канал решения {#arbitration}

Карточка (контроллер собирает, цитаты дословны): дословное замечание стороны (из блок-сообщения/журнала) + дословная позиция контроллера (из раздела «Переговоры») + нейтральная строка «что меняет каждый выбор» + аффорданс «объясни подробнее». Выбор владельца (`AskUserQuestion`, семя): держусь позиции / соглашаюсь / своё. Запись решения — через `escape-grant` (держусь/разрешаю) + `applyWaivers` (снятые возражения). После: держусь → ворота пропускают версию контроллера; соглашаюсь → переделываю, счётчик сброшен; своё → владелец вписывает обязательное.

## 7. Компоненты (всё в `tools/`, TDD) {#components}

Переиспользуем (бережно): `round-control.mjs` (счётчик L1 к живому циклу); `enforce-mentor-on-plan-write.mjs` (замечание в блок-сообщение, читает раздел «Переговоры»); `mentor-journal*.mjs` (круги + счётчик NO-GO); `enforce-judge-gate.mjs` (замечание судьи в блок-сообщение). Новое (малое, чистое): `mentor-nogo-counter.mjs` (зеркало `bumpJudgeNoGo`); `arbitration-card.mjs` (карточка); `negotiation-section.mjs` (парсер раздела «Переговоры»); `judge-objection-format.mjs` / `mentor-objection-format.mjs` (форматтеры). Канал решения — `escape-grant`/`applyWaivers` (живут).

## 8. Обработка сбоев (fail-closed) {#failures}

Битый счётчик → консервативно эскалация (как в `round-control`). Нет записи решения владельца → «не одобрено». LLM лёг (D27): код сверил с планом → пропуск; нужно суждение, а LLM нет → СТОП + эскалация; деньги кончились → громко владельцу; transient → тихий retry. Форматтеры fail-safe (мусор → пустая строка). Owner-facing — простой русский.

## 9. Границы {#boundaries}

Наставник живой — бережно, регрессия на каждом шаге. Судья inert в main → L2 тестируется без живого блока, активация Фаза 8 (шаг владельца). Read-deny и страж секретов не ослабляем. Субагенты (`op:Task`) запрещены машиной — исполнение inline.

## 10. Тестирование {#testing}

TDD. Регрессия tools-only: `npx vitest run --root app --config vitest.config.tools.mjs` (npx-кэш, vitest 4.1.8). Юнит-тесты: `arbitration-card` (дословность, 3 варианта, «что меняет», аффорданс); счётчики L1/L2 (сброс/потолок 3, битый → эскалация); канал решения (расход 1 раз, окно, отказ принять «решение» авторства Claude); хуки (замечание в блок-сообщении; раздел «Переговоры» прочитан); L2 при судье inert.

## 11. Открытые вопросы {#open-questions}

OВ-1 ручка видимости спора (В5 закрыт «итог+эскалации»). OВ-2 авто-одобрение волн (вне scope). OВ-3 калибровка наставника/судьи не-программистом (H1, отложено).

## 12. Известная брешь процесса: seed-write без ИИ-сторожа {#seed-gap}

Эта спека написана в условиях бреши, которую закрывает эпик. Запись файла-артефакта (Write) проходит без проверки наставником/судьёй — это **семя** (`supreme-gate` пропускает «печать артефакта», иначе bootstrap-круг). Но содержание семени в такой сессии не проходит ИИ-сторожа: судья судит на печати, наставник сторожит `plans/`. **Закрытие:** (1) Фаза 8 — живой судья на Гейте-1 (`extractGate1Product` судит `specs/`) проверяет содержание; (2) расширить наставника на `specs/`; (3) зажать семя (H4). **Предел (recursive-trust, L2):** запись первого артефакта невозможной не сделать; последний рубеж — владелец на видимом артефакте (D7/D17). **Урок сессии 12.06:** машина требует для inline-исполнения якорную спеку + исчерпывающий `steps-json` + отсутствие субагентов + нулевую итеративность — это ограничивает фиче-работу (находка для эпика).

## 13. Ссылки {#refs}

Замысел: `2026-06-01-router-discipline-plan-anchor-design-notes.md`. Роадмап: `2026-06-12-router-mentor-roadmap.md`. Живые модули: `round-control.mjs`, `enforce-mentor-on-plan-write.mjs`, `mentor-journal-store.mjs`, `enforce-judge-gate.mjs`, `judge-seal-channel.mjs`, `plan-lock.mjs`, `seal-orchestration.mjs`.
