diff --git a/docs/specs/2026-08-01-generator.md b/docs/specs/2026-08-01-generator.md index 6276fe0..d00d6db 100644 --- a/docs/specs/2026-08-01-generator.md +++ b/docs/specs/2026-08-01-generator.md @@ -198,10 +198,11 @@ целое, поэтому у предыстории своя ветвь состава, отдельная от оси (уточнение при исполнении #38, 2026-08-02); (зерно, день) → подпоток дня → именованные подпотоки компонентов: трафик, - торговые события, заказная и событийная стороны судьбы заказов — в - фиксированном порядке (уточнение [спекой заказов](2026-08-16-orders.md), - раздел 3: прежние «расхождения» и «опоздания» были названы по классам - витрины, а компонент называет часть мира). + торговые события, заказная и событийная стороны (судьба заказов и порча + событийного потока) — в фиксированном порядке (уточнение [спекой + заказов](2026-08-16-orders.md), раздел 3: прежние «расхождения» и + «опоздания» были названы по классам витрины, а компонент называет часть + мира). По построению: параллельный прогон равен последовательному; продление истории днём N+1 не трогает дни 1…N; правка одного компонента меняет только его часть снимка — в описи меняются хеши только затронутых diff --git a/docs/specs/2026-08-16-orders.md b/docs/specs/2026-08-16-orders.md index db4ae54..524c707 100644 --- a/docs/specs/2026-08-16-orders.md +++ b/docs/specs/2026-08-16-orders.md @@ -70,10 +70,11 @@ в трекере — не отдельная порода, а класс B, и делает его событийная сторона выбрасыванием события после присвоения номера (раздел 4); - номер заказа общий у обеих проекций: `order_id` = клиентский `purchaseID`, - читаемый номер «день и порядковый номер покупки» (спека генератора, блок - #40); нумеруются все покупки, дошедшие до потока дня, — до всяких потерь; + читаемый номер «день и порядковый номер покупки» (спека генератора, + раздел 9); нумеруются все покупки, дошедшие до потока дня, — до всяких + потерь; - скидка заказа выводится из промокода события по таблице «код → скидка» — - числу мира, которое этап 3 берёт готовым (спека генератора, раздел 8). + числу мира, которое этап 3 берёт готовым (спека генератора, разделы 8 и 9). В модели строка заказа в базе источника создаётся синхронно с покупкой, поэтому день рождения заказа и день создания строки совпадают. Смысл полей от этого не @@ -96,7 +97,10 @@ глазами как два производителя, каждый со своим топиком. Один прогон с двумя выходами отклонён: экономии он не даёт (со сдвигом отправки окно слепка и сыгранный день не пересекаются вовсе), а правило «приёмник выбирается тем, что -для него назвали» ломает. +для него назвали» ломает. Отклонены также: *отдельный пакет и образ* — +библиотека на двоих ради одной команды; *генератор пишет слепок файлом, в +топик льёт даг* — второй путь доставки и второй сериализатор; *слепок едет +топиком `hits`* — убивает два режима приёма. **Сборка окна.** Слепок дня D несёт заказы, рождённые в дни D−6…D, и собирается переигровкой этих семи дней: заказы дня — производная всей воронки дня, @@ -231,7 +235,7 @@ класса — разрыв воронки, на котором держится потеря, сжался бы втрое; при сюжетном разрыв снова равен доле потерь. `purchaseID`, суммы и позиции у дубля один в один — посчитал наивно, удвоил выручку. Дубль случается только там, где -до следующего визита куки есть место больше таймаута: иначе сборка сессий у +до следующего визита куки остаётся запас сверх таймаута: иначе сборка сессий у менти разошлась бы с `VisitID` — сломался бы эталон, ради которого `VisitID` в потоке лежит. Задержка дубля — секунды-минуты, короче таймаута визита, поэтому `VisitID` тот же. Полночь режет дубль парой — просмотр вместе с @@ -247,12 +251,15 @@ не расхождение в данных; менти различить не может. Гарантия плана старше расхождения. -**Опоздание — заказ прячется от ранних слепков.** `created_at` честный, но в -слепках дней d…d+δ−1 строки нет, а с d+δ она появляется в том состоянии, до -которого заказ дожил: отменённый на второй день и опоздавший на третий приедет -в первом же своём слепке как `cancelled` — «выгрузка догоняет жизнь». Задержка -— таблица весов из трёх строк: 0 на подавляющем весе, 1 и 2 — это и есть -«D+1/D+2» мастер-спеки. Дальше таблица не идёт: заказ с δ = 6 приехал бы ровно +**Опоздание — заказ прячется от ранних слепков.** `created_at` не +подделывается — строка создана, когда заказ родился, — но в слепках дней +d…d+δ−1 её нет, а с d+δ она появляется в том состоянии, до которого заказ +дожил: отменённый на второй день и опоздавший на третий приедет в первом же +своём слепке как `cancelled` — «выгрузка догоняет жизнь». Задержка — таблица +весов из трёх строк: 0 на подавляющем весе, 1 и 2 — это и есть «D+1/D+2» +мастер-спеки. Меряется она в днях снятия слепка, а не отправки: иначе сдвиг +отправки удвоился бы, и обещанные D+1/D+2 стали бы D+2/D+3. Дальше таблица не +идёт: заказ с δ = 6 приехал бы ровно в одном слепке, и обещание «пропущенный день ничего не ломает» на нём перестало бы быть верным; при δ ≤ 2 у всякого заказа слепков не меньше пяти. Легенда: заказ ушёл в ручную обработку и попал в выгрузку позже. Следствие для @@ -263,7 +270,8 @@ **Пересечения.** Броски независимы, пересечения выходят арифметикой, приоритет мастер-спеки работает по-настоящему. Исключений два, и оба названы выше: дубль -решается только у выживших покупок, и назначенное планом не портится. +решается только у выживших покупок, а назначенное планом не теряется и не +опаздывает — дельта и отмена ему разрешены, моста они не рвут. Следствие для калибровки: брошенная доля и наблюдаемая в сверке — разные числа (часть заказов забирают победители по приоритету, часть у класса C недоступна — однопозиционных заказов больше половины). Отклонено: *один класс на заказ* — @@ -346,8 +354,10 @@ границе суток 7|8. Генератор играет два источника с разными темпами — поток Метрики и ночную выгрузку магазина; разные темпы дают всё остальное. -`world-init` играет восемь дней одним прогоном `batch --day 0 --days 8`; со -сдвигом отправки уезжают **слепки дней 0…6**. Слепок дня 7 снят на границе +`world-init` играет восемь дней одним прогоном `batch --day 0 --days 8`; +слепки отправляет второй запуск — команда `snapshot` того же диапазона (два +источника — два запуска, раздел 2), и со сдвигом отправки уезжают **слепки +дней 0…6**. Слепок дня 7 снят на границе суток и уедет первым же ходом мира. Особого режима у стартового мира нет: правило отправки живёт в одном месте — в проигрывателе; генератору это решение не стоит ничего.