Тикет #50 закрыт руками, его работа входит в эту же ветку.
Что вошло
Торговые события (#40). Событие корзины садится на карточку товара,
покупка — на страницу подтверждения. Деньги считаются целыми копейками, в productPrice ложатся целые рубли, а точная сумма живёт в purchaseRevenue — из-за этого сумма по разобранным массивам честно
расходится с выручкой, и урок про Float64 перестаёт быть выдуманным. Номер
заказа ГГГГММДД-NNNN присваивается всякой покупке, дошедшей до потока дня.
Сырой ecommerce несёт больше плоских колонок: бренд, вариант, actionField.
Корзина и уровень спроса (#50). Приёмка #40 показала два равенства,
каких в живом магазине не бывает: событие корзины случалось ровно у визитов
со страницей /cart, а внутри такого визита в корзину уходили все открытые
карточки. Теперь класть может любой визит, открывший карточку — 41,4% таких
визитов корзину не открывают вовсе; у визита, дошедшего до /cart, корзина
по-прежнему непуста. У товара появился уровень спроса: колонка каталога с
тремя значениями и два ряда вероятностей в числах мира. Конверсия
«просмотр карточки → корзина» стала различима — 13,1% / 9,2% / 5,8% по
уровням, по отдельным товарам от 15,4% до 5,1%.
Числа мира после правки (14 дней канонического зерна)
Дневная аудитория 6637–7595, визитов 9879, средний день 49 834 события,
конверсия визита в покупку 2,43%, конверсия карточки в корзину 8,62%,
позиций на заказ 1,74, однопозиционных заказов 56,4%, брошено 7,25% позиций
в покупающих корзинах.
Как проверялось
make lint && make typecheck && make test из корня репозитория — 394
passed (было 297 до ветки).
Трафиковая половина побайтово не сдвинулась: sha256 по (URL, времени, WatchID) всех просмотров за 14 дней совпадает со снимком до правки.
Обе задачи прошли конвейер целиком: ревью постановки, реализация, саморевью,
два слепых ревью разными родословными, триаж у исполнителя, узкие
перепроверки теми же ревьюерами и приёмка своими глазами. По #40 — 9 находок,
9 закрыто; по #50 — 9 находок, 9 закрыто, ноль отклонённых.
Что решено по ходу и записано в спеку
Решения обеих задач лежат в docs/specs/2026-08-01-generator.md, раздел 9 —
блоки «Решено при исполнении #40», «#40 после приёмки» и «#50». Там же
записаны отклонённые варианты и решение владельца о том, что вилка конверсии
в корзину — ориентир, а не граница: настоящий предел здесь дневной бюджет
событий, на котором стоят манифест (#42) и порог скорости дня.
Хвост соседям: словарь ClickHouse над products.csv (#37/#43) должен взять
новую колонку сразу, а манифесту (#42) нужен хеш каталога — в файле теперь
живёт не только форма данных, но и поведение.
Торговая половина генератора: события корзины и покупки, а следом — правка
двух точных равенств, которые нашла приёмка.
Closes #40
Тикет #50 закрыт руками, его работа входит в эту же ветку.
## Что вошло
**Торговые события (#40).** Событие корзины садится на карточку товара,
покупка — на страницу подтверждения. Деньги считаются целыми копейками, в
`productPrice` ложатся целые рубли, а точная сумма живёт в
`purchaseRevenue` — из-за этого сумма по разобранным массивам честно
расходится с выручкой, и урок про Float64 перестаёт быть выдуманным. Номер
заказа `ГГГГММДД-NNNN` присваивается всякой покупке, дошедшей до потока дня.
Сырой `ecommerce` несёт больше плоских колонок: бренд, вариант,
`actionField`.
**Корзина и уровень спроса (#50).** Приёмка #40 показала два равенства,
каких в живом магазине не бывает: событие корзины случалось ровно у визитов
со страницей `/cart`, а внутри такого визита в корзину уходили все открытые
карточки. Теперь класть может любой визит, открывший карточку — 41,4% таких
визитов корзину не открывают вовсе; у визита, дошедшего до `/cart`, корзина
по-прежнему непуста. У товара появился уровень спроса: колонка каталога с
тремя значениями и два ряда вероятностей в числах мира. Конверсия
«просмотр карточки → корзина» стала различима — 13,1% / 9,2% / 5,8% по
уровням, по отдельным товарам от 15,4% до 5,1%.
## Числа мира после правки (14 дней канонического зерна)
Дневная аудитория 6637–7595, визитов 9879, средний день 49 834 события,
конверсия визита в покупку 2,43%, конверсия карточки в корзину 8,62%,
позиций на заказ 1,74, однопозиционных заказов 56,4%, брошено 7,25% позиций
в покупающих корзинах.
## Как проверялось
`make lint && make typecheck && make test` из корня репозитория — **394
passed** (было 297 до ветки).
Трафиковая половина побайтово не сдвинулась: sha256 по (URL, времени,
`WatchID`) всех просмотров за 14 дней совпадает со снимком до правки.
Обе задачи прошли конвейер целиком: ревью постановки, реализация, саморевью,
два слепых ревью разными родословными, триаж у исполнителя, узкие
перепроверки теми же ревьюерами и приёмка своими глазами. По #40 — 9 находок,
9 закрыто; по #50 — 9 находок, 9 закрыто, ноль отклонённых.
## Что решено по ходу и записано в спеку
Решения обеих задач лежат в `docs/specs/2026-08-01-generator.md`, раздел 9 —
блоки «Решено при исполнении #40», «#40 после приёмки» и «#50». Там же
записаны отклонённые варианты и решение владельца о том, что вилка конверсии
в корзину — ориентир, а не граница: настоящий предел здесь дневной бюджет
событий, на котором стоят манифест (#42) и порог скорости дня.
Хвост соседям: словарь ClickHouse над `products.csv` (#37/#43) должен взять
новую колонку сразу, а манифесту (#42) нужен хеш каталога — в файле теперь
живёт не только форма данных, но и поведение.
- Зачем:
- перед реализацией торговых событий грилинг закрыл шесть развилок; без
записи решения и отклонённые варианты потерялись бы, а часть из них
выходит за границы тикета и меняет постановку.
- Что:
- в раздел 9 спеки генератора добавлен блок «Решено при исполнении #40»:
корзина шире заказа, метка покупателя становится значимой, место
торговых событий, номер заказа, промокод, единицы денег, разная длина
массивов purchase* и product*, orjson, хвост покупки у границы суток.
- в раздел 8 добавлены хвосты этапам 3 и 4: скидка по промокоду и
намеренное расхождение сумм.
- в словарь добавлены «покупатель» и «торговое событие».
- Проверка:
- чтением: docs/specs/2026-08-01-generator.md, разделы 8 и 9; CONTEXT.md.
- Зачем:
- холодное ревью нашло две дыры уровня решений: лифт конверсии не делает
покупателя видимым в данных, а цены каталога кратны рублю — от этого
урок про 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.
- Зачем:
- холодное ревью отметило, что это решение, а не калибровка: от выбора
шага зависит, как «покупатель» читается в данных, и оставлять выбор
реализации нельзя.
- Что:
- в блоке решений #40 записано, что помеченный отличается на обоих шагах
воронки — и до корзины доходит чаще, и бросает её реже; числа под
каждый шаг остаются калибровкой.
- Проверка:
- чтением: docs/specs/2026-08-01-generator.md, раздел 9, блок #40.
- Зачем:
- клиентская сторона мира становится целой: без 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>
- Зачем:
- приёмка #40 нашла в торговых данных два точных равенства, каких в живом
магазине не бывает: событие корзины возникало ровно у визитов со
страницей /cart, а внутри такого визита в корзину ложились все открытые
карточки.
- Что:
- в спеку генератора, раздел 9, добавлен блок «Решено при исполнении #40
после приёмки»: корзина отвязана от страницы корзины, уровень спроса
становится свойством товара, границы правки — вилки раздела 5.
- записаны отклонённые варианты: свой процент у каждого sku и вывод
склонности из цены.
- в CONTEXT.md заведён термин «уровень спроса».
- Проверка:
- git show --stat; текст решений читается без обращения к переписке.
- Зачем:
- блок «Решено при исполнении #40 после приёмки» цитировал замер на зерне 0,
а канонический мир, на котором стоят все тесты, — CANONICAL_SEED
(20260601); числа относились к другому миру.
- Что:
- замер перемерен на каноническом зерне за 14 дней: тождество «событие
корзины ↔ страница /cart» держится каждый день, на дне 2 это 828 и 828.
- уточнены средний день (49 509 событий), конверсия визита (2,43%), состав
заказа (1,87 позиции) и доля брошенных позиций (число мира 15%, замер по
покупающим корзинам 12%).
- Проверка:
- скрипт замера на 14 днях CANONICAL_SEED; git show --stat.
- Зачем:
- приёмка #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 канонических дней совпадает со снимком до правки.
- Зачем:
- после #50 доля просмотров, доходящих до корзины, подошла к краю вилки
5–9%, и следующий исполнитель стал бы калибровать поведение под это
число. Владелец решил: пока доля правдоподобна, она ничего не сторожит —
у живых магазинов она гуляет широко.
- Что:
- в блок «Решено при исполнении #50» добавлено решение владельца: вилка —
ориентир; настоящий предел здесь дневной бюджет событий, на котором
стоят манифест (#42) и порог скорости дня.
- Проверка:
- git show --stat; следующий исполнитель читает решение, не переспрашивая.
ddmitry
merged commit a18e6b7a80 into main2026-08-02 22:59:28 +03:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Торговая половина генератора: события корзины и покупки, а следом — правка
двух точных равенств, которые нашла приёмка.
Closes #40
Тикет #50 закрыт руками, его работа входит в эту же ветку.
Что вошло
Торговые события (#40). Событие корзины садится на карточку товара,
покупка — на страницу подтверждения. Деньги считаются целыми копейками, в
productPriceложатся целые рубли, а точная сумма живёт вpurchaseRevenue— из-за этого сумма по разобранным массивам честнорасходится с выручкой, и урок про Float64 перестаёт быть выдуманным. Номер
заказа
ГГГГММДД-NNNNприсваивается всякой покупке, дошедшей до потока дня.Сырой
ecommerceнесёт больше плоских колонок: бренд, вариант,actionField.Корзина и уровень спроса (#50). Приёмка #40 показала два равенства,
каких в живом магазине не бывает: событие корзины случалось ровно у визитов
со страницей
/cart, а внутри такого визита в корзину уходили все открытыекарточки. Теперь класть может любой визит, открывший карточку — 41,4% таких
визитов корзину не открывают вовсе; у визита, дошедшего до
/cart, корзинапо-прежнему непуста. У товара появился уровень спроса: колонка каталога с
тремя значениями и два ряда вероятностей в числах мира. Конверсия
«просмотр карточки → корзина» стала различима — 13,1% / 9,2% / 5,8% по
уровням, по отдельным товарам от 15,4% до 5,1%.
Числа мира после правки (14 дней канонического зерна)
Дневная аудитория 6637–7595, визитов 9879, средний день 49 834 события,
конверсия визита в покупку 2,43%, конверсия карточки в корзину 8,62%,
позиций на заказ 1,74, однопозиционных заказов 56,4%, брошено 7,25% позиций
в покупающих корзинах.
Как проверялось
make lint && make typecheck && make testиз корня репозитория — 394passed (было 297 до ветки).
Трафиковая половина побайтово не сдвинулась: sha256 по (URL, времени,
WatchID) всех просмотров за 14 дней совпадает со снимком до правки.Обе задачи прошли конвейер целиком: ревью постановки, реализация, саморевью,
два слепых ревью разными родословными, триаж у исполнителя, узкие
перепроверки теми же ревьюерами и приёмка своими глазами. По #40 — 9 находок,
9 закрыто; по #50 — 9 находок, 9 закрыто, ноль отклонённых.
Что решено по ходу и записано в спеку
Решения обеих задач лежат в
docs/specs/2026-08-01-generator.md, раздел 9 —блоки «Решено при исполнении #40», «#40 после приёмки» и «#50». Там же
записаны отклонённые варианты и решение владельца о том, что вилка конверсии
в корзину — ориентир, а не граница: настоящий предел здесь дневной бюджет
событий, на котором стоят манифест (#42) и порог скорости дня.
Хвост соседям: словарь ClickHouse над
products.csv(#37/#43) должен взятьновую колонку сразу, а манифесту (#42) нужен хеш каталога — в файле теперь
живёт не только форма данных, но и поведение.
- Зачем: - перед реализацией торговых событий грилинг закрыл шесть развилок; без записи решения и отклонённые варианты потерялись бы, а часть из них выходит за границы тикета и меняет постановку. - Что: - в раздел 9 спеки генератора добавлен блок «Решено при исполнении #40»: корзина шире заказа, метка покупателя становится значимой, место торговых событий, номер заказа, промокод, единицы денег, разная длина массивов purchase* и product*, orjson, хвост покупки у границы суток. - в раздел 8 добавлены хвосты этапам 3 и 4: скидка по промокоду и намеренное расхождение сумм. - в словарь добавлены «покупатель» и «торговое событие». - Проверка: - чтением: docs/specs/2026-08-01-generator.md, разделы 8 и 9; CONTEXT.md.- Зачем: - холодное ревью нашло две дыры уровня решений: лифт конверсии не делает покупателя видимым в данных, а цены каталога кратны рублю — от этого урок про 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.- Зачем: - холодное ревью отметило, что это решение, а не калибровка: от выбора шага зависит, как «покупатель» читается в данных, и оставлять выбор реализации нельзя. - Что: - в блоке решений #40 записано, что помеченный отличается на обоих шагах воронки — и до корзины доходит чаще, и бросает её реже; числа под каждый шаг остаются калибровкой. - Проверка: - чтением: docs/specs/2026-08-01-generator.md, раздел 9, блок #40.- Зачем: - клиентская сторона мира становится целой: без 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>