diff --git a/CONTEXT.md b/CONTEXT.md index b351b7b..de3c1d0 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -12,9 +12,9 @@ _Избегать_: склад, склад данных **Состав мира**: -Постоянная часть мира генератора — популяция посетителей, их привычки, -календарь двухкуковых пар. Чистая функция зерна: вычисляется при старте -любого процесса, между прогонами не хранится. +Постоянная часть мира генератора — популяция посетителей с календарём их +появления, привычки, календарь двухкуковых пар. Чистая функция зерна: +вычисляется при старте любого процесса, между прогонами не хранится. _Избегать_: состояние мира **Ось модельного времени**: diff --git a/docs/specs/2026-08-01-generator.md b/docs/specs/2026-08-01-generator.md index 68ca0c9..537c4b4 100644 --- a/docs/specs/2026-08-01-generator.md +++ b/docs/specs/2026-08-01-generator.md @@ -48,6 +48,13 @@ плана состава, а не копятся в состоянии. Глобальные инварианты («каждый двухкуковый покупатель заказал с обеих кук») гарантируются планом — счётчики манифеста известны до генерации событий. +- **Состав не замкнут: посетители появляются и уходят.** План состава задаёт + календарь появления — у каждого посетителя есть дата первого визита и + профиль возвратов, заметная доля кук одноразовая, как в живом трафике. + Новые посетители появляются на всём протяжении оси: uniq(ClientID) растёт + с горизонтом, DAU и MAU не сходятся в одно число. Приток — часть плана, а + не мутация: счётчики манифеста по-прежнему известны до генерации + (уточнение по вычитке владельца, 2026-08-01). - **Своя ось модельного времени.** Мир рождается в фиксированный день D0 (понедельник — см. раздел 5); реальный календарь в модели не участвует. Между прогонами живут только зерно и позиция на оси: выключенный ноутбук — @@ -278,8 +285,11 @@ pytest-тест с маркером `perf` и таймаутом-обрубан звать; деньги — в целых копейках. - **Случайные значения — векторно из numpy (PCG64)**; посточный цикл — лишь там, где логика действительно посточная (цепочки сессий). -- **Faker — только для справочников** (каталог, имена), не в горячем цикле: - он медленнее numpy на 2–3 порядка. +- **Посточные фейкеры (Faker, mimesis) — только для справочников** (каталог + и прочие справочные строки), не в горячем цикле: они медленнее numpy на + 2–3 порядка. Выбор библиотеки — этапу 2: справочники генерируются один + раз, скорость безразлична; возможно, хватит таблиц-литералов в коде и + фейкер не понадобится вовсе. - **Сериализация — через единственный канонический сериализатор** (orjson); прямых `json.dumps` по коду нет. - **Распараллеливание — multiprocessing по модельным дням**; внутри дня — @@ -315,7 +325,8 @@ pytest-тест с маркером `perf` и таймаутом-обрубан Осталось из тумана карты — вопросы уровня тикетов, не развилок: - интерфейс запуска генератора (CLI / цели make) и как он делит режимы - проигрывателя; + проигрывателя; кто его зовёт в стенде — даги `world_init`/`next_day` из + оценки мастер-спеки (раздел 9) — и в каком контейнере он живёт; - формат описания мира и конфигурации (что константа кода, что параметр); - как фиксируется «зерновой» мир конца этапа 2 (раздел 9 мастер-спеки): с манифестным решением напрашивается мини-манифест зернового мира — форму