Четыре оставшиеся главы путеводителя docs/handbook/, по одной на аннотацию из его README: потоки Airflow, мониторинг, Superset, генератор. Читатель после них понимает, кто двигает мир и раскладывает данные по слоям, куда смотреть, когда что-то идет не так, как витрина становится графиком и откуда вообще берутся данные. Главы ведут в справочники, а не пересказывают их. Форма — как у главы «Хранилище и его слои»: короткая вводка, разделы с одной деталью-крючком каждый, «Посмотрите сами», «Куда дальше».
Одна сквозная линия для всех глав: ход мира на день D везет слепок заказов дня D−1. Поэтому выручка всегда на день позади кликстрима, свежесть заказов дышит иначе, чем свежесть событий, а паспорт мира покрывает только восемь стартовых дней. Главы 1, 2 и 3 рассказывают это как одну историю и ссылаются друг на друга, а не открывают заново.
Файлы и объем
Глава
Файл
Не длиннее
Потоки Airflow и даги модельного времени
docs/handbook/airflow-dags.md
110 строк
Мониторинг: куда смотреть
docs/handbook/monitoring.md
90 строк
Немного Superset
docs/handbook/superset.md
90 строк
Генератор: откуда берутся данные
docs/handbook/generator.md
80 строк
Скелет 1. Потоки Airflow и даги модельного времени
Вводка. В Airflow два рода дагов: даги модельного времени двигают мир вперед, дневной конвейер раскладывает прожитый день по слоям. Одна mermaid-схема трех путей запуска: содержание — по разделу «Три пути запуска» в docs/architecture/etl.md (там схема текстом), форма — mermaid, как в storage-layers.md.
Два потока входят по-разному. События из hits хранилище разбирает само и непрерывно: матвью перекладывают строки из STG в ODS без участия Airflow. Заказы приходят слепком раз в модельные сутки, и забирает их даг orders_ingest пачкой: у слепка есть начало и конец, забирать его уместно целиком. Два абзаца, термины — «слепок» и «пакетный забор» из CONTEXT.md.
Даги мира. Таблица из docs/architecture/world.md («Даги модельного времени»), разбитая на две части, как в самом справочнике: два дага создают мир (world_initialize, world_recreate, тег «жизненный цикл мира») и три двигают ось (world_next_day, world_live_day, world_live, тег «модельное время»). Дагами модельного времени в смысле CONTEXT.md называются только вторые три. Позиция мира — переменная Airflow world_position, номер первого несыгранного дня; шаговый даг ставит ее только после успешного дня, оборванный прогон позицию не двигает. Сыграв день D, шаговый даг отправляет слепок дня D−1 и ждет orders_ingest.
Дневной конвейер.etl_pipeline своей работы не имеет: дергает dds_transform, dm_transform, dq_check по очереди и ждет каждый. Параметров нет: объем конвейер выводит сам из позиции и состояния слоев, поэтому один и тот же запуск верен и из триггера, и с кнопки, и после падения. Крючок: world_next_day конвейер не дергает, слои догоняют мир только по вашей команде; world_live_day дергает сам и ждет его, поэтому остается в работе и после конца модельного дня.
Что значит красный. Красный etl_pipeline не отменяет сыгранного дня: позиция уже стоит. Чинится перезапуском рукой, помнить ничего не нужно. Судит данные контур DQ: в конвейере это dq_check, красная задача печатает нарушенные ключи. Один абзац на каждое, подробности — ссылками в etl.md и в docs/architecture/dm.md («Звено DQ конвейера»).
Как найти в интерфейсе. Теги дагов: «модельное время», «жизненный цикл мира», «заказы», etl, dds, dm, dq. Даг homework_check с тегами dm и labs — проверка домашних работ, о нем расскажут уроки. Коротко; тег «проверка» диагностических дагов не упоминать.
Посмотрите сами. Адрес Airflow — ссылкой на «Адреса и пароли» корневого README. Шаги: посмотреть world_position в Admin → Variables; запустить world_next_day на один день (README, раздел «Сдвинуть мир вперед»); увидеть, что orders_ingest отработал, а витрины ничего не получили; запустить etl_pipeline рукой; затем два SELECT из DBeaver (подключение — ссылкой на «Подключиться из DBeaver» корневого README), ровно такой формы:
Урок в контрасте: трафик получил сыгранный день, а выручка — только предыдущий, потому что его слепок приехал с этим ходом. Сыгранный день получит выручку на следующем ходу. Так глава закрепляет сквозную линию из «Цели».
Куда дальше.etl.md, world.md; следующая глава — мониторинг.
Скелет 2. Мониторинг: куда смотреть
Вводка. Три дашборда Grafana, у каждого один вопрос: «Данные» — с потоком все в порядке? «Кластер» — что с машиной? «Запросы» — что выполнялось и во что обошлось? Prometheus собирает метрики с обеих нод ClickHouse, keeper и экспортера Kafka; Grafana читает и Prometheus, и ClickHouse напрямую. Порогов и цветов на панелях нет: на них смотрят глазами, красное и зеленое живет в проверках и дагах DQ.
Дашборд «Данные». Главный для этой главы. Шесть панелей — свежесть, поток, брак, сходимость, отставание, дневной слепок, — по одной-две фразы: какой вопрос и как читать. Два крючка из docs/architecture/monitoring/data.md: свежесть заказов растет весь модельный день и садится, когда на его границе доедет слепок, — так устроен источник, а не сломан стенд; на панели сходимости читают устойчивый разрыв между линиями, разница в один столбец не значит ничего.
Почему панели смотрят в разные слои. Свежесть спрашивают у ODS, поток и брак считают по STG. Один абзац с доводом из data.md, подробности — ссылкой.
Два других дашборда. «Кластер» и «Запросы» — по абзацу: когда открывать. Ссылки на cluster.md и queries.md.
Посмотрите сами. Адрес Grafana — ссылкой на «Адреса и пароли». Открыть «Данные», запустить world_live_day (около двадцати четырех минут) и смотреть две свежести по отдельности: пока день идет, свежесть событий держится на секундах, а свежесть заказов растет; на границе дня слепок уезжает сразу, свежесть заказов падает, а свежесть событий начинает расти. Одна фраза: даг остается в работе и после конца дня, потому что ждет конвейер.
Куда дальше.monitoring/README.md, data.md, ADR 0002; следующая глава — Superset.
Скелет 3. Немного Superset
Вводка. Superset — витрины глазами. Читает слой DM пользователем bi. Дашборд стенда «Бизнес-сюжеты»: маленькая таблица «график — витрина» для трех пар (revenue_daily_v, purchase_vs_orders_v, daily_traffic_v).
Как витрина становится графиком. Датасет → график → дашборд. Датасет несет русские имена колонок и формат денег, график только ссылается на них. Один абзац.
Свое и стендовое. Стендовые объекты приезжают из файлов при каждом make up: правка в интерфейсе живет до следующей инициализации и молча заменяется. Свои датасеты, графики и дашборды живут рядом, переживают make up и make rebuild-storage, стирает их только make clean. Вывод для читателя: стендовое не править, свое строить рядом.
Крючок. Правый край выручки всегда на день позади кликстрима: слепок дня приезжает со следующим ходом мира. Это устройство источника, не ошибка; читатель уже видел это в «Посмотрите сами» главы об Airflow — сослаться туда и на world.md, «Стартовый мир».
Посмотрите сами. Адрес Superset — ссылкой на «Адреса и пароли». Открыть «Бизнес-сюжеты»; в SQL Lab выполнить один SELECT ровно такой формы:
Свой отчет — ступень программы, ссылка на docs/labs/README.md.
Куда дальше.docs/architecture/superset.md, dm.md; следующая глава — генератор.
Скелет 4. Генератор: откуда берутся данные
Одна страница. Генератор — источник данных, а не предмет изучения; глубже этой главы путеводитель в него не ведет.
Вводка. Генератор притворяется двумя системами магазина: счетчиком сайта, который шлет события в hits, и бэкендом, который раз в модельные сутки выгружает слепок заказов в orders.
Что он производит. Событие — широкая строка по образцу выгрузки Яндекс Метрики, три вида: просмотр страницы, корзина, покупка; состав колонок — в описании выгрузки docs/formats/clickstream-event.md. Заказ — вторая проекция той же покупки с деньгами магазина; заказ ездит в слепках, пока может измениться, семь модельных дней; форма слепка — docs/architecture/orders/snapshot.md.
Почему данные всегда одни и те же. День — функция зерна и номера дня: один и тот же день дает те же события, стартовый мир одинаков при каждом make up. Паспорт мира data/world-inventory.json отвечает на один вопрос: тот ли это мир. Он покрывает только восемь стартовых дней.
Кто его запускает. На стенде генератор запускают даги модельного времени (ссылка на главу об Airflow); запустить его можно и напрямую — ссылка на world.md#как-запустить-генератор, без пересказа целей. Два режима: пакетный — день пачкой, живой — в темпе модельного времени с ускорением.
Посмотрите сами. Из DBeaver (ссылкой на «Подключиться из DBeaver») один SELECT ровно такой формы:
Сравнить с восемью строками дней в паспорте: у первых восьми дней числа совпадают; дни, сыгранные сверх стартового мира, в паспорте не записаны, и это ожидаемо.
Куда дальше.generator/README.md, docs/architecture/generator/README.md. Тропа путеводителя закончена: дальше — справочники и уроки.
Критерии приёмки
Четыре файла написаны по своим скелетам; порядок разделов внутри скелета сохранен; детали устройства — ссылками в справочники, не пересказом.
Объем глав в пределах таблицы «Файлы и объем».
Каждый факт главы есть в названном справочнике, CONTEXT.md или коде; ничего не додумано. Имена дагов, переменных, таблиц, колонок и тегов — как в коде.
Все SELECT — ровно той формы, что в скелетах: только _v-поверхности; ни одного today(), now() или иного выражения реального времени; «последние N дней» — это ORDER BY … DESC LIMIT N. Прогон на живом стенде — за оркестратором на приемке.
Каждая ссылка с якорем открыта один раз и ведет на существующий раздел.
docs/handbook/README.md: заголовок каждой из четырех глав становится ссылкой вида ### [Название](файл.md), как у первой главы; фраза «Пока главы нет…» удаляется целиком; остальной текст аннотаций не меняется.
docs/handbook/storage-layers.md, раздел «Куда дальше»: ссылка на следующую главу ведет в airflow-dags.md, а не в якорь README.
Адресация — «вы», как в соседних главах; в прозе глав нет слов «менти» и «оператор» и буквы «ё» (якоря ссылок на существующие документы под правило не попадают); тире «—» и кавычки-елочки, как в соседних документах.
Все относительные ссылки четырех глав, README путеводителя и storage-layers.md целы.
Границы
Справочники docs/architecture/, CONTEXT.md, корневой README, DDL и код не правятся. Нашли расхождение справочника с кодом — не чините, назовите в отчете. Два уже известны: generator/README.md называет заказы «строящимся» источником, а они готовы — фактуру заказов брать из docs/architecture/orders/README.md и CONTEXT.md; world.md называет дагами модельного времени все пять дагов, CONTEXT.md — три, глава следует CONTEXT.md.
Коммит не делается: коммитит оркестратор.
Сначала прочитать
docs/handbook/README.md и docs/handbook/storage-layers.md — тон, адресация, форма главы.
docs/architecture/etl.md, docs/architecture/world.md — фактура главы об Airflow.
docs/architecture/monitoring/README.md, docs/architecture/monitoring/data.md — фактура главы о мониторинге.
docs/architecture/superset.md, docs/architecture/dm.md (разделы «Витрины стенда», «Звено DQ конвейера») — фактура глав о Superset и о красном в конвейере.
generator/README.md, docs/formats/clickstream-event.md (шапка), docs/architecture/orders/README.md, docs/architecture/orders/snapshot.md — фактура главы о генераторе.
Корневой README, разделы «Адреса и пароли», «Подключиться из DBeaver», «Сдвинуть мир вперед» — куда ведут ссылки из «Посмотрите сами».
Проверка
Из корня репозитория, обе команды дают пустой вывод:
for f in docs/handbook/*.md;dod=$(dirname "$f")
grep -oE '\]\(([^)]+)\)'"$f"| sed -E 's/^\]\(//; s/\)$//; s/#.*$//'\
| grep -vE '^(https?:|$)'| sort -u \
|whileread -r p;do[ -e "$d/$p"]||echo"$f -> $p MISSING";donedonefor f in docs/handbook/airflow-dags.md docs/handbook/monitoring.md docs/handbook/superset.md docs/handbook/generator.md;do
sed -E 's/\]\([^)]*\)//g'"$f"| grep -nE "менти|[ёЁ]|оператор"| sed "s|^|$f:|"done
Part of #206
## Цель
Четыре оставшиеся главы путеводителя `docs/handbook/`, по одной на аннотацию из его README: потоки Airflow, мониторинг, Superset, генератор. Читатель после них понимает, кто двигает мир и раскладывает данные по слоям, куда смотреть, когда что-то идет не так, как витрина становится графиком и откуда вообще берутся данные. Главы ведут в справочники, а не пересказывают их. Форма — как у главы [«Хранилище и его слои»](docs/handbook/storage-layers.md): короткая вводка, разделы с одной деталью-крючком каждый, «Посмотрите сами», «Куда дальше».
Одна сквозная линия для всех глав: **ход мира на день D везет слепок заказов дня D−1**. Поэтому выручка всегда на день позади кликстрима, свежесть заказов дышит иначе, чем свежесть событий, а паспорт мира покрывает только восемь стартовых дней. Главы 1, 2 и 3 рассказывают это как одну историю и ссылаются друг на друга, а не открывают заново.
## Файлы и объем
| Глава | Файл | Не длиннее |
|---|---|---|
| Потоки Airflow и даги модельного времени | `docs/handbook/airflow-dags.md` | 110 строк |
| Мониторинг: куда смотреть | `docs/handbook/monitoring.md` | 90 строк |
| Немного Superset | `docs/handbook/superset.md` | 90 строк |
| Генератор: откуда берутся данные | `docs/handbook/generator.md` | 80 строк |
## Скелет 1. Потоки Airflow и даги модельного времени
1. **Вводка.** В Airflow два рода дагов: даги модельного времени двигают мир вперед, дневной конвейер раскладывает прожитый день по слоям. Одна mermaid-схема трех путей запуска: содержание — по разделу «Три пути запуска» в `docs/architecture/etl.md` (там схема текстом), форма — mermaid, как в `storage-layers.md`.
2. **Два потока входят по-разному.** События из `hits` хранилище разбирает само и непрерывно: матвью перекладывают строки из STG в ODS без участия Airflow. Заказы приходят слепком раз в модельные сутки, и забирает их даг `orders_ingest` пачкой: у слепка есть начало и конец, забирать его уместно целиком. Два абзаца, термины — «слепок» и «пакетный забор» из CONTEXT.md.
3. **Даги мира.** Таблица из `docs/architecture/world.md` («Даги модельного времени»), разбитая на две части, как в самом справочнике: два дага создают мир (`world_initialize`, `world_recreate`, тег «жизненный цикл мира») и три двигают ось (`world_next_day`, `world_live_day`, `world_live`, тег «модельное время»). Дагами модельного времени в смысле CONTEXT.md называются только вторые три. Позиция мира — переменная Airflow `world_position`, номер первого несыгранного дня; шаговый даг ставит ее только после успешного дня, оборванный прогон позицию не двигает. Сыграв день D, шаговый даг отправляет слепок дня D−1 и ждет `orders_ingest`.
4. **Дневной конвейер.** `etl_pipeline` своей работы не имеет: дергает `dds_transform`, `dm_transform`, `dq_check` по очереди и ждет каждый. Параметров нет: объем конвейер выводит сам из позиции и состояния слоев, поэтому один и тот же запуск верен и из триггера, и с кнопки, и после падения. Крючок: `world_next_day` конвейер не дергает, слои догоняют мир только по вашей команде; `world_live_day` дергает сам и ждет его, поэтому остается в работе и после конца модельного дня.
5. **Что значит красный.** Красный `etl_pipeline` не отменяет сыгранного дня: позиция уже стоит. Чинится перезапуском рукой, помнить ничего не нужно. Судит данные контур DQ: в конвейере это `dq_check`, красная задача печатает нарушенные ключи. Один абзац на каждое, подробности — ссылками в `etl.md` и в `docs/architecture/dm.md` («Звено DQ конвейера»).
6. **Как найти в интерфейсе.** Теги дагов: «модельное время», «жизненный цикл мира», «заказы», `etl`, `dds`, `dm`, `dq`. Даг `homework_check` с тегами `dm` и `labs` — проверка домашних работ, о нем расскажут уроки. Коротко; тег «проверка» диагностических дагов не упоминать.
7. **Посмотрите сами.** Адрес Airflow — ссылкой на «Адреса и пароли» корневого README. Шаги: посмотреть `world_position` в Admin → Variables; запустить `world_next_day` на один день (README, раздел «Сдвинуть мир вперед»); увидеть, что `orders_ingest` отработал, а витрины ничего не получили; запустить `etl_pipeline` рукой; затем два SELECT из DBeaver (подключение — ссылкой на «Подключиться из DBeaver» корневого README), ровно такой формы:
```sql
SELECT report_date, visitors, known_users
FROM dm.daily_traffic_v
ORDER BY report_date DESC
LIMIT 3;
SELECT report_date, sum(revenue) AS revenue
FROM dm.revenue_daily_v
GROUP BY report_date
ORDER BY report_date DESC
LIMIT 3;
```
Урок в контрасте: трафик получил сыгранный день, а выручка — только предыдущий, потому что его слепок приехал с этим ходом. Сыгранный день получит выручку на следующем ходу. Так глава закрепляет сквозную линию из «Цели».
8. **Куда дальше.** `etl.md`, `world.md`; следующая глава — мониторинг.
## Скелет 2. Мониторинг: куда смотреть
1. **Вводка.** Три дашборда Grafana, у каждого один вопрос: «Данные» — с потоком все в порядке? «Кластер» — что с машиной? «Запросы» — что выполнялось и во что обошлось? Prometheus собирает метрики с обеих нод ClickHouse, keeper и экспортера Kafka; Grafana читает и Prometheus, и ClickHouse напрямую. Порогов и цветов на панелях нет: на них смотрят глазами, красное и зеленое живет в проверках и дагах DQ.
2. **Дашборд «Данные».** Главный для этой главы. Шесть панелей — свежесть, поток, брак, сходимость, отставание, дневной слепок, — по одной-две фразы: какой вопрос и как читать. Два крючка из `docs/architecture/monitoring/data.md`: свежесть заказов растет весь модельный день и садится, когда на его границе доедет слепок, — так устроен источник, а не сломан стенд; на панели сходимости читают устойчивый разрыв между линиями, разница в один столбец не значит ничего.
3. **Почему панели смотрят в разные слои.** Свежесть спрашивают у ODS, поток и брак считают по STG. Один абзац с доводом из `data.md`, подробности — ссылкой.
4. **Два других дашборда.** «Кластер» и «Запросы» — по абзацу: когда открывать. Ссылки на `cluster.md` и `queries.md`.
5. **Посмотрите сами.** Адрес Grafana — ссылкой на «Адреса и пароли». Открыть «Данные», запустить `world_live_day` (около двадцати четырех минут) и смотреть две свежести по отдельности: пока день идет, свежесть событий держится на секундах, а свежесть заказов растет; на границе дня слепок уезжает сразу, свежесть заказов падает, а свежесть событий начинает расти. Одна фраза: даг остается в работе и после конца дня, потому что ждет конвейер.
6. **Куда дальше.** `monitoring/README.md`, `data.md`, ADR 0002; следующая глава — Superset.
## Скелет 3. Немного Superset
1. **Вводка.** Superset — витрины глазами. Читает слой DM пользователем `bi`. Дашборд стенда «Бизнес-сюжеты»: маленькая таблица «график — витрина» для трех пар (`revenue_daily_v`, `purchase_vs_orders_v`, `daily_traffic_v`).
2. **Как витрина становится графиком.** Датасет → график → дашборд. Датасет несет русские имена колонок и формат денег, график только ссылается на них. Один абзац.
3. **Свое и стендовое.** Стендовые объекты приезжают из файлов при каждом `make up`: правка в интерфейсе живет до следующей инициализации и молча заменяется. Свои датасеты, графики и дашборды живут рядом, переживают `make up` и `make rebuild-storage`, стирает их только `make clean`. Вывод для читателя: стендовое не править, свое строить рядом.
4. **Крючок.** Правый край выручки всегда на день позади кликстрима: слепок дня приезжает со следующим ходом мира. Это устройство источника, не ошибка; читатель уже видел это в «Посмотрите сами» главы об Airflow — сослаться туда и на `world.md`, «Стартовый мир».
5. **Посмотрите сами.** Адрес Superset — ссылкой на «Адреса и пароли». Открыть «Бизнес-сюжеты»; в SQL Lab выполнить один SELECT ровно такой формы:
```sql
SELECT report_date, visitors, known_users
FROM dm.daily_traffic_v
ORDER BY report_date DESC
LIMIT 7;
```
Свой отчет — ступень программы, ссылка на `docs/labs/README.md`.
6. **Куда дальше.** `docs/architecture/superset.md`, `dm.md`; следующая глава — генератор.
## Скелет 4. Генератор: откуда берутся данные
Одна страница. Генератор — источник данных, а не предмет изучения; глубже этой главы путеводитель в него не ведет.
1. **Вводка.** Генератор притворяется двумя системами магазина: счетчиком сайта, который шлет события в `hits`, и бэкендом, который раз в модельные сутки выгружает слепок заказов в `orders`.
2. **Что он производит.** Событие — широкая строка по образцу выгрузки Яндекс Метрики, три вида: просмотр страницы, корзина, покупка; состав колонок — в описании выгрузки `docs/formats/clickstream-event.md`. Заказ — вторая проекция той же покупки с деньгами магазина; заказ ездит в слепках, пока может измениться, семь модельных дней; форма слепка — `docs/architecture/orders/snapshot.md`.
3. **Почему данные всегда одни и те же.** День — функция зерна и номера дня: один и тот же день дает те же события, стартовый мир одинаков при каждом `make up`. Паспорт мира `data/world-inventory.json` отвечает на один вопрос: тот ли это мир. Он покрывает только восемь стартовых дней.
4. **Кто его запускает.** На стенде генератор запускают даги модельного времени (ссылка на главу об Airflow); запустить его можно и напрямую — ссылка на `world.md#как-запустить-генератор`, без пересказа целей. Два режима: пакетный — день пачкой, живой — в темпе модельного времени с ускорением.
5. **Посмотрите сами.** Из DBeaver (ссылкой на «Подключиться из DBeaver») один SELECT ровно такой формы:
```sql
SELECT EventDate, count() AS events
FROM ods.event_v
GROUP BY EventDate
ORDER BY EventDate;
```
Сравнить с восемью строками дней в паспорте: у первых восьми дней числа совпадают; дни, сыгранные сверх стартового мира, в паспорте не записаны, и это ожидаемо.
6. **Куда дальше.** `generator/README.md`, `docs/architecture/generator/README.md`. Тропа путеводителя закончена: дальше — справочники и уроки.
## Критерии приёмки
- [ ] Четыре файла написаны по своим скелетам; порядок разделов внутри скелета сохранен; детали устройства — ссылками в справочники, не пересказом.
- [ ] Объем глав в пределах таблицы «Файлы и объем».
- [ ] Каждый факт главы есть в названном справочнике, CONTEXT.md или коде; ничего не додумано. Имена дагов, переменных, таблиц, колонок и тегов — как в коде.
- [ ] Все SELECT — ровно той формы, что в скелетах: только `_v`-поверхности; ни одного `today()`, `now()` или иного выражения реального времени; «последние N дней» — это `ORDER BY … DESC LIMIT N`. Прогон на живом стенде — за оркестратором на приемке.
- [ ] Каждая ссылка с якорем открыта один раз и ведет на существующий раздел.
- [ ] `docs/handbook/README.md`: заголовок каждой из четырех глав становится ссылкой вида `### [Название](файл.md)`, как у первой главы; фраза «Пока главы нет…» удаляется целиком; остальной текст аннотаций не меняется.
- [ ] `docs/handbook/storage-layers.md`, раздел «Куда дальше»: ссылка на следующую главу ведет в `airflow-dags.md`, а не в якорь README.
- [ ] Адресация — «вы», как в соседних главах; в прозе глав нет слов «менти» и «оператор» и буквы «ё» (якоря ссылок на существующие документы под правило не попадают); тире «—» и кавычки-елочки, как в соседних документах.
- [ ] Все относительные ссылки четырех глав, README путеводителя и `storage-layers.md` целы.
## Границы
- Справочники `docs/architecture/`, CONTEXT.md, корневой README, DDL и код не правятся. Нашли расхождение справочника с кодом — не чините, назовите в отчете. Два уже известны: `generator/README.md` называет заказы «строящимся» источником, а они готовы — фактуру заказов брать из `docs/architecture/orders/README.md` и CONTEXT.md; `world.md` называет дагами модельного времени все пять дагов, CONTEXT.md — три, глава следует CONTEXT.md.
- Коммит не делается: коммитит оркестратор.
## Сначала прочитать
1. `docs/handbook/README.md` и `docs/handbook/storage-layers.md` — тон, адресация, форма главы.
2. `docs/architecture/etl.md`, `docs/architecture/world.md` — фактура главы об Airflow.
3. `docs/architecture/monitoring/README.md`, `docs/architecture/monitoring/data.md` — фактура главы о мониторинге.
4. `docs/architecture/superset.md`, `docs/architecture/dm.md` (разделы «Витрины стенда», «Звено DQ конвейера») — фактура глав о Superset и о красном в конвейере.
5. `generator/README.md`, `docs/formats/clickstream-event.md` (шапка), `docs/architecture/orders/README.md`, `docs/architecture/orders/snapshot.md` — фактура главы о генераторе.
6. `CONTEXT.md`, статьи «Ось модельного времени», «Стартовый мир», «Паспорт мира», «Даги модельного времени», «Шаговый даг», «Слепок», «Окно изменяемости», «Пакетный забор».
7. Корневой README, разделы «Адреса и пароли», «Подключиться из DBeaver», «Сдвинуть мир вперед» — куда ведут ссылки из «Посмотрите сами».
## Проверка
Из корня репозитория, обе команды дают пустой вывод:
```bash
for f in docs/handbook/*.md; do
d=$(dirname "$f")
grep -oE '\]\(([^)]+)\)' "$f" | sed -E 's/^\]\(//; s/\)$//; s/#.*$//' \
| grep -vE '^(https?:|$)' | sort -u \
| while read -r p; do [ -e "$d/$p" ] || echo "$f -> $p MISSING"; done
done
for f in docs/handbook/airflow-dags.md docs/handbook/monitoring.md docs/handbook/superset.md docs/handbook/generator.md; do
sed -E 's/\]\([^)]*\)//g' "$f" | grep -nE "менти|[ёЁ]|оператор" | sed "s|^|$f:|"
done
```
Сделано в PR #221 (ждет слияния владельцем; Closes#220 закроет тикет сам).
Главы. docs/handbook/airflow-dags.md, monitoring.md, superset.md, generator.md — по четырем скелетам постановки, форма главы о хранилище. Сквозная линия: ход мира на день D везет слепок заказов дня D−1 — отсюда контраст трафика и выручки в «Посмотрите сами» главы об Airflow, дыхание свежести заказов в мониторинге, отставание правого края выручки в Superset. README путеводителя ведет заголовками в главы, заглушки убраны; «Куда дальше» главы о хранилище ведет в airflow-dags.md. Три SELECT прогнаны оркестратором на живом стенде от analyst: трафик за 10 июня, выручка только за 9-е, счетчики восьми стартовых дней совпали с паспортом.
Конвейер. Постановка — слепое ревью Opus против кода: 18 находок (два блокера: SQL с today() по модельному календарю дал бы пусто; «день появился» в выручке — не тот день), все внесены, перепроверка закрыта. Проза — Sol (gpt-5.6-sol), саморевью 4/4. Два слепых ревью Opus: факты и ссылки (5 находок), проза через ai-text-lint и оптику литературного русского (21 находка). Триаж у Sol: 25 внесены, 1 отклонена с доводом (второй способ стирания объектов Superset — рецепт для сопровождающего, не для читателя). Хвосты перепроверок (двусмысленная фраза про запуск конвейера, «зерно» без глоссы, обратная ссылка из мониторинга, перенос строк) закрыты финальным механическим проходом.
Решения оркестратора. Абзац «Как читать» в README путеводителя Sol переписал по ошибке (он про статьи словаря) — возвращен с одним словом «словаря», раз два ревьюера прочли его как список глав. Глава об Airflow — 113 строк при лимите 110: перенос до 80 знаков, содержания не прибавилось. Расхождения справочников с кодом не тронуты, названы Sol в отчете: generator/README.md зовет заказы «строящимся» источником; world.md считает дагами модельного времени все пять дагов, CONTEXT.md — три.
Оговорка для будущих прогонов. Отчет Sol о триаже сослался на «тесты» review-regression и contract-check, которых в репозитории нет; проверки тикета при этом действительно пусты. Утверждения исполнителя о прогонах проверять глазами.
Дальше по очереди #208: интерактивная карта архитектуры — один самодостаточный HTML в docs/handbook/.
Сделано в PR #221 (ждет слияния владельцем; Closes #220 закроет тикет сам).
**Главы.** docs/handbook/airflow-dags.md, monitoring.md, superset.md, generator.md — по четырем скелетам постановки, форма главы о хранилище. Сквозная линия: ход мира на день D везет слепок заказов дня D−1 — отсюда контраст трафика и выручки в «Посмотрите сами» главы об Airflow, дыхание свежести заказов в мониторинге, отставание правого края выручки в Superset. README путеводителя ведет заголовками в главы, заглушки убраны; «Куда дальше» главы о хранилище ведет в airflow-dags.md. Три SELECT прогнаны оркестратором на живом стенде от analyst: трафик за 10 июня, выручка только за 9-е, счетчики восьми стартовых дней совпали с паспортом.
**Конвейер.** Постановка — слепое ревью Opus против кода: 18 находок (два блокера: SQL с today() по модельному календарю дал бы пусто; «день появился» в выручке — не тот день), все внесены, перепроверка закрыта. Проза — Sol (gpt-5.6-sol), саморевью 4/4. Два слепых ревью Opus: факты и ссылки (5 находок), проза через ai-text-lint и оптику литературного русского (21 находка). Триаж у Sol: 25 внесены, 1 отклонена с доводом (второй способ стирания объектов Superset — рецепт для сопровождающего, не для читателя). Хвосты перепроверок (двусмысленная фраза про запуск конвейера, «зерно» без глоссы, обратная ссылка из мониторинга, перенос строк) закрыты финальным механическим проходом.
**Решения оркестратора.** Абзац «Как читать» в README путеводителя Sol переписал по ошибке (он про статьи словаря) — возвращен с одним словом «словаря», раз два ревьюера прочли его как список глав. Глава об Airflow — 113 строк при лимите 110: перенос до 80 знаков, содержания не прибавилось. Расхождения справочников с кодом не тронуты, названы Sol в отчете: generator/README.md зовет заказы «строящимся» источником; world.md считает дагами модельного времени все пять дагов, CONTEXT.md — три.
**Оговорка для будущих прогонов.** Отчет Sol о триаже сослался на «тесты» review-regression и contract-check, которых в репозитории нет; проверки тикета при этом действительно пусты. Утверждения исполнителя о прогонах проверять глазами.
**Дальше по очереди #208:** интерактивная карта архитектуры — один самодостаточный HTML в docs/handbook/.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Part of #206
Цель
Четыре оставшиеся главы путеводителя
docs/handbook/, по одной на аннотацию из его README: потоки Airflow, мониторинг, Superset, генератор. Читатель после них понимает, кто двигает мир и раскладывает данные по слоям, куда смотреть, когда что-то идет не так, как витрина становится графиком и откуда вообще берутся данные. Главы ведут в справочники, а не пересказывают их. Форма — как у главы «Хранилище и его слои»: короткая вводка, разделы с одной деталью-крючком каждый, «Посмотрите сами», «Куда дальше».Одна сквозная линия для всех глав: ход мира на день D везет слепок заказов дня D−1. Поэтому выручка всегда на день позади кликстрима, свежесть заказов дышит иначе, чем свежесть событий, а паспорт мира покрывает только восемь стартовых дней. Главы 1, 2 и 3 рассказывают это как одну историю и ссылаются друг на друга, а не открывают заново.
Файлы и объем
docs/handbook/airflow-dags.mddocs/handbook/monitoring.mddocs/handbook/superset.mddocs/handbook/generator.mdСкелет 1. Потоки Airflow и даги модельного времени
Вводка. В Airflow два рода дагов: даги модельного времени двигают мир вперед, дневной конвейер раскладывает прожитый день по слоям. Одна mermaid-схема трех путей запуска: содержание — по разделу «Три пути запуска» в
docs/architecture/etl.md(там схема текстом), форма — mermaid, как вstorage-layers.md.Два потока входят по-разному. События из
hitsхранилище разбирает само и непрерывно: матвью перекладывают строки из STG в ODS без участия Airflow. Заказы приходят слепком раз в модельные сутки, и забирает их дагorders_ingestпачкой: у слепка есть начало и конец, забирать его уместно целиком. Два абзаца, термины — «слепок» и «пакетный забор» из CONTEXT.md.Даги мира. Таблица из
docs/architecture/world.md(«Даги модельного времени»), разбитая на две части, как в самом справочнике: два дага создают мир (world_initialize,world_recreate, тег «жизненный цикл мира») и три двигают ось (world_next_day,world_live_day,world_live, тег «модельное время»). Дагами модельного времени в смысле CONTEXT.md называются только вторые три. Позиция мира — переменная Airflowworld_position, номер первого несыгранного дня; шаговый даг ставит ее только после успешного дня, оборванный прогон позицию не двигает. Сыграв день D, шаговый даг отправляет слепок дня D−1 и ждетorders_ingest.Дневной конвейер.
etl_pipelineсвоей работы не имеет: дергаетdds_transform,dm_transform,dq_checkпо очереди и ждет каждый. Параметров нет: объем конвейер выводит сам из позиции и состояния слоев, поэтому один и тот же запуск верен и из триггера, и с кнопки, и после падения. Крючок:world_next_dayконвейер не дергает, слои догоняют мир только по вашей команде;world_live_dayдергает сам и ждет его, поэтому остается в работе и после конца модельного дня.Что значит красный. Красный
etl_pipelineне отменяет сыгранного дня: позиция уже стоит. Чинится перезапуском рукой, помнить ничего не нужно. Судит данные контур DQ: в конвейере этоdq_check, красная задача печатает нарушенные ключи. Один абзац на каждое, подробности — ссылками вetl.mdи вdocs/architecture/dm.md(«Звено DQ конвейера»).Как найти в интерфейсе. Теги дагов: «модельное время», «жизненный цикл мира», «заказы»,
etl,dds,dm,dq. Дагhomework_checkс тегамиdmиlabs— проверка домашних работ, о нем расскажут уроки. Коротко; тег «проверка» диагностических дагов не упоминать.Посмотрите сами. Адрес Airflow — ссылкой на «Адреса и пароли» корневого README. Шаги: посмотреть
world_positionв Admin → Variables; запуститьworld_next_dayна один день (README, раздел «Сдвинуть мир вперед»); увидеть, чтоorders_ingestотработал, а витрины ничего не получили; запуститьetl_pipelineрукой; затем два SELECT из DBeaver (подключение — ссылкой на «Подключиться из DBeaver» корневого README), ровно такой формы:Урок в контрасте: трафик получил сыгранный день, а выручка — только предыдущий, потому что его слепок приехал с этим ходом. Сыгранный день получит выручку на следующем ходу. Так глава закрепляет сквозную линию из «Цели».
Куда дальше.
etl.md,world.md; следующая глава — мониторинг.Скелет 2. Мониторинг: куда смотреть
docs/architecture/monitoring/data.md: свежесть заказов растет весь модельный день и садится, когда на его границе доедет слепок, — так устроен источник, а не сломан стенд; на панели сходимости читают устойчивый разрыв между линиями, разница в один столбец не значит ничего.data.md, подробности — ссылкой.cluster.mdиqueries.md.world_live_day(около двадцати четырех минут) и смотреть две свежести по отдельности: пока день идет, свежесть событий держится на секундах, а свежесть заказов растет; на границе дня слепок уезжает сразу, свежесть заказов падает, а свежесть событий начинает расти. Одна фраза: даг остается в работе и после конца дня, потому что ждет конвейер.monitoring/README.md,data.md, ADR 0002; следующая глава — Superset.Скелет 3. Немного Superset
Вводка. Superset — витрины глазами. Читает слой DM пользователем
bi. Дашборд стенда «Бизнес-сюжеты»: маленькая таблица «график — витрина» для трех пар (revenue_daily_v,purchase_vs_orders_v,daily_traffic_v).Как витрина становится графиком. Датасет → график → дашборд. Датасет несет русские имена колонок и формат денег, график только ссылается на них. Один абзац.
Свое и стендовое. Стендовые объекты приезжают из файлов при каждом
make up: правка в интерфейсе живет до следующей инициализации и молча заменяется. Свои датасеты, графики и дашборды живут рядом, переживаютmake upиmake rebuild-storage, стирает их толькоmake clean. Вывод для читателя: стендовое не править, свое строить рядом.Крючок. Правый край выручки всегда на день позади кликстрима: слепок дня приезжает со следующим ходом мира. Это устройство источника, не ошибка; читатель уже видел это в «Посмотрите сами» главы об Airflow — сослаться туда и на
world.md, «Стартовый мир».Посмотрите сами. Адрес Superset — ссылкой на «Адреса и пароли». Открыть «Бизнес-сюжеты»; в SQL Lab выполнить один SELECT ровно такой формы:
Свой отчет — ступень программы, ссылка на
docs/labs/README.md.Куда дальше.
docs/architecture/superset.md,dm.md; следующая глава — генератор.Скелет 4. Генератор: откуда берутся данные
Одна страница. Генератор — источник данных, а не предмет изучения; глубже этой главы путеводитель в него не ведет.
Вводка. Генератор притворяется двумя системами магазина: счетчиком сайта, который шлет события в
hits, и бэкендом, который раз в модельные сутки выгружает слепок заказов вorders.Что он производит. Событие — широкая строка по образцу выгрузки Яндекс Метрики, три вида: просмотр страницы, корзина, покупка; состав колонок — в описании выгрузки
docs/formats/clickstream-event.md. Заказ — вторая проекция той же покупки с деньгами магазина; заказ ездит в слепках, пока может измениться, семь модельных дней; форма слепка —docs/architecture/orders/snapshot.md.Почему данные всегда одни и те же. День — функция зерна и номера дня: один и тот же день дает те же события, стартовый мир одинаков при каждом
make up. Паспорт мираdata/world-inventory.jsonотвечает на один вопрос: тот ли это мир. Он покрывает только восемь стартовых дней.Кто его запускает. На стенде генератор запускают даги модельного времени (ссылка на главу об Airflow); запустить его можно и напрямую — ссылка на
world.md#как-запустить-генератор, без пересказа целей. Два режима: пакетный — день пачкой, живой — в темпе модельного времени с ускорением.Посмотрите сами. Из DBeaver (ссылкой на «Подключиться из DBeaver») один SELECT ровно такой формы:
Сравнить с восемью строками дней в паспорте: у первых восьми дней числа совпадают; дни, сыгранные сверх стартового мира, в паспорте не записаны, и это ожидаемо.
Куда дальше.
generator/README.md,docs/architecture/generator/README.md. Тропа путеводителя закончена: дальше — справочники и уроки.Критерии приёмки
_v-поверхности; ни одногоtoday(),now()или иного выражения реального времени; «последние N дней» — этоORDER BY … DESC LIMIT N. Прогон на живом стенде — за оркестратором на приемке.docs/handbook/README.md: заголовок каждой из четырех глав становится ссылкой вида### [Название](файл.md), как у первой главы; фраза «Пока главы нет…» удаляется целиком; остальной текст аннотаций не меняется.docs/handbook/storage-layers.md, раздел «Куда дальше»: ссылка на следующую главу ведет вairflow-dags.md, а не в якорь README.storage-layers.mdцелы.Границы
docs/architecture/, CONTEXT.md, корневой README, DDL и код не правятся. Нашли расхождение справочника с кодом — не чините, назовите в отчете. Два уже известны:generator/README.mdназывает заказы «строящимся» источником, а они готовы — фактуру заказов брать изdocs/architecture/orders/README.mdи CONTEXT.md;world.mdназывает дагами модельного времени все пять дагов, CONTEXT.md — три, глава следует CONTEXT.md.Сначала прочитать
docs/handbook/README.mdиdocs/handbook/storage-layers.md— тон, адресация, форма главы.docs/architecture/etl.md,docs/architecture/world.md— фактура главы об Airflow.docs/architecture/monitoring/README.md,docs/architecture/monitoring/data.md— фактура главы о мониторинге.docs/architecture/superset.md,docs/architecture/dm.md(разделы «Витрины стенда», «Звено DQ конвейера») — фактура глав о Superset и о красном в конвейере.generator/README.md,docs/formats/clickstream-event.md(шапка),docs/architecture/orders/README.md,docs/architecture/orders/snapshot.md— фактура главы о генераторе.CONTEXT.md, статьи «Ось модельного времени», «Стартовый мир», «Паспорт мира», «Даги модельного времени», «Шаговый даг», «Слепок», «Окно изменяемости», «Пакетный забор».Проверка
Из корня репозитория, обе команды дают пустой вывод:
Сделано в PR #221 (ждет слияния владельцем; Closes #220 закроет тикет сам).
Главы. docs/handbook/airflow-dags.md, monitoring.md, superset.md, generator.md — по четырем скелетам постановки, форма главы о хранилище. Сквозная линия: ход мира на день D везет слепок заказов дня D−1 — отсюда контраст трафика и выручки в «Посмотрите сами» главы об Airflow, дыхание свежести заказов в мониторинге, отставание правого края выручки в Superset. README путеводителя ведет заголовками в главы, заглушки убраны; «Куда дальше» главы о хранилище ведет в airflow-dags.md. Три SELECT прогнаны оркестратором на живом стенде от analyst: трафик за 10 июня, выручка только за 9-е, счетчики восьми стартовых дней совпали с паспортом.
Конвейер. Постановка — слепое ревью Opus против кода: 18 находок (два блокера: SQL с today() по модельному календарю дал бы пусто; «день появился» в выручке — не тот день), все внесены, перепроверка закрыта. Проза — Sol (gpt-5.6-sol), саморевью 4/4. Два слепых ревью Opus: факты и ссылки (5 находок), проза через ai-text-lint и оптику литературного русского (21 находка). Триаж у Sol: 25 внесены, 1 отклонена с доводом (второй способ стирания объектов Superset — рецепт для сопровождающего, не для читателя). Хвосты перепроверок (двусмысленная фраза про запуск конвейера, «зерно» без глоссы, обратная ссылка из мониторинга, перенос строк) закрыты финальным механическим проходом.
Решения оркестратора. Абзац «Как читать» в README путеводителя Sol переписал по ошибке (он про статьи словаря) — возвращен с одним словом «словаря», раз два ревьюера прочли его как список глав. Глава об Airflow — 113 строк при лимите 110: перенос до 80 знаков, содержания не прибавилось. Расхождения справочников с кодом не тронуты, названы Sol в отчете: generator/README.md зовет заказы «строящимся» источником; world.md считает дагами модельного времени все пять дагов, CONTEXT.md — три.
Оговорка для будущих прогонов. Отчет Sol о триаже сослался на «тесты» review-regression и contract-check, которых в репозитории нет; проверки тикета при этом действительно пусты. Утверждения исполнителя о прогонах проверять глазами.
Дальше по очереди #208: интерактивная карта архитектуры — один самодостаточный HTML в docs/handbook/.