refactor(skill): coordinator-loop вокруг «индекс, не полный текст»

Переписан SKILL.md (194→159): user-invoked, ведущее правило «работай по
индексу», per-finding триаж делегирован claude-team-review, режимы ревью
по риску (два лена разными субагентами на риске), коммит-гейт берёт только
сводку тестов, финал = ревью на соответствие замыслу + handoff под ручную
кросс-линию. README, rationale и июньский context-economy handoff подровнены;
добавлен handoff по сессии. Прошёл /claude-team-review — 2 раунда, APPROVED.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dmitry DementievandClaude Opus 4.8 committed 2026-07-02 18:38:53 +03:00
1 parent 9ceeb0ca4e
commit b0998780d3
5 files changed
+194 -159

No files matched your search

+117 -152
View File
@@ -1,194 +1,159 @@
---
name: coordinator-loop
disable-model-invocation: true
description: >-
Координаторский цикл для цепочки зависимых задач (issues из /to-issues): на каждую
задачу запускается worker-субагент с одной конкретной целью, затем саморевью,
классификация находок, независимый ревьюер на рискованных местах и коммит силами
координатора. Узкоспециализированный навык — НЕ включай автоматически. Применять
только по явному запросу: команда /coordinator-loop или прямая просьба вести работу
координаторским циклом worker -> ревью -> коммит.
Координаторский цикл по цепочке готовых issue: на каждый — worker-субагент по TDD
с ревью через claude-team-review, коммит делает координатор. Контекст координатора
держится чистым — в него входит только индекс находок, не diff. Узкий навык, только
по явному вызову /coordinator-loop.
---
# Координационный цикл субагентов
Ты — **координатор**. Ты не пишешь основную реализацию сам. Ты ведёшь цепочку
зависимых задач: выдаёшь задачу исполнителю, фильтруешь находки, держишь границы
и единственный делаешь коммиты.
Ты — **координатор**. Реализацию не пишешь и код не читаешь. Ты ведёшь цепочку
зависимых issue: даёшь worker-у задачу с контекстом, принимаешь от него **индекс**,
классифицируешь на уровне цепочки и единственный делаешь коммиты.
Ядро навыка — не «запусти побольше агентов», а **цикл с классификацией находок и
контролем границ**. Главная формула:
```text
worker реализует -> worker сам себя ревьюит -> координатор фильтрует ->
worker чинит выбранное -> независимый ревьюер проверяет риск -> координатор фильтрует ->
при большом исправлении повторить ревью -> координатор коммитит
```
## С чего начать
1. Возьми из очереди один issue (нарезаю их через `/to-issues`) и прочитай его
зависимости.
2. Проверь, что рабочее дерево чистое.
3. Сформулируй контракт worker-у: цель = issue, границы, методика.
4. Запусти одного worker-а. Дальше — по циклу ниже.
**Ведущее правило — работай по индексу, а не по полному тексту.** Всё, что попадает в
твой контекст, — это **индекс**: находка, `файл:строка`, какой критерий нарушен,
минимальный путь воспроизведения. Полного diff, вывода тестов и нарратива ревью в твоём
контексте быть не должно — их читают субагенты у себя, а тебе возвращают индекс.
Верификацию находок делает ревьюер, не ты. (Исключение — состав diff на коммит-гейте:
`git diff --stat`/`--name-only`, какие файлы и в границах ли; это не полный текст, см.
шаг 6.) Проверяй себя каждый цикл: *в мой контекст попал полный текст вместо индекса?
Если да — это баг процесса.* Так контекст не пухнет, не компактится и не начинает
косячить — это главная болезнь, которую навык лечит.
## Когда применять
Подходит для **последовательных инженерных срезов** с тестами, документами и
явными acceptance criteria, когда соседние задачи трогают близкий код и их нельзя
безопасно параллелить.
Не подходит (или нужен облегчённый режим): независимые задачи, которые можно
параллелить; маленькие однофайловые правки; задачи без тестовой базы; задачи, где
субагентам нельзя писать в общее рабочее дерево.
Последовательные инженерные срезы с тестами и acceptance criteria, где соседние задачи
трогают близкий код и их нельзя безопасно параллелить. Не подходит: независимые задачи
(параллель), однофайловые правки, задачи без тестовой базы. Если цепочка не подходит —
скажи об этом пользователю, а не тяни цикл силой.
## Роли
- **Координатор** — ты. Управляешь порядком, проверяешь границы, классифицируешь
находки, делаешь sanity-check и коммиты.
- **Worker** — субагент-исполнитель с одной конкретной целью (один issue). Работает
в общем дереве, меняет файлы, гоняет тесты, **но не коммитит**.
- **Саморевью worker-а** — отдельная фаза: тот же worker временно становится
проверяющим и **сначала только выдаёт находки, не правя их**.
- **Независимый ревьюер** — отдельный субагент со **свежим контекстом**. Он не
редактирует файлы, но проверяет находки делом: читает diff, issue, спеки и тесты,
**сам прогоняет тесты и линтеры**, сверяется с документацией. Ограничивай ему
право *записи*, а не право *проверять*: ревьюер, которому оставили только чтение,
скатывается в догадки.
- **Находка** — гипотеза о проблеме, а не автоматическое требование правки.
Решение принимаешь ты.
Все агенты работают с **одним рабочим деревом**. Поэтому каждый цикл начинай и
заканчивай явной проверкой `git status --short` и отделяй рабочие изменения задачи
от процессных заметок и чужих правок.
- **Координатор** — ты. Порядок issue, богатый контракт, chain-level классификация по
индексу, коммит-гейт, финальный handoff. **Код ради верификации не читаешь** — это
ревьюер; на коммит-гейте смотришь лишь **состав** diff (не текст, см. шаг 6).
- **Worker** — субагент с одной целью (один issue). Гоняет `/goal` (петля
план→код→тест→проверка готовности внешним ревьюером), меняет файлы, **не коммитит и не откатывает чужое**.
Возвращает индекс + статус.
- **Ревьюер** — свежий субагент, которого запускает **сам worker** внутри `/goal` через
`claude-team-review`. Читает код сам, докладу не верит. Триаж находок встроен в
team-review (лид чинит нужное, отклоняет противоречащее требованиям). Нарративы ревью
живут в контексте worker-а, до тебя доходит только его финальный индекс.
## Цикл на одну задачу
1. **Прочитай issue и его зависимости.** На них строятся цель, границы и порядок.
Если предыдущие задачи цепочки не закрыты — не начинай.
2. **Чистое дерево.** Проверь `git status --short` до запуска worker-а. Если есть
чужие правки — сразу остановись и спроси пользователя, что с ними делать. Если
есть только твои процессные правки — после проверки diff отдели их отдельным
docs-коммитом.
3. **Запусти одного worker-а на этот issue.** Дай задание как контракт (см. ниже).
4. **Дождись отчёта.** Если работа долго молчит (особенно статистика и долгие
тесты) — запроси промежуточный статус, не дожидаясь конца вслепую.
5. **Саморевью без правок.** Попроси того же worker-а отревьюить свою работу и
выдать находки, ничего пока не исправляя.
6. **Классифицируй находки** (см. ниже).
7. **Верни worker-у только одобренное** для исправления.
8. **Свой sanity-check.** Не реимплемент, а проверка связей: дефолты, compose и
конфиги, документы, acceptance criteria, `git status`, тесты.
9. **На рискованном месте — независимый ревьюер** в свежем субагенте (см.
«Когда звать ревьюера»).
10. **Классифицируй находки ревьюера.**
11. **Большое исправление — повторный круг ревью.** Если правка изменила дизайн
или формат данных, ревьюй её результат заново.
12. **Коммит делаешь ты.** Это последняя точка контроля состава diff.
13. **Закрой субагентов.** Следующая задача стартует в новом worker-е.
1. **Чистое дерево.** `git status --short` до старта. Чужие правки — стоп, спроси
пользователя. Свои процессные — отдели docs-коммитом.
2. **Прочитай issue и зависимости.** Предыдущие в цепочке не закрыты — не начинай.
3. **Контракт worker-у** (см. ниже) и запусти **одного** worker-а.
4. **Дождись индекса.** Долго молчит — запроси промежуточный статус, не жди вслепую.
Пришло push-уведомление — сразу обрабатывай, не крути опрос по кругу.
5. **Классифицируй по индексу — только chain-level** (см. «Классификация»).
6. **Коммит-гейт.** Прогони полный тест-сет, но в контекст возьми **только сводку**: код
возврата и имена упавших тестов (`pytest -q`/хвост вывода), не полный вывод. Так же
проверь **состав** diff (`git diff --stat`/`--name-only`: какие файлы, в границах ли —
не полный текст) и коммить. Упали тесты — верни их worker-у по именам, трейсбеки в свой
контекст не тащи. Это последняя точка контроля состава изменений.
7. **Закрой субагентов.** Следующий issue стартует в новом worker-е.
## Контракт задания worker-у
Worker — это субагент с одной конкретной целью, который гоняет её как
самопроверяющуюся петлю (план → делает → тест → ревью, пока цель не достигнута; в
Codex это встроенная команда `/goal`, по сути «петля Ральфа»). Цель берётся из
одного issue (issues удобно нарезать через `/to-issues`).
- **одна цель из issue** и критерий «готово» (acceptance criteria);
- **зачем**: ссылки на PRD/спеку/смежное. Без общего контекста worker триажит находки
вслепую; с ним — способен судить сам (это и делает верификацию на воркере надёжной);
- **границы** — что трогать нельзя;
- методика **`/tdd`** (короткие срезы тест→код); точечные тесты в петле;
- **саморевью свежим взглядом** перед сдачей (отдельно от петли `/goal`) — worker
критически перечитывает свою работу и правит очевидное. Базовый минимум даже без
team-review: ошибаются все;
- **после реализации — `claude-team-review` по коду** (число проверок — по режиму ниже);
- **формат отчёта — индекс**: находка/изменение, `файл:строка`, минимальный repro, какой
критерий; запрет вставлять diff и полный вывод тестов;
- **статус-контракт** `DONE / DONE_WITH_CONCERNS / BLOCKED / NEEDS_CONTEXT` — worker сам
стопорится на архитектурной неясности, а не додумывает молча;
- **запрет коммита** и **запрет отката чужого**.
В задании worker-у должны быть:
Цель worker-а — **одна** (один issue = одна петля). Не запускай `/goal` на всю цепочку
сразу: от координатора нужна остановка на контрольных точках, а не «закрыть всё любой ценой».
- одна конкретная цель из issue и критерий «готово» (acceptance criteria);
- границы задачи (что трогать нельзя);
- методика `/tdd` (короткие срезы «тест → код»);
- **запрет на коммит**;
- **запрет на откат чужих изменений**;
- формат финального отчёта: файлы, тесты, проверки, выполненные acceptance
criteria, риски и `git status --short`.
## Режимы ревью — рычаг стоимости
Цель worker-а — **одна** (один issue = одна петля). Сам не запускай `/goal` на всю
цепочку сразу: от координатора нужна управленческая осторожность и остановки на
контрольных точках, а не «закрыть всё одной петлёй любой ценой».
Две проверки **разными субагентами** — по задаче и по коду — ловят непересекающиеся
множества находок, но это расход токенов (по бюджету, не по контексту координатора).
Плати по риску, не на каждой мелочи:
- **тривиальный issue** — team-review не зови; ревью только петлёй `/goal` (её внешний
ревьюер готовности) **плюс отдельное перечитывание своей работы свежим взглядом**
worker-ом — это не встроенный шаг `/goal` (ошибаются все);
- **обычный (дефолт)** — один прогон `claude-team-review` **по коду**; соответствие
issue/спеке держит петля `/goal`;
- **рискованный / гейт** — два прогона разными субагентами: **по задаче** (сделал ли то,
что в issue/спеке) + **по коду** (тонкие баги, межмодульное). Проверку по задаче можно
на дешёвой модели — модель по роли.
Порог риска: state и сериализация, формат данных, интеграция сервиса, статистические
модели, честность документации, межмодульные инварианты.
## Классификация находок
Ревьюер и саморевью — не источник истины. Каждую находку проверь и отнеси к одной
из категорий:
Per-finding триаж («реально / ложно / чинить») уже делает `claude-team-review` внутри
worker-а — **не переписывай его**. Ты решаешь только **на уровне цепочки**, читая индекс:
- **чинить до коммита** — реальный дефект, нарушение acceptance criteria или
слабое доказательство ключевого поведения;
- **записать как риск** — важно помнить, но текущий коммит не блокирует;
- **ложная тревога** — неверно понят код, тест или границы задачи;
- **вне скоупа** — может пригодиться позже, но не относится к этому issue.
- **записать риском** — важно помнить, текущий коммит не блокирует (реестр рисков цепочки);
- **вне скоупа** — пригодится позже, отдать в следующий issue.
Без этой фильтрации ревьюер легко превращается в источник расползания задачи.
## Финал цепочки
## Когда звать независимого ревьюера
1. **Ревью на соответствие замыслу** (рекомендуется для любой нетривиальной цепочки).
В самом конце — один прогон субагента-ревьюера **сильной моделью** (не дешёвой):
читает **всю** реализацию против **исходной спеки/PRD** и проверяет, не разъехалась ли
поэтапная реализация с замыслом. Возвращает индекс. Один прогон добавляет к общей
стоимости немного, а ловит дрейф, который per-issue срезы не видят — ни одно ревью
отдельной задачи не сверяло целое с целым замыслом. Это Codex (одна линия): берёт
**охват** (целое против замысла), но не кросс-линию — глубокие сквозные слепые пятна
линии остаются на п.2.
2. **Handoff, а не ревью.** Последний акт координатора — записка (`.scratch/<feature>/…`
или через `/handoff`), которая **готовит опциональный ручной кросс-линия ревью**:
- индекс построенного по issue (`файл:строка` ключевых стыков);
- что покрыто ревью — **одна линия** (Codex ревьюил Codex);
- **открытый риск**: межмодульные инварианты и форма распределения ревью другой
родословной **не покрыты** → рекомендуется ручной проход Клодом.
Не после каждой мелкой правки — это дорого и раздувает задачу. Зови на
рискованных точках:
Даже если проход не запустят — дыра остаётся **видимым задокументированным риском**, а
не тихим слепым пятном. Запустят — Клод получит нацеленный бриф, а не холодное перечитывание.
- state и сериализация;
- интеграция сервиса;
- изменения формата данных;
- статистические модели;
- документация (честность README и операционных документов);
- после большого исправления — повторный круг.
## Родословная — почему кросс-линия остаётся риском
Ревьюер проверяет не только падения, но и **силу доказательства**: достаточно ли
тест доказывает нужное поведение, а не просто «что-то прошло».
## Свежий контекст вместо другой модели
Дисциплинированный цикл (worker + саморевью + ревьюер той же линии) хорошо ловит
**точечные** дефекты. Но до внешнего взгляда доживают два семейства, которые одна
линия систематически не видит:
- **межмодульные инварианты** — свойство тянется через несколько модулей или путей,
и ни один тест не сводит их вместе;
- **форма распределения** — среднее и пороги на цели, но форма уехала.
В идеале их закрывает ревьюер **другой родословной** (другая модель). Если её нет —
бери ту же модель в свежем субагенте, но помни: это **более слабый заменитель**
(свежий контекст снимает память о реализации, но не общую слепоту линии). Поэтому
прямо ставь ревьюеру задачу искать именно межмодульное и распределительное. А если
на gate — контрольной точке цепочки (слияние, релиз, переход к следующему этапу) —
корректность как раз такая, **зафиксируй как риск**, что ревью другой родословной
ещё причитается.
## Облегчённый и полный режим
Навык параметризуемый — не запускай полную схему всегда.
- **Облегчённый режим** (простой, низкорисковый issue): worker + саморевью + твой
sanity-check. Без отдельного ревьюера.
- **Полный режим** (риск из списка выше или контрольная точка): добавляешь
независимого ревьюера и, при большом исправлении, повторный круг.
Если что-то сознательно не проверял (например, использовал мок вместо реального
стека) — **явно это зафиксируй**, не выдавай за проверенное.
Внутри Кодекса ревьюер — тоже Codex (одна линия), а свежий контекст не снимает общую
слепоту линии к сквозным дефектам — поэтому кросс-линия (Claude по написанному Codex)
остаётся ручным опциональным проходом **вне** скилла, не автоматизируется. Координатор её
не выполняет, а фиксирует непокрытый риск в handoff (финал, шаг 2). Эмпирика —
[references/rationale.md](references/rationale.md).
## Чек-лист координатора
- [ ] Дерево чистое перед стартом; чужие правки обнаружены сразу и согласованы с
пользователем, процессные правки отделены.
- [ ] Worker получил один issue и контракт (цель, границы, TDD, запрет коммита и
отката чужого, формат отчёта).
- [ ] Саморевью сделано без правок; находки классифицированы.
- [ ] Свой sanity-check связей пройден.
- [ ] На риске запущен независимый ревьюер со свежим контекстом и нацеленным
заданием; большое исправление прошло повторный круг.
- [ ] Незакрытое ревью другой родословной зафиксировано как риск.
- [ ] Коммит сделан координатором, diff узкий и в границах задачи.
- [ ] Дерево чистое перед стартом; чужие правки согласованы, процессные отделены.
- [ ] Worker получил один issue + **зачем** (PRD/спека), границы, `/tdd`, режим ревью,
индекс-формат, статус-контракт, запрет коммита и отката; саморевью свежим взглядом сделан.
- [ ] В мой контекст вошёл **только индекс** — ни diff, ни логов, ни нарратива ревью.
- [ ] Chain-level классификация сделана по индексу (риск / вне скоупа).
- [ ] Коммит сделан координатором, diff узкий и в границах; полный тест-сет на гейте — в контекст только сводка (pass/fail + упавшие), не вывод.
- [ ] В конце цепочки — ревью на соответствие замыслу (сильная модель); дрейф от спеки проверен.
- [ ] Финальный handoff готовит кросс-линия ревью; непокрытая родословная — открытый риск.
- [ ] Субагенты закрыты; `git status` чист на выходе.
## Подробнее
Эмпирика, на которой стоят эти правила (что именно ловил и пропускал цикл),
вынесена в [references/rationale.md](references/rationale.md).
- [references/rationale.md](references/rationale.md) — эмпирика: какой шаг какой класс
дефектов ловит, центральная находка про родословную, открытые вопросы.
- `handoffs/` — экономия контекста (два пожара: контекст vs лимит), наблюдаемость и
непроверенные кандидаты-фиксы (файловый канал, демоушн закрытых issue, точечные тесты).
## Источники упомянутых скиллов
- `/to-issues`, `/tdd` — из набора инженерных скиллов Matt Pocock:
<https://github.com/mattpocock/skills>.
- `/goal` — встроенная команда Codex CLI.
- `/coordinator-loop` — этот навык; вырос из внутреннего эксперимента с
координатором субагентов.
- `/to-issues`, `/tdd`, `/claude-team-review` — инженерные скиллы (набор Matt Pocock и внутренние).
- `/goal` — встроенная петля Codex (план→код→тест→проверка готовности внешним ревьюером).