---
name: avtero_named_canonical_gate
description: avtero — canonical-гейт названных деталей (v0.7.21): part-строки строит пайплайн из req×resolver, LLM выброшен; все ранние return покрыты; неточные филлеры скипают _named_blank
metadata:
  node_type: memory
  type: project
  originSessionId: 4eea915e-3b47-4cd5-8a0e-bfa29b78a87c
---

**Гарантия «номера бьются» для явно названных деталей (v0.7.21, 2026-07-02, D-named-canonical):** `_enforce_named_parts` в `orchestrator.py` — в strict-режиме part-строки СТРОЯТСЯ из `_requested_parts` × `_resolve_named_part`; LLM-строки выбрасываются (донор только why_needed по head-noun); не нашлось → пусто + note «сверьте у дилера» + `_named_blank`. Гейт в ОБОИХ путях run(): пост-LLM (перед emex-валидатором) И catalog_fallback (ранний return при LLM-таймауте — ловился только live-логом!). Филлеры exact-chain backfill + local-tree (`_fill_primary_oem_from_local_trees`) скипают `_named_blank` (bilstein подставлял опору ДВС 21810-0Q000 на «опора»). Прозрачность: чужая ось в каталожном имени → check_note «По каталогу: ПРУЖИНА ЗАДНЕЙ ПОДВЕСКИ.».

**Почему НЕ промпт/матчер (проверено live, 3 итерации):** existence-валидатор пропускает реальный номер чужой детали (задний аморт 553001M300 под именем переднего); LLM игнорирует «не подменяй» и лепит ЛОЖНЫЕ квалификаторы («колодки ручника (ПЕРЕДНИЙ)» — merged-ре-резолв сам подставил 581011MA20!), дублирует лев/прав мимо матчера.

**Грабли верификации:** 5-мин ПЕРСИСТЕНТНЫЙ кэш run() по (vin,work_text,…) переживает рестарт — правки проверять ТОЛЬКО кэш-бастером (менять текст); enforcement-лог «installed N canonical row(s)» обязан появляться на КАЖДЫЙ live-прогон, его отсутствие = прогон ушёл в непокрытую ветку.

**v0.7.28 (аудит 2026-07-02, D-conjunction-split-noun-guard):** сплиттер `_requested_parts` режет и по « и » с тем же guard `_pos_only` — «задние колодки и наконечник» раньше МОЛЧА терял колодки и вешал «(зад)» на наконечник (canonical-гейт строит строки из `_requested_parts` → потеря системная); пары «передние и задние» целы. Бэкап `*.bak-isplit-*`, регресс `tests/test_i_conjunction_split.py` (5). Плюс реверс-триггеры «суппорт ремкомплект»/«egr клапан» (`*.bak-revtrig-*`).

Регресс: `tests/test_named_enforcement.py` (6, canonical-контракт) + `tests/test_cerato_multipart.py` (6, сплит по «+»/наконечник). Бэкапы `orchestrator.py.bak-{enforce,enforce2,enforce3,canonical,fbenforce,final2,ltskip}-*`. Связано [[avtero_hard_corrections_learning]] [[avtero_validation_audit_axle]].
