docs(adr): решён пульт мира — работники, выключатель, контейнер

Зачем: модельный день прогоняется только руками, и владельцу нечем
проверять процессы стенда вживую. Этап 3 без дага не существует вовсе,
поэтому форму пульта и способ вызова генератора надо решить раньше.

Что: ADR 0009 — работники без расписания (`world_next_day` пачкой,
`world_live_day` в темпе) и выключатель `world_live` без своей работы,
ждущий дочерний прогон триггером; генератор зовётся `DockerOperator` в
каноническом контейнере, потому что в образе Airflow ему не жить
(Python 3.14 против 3.13); позиция ставится как «последний сыгранный + 1»,
и это правило вместо сторожа. Пакетная автоматика отложена, не отвергнута.
Расхождения внесены в спеку генератора: позицию ставит сыгравший, у живого
дня появился выключатель. В словарь добавлен «пульт мира».

Проверка: `make config-test` зелёный; API Airflow 3.3 (пауза и ручной
запуск, ожидание триггера по идентификатору прогона, привязка сенсора к
логической дате, `DockerOperator`) сверено через MCP Context7, версия
Python в образе — замером.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-13 12:23:43 +03:00
co-authored by Claude Opus 5
parent 9d43ff5489
commit aa4797ae93
3 changed files with 165 additions and 5 deletions
+8 -5
View File
@@ -105,7 +105,8 @@
- **Два режима движения по одной оси.** Пошаговый — базовый для лаб: старт
с эталонного снимка, дальше «прожить следующий день» — явное действие.
Живой день — текущий день проигрывается с ускорением, дашборд и мониторинг
«дышат»; включается по требованию, не постоянный фон.
«дышат»; включается по требованию постоянным фоном идёт, только пока
включён выключатель пульта ([ADR 0009](../adr/0009-world-control.md)).
- **Граница суток — единственный структурный шов.** Сессии режутся по ней,
дневная партиция самодостаточна; в конце модельного дня — слепок заказов.
День проживается целиком, полдня не бывает: недожитый из-за обрыва день
@@ -445,10 +446,12 @@
теперь есть.
- **Этап 5 (Airflow)**: живой день со стороны хранилища — обычный ETL-даг
по расписанию (~раз в 24 минуты); генератор не дорабатывается.
- **Этап 5, позиция на оси времени.** Проигрыватель состояния не хранит
(раздел 9), поэтому вести позицию — работа того, кто его зовёт. Живёт она
переменной Airflow: отсутствие переменной означает мир в стартовом
состоянии, заводит и двигает её только даг `next_day` и только по успеху.
- **Позиция на оси времени** (хвост отдан пульту мира раньше этапа 5 —
[ADR 0009](../adr/0009-world-control.md))**.** Проигрыватель состояния не
хранит (раздел 9), поэтому вести позицию — работа того, кто его зовёт. Живёт
она переменной Airflow: отсутствие переменной означает мир в стартовом
состоянии, а ставит её тот даг пульта, который сыграл день, — значением
«последний сыгранный + 1» и только по успеху.
Довод — генератор отдельная и заменяемая сущность, привязывать его к
хранилищу незачем, а `make clean` сносит том метаданных Airflow вместе с
данными ClickHouse, так что позиция и мир чистятся одной командой.