docs(generator): решения #40 после холодного ревью

- Зачем:
  - холодное ревью нашло две дыры уровня решений: лифт конверсии не делает
    покупателя видимым в данных, а цены каталога кратны рублю — от этого
    урок про Float64 остаётся без материала.
- Что:
  - метка покупателя получает второй рычаг: помеченные дольше живут и чаще
    возвращаются; границы правки заданы вилками раздела 5, база до правок
    записана числами.
  - часть цен каталога получит копейки; хвост этапу 4 переписан честнее.
  - дописаны нерешённые места: количество штук и повторная карточка,
    множество нумерации заказов, таблица «код — скидка», состав сырого
    ecommerce, резерв времени вместо зажима к полуночи.
  - два расхождения внесены в мастер-спеку и записаны в раздел 7: длина
    массивов purchase* и product*, механика класса amount_delta.
- Проверка:
  - чтением: docs/specs/2026-08-01-generator.md, разделы 7-9;
    docs/specs/2026-07-30-stand-v2-realism.md, разделы 1, 4, 7.
This commit is contained in:
2026-08-02 17:37:48 +03:00
parent a7442765ff
commit 2cfda7180f
2 changed files with 104 additions and 58 deletions
+7 -4
View File
@@ -48,8 +48,10 @@
## 1. Широкое событие кликстрима
Форма — хит Метрики из облачной выгрузки: одно событие = одна строка,
многозначное — в параллельных массивах одной длины, плюс одно сырое
JSON-поле `ecommerce`. Сессий в потоке нет — их менти собирает сам в DDS.
многозначное — в параллельных массивах, плюс одно сырое JSON-поле
`ecommerce`. Одна длина у массивов общая внутри группы: `purchase*` — по
элементу на заказ, `product*` — по элементу на товар; между собой группы
разной длины. Сессий в потоке нет — их менти собирает сам в DDS.
### 1.1 Решения по именам и типам
@@ -239,7 +241,7 @@ CSV в репозитории (`data/catalog/products.csv`: `sku`, `name`, `cate
|---|---|---|---|
| A | Отмена | заказ дошёл до `cancelled`, `purchase` остался | ~5% заказов |
| B | Потерянное событие | заказ есть, `purchase` не доехал | ~3% |
| C | Дельта суммы | сверка приведена к сравнимой базе (`items_total`, не `total`); `amount_delta` — только необъяснённый остаток после этого: округления Float64, вероятность в генераторе | ~12% |
| C | Дельта суммы | сверка приведена к сравнимой базе (`items_total`, не `total`); `amount_delta` — только необъяснённый остаток после этого, и создаёт его генератор намеренно: деньги считаются целыми копейками, поэтому Float64 сам по себе не плывёт | ~12% |
| D | Дубль события | повторный `purchase` от обновления `/confirmation`: новый `WatchID` с тем же `purchaseID` — бизнес-дубль, не технический; дедуп ReplacingMergeTree его не съедает и не должен | ~2% |
Классы пересекаются — приоритет: `cancelled` > `lost_event` >
@@ -405,7 +407,8 @@ Kafka день переигрывается генератором заново:
(`match` / `cancelled` / `lost_event` / `duplicate_event` / `amount_delta`,
в порядке приоритета — классы пересекаются, побеждает более ранний).
`match` — большинство строк; `amount_delta` — только необъяснённый остаток
после приведения к сравнимой базе (округления Float64, ~1–2% заказов).
после приведения к сравнимой базе; его создаёт генератор намеренно
(~1–2% заказов, см. раздел 4).
Строка «`purchase` без заказа» внутри живого окна — опоздание, ждущее
слепка, а не расхождение: она получает служебный класс `awaiting_order`
(шестое значение `mismatch_class`, вне приоритетов расхождений). После