docs(skill): добавлен handoff по экономии контекста coordinator-loop
- Зачем: - сохранить выводы сессии проектирования у самого навыка, чтобы будущая сессия по доработке нашла их рядом с handoff про наблюдаемость. - Что: - добавлена расширенная версия handoff: диагностика двух «пожаров» по логам Codex, prior art (obra:superpowers), два принятых правила с адресами правок в SKILL.md, кандидаты-фиксы и открытые вопросы. - Проверка: - открыть handoffs/2026-06-14-coordinator-loop-context-economy.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
cf4056fe66
commit
27370b92ba
1 file changed
+266
+266
@@ -0,0 +1,266 @@
|
||||
# Handoff: экономия контекста в coordinator-loop
|
||||
|
||||
Дата: 2026-06-14 MSK
|
||||
Статус: рабочая договорённость по итогам сессии проектирования. В `SKILL.md` ещё не внесена.
|
||||
|
||||
## Зачем этот handoff
|
||||
|
||||
Сохранить выводы сессии, пока свежие. Разбирались, почему навык `coordinator-loop`
|
||||
(координатор + субагенты) при длинной цепочке задач переполняет контекст координатора и дорого
|
||||
стоит по токенам. Это снимок для продолжения в новой сессии, а не готовая спецификация: часть
|
||||
решений принята, часть осталась открытой — так и записано. Здесь сознательно «чуть больше
|
||||
информации, чем нужно»: для handoff недобор хуже перебора.
|
||||
|
||||
## Где что лежит (чтобы следующая сессия всё нашла)
|
||||
|
||||
- **Навык, источник-правды (git):** `~/dotfiles/agents/.agents/skills/coordinator-loop/`
|
||||
(`SKILL.md`, `README.md`, `references/rationale.md`, `handoffs/`). Этот handoff — здесь.
|
||||
- **Развёрнутая копия навыка** (её читает Claude Code): `~/.claude/skills/coordinator-loop/`.
|
||||
Правки вносить в dotfiles, потом разворачивать обычным способом.
|
||||
- **Побратим:** `handoffs/2026-06-14-observability-design.md` (рядом) — проектирование файлового
|
||||
канала `coordinator-runs/`. **Свести с этим handoff, см. раздел «Связь».**
|
||||
- **Прогон, на котором всё замеряли:** репозиторий
|
||||
`~/sources/clickstream-ch-kafka-superset-demo`, фичи `feature-data-generator` (8 задач) и
|
||||
`generator-model-time-startup-history` (6 задач). Вёлся как `/coordinator-loop` под Codex.
|
||||
- **Сырьё диагностики:** `~/.codex/logs_2.sqlite`, `~/.codex/sessions/2026/`,
|
||||
`~/.codex/goals_1.sqlite`. Внимание: файлы Codex **нумерованные и ротируются** — к будущей
|
||||
сессии этих именно логов может уже не быть. Поэтому ключевые числа вынесены в этот handoff
|
||||
ниже, чтобы не зависеть от сырья.
|
||||
- **Prior art:** obra:superpowers, навык `subagent-driven-development` —
|
||||
<https://github.com/obra/superpowers/tree/main/skills/subagent-driven-development>
|
||||
(`SKILL.md`, `implementer-prompt.md`, `spec-reviewer-prompt.md`,
|
||||
`code-quality-reviewer-prompt.md`).
|
||||
|
||||
## Что болит
|
||||
|
||||
У координатора дважды заканчивался контекст (по разу на каждый из двух прогонов), и работа съела
|
||||
почти весь 5-часовой лимит подписки (по логам — около 3 ч 45 мин на втором прогоне).
|
||||
|
||||
## Диагностика
|
||||
|
||||
Главный метод и главный урок: **логи — истина, самоотчёт модели — нет.** Codex на прямой вопрос
|
||||
искренне назвал виновником многословные отчёты субагентов, пересекающие границу. Логи это
|
||||
опровергли. Модель не видит свой токен-счёт и сочиняет правдоподобную, но неверную картину.
|
||||
Спасло то, что полезли в логи, а не поверили рассказу. Разбор логов делал **отдельный субагент
|
||||
на дешёвой модели** (Sonnet), чтобы не забивать контекст основного агента сырьём. Этот приём
|
||||
стоит повторять.
|
||||
|
||||
### Два разных пожара (мы их сначала склеивали)
|
||||
|
||||
**Пожар A — контекст координатора.** Горел НЕ от отчётов на границе субагент→координатор: они
|
||||
были компактны (в среднем 2,6 КБ, максимум 7,3 КБ, всего 112 КБ за 44 возврата; полных diff и
|
||||
логов тестов в них не было). Горел от того, что происходило **внутри сессии самого
|
||||
координатора**:
|
||||
|
||||
- координатор **сам читал полные diff'ы**, чтобы проверить находки, — 19 diff'ов крупнее 10 КБ,
|
||||
суммарно 413 КБ, независимо от сводок воркеров;
|
||||
- сессия ревьюера-апрувера раздулась до 947 КБ за 21 ход, и **42 из 44 ожиданий `wait_agent`
|
||||
завершились таймаутом** (опрос по кругу при том, что push-уведомления приходили).
|
||||
|
||||
Пик контекста координатора: 199 307 токенов из окна 258 400 (77 %), одна компактизация.
|
||||
|
||||
**Пожар B — 5-часовой лимит** (отдельная от контекст-окна вещь — это суммарный расход токенов):
|
||||
|
||||
- **103 прогона полного тест-сета** (каждый ~40 КБ вывода, до 16 877 токенов за один) — главный
|
||||
потребитель;
|
||||
- `/goal`-петли воркеров по ~400K токенов на задачу (задачи 05 и 06; 30 и 23 минуты);
|
||||
- 13 Docker-сборок и накладные расходы опроса.
|
||||
|
||||
### Процессные счётчики (прогон issues 02–06)
|
||||
|
||||
| Метрика | Значение |
|
||||
|---|---|
|
||||
| Обработано issues | 5 (02–06) |
|
||||
| Воркеров запущено | 5 + 2 `/goal`-петли |
|
||||
| Вызовов независимого ревьюера | 7 (4 explorer + 3 default) |
|
||||
| Кругов ревью на задачу (среднее) | 1,4 |
|
||||
| Кругов правок после ревью | ~2 на задачу |
|
||||
| Прогонов полного тест-сета | 103 |
|
||||
| Docker-сборок | 13 |
|
||||
| Всего exec_command | 996 |
|
||||
| Общая длительность прогона | ~3 ч 45 мин |
|
||||
|
||||
### Главные потребители (по убыванию)
|
||||
|
||||
1. Полный вывод тестов внутри воркеров — 103 вывода по ~40 КБ.
|
||||
2. Повторное чтение diff'ов координатором — 19 outputs >10 КБ, 413 КБ.
|
||||
3. Опросный цикл ревьюера-апрувера — 21 ход, сессия 947 КБ.
|
||||
4. `/goal`-петли (issues 05 и 06) — ~400K токенов каждая.
|
||||
5. Отчёты субагентов на границе — низкое влияние (среднее 2,6 КБ).
|
||||
|
||||
### Гипотезы и вердикты
|
||||
|
||||
| # | Гипотеза | Вердикт | Доказательство |
|
||||
|---|---|---|---|
|
||||
| H1 | контекст рос из-за отчётов субагентов | **опровергнута** | средний отчёт 2,6 КБ, max 7,3 КБ; diff и логи в них не входили |
|
||||
| H2 | координатор перечитывал то, что воркер уже сообщил | **подтверждена** | 19 полных diff в сессии координатора, 413 КБ |
|
||||
| H3 | компактизация теряла важное и его восстанавливали | частично | после компактизации координатор перечитывал статусы issue и git-историю |
|
||||
| H4 | полный режим ревью применялся избыточно | частично, переосмыслена | дело не в самом ревью, а в polling-overhead: 42/44 таймаута, сессия 947 КБ |
|
||||
| H5 | лимит съели `/goal` и тест-прогоны | частично | 103 полных ретеста — главное; `/goal` был только на 05–06 |
|
||||
|
||||
### Что Codex дал верно, несмотря на промах с локацией
|
||||
|
||||
Его интроспекция угадала **форму** балласта (материал, который должен был сжиматься после своего
|
||||
момента) и продиктовала точные компактные форматы. Он перечислил, что таскал зря: полные выводы
|
||||
тестов; полные diff'ы крупных файлов; полные отчёты ревьюеров (вместо классифицированных
|
||||
находок); полные отчёты воркеров после приёмки issue; тексты уже закрытых issue; собственные
|
||||
пользовательские апдейты («запускаю», «жду воркера»); полные build/compose/ClickHouse-логи;
|
||||
длинные фрагменты спек после первичного чтения.
|
||||
|
||||
Ключевой ответ про классификацию находок: отчёта субагента **хватало для маршрутизации**
|
||||
(blocker / риск / docs-мелочь / ложная тревога), но для финального решения «чинить или нет» по
|
||||
**межмодульному инварианту** он **всё равно лез в код** — отчёт был индексом и аргументацией, а
|
||||
не заменой чтения. Примеры мест, куда он шёл: `service.py:_is_startup_history_state`, порядок
|
||||
записи manifest/state, путь восстановления state→manifest→state→live load→startup-marker→
|
||||
fallback, SQL-воронка для доказательства. Вывод: лучший отчёт — это **индекс** (находка,
|
||||
`файл:строка`, минимальный путь воспроизведения, какой критерий нарушен, что проверить в коде),
|
||||
а не нарратив.
|
||||
|
||||
Про `wait_agent`: таймауты стояли 600000 мс (10 мин) для воркера/ревьюера, 900000 мс (15 мин)
|
||||
для долгих стендовых задач, 180000 мс (3 мин) после запроса промежуточного статуса.
|
||||
Push-уведомления (`<subagent_notification>`) приходили, но Codex им не доверял и ждал заново —
|
||||
отсюда лишний опрос. Сам прописал лечение: на уведомление **сразу обрабатывать результат**, а не
|
||||
запускать `wait_agent` повторно; после `spawn_agent` не делать длинный `wait_agent`, если есть
|
||||
локальная работа; один разумный статус-таймер вместо polling-цикла.
|
||||
|
||||
## Prior art: obra:superpowers `subagent-driven-development`
|
||||
|
||||
Чужой навык глубоко проработан (в том числе по экономии токенов и выбору минимально достаточной
|
||||
модели) и стоит на той же идее: оркестратор не делает работу сам, держит контекст чистым,
|
||||
субагенты — «свежий контекст». По части ядра мы переизобретали его.
|
||||
|
||||
Как у них устроено: на задачу один эфемерный **implementer** → два последовательных ревьюера
|
||||
(spec-review → quality-review) → фиксы → следующая задача. Задачи строго последовательны.
|
||||
Implementer возвращает компактный статус `DONE / DONE_WITH_CONCERNS / BLOCKED / NEEDS_CONTEXT` +
|
||||
изменённые файлы + итог тестов (без полного вывода). Spec-reviewer читает реальный код и не
|
||||
доверяет докладу implementer'а. Модель выбирается по роли (дешёвая → стандартная → сильная).
|
||||
|
||||
**Берём оттуда:**
|
||||
|
||||
- **Ревьюер читает код сам и не верит докладу** — жёсткое правило, убивает Пожар A по построению
|
||||
(координатор перестаёт быть верификатором).
|
||||
- **Модель по роли.** Поправка под нас: наш implementer «толстый» (`/goal`), ему нужна сильная
|
||||
модель; дешёвая выигрывает на субагенте-верификаторе простых находок, docs-проверках и
|
||||
диагностике (разбор логов мы и сделали на Sonnet).
|
||||
- **Статус-контракт воркера** `DONE / DONE_WITH_CONCERNS / BLOCKED / NEEDS_CONTEXT` — протокол
|
||||
эскалации, которого у нас нет: воркер сам стопорится на архитектурной неясности.
|
||||
- **Качественная стадия ревью** (хорош ли код, межмодульные инварианты).
|
||||
|
||||
**Не берём (сознательно другой выбор):**
|
||||
|
||||
- У superpowers **толстый план** (~2000 строк, почти реализация) + тонкий механический
|
||||
implementer. У нас **тонкий issue** (acceptance criteria) + толстый `/goal`, который сам
|
||||
додумывает реализацию и самопроверяется. Для учебного репозитория наш путь лучше: issue
|
||||
читаемы менти, реальное решение живёт в петле, нет огромного плана.
|
||||
- Их **спек-стадия ревью** у нас по большей части избыточна: «выполнили ли спеку» уже проверяет
|
||||
петля `/goal`. Берём только качественную линзу.
|
||||
|
||||
Вывод: `coordinator-loop` остаётся отдельным навыком (своя идентичность — цепочка issue из
|
||||
`/to-issues`, гейт-классификация находок, владение коммитом). Заимствуем механику делегирования,
|
||||
а не план-центричную философию.
|
||||
|
||||
## Решения сессии — с адресами правок в `SKILL.md`
|
||||
|
||||
**Принято (дёшево, метрически обосновано):**
|
||||
|
||||
1. **Координатор не читает diff ради проверки находки.** Чтение кода уходит ревьюеру-субагенту:
|
||||
он читает код сам и возвращает только вердикт. Чинит Пожар A (413 КБ). Куда править:
|
||||
- «Цикл на одну задачу», **шаг 8 «Свой sanity-check»** — сейчас список включает чтение
|
||||
(дефолты, compose/конфиги, документы, acceptance criteria, git status, тесты). Сузить:
|
||||
sanity-check проверяет связи, но **не читает diff/код ради верификации находки** — это
|
||||
работа ревьюера.
|
||||
- «Роли», пункт **Координатор** («делает sanity-check») — уточнить так же.
|
||||
- «Роли», пункт **Независимый ревьюер** — добавить жёсткое правило superpowers: ревьюер
|
||||
читает код сам и **не верит докладу**; именно он несёт верификацию.
|
||||
- «Когда звать независимого ревьюера» — это и есть порог, на котором верификация (с чтением
|
||||
кода) уходит в субагента; для межмодульных инвариантов — обязательно.
|
||||
|
||||
2. **Доверять push, не крутить `wait_agent` по кругу.** Пришло `<subagent_notification>` — сразу
|
||||
обрабатывать; один разумный статус-таймер вместо polling-цикла; после `spawn_agent` не делать
|
||||
длинный `wait_agent`, если есть локальная работа. Возможно, самый дешёвый одиночный выигрыш
|
||||
(сток 947 КБ почти случайный, не дизайн). Куда править — **открытый вопрос** (см. ниже):
|
||||
`wait_agent` — рантайм Codex, а `SKILL.md` host-agnostic. Связано со «Цикл», **шаг 4
|
||||
«Дождись отчёта»**.
|
||||
|
||||
**Намеренная цена — НЕ трогать:**
|
||||
|
||||
- `/goal`-петля (~400K токенов/задача) — сознательный обмен на качество решения;
|
||||
- независимое межмодульное ревью на пороге риска;
|
||||
- декомпозиция «тонкий issue + толстый `/goal`».
|
||||
|
||||
**Кандидаты-фиксы (не приняты, проверить на прогоне) — с адресами:**
|
||||
|
||||
- **Точечные тесты в петле, полный тест-сет — только на гейте.** Главный потребитель токенов
|
||||
(103 ретеста). Риск пропустить межмодульный регресс в середине петли ловит гейт + межмодульный
|
||||
ревьюер. Куда: «Контракт задания worker-у» (методика тестов) и шаг 12 «Коммит» (полный сет
|
||||
перед коммитом).
|
||||
- **Отчёты в формате индекса, а не нарратива.** Куда: «Контракт задания worker-у» →
|
||||
«формат финального отчёта»: находка/изменение, `файл:строка`, минимальный repro, какой
|
||||
критерий, что проверить; запрет на вставку diff и полных логов.
|
||||
- **Статус-контракт воркера** `DONE / DONE_WITH_CONCERNS / BLOCKED / NEEDS_CONTEXT`. Куда:
|
||||
«Контракт задания worker-у».
|
||||
- **Демоушн закрытых issue** в компактную durable-форму (`summary`), чтобы компактизация её не
|
||||
уничтожала. Куда: новый короткий раздел + связь с observability-handoff (`summary.md`).
|
||||
- **Файловый канал в общем дереве** для обмена находками (оркестрация по ссылке, а не payload
|
||||
через контекст). Куда: см. observability-handoff (`coordinator-runs/`).
|
||||
- **Модель по роли.** Куда: «Облегчённый и полный режим» / «Контракт задания worker-у».
|
||||
- **Только качественная стадия ревью** (спек несёт `/goal`). Куда: «Роли» (ревьюер) + «Когда
|
||||
звать независимого ревьюера».
|
||||
|
||||
## Связь с handoff про наблюдаемость
|
||||
|
||||
Побратим `2026-06-14-observability-design.md` (рядом) уже спроектировал файловый канал
|
||||
`coordinator-runs/` (live-логи + `summary.md`, чтение по требованию, координатор не ведёт лог
|
||||
сам). Это **тот же** файловый канал, что нужен кандидатам-фиксам «демоушн» и «файловый канал».
|
||||
**Свести в один дизайн, не строить две файловые системы.** Оба не реализованы — слить легко.
|
||||
|
||||
## Открытые вопросы (с моей рекомендацией, но не закрыты)
|
||||
|
||||
1. **Объём первого захода.** A — полная переделка сразу; B — внести только два дёшевых правила,
|
||||
остальное пометить «проверить на следующем прогоне». Рекомендация: **B** (держит навык от
|
||||
разрастания).
|
||||
2. **Кто верифицирует находку** — автор-воркер со своим знанием кода и проверяемым обоснованием,
|
||||
или свежий ревьюер? Склонялись к автору на знании + независимый на пороге риска. Не закрыто.
|
||||
3. **Где живёт правило 2 (push/`wait_agent`).** Это рантайм Codex, а `SKILL.md` host-agnostic.
|
||||
Куда: короткий раздел «Синхронизация с субагентами» в `SKILL.md` с пометкой «Codex-specific»,
|
||||
либо `references/rationale.md`, либо привычка оператора. Не решено.
|
||||
4. **Слить ли два handoff** (этот и про наблюдаемость) в один дизайн до правки `SKILL.md`?
|
||||
Рекомендация: да.
|
||||
5. **Кросс-хост.** Файловый канал отчасти оправдан тем, что host-agnostic (Codex и Claude Code).
|
||||
Если на деле только Codex — обоснование слабее. Уточнить требование.
|
||||
6. **Носитель для проверки.** Фича почти закрыта (осталась issue 06), новой цепочки под рукой
|
||||
нет. На чём гонять проверочный прогон — пока неясно; числа-ориентиры ниже остаются baseline
|
||||
на будущую фичу.
|
||||
|
||||
## Числа-ориентиры для следующего прогона
|
||||
|
||||
Чтобы измерить, помогли ли фиксы, а не поверить на слово:
|
||||
|
||||
- пик контекста координатора: было 77 % окна (199K/258K) — должно заметно упасть;
|
||||
- собственные diff-чтения координатора: было 413 КБ — должно стремиться к нулю;
|
||||
- сессия ожиданий/опроса: было 947 КБ при 42/44 таймаутах — push обрабатывается, цикла нет;
|
||||
- прогоны полного тест-сета: было 103 — точечные в петле, полный только на гейте.
|
||||
|
||||
## Что ещё не сделано
|
||||
|
||||
- Решения не внесены в `SKILL.md`.
|
||||
- Кандидаты-фиксы не приняты и не проверены на реальном прогоне.
|
||||
- Два handoff не сведены.
|
||||
- Не решён объём первого захода (вопрос 1).
|
||||
- Не решено, где живёт правило 2 (вопрос 3).
|
||||
|
||||
## Рекомендуемые следующие шаги
|
||||
|
||||
1. Решить объём первого захода (A vs B).
|
||||
2. Свести этот handoff с handoff про наблюдаемость в один дизайн.
|
||||
3. Внести минимум в `SKILL.md` (два принятых правила) по адресам выше, сверяясь с superpowers как
|
||||
prior art.
|
||||
4. На ближайшей новой фиче замерить числа-ориентиры; по факту резать или добавлять.
|
||||
5. Опционально — лёгкая дивергенция/конвергенция через `brainstorm-with-docs`, если решение
|
||||
захочется поискать шире. Возможно, и не понадобится: два дешёвых фикса метрически очевидны.
|
||||
|
||||
## Suggested skills
|
||||
|
||||
- `write-a-skill` — при переносе правил в `SKILL.md`, чтобы не раздувать основной файл.
|
||||
- `brainstorm-with-docs` — если делать полноценный заход с дивергенцией/конвергенцией.
|
||||
- `conventional-commits` — для коммитов изменений в навыке.
|
||||
Reference in new issue
Block a user