70 lines
5.2 KiB
Markdown
70 lines
5.2 KiB
Markdown
# Баг: наставник GO с пустым `recommendation` → судья не вызывается (`no_mentor_go`)
|
||
|
||
**Дата:** 16.06.2026. **Где:** машинерия стены «роутер-наставник», оркестратор
|
||
`enforce-mentor-then-judge` (наставник → судья). **Severity:** блокирующий печать — план с
|
||
чистым GO не опечатывается. **Куда:** проект **claude-brain** (управляющий слой).
|
||
|
||
## Симптом
|
||
|
||
При записи опечатываемого плана наставник (Agent mentor, модель `deepseek-v4-pro`)
|
||
возвращает чистый GO без замечаний:
|
||
|
||
```json
|
||
{ "plan_points_addressed": [...], "reasoning": "...", "recommendation": "", "confidence": 0.95, "decision": "GO" }
|
||
```
|
||
|
||
Оркестратор применяет проверку-содержательности вердикта, видит **пустой слот
|
||
`recommendation`** и помечает вердикт несодержательным → `no_mentor_go` → **судья НЕ
|
||
вызывается** → план не печатается. В логе:
|
||
`несодержательный вердикт: пустые слоты [recommendation]` + `⏭ пропуск (no_mentor_go)`.
|
||
|
||
## Корень
|
||
|
||
Проверка-содержательности (введена M4-аудитом: «слот вердикта обязан быть непустой
|
||
строкой, `{}` больше не содержателен») применяется **одинаково** к GO и NO-GO. Для NO-GO
|
||
непустой `recommendation`/objection логичен. Для **GO** пустой `recommendation` — нормальное
|
||
состояние (плану нечего рекомендовать), но проверка его отбраковывает → валидный GO теряется
|
||
→ судья пропускается → печать не встаёт. Дефект делает невозможной печать «идеального» плана,
|
||
к которому у наставника нет замечаний.
|
||
|
||
## Воспроизведение
|
||
|
||
1. Записать чистый, корректный опечатываемый план (без спорных мест).
|
||
2. Наставник возвращает `decision:GO` с `recommendation:""`.
|
||
3. Печать не встаёт; в логе `no_mentor_go`, судья не вызывался.
|
||
|
||
**Обход (подтверждён 16.06):** добавить в `## Переговоры` плана круг, прямо приглашающий
|
||
наставника записать forward-`recommendation` (напр. «при одобрении зафиксируй в
|
||
recommendation указание исполнителю …»). Тогда слот непуст → судья вызывается → печать встаёт.
|
||
Это костыль уровня контроллера, не лечит корень.
|
||
|
||
## Предлагаемый фикс (корень)
|
||
|
||
Сделать проверку-содержательности **decision-aware**:
|
||
|
||
- `decision === 'GO'` → пустой `recommendation` **допустим** (достаточно непустого `reasoning`
|
||
и/или `plan_points_addressed`); вердикт содержателен.
|
||
- `decision === 'NO-GO'` → требовать непустой `recommendation`/objection (как сейчас).
|
||
|
||
## Где искать в коде
|
||
|
||
Слой, считающий `no_mentor_go` и проверяющий содержательность вердикта наставника:
|
||
`mentor-verdict.mjs` / `judge-orchestrator.mjs` / `enforce-mentor-then-judge.mjs`. Искать
|
||
проверку пустых слотов вердикта (`пустые слоты`, `no_mentor_go`).
|
||
|
||
## Доказательство (лог AITUNNEL)
|
||
|
||
16.06.2026 14:17:32, эндпоинт `/v1/messages`, модель `deepseek-v4-pro`, ключ «Agent mentor»,
|
||
ответ ASSISTANT: `"decision": "GO"`, `"confidence": 0.95`, `"recommendation": ""`,
|
||
`plan_points_addressed` заполнен (обе претензии сняты) → оркестратор: `no_mentor_go`, судья не
|
||
вызван. На следующей итерации плана с Переговоры-кругом, приглашающим recommendation, наставник
|
||
вернул GO с непустым `recommendation` → судья вызвался → план опечатан.
|
||
|
||
## Связанная находка (для того же разбора)
|
||
|
||
Десинк **criterion-gate**: `enforce-supreme-gate` удаляет frozen-plan на совпадении
|
||
**последнего** шага плана раньше, чем `enforce-criterion-gate` (со-хук) проверит
|
||
`frozenPlanValid` → ложный блок git push «кодовое изменение без валидного запечатанного
|
||
плана». Лечится не-терминальным мутирующим шагом, но корень — порядок хуков (supreme-gate не
|
||
должен удалять печать, если со-хук в той же цепочке блокнёт действие). Тот же класс, что F-J.
|