From 27370b92ba6645b9f4d86e09137f57f7f3d1a8f7 Mon Sep 17 00:00:00 2001 From: Dmitry Dementev Date: Sun, 14 Jun 2026 21:39:40 +0300 Subject: [PATCH] =?UTF-8?q?docs(skill):=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=20handoff=20=D0=BF=D0=BE=20=D1=8D=D0=BA?= =?UTF-8?q?=D0=BE=D0=BD=D0=BE=D0=BC=D0=B8=D0=B8=20=D0=BA=D0=BE=D0=BD=D1=82?= =?UTF-8?q?=D0=B5=D0=BA=D1=81=D1=82=D0=B0=20coordinator-loop?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Зачем: - сохранить выводы сессии проектирования у самого навыка, чтобы будущая сессия по доработке нашла их рядом с 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) --- ...-06-14-coordinator-loop-context-economy.md | 266 ++++++++++++++++++ 1 file changed, 266 insertions(+) create mode 100644 agents/.agents/skills/coordinator-loop/handoffs/2026-06-14-coordinator-loop-context-economy.md diff --git a/agents/.agents/skills/coordinator-loop/handoffs/2026-06-14-coordinator-loop-context-economy.md b/agents/.agents/skills/coordinator-loop/handoffs/2026-06-14-coordinator-loop-context-economy.md new file mode 100644 index 0000000..8fa31fa --- /dev/null +++ b/agents/.agents/skills/coordinator-loop/handoffs/2026-06-14-coordinator-loop-context-economy.md @@ -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` — + + (`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-уведомления (``) приходили, но 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` по кругу.** Пришло `` — сразу + обрабатывать; один разумный статус-таймер вместо 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` — для коммитов изменений в навыке.