docs(specs): собрана спека генератора из решений развилок карты #26

- Зачем:
  - этап 2 нельзя нарезать на тикеты без единой картины генератора,
    а решения четырёх развилок карты #26 жили только в тикетах трекера.
- Что:
  - новая спека docs/specs/2026-08-01-generator.md: функциональный мир,
    детерминизм до байта (SeedSequence сверен через Context7), контракт
    схемы, канонический сериализатор, числа и порог производительности;
    отклонённые варианты записаны с доводами.
  - мастер-спека согласована тем же коммитом: 1.4 — data contract вместо
    автогенерации DDL, 8 — в git только манифест, 11 — числа вместо
    «зафиксировать требования»; мелкие согласования в 7 и 9.
  - CONTEXT.md пополнен терминами модели мира и вывода генератора.
- Проверка:
  - вычитка; относительные ссылки спек указывают на существующие файлы
    в docs/specs/ и docs/research/.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-01 19:47:29 +03:00
co-authored by Claude Opus 5
parent a9fade84f5
commit f85626508f
3 changed files with 403 additions and 20 deletions
+33 -20
View File
@@ -163,12 +163,18 @@ Ecommerce (заполнены только у торговых событий):
### 1.4 Схема как контракт
Одно машинное описание схемы события (python-модуль или YAML) — источник
истины: из него выводятся DDL и валидация генератора, а не наоборот. 47
колонок повторяются примерно в семи местах (генератор, DDL, SELECT матвью,
трансформации, витрины, манифест, доки) — без контракта они расходятся
молча. Заодно это учебный артефакт: менти видит на живом примере, что такое
«схема как контракт».
Машинное описание схемы события python-модуль с чистыми данными,
собственность генератора (data contract; решение развилки «Архитектура»
карты #26, подробности — [спека генератора](2026-08-01-generator.md),
раздел 3). Из контракта выводятся сам генератор, его валидация и
рендеренное «описание выгрузки» в доках — аналог документации Метрики.
Сторона хранилища (DDL, SELECT матвью, трансформации, витрины) пишется по
этой документации на своих этапах, как в бою хранилище адаптируется к
источнику; границу сторожат строгий приём (раздел 6) и contract-тест в
smoke — сравнение `system.columns` поднятого стенда со схемой генератора.
Без контракта 47 колонок, повторяясь примерно в семи местах, расходятся
молча. Заодно это учебный артефакт: менти видит на живом примере, что
такое data contract.
## 2. Заказы бэкенда
@@ -375,7 +381,8 @@ ReplacingMergeTree. Таблицы `stg.*_raw` хранят виртуальны
(`_topic`, `_partition`, `_offset`, `_timestamp`) — без них урок «какая нода
читала топик» ненаблюдаем. `stg.hits_raw` дополнительно хранит извлечённый
`event_date` — им кормится переобработка дня X (при исчерпании retention
Kafka переобработка возможна только из эталонного артефакта).
Kafka день переигрывается генератором заново: снимок — кэш чистой функции,
см. [спеку генератора](2026-08-01-generator.md)).
`dds.v_event` — первый на стенде пример правила «слой — это контракт, а не
обязательно копия данных».
@@ -425,9 +432,15 @@ Kafka переобработка возможна только из эталон
## 8. Эталонный мир и манифест
Пересборка артефакта `data/startup_history/` неизбежна и оплачена решением
#18 один раз — все изменения генератора съезжаются в одну пересборку.
Манифест расширяется контрольными числами:
В git хранится только манифест эталонного мира; сам снимок (14 модельных
дней) генерируется на месте — при `make up` и при проверках (решение
развилки «Производительность» карты #26, подробности —
[спека генератора](2026-08-01-generator.md), раздел 5). Манифест несёт
паспорт мира (каноническое зерно, версия генератора), контрольные счётчики
и хеши по дням; проверки «пустой git diff» и «пересгенерируй день N —
сравни хеш» живут на нём. Политика версионирования артефакта (бывший туман
карты #10) закрыта этим же ходом: версионируется манифест.
Контрольные числа манифеста:
- заказная сторона: заказы и выручка по дням; манифест хранит точные
счётчики по каждому классу расхождений (отмены, потери, дубли, дельты сумм) —
@@ -435,9 +448,8 @@ Kafka переобработка возможна только из эталон
- идентичность: uniq кук, uniq известных пользователей, число двухкуковых
покупателей — лаба склейки получает самопроверку.
Артефакт вырастет (ecommerce-массивы, заказы) — размер проверить при
пересборке. Политика версионирования артефакта здесь не решается (туман
карты #10).
Снимок вырастет против v1 (ecommerce-массивы, заказы) — размер проверить
при пересборке.
## 9. Оценка объёма исполнения
@@ -451,7 +463,7 @@ v2 стартует пустым, поэтому объём ниже — это
| SQL | 5 DDL-файлов (ON CLUSTER, Replicated*, Distributed) + трансформации событий, заказов, identity, сверки + словарь | L — ~12–15 файлов, главная сложность |
| Airflow | DAG'и по образцу v1: etl_pipeline (партиционная переобработка, ожидание дневного батча заказов — сенсор/Datasets), world_init/next_day, helpers | M — ~56 файлов |
| Superset | датасеты + дашборд с тремя новыми сюжетами | M — 2 файла |
| Эталонный мир | сборка артефакта v2, манифест-счётчики, чек-скрипты | M–L |
| Эталонный мир | пересборка снимка на месте, манифест-счётчики, чек-скрипты | M–L |
| Мониторинг | дашборды Grafana «данные», «кластер», «запросы»; ClickHouse источником данных, панели на SQL; Prometheus тонким полом (ADR 0002) | M — конфиги и дашборды |
| Документация | доки v2 пишутся заново (см. раздел 12) | M, в тех же PR |
@@ -496,7 +508,8 @@ v2 стартует пустым, поэтому объём ниже — это
5. Airflow: `etl_pipeline` (партиционная переобработка, ожидание дневного
батча заказов — сенсор/Datasets).
6. Расхождения B+D и опоздания; счётчики манифеста.
7. Эталонный мир: пересборка артефакта, чек-скрипты.
7. Эталонный мир: манифест и пересборка снимка, чек-скрипты; CI-генерация
на amd64 и arm64.
8. Superset-дашборд v2.
9. Мониторинг и runbook «keeper упал / DDL повис в очереди». Состав дашбордов
и границы — ADR 0002.
@@ -510,7 +523,6 @@ smoke-проверки, а не «дашборд зелёный». Это мин
- «Грязь» в данных: боты, дубли на транспорте, опоздавшие мобильные батчи,
расхождение часов клиент/коллектор — туман карты, вернётся своим тикетом.
- Политика версионирования эталонного артефакта — туман карты.
- Лабы и курс: v2 — другой стенд, лабы для него пишутся с нуля отдельной
работой после этой спеки; редизайн лаб v1 (#7) остаётся в v1 и сюда не
переносится. Спека даёт будущим лабам только опорные точки — контрольные
@@ -550,10 +562,11 @@ smoke-проверки, а не «дашборд зелёный». Это мин
(батчевая генерация вместо посточной, быстрая JSON-сериализация,
распараллеливание по модельным дням). Читаемость генератора для менти —
не довод при выборе языка: он в любом случае сложнее уровня DE-джуна.
До этапа 3 зафиксировать требования производительности (пересборка
эталонного мира, живой поток ×60); переход на компилируемый язык
(Rust/Go) — только если замеры покажут, что Python приемлемой скорости
не даёт.
Числовые требования производительности и способ замера зафиксированы
[спекой генератора](2026-08-01-generator.md), раздел 5 (порядки величин —
[исследование](../research/2026-08-01-python-batch-generation-speed.md));
переход на компилируемый язык (Rust/Go) — только если живые замеры
этапа 2 выйдут за её порог.
## 12. Влияние на документацию