feat(skill): coordinator-loop — топология ревью под Codex и эскалация

- Зачем:
  - боевой прогон цепочки 07-11 показал: worker в Codex не может запускать
    субагентов, ревью шло пятью кругами без ограничителя, финальный handoff
    и закрытие issue выпадали из цикла.
- Что:
  - ревьюеров запускает координатор (наблюдатели, ограничение промптом),
    триаж находок и флаг «спор» — в worker-е; политика кругов с потолком.
  - две ручки стоимости: модель по роли и уровень мышления, таблица
    references/effort-levels.md; шаблон references/reviewer-prompt.md —
    скилл самодостаточен, без файлов claude-team-review.
  - журнал с метками времени; финал: PRD до ревью, Status: done
    docs-коммитом, handoff — условие выхода; handoff пакета правок.
- Проверка:
  - адверсарное ревью пакета свежим субагентом (2 блокера и 7 important
    закрыты) плюс саморевью; следующий боевой прогон цепочки — замер.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
ddadminandClaude Fable 5 committed 2026-07-04 20:09:35 +03:00
1 parent 2ed3fd81ea
commit 2d9fc7eadb
6 files changed
+542 -77

No files matched your search

@@ -0,0 +1,210 @@
# Handoff: топология ревью под Codex, эскалация и дисциплина финала
Дата: 2026-07-04 MSK
Статус: пакет правок по итогам боевого прогона; прошёл адверсарное ревью свежим
субагентом (2 блокера, 7 important, 4 minor — все закрыты правкой этого текста).
В `SKILL.md` вносится следом.
## Зачем этот handoff
Зафиксировать решения по итогам первого боевого прогона переписанного скилла
(цепочка issue 07 → 11 фичи `generator-model-time-startup-history`,
репозиторий `~/sources/clickstream-ch-kafka-superset-demo`) до правки `SKILL.md`.
Источник фактов — журнал прогона
`.scratch/generator-model-time-startup-history/coordinator-journal.md`
(коммиты `d2899e9`, `5081319`, `0a240e3`): отдельного handoff'а координатор не
написал, диагностика лежит в журнале.
## Что показал прогон
Хорошее: дисциплина «индекс, не полный текст» удержалась; журнал фиксировал
происхождение ревью в момент события; финальное chain-ревью поймало дрейф PRD.
Контекст координатора, по впечатлению пользователя, не страдал (прерывания и
дополнительные вопросы прогон пережил) — но это наблюдение, не замер:
числа-ориентиры июня (пик % окна, объём diff-чтений, число тест-прогонов) на
этом прогоне не сняты, сырьё в `~/.codex` ротируется. Пункт остаётся открытым.
Проблемы:
1. **Worker не может запускать субагентов в среде Codex.** У субагентов нет
`multi_agent_v1.spawn_agent`; `tool_search` не находит ни spawn, ни
`claude-team-review`. Проверено дважды: read-only диагностом и отдельным
диагностом с `agent_type=worker` (журнал, записи «Диагностика nested review
tools»). Ключевое допущение дизайна («ревьюера запускает сам worker внутри
`/goal`») в этой среде не работает. Координатор импровизировал: запускал
ревьюеров сам и возвращал worker-у индекс находок — сработало.
2. **Пинг-понг ревью без ограничителя.** Issue 07 прошёл пять кругов code
review; спорная находка (raw-сериализация) продержалась два круга, пока
координатор не изобрёл «узкий гейт на xhigh» по одной находке (усиленный
уровень понадобился на двух кругах из пяти плюс на финальном chain-ревью —
и по делу). Ограничителя и правил эскалации в скилле нет — открытые вопросы
rationale стали боевыми.
3. **Статус-контракт смешивает «работа заблокирована» и «шаг процесса
недоступен»**: worker по issue 11 вернул `BLOCKED` при готовой реализации —
заблокирован был только механизм ревью. Со стендовыми проверками так же:
docker недоступен в песочнице worker-а (07).
4. **Финальный handoff не написан** — шаг «Финал цепочки, п.2» тихо выпал,
бриф для кросс-прохода никто не получил.
5. **Закрытие issue делалось, но внутри feature-коммитов**: статусы 07 и 11
переведены в `done` в коммитах `3c38465` и `4f8f992` — процессная правка
смешана с рабочим diff. Прошлая цепочка (01–06) хуже: статусы остались
неверными («ready-for-human от глючившего координатора», триаж 2026-07-04).
Правила в скилле нет — каждый прогон решает по-своему.
6. **Журнал без меток времени** — длительность этапов и границы issue по
времени не восстановить. Метка времени была в дизайне live-log
(`2026-06-14-observability-design.md`) и потерялась, когда live-log «вырос
в журнал» (2026-07-03).
## Решения (пакет правок)
1. **Датированный факт среды вместо preflight-пробы.** В `SKILL.md` — короткая
врезка: «Среда Codex (проверено 2026-07-04): worker не может запускать
субагентов; ревьюеров запускает координатор». Не перепроверять каждый
прогон — только при сигнале обратного (например, `tool_search` нашёл spawn).
Гонять диагностику на каждой цепочке — жечь токены и время.
2. **Топология ревью: запуск у координатора, триаж у worker-а.**
- Координатор запускает reviewer-субагентов-**наблюдателей** и пересылает
worker-у индекс находок дословно, без своих интерпретаций (он не читает
код и судить не может). Наблюдатель — не read-only субагент: инструменты
полные (тесты, воспроизведение, поиск), ограничение «не менять репозиторий
и среду» держится промптом — как в `claude-team-review`.
- `claude-team-review` запускает только **владелец правок** — worker, в
средах, где worker может запускать субагентов. Координатору запускать
team-review нельзя: его лид чинит код сам, а это второй писатель в дереве
и слом границы «координатор кода не трогает». Под Codex механизм —
reviewer-субагент координатора с ревью-промптом; промпт адаптирован в
`references/reviewer-prompt.md` самого скилла (из `claude-team-review`) —
скилл самодостаточен, внешних файлов не требует.
- Триаж находок остаётся в worker-е: у него контекст кода и «зачем» из
контракта. Worker вправе аргументированно отклонить находку — через
контракт и тест, не голословно (приём из прогона).
- Бонус топологии: координатор видит зацикливание ревью (см. п.4).
- Цена: индексы ревью идут через контекст координатора, по кругу на каждый
rerun. Прямого замера этого трафика нет (июньские 2,6 КБ — замер
финальных отчётов worker-ов, не пер-раундового трафика ревью), но порядок
тот же — килобайты. Если на длинной цепочке начнёт пухнуть — готовый
фолбэк: файловый канал из `2026-06-14-observability-design.md` (ревьюер
пишет индекс в файл, координатору — путь и вердикт). Сейчас не вносим.
3. **Контракт ревьюеру** (новый, симметричен контракту worker-а): наблюдатель
с полными инструментами (ограничение «не менять репозиторий и среду» —
промптом), код читает сам и докладу worker-а не верит; возвращает
**индекс** — находка,
`файл:строка`, какой критерий нарушен, минимальный repro; вердикт одной
строкой (`APPROVED` / `CHANGES_REQUESTED`); запрет вставлять diff, полный
вывод тестов и нарратив рассуждений. Уровень мышления и модель задаёт
координатор при запуске (см. п.5).
4. **Политика кругов ревью.** Тождество находок между кругами судит не
координатор (по индексам оно не определяется — формулировки и `файл:строка`
между кругами плывут, что видно по прогону 07), а **worker в триаже**: если
ревьюер снова поднимает вопрос, который worker уже аргументированно
отклонял, worker помечает это в своём индексе флагом **«спор»** с отсылкой
к прежнему обоснованию. Координатор реагирует на флаг и на общий счётчик:
- **спор** → не общий rerun, а узкий гейт по спорному вопросу на усиленном
уровне (паттерн «xhigh narrow gate» из прогона);
- спор пережил и узкий усиленный гейт → **стоп, решение человека**;
- независимо от споров: больше **четырёх** кругов ревью на issue → стоп,
координатор выносит человеку вопрос «дробить issue или принимать риск»
(потолок взят по прогону 07 — пять кругов прошли без управления);
- rerun после правок по гейт-находкам назначает координатор автоматически —
это больше не concern worker-а (в прогоне дважды висело «rerun ещё не
выполнен»).
5. **Две ручки стоимости: модель по роли и уровень мышления.** Это разные оси,
не смешивать: «модель по роли» в скилле уже есть (дешёвая на task-lens,
сильная на финале), прогон же эскалировал **уровень рассуждений** (xhigh)
на той же модели. Вводим три относительных уровня без имён:
*экономный* (ступень вниз: task-lens ревью, диагностика, разбор логов),
*рабочий* (дефолт: worker, обычное code review), *усиленный* (ступень
вверх: эскалация по п.4, находки про межмодульные инварианты и форму
распределений, финальное chain-ревью — усиленный уровень на сильной
модели). Соответствие ролей конкретным моделям и уровням хоста — датированная
таблица `references/effort-levels.md`; логика скилла имён не знает. Дефолт —
рабочий уровень, вверх только по триггеру. Хост без управляемых уровней:
эскалация вырождается в «свежий субагент». Уровень фиксируется в записи
журнала о запуске ревью.
6. **Происхождение ревью пишет координатор в журнал** — в момент запуска и в
момент вердикта: режим, механизм, кто запускал, уровень, вердикт. Worker
больше не автор этой строки (факты «кто запускал» и «уровень» знает только
координатор); в индексе worker-а остаются саморевью и триаж (включая флаг
«спор»). Честная граница прежняя: журнал — самозапись координатора,
append-only след для внешней проверки; ложь в моменте ловит кросс-линия и
человек, не сам журнал.
7. **Метка времени в журнале.** Каждая запись начинается с `HH:MM` (дата — в
заголовке дня; время брать вызовом `date`, модель его не знает). Порог
записей прежний — точки записи из раздела «Журнал прогона»; мельче
(каждая команда, каждый прочитанный файл) не писать, чтобы метки не
превратили журнал в спам. Heartbeat worker-а в пакет **не входит**: журнал
пишет только координатор, файлового канала нет, а слать сигналы в контекст
координатора — противоречить его экономии. Если когда-нибудь вносим
файловый канал — heartbeat возвращается вместе с ним (дизайн готов в
observability-handoff).
8. **Статус-контракт: недоступность стендовой проверки ≠ `BLOCKED`.** Если
проверка (docker, стенд, сеть) недоступна в среде worker-а, он возвращает
`DONE_WITH_CONCERNS` с фактом («docker отсутствует: <вывод>») и **готовой
командой**, которую координатор прогоняет сам. `BLOCKED` — только про саму
работу. Оговорка по прогону: команда может не пройти и у координатора
(на коммит-гейте 11 `snap-confine` ломал dry-run в sandbox — перегоняли вне
sandbox); тогда координатор фиксирует в журнале, где и как проверка
прошла фактически. Случай «ревью недоступно worker-у» из контракта уходит
совсем — worker ревью больше не запускает (п.2).
9. **Дисциплина финала.**
- Обновить PRD/трекер **до** финального chain-ревью, чтобы оно проверяло
приведённое состояние (low finding прогона — предсказуемый класс).
- После коммит-гейта issue — `Status: done` в файле issue, **docs-коммитом
вместе с журналом**, не в feature-коммите. Это смена фактического
поведения (прогон 07/11 закрывал статусы внутри feature-коммитов):
файл issue — процессный, как и журнал, и на границе шага 6 «только файлы
worker-а» он файлом worker-а не считается.
- Финальный handoff обязателен для нетривиальной цепочки и является
**условием выхода из цикла**, а не пунктом-пожеланием; место и формат — по
конвенции репозитория (AGENTS.md / ADR), если она есть.
## Куда править
- `SKILL.md`:
- frontmatter `description` («с ревью через claude-team-review» — убрать);
- «Роли» — ревьюер: запускает координатор, наблюдатель, контракт по п.3;
- врезка про среду Codex (п.1);
- «Цикл» — шаги 4–6: приём индекса ревью, политика кругов и rerun (п.4),
происхождение в журнале (п.6), закрытие issue (п.9);
- «Журнал прогона» — метка времени (п.7), происхождение пишет координатор;
- «Контракт задания worker-у» — убрать запуск team-review worker-ом,
добавить триаж находок ревью + флаг «спор», статус-контракт по п.8;
- новый раздел «Контракт ревьюеру» (п.3);
- «Режимы ревью» — две ручки (модель по роли + уровень мышления), таблица
`references/effort-levels.md` (п.5);
- «Классификация находок» — триаж делает worker, не «team-review внутри
worker-а»;
- «Финал цепочки» — порядок: PRD/трекер → chain-ревью (усиленный уровень на
сильной модели) → handoff как условие выхода (п.9);
- чек-лист — привести к новым ролям (происхождение в журнале, уровни,
handoff обязателен, закрытие issue).
- `README.md`: строка потока и раздел «Что получается» («/goal + /tdd +
claude-team-review», «per-finding триаж делает claude-team-review внутри
worker-а»), «сильной моделью» в описании финала, раздел «Статус и что
дальше» — открытый вопрос «бюджет кругов ревью» закрывается п.4.
- `references/rationale.md`: датированная поправка 2026-07-04 — факт среды
Codex, боевое подтверждение вопросов про круги ревью, закрытие вопроса
«бюджет кругов» политикой п.4.
- `references/effort-levels.md`: новая датированная таблица уровней (п.5).
## Чего сознательно не делаем
- Файловый канал / `coordinator-runs/` — не вносим, зафиксирован как фолбэк
(п.2) и носитель heartbeat (п.7).
- Preflight-проба среды на каждый прогон — отвергнута (расход без пользы).
- Автоматизация кросс-линейного прохода — по-прежнему вне скилла.
- Замер чисел-ориентиров июня — не сделан в этом прогоне и не закрыт; снять
на следующей цепочке, пока сырьё в `~/.codex` не ротировалось.
## Suggested skills
- `conventional-commits` — коммиты в dotfiles.
- `coordinator-loop` — следующий боевой прогон (цепочка 12 или 08) как замер.