docs(generator): добавлены задачи по модельному времени
- Зачем: - нужен рабочий план для реализации модельного времени и стартовой истории. - Что: - добавлен parent PRD с инвариантами, зависимостями и review gate. - добавлены шесть локальных issue для последовательной работы. - добавлен handoff для продолжения в новой сессии. - Проверка: - git diff --check.
This commit is contained in:
@@ -0,0 +1,80 @@
|
|||||||
|
# Модельное время и стартовая история генератора
|
||||||
|
|
||||||
|
Status: Draft
|
||||||
|
|
||||||
|
## Зачем
|
||||||
|
|
||||||
|
Нужно довести решение ADR-0005 и ADR-0006 до рабочего процесса: генератор живёт
|
||||||
|
по модельному времени, умеет быстро создать прошлое, сохранить слепок состояния
|
||||||
|
и продолжить поток так, чтобы результат был проверяем в ClickHouse.
|
||||||
|
|
||||||
|
Источник решений:
|
||||||
|
|
||||||
|
- `docs/specs/2026-06-14-generator-model-time-and-startup-history.md`
|
||||||
|
- `docs/adr/0005-generator-model-clock.md`
|
||||||
|
- `docs/adr/0006-generation-as-sole-analytics-source.md`
|
||||||
|
- `docs/research/2026-06-11-subagent-coordinator-experiment.md`
|
||||||
|
|
||||||
|
## Общие правила приёмки
|
||||||
|
|
||||||
|
- Каждый кодовый срез должен заканчиваться проверкой через ClickHouse, а не
|
||||||
|
только локальными тестами генератора.
|
||||||
|
- Быстрый цикл внутри задачи идёт через `/tdd`: один поведенческий тест,
|
||||||
|
минимальная реализация, зелёная проверка.
|
||||||
|
- Координатор не работает в `/goal` на всю цепочку. Один worker получает один
|
||||||
|
issue, не коммитит и не реализует следующие задачи.
|
||||||
|
- После реализации worker делает саморевью без правок. Координатор
|
||||||
|
классифицирует находки и возвращает только обязательные исправления.
|
||||||
|
- Коммиты делает координатор после своих проверок и `git status --short`.
|
||||||
|
- Ручная проверка дашбордов глазами выполняется только в конце всей цепочки.
|
||||||
|
|
||||||
|
## Сквозные инварианты
|
||||||
|
|
||||||
|
- `event_timestamp` — модельное время, а не настенные часы компьютера.
|
||||||
|
- Операционные метки сервиса, история пачек, метрики здоровья и длительность
|
||||||
|
тика остаются настенным временем, если отдельная задача не докажет обратное.
|
||||||
|
- При одинаковых `GEN_SEED`, `T0`, скорости и настройках поток повторяем.
|
||||||
|
- При ×K модельное время и событийный бюджет идут по модельной длительности
|
||||||
|
тика, а не по реальной длительности сна процесса.
|
||||||
|
- После сбоя точка возобновления считается из сохранённой связки модельного и
|
||||||
|
настенного времени, а не простым `datetime.now()`.
|
||||||
|
- Стартовая история — это события плюс слепок состояния плюс манифест, чтобы не
|
||||||
|
смешать данные от разных `GEN_SEED`, `T0` и `T_end`.
|
||||||
|
- На стыке `[T0, T_end]` и живого продолжения не должно быть дублей и дыр.
|
||||||
|
- Повторная проверка на чистом стенде должна быть воспроизводимой: либо команда
|
||||||
|
явно чистит данные, либо процесс идемпотентен.
|
||||||
|
|
||||||
|
## Задачи
|
||||||
|
|
||||||
|
1. `issues/01-time-and-startup-history-contract.md` — контракт модельного
|
||||||
|
времени и стартовой истории.
|
||||||
|
2. `issues/02-model-time-to-clickhouse.md` — минимальный поток по модельному
|
||||||
|
времени до ClickHouse.
|
||||||
|
3. `issues/03-model-speed-and-day-factor.md` — ×K и дневной коэффициент по
|
||||||
|
модельному времени.
|
||||||
|
4. `issues/04-state-v2-model-resume.md` — восстановление state v2 от модельной
|
||||||
|
точки возобновления.
|
||||||
|
5. `issues/05-startup-history-backfill-to-clickhouse.md` — промотка прошлого,
|
||||||
|
стартовая история и живое продолжение до ClickHouse.
|
||||||
|
6. `issues/06-generated-history-as-analytics-source.md` — штатный путь стенда
|
||||||
|
переводится на стартовую историю как источник аналитики.
|
||||||
|
|
||||||
|
## Контрольные точки
|
||||||
|
|
||||||
|
- После задачи 3 нужен внешний review gate по сквозному инварианту времени:
|
||||||
|
проверить, где ещё остались настенные часы, и не расходятся ли живой путь,
|
||||||
|
расчёт интенсивности и сохранение состояния.
|
||||||
|
- После задачи 5 нужен внешний review gate по распределениям и двум путям
|
||||||
|
генерации: проверить форму данных, стык истории и живого продолжения,
|
||||||
|
однородность визита до и после восстановления.
|
||||||
|
|
||||||
|
Для этих контрольных точек по возможности нужен reviewer другой родословной, а
|
||||||
|
не тот же worker: research показал, что сквозные свойства и форма распределений
|
||||||
|
хуже ловятся одной линией проверки.
|
||||||
|
|
||||||
|
## Финальная ручная приёмка
|
||||||
|
|
||||||
|
После задачи 6 человек смотрит Superset/Grafana и проверяет, что стенд живёт на
|
||||||
|
генерации: видны история, возвраты, воронка и суточное «дыхание». Если текущих
|
||||||
|
панелей не хватает для такого просмотра, создаётся отдельная задача на панель
|
||||||
|
или runbook, а не расширяется эта цепочка задним числом.
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
Status: ready-for-human
|
||||||
|
|
||||||
|
# Контракт модельного времени и стартовой истории
|
||||||
|
|
||||||
|
## Parent
|
||||||
|
|
||||||
|
`.scratch/generator-model-time-startup-history/PRD.md`
|
||||||
|
|
||||||
|
## What to build
|
||||||
|
|
||||||
|
Зафиксировать рабочий контракт для реализации модельного времени и стартовой
|
||||||
|
истории. Это HITL-срез: до кода нужно решить внешний интерфейс, формат
|
||||||
|
стартовой истории и правила восстановления, чтобы worker-и не угадывали
|
||||||
|
поведение через тесты.
|
||||||
|
|
||||||
|
Контракт должен остаться коротким и понятным: что задаёт `T0`, как задаётся ×K,
|
||||||
|
что такое `T_end`, как выглядит стартовая история, какие метки времени
|
||||||
|
модельные, а какие операционные.
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] Выбраны имена и формат настроек для `T0`, скорости ×K и режима промотки
|
||||||
|
прошлого.
|
||||||
|
- [ ] Описано, как после сбоя вычисляется модельная точка возобновления при ×K:
|
||||||
|
из сохранённой модельной метки, сохранённой настенной метки и скорости.
|
||||||
|
- [ ] Описан манифест стартовой истории: минимум `GEN_SEED`, `T0`, `T_end`,
|
||||||
|
настройки генерации, версия state и контрольные числа.
|
||||||
|
- [ ] Описана граница `T_end`: где заканчивается прошлое и с какой метки
|
||||||
|
начинается живое продолжение, без дублей и дыр.
|
||||||
|
- [ ] Разделены модельные метки событий и настенные операционные метки сервиса.
|
||||||
|
- [ ] Решено, как координатор будет получать повторяемую ClickHouse-проверку:
|
||||||
|
через очистку данных или идемпотентный прогон.
|
||||||
|
- [ ] Контракт записан в durable-документ: обновление `PRD.md`, короткий
|
||||||
|
design note в `.scratch/generator-model-time-startup-history/` или уточнение
|
||||||
|
спеки. Сам issue 01 только ссылается на источник истины.
|
||||||
|
|
||||||
|
## Blocked by
|
||||||
|
|
||||||
|
None - can start immediately
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
Status: ready-for-agent
|
||||||
|
|
||||||
|
# Модельное время до ClickHouse
|
||||||
|
|
||||||
|
## Parent
|
||||||
|
|
||||||
|
`.scratch/generator-model-time-startup-history/PRD.md`
|
||||||
|
|
||||||
|
## What to build
|
||||||
|
|
||||||
|
Сделать минимальный живой поток, где генератор стартует от `T0`, пишет
|
||||||
|
`event_timestamp` по модельному времени и доводит события до ClickHouse
|
||||||
|
обычным путём стенда. Срез должен доказать не внутренний класс часов, а
|
||||||
|
наблюдаемое поведение: данные в ClickHouse начинаются от модельной точки и
|
||||||
|
повторяются при тех же настройках.
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] При фиксированных `GEN_SEED` и `T0` первый короткий прогон пишет события с
|
||||||
|
модельными `event_timestamp`, начинающимися около `T0`.
|
||||||
|
- [ ] Повторный чистый прогон с теми же настройками даёт те же контрольные
|
||||||
|
числа в ClickHouse.
|
||||||
|
- [ ] Расчёт дневного коэффициента в этом срезе больше не зависит от реального
|
||||||
|
часа запуска процесса.
|
||||||
|
- [ ] Локальные тесты проверяют поведение через публичный интерфейс генератора
|
||||||
|
или сервиса, без привязки к внутреннему устройству часов.
|
||||||
|
- [ ] Есть команда или короткая инструкция для координатора: поднять стенд,
|
||||||
|
прогнать поток, выполнить SQL-проверку в ClickHouse.
|
||||||
|
- [ ] Документация запуска не утверждает, что `event_timestamp` равен
|
||||||
|
настенному времени.
|
||||||
|
|
||||||
|
## Blocked by
|
||||||
|
|
||||||
|
- `.scratch/generator-model-time-startup-history/issues/01-time-and-startup-history-contract.md`
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
Status: ready-for-agent
|
||||||
|
|
||||||
|
# ×K и дневной коэффициент по модельному времени
|
||||||
|
|
||||||
|
## Parent
|
||||||
|
|
||||||
|
`.scratch/generator-model-time-startup-history/PRD.md`
|
||||||
|
|
||||||
|
## What to build
|
||||||
|
|
||||||
|
Добавить ускоренный живой ход модельных часов. При ×K за один реальный тик
|
||||||
|
должна проходить большая модельная длительность, а событийный бюджет должен
|
||||||
|
считаться по этой модельной длительности. Дневной коэффициент считается по
|
||||||
|
модельному часу.
|
||||||
|
|
||||||
|
Результат должен быть виден в ClickHouse: модельные метки уходят вперёд быстрее
|
||||||
|
реального времени, а объём событий соответствует пройденному модельному
|
||||||
|
интервалу.
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] На ×1 поведение остаётся совместимым с обычным живым режимом.
|
||||||
|
- [ ] На ×K модельные `event_timestamp` за короткий реальный прогон покрывают
|
||||||
|
примерно `K` раз большую модельную длительность.
|
||||||
|
- [ ] Событийный бюджет считается по модельной длительности тика, а не по
|
||||||
|
реальному времени сна процесса.
|
||||||
|
- [ ] Дневной коэффициент меняется при переходе модельного времени через
|
||||||
|
дневные/ночные часы, независимо от реального часа запуска.
|
||||||
|
- [ ] ClickHouse-проверка показывает повторяемые контрольные числа при тех же
|
||||||
|
`GEN_SEED`, `T0`, скорости и настройках.
|
||||||
|
- [ ] В `generator/README.md` или `docs/OPERATIONS.md` кратко описано, что ×K
|
||||||
|
ускоряет именно модельное время стенда.
|
||||||
|
|
||||||
|
## Blocked by
|
||||||
|
|
||||||
|
- `.scratch/generator-model-time-startup-history/issues/02-model-time-to-clickhouse.md`
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
Status: ready-for-agent
|
||||||
|
|
||||||
|
# Восстановление state v2 от модельной точки
|
||||||
|
|
||||||
|
## Parent
|
||||||
|
|
||||||
|
`.scratch/generator-model-time-startup-history/PRD.md`
|
||||||
|
|
||||||
|
## What to build
|
||||||
|
|
||||||
|
Привести восстановление state v2 к модельному времени. Один и тот же слепок
|
||||||
|
должен уметь восстанавливаться в двух разных случаях: после сбоя, где время
|
||||||
|
действительно прошло, и при старте из стартовой истории, где продолжение идёт
|
||||||
|
от `T_end` без искусственного разрыва.
|
||||||
|
|
||||||
|
Срез должен доказать поведение не только локальными тестами состояния, но и
|
||||||
|
данными в ClickHouse: активные визиты продолжаются или закрываются по правилам
|
||||||
|
модельного времени.
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] State сохраняет достаточно данных, чтобы после сбоя вычислить модельную
|
||||||
|
точку возобновления при ×K.
|
||||||
|
- [ ] Восстановление после короткого сбоя продолжает активные визиты и досылает
|
||||||
|
созревшие события с исходными модельными метками.
|
||||||
|
- [ ] Восстановление после долгого сбоя закрывает сильно просроченные активные
|
||||||
|
визиты без досылки остатка.
|
||||||
|
- [ ] Восстановление из стартовой истории использует `T_end` как точку
|
||||||
|
возобновления и не обрывает активные визиты из-за настенного простоя.
|
||||||
|
- [ ] Повреждённый или несовместимый state не валит сервис: генератор стартует
|
||||||
|
с чистого листа и пишет предупреждение.
|
||||||
|
- [ ] ClickHouse-проверка подтверждает, что на стыке восстановления нет дублей
|
||||||
|
событий и нет разрыва `click_id` внутри продолжающегося визита.
|
||||||
|
- [ ] После реализации выполнено саморевью worker-а и отдельное reviewer-ревью,
|
||||||
|
потому что задача меняет state/serialization и сервисное восстановление.
|
||||||
|
|
||||||
|
## Blocked by
|
||||||
|
|
||||||
|
- `.scratch/generator-model-time-startup-history/issues/03-model-speed-and-day-factor.md`
|
||||||
|
- Review gate из `PRD.md`: сквозной инвариант времени после задачи 3
|
||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
Status: ready-for-agent
|
||||||
|
|
||||||
|
# Стартовая история до ClickHouse
|
||||||
|
|
||||||
|
## Parent
|
||||||
|
|
||||||
|
`.scratch/generator-model-time-startup-history/PRD.md`
|
||||||
|
|
||||||
|
## What to build
|
||||||
|
|
||||||
|
Сделать промотку прошлого: генератор быстро проходит от `T0` до `T_end`, создаёт
|
||||||
|
события за этот отрезок, сохраняет слепок состояния и манифест стартовой
|
||||||
|
истории. Эту историю нужно загрузить в ClickHouse и доказать, что живой поток
|
||||||
|
может продолжить её с `T_end`.
|
||||||
|
|
||||||
|
Это главный срез стартовой истории. Он должен проверять не только факт наличия
|
||||||
|
данных, но и форму данных: пирамиду, возвраты, длину визита, воронку и стык
|
||||||
|
между прошлым и живым продолжением.
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] Промотка прошлого создаёт события за `[T0, T_end]`, слепок состояния и
|
||||||
|
манифест с контрольными данными.
|
||||||
|
- [ ] При одинаковых `GEN_SEED`, `T0`, `T_end` и настройках результат промотки
|
||||||
|
повторяем в пределах согласованных допусков.
|
||||||
|
- [ ] История загружается в ClickHouse штатной или явно описанной командой.
|
||||||
|
- [ ] SQL-проверка показывает здоровую пирамиду: пользователей меньше, чем
|
||||||
|
визитов, визитов меньше, чем событий.
|
||||||
|
- [ ] SQL-проверка показывает возвраты: у части пользователей больше одного
|
||||||
|
визита.
|
||||||
|
- [ ] SQL-проверка длины визита проверяет форму, а не только среднее: долю
|
||||||
|
коротких визитов, медиану и долю срезов о потолок.
|
||||||
|
- [ ] SQL-проверка воронки `/home -> товары -> /cart -> /payment ->
|
||||||
|
/confirmation` монотонно убывает, а доля дошедших до `/confirmation` в
|
||||||
|
согласованном коридоре.
|
||||||
|
- [ ] Живое продолжение после `T_end` не создаёт дублей на границе и не выглядит
|
||||||
|
как независимый второй мир.
|
||||||
|
- [ ] Подготовлены данные, команды и SQL-проверки, достаточные для внешнего
|
||||||
|
review gate по распределениям и двум путям генерации из `PRD.md`.
|
||||||
|
|
||||||
|
## Blocked by
|
||||||
|
|
||||||
|
- `.scratch/generator-model-time-startup-history/issues/04-state-v2-model-resume.md`
|
||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
Status: ready-for-agent
|
||||||
|
|
||||||
|
# Стартовая история как источник аналитики
|
||||||
|
|
||||||
|
## Parent
|
||||||
|
|
||||||
|
`.scratch/generator-model-time-startup-history/PRD.md`
|
||||||
|
|
||||||
|
## What to build
|
||||||
|
|
||||||
|
Перевести штатный путь стенда на стартовую историю как источник аналитики.
|
||||||
|
Чистый стенд должен получать данные из генерации: стартовая история загружается,
|
||||||
|
STG→ODS→DDS→DM строится на ней, а Superset работает с этими витринами. Архивный
|
||||||
|
статический сид остаётся только временной кладовкой фактуры для генератора, а не
|
||||||
|
источником аналитического контура.
|
||||||
|
|
||||||
|
Срез не требует финальной ручной оценки красоты дашбордов, но должен дать
|
||||||
|
техническое доказательство: витрины и датасеты не пустые, контрольные числа
|
||||||
|
берутся из генерации.
|
||||||
|
|
||||||
|
Границы среза: штатный путь стенда и документы запуска. Переписывание уроков,
|
||||||
|
новые панели и улучшение формы дашбордов остаются follow-up, если по ходу не
|
||||||
|
окажутся маленькой обязательной правкой для запуска.
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] Штатная команда запуска чистого стенда создаёт или загружает стартовую
|
||||||
|
историю и прогоняет её до DM-витрин.
|
||||||
|
- [ ] `kafka_load_dag` или заменяющий его путь больше не использует архивный
|
||||||
|
`data/*.jsonl` как источник аналитики.
|
||||||
|
- [ ] ClickHouse-проверки из задачи 5 доступны как повторяемая команда для
|
||||||
|
координатора или CI.
|
||||||
|
- [ ] Основные DM-витрины, на которых стоят дашборды, непустые и показывают
|
||||||
|
данные генерации.
|
||||||
|
- [ ] Superset-датасеты и дашборды технически открываются на данных генерации;
|
||||||
|
ручная оценка формы графиков остаётся финальной HITL-приёмкой.
|
||||||
|
- [ ] `README.md`, `docs/OPERATIONS.md` и `generator/README.md` больше не
|
||||||
|
описывают архивный сид как основной источник аналитики.
|
||||||
|
- [ ] Если уроки или дашборды требуют нетривиальной переделки, создан follow-up
|
||||||
|
issue вместо расширения этой задачи.
|
||||||
|
- [ ] Описан повторный чистый прогон: какие данные очищаются и какие команды
|
||||||
|
выполняются, чтобы координатор мог надёжно перепроверить результат.
|
||||||
|
|
||||||
|
## Blocked by
|
||||||
|
|
||||||
|
- `.scratch/generator-model-time-startup-history/issues/05-startup-history-backfill-to-clickhouse.md`
|
||||||
|
- Review gate из `PRD.md`: распределения и два пути генерации после задачи 5
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
# Handoff: задачи по модельному времени и стартовой истории
|
||||||
|
|
||||||
|
Дата: 2026-06-14
|
||||||
|
Жанр: одноразовый handoff по ADR-0003.
|
||||||
|
|
||||||
|
## Что сделано
|
||||||
|
|
||||||
|
Создан рабочий набор артефактов для следующей фазы работ:
|
||||||
|
|
||||||
|
- `.scratch/generator-model-time-startup-history/PRD.md`
|
||||||
|
- `.scratch/generator-model-time-startup-history/issues/01-time-and-startup-history-contract.md`
|
||||||
|
- `.scratch/generator-model-time-startup-history/issues/02-model-time-to-clickhouse.md`
|
||||||
|
- `.scratch/generator-model-time-startup-history/issues/03-model-speed-and-day-factor.md`
|
||||||
|
- `.scratch/generator-model-time-startup-history/issues/04-state-v2-model-resume.md`
|
||||||
|
- `.scratch/generator-model-time-startup-history/issues/05-startup-history-backfill-to-clickhouse.md`
|
||||||
|
- `.scratch/generator-model-time-startup-history/issues/06-generated-history-as-analytics-source.md`
|
||||||
|
|
||||||
|
Артефакты режут работу на 6 последовательных issue и 2 review gate. Главная
|
||||||
|
идея: каждый кодовый срез должен подтверждаться через ClickHouse, а не только
|
||||||
|
локальными тестами генератора. Финальная проверка дашбордов глазами остаётся в
|
||||||
|
конце.
|
||||||
|
|
||||||
|
## Важные решения
|
||||||
|
|
||||||
|
- Координатор не берёт `/goal` на всю цепочку: один worker получает один issue.
|
||||||
|
- Worker работает через `/tdd`, не коммитит и не реализует следующие задачи.
|
||||||
|
- После реализации worker делает саморевью без правок.
|
||||||
|
- Координатор классифицирует находки и коммитит сам.
|
||||||
|
- После задачи 3 нужен review gate по сквозному инварианту времени.
|
||||||
|
- После задачи 5 нужен review gate по распределениям и двум путям генерации.
|
||||||
|
- Для этих review gate по возможности нужен reviewer другой родословной: это
|
||||||
|
следует из `docs/research/2026-06-11-subagent-coordinator-experiment.md`.
|
||||||
|
|
||||||
|
## Что важно не потерять
|
||||||
|
|
||||||
|
- В задаче 1 нужно зафиксировать durable-контракт, а не оставить решение только
|
||||||
|
в комментарии к issue.
|
||||||
|
- При ×K восстановление после сбоя нельзя считать простым `datetime.now()`: нужна
|
||||||
|
сохранённая связка модельного и настенного времени.
|
||||||
|
- Стартовая история должна быть парным артефактом: события, слепок состояния и
|
||||||
|
манифест.
|
||||||
|
- Задача 6 специально сужена до штатного пути стенда и документов запуска.
|
||||||
|
Уроки, новые панели и улучшения дашбордов уходят в follow-up, если окажутся
|
||||||
|
нетривиальными.
|
||||||
|
|
||||||
|
## Suggested skills
|
||||||
|
|
||||||
|
- `to-issues` — если понадобится переразбить или опубликовать дополнительные
|
||||||
|
issue.
|
||||||
|
- `tdd` — основной режим работы worker-а над каждым кодовым issue.
|
||||||
|
- `conventional-commits` — перед каждым коммитом координатора.
|
||||||
|
- `claude-team-review` или другой внешний reviewer — на двух review gate.
|
||||||
|
- `handoff` — если работа прерывается между issue или после review gate.
|
||||||
|
|
||||||
|
## Следующий шаг
|
||||||
|
|
||||||
|
Начать с
|
||||||
|
`.scratch/generator-model-time-startup-history/issues/01-time-and-startup-history-contract.md`.
|
||||||
|
Это HITL-задача: нужно закрепить интерфейс модельного времени, манифест
|
||||||
|
стартовой истории, правило границы `T_end` и способ повторяемой проверки в
|
||||||
|
ClickHouse.
|
||||||
Reference in New Issue
Block a user