WB Localization 2.0

Автономный сервис, который сам перекладывает товар между складами Wildberries
Паспорт сервиса · версия 2 · 28 мая 2026

Что это. Сервис, который каждый день сам решает «какой товар куда переставить» внутри складов Wildberries, отправляет задачи в кабинет WBcon и следит за их выполнением. CEO не одобряет задачи поштучно — только настраивает защитные правила и смотрит отчёт.

Единственная цель. Поднять индекс локализации с текущих 67% до 90%+. Чем выше локализация — тем дешевле логистика WB, выше выкуп, быстрее доставка.

Где живёт. Сервер timeweb (cron + Python). Данные — в нашей Supabase. Кабинет — в WBcon. Сводки — в Telegram @wookiee_alerts_bot.

01Что делает сервис 02Откуда берёт данные 03Главная метрика — индекс локализации 04Дневной цикл — 6 этапов 05Алгоритм — как выбираем что переставить 06Воронка кандидатов — общая логика 07База данных — что копится и как смотреть 08Склады WB + защитные правила 09Telegram-сообщения 10Расписание cron (МСК) 11Известные проблемы 12Дорожная карта 13Интерфейс в Hub — главное меню 14Интерфейс — экран за экраном

01 · Что делает сервис

Проблема, которую решаем. У Wookiee 920+ артикулов лежат на 23 рабочих складах WB по всей России. Когда покупатель из Новосибирска заказывает товар, который физически лежит в Коледино — WB везёт его 5 дней через всю страну и берёт с нас за это повышенный коэффициент тарифа (КТР) и сниженный коэффициент региональной приоритезации (КРП). Покупатель ждёт долго → выкуп падает. Карточка не попадает в ТОП регионального поиска → продаж меньше.

Что делает сервис. Каждый день автоматически считает: «вот этот товар лучше переставить из Коледино в Новосибирск, потому что там его всё равно покупают». Отправляет такие задачи в WBcon. Следит, чтобы за неделю индекс локализации (доля заказов с ближайшего склада) рос.

Из каких четырёх блоков состоит сервис

📥
Сбор данных
Читает остатки, заказы, активные задачи WBcon, квоты направлений. Складывает снимки в Supabase.
🧠
Алгоритм
Считает кандидатов на перестановку. Скорит каждого по формуле: «выполнимость × деньги × приоритет».
🚚
Постановка
Удаляет устаревшие задачи, отправляет новые в WBcon. Аудирует каждый ответ. Окно: 09:00 МСК.
📊
Контроль
4 раза в день проверяет «что выполнено, что отменено». Шлёт сводки в Telegram. Алерт если cron упал.

Как они связаны

flowchart LR DATA["📥 Сбор данных
каждый цикл"] --> ALGO["🧠 Алгоритм
ранжирует кандидатов"] ALGO --> POST["🚚 Постановка
POST/DELETE в WBcon"] POST --> CTRL["📊 Контроль
трекер + отчёт"] CTRL -.обратная связь.-> ALGO style DATA fill:#eaf2fa,stroke:#1e4d7a style ALGO fill:#e8f0eb,stroke:#2a4d3a style POST fill:#fdf2e6,stroke:#b54708 style CTRL fill:#eaf2fa,stroke:#1e4d7a

Контроль возвращает данные в алгоритм: какие пары (склад A → склад B) выполняются успешно, какие WB отклоняет, какие зависают. Это та самая «калибровка по факту», которая будет в Sub-project B.

02 · Откуда сервис берёт данные

Сервис общается с тремя внешними системами. Понимать кто кому хозяин — критично, иначе непонятно почему мы не можем просто «прийти и взять».

flowchart LR WB[("🟣 Wildberries
(сам маркетплейс)")] PARTNER[("🟠 Подрядчик
Wildberries DB
89.23.119.253:6433")] SVC["🟢 Наш сервис
WB Localization 2.0
на timeweb")] SUPA[("💾 Наша Supabase
17 таблиц wb2_/wbcon_")] WBCON["🟡 WBcon API
наш кабинет для
перестановок"] WB --"раз в день ETL"--> PARTNER PARTNER --"только чтение
остатки, заказы"--> SVC SVC <--"снимки + аудит"--> SUPA SVC <==>|"чтение + запись
POST/DELETE задач"| WBCON WBCON -.задачи на номер.- WB style WB fill:#f0e8f5,stroke:#6b3a8c style PARTNER fill:#fdf2e6,stroke:#b54708 style SVC fill:#e8f0eb,stroke:#2a4d3a,stroke-width:3px style SUPA fill:#eaf2fa,stroke:#1e4d7a style WBCON fill:#fff5d6,stroke:#b58c08

Кто здесь кто

СистемаЧьяЧто оттуда нужноМожем ли писать?
Wildberries (сам маркетплейс) WB Источник всех данных. WB не отдаёт нам данные напрямую — только через свой API (медленный и ограниченный). Только через стандартный API селлера. Перестановки — отдельно через WBcon.
Wildberries DB (89.23.119.253) Сторонний подрядчик Готовая агрегированная база: остатки по складам, заказы, движения, история. Подрядчик сам ETL-ит данные из WB и держит свою копию. ТОЛЬКО ЧТЕНИЕ Подрядчик нам не разрешает писать.
WBcon (сторонний сервис) Сторонний сервис, наш кабинет Это система, через которую WB разрешает делать перестановки. Звонит на телефон при создании задачи. У нас 2 номера-кабинета: ООО ВУКИ + ИП Медведева. ЧТЕНИЕ + ЗАПИСЬ Поставить новую задачу, удалить старую, посмотреть статус.
Supabase (наша) Наша Наш «мозг» — здесь хранятся снимки WBcon, итоги расчётов алгоритма, аудит всех POSTов, история индекса. ЧТЕНИЕ + ЗАПИСЬ Полный контроль.

Почему нельзя «просто взять у WB напрямую»

03 · Главная метрика — индекс локализации

Что это. Доля заказов, которые ушли с ближайшего к покупателю склада. Если покупатель из Новосибирска купил товар, который физически лежал в Новосибирске — это +1 к локализации. Если приехал с Коледино — 0.

Зачем поднимать.

Как сейчас. Колеблется около 67% последнюю неделю. Цель — 90%+. Каждая точка процента индекса = сотни тысяч рублей в месяц (точная цифра — задача Sub-project C).

ДатаИндексSKU в выборкеЧто произошло
22 мая67.11%275Расширенная выборка
23 мая67.28%201Перешли на core-выборку
26 мая67.22%201Первый live-батч 483 POST (вручную)
27 мая67.19%201
28 мая67.16%201Cron запущен · 164 POST автономно

Важно Колебание ±0.1 п.п. за неделю — это шум, не сигнал. Решения смотрим на горизонте 14–30 дней. Автопилот стартовал вчера.

04 · Дневной цикл — 6 этапов

Каждый день сервис проходит один и тот же цикл из 6 этапов. Все времена — по московскому времени.

flowchart LR E["🌙 22:00
построить план"] --> M["🌅 07:00
перепроверка"] --> P["🚚 09:00
POST в WBcon"] --> T["📈 12/15/18/21
трекер"] --> D["📊 21:30
отчёт"] L["⏰ каждый час
сторож"] style E fill:#e8f0eb,stroke:#2a4d3a style M fill:#e8f0eb,stroke:#2a4d3a style P fill:#fdf2e6,stroke:#b54708,stroke-width:3px style T fill:#eaf2fa,stroke:#1e4d7a style D fill:#eaf2fa,stroke:#1e4d7a style L fill:#f0ede5,stroke:#8a8a8a
🌙 22:00
Вечер — построить план
Подтягивает свежие данные из всех источников. Прогоняет алгоритм. Сохраняет 700–2500 кандидатов в БД, экспортирует план в Google Sheet, шлёт сводку в Telegram «План на завтра: N задач, X штук».
🌅 07:00
Утренняя перепроверка
За ночь могут поменяться остатки и квоты. Сервис снова собирает свежие данные и считает drift — процент кандидатов, которые перестали быть валидными. Если < 20% — молчит. Если > 50% — URGENT «нужен ручной пересчёт».
🚚 09:00
Постановка в WBcon
Главное событие дня. Окно WBcon открывается ровно в 09:00. Сервис: 1) удаляет устаревшие задачи; 2) отправляет новые. Каждый ответ WBcon аудируется. В Telegram прилетает «Батч поставлен: N задач», сообщение потом обновляется трекером весь день.
📈 12/15/18/21
Трекер — следить за выполнением
4 раза в день ходит в WBcon и спрашивает «что с моими задачами». Редактирует то же Telegram-сообщение — прогресс растёт прямо в одной строчке: «выполнено 87/164, в очереди 65, отменено WB 8».
📊 21:30
Дайджест — отчёт за день
Если за день что-то странное (отказов больше 5%, технических ошибок больше 20%, drift в утренней проверке) — собирает в одно сообщение. Если день был спокойный — молчит.
⏰ каждый час
Сторож — heartbeat
Чистит зависшие блокировки. Проверяет «а сработали ли cron-этапы за последние 24 часа». Если evening или morning не отметились — URGENT «cron сломан».

05 · Алгоритм — как мы выбираем что переставить

Это сердце сервиса. Объясняю по шагам — как для человека, не как для разработчика.

Шаг 1 — перебрать все возможные перестановки

Для каждой пары (SKU + размер + склад-донор + склад-получатель) сервис задаёт вопрос: «может, стоит переставить?». На 920 артикулах × ~6 размерах × 23 склада × 23 склада это потенциально миллион пар. Большинство отсеивается сразу — нет товара на доноре, нет смысла везти на получателя, не хватает квоты направления.

После первичного отсева остаётся 700–2500 живых кандидатов в день (зависит от того, сколько SKU «съехало» с целевой локализации за сутки).

Шаг 2 — посчитать ранг каждого кандидата

Главная формула:

rank = feasibility × max(0, impact_рублей) × (1 + priority_bonus)

Три компонента:

🚦 feasibility 0..1

«Доедет ли задача?» Произведение четырёх вероятностей:

  • policy_mult — пара складов разрешена? (1.0 если auto, 0.5 если manual, 0 если blocked)
  • quota_stability — направление стабильное в истории?
  • quota_fit — наша задача помещается в дневную квоту WB?
  • success_rate — историческая успешность пары (по умолчанию 0.85, пока wb2_pair_outcomes не накопил)
💰 impact рубли в месяц

«Сколько мы заработаем/сэкономим, если этот SKU переедет?» Считается так:

  • Берём current_loc (где сейчас процент локализации этого SKU)
  • Считаем projected_loc (где будет, если переставим планируемое qty)
  • Смотрим, как изменятся КТР и КРП WB на этих процентах
  • Множим на месячные заказы → получаем экономию логистики + рост выручки от КРП в рублях
🎯 priority bonus множитель

«Насколько срочно тащить именно этот SKU вверх?» Плавный приоритет (без жёстких порогов):

  • Ниже 60% локализации — сильный бонус (×10)
  • 60–90% — слабый бонус (×1)
  • Выше 90% — ноль (уже достигли цели, не приоритет)

Пример: SKU на 42% → bonus 2.28. На 88% → 0.02.

Шаг 3 — разложить кандидатов по дорожкам (lanes A–F)

Это вторая защитная сетка: даже отранжированных кандидатов алгоритм разделяет по «дорожкам» в зависимости от текущей локализации SKU и приоритетности направления WB:

ДорожкаУсловиеЧто значит
ASKU <60% локализация + направление tier=highСамое приоритетное — критично низкая локализация на горячем направлении
BSKU 60–75% + tier=highПодтянуть «середняка» на горячем направлении
CSKU <60% + tier=mediumНизкая локализация на среднем направлении (~90% сегодняшних кандидатов сюда)
DSKU 75–90% + tier=highДотянуть «хорошо» до «отлично» на горячем направлении
ESKU 60–75% + tier=mediumСредний приоритет
FЗаблокирован / низкое направление / уже >90%Не предлагаем

Шаг 4 — финальная сортировка

В POST идут отсортированные по: (1) Новосибирск в конец (там высокая конкуренция за квоту, не блокируем остальные направления), (2) по убыванию rank-score. Топ-N (сейчас 500) реально отправляется в WBcon.

Что меняет CEO, а что — алгоритм сам

ЧтоГде лежитКто меняет
Веса формулы (0.30 локализация, 0.20 выручка, …)Код scoring.pyБудущий Sub-project B — автокалибровка
Пороги lanes (60%, 75%, 90%)Код planner.pySub-project B
Список заблокированных складовБД wbcon_constraintsCEO — UPDATE в БД
Cooldown 72чБД wbcon_constraintsCEO
Дневные лимиты (per-SKU 400, total 5000)Код sync.pyCEO через обсуждение → правит код
candidate_limit=500Код sync.pyCEO — защитная заглушка первого дня

06 · Воронка кандидатов — общая логика

Каждый день одна и та же воронка из 6 ступеней. Цифры в иллюстрации — типичные, в реальности зависят от дня (плюс-минус 30%).

flowchart TB A["🧮 ~миллион потенциальных пар
SKU × размер × склад-донор × склад-получатель"] A -->|"нет товара / нет смысла
нет квоты направления"| B["🎯 ~700–2 500 живых кандидатов
(алгоритм построил)"] B -->|"scoring по формуле
отсев lane F (заблокированные)"| C["📊 ~500–2 000 после фильтра
дорожки A–E"] C -->|"candidate_limit = 500
(защитная заглушка)"| D["🚦 топ-500 идут в POST stage"] D -->|"per-SKU 400 шт / day
total 5 000 шт / day"| E["⚡ 400–500 попыток POST"] E -->|"chrt_id resolve
(БД → кэш → live)"| F["✅ N задач уходит в WBcon"] E -.->|"не нашли chrt_id"| G["⚠️ остальные в очередь
(кэш растёт со временем)"] style A fill:#f0e8f5,stroke:#6b3a8c style B fill:#eaf2fa,stroke:#1e4d7a style C fill:#e8f0eb,stroke:#2a4d3a style D fill:#fdf2e6,stroke:#b54708 style E fill:#fdf2e6,stroke:#b54708 style F fill:#e8f0eb,stroke:#2a4d3a,stroke-width:3px style G fill:#fdf2e6,stroke:#b54708

Что отсеивается на каждом шаге

#СтупеньЧто отсевается и почему
1Построение пар Алгоритм не рассматривает пары: где на доноре нет товара, где донор и получатель совпадают, где у получателя уже хороший остаток, где направление закрыто WB.
2Scoring + lane F Кандидаты с заблокированными парами (politicy=blocked / direction_tier=low) уходят в lane F и не доходят до POST.
3candidate_limit=500 Жёсткая константа в sync.py:177. «Защитная заглушка первого дня». Берёт топ-500 по rank. Когда автопилот докажет стабильность — поднимем до 1500–2000.
4Дневные лимиты Не больше 400 шт одной модели в день (через все пары складов). Не больше 5000 шт всего. Лишнее переносится «на завтра» (но завтра алгоритм пересчитывает с нуля — это просто верхний потолок).
5chrt_id resolve Чтобы POST в WBcon прошёл, нужен chrt_id (внутренний ID размера в WBcon). 3 источника: колонка в БД (пока NULL), live-запрос в WBcon stocks (rate-limited), исторический кэш из wb2_task_outcomes (растёт сам). Сегодня покрытие ~35%, через 2 недели должно быть 70–90%.
6POST в WBcon Что осталось — реально летит в кабинет. Каждый запрос аудируется в wb2_task_outcomes: что отправили, что ответ, в какое время. Дальше задачу подхватывает WB и кладёт на исполнение склада.

07 · База данных — что копится и как смотреть

17 таблиц в Supabase. Делятся на 4 функциональные группы. Для каждой ключевой таблицы — что лежит, какие колонки, пример строки, какие срезы можно делать.

Группа A — снимки WBcon (что лежит в нашем кабинете)

ТаблицаЧто хранитСтрок
wbcon_warehousesСправочник 29 складов WB с их WBcon-ID29
wbcon_task_snapshotsАктивные задачи WBcon — снимок на каждый цикл~2 500
wbcon_in_transit_snapshotsТовар «в пути» по парам складов~700
wbcon_quota_snapshotsКвоты направлений WBcon (сколько примет каждый склад)~200
wbcon_direction_snapshotsСнимки разрешённых направлений~1 500
wbcon_constraintsЗащитные правила (см. §08)12

Главная — wbcon_task_snapshots

Активные задачи WBcon. Колонки:

external_task_id  — ID задачи в WBcon (например, 845)
normalized_status — нормализованный статус (active / in_transit / no_response)
nm_id, chrt_id    — что за товар и размер
size_name         — название размера ("S", "M")
src_id, dst_id    — ID складов донора и получателя
src_name, dst_name — их названия
qty               — сколько штук просим переставить
first_seen_at, last_seen_at  — когда впервые увидели в WBcon и когда последний раз

Срезы которые можно делать:

Главная — wbcon_in_transit_snapshots

Товар, который уже отправили, но ещё не доехал. Алгоритм использует это в формуле эффективного остатка (см. §05). Без этой таблицы он бы предлагал переставить одно и то же снова и снова.

Группа B — расчёты алгоритма (мозги сервиса)

ТаблицаЧто хранитСтрок
wb2_runs1 строка = 1 прогон алгоритма. Дата, статус, итоги в JSON.~10–15 в день
wb2_candidate_movesКаждый кандидат на перестановку с полной диагностикой scoring5 000+
wb2_rule_setsНастройки алгоритма (cadence, thresholds)2 (1 active)

Самая важная таблица сервиса — wb2_candidate_moves

Здесь лежат ВСЕ кандидаты которые алгоритм когда-либо рассматривал — и принятые, и отброшенные. Это и есть «черный ящик» алгоритма наружу. Колонки:

id                    — уникальный ID кандидата
run_id                — к какому прогону относится (FK на wb2_runs)
candidate_key         — уникальный ключ (cabinet|article|size|src|dst)
article, nm_id, chrt_id, size_name  — что за товар
src_warehouse_name, dst_warehouse_name — пара складов
lane                  — A/B/C/D/E/F (см. §05)
rank_score            — итоговый ранг (feasibility × impact × priority)
expected_success_probability  — вероятность что доедет
expected_localization_gain    — на сколько вырастет локализация SKU (рубли/месяц)
score_features_json   — ПОЛНАЯ диагностика scoring (см. ниже)
decision              — selected / rejected / backlog / cooldown
planned_qty           — сколько штук планируем переставить
decision_reason       — почему такое решение
created_at            — когда посчитан

Внутри score_features_json лежит scoring_diag — расшифровка каждого числа:

{
  "impact": {
    "price": 2122.12,            // цена единицы
    "current_loc": 48.9,         // текущая локализация SKU
    "projected_loc": 50.4,       // прогнозируемая после перестановки
    "monthly_orders": 45.2,      // сколько заказов в месяц
    "ktr_now": 1.2, "ktr_new": 1.1,
    "krp_now": 2.05, "krp_new": 2.05,
    "impact_ktr_rub": 361.0,     // экономия логистики, ₽/мес
    "impact_krp_rub": 0.0        // дополнительная выручка от КРП, ₽/мес
  },
  "feasibility": {
    "policy_mult": 1.0,          // разрешено
    "quota_fit": 1.0,            // помещаемся
    "success_rate": 0.85,        // историческая
    "pair_history": [0, 0]       // [успехов, попыток] — пока пусто
  },
  "priority": {
    "projected_loc_pct": 100.0,
    "bonus_primary": 0.0,
    "bonus_secondary": 0.0
  }
}

Срезы которые можно делать:

Группа C — аудит и история (что реально произошло)

ТаблицаЧто хранитСтрок
wb2_task_outcomesАудит каждой операции POST/DELETE с полным request/response1 200+
wb2_run_logHeartbeat + DB-lock каждого cron-этапа~10/день
wb2_localization_historyДневной снимок индекса локализации по каждому SKU+201/день

Главная — wb2_task_outcomes

Каждая операция (POST новой задачи, DELETE устаревшей) пишет сюда строку. Это наш чёрный ящик — если что-то пошло не так, ищем здесь.

id                       — уникальный
cabinet_code             — 'ooo' или 'ip'
external_task_id         — ID задачи в WBcon (для POST=success)
candidate_move_id        — FK на wb2_candidate_moves (откуда брали)
submitted_at, resolved_at — времена постановки и завершения
resolution               — 'success' / 'unknown' / 'cancelled'
sku_loc_pct_before, sku_loc_pct_after — локализация SKU до/после
metadata_json            — request, response, error в JSON

В metadata_json — полная история: что отправили, что получили, какая ошибка. Это и есть тот неявный кэш chrt_id — sync.py при следующих POSTах смотрит сюда «а постили ли мы такой SKU раньше».

Срезы:

История индекса — wb2_localization_history

+201 строка в день (по SKU из core-выборки). Поля:

snapshot_date  — дата
cabinet_code   — ooo / ip
nm_id          — SKU
loc_pct        — индекс локализации в этот день
orders_period  — заказы за расчётный период (для веса)

Это и есть та таблица, на которой будут все графики «индекс растёт?». Из неё считается средневзвешенный индекс по кабинету. И именно здесь Sub-project C будет искать каузальную связь «наши действия → рост».

08 · Склады WB + защитные правила

29 складов

Все живут в wbcon_warehouses. Разбиты по регионам (региональная группировка — для понимания, в БД её пока нет):

Центральные
Коледино · Подольск · Тула · Электросталь · Белые Столбы · Рязань · Котовск · Сарапул
Юг
Краснодар (Тихорецкая) · Невинномысск · Волгоград
Восток
Казань · Новосемейкино · Самара · Пенза · Екатеринбург · Новосибирск
Северо-Запад
СПБ Шушары · Владимир Воршинское

Двойники : Питание — отдельный режим WB, в перестановках не используется (заблокирован в защитных правилах).

12 защитных правил в wbcon_constraints

«Не навреди» — главный принцип. Правила версионируются (effective_from / effective_to), менять = политическое решение, не эксперимент алгоритма.

ПравилоЗначениеНа человеческом
blocked_to_warehouses Коледино, Подольск, СПБ Шушары, Шушары, Казань, Питание Перегружены — никогда не отправляем сюда товар, даже если по математике выгодно
blocked_from_warehouses Екатеринбург, Владимир, Новосемейкино, Самара, Пенза, Подольск С этих складов забирать через автомат нельзя — пойдут на ручной разбор
high_competition_warehouses Новосибирск, Екатеринбург, СПБ, Казань Эти склады нарасхват — режем квоту, не лезем впереди других продавцов
cooldown_hours_72 72 часа Если вчера предложили пару (SKU + склад-донор) — следующие 3 суток повторно не предложим
no_response_reserve_hours_23 23 часа Задачи без ответа считаем «возможно едут» 23 часа после создания (потом списываем)
in_transit_confidence_0_9 0.9 Товар в пути считаем как 90% — 10% риск что не доедет (отмены, потери)
safe_rate_per_phone_per_second_3 3 req/s Безопасная скорость наших запросов к WBcon на номер
rate_limit_429_threshold_4_5 4.5 req/s Выше этого WBcon начнёт отдавать 429 (rate limit)
default_daily_capacity_units_300 300 шт Дневной потолок единиц для одного направления (когда квота направления неизвестна)
default_capture_factor_0_6 0.6 Можем занять до 60% квоты направления одной задачей — остальное оставляем другим

Настройки нашего алгоритма — wb2_rule_sets

Активный набор: phase-a-default. Это не правила WB, а наши тайминги:

{
  "cycle_evening_msk":              "22:00",     ← вечерний расчёт по МСК
  "cycle_morning_check_msk":        "07:00",     ← утренняя перепроверка
  "cycle_post_msk":                 "09:00",     ← окно WBcon открывается
  "cycle_tracker_msk":              ["12:00","15:00","18:00","21:00"],
  "cycle_digest_msk":               "21:30",     ← вечерний дайджест
  "morning_check_drift_threshold":   0.2,        ← молчим если < 20% drift
  "morning_check_replan_if_invalid_pct_gt": 0.5, ← URGENT если > 50%
  "digest_threshold_tech_fail_pct":  20,         ← порог tech-fail для дайджеста
  "digest_threshold_wb_reject_pct":  5,          ← порог отказов WB
  "duplicate_alert_window_hours":    24,         ← окно дедупа URGENT
  "lock_ttl_minutes":                60,         ← макс длительность DB-lock
  "hanging_task_ttl_days":           7           ← когда списать «зависшую» задачу
}

09 · Telegram-сообщения — на человеческом

Бот: @wookiee_alerts_bot (общий с другими сервисами Wookiee). 6 типов сообщений, переписаны на нормальный русский, без жаргона.

🌙 Вечером — план на завтра (22:00)

22:00 МСК · silent
📋 План перестановок на 29 мая Подготовил 782 задачи на 4 250 штук. В среднем у каждой 42% шанс что склад примет. Топ-5 по объёму: • Wendy чёрный, размер S — 50 шт • Лунный комплект белый, S — 42 шт • Alice чёрный, S — 36 шт • Carmen бежевый, M — 28 шт • Vivi красный, S — 22 шт Если ничего не случится — в 9 утра всё уйдёт в WBcon само.

🌅 Утром — короткая перепроверка (07:00)

07:00 МСК · silent (только если drift >20%)
🌅 Утренняя перепроверка За ночь поменялось 18% кандидатов из вечернего плана (остатки сместились, новые задачи WBcon). План остался валидным — иду на POST в 09:00 МСК без изменений.

🚚 В 09:00 — батч поставлен

09:0X МСК · silent · потом обновляется
🚚 Батч 29 мая ушёл в WBcon Поставлено: 164 задачи Не получилось: 302 (нет chrt_id, разберём вечером) Удалено устаревших: 124 Прогресс буду обновлять прямо в этом сообщении до 21:00.

📈 Трекер — обновляется в течение дня

15:00 МСК · edit того же сообщения
🚚 Батч 29 мая — обновлено 15:00 МСК ✅ Уже на складе: 87 задач (412 штук) 🚛 Ещё в пути: 65 задач (280 штук) ❌ WB отменил: 8 ⚠️ Технические сбои: 4 (разберу вечером) Следующее обновление в 18:00 МСК.

📊 Дайджест за день (21:30)

21:30 МСК · silent · только если есть аномалии
📊 Итоги дня 29 мая Что прошло хорошо: 152 задачи доехали, экономия логистики ~28 000 ₽. На что обратить внимание: • 12% задач упали с ошибкой сервера WBcon (502). Завтра попробуем те же пары — должно пройти. • 6% задач отклонил WB — превысили дневную квоту Краснодара. • Утренний drift 18% — норма. Завтрашний план посчитаю в 22:00 МСК как обычно.

🚨 URGENT — что-то сломалось

громкий · требует реакции
🚨 POST не получился 09:03 МСК пытался отправить батч 29 мая — WBcon ответил «503 Service Unavailable». Это сторона WBcon. Жду стабильности, повторю автоматически в 09:30. Если не получится — напишу снова.

10 · Расписание cron — всё по Москве

Файл /etc/cron.d/wb-loc-2 на сервере timeweb. TZ=Europe/Moscow в шапке файла.

Время МСКЭтапCron expression
22:00Вечер — построить план0 22 * * *
07:00Утренняя перепроверка0 7 * * *
09:00POST batch0 9 * * *
12:00, 15:00, 18:00, 21:00Трекер0 12,15,18,21 * * *
21:30Дайджест30 21 * * *
каждый час :30Сторож (cleanup + heartbeat)30 * * * *

Сейчас Запущен только кабинет ООО ВУКИ. Кабинет ИП Медведева — на паузе по решению CEO.

11 · Известные проблемы и обходные пути

1. WBcon rate-limit на /stocks

WBcon ужесточил лимит на эндпоинт остатков — пустые ответы при превышении 4 req/window.

Обход: исторический кэш chrt_id. Сегодня ~35% покрытия, растёт с каждым POST.

2. wb2_candidate_moves.chrt_id пустой

Колонка есть (миграция 013), но планировщик пока её не заполняет — резолюция на POST-этапе.

План: в evening-этапе подмешивать chrt_id из кэша.

3. candidate_limit=500 захардкожено

«Защитная заглушка» в sync.py. Сейчас режет ~282 кандидата из плана.

План: поднять до 1500–2000 после 2–3 успешных автономных циклов.

4. ИП-кабинет (Медведева) выключен

Cron работает только для ООО.

Когда включать: по решению CEO.

5. Drift монитор простой

Считает «процент невалидных» — без разбора по причинам.

План: разложить причины в Sub-project B.

6. Нет каузальной атрибуции

Не отвечаем на вопрос «индекс вырос благодаря нам или сам».

План: Sub-project C — отдельный движок атрибуции.

12 · Дорожная карта — Sub-projects B–E

flowchart LR A["✅ Phase A
Reliability
cron + alerts + audit"] --> B["Phase B
Pair statistics
+ автокалибровка"] B --> C["Phase C
Causal attribution
«мы или само?»"] C --> D["Phase D
LLM agents
weekly review +
CEO digest"] D --> E["Phase E
Auto-stop
когда остановиться?"] UI["Hub UI
экраны §13-14"] A -.parallel.-> UI style A fill:#e8f0eb,stroke:#2a4d3a,stroke-width:3px style UI fill:#fdf2e6,stroke:#b54708,stroke-width:2px
ФазаЧто добавляет
B · Pair statisticsТаблица wb2_pair_outcomes копит «сколько раз пара (склад A→B) завершалась успехом». Алгоритм начинает учитывать реальные success-rate, а не догадку 0.85.
C · Causal attributionРаскладывает прирост индекса по причинам: вклад наших действий vs алгоритм WB vs сезонность. Отвечает на главный вопрос «работает ли сервис».
D · LLM agentsЕженедельный обзор по pair_outcomes. Утренний дайджест CEO на человеческом языке («что произошло вчера, на что обратить внимание»).
E · Auto-stopЛогика «когда хватит». Если индекс на плато 14 дней — снижаем интенсивность. Если ROI падает — стоп.

13 · Интерфейс в Hub — главное меню

Сейчас всё что видит CEO — это Telegram-сообщения. Добавляем раздел в Wookiee Hub: hub.os.wookiee.shop/wb-localization.

Главное меню — новый пункт «WB Локализация»

В левой навигации Hub появляется новый раздел «WB Локализация» с 6 подпунктами:

hub.os.wookiee.shop / wb-localization
Wookiee Hub
WB Локализация
6 разделов · автопилот живой с 28 мая 2026

Выберите раздел в боковом меню или используйте быстрые ссылки ниже ↓

📊 Главная
Текущий индекс, статус автопилота, сегодняшний батч
🎯 Воронка
Что попало в план, что отсеялось и почему
📋 История
Все POST/DELETE с фильтрами
📈 Эффективность
Индекс по SKU и по складам, тренды

Дальше — описание каждого экрана и mockups.

14 · Интерфейс — экран за экраном

Это первая итерация. Будем дорабатывать. Каждый экран — отдельная подстраница раздела.

Экран 1 — Главная (📊 «Лента»)

/wb-localization/

Цель. Один экран, на который CEO смотрит раз в день и понимает: всё в порядке или нет. Если красная лампочка — куда кликнуть.

hub.os.wookiee.shop / wb-localization
Wookiee Hub
📊 Главная
обновлено 28 мая 2026, 18:42 МСК
Индекс локализации
67.16%
▾ −0.05 п.п. за 7 дн
Цель
90%
+22.8 п.п. до цели
Сегодня в WBcon
164
122 уже выполнено
Экономия логистики
~28k
оценка за сегодня
Индекс локализации — последние 30 дней
90% ───────────────────── цель
67%
Сегодняшний батч — лента выполнения
✅ Выполнено122
🚛 В пути30
❌ WB отменил8
⚠️ Сбой4

Следующее обновление трекером в 21:00 МСК

Дневной цикл — статус каждого этапа
22:00 ✓
🌙 Вечер: план готов
07:00 ✓
🌅 Утро: drift 18%
09:00 ✓
🚚 POST: 164 OK
18:00 ✓
📈 Трекер
21:30
📊 Дайджест

Какие данные используются

Экран 2 — Воронка и кандидаты (🎯)

/wb-localization/funnel

Цель. Понять «почему сегодня всего 164, а не 700». Кликнуть на любую ступень и увидеть список отсеянных кандидатов.

hub.os.wookiee.shop / wb-localization / funnel
Wookiee Hub
🎯 Воронка и кандидаты
прогон run 46 · 28 мая 13:36 МСК · кабинет ООО
Воронка дня — 6 ступеней
СтупеньКандидатовДоляДействие
🧮 Все возможные пары~миллион(не показывается)
🎯 Живые кандидаты782100%смотреть →
📊 После scoring (lane A–E)782100%по lanes →
🚦 candidate_limit=50050064%282 отсев →
⚡ После дневных лимитов46660%34 отсев →
🔑 С разрешённым chrt_id16421%302 ждут →
✅ Уехало в WBcon16421%по складам →
Распределение по lane (дорожкам приоритета)
A29
B16
C — ниже 60% локализации × средний регион704
D33
Топ-10 кандидатов сегодня (по rank-score)
Модель/размерОткуда → кудаШтLocRankLane
Wendy чёрный, SКоледино → Краснодар5042% → 67%2 450A
set_moon2 белый, SТула → Новосибирск2850% → 100%2 030C
Carmen бежевый, MЭлектросталь → Казань2848% → 73%1 880A
... ещё 7 строк ...

Какие данные используются

Экран 3 — История задач (📋)

/wb-localization/tasks

Цель. Полный лог всех POST/DELETE с фильтрами. Когда что-то висит — посмотреть. Когда склад жалуется на «задачу X» — найти.

hub.os.wookiee.shop / wb-localization / tasks
Wookiee Hub
📋 История задач WBcon
все POST и DELETE с момента запуска · 1 267 строк
📅 За 7 дней ▾
🏪 Все склады ▾
📦 Все модели ▾
🎯 Все статусы ▾
⬇ Скачать CSV
Всего POST
812
Выполнено
619
В пути
142
WB отказал
38
DELETE
455
ВремяЗадачаМодель/размерОткуда → кудаШтСтатус
28.05 14:52#845Wendy/black SКоледино → Краснодар50✅ выполнено
28.05 14:52#844set_moon2/white SТула → Новосибирск28🚛 в пути
28.05 14:52#843Carmen/beige MЭлектросталь → Казань28❌ WB отменил
28.05 14:51#842Alice/black SПодольск → СПБ36✅ выполнено
... показано 4 из 812 ...

Клик по строке → детали: full request/response, время WBcon-резолюции, ссылка на кандидата.

Какие данные используются

Экран 4 — Эффективность (📈)

/wb-localization/effectiveness

Цель. Главный вопрос «работает ли сервис». График индекса по дням, разбивка по складам и SKU, выявить узкие места.

hub.os.wookiee.shop / wb-localization / effectiveness
Wookiee Hub
📈 Эффективность сервиса
«работает ли это?» — 7 / 30 / 90 дней
Текущий индекс
67.16%
▾ −0.05 п.п. за 7 дн
За 30 дней
+0.7 п.п.
медленный рост
Действий сделано
812
за всё время
Экономия (оценка)
~140k₽
за месяц
Индекс по складам — топ 10
СкладИндексΔ 7д
Краснодар (Тих.)78%+1.2
Невинномысск74%+0.4
Новосибирск71%−0.3
Тула68%0
Коледино62%−0.8
Электросталь59%+0.2
Узкие SKU — нужна помощь
SKUИндексВ очереди
Gimelim plus, XL32%12
Wendy чёрный, XS38%8
Zella купальник, M41%14
Carmen бежевый, L44%6
set_moon белый, XL46%5
Индекс vs действия — 60 дней

Зелёная линия — индекс. Синие точки — дни с POST'ом.

2 апр
28 мая

⓵ В Phase C добавим разложение «причина роста: мы / WB / сезон»

Какие данные используются

Экран 5 — Защитные правила (🛡)

/wb-localization/rules

Цель. CEO видит и при необходимости меняет: список заблокированных складов, cooldown, дневные лимиты. История изменений.

hub.os.wookiee.shop / wb-localization / rules
Wookiee Hub
🛡 Защитные правила
12 правил активны · изменение требует подтверждения через Telegram
Склады — куда / откуда нельзя
ТипСписок складовДействует с
🚫 Куда не ставим Коледино, Подольск, СПБ Шушары, Шушары, Казань, Питание 22 мая 2026 ✎ изменить
⚠️ Откуда — ручной разбор Екатеринбург, Владимир, Новосемейкино, Самара, Пенза, Подольск 22 мая 2026 ✎ изменить
🔥 Высокая конкуренция Новосибирск, Екатеринбург, СПБ, Казань 22 мая 2026 ✎ изменить
Числовые лимиты
ЛимитЗначениеЗачем
Cooldown пары (SKU + донор)72 часаНе предлагаем повторно 3 суток
Per-SKU дневной лимит400 штОдной модели не больше 400 шт/день
Total дневной лимит5 000 штВсего за день не больше 5 000
candidate_limit (заглушка)500Топ-500 кандидатов идут в POST. ⚠️ Защитная заглушка.
In-transit confidence0.910% риск что товар «в пути» не доедет
Тайминги cron — все по Москве

22:00 план → 07:00 перепроверка → 09:00 POST → трекер каждые 3ч → 21:30 дайджест

История изменений правил
КогдаКтоЧто
22 маяmigration 009Создан изначальный набор из 12 правил
— пока единственная запись —

Какие данные используются

Экран 6 — Автоматика и логи (🤖)

/wb-localization/automation

Цель. Технический экран. Когда что-то не сработало — посмотреть лог. Когда нужно ручное вмешательство — кнопки запуска этапов.

hub.os.wookiee.shop / wb-localization / automation
Wookiee Hub
🤖 Автоматика и логи
cron статус, журнал прогонов, ручной запуск этапов
Состояние cron — сейчас
22:00 МСК
🌙 Вечер
последний: вчера 22:00 ✓
07:00 МСК
🌅 Утро
последний: сегодня 07:00 ✓
09:00 МСК
🚚 POST
последний: сегодня 09:00 ✓
Сторож
heartbeat 18:30 ✓
Журнал прогонов — последние 20
ВремяЭтапСтатусДеталь
28.05 18:30cleanup0 stale locks
28.05 18:00trackerобновлено сообщение msg_107
28.05 15:00tracker87 done / 65 exec
28.05 14:52post164 POST / 124 DELETE
28.05 14:40postWBconRequestError 503 — retry
28.05 13:38morningdrift 18%
28.05 13:36evening782 кандидата
Ручной запуск (kill-switch)

Только если что-то сломалось и нужно принудительно перезапустить:

⏵ Запустить evening сейчас
⏵ Запустить tracker сейчас
⛔ Выключить POST (kill-switch)
Последние URGENT в Telegram
ДатаТипСообщение
28.05 14:40POST failWBcon 503
— нет других —

Какие данные используются

Что я хочу обсудить дальше

Это первая итерация. Доработаем по ходу. Главные открытые вопросы:

  1. Главная — что важнее увидеть первым? Сейчас сверху индекс + цель + сегодняшний батч. Может стоит «алерты дня» поднять выше?
  2. Воронка — нужен ли drill-down? Клик на ступень → список отсеянных. Или достаточно сводных цифр?
  3. История задач — какие фильтры важнее? Сейчас: дата / склад / модель / статус. Что ещё?
  4. Эффективность — как показывать «работает или нет»? До Sub-project C точного ответа не дадим, но что показать прямо сейчас?
  5. Правила — какие можно править прямо из UI vs только через диалог в Telegram? Списки складов — да. Числовые лимиты — наверное тоже. candidate_limit — точно через диалог.
  6. Карта складов на главной? Я её не добавил — нужна ли визуально или таблица в «Эффективности» достаточно?