Commit Graph
179 Commits
Author SHA1 Message Date
ddadminandClaude Fable 5.1 29a01f0016 docs(labs): переписана проза пяти ТЗ ступени 1 и раздел «Как принято»
- Зачем:
  - владелец при чтении забраковал прозу ТЗ ступени 1: образы вместо
    утверждений, заголовки-метафоры, договоренности стенда поданы как
    законы. Тикет #228.
- Что:
  - пять ТЗ (задания 1–5) написаны заново по форме ТЗ ступени 2:
    содержание, колонки, формулы, самопроверка и приемка сохранены.
  - раздел README лаб «Общие правила ступени 1» переименован в «Как принято
    на ступени 1» и переписан как выбор с доводом; точечно поправлены
    «Самопроверка» и таблица ступени 1.
- Проверка:
  - grep по «ё», «менти», формам «ты» и словам-законам по docs/labs/*.md
    молчит (единственное «правило» — в нетронутом разделе «Уборка»).
  - скрипт ссылок и якорей из #226 печатает пусто; git diff --check чист.
  - сверка имен в обратных кавычках и чекбоксов старых и новых файлов —
    без расхождений.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-06 08:44:27 -04:00
ddadmin cffe1aeb73 docs(labs): обращение «вы» во всех учебных заданиях
- Зачем:
  - README и путеводитель обращаются к читателю на «вы», а ТЗ в docs/labs/
    были на «ты»; после пересборки индекса смесь стала заметна.
- Что:
  - во всех восьми файлах docs/labs/ местоимения, глаголы и повелительное
    наклонение переведены во второе лицо множественного числа.
  - названия ступеней в таблице README оставлены как в спеке.
- Проверка:
  - grep по формам «ты/твой», 'ё' и 'менти' по docs/labs/ молчит;
    git diff --check чистый; ревью диффа свежей сессией.
2026-09-03 17:29:13 -04:00
ddadmin 830efa7ef4 docs(labs): ТЗ ступени 2 «Свой график в Superset» и порядок программы
- Зачем:
  - программа лаб принята спекой, но индекс docs/labs/ показывал только
    пять витрин и дашборд; ступень 2 не имела ТЗ (#226).
- Что:
  - новое ТЗ docs/labs/superset-chart.md: один столбиковый график доли
    отказов по устройствам поверх dm.session_overview_v, метрика в датасете.
  - docs/labs/README.md: семь ступеней основной программы и пять разделов
    факультативов; правила пяти витрин помечены как правила ступени 1.
  - шапка docs/labs/superset-dashboard.md: факультатив раздела «Superset и BI».
- Проверка:
  - grep 'ё' и 'менти' по трем файлам молчат; скрипт ссылок из тикета
    печатает пусто; git diff --check чистый.

Closes #226
2026-09-03 17:12:37 -04:00
ddadmin 3fa669a920 docs(handbook): добавлено описание соединений на карте
- Зачем:
  - читатель карты видит ключи переноса данных, не переходя к карточкам узлов.
- Что:
  - для 17 стрелок добавлено поле «Как соединяет», сверенное с SQL.
  - раздел выведен в карточке стрелки и пересобрана карта.
- Проверка:
  - uv run docs/handbook/architecture-map/render.py --check.
  - make lint.
  - make typecheck && make test в generator/.
2026-09-03 04:34:25 -04:00
ddadmin 466acafce6 docs(handbook): интерактивная карта слоев хранилища
Зачем: путеводитель рассказывает путь данных через слои словами, а карта
дает его увидеть и потрогать: у одного смысла в каждом слое свое имя и своя
поверхность, а переносят данные три разных механизма — матвью непрерывно,
даг пачкой, представление без копии. Постановка — тикет #222, форма —
резолюция #208 (один самодостаточный HTML, исходники рядом).

Что: docs/handbook/architecture-map.html — готовая карта; исходники в
docs/handbook/architecture-map/ (map.yaml — слои, узлы, стрелки, карточки;
template.html — разметка, стили, скрипт; render.py — сборка и --check;
README.md). Щелчок по узлу открывает карточку и подсвечивает путь, щелчок по
стрелке — кто и каким SQL переносит данные; переключатель потока приглушает
чужую часть карты. Ссылки карточек ведут в справочники и DDL на Gitea.
Путеводитель и глава о хранилище ведут на карту; make lint проверяет ruff
для сборщика и свежесть рендера; testing.md и AGENTS.md обновлены.

Проверка: uv run docs/handbook/architecture-map/render.py --check и
make lint зеленые; внешних запросов в HTML нет; ссылки и якоря карточек
сверены с Gitea; карта прощелкана в headless Chromium на ширинах
1280–1920: подсветка пути, фильтр, Esc, карточки узлов и стрелок.
Ревью: постановка — Opus; реализация — Codex (Sol), два слепых ревью Opus
(уместность и код), вычитка прозы Sol.
2026-09-03 03:40:14 -04:00
ddadminandClaude Fable 5.1 043d1c1382 docs(handbook): четыре главы переписаны живым русским
Зачем: владелец прочел главы и нашел неестественные фразы: дашборды
«спрашивают», даги «двигают ось», заказ «ездит в слепках», Superset —
«витрины глазами», объекты «приезжают из файлов». Читателю такие
образы надо расшифровывать, а урок в них не прячется.

Что: в четырех главах олицетворения заменены прямыми формулировками,
«позиция мира» и «шаговый даг» раскрыты через world_position и имена
дагов, паспорт мира описан по составу и назначению, окно слепка
заказов объяснено словами, режимы генератора и правило импорта
Superset сказаны прямо. Тире и стрелки оставлены: это домашний стиль.

Проверка: проверки тикета #220 на битые ссылки и запретные слова
пусты, строки прозы не длиннее 80 знаков, git diff --check чист.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 02:00:37 -04:00
ddadminandClaude Fable 5.1 ac21399fe4 docs(handbook): написаны четыре главы путеводителя
Зачем: после главы о хранилище путеводитель обещал еще четыре главы, а
вместо них стояли заглушки «Пока главы нет…». Без них читатель не видит,
кто двигает мир и раскладывает данные по слоям, куда смотреть в Grafana,
как витрина становится графиком и откуда берутся данные.

Что: docs/handbook/airflow-dags.md, monitoring.md, superset.md,
generator.md — по скелетам тикета #220, форма — как у главы о хранилище.
Сквозная линия трех глав: ход мира на день D везет слепок заказов дня D−1,
поэтому выручка всегда на день позади кликстрима. README путеводителя
ведет заголовками в файлы глав, заглушки убраны; «Куда дальше» главы о
хранилище ведет прямо в главу об Airflow.

Проверка: три SELECT из глав прогнаны на живом стенде от analyst — трафик
получил сыгранный день, выручка только предыдущий, счетчики первых восьми
дней совпали с паспортом мира. Скрипт проверки ссылок и запретных слов из
тикета пуст. Постановка отревьюена Opus (18 находок внесены); главы прошли
саморевью Sol и два слепых ревью Opus — факты и проза (ai-text-lint плюс
оптика литературного русского): 25 находок внесены, 1 отклонена.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 17:14:43 -04:00
ddadminandClaude Fable 5 46e82b5240 docs(handbook): написана глава «Хранилище и его слои»
- Зачем:
  - первая глава путеводителя: без нее читатель попадает из README сразу
    в справочники, минуя объяснение пути данных (тикет #218, карта #206).
- Что:
  - добавлена docs/handbook/storage-layers.md: путь STG → ODS → DDS → DM,
    правило чтения через _v, зона dic, таблица ключей соединения слоев
    и два SELECT для самостоятельной пробы.
  - в docs/handbook/README.md раздел «Будущие главы» стал «Главы»,
    аннотация первой главы ведет в ее файл.
- Проверка:
  - обе команды из раздела «Проверка» тикета #218 дают пустой вывод;
    оба SELECT прогнаны на живом стенде от пользователя analyst.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-02 16:15:16 -04:00
ddadminandClaude Fable 5.1 7108cd4af3 docs(readme): корневой README пересобран по четырем блокам
Зачем: README был складом сведений, осевших там, где писались. По
раскладке резолюции #211 он становится лицом репозитория: промо-блок,
«куда я попал», типовые действия, ссылки. Слово «менти» уходит из README
и путеводителя, хвосты #212 и #214 закрываются.

Что: промо-цитата со ссылкой на план обучения и ментора; шапка с
нейтральной адресацией и одной фразой о составе и пути данных; «Быстрый
старт» сжат до двух команд по решению владельца — проверки остаются
роботам, в README одна ссылка на карту проверок; разделы «Адреса и
пароли», «Сдвинуть мир вперед», «Вернуть мир к началу», «Выключить или
сбросить целиком», «Подключиться из DBeaver»; «Документация» называет все
семь справочников вложенным списком. Умерли «Статус», «Что здесь будет»,
«Чем отличается от предшественника» и три заголовка-якоря. В world.md
снята устаревшая фраза о «даге этапа 5», stand.md и ADR 0007 ведут на
новый раздел «Адреса и пароли», в путеводителе снято слово «менти».

Проверка: скрипт ссылок пуст, grep «менти» по README и путеводителю пуст,
make config-test зеленый. Саморевью Sol 1/1; слепое ревью Opus — 0
блокеров, 2 minor, 3 nit, все закрыты; вычитка прозы ai-text-lint и
оптикой литературного русского — 15 находок, 9 внесены, 6 отклонены как
слова владельца и термины.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-02 15:37:04 -04:00
ddadminandClaude Fable 5.1 59d8c83b17 docs(glossary): четыре термина переименованы, world.md и stand.md вычитаны
- Зачем:
  - справочники читает человек со стороны, а «пульт мира», «опись мира»,
    «работник» и «сырьё» звучали шуткой или калькой времён разработки
    (тикет #214, выбор владельца).
- Что:
  - CONTEXT.md: статьи «Паспорт мира», «Даги модельного времени»,
    «Шаговый даг», «Сырые данные», старые слова в строках «Избегать»;
    пометки в ADR 0005, 0008, 0009 без переписывания решений.
  - замены по README, справочникам, путеводителю, лабам, спекам,
    комментариям дагов и SQL, тегу дага и панели Grafana; имена в коде
    не тронуты.
  - world.md и stand.md: 35 находок вычитки внесены, регистр выровнен.
- Проверка:
  - make config-test; make lint в корне и в generator/; make test в
    generator/ (437 passed); скрипт ссылок из #212 пуст; grep старых
    слов вне ADR, research и CONTEXT.md пуст.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QBCtU38qSHg5DvgtnKXcW
2026-09-02 16:46:50 +03:00
ddadminandClaude Fable 5.1 7a3542d933 docs(architecture): ледгер stand.md разбит по темам, кальки в world.md сняты
Зачем: ревью владельца по PR #213. Сверка конфигурации в stand.md
приехала из README одним абзацем на двадцать строк, а Superset был
приклеен к Airflow без пустой строки. Три места в world.md читались
калькой с английского.

Что: ледгер «Что проверено» разбит на записи по темам — ClickHouse,
Kafka, метрики и Grafana, Airflow, Superset. В world.md заголовок
«Как позвать генератор» стал «Как запустить генератор» (якоря в README
и generator/README.md обновлены), переписаны абзацы про значения по
умолчанию и про сокет Docker. Смысл не менялся. Словарь проекта
(«пульт мира», «опись мира», «работник», «сырье») не трогался: это
термины CONTEXT.md и ADR, их пересмотр — отдельная развилка.

Проверка: скрипт ссылок из тикета — пустой вывод; make config-test —
ЗЕЛЁНО; старый якорь «как-позвать-генератор» в репозитории не встречается.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QBCtU38qSHg5DvgtnKXcW
2026-09-01 23:04:45 +03:00
ddadminandClaude Fable 5.1 bad5981904 docs(architecture): операторские разделы README переехали в справочники
Зачем: README служил складом для двух зон без своих справочников —
«службы и доступ» и «мир и его пульт». Раскладка принята резолюцией
#211: README остается лицом, устройство живет в docs/architecture/.

Что: новые docs/architecture/stand.md («Стенд: службы, доступ,
настройка», доводы — ADR 0001 и 0007) и docs/architecture/world.md
(«Мир и его пульт», доводы — ADR 0009 и 0013). Доводы смоука и
описания целей make слиты в testing.md без повторов: фраза о
check_containers_survived и абзац про config-test умерли как дубли.
На месте каждого переехавшего раздела README — абзац со ссылкой,
адреса и пароли интерфейсов остались. Путеводитель и README
генератора ссылаются на world.md вместо якорей README. Переехавший
текст не правился, только относительные ссылки.

Проверка: скрипт ссылок из тикета — пустой вывод; make config-test —
ЗЕЛЁНО; подиффовая сверка переехавших диапазонов с README@2588515 —
без расхождений (слепое ревью); в новой прозе нет «ё».

Closes #212

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QBCtU38qSHg5DvgtnKXcW
2026-09-01 22:49:23 +03:00
ddadminandClaude Fable 5 ab35560ece docs(handbook): скелет путеводителя и человеческая шапка README
- Зачем:
  - менти негде было понять с первого экрана, что перед ним и куда идти;
    тикет #209 карты #206 открывает учебную документацию стенда.
- Что:
  - создан docs/handbook/README.md: тропа чтения и пять аннотированных
    будущих глав с временными ссылками на справочники.
  - шапка README.md переписана для менти: четыре действия и ссылки на
    путеводитель и уроки; в разделе «Документация» добавлены handbook и labs.
  - в AGENTS.md добавлено правило имен для docs/handbook/.
- Проверка:
  - команда проверки ссылок из тикета #209 — пустой вывод;
  - git diff: операторские разделы README не тронуты.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-01 14:15:25 -04:00
ddadminandClaude Fable 5 453950a639 docs(specs): итог тикета #203 внесен в раздел 9 спеки программы лаб
- Зачем:
  - раздел 9 отсылал к открытому тикету #203; решение принято, указатель
    должен вести на итог, а не на вопрос.
- Что:
  - фраза «докуда ведет карта #182» заменена итогом: карта закрыта приемкой
    спеки, исполнение ведет карта #206.
- Проверка:
  - вычитка раздела 9 файла docs/specs/2026-09-01-labs-program.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-01 09:32:27 -04:00
ddadmin eed5b4b4e6 docs(specs): словарь программы лаб очеловечен по ревью владельца
- Зачем:
  - термины спеки перейдут в задания, а «хребет», «ветки» и «точка
    прицепа» с калькированными заголовками сюжетов смущали бы студентов.
- Что:
  - хребет → основная программа, шаги → ступени, ветки → факультативы,
    «точка прицепа» заменена формулой «открывается после ступени N»;
  - заголовки разделов и сюжетов переписаны из позиции студента
    («Почему выручка не сходится», «Куда попадают битые строки»);
  - переносы выровнены по ~80 колонок по всему файлу.
- Проверка:
  - текст без учета пробелов не изменился на шаге переносов (SHA-256);
    решения, состав и порядок программы не менялись.
2026-09-01 09:07:40 -04:00
ddadmin 4fd872f296 docs(specs): спека программы учебных лаб — хребет и ветки
- Зачем:
  - тикет #202 карты #182: собрать из инвентаризации #201 программу лаб
    целиком — состав, порядок, формы и судьбу идей-кандидатов.
- Что:
  - создан docs/specs/2026-09-01-labs-program.md: хребет из семи
    обязательных шагов и пять тематических разделов необязательных лаб;
  - узаконены границы вычитания по потокам и поименные резолюции идей
    #143, #145, #148, #149, #186, #187, #188;
  - записаны отклоненные варианты оси прогрессии и границы спеки (#203).
- Проверка:
  - вычитка владельцем (спека принята), слепое ревью фактов против
    инвентаризации и доков — все находки закрыты.
2026-09-01 08:45:43 -04:00
ddadminandClaude Fable 5 502d705ca1 docs(research): инвентаризация сюжетов лаб по слоям стенда
- Зачем:
  - спеке программы лаб (#202) нужен полный веер сюжетов вместо семи
    случайно накопленных идей; резолюция тикета #201 карты #182.
- Что:
  - заметка docs/research/2026-08-31-labs-inventory.md: 32 сюжета по
    слоям STG, ODS, DDS, DM, BI и поперек слоев, три формы заданий,
    разбор гипотезы «вычитание + DQ» с таблицей по потокам.
- Проверка:
  - фактура (пути, имена таблиц, номера тикетов) сверена с репозиторием
    при вычитке; кода изменение не касается.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 11:38:54 -04:00
ddadminandClaude Fable 5 6174536cc1 docs(specs): BI-лаба узаконена в исключении раздела 10
Зачем: раздел 10 выносил все лабы v2 в отдельную работу учебного пути,
делая исключение только для домашек DM, — необязательная лаба Superset
из #197 формально в него не попадала.

Что: исключение расширено фразой про лабу «свой дашборд в Superset» с
меркой владельца: домашки DM и эта лаба продуманы до готовых ТЗ,
остальные лабы пока на уровне идей.

Проверка: вычитка; решение владельца репозитория из обсуждения #197.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 04:05:43 -04:00
ddadminandClaude Fable 5 989ff71495 docs(labs): ТЗ необязательной лабы «свой дашборд в Superset»
Зачем: владеть хотя бы одним BI-инструментом на базовом уровне — полезный
навык дата-инженера, но стенд в первую очередь про ClickHouse, поэтому
лаба необязательная. Обещание «отдельная домашка после этапа 8» в доке DM
висело без адреса.

Что: ТЗ docs/labs/superset-dashboard.md — пять датасетов поверх публичных
представлений заданий 1-5, свой дашборд отдельно от стендового, проверка
глазами без homework_check; шестая строка и разведение «пяти заданий по
витринам» в docs/labs/README.md; абзац о сроке жизни объектов менти в
docs/architecture/superset.md; ссылка на лабу из доки DM; правило слага в
AGENTS.md расширено до «предмет задания».

Проверка: кода и DDL нет; слепое ревью текста (9 находок закрыто, 2
дополнительные с перепроверки) и финальная вычитка.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 03:55:40 -04:00
ddadminandClaude Fable 5 3ffce6387e feat(superset): датасеты и дашборд «Бизнес-сюжеты» деревом импорта
- Зачем:
  - этап 8 (#196): три сюжета спеки — выручка, сверка, посетители /
    известные — должны приезжать в Superset при каждой инициализации
    стенда, без ручной сборки в интерфейсе.
- Что:
  - дерево infra/superset/import/ дополнено датасетами трех витрин dm,
    тремя графиками и дашбордом «Бизнес-сюжеты»; uuid розданы рукой,
    русские строки читаемы, metadata.yaml сокращен до версии формата.
  - написан справочник docs/architecture/superset.md: устройство зоны,
    дерево импорта, маршрут свежего экспорта, ловушки импорта.
  - в docs/architecture/dm.md добавлена ссылка на справочник зоны.
- Проверка:
  - docker compose run --rm superset-init — импорт начисто, затем три
    графика отдают данные через API (54/48/10 строк).
  - прогон рецепта «чистая установка» из справочника: сброс базы superset
    в postgres-metadata, импорт, активы на месте.
  - make lint и make check-services зеленые (7/7).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 18:42:01 -04:00
ddadminandClaude Fable 5 9b1826f5ff feat(generator): откалиброваны доли заказной стороны
- Зачем:
  - семь мест обещали калибровку черновых долей «при пересборке
    эталонного мира (этап 7)», а пересборки не будет (#192); числа
    сверены замером и зафиксированы (#194, хвост этапа 7 — #9).
- Что:
  - замер на каноническом мире (28 дней, без транспорта): все доли в
    пределах ориентиров; пометки «черновое» сняты, наблюдаемые доли
    вписаны в комментарии world.py, fate.md и запись «Что проверено»;
  - потеря purchase: наблюдаемых 1,78% при броске 3% — вычеты штатные
    (пары склейки, приоритет отмены), принято решением владельца;
    ориентир класса B в мастер-спеке различает бросок и наблюдаемую долю;
  - веса мира и опись не тронуты: правки world.py — только комментарии.
- Проверка:
  - cd generator && make lint && make typecheck && make test (437 passed);
  - git diff по data/world-inventory.json пуст; grep «черновое|калибровка»
    по generator/src и docs/architecture/orders пуст.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 16:42:32 -04:00
ddadminandClaude Fable 5 8b7987c5c2 docs(specs): снято обещание CI-генерации на amd64 и arm64
- Зачем:
  - CI дублировал бы сторожем то, что уже гарантировано устройством:
    дисциплина целочисленной случайности снимает межархитектурные
    расхождения (решение владельца 2026-08-30, хвост этапа 7 — #9).
- Что:
  - резолюция вписана в раздел 5 спеки генератора;
  - строки этапа 7 в обеих спеках приведены к резолюции.
- Проверка:
  - grep "CI гоняет" docs/specs/ пуст; чтение раздела 5.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 16:11:34 -04:00
ddadminandClaude Fable 5 c1b61d81b9 feat(generator): эталонный мир зафиксирован равным стартовому
- Зачем:
  - у дней 8-13 описи не нашлось читателя: обещание эталона в 14 дней
    снято решением владельца 2026-08-30 (#192, этап 7 — #9).
- Что:
  - резолюция перенесена в обе спеки, докстринг описи и словарь CONTEXT.md;
  - добавлен тест: проигранный через CLI день совпадает с хешем описи;
  - сняты замеры: пересборка описи 20,5 с, снимок 460,7 МБ, make test
    176,5 с — записаны в карту проверок и таблицу бюджетов.
- Проверка:
  - cd generator && make lint && make typecheck && make test (437 passed);
  - git diff по data/world-inventory.json пуст.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 15:53:52 -04:00
ddadmin c68a451698 docs(orders): восстановлено описание окна опоздания
- Зачем:
  - при перевёрстке абзаца пропало правило отсутствия заказа до дня приезда.
- Что:
  - восстановлен диапазон скрытых слепков d…d+δ−1.
  - исправлена пунктуация и прояснено обнуление задержки назначенного заказа.
- Проверка:
  - git diff --check.
  - make config-test.
2026-08-29 02:03:24 -04:00
ddadmin 8db1c58c12 feat(generator): добавлено опоздание заказов в слепках
- Зачем:
  - менти должен увидеть, как запоздавшая выгрузка меняет открытое окно, не подделывая аудит источника.
- Что:
  - заказам назначена задержка D, D+1 или D+2 последним броском подпотока ORDERS.
  - назначенный планом заказ приезжает сразу, а Woven передаёт эту гарантию именованным полем.
  - обновлены документы, проверки границ механики и эталонные хеши слепков.
- Проверка:
  - make lint, make typecheck и make test в generator: 436 тестов прошли.
  - make config-test: конфигурация прошла проверку.
  - world_live_day и следующий etl_pipeline перевели заказ 20260608-0001 из awaiting_order в match.
2026-08-28 17:30:55 -04:00
ddadminandClaude Fable 5 c28f724706 feat(generator): потеря и дубль purchase (B, D) и счетчики описи
- Зачем:
  - трекер стенда был полным, и правило «деньги — по бэкенду» держалось
    на слове; классы B и D делают недосчет и пересчет трекера
    наблюдаемыми (этап 6, #184).
- Что:
  - подпоток BEACONS: точечная потеря purchase (~3%) и сюжетный дубль
    (~2%) швом после _purchases, с гарантией моста идентичностей и
    условием допуска дубля по паузе до следующего визита;
  - опись считает пять классов по приоритету спеки; фильтр
    classes_vs_inventory расширен, нулевой класс читается нулем;
  - fate.md, seeds.md, dm.md и orders/README.md приведены к имени
    BEACONS и строгому правилу допуска.
- Проверка:
  - make lint, make typecheck, make test (433 passed) и make inventory
    из generator/ — хеши слепков не изменились;
  - на стенде: make smoke, make check-clickhouse, make check-services
    зеленые; в dq_summary classes_vs_inventory и sessions_vs_reference
    pass, витрина сверки показывает lost_event и duplicate_event.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-28 13:13:47 -04:00
ddadminandClaude Fable 5 6f18e9989c docs(generator): заморожена спека этапа 2, решения — в ADR 0015-0017
- Зачем:
  - спека разрослась до 1058 строк, а журнал решений в разделе 9 читался
    только целиком; агентам и людям нужен дешевый адресный заход к
    основаниям решений генератора.
- Что:
  - заведены ADR 0015 (пояс счетчика), 0016 (паспорт куки) и 0017 (номер
    заказа); четыре адресные ссылки на «раздел 9» перешиты на них.
  - раздел 9 пересобран в 11 тематических подразделов с датами и тикетами
    у каждого решения и закрыт пометкой о заморозке; устаревшие
    промежуточные замеры свернуты до указателей на актуальные.
  - строка статуса в шапке отмечает закрытие спеки как документа этапа 2.
- Проверка:
  - wc -l docs/specs/2026-08-01-generator.md (951, было 1058);
    rg -n 'раздел[а-яё]* 9|разделы 8 и 9' docs -g '*.md' — 18 попаданий,
    все классифицированы; разделы 1-8 нетронуты (сверка хешем).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-28 08:16:11 -04:00
ddadmin 74061aa499 Merge branch 'main' into 48-generator-guide 2026-08-28 06:06:19 -04:00
Dmitry Dementiev cd4f9c55f5 docs(compose): объяснение общей сборки сокращено
- Зачем:
  - ADR и комментарии повторяли устройство Compose и говорили о сборке безлично.
- Что:
  - в Compose оставлен один указатель на причину решения.
  - ADR хранит правило общей сборки и объясняет гонку Buildx.
- Проверка:
  - make config-test.
  - git diff --check.
2026-08-28 13:03:47 +03:00
ddadminandClaude Fable 5 0c466c082e docs(generator): путеводитель по генератору и живой проход make demo
- Зачем:
  - спека отвечает «почему», а жанра «как пройти устройство по коду»
    не было (#48); черновик в generator/README.md ждал выверки.
- Что:
  - новый набор docs/architecture/generator/: индекс с целевой картиной
    и mermaid-схемой плюс шесть поддокументов по темам тикета.
  - демо-модуль и цель make demo: канонический D0, все стадии цепочки
    на одном экране; тест-сторож проверяет стадии без прибитых чисел.
  - раздел «Как это работает» в generator/README.md сжат до ссылки
    на путеводитель, черновая врезка снята.
- Проверка:
  - из generator/: make lint, make typecheck, make test (430 passed),
    make demo; два слепых ревью и узкая перепроверка — находки закрыты.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-28 06:00:36 -04:00
Dmitry Dementiev 1f203c974d fix(compose): устранена гонка сборки общих образов
- Зачем:
  - make up иногда падал, когда несколько служб параллельно экспортировали один тег образа.
- Что:
  - сборка образов Airflow и Superset закреплена за службами инициализации.
  - зависимые службы только используют готовый образ, решение описано в ADR 0001.
- Проверка:
  - make config-test.
  - docker compose --progress plain build superset superset-init airflow-scheduler airflow-init.
  - два запуска make up прошли экспорт трёх уникальных тегов без image already exists.
2026-08-28 12:53:33 +03:00
ddmitry 5946175efa Merge pull request 'fix(grafana): исправлена загрузка плагина при сборке' (#177) from fix/grafana-plugin-download into main
Reviewed-on: #177
2026-08-28 12:42:27 +03:00
ddadmin cc836fc3c5 fix(superset): стабилизирована проверка рабочего контура
- Зачем:
  - холодный запуск второго приложения Superset давал ложный красный результат исправного стенда.
- Что:
  - тяжёлые `create_app()` и `superset test-db` заменены проверкой сохранённого подключения через REST API.
  - добавлены проверка схемы `dm`, безопасная диагностика и краткая запись приёмки с замерами.
- Проверка:
  - `make config-test`.
  - `make smoke`: 21/21 за 25 секунд.
  - три `make check-services` после перезапуска Superset: 7/7 за 71, 67 и 70 секунд; финальный прогон — 7/7 за 70 секунд.
  - контрольный неверный UUID: 5/1, красной стала проверка метаданных.
2026-08-28 12:38:54 +03:00
Dmitry Dementiev e422e6d1fa fix(grafana): исправлена загрузка плагина при сборке
- Зачем:
  - make up падал с HTTP 451 при загрузке плагина из каталога Grafana.
- Что:
  - закреплённый выпуск плагина загружается из официального GitHub Releases.
  - версия плагина вынесена в один аргумент сборки, причина выбора описана в справочнике мониторинга.
- Проверка:
  - docker build --progress=plain -t clickstream-grafana:local infra/grafana.
  - docker run --rm --entrypoint grafana clickstream-grafana:local cli --pluginsDir /usr/share/grafana/plugins plugins ls.
  - make config-test.
2026-08-28 12:31:48 +03:00
ddadminandClaude Fable 5 17995d4c5e fix(airflow): формулировки пульта переписаны живым русским
- Зачем:
  - владелец на ревью PR #175 отметил кальку в подсказках; читать их
    будет менти, и язык здесь — часть продукта.
- Что:
  - переписаны подсказка формы days, докстринги работников, строки
    журнала remember_played, абзац README и пункт в etl.md; смысл
    не менялся.
- Проверка:
  - make lint, make config-test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-28 05:14:51 -04:00
ddadminandClaude Fable 5 c2c4401a16 feat(airflow): пульт мира объясняет ось дней в форме и журнале
- Зачем:
  - оператор принимал служебную logical_date Airflow за дату мира (#111),
    а документацию читают реже, чем форму запуска.
- Что:
  - у параметра days появилась подсказка description_md, а в докстринги
    работников добавлена фраза: день определяет world_position, служебные
    поля Airflow к оси мира отношения не имеют.
  - remember_played пишет в журнал сыгранные дни и новую позицию.
  - README дополнен абзацем про служебные поля за «Advanced Options»;
    из etl.md сняты устаревшие стыки на закрытые #7 и #2.
- Проверка:
  - make lint, make config-test; ручной прогон world_next_day зелёный,
    позиция 9 -> 10, в журнале «сыграны дни 9–9, позиция теперь 10».

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-28 05:05:44 -04:00
ddadminandClaude Fable 5 f33d75113d feat(dm): добавлены учебные задания витрин и даг самопроверки
- Зачем:
  - менти строит витрины DM сам, от DDL по правилу зерна до задачи в
    конвейере; стенду нужны ТЗ с образцом и обратная связь по каждой
    витрине (#159, резолюция #135).
- Что:
  - docs/labs/: README и пять ТЗ — events_enriched_v, top_pages_daily,
    session_overview, dq_errors_daily, utm_effectiveness; каждое ТЗ
    называет урок, состав колонок, форму по зерну и самопроверку.
  - dags/homework_check.py: ручной даг, задача на витрину, красная без
    витрины или при расхождении; проверки — шесть файлов sql/dq/ с
    инвариантами против DDS и ODS, без золотых констант; в dq_summary
    не пишет.
  - docs: dm.md называет homework_check и снимает «Остается нарезке»,
    §7 и §10 мастер-спеки согласованы с лабами, dds/session.md указывает
    на ТЗ, AGENTS.md пополнен правилом имен docs/labs/.
- Проверка:
  - make lint; make smoke 21/21, make check-clickhouse 10/10,
    make check-services 7/7.
  - на свежем стенде все пять задач homework_check красные и называют
    ТЗ; черновик каждой витрины по тексту ТЗ зеленит свою задачу,
    после сноса — снова красная; строк от самопроверки в dq_summary нет.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 17:44:15 -04:00
ddadmin 54686651df fix(dq): устранено переполнение памяти проверок
- Зачем:
  - параллельный DQ выгружал деловые ключи в Python и исчерпывал 640 МиБ планировщика.
- Что:
  - четыре сверки агрегируют дневные итоги и ограниченную диагностику в ClickHouse.
  - коробка планировщика поднята до 1,5 ГиБ, локальные пределы задач удалены.
  - измерения и граница между SQL и Python записаны в документации.
- Проверка:
  - make lint, make config-test, make smoke, make check-clickhouse, make check-services.
  - полный etl_pipeline, красный и восстановительный прогоны dq_check.
2026-08-27 11:25:19 -04:00
ddadmin 26b2e5fea1 feat(dq): добавлен контроль качества конвейера
- Зачем:
  - конвейеру нужна публикуемая сводка текущего качества с красным завершением при нарушении договоров.
- Что:
  - добавлены DDL, публичное представление и пять сверок на естественном деловом зерне.
  - даг dq_check встроен после DM и публикует полные дневные партиции до именованных утверждений.
  - параллелизм DDS, DM и DQ приведён к измеренному лимиту памяти планировщика.
- Проверка:
  - make lint; make config-test; make rebuild-storage.
  - make smoke; make check-clickhouse; make check-services.
  - три семейства проверок покрашены искусственными расхождениями и восстановлены повторным полным прогоном.
2026-08-27 07:55:28 -04:00
ddadmin cec11edaf3 chore(repo): влиты изменения задачи 155
- Зачем:
  - ветка ETL должна учитывать новую витрину `purchase_vs_orders` из `main`.
- Что:
  - `origin/main` влит без переписывания истории опубликованного PR;
  - `dm_transform` теперь собирает третью витрину внутри общего конвейера.
- Проверка:
  - `make config-test`, `make lint`;
  - `generator`: `make lint`, `make typecheck`, `make test` — 429 тестов;
  - `make rebuild-storage`, `make smoke`, `make check-clickhouse`, `make check-services`;
  - импорт DAG без ошибок, `purchase_vs_orders` заполнена.
2026-08-27 12:23:02 +03:00
ddadmin 20071c565f feat(dm): добавлена сверка покупок с заказами
- Зачем:
  - показать расхождения трекера и бэкенда на зерне заказа
  - сохранить отложенные покупки наблюдаемыми до следующего слепка
- Что:
  - добавлены таблицы, представление и пересборка purchase_vs_orders
  - сумма покупки нормализована в Decimal на границе ODS
  - обновлены договоры и указатели на механику пересборки
- Проверка:
  - `make config-test`, `make lint`
  - `cd generator && make docs lint typecheck test`
  - `make rebuild-storage`, явные `dds_transform` и `dm_transform`
  - `make smoke`, `make check-clickhouse`, `make check-services`
2026-08-27 04:21:15 -04:00
ddadmin 61e662c19c refactor(etl): упрощена проверка готовности Kafka
- Зачем:
  - верхние смещения можно получить тем же административным клиентом без одноразового Consumer и фиктивной группы.
- Что:
  - чтение хвоста переведено на AdminClient.list_offsets с OffsetSpec.latest.
  - назначение system.one названо рядом с запросом, а документация и запись проверок сокращены и переставлены по смыслу.
- Проверка:
  - make config-test; make lint.
  - живые проверки готового и отсутствующего разделов Kafka; полный etl_pipeline.
2026-08-27 11:17:43 +03:00
ddadmin 12a5c109b2 feat(etl): добавлен дневной конвейер трансформаций
Зачем:
- Один запуск должен одинаково работать из жизненного цикла, вручную после разгона и повторно после отказа.

Что:
- Добавлена последовательная сцепка DDS и DM с ожиданием каждого слоя.
- DDS дожидается смещений Kafka и очереди доставки ClickHouse за общий срок.
- ETL встроен в создание мира и живой день; документация приведена к новому графу.

Проверка:
- make config-test; make lint.
- make smoke: 21/21; make check-clickhouse: 10/10; make check-services: 7/7.
- make rebuild-storage, живой и пакетный дни, искусственный отказ и ручное восстановление ETL.
2026-08-27 02:43:29 +03:00
ddadmin da0477f0f1 feat(dm): добавлены витрины выручки и трафика
Зачем:
- Показать два ритма пересборки агрегатов на готовых витринах DM.

Что:
- Добавлены физические модели и публичные договоры revenue_daily и daily_traffic.
- Добавлен dm_transform с оконной заменой выручки и полным пересчетом трафика.
- Отрицательный опыт локального соединения через публичные _v зафиксирован; выбран явный GLOBAL LEFT JOIN.
- Замены партиций сериализованы после подтвержденного OOM при трех одновременных задачах.
- Обновлены архитектурные документы и мастер-спека.

Проверка:
- make lint, make config-test, make smoke, make check-clickhouse, make check-services.
- Чистая сборка world_recreate, dds_transform и dm_transform; меры сверены с прямыми агрегатами.
2026-08-26 13:55:26 -04:00
ddadmin 39ff0b5bb4 feat(dds): добавлена карта идентичностей
- Зачем:
  - реализованы требования issue #153 к мосту между кукой и пользователем.
- Что:
  - добавлены физическая карта, точное представление и полный пересчёт через GLOBAL JOIN.
  - задача identity_map поставлена после сборки заказов в dds_transform.
  - устройство и живые проверки карты записаны в документации хранилища.
- Проверка:
  - make lint, make smoke, make check-clickhouse, make check-services.
  - три запуска dds_transform: 4770 физических строк и 1590 уникальных пар в _v.
2026-08-26 12:30:40 -04:00
ddadmin a9cead2974 docs(orders): документация перестроена вокруг текущей модели
- Зачем:
  - описание вело нового читателя через историю исправления вместо действующего
    контракта слоёв.
- Что:
  - прямо описаны версия заказа, границы пакетного приёма и расчёт окна DDS.
  - ответственность ODS, DDS и конвейера разделена без ссылок на прежние
    ошибки как на основной довод.
  - исторический вывод исследования помечен до устаревшего абзаца, а ссылки
    ведут к отдельным решениям и контрактам.
- Проверка:
  - make lint.
  - make config-test.
2026-08-26 18:47:22 +03:00
ddadminandClaude Opus 5 a82c75705d feat(ods): версией заказа стала дата слепка, окно DDS — из данных
- Зачем:
  - ярлык snapshot_date выжившей строки доставался жребием, а объём
    пересборки DDS держался на константе окна с двумя несверяемыми копиями
    (ADR 0014, развилка #163).
- Что:
  - ods.order_rep переведена на ReplacingMergeTree(snapshot_date): выживает
    строка позднейшего слепка, ярлык стал правдивым.
  - order_scope.sql выводит окно из дней последнего слепка; ORDER_WINDOW_DAYS
    и параметр window_days сняты со стенда, мёртвая защита краем источника
    убрана.
  - документы и комментарии SQL приведены к ADR 0014: роль ODS, условие
    «одна дата — один слепок», объём прогона и слепые пятна конвейера.
- Проверка:
  - make lint; make rebuild-storage, затем make smoke, make check-clickhouse,
    make check-services — зелёные.
  - после двух слепков snapshot_date всех 1917 строк ods.order_v равен
    последнему слепку заказа, расхождений ноль; деловые поля построчно
    совпали с эталоном argMax по updated_at из сырья.
  - dds_transform без K: первый прогон 06-01…06-07, после нового дня мира
    06-02…06-08, повтор прогона содержимого не изменил.

Closes #165

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 17:28:14 +03:00
ddadminandClaude Opus 5 176cf5520d feat(dds): добавлена модель сессии и нарезка визитов окнами
Зачем:
- Дать слою расчётную сущность, которой в потоке нет: стенд режет визиты сам,
  а VisitID генератора остаётся эталоном самопроверки.
- Отделить прожитый день от живого — иначе визит, начатый в 23:50, замёрз бы
  обрезанным навсегда: пересобирать замёрзший день слой не станет.

Что:
- Добавлены dds.session_rep/_dist, двойник-донор dds.session_stage_rep/_dist и
  публичный договор dds.session_v.
- Нарезка стоит на двух окнах: первое ставит шов там, где пауза длиннее
  тридцати минут, второе считает нарастающий итог швов — номер визита. Границу
  суток держит разбиение окна, отдельной проверки ей не нужно.
- Порядок в окнах полный, по метке времени и event_id: сортировок две, и при
  равных метках они разошлись бы, разорвав сессию надвое.
- Объём прогона считается от первой дыры в слое по последний прожитый день;
  прожитый день выводится из позиции мира и первого дня событий. Собирать
  нечего — группа задач пропускается, а не зеленеет впустую.
- В dds_transform появилась группа session рядом с заказом; зависимости по
  данным между ними нет.
- Потолок max_active_tasks: размноженная замена без него выносит планировщика
  за отведённые ему 640 МиБ.
- parallel_distributed_insert_select у сессий не назначается вслух — ключ
  шардирования у источника и цели один по контракту ко-локации.
- Записано, что позиция отвечает за «прожит», а не за «доехал»: сторож хвоста
  потока приезжает отдельным тикетом.

Проверка:
- make lint
- make smoke (21 проверка), make check-clickhouse (10), make check-services
- Стартовый мир, пересобранный с нуля: 79367 сессий за восемь дней;
  расхождение с uniqExact(VisitID) по паре «кука × день» — ноль; все 401185
  событий ровно в одной сессии; session_id уникальны.
- Ни одной паузы длиннее тридцати минут внутри сессии и ни одной пары соседних
  визитов куки, разделённой меньшим промежутком.
- Повтор после DROP PARTITION ALL: те же session_id и то же содержимое строк.
- Снесённая руками партиция 2026-06-04: следующий прогон взял хвост от неё,
  дни до дыры не тронуты.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 07:56:44 -04:00
ddadminandClaude Fable 5 c361c36e3d docs(adr): версия заказа в ODS пересмотрена на дату слепка
- Зачем:
  - лотерея ярлыков доставки при ничьей по updated_at делала слой
    недетерминированным и держала окно K двумя копиями без сверки (#163).
- Что:
  - добавлен ADR 0014: версия ods.order — snapshot_date, с ответом доводу
    ADR 0010, границами допущения и веером отклонённых вариантов.
  - в ADR 0010 помечен пересмотр колонки версии.
- Проверка:
  - реализация и замеры — тикет #165; решение кодом пока не применено.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 06:38:46 -04:00
ddadminandClaude Opus 5 1e8b83ffbb feat(dds): добавлена модель заказа и пересборка окна заменой партиций
Зачем:
- Дать слою первую физическую сущность и показать идемпотентность, устроенную
  иначе, чем в приёме: заменой партиции, а не колонкой версии.
- Родить механику дневной пересборки на кластере — образец для сессий и витрин.

Что:
- Добавлены dds.order_rep/_dist, двойник-донор dds.order_stage_rep/_dist и
  публичный договор dds.order_v с разбором позиций в три массива.
- Добавлены запросы объёма прогона, сборки в двойник и замены партиции по дню.
- Добавлен даг dds_transform: группа задач order, замена — размноженной задачей.
- Окно изменяемости K пришло на сторону стенда якорем compose; владелец числа
  остаётся у генератора.
- Объём считается от позднейшего дня заказа и первого недостающего дня: ярлыки
  доставки ODS для этого непригодны, а максимум собранного дня прячет дыры.
- Записано, чего конвейер о себе не знает, и адресовано контуру DQ.

Проверка:
- make lint
- make smoke, make check-clickhouse, make check-services
- Прогон по стартовому миру: 1917 заказов, счёт равен ods.order_v, каждый заказ
  на шарде своего cityHash64(order_id), сумма позиций равна items_total.
- Повтор без нового слепка: содержимое то же, _load_id новый; после слепка
  пересобрано окно, день за окном не тронут.
- Снесённая руками партиция 2026-06-01 восстановлена побайтово.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 05:20:39 -04:00