- Зачем: - наблюдения по задаче 07 нужны для итоговой рефлексии эксперимента с субагентами. - Что: - добавлен вывод о роли reviewer-а в проверке силы интеграционного теста. - Проверка: - git diff -- .scratch/handoffs/2026-06-11-subagent-coordinator-experiment.md.
243 lines
17 KiB
Markdown
243 lines
17 KiB
Markdown
# Handoff: эксперимент с координатором субагентов
|
||
|
||
Дата: 2026-06-11
|
||
Ветка: `feature/data-generator`
|
||
Жанр: одноразовый handoff по [ADR-0003](../../docs/adr/0003-handoffs-in-scratch.md).
|
||
|
||
## Зачем нужен этот handoff
|
||
|
||
Пользователь хочет провести эксперимент: не реализовывать следующие задачи
|
||
самому верхнеуровневому агенту, а использовать его как координатора цепочки
|
||
субагентов. После эксперимента планируется отдельно отрефлексировать, что
|
||
сработало, что не сработало и стоит ли закреплять такой процесс.
|
||
|
||
Этот документ фиксирует текущее понимание процесса перед запуском, чтобы не
|
||
потерять договорённости в новой сессии.
|
||
|
||
## Текущий рабочий контекст
|
||
|
||
Активная линия работы — переработка steady-stream генератора кликстрима.
|
||
Задачи лежат в `.scratch/feature-data-generator/issues/`.
|
||
|
||
Уже выполнены и ожидают человеческой приёмки:
|
||
|
||
- `01-minimal-connected-visit.md`
|
||
- `02-visit-page-path-and-monotonic-time.md`
|
||
- `02-5-generator-service-cleanup.md`
|
||
- `03-tick-stream-with-active-visits.md`
|
||
- `04-user-population-and-returns.md`
|
||
|
||
Оставшаяся последовательность:
|
||
|
||
1. `05-intensity-and-flow-calibration.md`
|
||
2. `06-state-v2-and-restart.md`
|
||
3. `07-service-integration-and-docs.md`
|
||
|
||
Задачи зависимы и, вероятно, меняют близкие файлы генератора, поэтому запускать
|
||
их надо строго последовательно, не параллельно.
|
||
|
||
В рабочем дереве на момент обсуждения была незакоммиченная правка только в
|
||
`.scratch/feature-data-generator/issues/06-state-v2-and-restart.md`: добавлен
|
||
комментарий, что задачу 06 нельзя начинать до завершения предыдущих срезов,
|
||
особенно задачи 05.
|
||
|
||
## Договорённая схема эксперимента
|
||
|
||
Верхнеуровневый агент не включает для себя `/goal`. Его роль — координатор и
|
||
gatekeeper, а не непосредственный исполнитель.
|
||
|
||
Для каждой задачи:
|
||
|
||
1. Координатор запускает нового worker-субагента на ровно один issue.
|
||
2. Задание субагенту формулируется в стиле `/goal`:
|
||
- реализовать конкретный файл задачи;
|
||
- работать по методике `/tdd`;
|
||
- не реализовывать следующие задачи;
|
||
- не коммитить;
|
||
- не откатывать чужие изменения;
|
||
- в конце отчитаться по изменённым файлам, тестам, проверкам и рискам.
|
||
3. После реализации тот же субагент делает саморевью в отдельной роли:
|
||
- остановиться;
|
||
- проверить результат против acceptance criteria, спеки и тестов;
|
||
- искать ошибки, лишний объём, хрупкость и нарушение учебной читаемости;
|
||
- сначала выдать находки с важностью, не исправляя их сразу.
|
||
4. Координатор решает, какие замечания достаточно важные.
|
||
5. Тот же субагент исправляет только одобренные важные замечания.
|
||
6. Координатор проверяет верхнеуровневые вещи:
|
||
- границы задачи;
|
||
- список изменённых файлов;
|
||
- честность отметок acceptance criteria;
|
||
- тесты;
|
||
- `git status`;
|
||
- отсутствие смешивания нескольких задач.
|
||
7. Коммит делает координатор, не субагент.
|
||
8. Координатор закрывает агента и переходит к следующему issue новым
|
||
worker-субагентом.
|
||
|
||
Для сложных переходов, особенно после задачи 05 перед задачей 06, можно добавить
|
||
отдельного reviewer-субагента. Это не обязательный шаг на каждую задачу, а
|
||
контрольная мера, если есть риск, что саморевью исполнителя недостаточно.
|
||
|
||
## Роль координатора
|
||
|
||
Координатор не должен пытаться заново глубоко реализовывать или полностью
|
||
повторять работу субагента. Его польза — в управлении процессом:
|
||
|
||
- держать порядок задач;
|
||
- ограничивать область изменений;
|
||
- читать отчёты и принимать решения;
|
||
- запускать исправления только по существенным замечаниям;
|
||
- делать финальный обзор diff на уровне границ и рисков;
|
||
- выполнять проверки и коммитить.
|
||
|
||
Главный риск верхнеуровневого `/goal`: он может заставить координатора
|
||
оптимизировать работу под закрытие большой цели, а не под аккуратное управление
|
||
этапами. Поэтому для координатора `/goal` не использовать.
|
||
|
||
## Почему саморевью тем же субагентом допустимо
|
||
|
||
Пользователь отмечает, что на практике субагенты хорошо делают “ревью свежим
|
||
взглядом” внутри уже накопленного подробного контекста задачи. Это может быть
|
||
полезнее, чем полностью внешний поверхностный обзор координатора, которому не
|
||
хватит деталей реализации.
|
||
|
||
Ожидаемая модель:
|
||
|
||
- субагент глубоко понимает сделанную задачу и проверяет её на несостыковки;
|
||
- координатор не доверяет этому слепо, но оценивает адекватность выводов и
|
||
границы изменений;
|
||
- для особо рискованных мест можно подключить отдельного проверяющего агента.
|
||
|
||
## Suggested skills
|
||
|
||
- `tdd` — должен использовать worker-субагент при реализации каждой задачи.
|
||
- `conventional-commits` — использовать координатору перед созданием каждого
|
||
коммита.
|
||
- `claude-team-review` — опционально после задачи 05 или перед задачей 06, если
|
||
нужен дополнительный независимый взгляд на модель.
|
||
- `handoff` — после эксперимента зафиксировать рефлексию: что получилось, что
|
||
не получилось, какие правила стоит оставить.
|
||
|
||
## Возможная первая команда субагенту
|
||
|
||
```text
|
||
/goal Реализовать .scratch/feature-data-generator/issues/05-intensity-and-flow-calibration.md с использованием /tdd.
|
||
|
||
Работай только в границах этой задачи. Не реализовывай задачи 06-07.
|
||
Не коммить. Не откатывай чужие изменения.
|
||
|
||
Сначала прочитай сам issue и источники решений, указанные в нём. Работай
|
||
вертикальными TDD-срезами: один тест на наблюдаемое поведение -> минимальная
|
||
реализация -> зелёная проверка -> следующий тест.
|
||
|
||
В конце остановись и отчитайся:
|
||
- какие файлы изменены;
|
||
- какие тесты добавлены или изменены;
|
||
- какие проверки запускались и с каким результатом;
|
||
- какие acceptance criteria закрыты;
|
||
- какие риски или спорные места остались.
|
||
```
|
||
|
||
После этого координатор должен попросить того же субагента выполнить саморевью
|
||
результата, не исправляя замечания до отдельного решения координатора.
|
||
|
||
## Наблюдения во время эксперимента
|
||
|
||
### Цикл 05: интенсивность и калибровка потока
|
||
|
||
Стартовая задача оказалась дорогой по обратной связи: это не локальный инвариант,
|
||
а отладка статистической модели на длинных симуляциях. Первый worker долго
|
||
работал без промежуточного отчёта; координатору пришлось сначала поставить
|
||
мягкий статус-чек в очередь, затем прервать агента ради статуса. Это не сломало
|
||
работу, но показало: для статистических задач лучше заранее задавать контрольные
|
||
точки или ожидать длинный первый цикл.
|
||
|
||
Саморевью того же worker оказалось полезным. Оно нашло несколько реальных
|
||
несостыковок:
|
||
|
||
- `docker-compose.yml` оставлял старую интенсивность `GEN_LAMBDA_BASE_PER_MIN=200`;
|
||
- тест межсессионной паузы был слишком широким;
|
||
- в тестовой конфигурации оставались старые числа;
|
||
- README мог быть двусмысленным про `GEN_MIN/MAX_EVENTS_PER_TICK`.
|
||
|
||
Координаторская проверка тоже добавила ценность: после саморевью был найден
|
||
конфликт между новым `GEN_LAMBDA_BASE_PER_MIN=30` и старым нижним пределом
|
||
`GEN_MIN_EVENTS_PER_TICK=5`. При тике 5 секунд это давало минимум 60 событий в
|
||
минуту и ломало критерий интенсивности. Worker исправил это отдельной точечной
|
||
итерацией.
|
||
|
||
Полезная схема цикла:
|
||
|
||
1. worker реализует задачу;
|
||
2. координатор прерывает только если агент слишком долго молчит;
|
||
3. worker делает саморевью без правок;
|
||
4. координатор выбирает, какие замечания чинить;
|
||
5. worker чинит только выбранные пункты;
|
||
6. координатор добавляет свой узкий sanity-check по связям между дефолтами,
|
||
документацией и критерием задачи;
|
||
7. координатор коммитит.
|
||
|
||
Результат цикла 05:
|
||
|
||
- коммит `8f1e997 feat(generator): откалиброван поток steady-stream генератора`;
|
||
- полный прогон: `uv run --with-requirements generator/requirements.txt pytest generator/tests -q`
|
||
— 96 passed;
|
||
- `git diff --check` — без замечаний.
|
||
|
||
Промежуточный вывод: тот же субагент действительно хорошо использует подробный
|
||
контекст задачи для саморевью, но координатор всё равно нужен как внешний
|
||
проверяющий связей между настройками, обычным запуском и acceptance criteria.
|
||
|
||
### Reviewer-субагент между задачами
|
||
|
||
После задачи 06 пользователь предложил добавить отдельного reviewer-субагента
|
||
между задачами. Это выглядит особенно полезно на границах вроде 06 -> 07, где
|
||
следующая задача будет опираться на уже изменённые состояние, сервисный цикл и
|
||
документацию.
|
||
|
||
Важное ограничение: reviewer не является источником истины. Его находки нужно
|
||
рассматривать как гипотезы и классифицировать координатором:
|
||
|
||
- `чинить до коммита` — реальный дефект или риск закрытия acceptance criteria;
|
||
- `записать как риск` — важно знать, но не блокирует текущую задачу;
|
||
- `ложная тревога` — reviewer неверно понял код, тест или границы задачи;
|
||
- `вне скоупа` — может быть полезно позже, но не относится к текущему issue.
|
||
|
||
Только находки из первой группы возвращаются worker-агенту на исправление.
|
||
Иначе есть риск превратить reviewer-а в источник лишнего объёма и расползания
|
||
задачи.
|
||
|
||
В цикле 06 это правило сразу пригодилось. Саморевью исполнителя и отдельный
|
||
reviewer независимо нашли два существенных риска:
|
||
|
||
- битое state v2 с валидным ГПСЧ могло пройти `from_dict_safe`, а затем уронить
|
||
сервис уже в `restore_state`;
|
||
- снимок активных визитов сохранялся полными batch-словарями и на верхних
|
||
лимитах получался порядка мегабайт, хотя спека говорит про компактное
|
||
состояние.
|
||
|
||
Координатор проверил обе гипотезы локально: `restore_state` действительно падал
|
||
на битой вложенной структуре, а оценка JSON-снимка при 200 активных визитах и
|
||
популяции 300 дала около 4.7 MB. Эти находки классифицированы как `чинить до
|
||
коммита` и возвращены worker-агенту. Низкие замечания про совместимость
|
||
`generate_tick_batch` и пересечение сервиса с задачей 07 не стали правками:
|
||
первое оказалось ложной тревогой, второе — допустимым пересечением для
|
||
восстановления state v2.
|
||
|
||
После крупной переделки по замечаниям reviewer-а нужен второй круг ревью. В
|
||
цикле 06 это подтвердилось: исправление компактного состояния само изменило
|
||
дизайн снимка и восстановление активных визитов. Второй reviewer нашёл новый
|
||
дефект уже в исправленной версии: формально похожий v2-state с `population=[]`
|
||
или строковым `pending_visit_births` проходил первичную загрузку, но затем
|
||
оставлял поток без пользователей или ронял следующий тик. Координатор
|
||
подтвердил это локальной проверкой и вернул worker-агенту как единственный
|
||
обязательный пункт второго круга.
|
||
|
||
В цикле 07 reviewer оказался полезен уже не для поиска падений, а для силы
|
||
доказательства. Worker добавил сервисный тест с мок-публикацией, но внешний
|
||
reviewer заметил, что один опубликованный event доказывает четыре топика и
|
||
связи, но слабее доказывает невырожденную модель «один визит -> несколько
|
||
событий с одним `click_id`». Координатор классифицировал это как `чинить до
|
||
коммита`: финальный интеграционный тест должен доказывать именно уход от старой
|
||
плоской модели, а не только факт публикации.
|