diff --git a/.scratch/generator-model-time-startup-history/PRD.md b/.scratch/generator-model-time-startup-history/PRD.md new file mode 100644 index 0000000..95f38c5 --- /dev/null +++ b/.scratch/generator-model-time-startup-history/PRD.md @@ -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, а не расширяется эта цепочка задним числом. diff --git a/.scratch/generator-model-time-startup-history/issues/01-time-and-startup-history-contract.md b/.scratch/generator-model-time-startup-history/issues/01-time-and-startup-history-contract.md new file mode 100644 index 0000000..642fe3d --- /dev/null +++ b/.scratch/generator-model-time-startup-history/issues/01-time-and-startup-history-contract.md @@ -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 diff --git a/.scratch/generator-model-time-startup-history/issues/02-model-time-to-clickhouse.md b/.scratch/generator-model-time-startup-history/issues/02-model-time-to-clickhouse.md new file mode 100644 index 0000000..ae031e9 --- /dev/null +++ b/.scratch/generator-model-time-startup-history/issues/02-model-time-to-clickhouse.md @@ -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` diff --git a/.scratch/generator-model-time-startup-history/issues/03-model-speed-and-day-factor.md b/.scratch/generator-model-time-startup-history/issues/03-model-speed-and-day-factor.md new file mode 100644 index 0000000..6b56401 --- /dev/null +++ b/.scratch/generator-model-time-startup-history/issues/03-model-speed-and-day-factor.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` diff --git a/.scratch/generator-model-time-startup-history/issues/04-state-v2-model-resume.md b/.scratch/generator-model-time-startup-history/issues/04-state-v2-model-resume.md new file mode 100644 index 0000000..57f618b --- /dev/null +++ b/.scratch/generator-model-time-startup-history/issues/04-state-v2-model-resume.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 diff --git a/.scratch/generator-model-time-startup-history/issues/05-startup-history-backfill-to-clickhouse.md b/.scratch/generator-model-time-startup-history/issues/05-startup-history-backfill-to-clickhouse.md new file mode 100644 index 0000000..554c5f8 --- /dev/null +++ b/.scratch/generator-model-time-startup-history/issues/05-startup-history-backfill-to-clickhouse.md @@ -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` diff --git a/.scratch/generator-model-time-startup-history/issues/06-generated-history-as-analytics-source.md b/.scratch/generator-model-time-startup-history/issues/06-generated-history-as-analytics-source.md new file mode 100644 index 0000000..fefb941 --- /dev/null +++ b/.scratch/generator-model-time-startup-history/issues/06-generated-history-as-analytics-source.md @@ -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 diff --git a/.scratch/handoffs/2026-06-14-generator-model-time-startup-history-issues.md b/.scratch/handoffs/2026-06-14-generator-model-time-startup-history-issues.md new file mode 100644 index 0000000..a844b09 --- /dev/null +++ b/.scratch/handoffs/2026-06-14-generator-model-time-startup-history-issues.md @@ -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.