feat(generator): план состава мира — зерно, приток, двухкуковые пары #46

Merged
ddmitry merged 5 commits from feat/38-world-plan into main 2026-08-02 13:25:58 +03:00
Owner

Closes #38.

Зачем

Состав мира — чистая функция зерна: популяция посетителей с привычками,
календарь появления и затухания, календарь двухкуковых пар и иерархия
зёрен, на которой держится весь детерминизм. Счётчики будущего манифеста
известны по плану — до генерации хоть одного события.

Что

  • world.py — конфигурация мира одним модулем чистых данных: приток,
    недельная волна, профиль возвратов, доли покупателей и пар, D0.
  • seeds.py — дерево зёрен на SeedSequence: состав мира (ось и
    предыстория — отдельные ветви) и дни с именованными компонентами.
  • plan.py — ленивый план: когорта дня, аудитория дня из окна возвратов,
    гарантированные заказы пар, счётчики горизонта. Случайность — только
    целыми числами.
  • Спека, раздел 1: вторая кука пары рождается по затухающему профилю
    возвратов; окно активности — от первого визита человека, общее на обе
    куки. Раздел 2: ветвь предыстории в дереве зёрен. Раздел 9: измеренные
    числа канонического мира.
  • CONTEXT.md: «когорта дня», «подпоток», «конфигурация мира»; «хвост
    возвратов» уточнён.

Числа канонического мира (14 дней)

Приток 3 828 кук в день в среднем, дневная аудитория 6 235–7 124 — обе
величины в вилках раздела 5. Накопленная аудитория 68 тыс.: 53,6 тыс.
новыми куками плюс 14,5 тыс. возвратами предыстории — прежняя оценка
≈60 тыс. считала возвраты предыстории вдвое скромнее, в спеке поправлено.
Пар, реализованных внутри снимка, — 170.

Проверка

  • make test — 297 тестов; make lint, make typecheck — чисто.
  • Тесты проверены мутациями: 17 подмен в plan/world/seeds,
    выживших нет.
  • Три линии ревью: стандарты репозитория, соответствие постановке,
    линия дефектов Кодексом. Все находки закрыты; одна отклонена с доводом
    (полная неприкосновенность запомненной когорты в numpy недостижима —
    граница защиты названа в докстроке).
Closes #38. ## Зачем Состав мира — чистая функция зерна: популяция посетителей с привычками, календарь появления и затухания, календарь двухкуковых пар и иерархия зёрен, на которой держится весь детерминизм. Счётчики будущего манифеста известны по плану — до генерации хоть одного события. ## Что - `world.py` — конфигурация мира одним модулем чистых данных: приток, недельная волна, профиль возвратов, доли покупателей и пар, D0. - `seeds.py` — дерево зёрен на `SeedSequence`: состав мира (ось и предыстория — отдельные ветви) и дни с именованными компонентами. - `plan.py` — ленивый план: когорта дня, аудитория дня из окна возвратов, гарантированные заказы пар, счётчики горизонта. Случайность — только целыми числами. - Спека, раздел 1: вторая кука пары рождается по затухающему профилю возвратов; окно активности — от первого визита человека, общее на обе куки. Раздел 2: ветвь предыстории в дереве зёрен. Раздел 9: измеренные числа канонического мира. - CONTEXT.md: «когорта дня», «подпоток», «конфигурация мира»; «хвост возвратов» уточнён. ## Числа канонического мира (14 дней) Приток 3 828 кук в день в среднем, дневная аудитория 6 235–7 124 — обе величины в вилках раздела 5. Накопленная аудитория 68 тыс.: 53,6 тыс. новыми куками плюс 14,5 тыс. возвратами предыстории — прежняя оценка ≈60 тыс. считала возвраты предыстории вдвое скромнее, в спеке поправлено. Пар, реализованных внутри снимка, — 170. ## Проверка - `make test` — 297 тестов; `make lint`, `make typecheck` — чисто. - Тесты проверены мутациями: 17 подмен в `plan`/`world`/`seeds`, выживших нет. - Три линии ревью: стандарты репозитория, соответствие постановке, линия дефектов Кодексом. Все находки закрыты; одна отклонена с доводом (полная неприкосновенность запомненной когорты в numpy недостижима — граница защиты названа в докстроке).
ddmitry added 5 commits 2026-08-02 13:24:02 +03:00
- Зачем:
  - тикет #38 требует решить и внести в спеку генератора числа притока,
    D0 и формат конфигурации мира до реализации плана состава.
- Что:
  - раздел 1 спеки: ленивый план по когортам дня, предыстория с полкой
    от D0, гарантия двухкуковых пар назначенными заказами (единица —
    человек), пять отклонённых вариантов с доводами.
  - раздел 9: приток 3 800 кук/день, окно активности 90 дней (решение
    владельца), доля покупателей 5% людей, D0 = 2026-06-01,
    конфигурация мира — модуль чистых данных; шапка Proposed → Accepted.
  - CONTEXT.md: термины «план состава», «приток», «хвост возвратов»,
    «предыстория»; «состав мира» уточнён, словарь очищен от решений.
- Проверка:
  - двойное слепое ревью правок (Codex + Claude), все 20 находок
    закрыты; арифметика чисел пересчитана ревьюерами независимо.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Зачем:
  - тикет #38: состав мира должен быть чистой функцией зерна, а счётчики
    будущего манифеста — известны до генерации хоть одного события.
- Что:
  - `world.py` — конфигурация мира одним модулем чистых данных: приток,
    недельная волна, профиль возвратов, доли покупателей и пар, D0.
  - `seeds.py` — иерархия подпотоков на `SeedSequence`: состав мира
    (ось и предыстория) отдельно от дней и их компонентов.
  - `plan.py` — ленивый план состава: когорта дня, аудитория дня из
    окна возвратов, гарантированные заказы пар, счётчики горизонта.
    Случайность — только целыми числами.
  - спека, раздел 1: вторая кука пары рождается по затухающему профилю
    возвратов; раздел 9: измеренные числа канонического мира, оценка
    накопленной аудитории поправлена с ≈60 до 68 тыс.
  - CONTEXT.md: термин «когорта дня»; README генератора — новые модули.
- Проверка:
  - make test (295 тестов), make lint, make typecheck;
  - тесты проверены мутациями: 12 подмен в плане и конфигурации,
    каждая роняет ровно свой тест.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Зачем:
  - ревью нашло два места, где код и документы говорили неправду, и
    несколько мест, где имена или комментарии вводили в заблуждение.
- Что:
  - обещание докстроки `seeds.py` подкреплено тестом: адрес в дереве
    даёт тот же подпоток, что цепочка `spawn`.
  - в тесте гарантии пар убран сторож-тавтология, вместо него проверка,
    что заказы назначены с двух разных кук.
  - `Cohort.visitors_on` — «кто пришёл в день D» спрашивается у когорты,
    а не собирается снаружи из четырёх её массивов.
  - имена: `CLIENT_ID_LIMIT`, `_RETURN_*_CUMULATIVE`, `first_of_day`,
    `WEEKLY_PROFILE_PERCENT` — профиль недели один на весь мир, по нему
    же пойдёт трафик дня-функции (#39).
  - спека: в дерево зёрен внесена ветвь предыстории; окно активности —
    от первого визита человека, общее на обе куки (иначе загляд назад
    ленивой формы удваивается); оценка накопленной аудитории больше не
    спорит с измерением.
  - CONTEXT.md: «подпоток» и «конфигурация мира».
- Проверка:
  - make test (296), make lint, make typecheck; мутации перепроверены
    после переноса среза дня в `Cohort`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Зачем:
  - третья линия ревью (Кодекс, другое семейство моделей) нашла дыру в
    стороже неизменности когорты, отставший словарь и тест, который
    сторожил не тот адрес дерева зёрен.
- Что:
  - когорта отдаётся видом на замороженный массив: флаг только для
    чтения вызывающий мог снять и испортить память, которой пользуются
    все дни окна. Граница защиты названа в докстроке — от случайности,
    не от умысла.
  - CONTEXT.md и комментарий `RETURN_TAIL_DAYS`: окно активности — от
    первого визита человека, общее на обе куки (спека это уже говорила,
    словарь отстал).
  - сторож предыстории сверял день −N с днём N, а сталкиваются −N и
    N−1; тем же классом слепоты страдали сторожа независимости состава
    и дня и различия компонентов — все три переписаны на сверку со всем
    куском адресов, куда подпоток мог бы попасть.
- Проверка:
  - make test (297), make lint, make typecheck;
  - батарея из 17 мутантов по plan/world/seeds — выживших нет; гоняется
    с PYTHONDONTWRITEBYTECODE=1: цикл правки и отката внутри одной
    секунды оставлял устаревший .pyc, и тесты шли по старому байт-коду.
- Отклонено с доводом:
  - перепроверка настаивала, что сторож неизменности не закрыт: через
    `.base` вида владелец данных размораживается. Верно фактически, но
    закрывающего состояния у находки нет — владелец памяти в numpy
    размораживается всегда, а копия когорты на каждый вызов меняет 2 мс
    на 16 МиБ копирования и убивает смысл запоминания.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ddmitry merged commit 937ba014b4 into main 2026-08-02 13:25:58 +03:00
ddmitry deleted branch feat/38-world-plan 2026-08-02 13:25:58 +03:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ddmitry/clickstream-data-platform#46