ADR-0079: Расхождение бренда при совпавшем артикуле решает арбитр
Status: accepted Date: 2026-08-11 Deciders: belkanov, agent-claude
Контекст
ADR-0070 сделал ключом
идентичности пару (manufacturer_id, нормализованный артикул). Это закрыло
класс ошибок, когда неуникальный артикул склеивал товары разных фирм, но создало
слепую зону: Tier1 требует точного совпадения manufacturer_id, Tier2
отбрасывает кандидата с другим непустым брендом — то есть пару «тот же артикул,
другой бренд» не видит ни один тир, и оффер уходил в «кандидата нет»
(ADR-0078).
Зона оказалась большой. Замер прода 2026-08-11: 124 093 группы mpn_norm
(длина ≥5) расщеплены разными manufacturer_id на 270 216 канонов. Разбор
показал, что поставщики пишут в поле производителя разные вещи для одного и того
же товара: владельца бренда (DKC), линейку или торговую марку
(YON (группа DKC)), транслитерацию (VARTON / Вартон), локального
поставщика. Контрольный кейс: артикул MD63-1C1-6, оба наименования —
YON MD63 1P 1А C 6kA, изделие одно, а каноников два.
Обратное тоже верно: под одним артикулом у разных производителей регулярно лежат
разные изделия (IEK | Legrand, Kranz | REXANT, CUTOP | FIT), а внутри одной
фирмы один артикул может покрывать целую размерную сетку
(ADR-0073,
docs/superpowers/specs/2026-08-11-matcher-terminal-strong-fallback-design.md).
Отсюда решение владельца продукта: склейку по производителю/бренду не делать.
Сведение записей справочника manufacturers (наполнение alias_slugs) как
способ склейки отвергнуто — оно необратимо схлопнуло бы такие пары сразу на
124 093 группах. Но и оставлять пару в «кандидата нет» неверно: тогда
оффер-огрызок без характеристик никогда не получит осей и останется вне подбора
аналогов, потому что назначение характеристик собирает факты только по офферам
своего каноника.
Решение
- Совпадение артикула при расходящемся непустом
manufacturer_idне даёт ни автоматической склейки, ни терминального решения. Такая пара направляется арбитру (Tier3, LLM) с триггеромcross_brand_mpn. - До ответа арбитра решение имеет
status = 'conflict',tier = 'none',match_confidence = 'unmatched'и не назначает каноник. Конфликтная ветвь очереди рематча подхватывает такие решения по штатномуMATCHER_RECHECK_COOLDOWN, поэтому пара не теряется, если арбитр недоступен. - Арбитраж идёт своим системным промптом. Промпт tier1-конфликта для этого
непригоден: он прямо предписывает не выбирать кандидата при расходящемся
бренде, то есть отказал бы на каждой паре. Новый промпт снимает этот запрет и
одновременно запрещает принимать пару по одному совпадению артикула: решение
принимается по наименованию и характеристикам, а при недостаточных данных
модель обязана вернуть
null. - Низкая уверенность арбитра уводит пару в ручную модерацию — в очередь
добавлено значение триггера
cross_brand_mpn(миграция 0357). - Кандидаты для арбитража отбираются только при артикуле длиной ≥5 символов и
только среди офферов других поставщиков с непустым и отличающимся
manufacturer_id; число кандидатов на пару ограничено пятью. Пары с пустым брендом остаются за Tier2 fingerprint.
Последствия
Плюсы
- Слепая зона закрыта без пакетного мержа справочника: решение принимается по каждой паре отдельно и обратимо.
- Механизм работает и для оффера-огрызка без характеристик — арбитр видит наименования, тогда как сравнение по осям здесь невозможно.
- Признак
same_mpn_other_brandв причине кандидата и отдельный триггер делают поток различимым в модерации и аналитике.
Минусы
- Поток LLM-вызовов: 124 093 группы при
MATCHER_TIER3_MAX_PER_TICK=300и тике в минуту — порядка семи часов прогона плюс расход квоты. Кап не снимается, поэтому поток растянут и делится с остальными Tier3-путями. - Ошибка арбитра даёт неверную склейку. Смягчение:
nullпри сомнении, модерация при низкой уверенности, решение не терминально.
Нейтральные последствия
- Прежнее поведение для пар с совпадающим брендом не меняется: Tier1 и Tier2 работают как раньше.
- Пары, где арбитр вернул
null, остаются в конфликте и будут переспрошены после следующего изменения данных.
Рассмотренные альтернативы
Сведение бренд-псевдонимов в справочнике
Отвергнуто владельцем продукта: под одним артикулом у разных брендов лежат разные товары, а мерж записей необратим и применялся бы пакетно.
Склейка по совпадению identity-осей без LLM
Дешевле и детерминированнее, но неприменима именно там, где проблема острее: у оффера-огрызка осей нет (у 130 425 из 440 564 офферов ETM ровно одна характеристика). Оставлено как возможное дополнение — сначала дешёвая проверка осей, арбитр только когда осей недостаточно.
Перенос характеристик по артикулу без склейки
Это та же склейка по артикулу, только на уровне фактов: при разных изделиях каноник получил бы чужие оси, то есть порчу данных вместо пустоты.