docs(generator): проведён триаж бэклога фичи, задачи 01-06 закрыты
- Зачем:
- follow-up задачи после ревью 2026-06-14 лежали без триажа; решения по
артефакту, громкому отказу и интерфейсу приняты 2026-07-04 и должны
попасть в задачи до передачи исполнителю.
- Что:
- задачи 07 (миграция курса) и 08 (артефакт) поменяны местами — номера
отражают порядок; ссылки обновлены.
- 07 (артефакт + runbook) дооформлен: импорт строго через Kafka (напрямую
в ClickHouse не пишет), громкий отказ при несовместимом state с правкой
спеки, граница runbook «использование, не устройство»; ready-for-agent.
- 08 дооформлен: устройство генератора вне пути менти, реальный объём
(make data во всех уроках 00-05), демо вне скоупа; ready-for-agent.
- новые задачи: 11 глаголы/длительность/профили (после 07, до 12),
12 Airflow-DAG как пульт (приоритет поднят), 13 доливка (после 09).
- задачи 01-06 переведены в done (стояли ошибочные ready-for-human);
PRD фичи дополнен списком задач 7-13 с порядком и зависимостями.
- Проверка:
- head -1 .scratch/generator-model-time-startup-history/issues/*.md;
grep по старым именам файлов ничего не находит вне handoff.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -74,6 +74,26 @@ Status: Draft
|
|||||||
6. `issues/06-generated-history-as-analytics-source.md` — штатный путь стенда
|
6. `issues/06-generated-history-as-analytics-source.md` — штатный путь стенда
|
||||||
переводится на стартовую историю как источник аналитики.
|
переводится на стартовую историю как источник аналитики.
|
||||||
|
|
||||||
|
Дополнено по итогам независимого ревью (2026-06-14) и триажа (2026-07-04) —
|
||||||
|
номера отражают рекомендуемый порядок внутри веток зависимостей:
|
||||||
|
|
||||||
|
7. `issues/07-startup-history-portable-artifact-and-usage-docs.md` —
|
||||||
|
портативный артефакт (импорт через Kafka, не напрямую в ClickHouse),
|
||||||
|
громкий отказ при несовместимом state, runbook.
|
||||||
|
8. `issues/08-migrate-course-from-archive-seed.md` — миграция учебных
|
||||||
|
материалов на генерацию; после задачи 7 (уроки ссылаются на runbook).
|
||||||
|
9. `issues/09-seam-browser-fixture-not-preserved.md` — дефект: браузерная
|
||||||
|
фактура не переживает восстановление визита на стыке. Независим, можно
|
||||||
|
параллельно.
|
||||||
|
10. `issues/10-dashboard-geo-map-readability.md` — читаемость гео-карты
|
||||||
|
дашборда. Независим, можно параллельно.
|
||||||
|
11. `issues/11-generator-launch-verbs-and-profiles.md` — глаголы, длительность
|
||||||
|
и профили запуска; после задачи 7, до задачи 12.
|
||||||
|
12. `issues/12-generator-control-dag.md` — Airflow-DAG как пульт генератора;
|
||||||
|
после задачи 11 (оборачивает глаголы).
|
||||||
|
13. `issues/13-backfill-top-up-from-snapshot.md` — доливка истории от слепка;
|
||||||
|
без приоритета, после задачи 9 (доливка тиражирует стыки восстановления).
|
||||||
|
|
||||||
## Контрольные точки
|
## Контрольные точки
|
||||||
|
|
||||||
- После задачи 3 нужен внешний review gate по сквозному инварианту времени:
|
- После задачи 3 нужен внешний review gate по сквозному инварианту времени:
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
Status: ready-for-human
|
Status: done
|
||||||
|
|
||||||
# Контракт модельного времени и стартовой истории
|
# Контракт модельного времени и стартовой истории
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Status: ready-for-human
|
Status: done
|
||||||
|
|
||||||
# Модельное время до ClickHouse
|
# Модельное время до ClickHouse
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
Status: ready-for-human
|
Status: done
|
||||||
|
|
||||||
# ×K и дневной коэффициент по модельному времени
|
# ×K и дневной коэффициент по модельному времени
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Status: ready-for-human
|
Status: done
|
||||||
|
|
||||||
# Восстановление state v2 от модельной точки
|
# Восстановление state v2 от модельной точки
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
Status: ready-for-human
|
Status: done
|
||||||
|
|
||||||
# Стартовая история до ClickHouse
|
# Стартовая история до ClickHouse
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
Status: ready-for-human
|
Status: done
|
||||||
|
|
||||||
# Стартовая история как источник аналитики
|
# Стартовая история как источник аналитики
|
||||||
|
|
||||||
@@ -197,7 +197,7 @@ Superset technical check:
|
|||||||
|
|
||||||
Follow-up:
|
Follow-up:
|
||||||
|
|
||||||
- `.scratch/generator-model-time-startup-history/issues/07-migrate-course-from-archive-seed.md`
|
- `.scratch/generator-model-time-startup-history/issues/08-migrate-course-from-archive-seed.md`
|
||||||
— миграция учебных материалов с архивного сида на генерацию.
|
— миграция учебных материалов с архивного сида на генерацию.
|
||||||
|
|
||||||
## Риски и что не проверено
|
## Риски и что не проверено
|
||||||
|
|||||||
-40
@@ -1,40 +0,0 @@
|
|||||||
Status: needs-triage
|
|
||||||
|
|
||||||
# Миграция учебных материалов с архивного сида на генерацию
|
|
||||||
|
|
||||||
## Parent
|
|
||||||
|
|
||||||
`.scratch/generator-model-time-startup-history/PRD.md`
|
|
||||||
|
|
||||||
## Why
|
|
||||||
|
|
||||||
После перевода штатного аналитического контура на стартовую историю генератора
|
|
||||||
часть учебных материалов всё ещё описывает `data/*.jsonl` как основной источник
|
|
||||||
данных стенда. Это нельзя править внутри issue 06: потребуется пройти уроки и
|
|
||||||
сохранить понятный учебный путь.
|
|
||||||
|
|
||||||
## What to build
|
|
||||||
|
|
||||||
Обновить курс и демо-материалы так, чтобы основной путь был:
|
|
||||||
|
|
||||||
```text
|
|
||||||
startup-history/backfill -> Kafka -> STG -> ODS -> DDS -> DM -> Superset
|
|
||||||
```
|
|
||||||
|
|
||||||
Архивный `data/*.jsonl` оставить только как временную фактуру генератора.
|
|
||||||
|
|
||||||
## Acceptance criteria
|
|
||||||
|
|
||||||
- [ ] `docs/course/` больше не ведёт ученика через `make data` или `kafka_load`
|
|
||||||
как основной путь получения аналитических данных.
|
|
||||||
- [ ] Уроки явно объясняют, что `data/*.jsonl` пока остаётся кладовкой значений
|
|
||||||
для генератора, а не источником аналитического контура.
|
|
||||||
- [ ] Демо-шпаргалки и тест-план согласованы с новым штатным путём запуска.
|
|
||||||
- [ ] Если для уроков нужны новые скриншоты или ручная оценка dashboard, это
|
|
||||||
вынесено в HITL-приёмку.
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
Найденные места для начала: `docs/course/PRD.md`,
|
|
||||||
`docs/course/lessons/06_superset_bi.md`, `docs/DEMO_CHEATSHEET_5MIN.md`,
|
|
||||||
`docs/DEMO_SCRIPT_10_15MIN.md`, `docs/TEST_PLAN.md`.
|
|
||||||
+117
@@ -0,0 +1,117 @@
|
|||||||
|
Status: ready-for-agent
|
||||||
|
|
||||||
|
# Портативный артефакт стартовой истории и runbook по стенду
|
||||||
|
|
||||||
|
## Parent
|
||||||
|
|
||||||
|
`.scratch/generator-model-time-startup-history/PRD.md`
|
||||||
|
|
||||||
|
## Why
|
||||||
|
|
||||||
|
Сейчас стартовая история персистится только в Kafka compact-топиках
|
||||||
|
(`generator_state`, `generator_startup_history_manifest`) и в ClickHouse. Чистая
|
||||||
|
пересборка стенда (`make generated-history-analytics` делает `down -v`) каждый раз
|
||||||
|
**заново генерирует** backfill. Портативного файла-артефакта, который можно
|
||||||
|
сгенерировать один раз и быстро восстановить на чистом стенде без запуска
|
||||||
|
генератора, нет.
|
||||||
|
|
||||||
|
Из-за этого неудобно: мгновенно сбросить стенд, держать длинную стартовую
|
||||||
|
историю (2+ суток, чтобы суточная волна повторялась на графике) без повторной
|
||||||
|
генерации. Сейчас «дёшево» только live-возобновление из слепка и перезапуск без
|
||||||
|
`down -v`; полный сброс требует регенерации.
|
||||||
|
|
||||||
|
Этот пункт работает на главную цель: если стенд поднимается одной командой и есть
|
||||||
|
короткий runbook, генератор остаётся скрытой инфраструктурой и менти не нужно
|
||||||
|
знать его устройство. Развилка курса «урок про генератор vs скрытая
|
||||||
|
инфраструктура» уже закрыта в пользу скрытой инфраструктуры
|
||||||
|
(`docs/course/PRD.md` §7, 2026-07-04) — эта задача обеспечивает решению опору.
|
||||||
|
|
||||||
|
## What to build
|
||||||
|
|
||||||
|
- **Экспорт** стартовой истории в портативный файл-артефакт: события (в формате
|
||||||
|
сообщений топиков) плюс слепок состояния плюс манифест — один связный набор,
|
||||||
|
чтобы не смешать `GEN_SEED`, `T0`, `T_end` и настройки генерации.
|
||||||
|
- **Импорт** (решение 2026-07-04): воспроизвести события артефакта в Kafka-топики
|
||||||
|
и вернуть слепок с манифестом в служебные compact-топики. **Напрямую в
|
||||||
|
ClickHouse импорт не пишет ничего**: стенд наполняется штатным путём
|
||||||
|
(Kafka engine + MV -> STG, батч-ETL -> витрины). Так не появляется обходного
|
||||||
|
пути данных, каждый импорт заодно прогоняет весь пайплайн, а менти видит,
|
||||||
|
как пустой стенд наполняется изучаемыми механизмами. Live продолжает с `T_end`.
|
||||||
|
- **Громкий отказ при несовместимом state** (решение 2026-07-04, пересмотр
|
||||||
|
правила спеки). Различать два случая. Нет состояния или оно повреждено ->
|
||||||
|
чистый старт с предупреждением (как сейчас, оставить). Состояние есть и
|
||||||
|
читается, но настройки несовместимы при `GEN_STATE_RESET=false` (оператор
|
||||||
|
намерен продолжить) -> жёсткое падение с указанием разошедшихся полей
|
||||||
|
(`seed`/`T0`/`timezone`/`speed`) и подсказкой выставить `GEN_STATE_RESET=true`,
|
||||||
|
если новый мир нужен осознанно. Текущее тихое поведение — `service.py:217-220`.
|
||||||
|
Правка идёт вместе с обновлением
|
||||||
|
`docs/specs/2026-06-14-generator-model-time-and-startup-history.md`.
|
||||||
|
- **Runbook «как пользоваться стендом на генерации»**: как сгенерировать,
|
||||||
|
сохранить, восстановить, выбрать длительность стартовой истории; что дёшево
|
||||||
|
(live-возобновление, перезапуск без чистки), а что требует регенерации.
|
||||||
|
- Новые команды экспорта/импорта делать в стиле глаголов (явное действие одной
|
||||||
|
командой), а не новыми комбинациями env-переменных.
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] Есть команда экспорта: стартовая история -> портативный файл-артефакт
|
||||||
|
(события + слепок + манифест) одним связным набором.
|
||||||
|
- [ ] Есть команда импорта: на чистом стенде артефакт воспроизводится в Kafka
|
||||||
|
(события + служебные compact-топики) **без запуска генерации**; напрямую в
|
||||||
|
ClickHouse импорт не пишет. После штатного ETL контрольные числа в ClickHouse
|
||||||
|
совпадают с манифестом и исходной генерацией.
|
||||||
|
- [ ] После импорта live продолжает с `T_end`: без дублей на границе и без
|
||||||
|
смешения миров.
|
||||||
|
- [ ] Сохранено антисмешивание: импорт отвергает артефакт, несовместимый по
|
||||||
|
манифесту (`GEN_SEED`, `T0`, `T_end`, настройки генерации, версия state).
|
||||||
|
- [ ] Громкий отказ: живое читаемое состояние + несовместимые настройки при
|
||||||
|
намерении продолжить -> падение с перечислением разошедшихся полей и
|
||||||
|
подсказкой; нет состояния или повреждено -> чистый старт с предупреждением
|
||||||
|
(как сейчас). Спека обновлена в этом же изменении.
|
||||||
|
- [ ] Runbook описывает генерацию один раз, дешёвое восстановление, выбор
|
||||||
|
длительности и то, что переживает перезапуск, а что требует регенерации.
|
||||||
|
- [ ] Runbook — про **использование**, устройство генератора в нём не
|
||||||
|
объясняется; за конструкцией он отсылает к `generator/README.md` и
|
||||||
|
`docs/specs/`.
|
||||||
|
- [ ] Документы запуска (`README.md`, `docs/OPERATIONS.md`,
|
||||||
|
`generator/README.md`) ссылаются на runbook.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Опирается на спеку `docs/specs/2026-06-14-generator-model-time-and-startup-history.md`,
|
||||||
|
разделы «Манифест стартовой истории» и «Повторяемая проверка в ClickHouse».
|
||||||
|
- Спека уже упоминала будущий runbook «проверка генератора на стенде» — этот
|
||||||
|
issue его и закрывает, расширяя до полного цикла «генерация — сохранение —
|
||||||
|
восстановление».
|
||||||
|
- Откуда экспорту брать события — решить при реализации и зафиксировать в
|
||||||
|
спеке/runbook. Кандидаты: писать файл артефакта прямо при backfill (вторая
|
||||||
|
копия рядом с публикацией в Kafka), вычитать топики событий (учесть retention)
|
||||||
|
или выгрузить из STG (следить за точностью формата сообщений). Критерий
|
||||||
|
выбора: артефакт должен байт в байт воспроизводить сообщения топиков.
|
||||||
|
- Рекомендуемый режим ревью по coordinator-loop: **гейт** (state, сериализация,
|
||||||
|
формат данных, правка спеки — всё из порогов риска).
|
||||||
|
- Связано с `08-migrate-course-from-archive-seed.md`: миграция уроков идёт после
|
||||||
|
этой задачи и будет ссылаться на runbook отсюда (номера отражают порядок,
|
||||||
|
переставлены 2026-07-04).
|
||||||
|
|
||||||
|
## Идеи интерфейса — решения (2026-07-04)
|
||||||
|
|
||||||
|
Бывший раздел «на будущее, не решено» разобран с пользователем. Судьба идей:
|
||||||
|
|
||||||
|
- **Громкий отказ при несовместимом state** — включён в эту задачу
|
||||||
|
(см. What to build и критерии).
|
||||||
|
- **Глаголы / длительность / профили** — отдельная задача
|
||||||
|
`11-generator-launch-verbs-and-profiles.md`, делать **после этой и до
|
||||||
|
DAG-пульта**: чистый интерфейс «под капотом» делает DAG тонкой обёрткой с
|
||||||
|
простыми и понятными параметрами.
|
||||||
|
- **Airflow-DAG как пульт генератора** — приоритет поднят (пользователь,
|
||||||
|
2026-07-04): это будущий основной человеческий интерфейс стенда — «слишком
|
||||||
|
сложно» лечится формой в веб-UI, а не только runbook'ом. Отдельная задача
|
||||||
|
`12-generator-control-dag.md`, делать после задачи 11.
|
||||||
|
- **Доливка прошлого кусочком** — отдельная задача
|
||||||
|
`13-backfill-top-up-from-snapshot.md`, без приоритета.
|
||||||
|
|
||||||
|
## Blocked by
|
||||||
|
|
||||||
|
- `.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`
|
||||||
+78
@@ -0,0 +1,78 @@
|
|||||||
|
Status: ready-for-agent
|
||||||
|
|
||||||
|
# Миграция учебных материалов с архивного сида на генерацию
|
||||||
|
|
||||||
|
## Parent
|
||||||
|
|
||||||
|
`.scratch/generator-model-time-startup-history/PRD.md`
|
||||||
|
|
||||||
|
## Why
|
||||||
|
|
||||||
|
После перевода штатного аналитического контура на стартовую историю генератора
|
||||||
|
часть учебных материалов всё ещё описывает `data/*.jsonl` как основной источник
|
||||||
|
данных стенда. Это нельзя править внутри issue 06: потребуется пройти уроки и
|
||||||
|
сохранить понятный учебный путь.
|
||||||
|
|
||||||
|
Развилка «отдельный урок про генератор vs скрытая инфраструктура» закрыта
|
||||||
|
(2026-07-04, `docs/course/PRD.md` §7): **отдельного урока не будет, генератор —
|
||||||
|
скрытая инфраструктура**. Устройство генератора — это разработка бэкенда и
|
||||||
|
математика, не инженерия данных; в цели курса не попадает. Уроки адаптируем,
|
||||||
|
не вводя марковские цепи и сложный Python в путь менти.
|
||||||
|
|
||||||
|
## What to build
|
||||||
|
|
||||||
|
Обновить курс и связанные материалы (тест-план) так, чтобы основной путь был:
|
||||||
|
|
||||||
|
```text
|
||||||
|
startup-history/backfill -> Kafka -> STG -> ODS -> DDS -> DM -> Superset
|
||||||
|
```
|
||||||
|
|
||||||
|
Архивный `data/*.jsonl` оставить только как временную фактуру генератора.
|
||||||
|
Генератор в уроках подаётся как готовый источник данных стенда («откуда берутся
|
||||||
|
данные»), без погружения в его устройство.
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] `docs/course/` больше не ведёт ученика через `make data` или `kafka_load`
|
||||||
|
как основной путь получения аналитических данных.
|
||||||
|
- [ ] Уроки явно объясняют, что `data/*.jsonl` пока остаётся кладовкой значений
|
||||||
|
для генератора, а не источником аналитического контура.
|
||||||
|
- [ ] Уроки не вводят устройство генератора (марковская модель, внутренний
|
||||||
|
Python) в путь менти: генератор упоминается только как готовый источник данных.
|
||||||
|
- [ ] Тест-план согласован с новым штатным путём запуска.
|
||||||
|
- [ ] Если для уроков нужны новые скриншоты или ручная оценка dashboard, это
|
||||||
|
вынесено в HITL-приёмку.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
Реальный объём больше, чем кажется: `make data` вплетён во **все** уроки 00–05,
|
||||||
|
а не только в урок 06 (проверка 2026-07-04, `grep -rn "make data" docs/course/`):
|
||||||
|
|
||||||
|
- `docs/course/README.md` — быстрый старт через `LIMIT=50 make data`;
|
||||||
|
- `lessons/00_kafka_intro.md` — `make data` играет роль трекера, на нём построен
|
||||||
|
весь разбор партиций и offset'ов;
|
||||||
|
- `lessons/01–05` — `LIMIT=50 make data` в запуске, «полном сбросе» и таблицах
|
||||||
|
проверок;
|
||||||
|
- `docs/TEST_PLAN.md` — сценарии на старом пути.
|
||||||
|
|
||||||
|
Тонкое место — урок 00: там ручная заливка используется как учебный приём
|
||||||
|
(наглядно видно сообщения в топике). Решить при миграции, чем её заменить, не
|
||||||
|
потеряв наглядность; критерий приёмки запрещает `make data` как **основной путь
|
||||||
|
аналитики**, а не как локальный демонстрационный приём внутри урока.
|
||||||
|
|
||||||
|
Схема потока в `docs/course/PRD.md` §1 уже обновлена (поправка 2026-07-04) — PRD
|
||||||
|
дополнительно править не нужно.
|
||||||
|
|
||||||
|
Демо-материалов в скоупе нет: демо-употребление стенда устарело (демо выросло в
|
||||||
|
отдельный проект), шпаргалки удалены из репозитория 2026-07-04 (см. поправку в
|
||||||
|
шапке `docs/course/PRD.md`).
|
||||||
|
|
||||||
|
## Blocked by
|
||||||
|
|
||||||
|
- Жёстких блокеров нет: штатный путь (`make generated-history-analytics`) уже
|
||||||
|
существует, уроки можно вести через него.
|
||||||
|
- Мягкая зависимость от
|
||||||
|
`07-startup-history-portable-artifact-and-usage-docs.md`: runbook из issue 07
|
||||||
|
изменит команды запуска и восстановления стенда, а уроки будут на него
|
||||||
|
ссылаться. Делать эту задачу после него, иначе уроки придётся править дважды
|
||||||
|
(номера уже отражают порядок: 07 -> 08, переставлены 2026-07-04).
|
||||||
-96
@@ -1,96 +0,0 @@
|
|||||||
Status: needs-triage
|
|
||||||
|
|
||||||
# Портативный артефакт стартовой истории и runbook по стенду
|
|
||||||
|
|
||||||
## Parent
|
|
||||||
|
|
||||||
`.scratch/generator-model-time-startup-history/PRD.md`
|
|
||||||
|
|
||||||
## Why
|
|
||||||
|
|
||||||
Сейчас стартовая история персистится только в Kafka compact-топиках
|
|
||||||
(`generator_state`, `generator_startup_history_manifest`) и в ClickHouse. Чистая
|
|
||||||
пересборка стенда (`make generated-history-analytics` делает `down -v`) каждый раз
|
|
||||||
**заново генерирует** backfill. Портативного файла-артефакта, который можно
|
|
||||||
сгенерировать один раз и быстро залить на чистый ClickHouse без запуска
|
|
||||||
генератора, нет.
|
|
||||||
|
|
||||||
Из-за этого неудобно: раздать готовое демо, мгновенно сбросить стенд, держать
|
|
||||||
длинную стартовую историю (2+ суток, чтобы суточная волна повторялась на графике)
|
|
||||||
без повторной генерации. Сейчас «дёшево» только live-возобновление из слепка и
|
|
||||||
перезапуск без `down -v`; полный сброс требует регенерации.
|
|
||||||
|
|
||||||
Этот пункт работает на главную цель: если стенд поднимается одной командой и есть
|
|
||||||
короткий runbook, генератор становится скрытой инфраструктурой и менти не нужно
|
|
||||||
знать его устройство. Связано с открытым вопросом курса про отдельный урок по
|
|
||||||
генератору (см. `docs/course/PRD.md`, §7).
|
|
||||||
|
|
||||||
## What to build
|
|
||||||
|
|
||||||
- Экспорт стартовой истории в портативный файл-артефакт: события плюс слепок
|
|
||||||
состояния плюс манифест — один связный набор, чтобы не смешать `GEN_SEED`,
|
|
||||||
`T0`, `T_end` и настройки генерации.
|
|
||||||
- Импорт: залить артефакт на чистый ClickHouse и Kafka без прогона генерации;
|
|
||||||
live-режим продолжает с `T_end`.
|
|
||||||
- Runbook «как пользоваться стендом на генерации»: как сгенерировать, сохранить,
|
|
||||||
восстановить, выбрать длительность стартовой истории; что дёшево
|
|
||||||
(live-возобновление, перезапуск без чистки), а что требует регенерации.
|
|
||||||
|
|
||||||
## Acceptance criteria
|
|
||||||
|
|
||||||
- [ ] Есть команда экспорта: backfill -> портативный файл-артефакт
|
|
||||||
(события + слепок + манифест).
|
|
||||||
- [ ] Есть команда импорта: артефакт -> чистый ClickHouse без запуска генератора;
|
|
||||||
контрольные числа манифеста и ClickHouse совпадают с исходной генерацией.
|
|
||||||
- [ ] Сохранено антисмешивание: импорт отвергает артефакт, несовместимый по
|
|
||||||
манифесту (`GEN_SEED`, `T0`, `T_end`, настройки генерации, версия state).
|
|
||||||
- [ ] Runbook описывает генерацию один раз, дешёвое восстановление, выбор
|
|
||||||
длительности и то, что переживает перезапуск, а что требует регенерации.
|
|
||||||
- [ ] Документы запуска (`README.md`, `docs/OPERATIONS.md`,
|
|
||||||
`generator/README.md`) ссылаются на runbook.
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
- Опирается на спеку `docs/specs/2026-06-14-generator-model-time-and-startup-history.md`,
|
|
||||||
разделы «Манифест стартовой истории» и «Повторяемая проверка в ClickHouse».
|
|
||||||
- Спека уже упоминала будущий runbook «проверка генератора на стенде» — этот
|
|
||||||
issue его и закрывает, расширяя до полного цикла «генерация — сохранение —
|
|
||||||
восстановление».
|
|
||||||
- Связано с `07-migrate-course-from-archive-seed.md`: удобный стенд упрощает выбор
|
|
||||||
«адаптировать уроки», а не писать тяжёлый урок про генератор.
|
|
||||||
|
|
||||||
## Идеи интерфейса (на будущее, не решено)
|
|
||||||
|
|
||||||
Запуск сейчас недружелюбный: поведение собирается из ~10 связанных env-переменных,
|
|
||||||
`T_end` задаётся абсолютной меткой вместо длительности, а несовпадение настроек при
|
|
||||||
live-продолжении даёт тихий «свежий старт» (warning в лог, общее сообщение, без
|
|
||||||
указания разошедшегося поля — `service.py:217-220`). Идеи, как сделать удобнее:
|
|
||||||
|
|
||||||
- **Глаголы вместо матрицы флагов:** явные `backfill` / `continue` / `reset`, а не
|
|
||||||
комбинация `GEN_RUN_MODE` + `GEN_STATE_RESET`.
|
|
||||||
- **Длительность как длительность и профили:** `HISTORY_DURATION=2d` вместо ручного
|
|
||||||
расчёта `T_end`; именованные профили вместо повторения блока из ~10 переменных.
|
|
||||||
- **Громкий и адресный отказ при несовпадении (пересмотр решения спеки).** Сейчас
|
|
||||||
при `GEN_STATE_RESET=false` несовместимый по настройкам state молча ведёт к чистому
|
|
||||||
старту (`service.py:217-220`) — это сознательный выбор спеки ради устойчивости.
|
|
||||||
Предложение: различать два случая. Нет состояния или оно повреждено -> чистый старт
|
|
||||||
с предупреждением (как сейчас, оставить). Состояние есть и читается, но настройки
|
|
||||||
несовместимы при `GEN_STATE_RESET=false` (оператор намерен продолжить) -> **жёсткое
|
|
||||||
падение** с указанием разошедшихся полей (`seed`/`T0`/`timezone`/`speed`) и подсказкой
|
|
||||||
выставить `GEN_STATE_RESET=true`, если новый мир нужен осознанно. Меняет правило
|
|
||||||
спеки «несовместимо -> чистый старт», поэтому правка идёт вместе с обновлением
|
|
||||||
`docs/specs/2026-06-14-generator-model-time-and-startup-history.md`.
|
|
||||||
- **Доливка прошлого кусочком:** backfill, продолжающий слепок от `T_end` (сейчас
|
|
||||||
backfill всегда стартует с чистого состояния от `T0`, `service.py:178-185`).
|
|
||||||
- **Airflow DAG как пульт запуска (идея пользователя, 2026-06-14):** обернуть операции
|
|
||||||
генератора в параметризованный DAG (params: режим, `T0`, длительность, скорость,
|
|
||||||
seed) — UI, валидация настроек против манифеста до запуска, повторные попытки,
|
|
||||||
наглядность. Хорошо ложится на ограниченный backfill/доливку (конечная задача);
|
|
||||||
непрерывный live — это долгоживущий сервис compose, DAG его скорее стартует/останавливает,
|
|
||||||
чем держит внутри таска. Бонус: такой DAG сам по себе учебный (тема урока 4 —
|
|
||||||
оркестрация Airflow), что ближе к цели курса, чем устройство генератора.
|
|
||||||
|
|
||||||
## Blocked by
|
|
||||||
|
|
||||||
- `.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`
|
|
||||||
+58
@@ -0,0 +1,58 @@
|
|||||||
|
Status: ready-for-agent
|
||||||
|
|
||||||
|
# Глаголы, длительность и профили запуска генератора
|
||||||
|
|
||||||
|
## Parent
|
||||||
|
|
||||||
|
`.scratch/generator-model-time-startup-history/PRD.md`
|
||||||
|
|
||||||
|
## Why
|
||||||
|
|
||||||
|
Запуск генератора недружелюбный: поведение собирается из ~10 связанных
|
||||||
|
env-переменных, а смысл запуска — из их комбинации (`GEN_RUN_MODE` +
|
||||||
|
`GEN_STATE_RESET`). Конец истории задаётся абсолютной меткой `GEN_MODEL_T_END`,
|
||||||
|
которую оператор считает в уме от `T0`.
|
||||||
|
|
||||||
|
Задача — дать чистый интерфейс «под капотом» перед DAG-пультом
|
||||||
|
(`12-generator-control-dag.md`): если команды простые и говорящие, DAG
|
||||||
|
становится тонкой обёрткой с понятными параметрами, а не переводчиком
|
||||||
|
формы в матрицу переменных (решение пользователя, 2026-07-04).
|
||||||
|
|
||||||
|
## What to build
|
||||||
|
|
||||||
|
- **Глаголы вместо матрицы флагов:** явные команды `backfill` / `continue` /
|
||||||
|
`reset` (make-цели или аргументы запуска), а не комбинация
|
||||||
|
`GEN_RUN_MODE` + `GEN_STATE_RESET`. Старые переменные могут остаться как
|
||||||
|
низкоуровневый механизм, но документированный путь — глаголы.
|
||||||
|
- **Длительность вместо абсолютной метки:** задавать конец истории как
|
||||||
|
длительность от `T0` (например, `2d`), расчёт `T_end` — внутри.
|
||||||
|
- **Именованные профили** вместо повторения блока переменных: минимум два —
|
||||||
|
быстрый проверочный (6 часов, текущий дефолт CI) и «с суточной волной»
|
||||||
|
(2+ суток).
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] Стартовую историю на 2 суток можно получить одной командой с глаголом и
|
||||||
|
длительностью/профилем, без ручного расчёта `T_end` и без выставления
|
||||||
|
`GEN_RUN_MODE`/`GEN_STATE_RESET` вручную.
|
||||||
|
- [ ] Глаголы не меняют семантику режимов: за `backfill`/`continue`/`reset`
|
||||||
|
стоит тот же контракт модельного времени и state, что в спеке
|
||||||
|
`docs/specs/2026-06-14-generator-model-time-and-startup-history.md`.
|
||||||
|
- [ ] Профили покрывают быстрый проверочный прогон и прогон с суточной волной;
|
||||||
|
выбранный профиль виден в логах/манифесте.
|
||||||
|
- [ ] Runbook (из задачи 07) и документы запуска переведены на глаголы и
|
||||||
|
профили; старый способ через переменные упомянут как низкоуровневый.
|
||||||
|
- [ ] Существующие тесты генератора проходят; поведение по умолчанию
|
||||||
|
(CI-профиль) не изменилось.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Это интерфейсный слой над существующей механикой: генерацию, state и
|
||||||
|
антисмешивание не менять.
|
||||||
|
- Вместе с глаголами не забыть команды экспорта/импорта из задачи 07 — они
|
||||||
|
уже в стиле глаголов, привести всё к одному стилю.
|
||||||
|
|
||||||
|
## Blocked by
|
||||||
|
|
||||||
|
- `07-startup-history-portable-artifact-and-usage-docs.md` — runbook и команды
|
||||||
|
экспорта/импорта появляются там; эта задача переводит их на единый стиль.
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
Status: needs-triage
|
||||||
|
|
||||||
|
# Airflow-DAG — пульт управления генератором
|
||||||
|
|
||||||
|
## Parent
|
||||||
|
|
||||||
|
`.scratch/generator-model-time-startup-history/PRD.md`
|
||||||
|
|
||||||
|
## Why
|
||||||
|
|
||||||
|
Даже с runbook и глаголами управление генератором остаётся консольным. Идея
|
||||||
|
(пользователь, 2026-06-14; приоритет поднят 2026-07-04): параметризованный DAG
|
||||||
|
в Airflow как основной человеческий интерфейс стенда — форма в веб-UI, где
|
||||||
|
выбираются режим, длительность/профиль, seed, скорость. Плюсы: валидация
|
||||||
|
настроек против манифеста ещё до запуска, повторные попытки, наглядный статус.
|
||||||
|
|
||||||
|
Учебный бонус: такой DAG сам по себе учебный материал — живой пример
|
||||||
|
параметризованной оркестрации (тема урока 4), что ближе к цели курса, чем
|
||||||
|
устройство генератора.
|
||||||
|
|
||||||
|
## What to build
|
||||||
|
|
||||||
|
Черновой контур (уточнить после задач 07 и 11):
|
||||||
|
|
||||||
|
- Параметризованный DAG с операциями: создать стартовую историю (backfill),
|
||||||
|
экспортировать артефакт, импортировать артефакт, сбросить мир.
|
||||||
|
- Валидация параметров против манифеста **до** запуска операции; при
|
||||||
|
несовместимости — понятная ошибка в UI, а не тихий новый мир.
|
||||||
|
- Конечные операции (backfill, экспорт, импорт, сброс) — таски DAG.
|
||||||
|
Непрерывный live — долгоживущий сервис compose: DAG его стартует и
|
||||||
|
останавливает, но не держит внутри таска.
|
||||||
|
- Под капотом DAG вызывает глаголы из задачи 11, а не собирает env-матрицу.
|
||||||
|
|
||||||
|
## Acceptance criteria (черновые, дооформить после 07 и 11)
|
||||||
|
|
||||||
|
- [ ] Стартовую историю выбранной длительности можно создать из веб-UI Airflow,
|
||||||
|
не выставляя переменных окружения вручную.
|
||||||
|
- [ ] Несовместимые параметры отклоняются до запуска с указанием разошедшихся
|
||||||
|
полей.
|
||||||
|
- [ ] Импорт/экспорт артефакта доступны как операции DAG.
|
||||||
|
- [ ] Runbook дополнен разделом «пульт в Airflow» как основным путём.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Проверить API параметров DAG (params/Datasets) через MCP Context7 по правилу
|
||||||
|
репозитория: спорные API Airflow сверять с актуальной документацией.
|
||||||
|
- DAG должен остаться понятным менти: это витрина оркестрации, не место для
|
||||||
|
хитрой логики. Сложность — в глаголах генератора (задача 11), не здесь.
|
||||||
|
|
||||||
|
## Blocked by
|
||||||
|
|
||||||
|
- `07-startup-history-portable-artifact-and-usage-docs.md` — операции
|
||||||
|
экспорта/импорта появляются там.
|
||||||
|
- `11-generator-launch-verbs-and-profiles.md` — DAG оборачивает глаголы и
|
||||||
|
профили; без них он превращается в переводчик формы в env-матрицу.
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
Status: needs-triage
|
||||||
|
|
||||||
|
# Доливка стартовой истории кусочком от слепка
|
||||||
|
|
||||||
|
## Parent
|
||||||
|
|
||||||
|
`.scratch/generator-model-time-startup-history/PRD.md`
|
||||||
|
|
||||||
|
## Why
|
||||||
|
|
||||||
|
Сейчас backfill всегда стартует с чистого состояния от `T0`
|
||||||
|
(`service.py:178-185`): удлинить существующую историю нельзя — есть 2 суток,
|
||||||
|
нужно 7, генерируй все 7 заново. Идея — «долить» продолжение от сохранённого
|
||||||
|
слепка `T_end`.
|
||||||
|
|
||||||
|
Приоритет низкий (решение 2026-07-04): с портативным артефактом
|
||||||
|
(задача 07) длинную историю можно сгенерировать один раз и переиспользовать,
|
||||||
|
так что потребность в доливке может и не возникнуть. Вернуться, если возникнет.
|
||||||
|
|
||||||
|
## What to build
|
||||||
|
|
||||||
|
- Режим backfill, продолжающий от слепка: новая порция истории от `T_end` до
|
||||||
|
нового `T_end'`, манифест обновляется.
|
||||||
|
|
||||||
|
## Acceptance criteria (черновые)
|
||||||
|
|
||||||
|
- [ ] Доливка продолжает мир слепка: без дублей и смешения на границе.
|
||||||
|
- [ ] Однородность визитов, переживших границу доливки, — включая per-event
|
||||||
|
браузерные поля (`dds.event`), см. дефект
|
||||||
|
`09-seam-browser-fixture-not-preserved.md`: доливка создаёт новые стыки,
|
||||||
|
тот же механизм восстановления.
|
||||||
|
- [ ] Манифест после доливки отражает новый `T_end'`; антисмешивание работает.
|
||||||
|
|
||||||
|
## Blocked by
|
||||||
|
|
||||||
|
- `09-seam-browser-fixture-not-preserved.md` — доливка тиражирует стыки
|
||||||
|
восстановления; сначала починить фактуру на стыке, иначе дефект размножится.
|
||||||
Reference in New Issue
Block a user