Кейс «Harold and the Purple Crayon»: LLM отдал title с кириллической буквой-двойником, сырое название ушло в запрос TVDB дословно (не нашлось), а гейт нормализации кир/лат двойники не сворачивал — двойной промах, пустой список кандидатов, ручной ввод id. - recognition: санитайзинг человекочитаемых полей плана (title/original_title/ provider_hint) на границе разбора, до валидации: strip control/zero-width, collapse пробелов, потокенная свёртка homoglyph-двойников по курируемой кир↔лат таблице. files[].src не трогаем (обязаны биться с торрентом). - metadata-match: тот же fold в normalize (гейт) как defense-in-depth; безгодовой второй проход сверки как fallback при известном годе и промахе первого — восстанавливает off-by-one авто-матчи и пополняет кандидатов review. В fallback требуем известный год кандидата (год-unknown → review, не авто); гейт год ±1 и инвариант авто-матча не двигаются. Спеки recognition/metadata-match обновлены, change заархивирован. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
65 lines
4.9 KiB
Markdown
65 lines
4.9 KiB
Markdown
## ADDED Requirements
|
||
|
||
### Requirement: Санитайзинг человекочитаемых полей плана
|
||
|
||
Перед структурной валидацией плана и сверкой с базами система SHALL санитизировать
|
||
человекочитаемые поля плана — `title`, `original_title`, `provider_hint` — как
|
||
недоверенный вывод LLM. Санитайзинг SHALL: (1) удалять управляющие и zero-width
|
||
символы (C0/C1, `U+200B` и родственные, BOM `U+FEFF`); (2) сводить внутренние
|
||
последовательности пробельных к одиночному пробелу и обрезать края; (3) сворачивать
|
||
кирилло-латинские homoglyph-двойники (см. ниже).
|
||
|
||
Свёртка двойников SHALL работать потокенно (по словам, разделённым не-буквенными
|
||
символами): токен, все буквы которого принадлежат одному скрипту, система SHALL
|
||
оставлять без изменений (билингвальность реальна — кириллические названия
|
||
неприкосновенны); в токене смешанного скрипта система SHALL определять доминирующий
|
||
скрипт по числу буквенных рун и заменять буквы-меньшинство их визуальными
|
||
двойниками из доминирующего скрипта по курируемой таблице. При отсутствии
|
||
доминирующего скрипта (равенство) токен SHALL оставаться без изменений.
|
||
|
||
Санитайзинг SHALL применяться ТОЛЬКО к перечисленным человекочитаемым полям.
|
||
`files[].src` система SHALL NOT санитизировать — эти значения обязаны совпадать с
|
||
реальными файлами торрента, и расхождение (в т.ч. homoglyph) SHALL оставаться
|
||
основанием отклонить план, а не поводом «чинить» путь.
|
||
|
||
Когда санитайзинг реально изменил значение поля, система SHALL логировать это на
|
||
уровне `Debug` (названия не относятся к секретам).
|
||
|
||
#### Scenario: Кириллический двойник в англоязычном названии сворачивается
|
||
|
||
- **GIVEN** план, где `title` = `Hаrold and the Purple Crayon` (буква `а` в первом
|
||
слове — кириллическая `U+0430`)
|
||
- **WHEN** план санитизируется
|
||
- **THEN** первое слово становится `Harold` (все буквы латинские)
|
||
- **AND** в запрос к базе и в сравнение уходит латинское название
|
||
|
||
#### Scenario: Честное кириллическое название не трогается
|
||
|
||
- **GIVEN** план российского фильма с `title` = `Тёмный рыцарь`, где все буквы
|
||
каждого слова кириллические
|
||
- **WHEN** план санитизируется
|
||
- **THEN** название остаётся кириллическим без замены букв
|
||
|
||
#### Scenario: Токен без доминирующего скрипта не трогается
|
||
|
||
- **GIVEN** план, где короткий токен содержит поровну латинских и кириллических
|
||
букв (доминирующего скрипта нет)
|
||
- **WHEN** план санитизируется
|
||
- **THEN** этот токен остаётся без замены букв (осознанный trade-off: двухбуквенный
|
||
homoglyph-typo не сворачивается)
|
||
|
||
#### Scenario: Zero-width и лишние пробелы вычищаются
|
||
|
||
- **GIVEN** план, где `title` содержит zero-width символ и сдвоенные пробелы
|
||
- **WHEN** план санитизируется
|
||
- **THEN** zero-width удалён, внутренние пробелы сведены к одиночным, края обрезаны
|
||
|
||
#### Scenario: files[].src не санитизируется
|
||
|
||
- **GIVEN** ответ LLM, где `files[].src` содержит символ-двойник и не совпадает ни
|
||
с одним реальным файлом торрента
|
||
- **WHEN** план обрабатывается
|
||
- **THEN** `files[].src` НЕ изменяется санитайзингом
|
||
- **AND** несовпадение src приводит к отклонению плана (эскалация в review), а не к
|
||
«починке» пути
|