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:
1 parent
2ed3fd81ea
commit
2d9fc7eadb
6 files changed
+542
-77
No files matched your search
+210
@@ -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) как замер.
|
||||
Reference in new issue
Block a user