- Зачем:
- закрыть 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>
7.0 KiB
ADR-0004: Steady-stream источник — синтетический иерархический генератор, не реплей
Принято: 2026-06-09
Статус: accepted
Связано: generator/KNOWN_ISSUES.md (диагноз
дефекта), CONTEXT.md,
ADR-0002 (спеки как durable design-доки),
спека docs/specs/2026-06-09-generator-rework-hierarchical.md
(форма доработки).
Решение
Режим steady-stream (живой поток на стенде) питается синтетическим
генератором, переписанным с нуля по иерархической модели «популяция
пользователей → сессии → события», а не реплеем статического сида. Модель
интенсивности текущего генератора (Poisson по тикам + дневной коэффициент +
jitter) сохраняется. Режим bootstrap (статический сид data/*.jsonl) и уроки
0–6 остаются прежними — генератор сосуществует с сидом, не заменяет его.
Контекст
Проект сменил назначение на учебный стенд с курсом. Базовый курс стоит на
статическом сиде, и это осознанно: сид честен внутри визита (click_id
группирует несколько событий — настоящая воронка; по полному замеру 2026-06-10 —
1..27 событий, медиана 10, см. профиль сид-датасета в CONTEXT.md). Но у сида
два потолка, которые
сид принципиально не закрывает:
users == sessions— каждый пользователь имеет ровно одинclick_id(1:1), возвращающихся пользователей нет (см.CONTEXT.md).- одноразовость — сид заливается батчем; не видно, как ClickHouse и витрины ведут себя на непрерывном живом потоке.
Нужен режим, в котором стенд живёт и движется на правдоподобных данных (воронка + жизнеподобные колебания интенсивности), при скромном объёме (у менти может не быть мощного железа — на объём/стресс не закладываемся).
Двойная учебная ценность — ключевой критерий выбора: ценны не только данные
(живой стенд + честная пирамида users < sessions < events), но и сам
генератор как объект изучения — его генеративная модель достойна того, чтобы её
разбирать в курсе.
Текущая реализация генератора не дорабатывается инкрементально: у неё
концептуальный дефект модели сущностей (свежий click_id на каждое событие
схлопывает иерархию — см. generator/KNOWN_ISSUES.md), переписываем с нуля.
Рассмотренные варианты
- A — синтетический иерархический генератор (принято). Популяция юзеров с
постоянным
user_domain_id→ 1..N сессий (click_idна сессию) → 1..M упорядоченных по времени событий с правдоподобной воронкой. Единственный вариант, дающий возвращающихся пользователей (users < sessions < events) и учебную ценность самого моделирования. Цена — самый большой объём работы и риск ошибиться в статистической модели. - C — реплей честного сида на часах. Лить реальные записи сида в Kafka во
времени, переписывая
event_timestampв «сейчас», зацикливая пул и модулируя rate. Отклонено. Дёшев и даёт гарантированно честную воронку почти без риска, но: (1) обходит ровно ту генеративно-модельную часть, ради учебной ценности которой всё и затевается; (2) наследует вырождениеusers == sessionsиз сида — полную пирамиду не даёт никогда; (3) «бесконечность» = зацикленный конечный пул. - B — минимальный «живой» генератор с грубой воронкой. Тот же rewrite, но воронка на фиксированных вероятностях, без глубины. Отклонено как половинчатое: числа воронки менее убедительны, а вопрос возвратов всё равно надо решать — то есть основной сложности не избегает.
Последствия
- Режим
steady-streamфиксируется как синтетическая генерация; направление переоткрывать не нужно (типовой вопрос «почему не реплей?» закрыт здесь). bootstrap-сид и уроки 0–6 не трогаем; живой поток подаётся отдельным уроком 7.- Контракт данных потока: здоровая пирамида
users < sessions < events, монотонное время внутри сессии,click_idпереиспользуется внутри сессии. Этот контракт наследуют будущие артефакты (спека доработки, урок 7, возможные правки витрин). - Детальная архитектура/требования — в спеке
2026-06-09-generator-rework-hierarchical.md. - Статистическая модель (распределения событий/сессия, сессий/пользователь, межсессионные паузы; нужен ли настоящий session-timeout; персистентность популяции через рестарты) выносится в отдельную follow-up-спеку и здесь намеренно не фиксируется.