chore(scratch): уборка одноразовых материалов и handoff новой фичи

- Зачем:
  - после слияния feature/data-generator одноразовые материалы .scratch
    (задачи 01-21, PRD, журналы, старые handoff'ы) больше не нужны:
    долговечное живёт в docs/, история — в git (срез 0e312b3).
- Что:
  - удалено всё содержимое .scratch (50 файлов).
  - добавлен handoff 20260719-2229-mentee-path-start.md: направление
    редизайна пути менти (4 задачи) и пилот GitHub Issues.
- Проверка:
  - git show --stat; в .scratch остался только новый handoff.
This commit is contained in:
2026-07-19 22:29:44 +03:00
parent 0e312b3c6c
commit de7f62cbab
48 changed files with 89 additions and 5114 deletions
@@ -1,65 +0,0 @@
# Handoff: спеки генератора готовы — передача на детальный план и реализацию
Дата: 2026-06-10
Ветка: `feature/data-generator`
Жанр: одноразовые леса́ (ADR-0003) — durable-рассуждение в спеках/ADR/CONTEXT, не здесь.
> Место: `.scratch/handoffs/` по [ADR-0003](../../docs/adr/0003-handoffs-in-scratch.md)
> (перекрывает generic-дефолт скилла «temp dir»: мультимашинность + worktrees).
> Предыдущий handoff (2026-06-09-generator-rework.md) отработал и удалён.
## Где остановились
Дизайн-этап переработки генератора **завершён**. Спека математической модели
написана, прошла **два** адверсариальных ревью свежими агентами (второе ревью
ловило ошибки правок первого — практика себя оправдала), все находки закрыты,
ключевые цифры перепроверены замерами по полному сиду. Кода по-прежнему
не трогали.
Разделение ролей (см. память проекта): дизайн/спеки — Fable, **детальный план
и реализация — Codex 5.5**. Следующая сессия — скорее всего, подготовка задачи
для Кодекса или сама реализация.
## Документы (источники истины, не пересказываю)
- **Мат-модель (главный документ для исполнителя):**
`docs/specs/2026-06-10-generator-math-model.md` — марковская цепочка по
страницам, формула «популяция ↔ интенсивность ↔ пауза», кулдаун, правило
30 минут на рестарт, критерии приёмки.
- **Форма доработки:** `docs/specs/2026-06-09-generator-rework-hierarchical.md`
(Open questions закрыты ссылкой на мат-спеку).
- **Почему генератор, а не реплей:** `docs/adr/0004-steady-stream-synthetic-generator.md`.
- **Профиль сид-датасета (опора калибровки):** `CONTEXT.md`, раздел
«Профиль сид-датасета» — измерено по полным файлам 2026-06-10.
- **Диагноз дефекта старого кода:** `generator/KNOWN_ISSUES.md`.
## Ловушки (одной строкой; детали — в спеках)
- Ранний «факт» **«1..7 событий на визит» был неверен** (срез файла); реально
1..27, медиана 10. Если встретишь «1..7» где-то ещё в доках/коде — это
остатки ошибки, чинить по профилю сида.
- **Формула паузы в мат-спеке обязательна** при смене λ/популяции; кулдаун в
неё не прибавляется (уже учтён балансом). Вторая ревизия исправляла именно
двойной счёт — не откатить случайно.
- **device/geo публикуются на каждое событие** (как в сиде) — это контракт с
ETL, не деталь.
- `event_timestamp` событий — **запланированное** время, не момент отправки
тика (иначе метки прилипают к сетке тиков).
- Модель интенсивности (`_calculate_events_count`) сохраняем; дефолт
`GEN_LAMBDA_BASE_PER_MIN` меняется 200 → 30.
## Следующий шаг
Передать пару спек Кодексу: детальный план реализации → код. Уровень спек
сознательно «решения и инварианты, без алгоритмов» — конкретику исполнитель
достраивает сам. Возможная подготовка: оформить задачу в `.scratch/<feature>/`
по `docs/agents/issue-tracker.md` (скилл `to-issues`, если план дробить).
## Suggested skills (для следующей сессии)
- **`to-issues`** — если решим дробить реализацию на задачи в локальном трекере.
- **`tdd`** — для этапа реализации (pytest-набор `generator/tests/` существует,
но писался под старую модель — пересмотр под новую неизбежен).
- **`adversarial-review`** / **`code-review`** — ревью реализации против
мат-спеки перед вливанием.
- **`conventional-commits`** — коммиты по правилам репозитория.
@@ -1,66 +0,0 @@
# Handoff: генератор разбит на AFK-задачи
Дата: 2026-06-11
Ветка: `feature/data-generator`
Жанр: одноразовые леса по [ADR-0003](../../docs/adr/0003-handoffs-in-scratch.md).
## Где остановились
После обсуждения с пользователем дизайн переработки steady-stream генератора
переведён из больших спек в локальные задачи для агентов. Код генератора не
меняли.
Создан каталог задач:
- `.scratch/feature-data-generator/issues/01-minimal-connected-visit.md`
- `.scratch/feature-data-generator/issues/02-visit-page-path-and-monotonic-time.md`
- `.scratch/feature-data-generator/issues/03-tick-stream-with-active-visits.md`
- `.scratch/feature-data-generator/issues/04-user-population-and-returns.md`
- `.scratch/feature-data-generator/issues/05-intensity-and-flow-calibration.md`
- `.scratch/feature-data-generator/issues/06-state-v2-and-restart.md`
- `.scratch/feature-data-generator/issues/07-service-integration-and-docs.md`
Все задачи имеют `Status: ready-for-agent`. Разрез сделан как последовательные
вертикальные срезы, а не как слои архитектуры. Решение пользователя: идти по
этому варианту.
## Важный контекст
- Старый генератор считаем слабым прототипом, а не ценным кодом для сохранения.
Сохранять надо внешние контракты, если они полезны: топики Kafka, формат
сообщений для текущего ETL, команды запуска, метрики, идею compact-топика
состояния.
- Отдельную задачу "зафиксировать внешний контракт" не создавали: контракт
встроен в первый и последний срезы.
- Детали модели не дублировать отсюда. Источники истины:
- `docs/specs/2026-06-10-generator-math-model.md`
- `docs/specs/2026-06-09-generator-rework-hierarchical.md`
- `docs/adr/0004-steady-stream-synthetic-generator.md`
- `CONTEXT.md`
- `generator/KNOWN_ISSUES.md`
- Предыдущий handoff `.scratch/handoffs/2026-06-10-generator-spec-to-codex.md`
остаётся полезным как предыстория спек.
## Следующий шаг
Начать с задачи 01 через TDD:
1. написать один красный тест на публичное поведение "минимальный связанный
визит";
2. реализовать минимальное новое генеративное ядро без Kafka;
3. не тащить старую плоскую модель `generate_batch()`;
4. после зелёного теста переходить к следующему поведению, не писать все тесты
заранее.
Пример запуска задачи:
```text
/goal Реализовать .scratch/feature-data-generator/issues/01-minimal-connected-visit.md с использованием /tdd. Соблюдать цикл: один тест на наблюдаемое поведение → минимальная реализация → зелёный тест → остановиться и отчитаться. Не писать все тесты заранее, не реализовывать задачи 02-07.
```
## Suggested skills
- `tdd` — для реализации каждой задачи короткими циклами red-green-refactor.
- `adversarial-review` или `claude-team-review` — после реализации нескольких
срезов, чтобы сверить код с мат-спекой.
- `conventional-commits` — при фиксации следующих изменений.
@@ -1,86 +0,0 @@
# Handoff: ADR про модельное время генератора + отложенное ревью петли
Дата: 2026-06-11
Ветка: `feature/data-generator`
Жанр: одноразовый handoff по [ADR-0003](../../docs/adr/0003-handoffs-in-scratch.md).
## Зачем этот handoff
Сессия с Fable шла в стиле brainstorm-with-docs про **модельное время
генератора**. Параллельно идёт эксперимент: автономная петля субагентов Кодекс
(координатор + worker + reviewer) доделывает срез генератора (задачи 06→07).
Эти две линии **намеренно разделены** — пересмотр времени не правит то, что петля
строит на реал-тайм-модели. Handoff фиксирует, что уже сделано и что осталось,
чтобы не потерять контекст в новой сессии.
## Что сделано в этой сессии (durable, не дублирую — см. файлы)
- Создан **[ADR-0005](../../docs/adr/0005-generator-model-clock.md)** «Модельные
часы генератора, отвязанные от настенного времени». Все решения там; кратко:
модельное время расцеплено с `now()`; режимы (живой ×1 / ускоренный ×K /
заливка `K → ∞`) — драйверы поверх одного шва; живой стенд масштабируется ×K
(дефолт ×1); правило 30 минут переопределяется в **модельном** времени с
параметрическим origin возобновления; «стартовая история стенда»
(сгенерированное прошлое + заморозка state v2) — **будущее направление, ещё не
строим**.
- Правки **[`CONTEXT.md`](../../CONTEXT.md)** (глоссарий): разведены три значения
слова «сид» (`GEN_SEED` / статический сид / стартовая история стенда) и добавлен
термин «модельное время и масштаб ×K».
**Эти изменения (ADR-0005 + CONTEXT.md) ещё НЕ закоммичены.** Их коммит — выход
брейншторма пользователя, его нельзя мешать с коммитами кода от петли (06/07).
Отдельный docs-коммит.
## Открытые線 для следующей сессии
### 1. Отложенное ревью результата автономной петли (приоритет)
Делать **после** того, как петля закоммитит задачу 07. Это read-only ревью.
Измерительный лист — в памяти проекта
`memory/ralph-loop-experiment-generator.md`. Главное:
- **A (главный индикатор эксперимента):** ссылочная целостность при
`restore_state`. `_validate_v2_payload` проверяет только форму, не ссылки.
Структурно-валидный state v2 с висячей ссылкой визит→пользователь
(`generator/src/clickstream_generator/runtime.py:283`) или пользователь→словарь
(`runtime.py:253/255`) проходит `from_dict_safe` и роняет `restore_state` без
обёртки try→fresh. Прогноз: петля это **пропустит** (слепые зоны внутри одной
линии Кодекс скоррелированы). Проверить гипотезу локально структурой с висячей
ссылкой (как пользователь проверял оценку снимка 4.7 MB и падение на битой
вложенности).
- **B/D (проверено OK ранее):** кулдауны по меткам, не тикам (`runtime.py:104`);
детерминизм компактного снимка (`_stable_event_id`, restore не жжёт ГПСЧ).
Подтвердить, что 06→07 их не сломали.
- **C (риск, вне скоупа 06):** всплеск досылки созревших событий с прошлыми
метками на первом тике после рестарта — всплыл ли хоть как риск в саморевью.
- Верхнеуровневое для 07: границы задачи, честность отметок acceptance, не
смешаны ли 06/07, `git status`.
Цель ревью двойная: (1) корректность 06/07; (2) мета-вывод — **какой класс
дефектов автономная петля систематически не видит без внешнего взгляда другой
модели**.
### 2. Реконсиляция мат-спеки с ADR-0005
После ревью петли. Разделы «Персистентность» и «Воспроизводимость» в
`docs/specs/2026-06-10-generator-math-model.md` написаны от настенных часов;
привести в соответствие с ADR-0005 (модельное время, правило 30 минут в
модельном времени). Не делать сейчас — файл смежен с тем, что петля трогала.
## Фон (память проекта, не дублирую)
- `memory/ralph-loop-experiment-generator.md` — схема Ральф-цикла + измерительный
лист.
- `memory/generator-full-rework.md`, `memory/fable-design-codex-implementation.md`
— направление переработки генератора и разделение ролей Fable(дизайн)/Codex(код).
- `.scratch/handoffs/2026-06-11-subagent-coordinator-experiment.md` — детальная
схема эксперимента с координатором и наблюдения по циклам 05/06.
## Suggested skills
- `conventional-commits` — для отдельного docs-коммита ADR-0005 + `CONTEXT.md`
(не мешать с кодом петли).
- `brainstorm-with-docs` — когда вернёмся к реконсиляции спеки или к проектированию
«стартовой истории стенда» (будущее направление из ADR-0005).
- `handoff` — после ревью петли зафиксировать рефлексию эксперимента (что петля
поймала/пропустила, особенно по находке A).
@@ -1,242 +0,0 @@
# Handoff: эксперимент с координатором субагентов
Дата: 2026-06-11
Ветка: `feature/data-generator`
Жанр: одноразовый handoff по [ADR-0003](../../docs/adr/0003-handoffs-in-scratch.md).
## Зачем нужен этот handoff
Пользователь хочет провести эксперимент: не реализовывать следующие задачи
самому верхнеуровневому агенту, а использовать его как координатора цепочки
субагентов. После эксперимента планируется отдельно отрефлексировать, что
сработало, что не сработало и стоит ли закреплять такой процесс.
Этот документ фиксирует текущее понимание процесса перед запуском, чтобы не
потерять договорённости в новой сессии.
## Текущий рабочий контекст
Активная линия работы — переработка steady-stream генератора кликстрима.
Задачи лежат в `.scratch/feature-data-generator/issues/`.
Уже выполнены и ожидают человеческой приёмки:
- `01-minimal-connected-visit.md`
- `02-visit-page-path-and-monotonic-time.md`
- `02-5-generator-service-cleanup.md`
- `03-tick-stream-with-active-visits.md`
- `04-user-population-and-returns.md`
Оставшаяся последовательность:
1. `05-intensity-and-flow-calibration.md`
2. `06-state-v2-and-restart.md`
3. `07-service-integration-and-docs.md`
Задачи зависимы и, вероятно, меняют близкие файлы генератора, поэтому запускать
их надо строго последовательно, не параллельно.
В рабочем дереве на момент обсуждения была незакоммиченная правка только в
`.scratch/feature-data-generator/issues/06-state-v2-and-restart.md`: добавлен
комментарий, что задачу 06 нельзя начинать до завершения предыдущих срезов,
особенно задачи 05.
## Договорённая схема эксперимента
Верхнеуровневый агент не включает для себя `/goal`. Его роль — координатор и
gatekeeper, а не непосредственный исполнитель.
Для каждой задачи:
1. Координатор запускает нового worker-субагента на ровно один issue.
2. Задание субагенту формулируется в стиле `/goal`:
- реализовать конкретный файл задачи;
- работать по методике `/tdd`;
- не реализовывать следующие задачи;
- не коммитить;
- не откатывать чужие изменения;
- в конце отчитаться по изменённым файлам, тестам, проверкам и рискам.
3. После реализации тот же субагент делает саморевью в отдельной роли:
- остановиться;
- проверить результат против acceptance criteria, спеки и тестов;
- искать ошибки, лишний объём, хрупкость и нарушение учебной читаемости;
- сначала выдать находки с важностью, не исправляя их сразу.
4. Координатор решает, какие замечания достаточно важные.
5. Тот же субагент исправляет только одобренные важные замечания.
6. Координатор проверяет верхнеуровневые вещи:
- границы задачи;
- список изменённых файлов;
- честность отметок acceptance criteria;
- тесты;
- `git status`;
- отсутствие смешивания нескольких задач.
7. Коммит делает координатор, не субагент.
8. Координатор закрывает агента и переходит к следующему issue новым
worker-субагентом.
Для сложных переходов, особенно после задачи 05 перед задачей 06, можно добавить
отдельного reviewer-субагента. Это не обязательный шаг на каждую задачу, а
контрольная мера, если есть риск, что саморевью исполнителя недостаточно.
## Роль координатора
Координатор не должен пытаться заново глубоко реализовывать или полностью
повторять работу субагента. Его польза — в управлении процессом:
- держать порядок задач;
- ограничивать область изменений;
- читать отчёты и принимать решения;
- запускать исправления только по существенным замечаниям;
- делать финальный обзор diff на уровне границ и рисков;
- выполнять проверки и коммитить.
Главный риск верхнеуровневого `/goal`: он может заставить координатора
оптимизировать работу под закрытие большой цели, а не под аккуратное управление
этапами. Поэтому для координатора `/goal` не использовать.
## Почему саморевью тем же субагентом допустимо
Пользователь отмечает, что на практике субагенты хорошо делают “ревью свежим
взглядом” внутри уже накопленного подробного контекста задачи. Это может быть
полезнее, чем полностью внешний поверхностный обзор координатора, которому не
хватит деталей реализации.
Ожидаемая модель:
- субагент глубоко понимает сделанную задачу и проверяет её на несостыковки;
- координатор не доверяет этому слепо, но оценивает адекватность выводов и
границы изменений;
- для особо рискованных мест можно подключить отдельного проверяющего агента.
## Suggested skills
- `tdd` — должен использовать worker-субагент при реализации каждой задачи.
- `conventional-commits` — использовать координатору перед созданием каждого
коммита.
- `claude-team-review` — опционально после задачи 05 или перед задачей 06, если
нужен дополнительный независимый взгляд на модель.
- `handoff` — после эксперимента зафиксировать рефлексию: что получилось, что
не получилось, какие правила стоит оставить.
## Возможная первая команда субагенту
```text
/goal Реализовать .scratch/feature-data-generator/issues/05-intensity-and-flow-calibration.md с использованием /tdd.
Работай только в границах этой задачи. Не реализовывай задачи 06-07.
Не коммить. Не откатывай чужие изменения.
Сначала прочитай сам issue и источники решений, указанные в нём. Работай
вертикальными TDD-срезами: один тест на наблюдаемое поведение -> минимальная
реализация -> зелёная проверка -> следующий тест.
В конце остановись и отчитайся:
- какие файлы изменены;
- какие тесты добавлены или изменены;
- какие проверки запускались и с каким результатом;
- какие acceptance criteria закрыты;
- какие риски или спорные места остались.
```
После этого координатор должен попросить того же субагента выполнить саморевью
результата, не исправляя замечания до отдельного решения координатора.
## Наблюдения во время эксперимента
### Цикл 05: интенсивность и калибровка потока
Стартовая задача оказалась дорогой по обратной связи: это не локальный инвариант,
а отладка статистической модели на длинных симуляциях. Первый worker долго
работал без промежуточного отчёта; координатору пришлось сначала поставить
мягкий статус-чек в очередь, затем прервать агента ради статуса. Это не сломало
работу, но показало: для статистических задач лучше заранее задавать контрольные
точки или ожидать длинный первый цикл.
Саморевью того же worker оказалось полезным. Оно нашло несколько реальных
несостыковок:
- `docker-compose.yml` оставлял старую интенсивность `GEN_LAMBDA_BASE_PER_MIN=200`;
- тест межсессионной паузы был слишком широким;
- в тестовой конфигурации оставались старые числа;
- README мог быть двусмысленным про `GEN_MIN/MAX_EVENTS_PER_TICK`.
Координаторская проверка тоже добавила ценность: после саморевью был найден
конфликт между новым `GEN_LAMBDA_BASE_PER_MIN=30` и старым нижним пределом
`GEN_MIN_EVENTS_PER_TICK=5`. При тике 5 секунд это давало минимум 60 событий в
минуту и ломало критерий интенсивности. Worker исправил это отдельной точечной
итерацией.
Полезная схема цикла:
1. worker реализует задачу;
2. координатор прерывает только если агент слишком долго молчит;
3. worker делает саморевью без правок;
4. координатор выбирает, какие замечания чинить;
5. worker чинит только выбранные пункты;
6. координатор добавляет свой узкий sanity-check по связям между дефолтами,
документацией и критерием задачи;
7. координатор коммитит.
Результат цикла 05:
- коммит `8f1e997 feat(generator): откалиброван поток steady-stream генератора`;
- полный прогон: `uv run --with-requirements generator/requirements.txt pytest generator/tests -q`
— 96 passed;
- `git diff --check` — без замечаний.
Промежуточный вывод: тот же субагент действительно хорошо использует подробный
контекст задачи для саморевью, но координатор всё равно нужен как внешний
проверяющий связей между настройками, обычным запуском и acceptance criteria.
### Reviewer-субагент между задачами
После задачи 06 пользователь предложил добавить отдельного reviewer-субагента
между задачами. Это выглядит особенно полезно на границах вроде 06 -> 07, где
следующая задача будет опираться на уже изменённые состояние, сервисный цикл и
документацию.
Важное ограничение: reviewer не является источником истины. Его находки нужно
рассматривать как гипотезы и классифицировать координатором:
- `чинить до коммита` — реальный дефект или риск закрытия acceptance criteria;
- `записать как риск` — важно знать, но не блокирует текущую задачу;
- `ложная тревога` — reviewer неверно понял код, тест или границы задачи;
- `вне скоупа` — может быть полезно позже, но не относится к текущему issue.
Только находки из первой группы возвращаются worker-агенту на исправление.
Иначе есть риск превратить reviewer-а в источник лишнего объёма и расползания
задачи.
В цикле 06 это правило сразу пригодилось. Саморевью исполнителя и отдельный
reviewer независимо нашли два существенных риска:
- битое state v2 с валидным ГПСЧ могло пройти `from_dict_safe`, а затем уронить
сервис уже в `restore_state`;
- снимок активных визитов сохранялся полными batch-словарями и на верхних
лимитах получался порядка мегабайт, хотя спека говорит про компактное
состояние.
Координатор проверил обе гипотезы локально: `restore_state` действительно падал
на битой вложенной структуре, а оценка JSON-снимка при 200 активных визитах и
популяции 300 дала около 4.7 MB. Эти находки классифицированы как `чинить до
коммита` и возвращены worker-агенту. Низкие замечания про совместимость
`generate_tick_batch` и пересечение сервиса с задачей 07 не стали правками:
первое оказалось ложной тревогой, второе — допустимым пересечением для
восстановления state v2.
После крупной переделки по замечаниям reviewer-а нужен второй круг ревью. В
цикле 06 это подтвердилось: исправление компактного состояния само изменило
дизайн снимка и восстановление активных визитов. Второй reviewer нашёл новый
дефект уже в исправленной версии: формально похожий v2-state с `population=[]`
или строковым `pending_visit_births` проходил первичную загрузку, но затем
оставлял поток без пользователей или ронял следующий тик. Координатор
подтвердил это локальной проверкой и вернул worker-агенту как единственный
обязательный пункт второго круга.
В цикле 07 reviewer оказался полезен уже не для поиска падений, а для силы
доказательства. Worker добавил сервисный тест с мок-публикацией, но внешний
reviewer заметил, что один опубликованный event доказывает четыре топика и
связи, но слабее доказывает невырожденную модель «один визит -> несколько
событий с одним `click_id`». Координатор классифицировал это как `чинить до
коммита`: финальный интеграционный тест должен доказывать именно уход от старой
плоской модели, а не только факт публикации.
@@ -1,76 +0,0 @@
# Handoff: ADR-0006 (источник аналитики) + спека модельного времени
Дата: 2026-06-14
Ветка: `feature/data-generator`
Режим работы: дизайн (brainstorm-with-docs), не реализация кода.
## Что сделано в этой сессии (закоммичено)
Содержание не дублирую — смотри сами файлы:
- **ADR-0006** `docs/adr/0006-generation-as-sole-analytics-source.md` — генерация
становится единственным источником аналитики; статический сид → архивный;
перевод процесса на новый (сгенерированный) сид — цель работы. Коммит `49512b1`.
- **Спека** `docs/specs/2026-06-14-generator-model-time-and-startup-history.md`
модельное время на практике: точка отсчёта `T0`, повторяемость, заливка
прошлого, стартовая история, сохранение состояния, скорость ×K, проверка в два
шага. Коммит `49512b1`.
- **Указатели вперёд** в ADR-0004 и ADR-0005 на ADR-0006 и спеку. Коммит `49512b1`.
- **AGENTS.md** — ужесточено правило про русский язык + добавлено правило про
понятность и краткость документов. Коммит `c4cc01e`.
## Контекст и решения, которых нет в артефактах (важны для продолжения)
- **Роль сида = «кладовка значений» (палитра атрибутов).** Генератор сам придумывает
структуру (иерархию, время, воронку), но фактуру (браузер/гео/устройство/utm)
копирует из строк сида: `generator/src/clickstream_generator/generation.py`
(строки ~202228, `{**base_browser, …}`), индексы в `dictionary.py`. Профиль
популяции хранится ссылкой на сид-сессию (мат-спека, §«Профиль пользователя»).
Поэтому сид нельзя удалить, пока генератор не научится фактуре сам.
- **Сид полностью чист** — проверено: 1000 записей × 4 файла, 0 падений в DQ
(`ods.*_errors`). Значит вывод сида не ломает учебный путь про грязные данные.
- **Двухшаговая проверка** (раздел «Проверка» спеки): шаг 1 — агент на чистом
стенде сверяет числа в ClickHouse (пирамида/воронка/возвраты), детерминированно;
шаг 2 — человек смотрит дашборды (распределение похоже на задуманное + стенд
«дышит» на ×K). Вскрытый пробел: дашборда с распределением сгенерированных
данных нет (Superset на сиде, Grafana показывает пропускную способность).
- **Известные расхождения калибровки** (из прошлого ревью, не в этих артефактах):
медиана длины визита ~8 против сидовых 10, всплеск на длине 2, нет
bounce-визитов длины 1, доля `/confirmation` ~27%. Когда генерация станет
источником, это станет «правдой» стенда — учесть при заполнении коридоров шага 1
и в будущей задаче калибровки/фактуры.
## Очередь (следующие шаги)
1. Выровнять `CONTEXT.md` (раздел «три значения слова сид») под ADR-0006:
статический сид → архивная кладовка значений, цель — полный вывод.
2. Пометить в мат-спеке `docs/specs/2026-06-10-generator-math-model.md` разделы
«Персистентность через рестарты» и «Воспроизводимость» как переописанные в
модельном времени новой спекой (ссылкой, без дублирования).
3. (Опционально) Этап 1 вживую: поднять стенд на текущем генераторе, снять
реальные числа в ClickHouse, заполнить коридоры в разделе «Проверка». Поднимает
docker-стек (меняет состояние) — только с согласия владельца.
4. Черновик спеки **синтеза фактуры** — то, что позволит удалить `data/*.jsonl`.
5. Черновик спеки **перестройки процесса** (загрузка `kafka_load_dag` → новый сид,
Superset/витрины, уроки) — на этапе реализации, по ADR-0006.
6. Реализация механизма (модельные часы/×K/стартовая история) — это код, зона Codex.
## Ограничения (продолжать соблюдать)
- Роль: Claude — ADR/спеки/ревью; Codex — код. Намерение, против которого
сверяем, живёт в ADR/спеках Claude.
- Язык: ясный русский без транслитераций (теперь зафиксировано в `AGENTS.md`).
- Коммиты: только по просьбе; формат conventional-commits; трейлер
`Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>`.
- Git строго аддитивно: на ветке может параллельно писать Codex — не делать
amend/rebase/reset чужих коммитов. В `main` — merge `--no-ff`, не тащить
`.scratch/`.
- Context7 для спорных/меняющихся API (особенно Airflow).
- Публичный репозиторий — без персональных данных менти.
## Suggested skills
- **brainstorm-with-docs** — для продолжения дизайна (пункты 1, 4, 5 очереди:
`CONTEXT.md`, спека фактуры, спека перестройки процесса).
- **conventional-commits** — для коммитов.
- **Context7 (MCP)** — при касании API.
@@ -1,16 +0,0 @@
# Handoff: экономия контекста в coordinator-loop (указатель)
Дата: 2026-06-14 MSK
Полная, авторитетная версия этого handoff перенесена **внутрь навыка**, рядом с
handoff про наблюдаемость:
`~/dotfiles/agents/.agents/skills/coordinator-loop/handoffs/2026-06-14-coordinator-loop-context-economy.md`
Почему там: handoff про доработку навыка `coordinator-loop`, и сам навык, и его
handoff-побратим (`2026-06-14-observability-design.md`) живут в dotfiles. Чтобы будущая
сессия по доработке навыка нашла всё в одном месте, авторитетная версия лежит у навыка.
Здесь оставлен только указатель: диагностика, на которой стоит handoff, снята с прогона
именно этого репозитория (фичи `feature-data-generator` и
`generator-model-time-startup-history` под `/coordinator-loop`).
@@ -1,68 +0,0 @@
# Handoff: задачи по модельному времени и стартовой истории
Дата: 2026-06-14
Жанр: одноразовый handoff по ADR-0003.
## Что сделано
Создан рабочий набор артефактов для следующей фазы работ:
- `.scratch/generator-model-time-startup-history/PRD.md`
- `.scratch/generator-model-time-startup-history/issues/01-time-and-startup-history-contract.md`
- `.scratch/generator-model-time-startup-history/issues/02-model-time-to-clickhouse.md`
- `.scratch/generator-model-time-startup-history/issues/03-model-speed-and-day-factor.md`
- `.scratch/generator-model-time-startup-history/issues/04-state-v2-model-resume.md`
- `.scratch/generator-model-time-startup-history/issues/05-startup-history-backfill-to-clickhouse.md`
- `.scratch/generator-model-time-startup-history/issues/06-generated-history-as-analytics-source.md`
Артефакты режут работу на 6 последовательных issue и 2 review gate. Главная
идея: каждый кодовый срез должен подтверждаться через ClickHouse, а не только
локальными тестами генератора. Финальная проверка дашбордов глазами остаётся в
конце.
## Важные решения
- Координатор не берёт `/goal` на всю цепочку: один worker получает один issue.
- Worker работает через `/tdd`, не коммитит и не реализует следующие задачи.
- После реализации worker делает саморевью без правок.
- Координатор классифицирует находки и коммитит сам.
- После задачи 3 нужен review gate по сквозному инварианту времени.
- После задачи 5 нужен review gate по распределениям и двум путям генерации.
- Для review gate после задачи 5 нужен reviewer другой родословной; без него
координатор останавливает цепочку и отдаёт риск человеку. Это следует из
`docs/research/2026-06-11-subagent-coordinator-experiment.md`.
## Что важно не потерять
- В задаче 1 нужно зафиксировать durable-контракт, а не оставить решение только
в комментарии к issue.
- При ×K восстановление после сбоя нельзя считать простым `datetime.now()`: нужна
сохранённая связка модельного и настенного времени.
- Короткий или долгий простой считается по модельному времени, а не по настенным
минутам.
- Чистый прогон должен сбрасывать не только ClickHouse, но и Kafka-топики данных
и состояние генератора.
- Стартовая история должна быть парным артефактом: события, слепок состояния и
манифест.
- Живой и восстановленный пути не должны менять контекст внутри одного визита;
это известная слепая зона из research.
- Задача 6 специально сужена до штатного пути стенда и документов запуска.
Уроки, новые панели и улучшения дашбордов уходят в follow-up, если окажутся
нетривиальными.
## Suggested skills
- `to-issues` — если понадобится переразбить или опубликовать дополнительные
issue.
- `tdd` — основной режим работы worker-а над каждым кодовым issue.
- `conventional-commits` — перед каждым коммитом координатора.
- `claude-team-review` или другой внешний reviewer — на двух review gate.
- `handoff` — если работа прерывается между issue или после review gate.
## Следующий шаг
Начать с
`.scratch/generator-model-time-startup-history/issues/01-time-and-startup-history-contract.md`.
Это HITL-задача: нужно закрепить интерфейс модельного времени, манифест
стартовой истории, правило границы `T_end` и способ повторяемой проверки в
ClickHouse.
@@ -1,96 +0,0 @@
# Handoff: независимое ревью модельного времени и стартовой истории
Дата: 2026-06-14
Жанр: одноразовый handoff по ADR-0003.
## Контекст
После прогона coordinator-loop по фичам `feature-data-generator` и
`generator-model-time-startup-history` (issues 0106, реализация Codex) проведено
независимое ревью результатов — другой родословной (Claude). Это в том числе
закрыло пропущенный внешний review gate после задачи 5 из PRD: он был выполнен той
же родословной, что и worker, а PRD требовал другую.
## Что проверили независимо (не по отчётам)
- `make generator-test``134 passed` (своим прогоном).
- Код = «Рабочий контракт реализации» спеки буква в букву: настройки
`GEN_MODEL_*`, state v2 (`model_timestamp/wall_timestamp/model_time_speed/…`),
формула live-возобновления, полуоткрытая граница `[T0, T_end)` с
`drain_until(include_boundary=False)`, манифест и антисмешивание.
- Данные в ClickHouse реальные и сходятся с отчётами до цифры: 6 ч → 16 054;
перепрогнали 1 сутки → 93 952; 2 суток → 187 087 событий / 17 397 визитов /
2 765 пользователей.
- Пирамида (users < visits < events), возвраты, монотонность обеих воронок,
отсутствие архивного сида (все строки 2026 года).
- Повторяемость суточной волны на 2 сутках: часовые числа day1≈day2
(отношение в основном 0.9–1.1), форма «ночь–день» повторяется.
- Стык backfill→live (live-доливка от `T_end=2026-01-03`): дублей 0, граница
держится, device/os/гео на стыке однородны.
- Дашборд: визуальная приёмка (шаг 2 спеки) — человеком и через Playwright.
«Rows by Layer» (4 равных столбца = 187 312) корректен: пайплайн проносит
событие 1:1, потерь нет, дедуп at-least-once на чистом backfill не возникает.
## Что нашли
- **issue 09 — реальный дефект стыка.** Браузерная фактура не переживает
восстановление визита: у визитов, активных ровно на `T_end`, в live-продолжении
меняется `browser_name`/`browser_language` (17/22 и 22/22), хотя внутри чистого
backfill браузер постоянен (0/14556). device/гео не задеты. Нарушает заявленный
критерий однородности задач 04/05; проверялось неполно (смотрели только поля
`dds.click`, а не per-event браузер в `dds.event`). Масштаб ~0.13% визитов.
- Гео-карта на дашборде нечитаема (нет легенды/подсказок/понятной шкалы) — issue 10.
- Стартовый сид по умолчанию — 6 часов (быстрый профиль для CI); суточная волна на
нём не видна, для просмотра нужен ≥2-суточный профиль через env.
## Открытые пробелы проверки (НЕ закрыты)
Ревью прошло по корректности кода, форме данных, стыку и дашборду, но НЕ трогало:
1. **×K не гоняли.** Все прогоны на `speed=1`. Ускорение модельного времени,
событийный бюджет по модельной длительности и смена дневного коэффициента при
×K проверены только в коде/по отчёту issue 03.
2. **Live-crash recovery не воспроизводили.** Формула возобновления с настенной
дельтой и закрытие просроченных визитов — только в коде. Гипотеза: дефект
issue 09 бьёт и сюда (тот же restore-механизм), эмпирически не подтверждено.
3. **Распределения не сверяли с коридорами мат-спеки** (`2026-06-10-generator-math-model.md`).
Подтвердили форму (монотонность, возвраты, длина), но не попадание
`confirmation_share` и доли коротких визитов в спроектированные коридоры.
4. **Воспроизводимость сами не перепрогоняли** — идентичность checksum при
повторном чистом прогоне взята из отчётов issue 03/05.
5. **Второй review gate (после задачи 3) не делали** — систематический sweep на
утечку настенных часов в расчёт интенсивности и сохранение состояния.
Помельче: не проверяли обработку повреждённого/старого state (fresh-start с
предупреждением), `browser_user_agent` (тот же механизм, что issue 09), сам процесс
coordinator-loop по правилам PRD.
## Зафиксированные follow-up (все needs-triage, на потом)
- `issues/07-migrate-course-from-archive-seed.md` — миграция уроков.
- `issues/08-startup-history-portable-artifact-and-usage-docs.md` — портативный
артефакт стартовой истории + runbook + идеи интерфейса (глаголы вместо флагов,
длительность/профили, громкий отказ при несовпадении, доливка кусочком,
Airflow-DAG как пульт).
- `issues/09-seam-browser-fixture-not-preserved.md` — дефект браузерной фактуры.
- `issues/10-dashboard-geo-map-readability.md` — читаемость гео-карты.
- `docs/course/PRD.md` §7 — развилка «генератор как скрытая инфраструктура vs
отдельный урок про генератор» (не грузить менти марковскими цепями).
## Состояние стенда
Поднят на 2 сутках генерации (+ несколько live-тиков от seam-проверки): ClickHouse,
Kafka, Superset, postgres-metadata. Дашборд:
`http://localhost:8088/superset/dashboard/ecommerce-analytics/`.
## Suggested skills
- `tdd` — для фикса issue 09 (один поведенческий тест на однородность браузера через
стык, затем минимальная правка).
- `conventional-commits` — перед коммитами.
- `claude-team-review` / внешний reviewer другой родословной — на пробелы 1–5.
## Следующий шаг
Сегодня только фиксация, без правок. Дальше — приоритизировать issue 09 (баг) против
08/10 (удобство/виз) и закрыть пробелы проверки 1–5 (особенно ×K и crash recovery).
@@ -1,91 +0,0 @@
# Handoff: триаж бэклога генератора и целеполагание стенда
Дата: 2026-07-04
Жанр: одноразовый handoff по ADR-0003.
## Рабочая форма (зафиксирована сегодня)
С Claude — обсуждение проекта, планы, проектные документы и независимые ревью.
Исполнение кода — Codex, предпочтительно через `/goal` или `/coordinator-loop`.
Сохранено в памяти Claude (memory), новая сессия подхватит автоматически.
## Что решено и зафиксировано
- **Целеполагание сверено** и записано в `docs/course/PRD.md` §1 (поправка
2026-07-04): три части трека ClickHouse (теория — внешние курсы, лабы —
clickhouse-learning-cluster, этот стенд — интеграции «как в жизни»); иерархия
целей: курс -> стенд-носитель -> генератор как скрытая инфраструктура.
- **Развилка «урок про генератор» закрыта**: урока не будет, генератор — скрытая
инфраструктура (PRD §7).
- **Демо-употребление устарело**: `docs/DEMO_CHEATSHEET_5MIN.md` и
`docs/DEMO_SCRIPT_10_15MIN.md` удалены, демо выросло в отдельный проект.
- **Новая открытая развилка** в PRD §7: кластерная конфигурация ClickHouse
(пользователь склоняется к «всё в одном», решение не принято).
- **Конвенция трекера**: завершённая задача — `Status: done`
(`docs/agents/issue-tracker.md`); задачи 01–06 фичи переведены в `done`
(стояли ошибочные `ready-for-human` от глючившего координатора).
## Бэклог фичи `generator-model-time-startup-history`
Список задач и порядок — в PRD фичи (раздел «Задачи», дополнен сегодня):
- **07** (артефакт + runbook, `ready-for-agent`) — импорт строго через Kafka
(напрямую в ClickHouse не пишет — решение пользователя), громкий отказ при
несовместимом state (пересмотр правила спеки), граница runbook «использование,
не устройство». Режим ревью — гейт.
- **08** (миграция курса, `ready-for-agent`) — после 07; `make data` вплетён во
все уроки 00–05, объём больше, чем кажется; тонкое место — урок 00.
- **11** (глаголы/длительность/профили, `ready-for-agent`) — после 07, до 12.
- **12** (DAG-пульт, `needs-triage`) — дооформить после 07 и 11; приоритет
поднят пользователем: будущий основной человеческий интерфейс стенда.
- **13** (доливка, `needs-triage`) — без приоритета, после фикса 09.
- Перестановка: бывший 07 (миграция) и 08 (артефакт) поменяны местами.
## Следующий шаг
Весь бэклог готов к передаче Codex. Порядок пересмотрен (решение 2026-07-04,
«пульт вперёд»): узкое место — время человека на ручную приёмку, поэтому
основная цепочка теперь 07 -> 11 -> 12 (пульт появляется раньше), а миграция
курса 08 идёт последней — её приёмку (проход по урокам) человек ведёт уже через
пульт. 09 и 10 независимы, можно параллельно; 13 — после фикса 09. Граф и
подробности — в PRD фичи, раздел «Задачи»; там же зафиксировано, что номер
файла — идентификатор, а не порядок.
## Дооформление 09 и 10 — что изменилось против прежнего понимания
Сделано в этот же день, вторым заходом. 09 и 10 переведены в `ready-for-agent`;
детали — в самих issue, здесь только сдвиги в понимании:
- **Гипотеза по 09 не подтвердилась.** Дело не в рассинхроне `event_index`, а в
источнике фактуры: при рождении визита браузерные строки берутся у случайного
«донора» из словаря, при восстановлении — у `seed_click_id` пользователя.
Прежняя развилка «выбор по абсолютному индексу, не трогая схему state»
оказалась нерабочей — restore не знает донора. Решение пользователя: хранить
`base_click_id` донора в state (альтернативы и причины отказа — в issue).
- **Дефект 09 шире браузера** (нашло ревью): per-event поля location (referer,
utm) расходятся на стыке так же — критерии приёмки расширены, иначе частичный
фикс «только браузер» прошёл бы приёмку. Расхождение event_id (uuid4 при
рождении, uuid5 при restore) зафиксировано как известное и вне скоупа.
- **По 10 сняты две мины:** пересборка по умолчанию даёт 6 часов истории, а не
2 суток (профиль «2 суток одной командой» — это ещё не сделанная задача 11);
legacy-виз `world_map`, похоже, вообще не умеет легенду и tooltip — основной
путь, вероятно, смена типа визуализации, а не настройка (проверить через
Context7 при реализации).
- **Процессная заметка:** дооформленные issue прогнаны через тройное ревью
(самопроверка + два свежих агента, адверсарно, с проверкой каждого утверждения
по коду). Улов оправдал затраты — см. пункты выше; для issue с режимом «гейт»
так стоит делать и дальше.
## Не забыть (вне бэклога)
Открытые пробелы независимого ревью от 2026-06-14 (см. handoff
`2026-06-14-generator-model-time-verification-review.md`): ×K не гоняли,
live-crash recovery не воспроизводили, распределения не сверяли с коридорами
мат-спеки, воспроизводимость checksum не перепроверяли.
## Suggested skills
- `conventional-commits` — перед коммитами.
- `tdd` — для фикса issue 09 (тест на однородность браузера через стык, затем
минимальная правка).
- `coordinator-loop` — на цепочки 07 -> 08 и 07 -> 11 -> 12.
@@ -1,185 +0,0 @@
# Handoff: цепочка генератора 12 -> 14 -> 09 -> 10 -> 08
Дата: 2026-07-04.
Жанр: одноразовый handoff по ADR-0003.
Источник: `.scratch/generator-model-time-startup-history/coordinator-journal.md`.
## Статус
Цепочка `12 -> 14 -> 09 -> 10 -> 08` завершена через `coordinator-loop`.
Финальный chain review закрыт `APPROVED`; правки финального review
закоммичены в `f8b419d`.
Все issue текущей очереди имеют `Status: done`; в PRD фичи осталась только
дальнейшая задача 13 (`needs-triage`).
## Коммиты
- `dd4af82``feat(airflow): добавлен пульт управления генератором`.
- `200bb82``docs(issues): закрыта задача 12 по пульту генератора`.
- `9d1bcc4``feat(generator): ускорен учебный профиль daily-wave`.
- `0cbfe9b``docs(issues): закрыта задача 14 по быстрому профилю`.
- `e2d0684``fix(generator): сохранена фактура визита при восстановлении`.
- `0f435d7``docs(issues): закрыта задача 09 по фактуре визита`.
- `0c80e24``fix(superset): заменена нечитаемая гео-карта`.
- `de938ed``docs(issues): закрыта задача 10 по гео-графику`.
- `d76c036``docs(course): переведены уроки на стартовую историю`.
- `3d4e13c``docs(issues): закрыта задача 08 по миграции курса`.
- `f8b419d``docs(generator): закрыты находки финального ревью цепочки`.
## Что построено
- `airflow/dags/generator_control_dag.py` — ручной Airflow-пульт
`backfill/import/check`, без Docker socket, с ожиданием `etl_pipeline`.
- `generator/src/clickstream_generator/airflow_control.py` — общая логика
env, предпроверок чистого стенда и сверки manifest для DAG-пульта.
- `docker-compose.yml` / `Makefile``make up` не автостартует live-генератор;
live запускается явно через `make generator-continue`.
- `generator/src/clickstream_generator/launch.py``daily-wave` переведён на
`speed=60`, `tick=1`; `ci` сохранён.
- `generator/src/clickstream_generator/runtime.py` и `state.py` — state v3
хранит `base_click_id`, восстановление визита берёт ту же per-event фактуру.
- `scripts/check_generated_analytics.sh` — стыковочная проверка browser/source и ODS
device/os/geo включается в режиме `auto` после live-строк.
- `superset/create_dashboard.py` — гео-блок заменён на `Top Countries by Events`
(`echarts_timeseries_bar`) с tooltip, легендой и единицами.
- `docs/course/` и `docs/TEST_PLAN.md` — учебный путь переведён с архивного
сида на `startup-history/backfill -> Kafka -> STG -> ODS -> DDS -> DM -> Superset`.
## Ревью по issue
- Issue 12: обычный режим. Worker `medium` был запущен до уточнения уровней,
проверка кода сначала `medium`, повторный прогон `high`. Первая проверка нашла
отсутствие подсказки `make clean` на грязных Kafka-топиках; повторный прогон
`APPROVED`.
- Issue 14: обычный режим. Worker `medium`, проверка кода `high`; `APPROVED`.
- Issue 09: гейт. Worker `high`; проверка задачи `high` и проверка кода `high`.
Первый круг нашёл ODS-проверку device/os/geo, потерю 1 мкс в timestamp offset
и ложнозелёный `generated-history-check`; второй круг `APPROVED`.
- Issue 10: обычный режим. Worker `medium`, проверка кода `high`.
Проверка нашла рассинхрон Superset export/layout, ложнозелёный тест и риск дубля
при rename; узкие повторные прогоны закрыты, итог `APPROVED`.
- Issue 08: обычный режим. Worker `medium`, проверка кода `high`.
Проверка нашла старый путь отката в стандарте уроков и несогласованность урока 06
вокруг `superset-dashboard`; повторный прогон `APPROVED`.
## Финальное ревью
Финальное ревью цепочки шло на усиленном уровне `xhigh`.
До обновления скилла повторные прогоны запускались свежими сессиями ревьюеров:
`Bernoulli`, `Noether`, `Banach`, `Curie`, `Sartre`, `Bacon`.
Это отклонение от обновлённого процесса зафиксировано как дорогой вариант.
После обновления скилла проектные doc-находки чинил отдельный worker для правок
`Raman` (`medium`), а повторный прогон выполнял тот же ревьюер `James` через
`send_input`.
Закрытые классы находок:
- PRD фичи больше не `Draft` и не держит закрытые 12/09/10/14/08 в остатке.
- Все `Status: done` issue фичи без пустых `[ ]`.
- Superset docs/course/artifacts/code не содержат старые `World Map/world_map`
маркеры рядом с новым `Top Countries`.
- `docs/OPERATIONS.md`, `docs/course/PRD.md`, `docs/ARCHITECTURE.md`,
`docs/REPO_MAP.md` и `CONTEXT.md` согласованы со startup-history-путём и
`generator_control`.
## Отклонения процесса
- Ранние повторные прогоны ревью запускались свежими субагентами, а не продолжением
того же ревьюера. После обновления `coordinator-loop` точечные повторные прогоны
нужно делать через `send_input` тому же ревьюеру.
- До обновления скилла координатор сам правил часть project docs по финальному
ревью. После обновления project docs правил worker для правок; процессные файлы
`.scratch/...` остались зоной координатора.
- Визуальная приёмка Superset и живой проход Airflow UI не выполнялись в этой
цепочке. Это не скрыто: все такие пункты вынесены в HITL/риски.
## Открытые риски
- Нужен кросс-линейный ревью-проход другой родословной по фактическим изменениям
`c672ed0..HEAD`. Особый фокус: issue 12 Airflow-пульт, issue 09 state v3 и
стыковочная проверка, issue 10 Superset export/layout, issue 08 учебный путь.
- Нужна ручная HITL-приёмка:
- Airflow UI: `generator_control` backfill/import/check на чистом стенде.
- Superset: кадр `Top Countries by Events` целиком и кадр с tooltip.
- Курс 00-06: проход через новый startup-history-путь.
- Задача 13 (`backfill-top-up-from-snapshot`) остаётся `needs-triage`; после
фикса issue 09 её можно дооформлять отдельно.
## Быстрые проверки, которые уже проходили
- `uv run --with-requirements generator/requirements.txt pytest generator/tests -q`
— PASS на issue 12 и 09.
- `make generator-test` — PASS на issue 14.
- `uv run --with pytest pytest tests/test_superset_dashboard_config.py` — PASS
на issue 10.
- Поисковые проверки курса на старые `make data`/`kafka_load`/фиксированные
сид-ожидания — PASS на issue 08.
- Финальные `rg`-проверки по PRD, чекбоксам, Superset-маркерам и
startup-history-дрифту — PASS перед `f8b419d`.
## Независимый ревью-проход (2026-07-04, свежий взгляд)
Кто и как: Claude, свежим взглядом по диапазону `c672ed0..HEAD`, без субагентов
(правило проекта: «свежим взглядом» = без субагентов). Читались реальные диффы
всех пяти задач и сверялись с текстами issue; тесты прогонялись заново, а не со
слов handoff.
Вердикт: цепочка выполнена на уровне кода и тестов; правок для приёмки не нужно.
Доказательства (прогонял сам):
- `generator/tests` — 172 passed (в том числе контрактный тест DAG и тесты пульта).
- `tests/test_superset_dashboard_config.py` — 5 passed.
- Грепы: старых маркеров `world_map`/`Geography Map` в коде и доках нет (остались
только законный историч. след в спеке, `previous_slice_names` и тест
переименования); во всех done-issue 0 пустых чекбоксов; `state v2` в отгруженном
коде не осталось.
- `etl_pipeline` действительно принимает `conf` `full_refresh` (`Param(True,
type="boolean")`) — имя параметра из `TriggerDagRunOperator` пульта совпадает.
По задачам:
- Issue 09 (гейт): донор `base_click_id` хранится в state; восстановление громко
падает на неизвестном доноре (тихие `.get`-fallback'и убраны); запасная ветка
рождения сделана восстановимой и провалидирована. Отдельная реальная находка —
µs-фикс `_timestamp_to_state_offset` (целочисленная арифметика вместо
`total_seconds()*1e6`). Тесты бьют прямо в критерии приёмки.
- Issue 12 (пульт): `retries=0`, `is_paused_upon_creation`, join после ветвления
через `NONE_FAILED_MIN_ONE_SUCCESS`, `wait_for_completion=True`, env до
`Config()`, предпроверка пустоты Kafka и STG. Compose-профиль `live-generator`
оставляет `make up` чистым; явные пути включают профиль по имени сервиса.
- Issue 14: `daily-wave` speed 1→60, tick 60→1; `ci` не тронут; пер-тиковые INFO
приглушены до DEBUG.
- Issue 10: `echarts_timeseries_bar` с tooltip, легендой и единицами; дедуп дублей
при переименовании; экспорт-JSON защищён тестами и от рассинхрона с конфигом, и
от дрейфа раскладки.
- Issue 08: доки, старый путь `make data`/`kafka_load` убран как основной, грепы
чисты.
Мелочи (косметика, не блокеры):
- `test_default_version` (`test_state.py`): docstring говорит «версии 2», а ассерт
уже `"3.0"`.
- `build_control_env` для `import` тоже зовёт `build_launch_env("backfill", …)`
безвредно (важен только «мир»-env), но может смутить читателя.
- `tooltipTimeFormat: "smart_date"` на категориальной оси — рудиментарный
параметр, безвреден.
## Открытые риски (обновление 2026-07-04)
- Кросс-линейный проход *другой родословной* (иная модель/агент) не выполнялся:
этот ревью сделан Claude свежим взглядом без субагентов. Для кода и тестов
этого достаточно; если нужна ещё одна родословная — отдельный шаг.
- Ручная приёмка (HITL) остаётся, код к ней честен (пропуски печатаются):
- Airflow UI: `generator_control` backfill/import/check на чистом стенде.
- Superset: кадр `Top Countries by Events` целиком и кадр с tooltip.
- Курс 00-06: проход по новому startup-history-пути.
- Задача 13 (`backfill-top-up-from-snapshot`) — `needs-triage`; предпосылка
(исправный restore из issue 09) выполнена, можно дооформлять.
## Следующий шаг
Независимый ревью кода и тестов пройден. Осталось: ручная HITL-приёмка (Airflow
UI, Superset-кадры, проход курса) и отдельное решение по задаче 13.
@@ -1,160 +0,0 @@
# Кросс-линейное ревью цепочки генератора 12 -> 14 -> 09 -> 10 -> 08
Дата: 2026-07-05 00:02.
Жанр: одноразовый handoff по ADR-0003; отчёт кросс-прохода другой родословной
(Claude) по диапазону `c672ed0..ec815ce`. Бриф — из
`.scratch/handoffs/2026-07-04-generator-chain-review.md`.
Метод: четыре параллельных адверсарных ревьюера с исполняемыми доказательствами
(мутационные тесты на копии, эксперимент с compose-профилем на реальной версии
Compose, зонды на реальном сиде, сверка Airflow API через Context7). Репозиторий
не менялся.
## Вердикт
**CHANGES_REQUESTED.** Счёт: 1 critical, 5 high, 10 medium, 4 low — после
`APPROVED` финального ревью той же линии. Третье подтверждение находки о
родословной: внутренние ревью закрыли локальные дефекты честно, кросс-линия
нашла сквозные сценарии.
## Сквозные семейства (главная ценность прохода)
1. **«Смешение миров» возвращается тремя дорогами.** Инвариант задачи 07
(«чистый стенд, громкий отказ») пробит: (а) state v2 после обновления кода
классифицируется как «повреждённый» → тихий чистый старт нового мира поверх
истории; (б) live-генератор ушёл в compose-профиль, и `make clean`/`down`
его больше **не убивают** — осиротевший генератор старого мира пишет в чистые
топики и переживает перезагрузку (`restart: unless-stopped`); (в) консольные
пути (`make generator-backfill`, `startup-history-import`) остались без
предпроверок, которые пульту сочли обязательными.
2. **Последствия «make up больше не стартует live» не выметены.** Алерт
`Kafka No Messages Produced` горит весь курс на здоровом стенде; уроки 0/5
ожидают поток; `sleep 5` в документированной проверке шва меньше времени
старта генератора — проверка стала пустышкой.
3. **Ложнозелёные проверки.** Superset-тесты пропускают дрейф параметров
(top-15 → 500 строк — 5 тестов зелёные); стыковая проверка сверяет шов там,
куда указал env, а не где он по манифесту; ODS-блок проходит на пустом ODS.
4. **Чистый клон/свежий стенд никто не прошёл.** `uv` не заявлен в
пререквизитах; README-быстрый старт падает без `ddl_init`; пульт вечно висит
на запаused `etl_pipeline`; после `git pull` образ Airflow не пересобирается
(DAG красный); центральное упражнение урока 1 физически невоспроизводимо.
Всё это лежало ровно в вынесенной в риски HITL-приёмке.
## Индекс находок по issue
### Issue 08 (курс) — CHANGES_REQUESTED
- **CRITICAL** `docs/course/lessons/01_kafka_to_clickhouse.md:192-239`
упражнение с `kafka_msg_ts` невоспроизводимо: «перезаливка среза» заменена на
`make generated-history-analytics && make up`, который делает `down -v` и
накатывает эталонный DDL — добавленная менти колонка уничтожается, финальный
SELECT падает; в тексте остался висящий `TRUNCATE` (след нестыковки).
Нужен путь перезаливки без сброса схемы (смена `kafka_group_name` /
`CLEAN_START=0` + повторный backfill) и проверка на стенде.
- **HIGH** `docs/course/README.md:19-34`, `README.md:43-47` — первая команда
курса требует `uv` на хосте; ни пререквизиты, ни quick start его не называют.
- **HIGH** `docs/course/lessons/05_monitoring.md:254,259-262,339` — на штатном
пути (без live) `Kafka No Messages Produced` горит постоянно; урок обещает
«алерты не шумят»; панели описаны для потока, которого нет.
- **MEDIUM** `00_kafka_intro.md:56-65` — служебные топики `generator_state` и
`generator_startup_history_manifest` не объяснены (урок построен на
разглядывании списка топиков).
- **MEDIUM** `00_kafka_intro.md:117-122` vs `05_monitoring.md:156-161`
взаимоисключающие утверждения о видимости consumer lag; проверить на стенде.
- **MEDIUM** `README.md:64-68`, `docs/OPERATIONS.md:175-199`
`make generated-history-check` после `PROFILE=daily-wave` падает: в check
зашит диапазон ci, PROFILE не передаётся.
- **MEDIUM** `docs/OPERATIONS.md:95` — источником STG первым назван архивный
`make data`.
### Issue 12/14 (пульт, профиль) — CHANGES_REQUESTED
- **HIGH** `airflow/dags/generator_control_dag.py:227-235` +
`etl_pipeline_dag.py:263``etl_pipeline` создаётся на паузе; `trigger_etl`
(`wait_for_completion`, без `execution_timeout`) виснет навсегда,
`max_active_runs=1` блокирует повторные запуски. В Airflow 2.10 нет
`fail_when_dag_is_paused` (Context7). Нужна предпроверка «etl_pipeline не на
паузе» + шаг unpause в README/runbook.
- **HIGH** `docker-compose.yml:293-294,334`, Makefile (`down`, `clean`) —
профильный `live-generator` не удаляется `down -v` (доказано экспериментом,
Compose v5.1.3); `restart: unless-stopped` воскрешает его после перезагрузки.
В `down`/`clean`/CLEAN_START нужен `--profile live-generator`.
- **MEDIUM** `README.md:32-40` — быстрый старт без `ddl_init`: precheck падает
сырым `UNKNOWN_TABLE`; добавить шаг и человекочитаемую подсказку.
- **MEDIUM** `airflow/requirements.txt:9-10`, Makefile `up` — после `git pull`
образ Airflow не пересобирается → `ModuleNotFoundError: prometheus_client`,
DAG красный. Нужен `--build` или инструкция.
- **MEDIUM** `docs/OPERATIONS.md:237-241` vs `kafka_io.py:161,253``sleep 5`
меньше времени старта continue (≥10 с): live-строк ноль, `CHECK_LIVE_SEAM=auto`
молча пропускает шов. Было `sleep 130` при тике 60 с.
- **MEDIUM** `airflow_control.py:102-141` vs `run_generator.sh:56-77`,
`import_startup_history_artifact.sh` — предпроверки только в DAG; консольные
пути тихо смешивают миры. Вынести `assert_stand_clean` в общую точку входа.
- **LOW** `service.py:203-215` — простой стенда ×60: ночь = +30 модельных суток
дыры; предупредить в runbook, советовать reset/повторный импорт.
- **LOW** — фиксация Context7-проверки Airflow API только в `.scratch/`, не в
коде/доках (AGENTS.md требует); сами вызовы для 2.10.5 корректны.
### Issue 09 (state v3, фактура) — CHANGES_REQUESTED
- **HIGH** `state.py:236-241``kafka_io.py:181``service.py:100-102`
поднятие STATE_VERSION молча превращает живой стенд во «второй мир»: v2 —
читаемый, несовместимый state, но version-гейт убивает его до семантики,
`from_dict_safe` даёт `None`, сервис тихо стартует новый мир с `model_t0`
поверх истории. Сверка `manifest.state_version != state.version`
(`service.py:246`) недостижима. Спека (строки 198-204, 245-247) требует
громкий отказ; `IncompatibleStateError` уже существует — использовать его при
известной старой версии и `GEN_STATE_RESET=false`; миграционной заметки в
доках нет.
- **MEDIUM** `check_generated_analytics.sh:13,273-289,342,387-393` — проверка
стыка сверяет шов по env-дефолту (`2026-01-01T06:00`), не по манифесту: после
`daily-wave` голый `make generated-history-check` «доказывает» однородность
фальшивого шва посреди backfill. LEFT JOIN `dds.click` структурно пуст; ODS-блок
проходит на пустом ODS. Брать `model_t_end` из манифеста, требовать ненулевые
ODS-строки.
- **MEDIUM** `generation.py:196-209` — предпосылка issue «fallback не
срабатывает» неверна: срабатывает у ~8% визитов (зонд, seed=4242, N=20000);
выпуск не изменился только потому, что у всех доноров сида строки внутри
click_id идентичны — свойство нигде не зафиксировано; при регенерации сида
с вариативностью ~8% визитов поедет. Зафиксировать свойство сида или
ограничить `GEN_MAX_SESSION_EVENTS` длиной максимального донора.
- Ядро фикса крепкое (проверено исполнением): инвариант «рождение ==
восстановление» держится, RNG не потребляется при restore, микросекунды
чинятся честно, форма распределений не сместилась (сверка с `e2d0684^`).
### Issue 10 (Superset) — CHANGES_REQUESTED
- **MEDIUM** `tests/test_superset_dashboard_config.py:64-76` — тесты сверяют
подмножество параметров: мутация «top-15 по убыванию» в экспорте (row_limit
15→500, order_desc→false и др.) проходит все 5 тестов. Нужно полное сравнение
`params` config-vs-export. Классы «возврат world_map» и «рассинхрон layout»
закрыты честно (мутации падают).
- **MEDIUM** issue `10-*:51-68`, `create_dashboard.py:158-185` — приёмка «по
кадру» выполнена декларативно, чарт никем не отрисован; порядок столбцов после
pivot не гарантирован — задать `x_axis_sort: "Events, pcs"`,
`x_axis_sort_asc: false`; снять кадр при HITL.
- **MEDIUM** `create_dashboard.py:505-520` — удаление дублей по глобальному
совпадению имени: повторный прогон молча удалит одноимённый чарт менти;
сузить по `datasource_id`, задокументировать деструктивность.
- **LOW** `create_dashboard.py:176``tooltipTimeFormat` бессмыслен для
категориальной оси; легенда дублирует ось при единственной серии.
- **LOW** `docs/SUPERSET_DASHBOARD.md:205-211` — путь ручного импорта экспорта
(legacy v0) ничем не проверяется.
## Маршрутизация (предложение)
- **Багфикс-цепочка Codex** (кандидат-порядок по риску): (1) семейство
«смешение миров» — 09-HIGH + 12-HIGH-clean + разъезд предпроверок одним
issue; (2) 12-HIGH-паузы + README/ddl_init/build — «свежий стенд» одним
issue; (3) 08-CRITICAL урок 1 + uv + алерт урока 5 — «курс на чистом клоне»;
(4) ложнозелёные проверки (09-MEDIUM-шов, 10-MEDIUM-тесты); (5) остальное.
- **HITL остаётся HITL** (кадры Superset, живой проход Airflow UI, проход по
урокам) — но пункты 08-CRITICAL и 12-HIGH показывают, что часть HITL дешевле
заменить проверками на чистом клоне в CI-манере.
- Отдельно: третий случай подтверждения находки о родословной — кандидат на
датированную поправку в `references/rationale.md` скилла coordinator-loop.
## Что подтверждено как корректное
Стыковка env DAG→генератор; ветвление DAG; отсутствие потребности в Docker
изнутри Airflow; make-цели/имена DAG/DDL-колонки/числа профилей в уроках; ядро
state v3; замена карты в обоих источниках; 172 unit-теста зелёные.
@@ -1,122 +0,0 @@
# Handoff: fixes after generator cross-line review
Дата: 2026-07-05 22:12.
Жанр: handoff по ADR-0003 после coordinator-loop 15 -> 16 -> 17 -> 18.
## Что закрыто
- 15: граница миров после обновления, clean/reset и host-запусков.
Коммиты: `080d5ae`, `108053b`.
- 16: свежий стенд и `generator_control` без неявных ручных шагов.
Коммиты: `27947ce`, `9804d0b`.
- 17: доверенные проверки startup-history и Superset.
Коммиты: `00c97eb`, `6731349`.
- 18: курс 00/01/05 проходит по startup-history на чистом стенде.
Коммиты: `77e4fb6`, `6d64f39`.
- Follow-up 19: отдельная задача на единые `make test` и `make lint`.
Коммит: `2778eae`.
- Финальный review fix: документация больше не советует обычный
`make generated-history-check` после backfill-only пути.
Коммит: `8e1c733`.
- Issue 19 закрыта после внешнего Claude review: единые `make test` и
`make lint`, подключение корневых контрактных тестов и усиление проверок
startup-history.
Коммит: `9b0b063`.
## Ключевые стыки реализации
- `generator/src/clickstream_generator/stand_clean.py` — общий guard чистого
стенда для Airflow и host-путей.
- `scripts/assert_stand_clean.sh` — host-проверка перед backfill/import/continue.
- `airflow/dags/generator_control_dag.py` — pause-check `etl_pipeline` до
мутирующих веток.
- `scripts/check_generated_analytics.sh` — manifest boundary, fail-closed
live seam, непустой ODS и fail-closed проверка DM-витрин.
- `scripts/run_generated_history_runtime_check.sh` — bounded runtime gate для
daily-wave + live seam.
- `scripts/run_generator.sh``reset` теперь проходит clean-stand guard до
запуска live-генератора.
- `Makefile``make test`, `make lint`, `contract-test`; обычный pytest-вывод
тихий, подробность можно включить через `PYTEST_ARGS`.
- `generator/src/clickstream_generator/state.py` — любая версия state не `3.0`
даёт громкий `UnsupportedStateVersionError`; `from_dict_safe` больше не
глотает ошибку старой/неизвестной версии.
- `generator/src/clickstream_generator/airflow_control.py`
`target_dag_trigger_error()` покрывает три ветки pause-check без импорта
Airflow.
- `superset/create_dashboard.py` — sync ограничен чартами целевого dashboard.
- `docs/course/lessons/00_kafka_intro.md`,
`docs/course/lessons/01_kafka_to_clickhouse.md`,
`docs/course/lessons/05_monitoring.md` — курс согласован с startup-history,
no-live default и consumer lag.
## Проверки
- Issue 15: `make generator-test`, `docker compose config --quiet`,
`py_compile`, `bash -n`.
- Issue 16: `make generator-test`, `docker compose config --quiet`,
`py_compile`, `make clean`, `make up`, `make ddl`.
- Issue 17: Docker target tests, `make generator-test`, `py_compile`,
`bash -n`, `make generated-history-runtime-check`.
- Issue 18: doc `rg`, `git diff --check`,
`make generated-history-analytics`, `make up`.
- Issue 19 / commit `9b0b063`: `make contract-test` — 16 passed;
`make generator-test` — 190 passed; `make lint` — passed; `make test`
190 generator tests, 16 contract tests, `docker compose config --quiet`.
- Финальный chain review `Gibbs`: initial `CHANGES_REQUESTED`, narrow rerun
`APPROVED`.
## Происхождение ревью
- 15: gate; task reviewer `Ptolemy` high, code reviewer `Linnaeus` high;
оба rerun `APPROVED`.
- 16: code reviewer `Laplace` high; primary review found paused-DAG order bug,
later reruns `APPROVED`.
- 17: code reviewer `Bacon` high; found Superset ownership and live-seam
defaults; bounded runtime gate rerun `APPROVED`.
- 18: docs/code reviewer `Hume` high; found Prometheus scrape-count drift;
rerun `APPROVED`.
- Финал: chain reviewer `Gibbs` xhigh; found docs drift around
`generated-history-check`; rerun `APPROVED`.
- После `9b0b063`: внешний Claude review подтвердил закрытие всех девяти
находок и дал `APPROVED`. Reviewer не перезапускал Docker-проверки сам, но
сверил код, тесты и документы; фактические прогоны были выполнены
координатором.
## Отклонения процесса
- Локальный `uv run ... pytest` у координатора падал до pytest из-за
`snap-confine` / `cap_dac_override`. Для координаторского gate целевые тесты
запускались через Docker-образ `generator:test`. Это вынесено в issue 19.
- Первичный runtime gate issue 17 через полный `daily-wave` был остановлен:
прогон был активным, но слишком долгим для коммит-гейта. После этого добавлен
bounded `make generated-history-runtime-check`.
- Несколько стендовых проверок чистили Docker volumes. Это ожидаемо для issue
16-18 и зафиксировано в журнале.
## Что вручную проверить дальше
- Чистый ручной путь через Airflow UI: `make up`, `make ddl` или `ddl_init`,
`airflow dags unpause etl_pipeline`, затем `generator_control` backfill.
- Backfill-only путь: `make generated-history-analytics`, затем
`CHECK_LIVE_SEAM=0 make generated-history-check`.
- Стык backfill/live: `make generated-history-runtime-check`.
- Superset: после готового DM открыть dashboard и сверить, что чарты созданы и
`Top Countries by Events` читается.
- Kafka UI: в уроке 00 должны быть понятны четыре data-топика и служебные
`generator_state`, `generator_startup_history_manifest`,
`generator_batch_history`.
## Suggested skills
- `triage` — если продолжать issue 13: он всё ещё `needs-triage`.
- `brainstorm-with-docs` — если перед issue 13 нужно заново согласовать
модель доливки истории от слепка.
- `coordinator-loop` — только после перевода issue 13 в `ready-for-agent`.
- `code-review` — для внешнего прохода по коммитам после ручной проверки.
## Открытые риски
- Ручная HITL-проверка после `9b0b063` ещё не выполнена пользователем.
- Issue 13 остаётся `needs-triage`: доливка истории от слепка должна опираться
на закрытые инварианты 15 и 17.
@@ -1,70 +0,0 @@
# Handoff: проверка пути менти, диагноз флаки-гейта, задача next-day
Дата: 2026-07-07 22:34.
Жанр: handoff по ADR-0003 после сессии «проверка пути менти + триаж 13/20».
## Что закрыто
- Проверка пути менти двумя субагентами (читатель документации на Opus,
прогонщик стенда на Sonnet):
- Документация: workable-with-friction, четыре мелких находки — все
исправлены. Коммит `900e949`.
- Стенд с нуля: clean -> generated-history-analytics -> up -> проверки ->
Superset (чарты с данными) -> Kafka (4 data-топика + служебные) ->
ClickHouse (ODS/DM непустые) — всё прошло, дубликатов ноль.
- Единственное падение: `make generated-history-runtime-check` красный
через раз — заведена задача 20.
- Диагноз задачи 20 (Codex, ключевой факт перепроверен по коду): генератор
фактуру на стыке НЕ ломает; корень — гонка остановки live-генератора в
самой проверке + seam-SQL, маскирующий непарные строки под «смену фактуры».
Детали и направление фикса — в задаче. Коммит `98be722`.
- Задача 13 переписана под глагол `next-day` в `generator_control`;
оба открытых вопроса закрыты; развилка реализации решена пользователем:
**вариант 2 — генерация следующего дня от слепка** (обоснование в задаче).
Коммиты `a3ac4b4`, `98be722`; решение развилки — в коммите с этим handoff.
- Созданы репо-локальные субагенты `.claude/agents/deep-reasoner.md` (Opus)
и `fast-worker.md` (Sonnet); `.gitignore` скрывает локальное в `.claude/`.
Коммит `984d6fc`.
## Состояние трекера
- `20-flaky-runtime-seam-check.md`**ready-for-agent**: диагноз есть,
направление фикса выбрано (управляемая остановка live после полного flush
всех топиков + precheck непарных строк в seam-check). Идти первым.
- `13-backfill-top-up-from-snapshot.md`**ready-for-agent**, blocked by 20.
Вариант реализации решён, критерии в задаче.
## Что дальше
1. Фикс задачи 20 по конвейеру `/claude-subagent-playbook`: постановка в
задаче самодостаточна, свежий адверсарный взгляд на неё до реализации,
реализация Кодексом (прямой `codex exec`, не плагин — см. handoff в
скилле), два слепых ревью.
2. После зелёного стабильного гейта (3+ прогона) — задача 13.
3. Ручная HITL-проверка пути менти пользователем всё ещё не сделана
(Airflow UI, Superset глазами, Kafka UI) — стенд остался в рабочем
состоянии после зелёного runtime-check.
## Проверки этой сессии
- `make generated-history-runtime-check`: красный (8/19), затем зелёный —
эмпирика флаки в задаче 20; полные логи в session-scratchpad (одноразовые,
сводка перенесена в задачу).
- Утверждение диагноза про запасную ветку перепроверено по
`generation.py:194-209`.
- Дерево чистое после каждого коммита; `.claude/settings.local.json`
в git не попал.
## Отклонения процесса
- Прогонщик стенда дважды засыпал без отслеживаемого фонового процесса и
в финале умер, не собрав отчёт, — вердикт собран координатором из логов.
- Диагност через плагин codex-rescue: форвардер отчитался «finished» при
живом фоновом вызове; результат забран напрямую из output-файла задания.
Уроки процесса — в handoff рядом со скиллом claude-subagent-playbook.
## Suggested skills
- `claude-subagent-playbook` — для фикса задачи 20 (одна нетривиальная
задача: постановка готова, нужен конвейер).
- `conventional-commits` — коммиты.
@@ -1,82 +0,0 @@
# Handoff: задача 13 закрыта конвейером, дальше — задача про расписание и HITL
Дата: 2026-07-12 23:59.
Жанр: handoff по ADR-0003 после сессии «задача 13 (глагол next-day) по
/claude-subagent-playbook».
## Что закрыто
- **Задача 13 — done.** Полный конвейер плейбука: двойное слепое ревью
постановки (оба CHANGES_REQUIRED, 9 решений внесены, коммит `540989d`)
-> реализация Codex (`gpt-5.6-sol`, high, тред
`019f57d2-ff7b-70d3-8143-3740324309d9`) -> два слепых ревью кода
(Codex: CHANGES_REQUIRED 3 MAJOR; Claude: APPROVED_WITH_MINORS) ->
триаж в 2 круга + узкий диагноз нулевого стыка -> перепроверки
ALL_CLOSED у обоих -> моя приёмка. Коммит `f5dee26`.
- Суть решений, диагноз нулевого стыка (естественный ночной провал, не
дефект restore) и аргументы отклонений — в самой задаче
`.scratch/generator-model-time-startup-history/issues/13-*.md`, здесь
не дублируются.
- Приёмка своими глазами: `make test` 204+31; `generated-history-chain-check`
зелёный (граница 1: crossing=1, граница 2: crossing=0 с явным статусом,
непарные — нули); регрессия `generated-history-runtime-check` задачи 20
зелёная (19 переходящих визитов). Учебный цикл: DM 322 -> 10 026 ->
19 196 за два next-day.
## Состояние
- Ветка `feature/data-generator`, дерево чистое после `f5dee26`
(+ handoff-коммит следом), запушено в origin.
- Стенд поднят, в мире 3 модельных дня (артефакт + два next-day от
прогонов исполнителя); live-генератор остановлен.
- Модель Codex — `gpt-5.6-sol` (high для реализации/ревью; xhigh не
окупается). Перед каждым фоновым запуском — сообщать пользователю, что
запускается и какой этап.
## Что дальше
1. **Завести задачу про расписание** («имитация жизни»): включение
`next-day` по расписанию. Обязана решить: как расписание задаёт
`operation=next-day` (дефолт DAG — `backfill`, планового запуска с
дефолтом быть не должно) и retention/формат накопительного состояния
манифеста (см. отклонение «полная перечитка Kafka» в задаче 13 —
оно блокирует её по записи в тикете).
2. **Ручная HITL-проверка пути менти** (Airflow UI, Superset глазами,
Kafka UI) — переносится пятый handoff подряд; исполнитель задачи 13
отметил, что Airflow UI руками не гонял (проводка next-day проверена
контрактными тестами и реальными запусками через `run_batch.sh`).
3. **Внести уроки в плейбук**: рефлексия по расходу контекста мастера
проведена в конце сессии 2026-07-12/13 (см. итоговое сообщение) —
согласовать с пользователем и записать в
`~/.claude/skills/claude-subagent-playbook/references/lessons.md`.
Ключевые кандидаты: ограничить раздел confirmations у ревьюеров
(одна строка на пункт); самый большой неконтролируемый расход —
эхо всего файла задачи в контекст мастера, когда исполнитель правит
файл, который мастер недавно писал сам.
## Проверки этой сессии
- `make test`: 204 (генератор) + 31 (контракты корня) — прогнаны мной,
исполнителем и ревьюерами независимо.
- Стенд: chain-check и runtime-check зелёные (лог приёмки одноразовый в
session-scratchpad, сводка — в задаче 13).
- Дерево сверялось с baseline после каждого ревью/перепроверки —
ревьюеры исходники не трогали.
## Отклонения процесса
- Перепроверка Codex принесла новую находку (MAJOR про микросекунды) —
это не нарушение узости, штатный случай из prompt-templates.md;
закрыта вторым кругом триажа тем же тредом исполнителя.
- Требование «громкий отказ на нулевом стыке» из обоих ревью покраснело
на честном стенде; решён диагнозом по данным (ветка «естественный
провал») и сменой семантики на явный статус — класс «артефакт
верификатора», как в задаче 20.
## Suggested skills
- `claude-subagent-playbook` — задача про расписание тем же конвейером
(постановку писать с нуля — этапы 1–2).
- `conventional-commits` — коммиты.
- `research` — если для задачи про расписание понадобится фактура по
Airflow (params при scheduled runs) — через Context7.
@@ -1,103 +0,0 @@
# Handoff: ручной HITL пути менти пройден — вырос в набросок редизайна
Дата: 2026-07-19 21:44.
Жанр: handoff по ADR-0003 после сессии «ручная HITL-проверка пути менти»
(долг переносился пятый handoff подряд — закрыт).
## Что сделано
- **HITL-проверка пути менти пройдена целиком, своими руками через UI.**
Чистый стенд (`make clean` + `make up`) -> Airflow UI: `ddl_init` ->
`generator_control` `backfill` (профиль `ci`) -> ETL -> `make superset-init`
-> дашборд глазами -> `generator_control` `next-day` -> проверка стыка.
Каждый шаг сверен по данным (ClickHouse, manifest, chain-check).
- **Результат мира:** backfill `[00:00, 06:00)` = 16 054 события; после
`next-day` = 110 602 события, визитов 10 228, пользователей 1 726;
`boundaries` = три границы, `model_t_end` = `2026-01-02 06:00`.
`generated-history-chain-check` — EXIT 0 (стык 06:00: 9 переходящих
визитов, непарных 0, однородность подтверждена).
- **9 находок + рамочная модель** — в
`.scratch/generator-model-time-startup-history/hitl-findings.md`.
Половина находок родилась из наблюдений менти. HITL из «проверить, что
не сломалось» перерос в **набросок редизайна пути менти**.
## Ключевые выводы (кратко; подробно — в hitl-findings.md)
- **Рамочная модель менти:** основной режим — `import` артефакта (база),
дальше две ветки от одного состояния: `next-day` (пакетно) и `continue`
(живой поток). Это три разных лабораторных. `next-day` и `continue`
не схлопывать. Подтверждено `launch.py:117-137`.
- **F7 + замер:** опыт на 6h беден; нужен готовый артефакт из файла.
Артефакт 6h = 49 МБ; `xz -9e` -> 1,1 МБ (48x, 13,5 с). На 3 дня ~13 МБ
— кладётся в обычный git. Паттерн-образец: `airflow-greenplum-solution`
(`bookings/seed/demo.sql.xz`).
- **Решение менти:** целевой стартовый мир — **3 дня на `daily-wave`**
(обсуждаемо). На `ci` три дня плоские — волну даёт `daily-wave`.
- **F8:** два профиля путают. Свести к одному учебному (волна, ×60);
`ci` (×1) — служебный для тестов. ×60 оправдан live-лабой (`continue`).
- **F9:** `next-day` растёт O(N²) из-за полной перечитки Kafka для
счётчиков (`service.py:591`). Параллелить не то (ломает детерминизм);
правильно — инкрементальные счётчики (O(N), снимает риск OOM). Это и
есть решение «новый формат состояния manifest», блокирующее расписание.
- **F1, F5 (баги UI):** форма `generator_control` держит необязательные
поля обязательными (`type="string"` без `null`); Airflow и Superset
быстро разлогинивают (ротацию секрета исключил, корень TBD).
## Состояние
- Ветка `feature/data-generator`. После этого handoff в дереве останутся:
`hitl-findings.md` + этот handoff (коммитятся), плюс **не коммитить**
`data/ci_backfill.json` (49 МБ, побочный от backfill; `.gitignore` его
не покрывает — риск, см. ниже).
- Стенд **оставлен поднятым** по просьбе пользователя; в мире 1,25 суток
(профиль `ci`), live-генератор не запущен. Выросший мир можно смотреть
в Superset (dashboard id 1).
## Что дальше
1. **Разложить находки в постановки по плейбуку** (этапы 1-2, двойное
слепое ревью). Ориентировочно ~4 задачи (номера 21+ в `issues/`):
- **Ядро:** эталонный 3-дневный артефакт (`daily-wave`) как база
менти через `import`; формат/сжатие (`xz`, нужен ли `raw_topics`);
место хранения (git после отладки сида). Снимает F7.
- **Профиль:** один учебный профиль, `ci` -> служебный тестовый.
Перед слиянием проверить, не зависит ли live-тест от скорости ×1
(F8).
- **Расписание + retention:** беспараметрный DAG `next-day` (F1/F3),
`schedule`, инкрементальные счётчики manifest (F9/F6). Это одна
связка — их корень общий.
- **Баг-фиксы:** F1 (форма) и F5 (разлогин); F4 (JS-баг Grid) низкий.
2. **Три режима -> свои уроки/лабы** — вход в учебный контент
(`docs/course/`). Под каждую ветку отдельная лаба: `next-day`
(пакетная инкрементальная обработка) и `continue` (потоковый приём);
общая база `import` — их совместное начало. Отдельно от
инфраструктурных задач.
3. **Мелочь по гигиене:** `data/*.json` не покрыт `.gitignore`
побочные артефакты backfill (49 МБ) рискуют попасть в коммит. Решить:
правило в `.gitignore` или чистить артефакты после прогонов.
## Проверки этой сессии
- `ddl_init`: 4 слоя созданы (stg 12 / ods 8 / dds 2 / dm 6 таблиц).
- Форма мира после backfill: пирамида 445 < 1516 < 16 054, интервал
`[00:00, 06:00)` точный.
- После `next-day`: 3 границы в manifest, мир до `2026-01-02 06:00`.
- `generated-history-chain-check`: EXIT 0.
- Длительность `next-day` (метаданные Airflow): задача `run_next_day`
638 с (~10,6 мин); ETL `trigger_etl` 30 с — узкое место в генерации.
- Замер сжатия: `xz -9e` 48x за 13,5 с; gzip -9 17x.
## Отклонения процесса
- Ревью субагентами не запускали: пользователь просил «свежий взгляд»,
что по договорённости = без субагентов. Проверка проведена мной руками.
- Обход бага F1: форму backfill/next-day заполняли значениями профиля
`ci` целиком (пустые необязательные поля UI не пропускает).
## Suggested skills
- `claude-subagent-playbook` — разложить находки в постановки тем же
конвейером (этапы 1-2 с нуля).
- `conventional-commits` — коммиты.
- `research` / Context7 — для задачи про профиль/форму (Airflow Param
`type=["null","string"]`) и про формат артефакта.
@@ -0,0 +1,89 @@
# Handoff: старт редизайна пути менти — спека и пилот GitHub Issues
Дата: 2026-07-19 22:29.
Жанр: handoff по ADR-0003 — точка входа в новую фичу на чистой ветке.
## Контекст
- `feature/data-generator` (146 коммитов) влита в main (`0e312b3`) и
запушена. Перед слиянием закрыта задача 21: баг F1 (необязательные поля
формы `generator_control` требовались как обязательные) починен через
`Param(None, type=["null", "string"])`, `.gitignore` покрыл артефакты
`data/*.json`, доки (`ARCHITECTURE.md`, `REPO_MAP.md`) догнали код.
`make test` (205 + 31) и `make lint` зелёные.
- `.scratch` очищен целиком (решение пользователя 2026-07-19): задачи
01–21, PRD, журналы и старые handoff'ы — одноразовые материалы, всё
долговечное перенесено в `docs/` (ADR 00040006, спеки, runbook
`startup-history`). История доступна в git: см. состояние на `0e312b3`,
ключевой файл находок —
`.scratch/generator-model-time-startup-history/hitl-findings.md@0e312b3`.
## Направление работ: редизайн пути менти
Рамочная модель (из ручного HITL 2026-07-19, подтверждена по
`launch.py`): основной режим менти — **`import` готового артефакта**
(база), от одного восстановленного состояния две ветки-лабы:
**`next-day`** (пакетно добавить сутки) и **`continue`** (живой поток,
оправдывает скорость ×60). `backfill` в целевой модели — инструмент
мейнтейнера для сборки артефакта, не первый шаг менти.
Ориентировочно 4 задачи:
1. **Ядро: эталонный 3-дневный артефакт** на профиле `daily-wave` как
база менти через `import`. Факты: артефакт 6h = 49 МБ raw; `xz -9e`
жмёт 48× (1,1 МБ за 13,5 с); 3 дня ≈ 13 МБ сжатого — кладётся в
обычный git. Паттерн-образец: `airflow-greenplum-solution`
(`bookings/seed/demo.sql.xz`). Открыто: нужен ли артефакту
`raw_topics` или хватит компактного `state`.
2. **Один учебный профиль**: `daily-wave` (волна, ×60) — учебный,
`ci` (×1, плоский) — служебный для тестов; форма не должна
подсовывать `ci` первым. Перед слиянием проверить, не зависит ли
runtime-seam-тест от скорости ×1.
3. **Расписание + инкремент**: беспараметрный DAG `next-day` (удобство
менти и пригодность к `schedule`) + инкрементальные счётчики manifest:
сейчас `next-day` перечитывает всю Kafka-историю с нуля — O(N²) по
дням и рост RAM (риск OOM); замер: день 2 = 638 с, узкое место —
генерация+пересчёт, не ETL (30 с). Параллелить нельзя (детерминизм),
правильный рычаг — накопленное состояние счётчиков в manifest/state.
4. **Баг-фиксы**: F5 — быстрый разлогин Airflow и Superset (ротация
секрета исключена; копать время жизни сессии/cookie); F4 — JS-ошибка
авто-refresh в Airflow Grid (косметика, низкий приоритет).
Отдельная линия (после инфраструктуры): три режима → свои лабы в
`docs/course/` (`import` — общая база; `next-day` — пакетная
инкрементальная обработка; `continue` — потоковый приём).
## Пилот GitHub Issues (решение пользователя 2026-07-19)
Новый процесс для этой фичи:
- Спека редизайна — файлом в репозитории (материал — hitl-findings из
истории git, см. выше).
- Тонкий корневой issue на GitHub со ссылкой на спеку и чекбоксами на
дочерние issues; дочерние — полноценные самодостаточные постановки.
- Triage-метки — пять канонических ролей из `docs/agents/triage-labels.md`
как настоящие метки GitHub.
- В том же заходе поправить контракт: AGENTS.md и
`docs/agents/issue-tracker.md` сейчас говорят «GitHub Issues не
используются» — заменить на правила пилота. Старые задачи не
мигрировать (архив в истории git).
## Что дальше (порядок)
1. Спека редизайна пути менти в `docs/specs/` (из hitl-findings).
2. Обновить контракт трекера (AGENTS.md, `docs/agents/issue-tracker.md`).
3. Корневой issue + 4 дочерних на GitHub, метки.
4. Работа по задачам конвейером `claude-subagent-playbook`.
## Состояние стенда
Стенд поднят: мир 1,25 суток на профиле `ci`, `model_t_end` =
`2026-01-02 06:00`, live-генератор не запущен, дашборд — Superset id 1.
Для новой работы, скорее всего, понадобится чистый прогон (`make clean`).
## Suggested skills
- `claude-subagent-playbook` — конвейер задач.
- `conventional-commits` — коммиты.
- `research` / Context7 — фактура для спеки (формат артефакта, Airflow
`schedule`).