docs(generator): дополнены наблюдения эксперимента с субагентами

- Зачем:
  - результаты первых циклов эксперимента нужно сохранить отдельно от рабочих изменений генератора.
- Что:
  - зафиксированы выводы по саморевью, reviewer-субагенту и второму кругу ревью.
  - описана классификация reviewer-находок перед отправкой worker-агенту.
- Проверка:
  - git diff --stat -- .scratch/handoffs/2026-06-11-subagent-coordinator-experiment.md.
This commit is contained in:
Dmitry Dementiev
2026-06-11 18:02:25 +03:00
parent 640050e409
commit 4a08465f7d
@@ -140,3 +140,95 @@ gatekeeper, а не непосредственный исполнитель.
После этого координатор должен попросить того же субагента выполнить саморевью После этого координатор должен попросить того же субагента выполнить саморевью
результата, не исправляя замечания до отдельного решения координатора. результата, не исправляя замечания до отдельного решения координатора.
## Наблюдения во время эксперимента
### Цикл 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-агенту как единственный
обязательный пункт второго круга.