- Зачем:
- рамка задачи 13 пересмотрена: ценность доливки — кормление стенда
дневными батчами (урок и имитация жизни), а не удлинение истории;
- прогон пути менти 2026-07-07 показал, что runtime-гейт стыка
backfill->live нестабилен — красный/зелёный через раз.
- Что:
- задача 13 переписана под глагол next-day в generator_control:
сценарии, развилка реализации (срез артефакта против доливки от
слепка), закрыт вопрос про импорт частями (сейчас всё или ничего);
- добавлена задача 20 про нестабильную runtime-проверку стыка с
эмпирикой двух прогонов и гипотезами для диагноза.
- Проверка:
- два прогона make generated-history-runtime-check (красный 8/19,
затем зелёный) — зафиксированы в задаче 20.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
95 lines
7.3 KiB
Markdown
95 lines
7.3 KiB
Markdown
Status: needs-info
|
|
|
|
# Глагол next-day: собрать следующий модельный день
|
|
|
|
## Parent
|
|
|
|
`.scratch/generator-model-time-startup-history/PRD.md`
|
|
|
|
## Why
|
|
|
|
Рамка пересмотрена 2026-07-07 (обсуждение с пользователем). Было: «удлинить
|
|
готовую историю» (2 суток -> 7) — этот мотив закрыл портативный артефакт
|
|
(задача 07), приоритет был низкий. Стало: **режим кормления стенда порциями**.
|
|
Ценность не в длине истории, а в дискретности подачи:
|
|
|
|
- **Урок.** Менти триггерит «следующий день» -> в Kafka падает батч за новый
|
|
модельный день -> прогон `etl_pipeline` -> витрины и дашборды сдвинулись.
|
|
Полный цикл DWH виден за один шаг; повторяемо и управляемо, в отличие от
|
|
непрерывного live.
|
|
- **Имитация жизни.** Тот же механизм по расписанию (`@daily` или чаще) —
|
|
стенд «живёт»: мониторинги бегут, метрики копятся, нагрузка видна.
|
|
- Удлинение истории остаётся как частный случай (несколько next-day подряд).
|
|
|
|
## Интерфейс
|
|
|
|
Новый глагол `next-day` в существующем DAG `generator_control`
|
|
(`airflow/dags/generator_control_dag.py`), не отдельный DAG: менти уже знает,
|
|
где ручки генератора; pause-check `etl_pipeline` и guard чистого стенда
|
|
переиспользуются. Ручной триггер — для урока, расписание — для «жизни».
|
|
|
|
## Развилка реализации (решить до реализации)
|
|
|
|
Интерфейс `next-day` одинаков для двух начинок, начинку можно менять, не
|
|
трогая то, чему учим:
|
|
|
|
1. **Резать готовый артефакт на дневные порции.** История сгенерирована одним
|
|
прогоном (задача 07), швов нет вообще — границы дней внутри одного мира
|
|
естественные. Дёшево, если механизм импорта умеет подавать историю частями
|
|
(см. «Открытые вопросы»). Ограничение: горизонт равен длине артефакта.
|
|
2. **Доливка от слепка `T_end`.** Настоящая генерация продолжения. Нужна,
|
|
когда жизнь стенда должна быть неограниченной. Каждый батч добавляет шов;
|
|
restore-механизм общий с рестартом и закалён задачей 09, но открыт хвост
|
|
про запасную ветку рождения визита (см. критерии).
|
|
|
|
Разумный путь: вариант 1 как MVP, вариант 2 — когда упрёмся в конец артефакта
|
|
(возможно, отдельной задачей).
|
|
|
|
## Открытые вопросы (блокируют ready-for-agent)
|
|
|
|
- [x] Умеет ли текущий импорт артефакта (`startup-history-import`) подавать
|
|
историю частями? **Нет, «всё или ничего»** (проверено 2026-07-07):
|
|
скрипт требует чистый стенд (`import_startup_history_artifact.sh:50`,
|
|
`assert_stand_clean.sh`), CLI артефакта воспроизводит все топики целиком и
|
|
не имеет опций среза, а валидация жёстко связывает manifest и state
|
|
(`startup_history_artifact.py`, `_validate_manifest_state`). Для варианта 1
|
|
нужен новый режим импорта: срез по модельному дню, цепочка manifest'ов
|
|
вместо «manifest равен state», и ослабление guard'а чистого стенда для
|
|
последующих порций (граница по манифесту вместо пустоты). Нюанс: артефакт
|
|
хранит один state на конец полной истории, поэтому live-продолжение
|
|
возможно только после последней порции; промежуточные дни — batch-only
|
|
(для учебного сценария этого достаточно).
|
|
- [ ] Для варианта 2 — решение по запасной ветке рождения визита
|
|
(`generation.py`, ветка без донора-кандидата): либо закрепить проверкой,
|
|
что она не срабатывает, либо ограничить длину визита так, чтобы fallback
|
|
не менял фактуру на стыке. Унаследовано из прежней редакции задачи.
|
|
|
|
## Acceptance criteria (черновые)
|
|
|
|
- [ ] Глагол `next-day` в `generator_control`: батч ровно за один следующий
|
|
модельный день от текущей границы манифеста.
|
|
- [ ] Идемпотентность: повторный триггер того же дня — громкий отказ по
|
|
манифесту, а не второй мир и не дубли.
|
|
- [ ] Манифест двигает `T_end` атомарно; антисмешивание работает на **цепочке**
|
|
границ (30 батчей = 30 границ), проверки
|
|
(`scripts/check_generated_analytics.sh` и родня) расширены с одной границы
|
|
на цепочку.
|
|
- [ ] Учебный цикл целиком: после `next-day` прогон `etl_pipeline` даёт новые
|
|
строки в DM-витринах; проверка повторяемая, не разовая.
|
|
- [ ] Для варианта 2: визиты, пережившие границу батча, однородны по всем
|
|
per-event полям (браузер, referer, utm) — тот же класс проверки, что в
|
|
задаче 09.
|
|
|
|
## Blocked by
|
|
|
|
- Открытые вопросы выше (статус needs-info до их закрытия).
|
|
- Исторические блокеры закрыты: `15-world-boundary-after-cross-review.md`
|
|
(граница миров) и `17-trusted-checks-startup-history-superset.md`
|
|
(доверенные проверки) — done.
|
|
|
|
Исторический контекст: `09-seam-browser-fixture-not-preserved.md` — шов
|
|
рождается при любом прохождении мира через сериализованный state (рестарт,
|
|
сбой, доливка — один код восстановления); фикс 09 положил донора фактуры в
|
|
state и закрыл тихие fallback'и. Прежняя редакция этой задачи называлась
|
|
«Доливка стартовой истории кусочком от слепка».
|