- Зачем:
- трекер стенда был полным, и правило «деньги — по бэкенду» держалось
на слове; классы B и D делают недосчет и пересчет трекера
наблюдаемыми (этап 6, #184).
- Что:
- подпоток BEACONS: точечная потеря purchase (~3%) и сюжетный дубль
(~2%) швом после _purchases, с гарантией моста идентичностей и
условием допуска дубля по паузе до следующего визита;
- опись считает пять классов по приоритету спеки; фильтр
classes_vs_inventory расширен, нулевой класс читается нулем;
- fate.md, seeds.md, dm.md и orders/README.md приведены к имени
BEACONS и строгому правилу допуска.
- Проверка:
- make lint, make typecheck, make test (433 passed) и make inventory
из generator/ — хеши слепков не изменились;
- на стенде: make smoke, make check-clickhouse, make check-services
зеленые; в dq_summary classes_vs_inventory и sessions_vs_reference
pass, витрина сверки показывает lost_event и duplicate_event.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
62 lines
3.9 KiB
Markdown
62 lines
3.9 KiB
Markdown
# Дерево зерен и порядок бросков
|
||
|
||
Этот документ отвечает на вопрос, почему место подпотока стабильно, а порядок
|
||
бросков внутри него менять нельзя.
|
||
|
||
## Два порядка
|
||
|
||
[`seeds.cohort_stream`](../../../generator/src/clickstream_generator/seeds.py)
|
||
и [`seeds.day_stream`](../../../generator/src/clickstream_generator/seeds.py)
|
||
находят ветвь по позиции `SeedSequence(entropy, spawn_key)`. Поэтому результат
|
||
ветви не зависит от того, какую соседнюю ветвь вычислили раньше.
|
||
|
||
Внутри найденной ветви живет один `Generator`. Каждый его вызов забирает
|
||
следующие значения. Поэтому порядок вызовов меняет результат: прежний
|
||
пятый бросок после вставки становится шестым и достается другому свойству
|
||
мира.
|
||
|
||
Дерево целиком описано в модуле
|
||
[`seeds`](../../../generator/src/clickstream_generator/seeds.py), а
|
||
[`seeds.Component`](../../../generator/src/clickstream_generator/seeds.py)
|
||
задает его нижний уровень — четыре подпотока дня:
|
||
|
||
```text
|
||
корневое зерно
|
||
├── состав мира
|
||
│ ├── ось событий → номер дня → когорта
|
||
│ └── предыстория → глубина → когорта до D0
|
||
└── дни
|
||
└── номер дня
|
||
├── TRAFFIC
|
||
├── COMMERCE
|
||
├── ORDERS
|
||
└── BEACONS — потеря и повторная отправка событий
|
||
```
|
||
|
||
Отрицательному дню нельзя отдать отрицательную позицию, поэтому предыстория
|
||
получила отдельную ветвь. Компоненты дня тоже занимают позиции, а не получают
|
||
зерна в порядке запуска.
|
||
|
||
## Что ломает вставка
|
||
|
||
Новый бросок в середине функции сдвигает все последующие значения этого
|
||
подпотока. Код продолжает работать, но тем же свойствам достается другая
|
||
случайность. Соседние подпотоки остаются прежними, а измененная часть
|
||
канонического мира проявляется в описи и побайтовом сравнении.
|
||
|
||
Какое обещание воспроизводимости это защищает, записано в
|
||
[спеке генератора](../../specs/2026-08-01-generator.md), раздел 2. Здесь важно
|
||
различать два свойства: `SeedSequence` стабилизирует адрес ветви, но порядок
|
||
бросков внутри `Generator` стабилизирует только сам код.
|
||
|
||
## Броски последними
|
||
|
||
Новое свойство продолжает существующий подпоток после прежних бросков. Такой
|
||
бросок не отнимает значения у уже рассчитанных свойств. В
|
||
[`plan.cohort`](../../../generator/src/clickstream_generator/plan.py) паспорт
|
||
куки был дописан после состава и назначенных заказов, а личность человека —
|
||
после паспорта. Поэтому прежние ряды остались прежними.
|
||
|
||
Почему паспорт вообще принадлежит этой ветви, разобрано отдельно в
|
||
[документе о паспорте куки](cookie-passport.md).
|