Commit Graph
18 Commits
Author SHA1 Message Date
ddadminandClaude Opus 5 923ebad80e docs(storage): связность восстановлена, форма дат на проводе задана
- Зачем:
  - холодное ревью связности нашло девять мест, где вставленный текст спорит с
    соседним; отдельно вскрылось, что представление дат в JSON не зафиксировано
    нигде, а #43 обязан его знать раньше, чем #41 напишет сериализатор.
- Что:
  - гарантия приёма переписана: после снятия синхронной вставки «хотя бы один
    раз» стало неправдой — есть и окно потери, и окно дубля.
  - критерий выбора пяти опорных колонок приведён к списку, который он
    порождает; `CounterID` оговорён отдельно.
  - «переобработки у ODS нет вовсе» смягчено до пакетной: ручная вставка из
    сырья в пределах окна возможна.
  - в спеку генератора добавлена форма дат на проводе — ISO-8601, с доводом от
    читаемости слоя сырья.
  - убраны осиротевшая фраза про порядок сервисов, дубль порядка классов брака,
    устаревшая датировка сверки и ещё три следа вставок.
- Проверка:
  - make config-test

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 21:53:03 +03:00
ddadmin 319db308bf docs(storage): приняты решения по приёму событий и именам
- Зачем:
  - тикет #37 молча опирался на конвенции хранилища, которых в проекте не
    было; без них #43 и следующие этапы разъехались бы в именах, служебных
    колонках и механике приёма.
- Что:
  - ADR 0005: топик читается байтами в STG, разбор идёт функциями в матвью
    ODS; строгий приём — сверка набора ключей плюс Nullable на пяти опорных
    колонках.
  - ADR 0006: суффикс вида в именах объектов (_rep, _dist, _kafka, _mv, _v).
  - docs/architecture/storage.md: конвенции имён и служебных колонок, путь в
    keeper, раскладка по шардам, срок жизни сырья, свойства приёма, раскладка
    файлов DDL и карта таблиц.
  - спеки приведены в соответствие: механизм строгого приёма, имена объектов,
    контракт транспорта «одно событие — одно сообщение Kafka», три проверки
    при исполнении.
- Проверка:
  - make config-test
2026-08-04 00:14:13 +03:00
ddadmin 4243aa2c88 docs(generator): вилка конверсии в корзину — ориентир, а не граница
- Зачем:
  - после #50 доля просмотров, доходящих до корзины, подошла к краю вилки
    5–9%, и следующий исполнитель стал бы калибровать поведение под это
    число. Владелец решил: пока доля правдоподобна, она ничего не сторожит —
    у живых магазинов она гуляет широко.
- Что:
  - в блок «Решено при исполнении #50» добавлено решение владельца: вилка —
    ориентир; настоящий предел здесь дневной бюджет событий, на котором
    стоят манифест (#42) и порог скорости дня.
- Проверка:
  - git show --stat; следующий исполнитель читает решение, не переспрашивая.
2026-08-02 22:54:31 +03:00
ddadmin c0f4d21df9 feat(generator): корзина отвязана от страницы, у товара — уровень спроса
- Зачем:
  - приёмка #40 нашла в торговых данных два точных равенства, каких в живом
    магазине не бывает: событие корзины случалось ровно у визитов со
    страницей /cart, а внутри такого визита в корзину уходили все открытые
    карточки. Привлекательность товара было нечем измерить, а аналитик читал
    бы эти равенства как склейку в разметке.
- Что:
  - класть в корзину может любой визит, открывший карточку; страница /cart
    осталась шагом воронки, а у визита, дошедшего до неё, корзина непуста.
  - у товара появился уровень спроса — колонка каталога с тремя значениями
    и два ряда вероятностей в числах мира: намерение визита берётся из шага
    воронки, а не из метки покупателя, которая уже действует через неё.
  - уровни рассыпаны по каталогу одной колодой: одинакового расклада по
    категориям нет, связи с ценой нет, и то и другое сторожится тестами.
  - числа мира перемерены: конверсия карточки в корзину 8,62% (по уровням
    13,1 / 9,2 / 5,8), кладут без открытия корзины 41,4% таких визитов,
    средний день 49 834 события, конверсия визита в покупку 2,43%.
  - спека генератора и мастер-спека приведены к новой форме каталога.
- Проверка:
  - make lint && make typecheck && make test — 394 passed (было 383).
  - трафиковая половина побайтово та же: sha256 по (URL, времени, WatchID)
    всех просмотров за 14 канонических дней совпадает со снимком до правки.
2026-08-02 22:46:30 +03:00
ddadmin 4165f10cdd docs(generator): числа блока грилинга — с канонического зерна
- Зачем:
  - блок «Решено при исполнении #40 после приёмки» цитировал замер на зерне 0,
    а канонический мир, на котором стоят все тесты, — CANONICAL_SEED
    (20260601); числа относились к другому миру.
- Что:
  - замер перемерен на каноническом зерне за 14 дней: тождество «событие
    корзины ↔ страница /cart» держится каждый день, на дне 2 это 828 и 828.
  - уточнены средний день (49 509 событий), конверсия визита (2,43%), состав
    заказа (1,87 позиции) и доля брошенных позиций (число мира 15%, замер по
    покупающим корзинам 12%).
- Проверка:
  - скрипт замера на 14 днях CANONICAL_SEED; git show --stat.
2026-08-02 21:21:43 +03:00
ddadmin fbffeda5ea docs(generator): решения грилинга — корзина и уровень спроса товара
- Зачем:
  - приёмка #40 нашла в торговых данных два точных равенства, каких в живом
    магазине не бывает: событие корзины возникало ровно у визитов со
    страницей /cart, а внутри такого визита в корзину ложились все открытые
    карточки.
- Что:
  - в спеку генератора, раздел 9, добавлен блок «Решено при исполнении #40
    после приёмки»: корзина отвязана от страницы корзины, уровень спроса
    становится свойством товара, границы правки — вилки раздела 5.
  - записаны отклонённые варианты: свой процент у каждого sku и вывод
    склонности из цены.
  - в CONTEXT.md заведён термин «уровень спроса».
- Проверка:
  - git show --stat; текст решений читается без обращения к переписке.
2026-08-02 21:06:51 +03:00
ddadminandClaude Opus 5 722dbe22b7 feat(generator): торговые события — корзина, покупка, сырой ecommerce
- Зачем:
  - клиентская сторона мира становится целой: без add_to_cart и purchase
    в данных нет ни таксономии событий, ни вложенного JSON, ни денег,
    а метка «покупатель» из плана состава ни на что не влияла (#40).
- Что:
  - добавлен модуль commerce: корзина шире заказа, номер заказа вида
    ГГГГММДД-NNNN, промокод без скидки в сумме, сырой ecommerce через orjson;
  - метка покупателя получила два рычага — долгую жизнь куки в плане и
    свою воронку в дне; CART_PERCENT опущен с 8 до 6, чтобы конверсия
    мира осталась около 2%;
  - часть цен каталога получила копейки: productPrice округляется форматом,
    purchaseRevenue несёт точную сумму — расхождение живёт внутри события;
  - граница суток забирает страницу подтверждения вместе с её покупкой:
    потерь на клиентской стороне этот этап не заводит;
  - решения и перемеренные числа мира записаны в спеку генератора, §9.
- Проверка:
  - make lint && make typecheck && make test — 383 passed (было 353).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 19:13:30 +03:00
ddadmin bfbaa96696 docs(generator): форма эффекта метки покупателя — оба шага воронки
- Зачем:
  - холодное ревью отметило, что это решение, а не калибровка: от выбора
    шага зависит, как «покупатель» читается в данных, и оставлять выбор
    реализации нельзя.
- Что:
  - в блоке решений #40 записано, что помеченный отличается на обоих шагах
    воронки — и до корзины доходит чаще, и бросает её реже; числа под
    каждый шаг остаются калибровкой.
- Проверка:
  - чтением: docs/specs/2026-08-01-generator.md, раздел 9, блок #40.
2026-08-02 17:42:48 +03:00
ddadmin 2cfda7180f 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.
2026-08-02 17:37:48 +03:00
ddadmin a7442765ff docs(generator): решения #40 — торговые события
- Зачем:
  - перед реализацией торговых событий грилинг закрыл шесть развилок; без
    записи решения и отклонённые варианты потерялись бы, а часть из них
    выходит за границы тикета и меняет постановку.
- Что:
  - в раздел 9 спеки генератора добавлен блок «Решено при исполнении #40»:
    корзина шире заказа, метка покупателя становится значимой, место
    торговых событий, номер заказа, промокод, единицы денег, разная длина
    массивов purchase* и product*, orjson, хвост покупки у границы суток.
  - в раздел 8 добавлены хвосты этапам 3 и 4: скидка по промокоду и
    намеренное расхождение сумм.
  - в словарь добавлены «покупатель» и «торговое событие».
- Проверка:
  - чтением: docs/specs/2026-08-01-generator.md, разделы 8 и 9; CONTEXT.md.
2026-08-02 17:17:31 +03:00
ddadminandClaude Opus 5 eb433ad023 feat(generator): день-функция — трафик, визиты и просмотры страниц
Зачем: план состава отдаёт дневную аудиторию, но событий у мира ещё не было.
День-функция превращает аудиторию в поток просмотров — на нём стоят лабы про
сборку визитов и про витрины, а следующий этап вешает на него торговые события.

Что:
- `day.py` — день как чистая функция зерна и номера дня: суточная волна в
  местном времени посетителя, визиты по документированным правилам нарезки,
  все 47 колонок выгрузки; шов для торговых событий — ряды `page` и `product`;
- `reference.py` — справочники-литералы: профили устройств, города Поволжья с
  настоящими гео-id Яндекса, источники трафика, карта сайта;
- `catalog.py` и `data/catalog/products.csv` — каталог на 180 позиций, общий у
  генератора и будущего словаря ClickHouse;
- `weights.py` — выбор по целым весам, один на план и на день;
- паспорт куки (устройство и город) переехал в план состава; броски приписаны
  последними, поэтому измеренные числа канонического мира не сдвинулись;
- словарь: «визит» закреплён за сессией, одноимённое понятие плана стало
  «днём активности»; статьи в `CONTEXT.md`;
- решения по ходу — в спеку генератора, раздел 9; наполнение
  `ParsedParamsKey1` отложено тикетом #47.

Проверка: `make lint`, `make typecheck`, `make test` — 353 passed (было 297).
Счётчики плана после правки те же: приток 3827,64/день, дневная аудитория
6235–7124, 68 119 посетителей за 14 дней, 170 двухкуковых пар. День 0 —
45 810 событий за 0,6 с, снимок 14 дней — 5,9 с при пороге 30 с на день.
Две слепые линии ревью, десять находок, все закрыты и перепроверены.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-02 16:12:17 +03:00
ddadminandClaude Opus 5 2502f906a8 fix(generator): правки по двум линиям ревью плана состава
- Зачем:
  - ревью нашло два места, где код и документы говорили неправду, и
    несколько мест, где имена или комментарии вводили в заблуждение.
- Что:
  - обещание докстроки `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>
2026-08-02 12:33:27 +03:00
ddadminandClaude Opus 5 abac6afe18 feat(generator): план состава мира — зерно, приток, двухкуковые пары
- Зачем:
  - тикет #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>
2026-08-02 12:20:48 +03:00
ddadminandClaude Opus 5 78ddb86817 docs(specs): решения #38 — ленивый план состава, числа притока, конфигурация
- Зачем:
  - тикет #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>
2026-08-02 11:47:59 +03:00
ddadminandClaude Opus 5 24c8dd9b98 refactor(generator): нормализованное имя вместо имени в DDS, тесты на имена сняты
- Зачем:
  - контракт вёл себя как хозяин чужого слоя: поле называлось dds_name, в
    описании стоял столбец «Имя в DDS», а два теста прибивали имена
    гвоздями. Спека же задала вид имени (snake_case), а не список: имена
    атрибутов складывает модель данных DDS, и решать это не трекеру.
- Что:
  - поле контракта и столбец описания стали нормализованным именем: имя
    источника в нашем стиле. В описании и в докстринге сказано прямо, что
    слой DDS называет атрибуты по своей модели.
  - сняты оба теста на имена — копия имён DDS и конспект состава по
    мастер-спеке. Они не проверяли верность имени, только неизменность, а
    неизменность и так сторожит пересборка описания: молчаливой правки
    контракта не бывает, она всплывает диффом документа.
  - остались проверки формы: 47 колонок, уникальность, стили имён,
    заполненность, согласие типов numpy и ClickHouse, порядок групп.
  - спека генератора (раздел 3) и CONTEXT.md согласованы тем же
    коммитом: уточнение внесено как расхождение, найденное при исполнении.
- Проверка:
  - make test (248 тестов), make lint, make config-test;
  - make docs, затем git diff --exit-code docs/ — пусто.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 23:01:04 +03:00
ddadminandClaude Opus 5 7df5e482b9 docs(specs): правки по холодному ревью — долг словаря и потерянные доводы
- Зачем:
  - холодное ревью (Fable, свежая сессия) нашло невыполненный хвост
    тикета #32 и места, где доводы резолюций сжались до непонятности.
- Что:
  - мастер-спека 1.1: «склад» заменён на «хранилище» (хвост #32);
    CONTEXT.md: DWH в избегаемых, отдельная статья «Пакетный режим».
  - спека: восстановлены доводы «на маке и в WSL тоже» и «менти упрётся
    в красный чек манифеста»; обещания про diff привязаны к манифесту;
    темп ×60 и расчёт порога согласованы с числами разделов; заголовок
    притока честен про затухание; выход за мандат оговорён в «Зачем».
  - раздел 9: добавлены числа притока и календарная дата-константа D0;
    заметка исследования: у Faker единицы «значений/с», не «строк/с».
- Проверка:
  - вычитка; решения развилок не пересматриваются, правки текстовые.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 21:00:18 +03:00
ddadminandClaude Opus 5 8c69397ccf docs(specs): приток посетителей и фейкеры без гвоздя — вычитка владельца
- Зачем:
  - вычитка спеки на приёмке нашла дыру: состав мира читался как
    замкнутая труппа без новых посетителей — неправдоподобный магазин.
- Что:
  - раздел 1: состав не замкнут — план задаёт календарь появления кук,
    доля одноразовых высока; приток — часть плана, не мутация.
  - раздел 6: «Faker» ослаблен до «посточные фейкеры (Faker, mimesis)»,
    выбор библиотеки — этапу 2; там же оговорка про таблицы-литералы.
  - раздел 9: к интерфейсу запуска добавлены вопросы «кто зовёт
    генератор (даги world_init/next_day)» и «в каком контейнере живёт».
  - CONTEXT.md: в «Состав мира» добавлен календарь появления.
- Проверка:
  - вычитка; правки точечные, решения развилок не пересматриваются.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 20:49:49 +03:00
ddadminandClaude Opus 5 f85626508f docs(specs): собрана спека генератора из решений развилок карты #26
- Зачем:
  - этап 2 нельзя нарезать на тикеты без единой картины генератора,
    а решения четырёх развилок карты #26 жили только в тикетах трекера.
- Что:
  - новая спека docs/specs/2026-08-01-generator.md: функциональный мир,
    детерминизм до байта (SeedSequence сверен через Context7), контракт
    схемы, канонический сериализатор, числа и порог производительности;
    отклонённые варианты записаны с доводами.
  - мастер-спека согласована тем же коммитом: 1.4 — data contract вместо
    автогенерации DDL, 8 — в git только манифест, 11 — числа вместо
    «зафиксировать требования»; мелкие согласования в 7 и 9.
  - CONTEXT.md пополнен терминами модели мира и вывода генератора.
- Проверка:
  - вычитка; относительные ссылки спек указывают на существующие файлы
    в docs/specs/ и docs/research/.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 19:47:29 +03:00