Files
clickstream-ch-kafka-supers…/.scratch/generator-model-time-startup-history/issues/20-flaky-runtime-seam-check.md
T
ddadminandClaude Fable 5 98be722808 docs(generator): диагноз флаки-гейта в задаче 20, задача 13 разблокирована
- Зачем:
  - Codex-диагноз нашёл корень нестабильности runtime-гейта: гонка
    остановки live-генератора, batch публикуется по топикам без
    атомарности, seam-SQL маскирует непарные строки под смену фактуры;
  - попутно закрыт второй открытый вопрос задачи 13 - запасная ветка
    рождения визита уже хранит донора (фикс задачи 09).
- Что:
  - задача 20: диагноз с судьбой трёх гипотез, направление фикса
    (управляемая остановка live + precheck непарных строк), статус
    ready-for-agent;
  - задача 13: вопрос про fallback-ветку закрыт, статус ready-for-human
    (осталось решение по развилке реализации).
- Проверка:
  - утверждение про донора перепроверено по generation.py:194-209;
    эмпирика диагноза - в логах прогонов, пути в задаче 20.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 22:29:42 +03:00

91 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Status: ready-for-agent
# Runtime-проверка стыка нестабильна: фактура меняется через раз
## Parent
`.scratch/generator-model-time-startup-history/PRD.md`
## Что нашли
Два подряд прогона `make generated-history-runtime-check` на одном и том же
стенде (2026-07-07, проверка пути менти) дали разный результат:
- Прогон 1 (20:1820:20): **красный**
`Ошибка: per-event фактура меняется на стыке: 8/19`
(у 8 из 19 визитов, переживших границу backfill->live, поменялась
per-event фактура). При этом `duplicate_events=0`, events=2776.
- Прогон 2 (21:5x, та же команда, без изменений кода): **зелёный**
«runtime-проверка startup-history/live seam прошла», конфликтов 0,
events=2815.
Конфигурация проверки: `GEN_LAUNCH_PROFILE=daily-wave`,
`GEN_HISTORY_DURATION=1h`, `GEN_MODEL_T_END=2026-01-01T01:00:00+00:00`
(зашита в `scripts/run_generated_history_runtime_check.sh`).
## Почему это важно
- Это гейт, которому мы доверяем стык backfill->live (задача 17); флаки-гейт
ничего не гарантирует: красный пугает зря, зелёный ничего не доказывает.
- Смена фактуры на стыке — класс дефекта задачи 09, который считается
закрытым (донор фактуры сохранён в state, тихие fallback'и заменены на
ошибки). Либо фикс неполон, либо есть второй источник расхождения.
- Задача 13 (глагол next-day) навешивает на этот же механизм цепочку границ —
ей нужен доверенный, стабильный гейт.
## Диагноз (Codex, 2026-07-07; ключевой факт перепроверен координатором)
**Корень: гонка остановки live-генератора, а не смена фактуры.** Цепочка:
`run_generated_history_runtime_check.sh` останавливает live сразу после первых
новых STG-строк -> генератор публикует batch по четырём топикам
последовательно, без атомарности -> `docker compose stop generator` может
оборвать процесс между топиками -> часть browser-событий остаётся без парных
location/device/geo -> DDS строит `dds.event` через `LEFT JOIN location`,
и такие строки получают `NULL` в referer/utm -> seam-SQL считает это «сменой
фактуры внутри click_id».
Эмпирика: в красном прогоне `browser_raw=2776`, но `location_raw=2736`
40 live-событий без пары; в зелёном `browser_raw=location_raw=2815`, поэтому
проверка прошла (хотя device/geo и там отстали: 2781).
Судьба гипотез:
1. Запасная ветка рождения — **опровергнута**: ветка уже хранит донора
(`generation.py:194-209`, комментарий «Запасная ветка тоже восстановима»)
и громко падает на неполных locations. Перепроверено координатором по коду.
2. Недетерминизм live — **подтверждена частично**: решает не сид, а настенный
момент остановки процесса и какие топики успели дописаться.
3. Проверочный SQL — **опровергнута в формулировке**: поля не «легитимно
различаются», SQL маскирует пропущенный location под «смену фактуры».
## Направление фикса (из диагноза)
1. **Основное:** сделать остановку live управляемой — завершать после полного
batch/tick и flush всех топиков (bounded live mode или ожидание записи
`generator_batch_history` с полными sent-счётчиками).
2. **Дополнительно:** precheck в seam-check на непарные
browser/location/device/geo live-строки — чтобы ошибка называла реальную
причину, а не «фактура поменялась».
3. Просто увеличить sleep перед stop — отклонено: снижает вероятность,
но гонку не убирает.
## Acceptance criteria
- [x] Причина расхождения 8/19 найдена и названа (код, не догадка) —
см. «Диагноз» выше.
- [ ] Остановка live в runtime-check управляемая: batch дописывается во все
топики целиком до остановки (направление фикса, пункт 1).
- [ ] Seam-check различает «непарные live-строки» и «смена фактуры»:
precheck называет реальную причину (пункт 2).
- [ ] `make generated-history-runtime-check` стабилен: N подряд прогонов
зелёные (N >= 3), зафиксировано в задаче.
## Blocked by
- Нет. Диагноз можно начинать сразу; стенд воспроизводит через раз.
Связано: `09-seam-browser-fixture-not-preserved.md` (класс дефекта и решение
про донора), `13-backfill-top-up-from-snapshot.md` (нуждается в доверенном
гейте на цепочке границ), `17-trusted-checks-startup-history-superset.md`
(появление этого гейта).