Commit Graph
76 Commits
Author SHA1 Message Date
ddadminandClaude Opus 4.8 fa93aef150 docs(context): глоссарий и спеки приведены в соответствие с ADR-0006
- Зачем:
  - ADR-0006 сделал генерацию единственным источником аналитики, а статический
    сид — архивным; глоссарий и спеки это ещё не отражали.
- Что:
  - CONTEXT.md: «статический сид» переименован в «архивный статический сид»
    (короткое имя сохранено), описан как временная кладовка значений с целью
    полного вывода; «стартовая история» получила синонимы «стартовый сид» и
    «новый сид»; раздел «Слои данных» отмечает переход аналитики на генерацию.
  - мат-спека: разделы «Персистентность через рестарты» и «Воспроизводимость»
    помечены как переописанные в спеке модельного времени (ссылкой, без повтора).
  - спека модельного времени: синоним «стартовый сид» добавлен в определение и
    в заметку о влиянии на документацию.
- Проверка:
  - git diff: термины и перекрёстные ссылки читаются непротиворечиво; ADR не
    правились (статус «архивный» не переносится в документы до ADR-0006).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 15:31:11 +03:00
ddadminandClaude Opus 4.8 49512b190a docs(generator): зафиксированы источник аналитики и стартовая история
- Зачем:
  - генератор даёт здоровую пирамиду, и стенду нужен единый источник аналитики вместо вырожденного статического сида.
- Что:
  - добавлен ADR-0006: генерация — единственный источник аналитики, статический сид становится архивным (кладовка значений до синтеза фактуры).
  - добавлена спека модельного времени: точка отсчёта, заливка прошлого, стартовая история, сохранение состояния, воспроизводимость и проверка в два шага.
  - в ADR-0004 и ADR-0005 добавлены указатели вперёд на ADR-0006 и спеку.
- Проверка:
  - чтение документов; перекрёстные ссылки между ADR-0004/0005/0006 и спекой согласованы.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 14:47:20 +03:00
ddadminandClaude Opus 4.8 899a3f07a1 docs(research): зафиксировано внешнее ревью петли субагентов
- Зачем:
  - закрыть отложенный заход эксперимента: внешнее ревью результата
    автономной петли моделью другой родословной (дизайн-линия, не Кодекс).
- Что:
  - добавлена секция об итогах ревью: прогноз по находке A не оправдался,
    петля её поймала (try→fresh + регрессионный тест в коммите 640050e).
  - зафиксировано, что внешний взгляд добавил сквозные находки (расхождение
    живого/восстановленного путей, форма распределения длины визита).
  - уточнена гипотеза о пользе reviewer-а другой родословной.
- Проверка:
  - git show --stat HEAD; чтение docs/research/2026-06-11-subagent-coordinator-experiment.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 13:17:06 +03:00
Dmitry Dementiev ce3552eaf2 docs(research): зафиксирован эксперимент с координатором субагентов
- Зачем:
  - выводы агентного эксперимента нужны как durable-основа для будущего скилла, а не как одноразовый handoff.
- Что:
  - добавлена research note с гипотезой, протоколом, наблюдениями и ограничениями эксперимента.
  - зафиксированы роли координатора, worker-а и reviewer-а, классификация находок и инварианты будущего скилла.
- Проверка:
  - ручная перечитка docs/research/2026-06-11-subagent-coordinator-experiment.md.
2026-06-11 18:44:07 +03:00
Dmitry Dementiev 341637c810 docs(generator): зафиксирована модель времени генератора (ADR-0005)
- Зачем:
  - инвариант «время генератора ≡ реальное ×1» неудобен для учебного плана:
    медленные явления (возвраты, воронка) не успеть показать на уроке, а
    историческую глубину живой генератор не создаёт.
- Что:
  - добавлен ADR-0005: модельные часы отвязаны от настенного времени, режимы
    (живой ×1 / ускоренный ×K / заливка) — драйверы одного шва, правило 30 минут
    переопределено в модельном времени; сид-продолжение помечено как будущее.
  - в CONTEXT.md разведены три значения «сида» и добавлен термин модельного
    времени и масштаба ×K.
  - добавлен handoff с отложенным ревью петли и реконсиляцией мат-спеки.
- Проверка:
  - прочитать docs/adr/0005-generator-model-clock.md и раздел «Три значения
    слова сид» в CONTEXT.md; git log -1.
2026-06-11 18:37:27 +03:00
Dmitry Dementiev 6c4e0f4d16 feat(generator): подключена новая модель к steady-stream сервису
- Зачем:
  - после калибровки потока и state v2 генератор нужно принять как рабочий steady-stream источник, а не как исторически сломанный прототип.
- Что:
  - добавлен сервисный тест multi-event визита с мок-публикацией во все четыре Kafka-топика.
  - compose позволяет переопределять демо-параметры генератора без правки файла, сохраняя внутренние контейнерные адреса.
  - README, OPERATIONS, KNOWN_ISSUES и карточка задачи синхронизированы с новой моделью и state v2.
- Проверка:
  - uv run --with-requirements generator/requirements.txt pytest generator/tests -q.
  - git diff --check.
  - GEN_STATE_RESET=true GEN_POPULATION_MAX=123 docker compose config.
2026-06-11 18:26:39 +03:00
Dmitry Dementiev 8f1e997cc9 feat(generator): откалиброван поток steady-stream генератора
- Зачем:
  - поток генератора должен соответствовать модели интенсивности и профилю сида перед реализацией состояния версии 2.
- Что:
  - событийный бюджет тика переведён в рождения визитов через ожидаемую среднюю длину визита.
  - дефолты интенсивности и обычный docker-compose запуск синхронизированы с целевыми 30 событиями в минуту.
  - добавлены статистические проверки длины визита, воронки, новых пользователей, межсессионных пауз и долгого окна потока.
  - обновлены README, OPERATIONS и карточка задачи 05.
- Проверка:
  - uv run --with-requirements generator/requirements.txt pytest generator/tests -q.
  - git diff --check.
2026-06-11 17:17:34 +03:00
Dmitry Dementiev 642789d484 refactor(generator): разнесён сервис генератора по src-пакету
- Зачем:
  - перед активными визитами нужно отделить генеративную модель от Kafka, состояния и сервисного цикла.
- Что:
  - перенесены модули генератора в пакет `src/clickstream_generator`.
  - `generator.py` оставлен фасадом и точкой входа с совместимыми импортами.
  - обновлены Dockerfile, тесты, README, спека и issue 02.5.
- Проверка:
  - `docker build -t generator:test generator`.
  - `docker run --rm -v /home/dmitry/sources/clickstream-ch-kafka-superset-demo:/workspace -w /workspace/generator generator:test pytest tests/ -q`.
  - `python -m py_compile generator.py src/clickstream_generator/*.py` в Docker.
2026-06-11 15:00:50 +03:00
Dmitry Dementiev 48e3bf2900 docs(generator): добавлена задача уборки сервиса
- Зачем:
  - перед задачей активных визитов нужно отделить модель генератора от сервисной обвязки.
- Что:
  - добавлена спека уборки сервиса генератора перед задачей 03.
  - добавлена промежуточная issue 02.5 с критериями приёмки.
  - уточнены требования к Dockerfile и временному тиковому слою.
  - задача 03 заблокирована новой задачей уборки.
- Проверка:
  - просмотрен staged diff через `git diff --cached --stat`.
2026-06-11 13:48:24 +03:00
Dmitry DementievandClaude Fable 5 bcca8f5127 docs(generator): уточнена мат-спека по итогам ревью, handoff для передачи
- Зачем:
  - повторное адверсариальное ревью нашло ошибку в формуле межсессионной
    паузы (двойной счёт кулдауна) и незакрытый контракт публикации
    device/geo; дизайн-этап завершён, работа передаётся исполнителю.
- Что:
  - исправлена формула паузы (баланс цикла, минус длительность визита);
    зафиксированы каденция device/geo «на каждое событие, как в сиде»,
    правило выбора возвращающегося, стартовое распределение страниц,
    калибровка по медиане и среднему, инвариант потолков конфигурации,
    компактное хранение профиля ссылкой на сид-сессию.
  - уточнены критерии приёмки (среднее паузы вместо медианы, счёт шага
    «товары», имена полей времени) в обеих спеках.
  - добавлен handoff .scratch/handoffs/2026-06-10-generator-spec-to-codex.md
    (передача на детальный план/реализацию), отработавший handoff от
    2026-06-09 удалён.
- Проверка:
  - цифры спеки сверены замерами по полным data/*.jsonl (стартовые страницы
    58/24/17, шаги воронки 98>=94>=56>=35>=25, device 1000 строк / 99
    уникальных); повторное ревью свежим агентом блокеров не оставило.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 18:02:57 +03:00
Dmitry DementievandClaude Fable 5 6efa031023 docs(generator): добавлена мат-спека модели и исправлен профиль сида
- Зачем:
  - закрыть Open questions спеки формы доработки перед передачей на
    реализацию; адверсариальное ревью показало, что прежние ориентиры
    (популяция/паузы/интенсивность) взаимно несовместимы, а документы
    опираются на неверный факт о сиде («1..7 событий на визит»).
- Что:
  - добавлена docs/specs/2026-06-10-generator-math-model.md: марковская
    цепочка по страницам, формула связи «популяция-интенсивность-пауза»
    (λ по умолчанию 30/мин), кулдаун возврата, правило 30 минут на рестарт,
    критерии приёмки.
  - в CONTEXT.md добавлен профиль сид-датасета (полный замер: длины визитов
    1..27, медиана 10, конверсия 25%, петли и события после /confirmation)
    и исправлено ложное «разброс времени внутри click_id <= 1 мин».
  - исправлен факт «1..7 событий» в KNOWN_ISSUES.md и ADR-0004; критерии
    Validation спеки формы доработки приведены к фактам сида.
- Проверка:
  - перекрёстные ссылки между спеками/ADR/CONTEXT.md открываются; цифры
    профиля сида воспроизводятся скриптом подсчёта по полным data/*.jsonl.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 17:32:47 +03:00
Dmitry DementievandClaude Opus 4.8 6ddc7a90d4 docs(generator): зафиксировано направление переработки генератора
- Зачем:
  - при возврате к генератору не переоткрывать выбор «генератор vs реплей»
    и иметь готовую рамку требований под реализацию steady-stream.
- Что:
  - ADR-0004: steady-stream питается синтетическим иерархическим генератором,
    не реплеем сида (обоснование + отклонённые варианты C/B).
  - спека docs/specs/2026-06-09: требования к иерархической модели сущностей
    и критерии приёмки; математика делегирована follow-up-спеке.
  - CONTEXT.md: термины «популяция пользователей», «возвращающийся пользователь».
- Проверка:
  - прочитать ADR-0004 и спеку; сверить термины в CONTEXT.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 18:04:00 +03:00
ddadminandDmitry Dementiev d97be5fa56 feat(monitoring): добавлен дашборд Grafana для мониторинга generator
- Зачем:
  - нужна визуализация метрик generator в реальном времени
  - Prometheus job уже настроен, не хватает Grafana dashboard
- Что:
  - добавлен provisioning-файл dashboards/generator-overview.json
  - 6 разделов: Overview, Events by Topic, Errors, Tick Statistics, Status, Info
  - Overview: Total Events/min (все 4 топика), Tick Duration (p50/p99)
  - Events by Topic: bar chart Events per Hour, Events Rate, Total Events
  - Errors: Total Errors, Error Rate, Errors by Topic (с 'or on() vector(0)')
  - Tick Statistics: Duration Distribution, Hour Factor (text), Tick Interval (text)
  - Status: Generator Status (threshold 120s), Generator Health (heartbeat), Time Since Last Tick
  - Info: команды и предупреждения о хардкоде GEN_TICK_SECONDS=5s
  - исправлены панели ошибок с 'or on() vector(0)' для корректного отображения 0
  - заменен heatmap на bar chart для стабильности
  - добавлены пояснения про Events/min = сумма 4 связанных топиков
  - Hour Factor синхронизирован с кодом генератора (00-05/09-18)
  - Generator Health: переименовано из State Management с value mappings
  - обновлены docs/OPERATIONS.md и generator/README.md
  - удален устаревший plans/generator-monitoring-plan.md
- Проверка:
  - дашборд открывается на http://localhost:3000/d/generator-overview
  - все панели отображают данные корректно (протестировано через Playwright)
  - ошибки показывают 0 вместо No data
  - Events/min корректно отображает сумму всех 4 топиков (~800-1000/min)
2026-06-09 17:27:17 +03:00
ddadminandDmitry Dementiev ffe81167c3 refactor(generator): удалён in-memory fallback для истории батчей
- Удалён класс InMemoryBatchHistory и вся fallback-логика
- Упрощён KafkaBatchHistory: убраны _initialized, get_stats(), обработка ошибок
- Обновлена документация (generator/README.md, docs/OPERATIONS.md)
- Упрощены тесты, удалены тесты для удалённого функционала
- Код стал честнее: без Kafka генератор падает при старте

Ревьюер: Prometheus даёт достаточно visibility, fallback избыточен
2026-06-09 17:27:16 +03:00
ddadminandDmitry Dementiev cbc2f72871 docs(docs): актуализировано ТЗ и потоки ingest
- Зачем:
  - убрать рассинхрон между кратким ТЗ, архитектурой и планом генератора
- Что:
  - сокращен docs/DE-task.md до формата краткого ТЗ проекта
  - обновлены docs/ARCHITECTURE.md и README.md: bootstrap через kafka_load и steady-stream через generator-service
  - обновлен plans/generator_demo_stream_plan.md: режим steady-stream и тик-публикация
- Проверка:
  - просмотрен git diff по измененным файлам
  - в коммит включены только мои документационные изменения
2026-06-09 17:26:31 +03:00
ddadmin 92e9c4b45a docs(accuracy): профильная документация выверена по коду
- Зачем:
  - профильные доки отстали от реализации: схема ods.*_errors, DQ-split и
    сборка dds.event описывались неверно, ряд артефактов и параметров отсутствовал.
    Канон по этим темам де-факто задают свежие уроки 2–3 курса.
- Что:
  - ARCHITECTURE: ods.*_errors как копия с Kafka-метаданными+raw+error_reason;
    DQ-split подан как пересекающийся; dds.event — browser-driven LEFT JOIN с
    маркером location_not_found; добавлен перечень DQ-маркеров; уточнены
    dq_summary (слой dm, orphan_events) и v_session_overview.
  - REPO_MAP: добавлен sql/ods/20_stg_to_ods.sql, утилиты DAG, скрипты Superset;
    scripts/make помечены как запасной путь, Airflow — основной.
  - OPERATIONS: параметр wait_stg_timeout_sec; порт Superset и креды ClickHouse.
  - SUPERSET_DASHBOARD: исправлен пароль ClickHouse (123456); убран сломанный
    make superset-export, удалён superset/export_dashboard.py и target в Makefile.
- Проверка:
  - git diff проверен против sql/*, airflow/dags/*, configs/default_user.xml;
    ER-диаграмма провалидирована mermaid-валидатором.
2026-06-06 21:43:31 +03:00
ddadmin 2f905e4c73 docs(course): README курса переписан от менти + крючок менторства
- Зачем:
  - прежний README вёл читателя в авторские доки (PRD/LEARNING_PLAN/
    LESSON_STANDARD), а менти нужна точка входа: с чего начать, как ходить
    по урокам и как поднять стенд. Цель PRD — самодостаточный материал.
- Что:
  - mentee-first структура: «что нужно до старта» (make up → ddl →
    LIMIT=50 make data, совпадает с уроками и правилом малого среза),
    индекс уроков 0–6 со ссылками и режимом, «как проходить».
  - блок-крючок «сам / с ментором» в тон роадмапа + CTA в Telegram.
  - авторские доки убраны в секцию «Под капотом курса».
- Проверка:
  - все 11 внутренних ссылок резолвятся; ai-text-lint чист (house style сохранён).
2026-06-06 19:06:16 +03:00
ddadmin bae1e02240 docs(superset): уточнена область фильтров dashboard
- Зачем:
  - нужно снять двусмысленность между native filters и click-to-filter в Superset dashboard.
- Что:
  - описана фильтрация через левую панель Superset.
  - уточнена область действия фильтров по совместимым charts и DM-витринам.
  - зафиксировано, что click-to-filter между виджетами не включен.
- Проверка:
  - git diff --check -- README.md docs/SUPERSET_DASHBOARD.md docs/course/lessons/06_superset_bi.md.
2026-06-06 18:50:50 +03:00
ddadmin d98ae9c48a docs(course): финальный ai-text-lint, синхронизация PRD §7 и уборка handoff'ов
- Зачем:
  - финализация подготовки уроков: пройти обязательный QA-шаг
    (ai-text-lint по LESSON_STANDARD §2), привести PRD к факту и убрать
    отработанные handoff'ы.
- Что:
  - урок 4: убран AI-маркер S01 («не только… но и» → «и… и») по итогам
    прогона ai-text-lint; остальные 6 уроков чисты от маркеров.
  - PRD §7: закрыты устаревшие открытые вопросы (глубина урока 5, Superset),
    оставлен только реальный пункт — ретроспектива после первого прогона.
  - удалены 3 отработанных handoff'а в .scratch/handoffs/.
- Проверка:
  - git show --stat HEAD; визуальная сверка PRD §7 и урока 4.
2026-06-06 18:41:15 +03:00
ddadmin 589c556b17 docs(course): сквозной ревью — правки консистентности уроков 2/3/5 и OPERATIONS
- Зачем:
  - сквозной ревью курса нашёл расхождения учебного текста с реальным выводом
    стенда и один баг в операторских доках — менти увидел бы не то, что в уроке.
- Что:
  - урок 2: порядок строк «Статистики ODS» выровнен под фактический вывод
    run_batch.sh (4 основных таблицы, затем 4 *_errors); снято «по строчкам».
  - урок 3: добавлено пояснение, что check_date — это today() из витрины
    (у менти будет своя дата, не как в примере).
  - урок 5: «должно быть не в Alerting» → «в состоянии Normal (не Alerting)».
  - OPERATIONS.md: несуществующий FULL=1 заменён на реальный knob LIMIT=50
    (по умолчанию полный объём — подтверждено load_kafka_data.sh:27,128).
- Проверка:
  - git diff показывает 4 файла, +9/-6; grep 'FULL=' по docs/ пуст.
  - порядок таблицы сверен с run_batch.sh:111-118; today() — sql/dm/40_dds_to_dm.sql:105.
2026-06-06 18:33:14 +03:00
ddadmin bbd5784e2a docs(course): синхронизирован LEARNING_PLAN с фактом — правки §3.1 сделаны
- Зачем:
  - все 11 чекбоксов §3.1 по урокам 2–3 были `[ ]`, хотя правки давно
    в коде/уроках; план вводил в заблуждение «работа не сделана».
- Что:
  - проставлены `[x]` по урокам 2 и 3 после сверки с реальным кодом
    (шапки «поток данных», DQ-split «зачем», чистка legacy-MV, демоут DM,
    seed 1919, war-story kafka_ts, recap цепочки).
  - в §4 добавлена строка статуса: уроки 0–6 написаны, контент собран.
- Проверка:
  - grep '\[ \]' docs/course/LEARNING_PLAN.md  # незакрытых пунктов §3.1 нет
2026-06-06 18:14:07 +03:00
ddadmin 24f538e6f4 docs(superset): синхронизирован урок 6 с дашбордом
- Зачем:
  - урок 6 должен совпадать с текущей конфигурацией Superset и не вводить в заблуждение по metadata store.
- Что:
  - URL дашборда в уроке переведен на стабильный slug ecommerce-analytics.
  - сниппет Page Funnel помечен как фрагмент с ключевыми полями, а не полный params.
  - устаревший комментарий про SQLite заменен на PostgreSQL metadata store.
- Проверка:
  - python3 -m py_compile superset/init_superset.py superset/create_dashboard.py.
  - git diff --check.
2026-06-06 18:12:06 +03:00
ddadmin bf940cc249 docs(course): пункт интро урока 6 выровнен под row-lineage
- Зачем:
  - после замены DQ-чарта на row-lineage в списке «на какие вопросы отвечает
    BI» остался повисший пункт «есть ли видимые проблемы качества данных» —
    чарта, который на него отвечал, больше нет.
- Что:
  - пункт переформулирован под актуальный чарт Rows by Layer
    («доходят ли строки до витрины без потерь по слоям конвейера»).
- Проверка:
  - сквозная вычитка урока 6: состав чартов, имена и числа согласованы.
2026-06-06 18:01:34 +03:00
ddadmin c9300e7d5d fix(superset): 5-минутные бакеты вместо часовых в графике динамики
- Зачем:
  - все события стенда укладываются в ~50 минут (20:51–21:41 28.11.2022),
    поэтому часовая гранулярность давала всего 2 точки и прямую диагональ,
    которая читалась как ошибка расчёта и ничему не учила менти.
- Что:
  - time_grain_sqla переведён с PT1H на PT5M (~10 точек, реальная форма трафика).
  - чарт переименован «Events by Hour» → «Events over Time» (идемпотентно через
    previous_slice_names), т.к. «by Hour» противоречит 5-минутным бакетам.
  - синхронизированы README, SUPERSET_DASHBOARD.md и урок 6.
- Проверка:
  - python3 -m py_compile superset/create_dashboard.py.
  - make superset-dashboard (идемпотентно, чарт ID 5 переименован, 10 чартов).
  - визуально через playwright-cli: кривая ~11 точек 20:50–21:40, консоль чистая.
2026-06-06 17:58:50 +03:00
ddadmin 2563c79082 docs(superset): синхронизация доков и урока 6 под row-lineage
- Зачем:
  - после смены чарта на row-lineage пользовательская дока, README и урок 6
    описывали несуществующий «Data Quality Summary» и старый состав KPI;
    термин «зерно (grain)» использовался без пояснения.
- Что:
  - SUPERSET_DASHBOARD.md, README, урок 6 описывают «Rows by Layer (event)»,
    выровнен состав KPI/чартов; термин «зерно» поясняется в уроке простыми
    словами с якорем из данных (события 1000 / визиты 99).
  - термин выровнен на «визит» по CONTEXT.md (click_id = визит/сессия).
  - в спеку редизайна добавлена секция «Пересмотр после приёмки» как след решения.
- Проверка:
  - grep по «Data Quality Summary»/«Row Count» вне handoffs пуст.
  - визуальная вычитка изменённых разделов.
2026-06-06 17:49:01 +03:00
ddadmin 1bec6bb8ad feat(superset): обновлен состав KPI и воронки дашборда
- Зачем:
  - нужно убрать дублирующий KPI Unique Sessions и сделать эталонный dashboard честнее для учебного анализа.
- Что:
  - обновлены KPI, добавлена Conversion to /confirmation и Page Funnel.
  - добавлена идемпотентная миграция старых chart names без дублей.
  - синхронизированы документация, урок 6 и спека редизайна.
  - добавлен handoff для продолжения работы в новой сессии.
- Проверка:
  - python3 -m py_compile superset/create_dashboard.py.
  - make superset-dashboard.
  - Superset metadata: dashboard_charts=10, obsolete_unique_sessions=0, page_funnel_type=funnel.
2026-06-06 17:00:02 +03:00
ddadmin 7c7e9e5a7c docs(superset): спека редизайна дашборда и handoff
- Зачем:
  - дашборд-эталон показывал две одинаковые KPI-плитки; нужен честный состав метрик
    на полных данных, зафиксированный до реализации.
- Что:
  - docs/specs/2026-06-06-...: KPI Events/Users/Avg per Visit/Conversion, Top Pages → Funnel, триаж чартов.
  - .scratch/handoffs/2026-06-06-...: handoff для реализации в новой сессии.
- Проверка:
  - числа спеки сверены с прямым запросом в ClickHouse на полном датасете.
2026-06-06 16:12:10 +03:00
ddadmin 18a55dd640 docs(adr): спеки в docs/specs, handoff'ы в .scratch/handoffs
- Зачем:
  - воркфлоу эволюционировал: design-спекам нужен durable-дом, а handoff'ам —
    стабильное место вместо эфемерного /tmp.
- Что:
  - ADR-0002: design-спеки переезжают в docs/specs/YYYY-MM-DD-*.md (superseding ADR-0001).
  - ADR-0003: handoff'ы — одноразовые леса́ в .scratch/handoffs/, коммитятся, уборка best-effort.
  - ADR-0001 помечен как частично заменённый; AGENTS.md описывает место handoff'ов.
- Проверка:
  - docs/adr/000{1,2,3} согласованы, перекрёстные ссылки рабочие.
2026-06-06 16:12:10 +03:00
ddadmin 9f69a33c31 fix(superset): исправлен BI-дашборд и добавлен урок 6
- Зачем:
  - Superset dashboard открывался с ошибками datasources и неудобным layout, а курс не содержал готового урока по BI-витрине.
- Что:
  - добавлен урок 6 про Superset поверх ClickHouse DM-витрин.
  - исправлена раскладка dashboard и дефолтный фильтр даты для исторических демо-данных.
  - добавлено восстановление metadata колонок датасетов при обновлении dashboard.
- Проверка:
  - make superset-dashboard.
  - /api/v1/dashboard/1/datasets и /superset/explore_json для chart 10 возвращают 200.
  - python3 -m py_compile superset/create_dashboard.py; git diff --cached --check.
2026-06-05 22:30:19 +03:00
ddadmin 5f5312c70c fix(dds): починены мёртвые проверки *_not_found + правки урока 3 по ревью
- Зачем:
  - перечитка урока 3 свежим взглядом нашла баг в его эталонном пути: проверки
    device_not_found/geo_not_found/location_not_found в DDS никогда не срабатывали,
    а текст урока ошибочно утверждал, что метки ставятся
- Что:
  - sql/dds/30_ods_to_dds.sql: добавлен SETTINGS join_use_nulls=1 в оба
    INSERT...SELECT. Без него LEFT JOIN на несовпадении клал в assumeNotNull(click_id)
    нулевой UUID (не NULL), и if(...IS NULL, ['*_not_found'], []) молча давал []
    (мёртвый код). Тот же класс бага про типы/NULL, что kafka_ts в уроке 1
  - docs/course/lessons/03_ods_to_dds.md: убраны ложные claim'ы про geo_not_found/
    location_not_found, формулировки приведены к реальному поведению (клик без гео
    остаётся с пустыми полями NULL; целостность событий — через orphan_events);
    поправлена опечатка «список всех клиентов» → «всех кликов»
- Проверка:
  - синтетический тест join_use_nulls=1: клик в device без geo → в ods_parse_errors
    появляются geo_not_found и geo_country_missing (до фикса — пусто)
  - LIMIT=50 make transform после фикса: dds.click=26, dds.event=50,
    orphan_events=0, ни одной строки с непустым ods_parse_errors (вывод не изменился —
    на чистом срезе несовпадений нет)
2026-06-05 21:58:44 +03:00
ddadmin d55f183fc9 docs(course): добавлен урок по мониторингу стенда
- Зачем:
  - нужен завершённый урок 5, который объясняет мониторинг стенда без предположения, что менти уже знаком с Grafana.
- Что:
  - добавлен урок про Prometheus targets, Grafana dashboards, exporters и alert rules.
  - описан управляемый сбой через остановку airflow-scheduler и восстановление стенда.
  - обновлены навигация курса, план урока и названия панелей мониторинга в operations runbook.
- Проверка:
  - git diff --cached --check.
  - сверка названий dashboard/panel/alert rules с provisioning-файлами Grafana.
2026-06-05 20:20:42 +03:00
ddadmin 707da9f80e feat(airflow): добавлен гейт целостности DDS для урока 4
- Зачем:
  - урок 4 должен показывать не только измерение сирот в DDS, но и остановку Airflow DAG при нарушении связи dds.event -> dds.click.
- Что:
  - добавлен assert_dds_integrity в etl_pipeline и документация управляемого красного сценария.
  - вынесены общие helper'ы для SQL-split и boolean-параметров Airflow.
  - добавлен урок 4 и обновлены навигация курса, план обучения и operations notes.
- Проверка:
  - python3 -m py_compile airflow/dags/etl_pipeline_dag.py airflow/dags/ddl_init_dag.py airflow/dags/kafka_load_dag.py airflow/dags/utils/airflow_params.py airflow/dags/utils/sql_helpers.py.
  - docker compose exec -T airflow-webserver airflow dags test etl_pipeline 2026-06-05T18:00:00 -c '{"full_refresh": true}'.
2026-06-05 19:13:22 +03:00
ddadmin 4f1e58752c docs(course): добавлен урок 3 (ODS→DDS, сборка сущностей и сироты)
- Зачем:
  - собрать разрозненные кусочки ODS в цельные сущности DDS и ввести понятие
    целостности связей (сироты), пока без жёсткого гейта — он в уроке 4
- Что:
  - добавлен docs/course/lessons/03_ods_to_dds.md: сущности dds.click/dds.event,
    UNION-универсум кликов, дедуп через argMax, LEFT JOIN, понятие сироты,
    управляемая правка (вставка сироты), recap STG→ODS→DDS, заметка про DM
  - §3.1: «поток данных» в шапку sql/dds/30_ods_to_dds.sql
  - демоут DM: убран закомментированный пример материализации в
    sql/dm/40_dds_to_dm.sql, добавлены «поток данных» и заметка «VIEW сейчас,
    материализуем если затормозит» со ссылкой на docs/ARCHITECTURE.md
  - sql/ddl/dm/40_dm.sql: пояснён seed 1919 в groupArraySample, поправлен
    неверный комментарий «последние» (groupArraySample берёт случайную выборку)
  - README курса: индекс обновлён до «уроки 0–3»
- Проверка:
  - LIMIT=50 make transform: dds.click=26, dds.event=50, orphan_events=0
  - §4 на стенде: вставка события-сироты → orphan 0→1; LEFT JOIN в
    dm.v_events_enriched даёт NULL по полям клика; make transform откатывает к 0
  - /ai-text-lint (article): house style сохранён, AI-маркеры не найдены
2026-06-05 18:33:36 +03:00
ddadmin 79f7103b28 docs(course): стандарт уроков фиксирует регистр, шапку и грабли
- Зачем:
  - наработанный по урокам 0–2 мягкий регистр жил только в памяти и хендоффах;
    стандарт его не требовал — следующий урок мог уехать обратно в сжатый стиль
    и повторить уже пройденные ошибки.
- Что:
  - добавлен §2 «Регистр и голос»: расшифровка терминов на первом употреблении,
    ###-подзаголовки, разбивка «стен», человеческий тон, house style, ai-text-lint;
  - в §1 описана шапка урока (Формат / «О чём урок простыми словами»), старые
    «Статус: черновик» и «Режим: руки» помечены как не возвращать;
  - добавлен §5 «Грабли»: проверять на стенде, сверять имена с DDL, один паттерн
    на урок, спорные API ClickHouse — через MCP Context7;
  - перенумерованы разделы (качество кода → §3, самопроверка → §4) и ссылки на них.
- Проверка:
  - прочитать LESSON_STANDARD.md сверху вниз: §1–§5 идут по порядку, ссылки
    «(раздел 4)» указывают на «Самопроверку».
2026-06-05 18:00:13 +03:00
ddadmin f56166181b docs(course): смягчён регистр уроков 0–1 и убран статус «черновик»
- Зачем:
  - на уроке 2 решили писать разжёванным языком; уроки 0–1 и шапки курса
    остались в сжатом регистре, а слово «черновик»/«Режим: руки» путало менти.
- Что:
  - урок 1: расшифрованы staging, MergeTree-дедуп, Materialized View и
    виртуальные колонки; секция «Загляни внутрь» разбита на ###-подзаголовки;
    плотные абзацы разбиты на пункты; добавлен зачин «О чём урок простыми словами».
  - урок 0: добавлен зачин «О чём урок простыми словами» (лёгкая полировка).
  - шапки всех уроков: «Статус: черновик. Режим: руки/наблюдение» заменены на
    понятное «Формат: практика/наблюдение — …».
  - PRD/LEARNING_PLAN/LESSON_STANDARD: убрано слово «черновик» из статуса.
- Проверка:
  - grep -rn "черновик" docs/course/ — пусто;
  - прочитать урок 1 сверху вниз: термины раскрыты на первом употреблении.
2026-06-05 18:00:13 +03:00
ddadmin 256ac14c66 docs(course): добавлен урок 2 (STG→ODS, типизация и DQ-split)
- Зачем:
  - нужен учебный урок «руки» про типизацию слоя ODS и разделение
    чистых/битых записей; по пути убрать мусор и неочевидности в
    эталонном пути, чтобы он читался за один проход.
- Что:
  - добавлен lessons/02_stg_to_ods.md по LESSON_STANDARD (6 секций,
    режим «руки», эталон голоса — урок 1); регистр смягчён под уровень
    «обзорно» с расшифровкой терминов (click-контекст, WITH, двойной учёт).
  - 20_stg_to_ods.sql: поток данных в шапку + блок «DQ-split» (почему
    строка может попасть и в основную таблицу, и в *_errors).
  - 20_ods.sql: убран мусорный блок из 8 DROP TABLE mv_*_to_ods;
    пояснено разное партиционирование (browser — по бизнес-дате,
    click-контекст — по дате загрузки).
- Проверка:
  - make ddl && make transform — проходят чисто, counts не изменились
    (browser/location 50, device/geo 26 дедуп, *_errors 0).
  - правка §4 (toFloat64OrNull→toInt64OrNull для geo_latitude) на стенде
    даёт geo_by_click_errors 0→50 и NULL-широту с флагом bad_geo_latitude.
2026-06-05 17:08:29 +03:00
ddadmin b15ee90939 docs(course): добавлен урок 0 (вводный по Kafka, наблюдение)
- Зачем:
  - курсу нужна разминка перед уроком 1: связать словарь из обзорного
    видео по Kafka (топик, партиция, offset, группа, lag) с живым стендом.
- Что:
  - добавлен lessons/00_kafka_intro.md по LESSON_STANDARD в режиме
    наблюдения (без управляемой правки и отката), эталон голоса — урок 1.
  - честная врезка про lag: у групп ch_stg_* колонки offset/lag в Kafka UI
    пустые, прогресс чтения смотреть в ClickHouse (system.kafka_consumers).
  - README курса: в строке lessons теперь указаны уроки 0 и 1.
- Проверка:
  - факты сверены на живом кластере: 4 топика *_events по 1 партиции,
    4 группы ch_stg_* (STABLE, 1 участник); прогоном подтверждено, что
    новая группа читает топик с начала (auto.offset.reset=earliest).
2026-06-03 23:25:23 +03:00
ddadminandClaude Opus 4.8 f4d3118a42 docs(course): добавлен урок 1 и выровнена рамка под созвоны
- Зачем:
  - нужен первый урок курса по эталонному пути STG, а рамка курса описывала сопровождение как «сессию-сверку», хотя по факту это самостоятельная работа + еженедельный созвон.
- Что:
  - добавлен docs/course/lessons/01_kafka_to_clickhouse.md (Kafka → ClickHouse, слой STG) по шаблону LESSON_STANDARD.
  - в sql/ddl/stg/10_stg.sql исправлен баг kafka_ts во всех 4 MV: toInt64(DateTime64) срезал миллисекунды, kafka_ts по всему стенду был 1970-01-21; теперь _timestamp_ms присваивается напрямую (downstream на kafka_ts не опирается).
  - урок 1 §3/§4 приведены к исправленному коду; врезка про рассинхрон MV↔таблица описывает реальное поведение (молчаливый сброс лишней колонки, не ошибка).
  - «сессия/сессия-сверка» → «созвон» в PRD (датированная поправка), LESSON_STANDARD §6 (секция «Что должно получиться») и README курса; добавлена ссылка на открытый DE-роадмап.
  - в LEARNING_PLAN исправлен вердикт аудита урока 1 (баг найден прогоном), war-story про toInt64(DateTime64) припаркована в урок 2.
- Проверка:
  - прогон на стенде: make up && make ddl && LIMIT=50 make data → kafka_ts = 2026-… с миллисекундами; правка §4 (ALTER + пересоздание MV + TRUNCATE + перезаливка) и откат отработали.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 23:03:24 +03:00
ddadminandClaude Opus 4.8 d8c5e61a3a docs(course): расщеплён план уроков и зафиксирован аудит путей
- Зачем:
  - середина пайплайна перегружала один урок тремя паттернами; нужны честный такт и разведённые слои.
- Что:
  - середина расщеплена: ODS и DDS — отдельные уроки (один паттерн на урок), DM демотирован в поверхность потребления; всего 7 уроков.
  - зафиксированы финальные вердикты аудита и список правок по урокам (LEARNING_PLAN §3/§3.1), включая гейт целостности DAG.
  - в LESSON_STANDARD добавлены шаг отката «верни как было» и артефакт на сессию; в PRD обновлены скоуп и такт ~день на урок.
- Проверка:
  - вычитка docs/course/{PRD,LEARNING_PLAN,LESSON_STANDARD}.md: номера уроков, скоуп и перекрёстные ссылки сходятся.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 21:22:07 +03:00
ddadmin aecbf392d9 docs(agents): подключена doc/issue-методология Pocock и зафиксирована раскладка
- Зачем:
  - развести документацию по времени жизни: транзиентные спеки отдельно от
    долговечных решений (ADR) и доменного словаря (CONTEXT.md), вместо одного
    громоздкого spec-документа.
- Что:
  - добавлен блок Agent skills в AGENTS.md (issue tracker / triage / domain docs).
  - созданы docs/agents/{issue-tracker,triage-labels,domain}.md: локальный
    markdown-трекер в .scratch/, дефолтные triage-метки, single-context раскладка.
  - зафиксировано решение как docs/adr/0001-spec-adr-issue-layout.md.
- Проверка:
  - git show --stat HEAD; прочитать AGENTS.md и docs/adr/0001-spec-adr-issue-layout.md.
2026-06-01 23:29:50 +03:00
ddadmin dc0e6f9452 docs(course): добавлен продвинутый курс «Кликстрим на ClickHouse»
- Зачем:
  - превратить стенд в самостоятельный учебный материал (трек «со звёздочкой») для продвинутых менти.
- Что:
  - docs/course/: PRD, LEARNING_PLAN, LESSON_STANDARD и README-индекс.
  - AGENTS.md: ссылка на курс в разделе навигации.
  - CLAUDE.md: @-include AGENTS.md для контекста агента.
- Проверка:
  - открыть docs/course/README.md и пройти по ссылкам на PRD/план/стандарт.
2026-06-01 22:28:14 +03:00
ddadmin 60dfe52bb6 docs: обновлены правила оформления коммитов
- Зачем:
  - уточнен приоритет языка (русский по умолчанию)
  - добавлены критерии обязательности body
  - дополнены примеры и шаблоны
- Что:
  - изменен primary language на Russian
  - добавлены правила для AI-generated commits
  - добавлена форма глагола для русского языка (результативная)
  - перенесены шаблоны: Russian → default, English → lang:en
  - обновлены все примеры на русский язык
- Проверка:
  - git log --oneline проверяет формат
2026-02-14 11:14:06 +03:00
ddadmin ec6111d260 fix(superset): stabilize bootstrap after clean reset
- make superset-init run via dedicated init service\n- tolerate missing dm views during early metadata refresh\n- add clickhouse dependency for init service\n- document clean-reset behavior and re-init flow
2026-02-11 09:48:56 +03:00
ddadmin 7819af8688 fix(superset): restore ClickHouse dialect and dataset metadata sync
- switch Superset ClickHouse URI back to clickhousedb://\n- refresh dataset metadata during init to restore filter columns\n- install runtime deps in image layer and add troubleshooting notes
2026-02-11 09:23:48 +03:00
ddadmin 3bed37f532 docs(docs): add 10-15 minute demo script
- Why:
  - align interview demo with recruiter requirement for 10-15 minutes
- What:
  - add timed walkthrough with code, architecture and verification points
  - include fallback steps for UI issues and final speaking script
- Check:
  - verify paths/commands against repository files and DAG ids
2026-02-10 23:57:38 +03:00
ddadmin 22f08382e5 fix(superset): align bootstrap with clickhousedb uri
- Why:
  - Superset bootstrap used outdated ClickHouse URI format and did not fail fast on init errors.
  - docs and exported dashboard metadata diverged from runtime connection settings.
- What:
  - build ClickHouse URI from env vars and use clickhousedb:// in init script.
  - refresh dataset metadata on existing datasets and surface import errors.
  - run create_dashboard during superset-init startup and align docs/exported URI references.
  - ignore node_modules in git.
- Check:
  - python3 -m py_compile superset/init_superset.py
  - manual dashboard smoke check in UI (charts render)
2026-02-10 23:51:38 +03:00
ddadmin 2e48f6065a feat: добавлен дашборд Superset для e-commerce аналитики
- Добавлен сервис superset-init в docker-compose для автоматической инициализации
- Созданы Python-скрипты для инициализации подключения ClickHouse и создания датасетов
- Создан скрипт для автоматического создания дашборда с 10 чартами
- Создан скрипт экспорта дашборда в JSON
- Добавлен экспортируемый JSON дашборда (ecommerce_analytics.zip.json)
- Обновлен Makefile с командами superset-init, superset-dashboard, superset-export
- Добавлена документация docs/SUPERSET_DASHBOARD.md

Дашборд включает:
- KPI блок (Total Events, Unique Users, Sessions, Avg/Session)
- Динамика трафика (Events by Hour, Traffic by Device)
- География (World Map)
- Маркетинг (UTM Effectiveness Table, Top Pages)
- Качество данных (DQ Summary)
- Native Filters (Date Range, Country, Device, Browser)
2026-02-10 20:48:05 +03:00
ddadmin e6c26ce353 docs(docs): add 5-minute demo cheatsheet
- Why:
  - give a student a short, repeatable interview demo script
- What:
  - add 5-minute timeline with speaking prompts
  - add SQL/CLI commands and fallback plan for UI issues
- Check:
  - review markdown content in docs/DEMO_CHEATSHEET_5MIN.md
2026-02-09 18:52:16 +03:00
ddadmin f411a46aea docs(docs): add comprehensive system test plan
- Why:
  - formalize complete end-to-end verification for the demo DWH stack
  - provide fast regression checks and full validation before demo/release
- What:
  - add new TEST_PLAN.md with two execution contours: Smoke and Full
  - include checks for infra bootstrap, Airflow DAG flow, STG/ODS/DDS/DM data quality, monitoring and alert provisioning
  - add dedicated scenario proving dirty records are captured in ods.*_errors without breaking ETL
- Check:
  - aligned steps with current DAG parameters/tasks and SQL transformation flow
  - validated expected alert names against Grafana provisioning files
2026-02-09 09:56:58 +03:00
ddadmin 0e470604fe chore(scripts): add make down and clean targets
- Why:
  - intensive development needs quick cluster stop/cleanup commands
  - current Makefile had only up and pipeline/monitoring targets
- What:
  - add make target down for standard docker compose shutdown
  - add make target clean for full cleanup with volumes and orphans
  - update OPERATIONS runbook with new make commands
- Check:
  - make -n down clean
2026-02-09 09:33:54 +03:00