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-агенту как единственный
обязательный пункт второго круга.