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>
This commit is contained in:
+42
-18
@@ -1,4 +1,4 @@
|
||||
Status: needs-triage
|
||||
Status: ready-for-agent
|
||||
|
||||
# Runtime-проверка стыка нестабильна: фактура меняется через раз
|
||||
|
||||
@@ -33,28 +33,52 @@ Status: needs-triage
|
||||
- Задача 13 (глагол next-day) навешивает на этот же механизм цепочку границ —
|
||||
ей нужен доверенный, стабильный гейт.
|
||||
|
||||
## Гипотезы (проверить при диагнозе)
|
||||
## Диагноз (Codex, 2026-07-07; ключевой факт перепроверен координатором)
|
||||
|
||||
1. **Тихая запасная ветка рождения визита** (`generation.py`, ветка без
|
||||
донора-кандидата): при истории в 1 час словарь визитов маленький, донора
|
||||
с достаточным числом событий может не найтись. Задача 09 требовала
|
||||
«молча оставить как есть нельзя» — проверить, что сделал фикс.
|
||||
2. Недетерминизм live-части: реальное время тиков решает, какие визиты
|
||||
пересекут границу; сам факт «через раз» указывает на зависимость от
|
||||
wall-clock, а не от сида.
|
||||
3. Проверочный SQL: убедиться, что сравнение полей не цепляет поля,
|
||||
легитимно различающиеся (по образцу исключения `event_id` в задаче 09).
|
||||
**Корень: гонка остановки 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».
|
||||
|
||||
## Acceptance criteria (черновые)
|
||||
Эмпирика: в красном прогоне `browser_raw=2776`, но `location_raw=2736` —
|
||||
40 live-событий без пары; в зелёном `browser_raw=location_raw=2815`, поэтому
|
||||
проверка прошла (хотя device/geo и там отстали: 2781).
|
||||
|
||||
- [ ] Причина расхождения 8/19 найдена и названа (код, не догадка).
|
||||
- [ ] Либо генератор починен (фактура на стыке стабильна при любом профиле),
|
||||
либо проверка исправлена (если ловила легитимные различия) — с объяснением.
|
||||
Судьба гипотез:
|
||||
|
||||
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), зафиксировано в задаче.
|
||||
- [ ] Если срабатывает запасная ветка рождения — она стала громкой или
|
||||
воспроизводимой при восстановлении (наследие задачи 09 и открытый вопрос
|
||||
задачи 13 закрываются согласованно).
|
||||
|
||||
## Blocked by
|
||||
|
||||
|
||||
Reference in New Issue
Block a user