recognize: название из метабазы санитизируется перед попаданием в план

- чистка стоит на каждой точке входа значения метабазы в план — сборка матча,
  копия кандидата для ревью, набор закреплённых значений источника и его
  чтение: гарантия, поставленная только на запись, обходится данными,
  сохранёнными прежними версиями
- название, непригодное как имя каталога (пустое или без единой буквы и
  цифры), не подставляется — раздача уходит в review с названной причиной
- гейт подтверждения матча не сдвинут: сравнение с планом идёт по значениям
  провайдера, чистится только копия, уходящая дальше
This commit is contained in:
av
2026-08-10 10:41:16 +03:00
parent bb278e8744
commit 9aecf757e0
26 changed files with 1653 additions and 53 deletions
+49 -2
View File
@@ -179,6 +179,25 @@ per-file `season`/`episode` (отдельного скалярного `season`
последовательности пробельных к одиночному пробелу и обрезать края; (3) сворачивать
кирилло-латинские homoglyph-двойники (см. ниже).
Санитайзинг SHALL быть **общим для обоих источников названия** — вывода LLM и
записи метабазы. Значение, пришедшее из метабазы и заменяющее поле плана при
подтверждённом матче, SHALL проходить тот же санитайзинг перед подстановкой (см.
`metadata-match`, требование «Подтверждение матча и каноническое имя»). Второго
способа чистить **названия плана** система SHALL NOT заводить: одна реализация
обслуживает оба источника. Речь только о полях плана — очистка компонента пути
под требования файловой системы (`layout`) и очистка отображаемого ярлыка
(`naming`) остаются своими, отдельными и законными.
Санитайзинг SHALL быть **идемпотентным**: повторное применение к уже
санитизированному значению SHALL NOT изменять его. На этом свойстве стоит
утверждение, что правка не меняет путей на диске для раздач с нормальным
названием, и оно проверяется тестом, а не подразумевается.
Следствие, на которое опирается раскладка: к моменту, когда план уходит в решение
auto/review, каждое из полей `title`, `original_title`, `provider_hint` совпадает
с тем, что дал бы санитайзинг этого значения — независимо от того, пришло оно от
LLM или из метабазы.
Свёртка двойников SHALL работать потокенно (по словам, разделённым не-буквенными
символами): токен, все буквы которого принадлежат одному скрипту, система SHALL
оставлять без изменений (билингвальность реальна — кириллические названия
@@ -187,10 +206,15 @@ per-file `season`/`episode` (отдельного скалярного `season`
двойниками из доминирующего скрипта по курируемой таблице. При отсутствии
доминирующего скрипта (равенство) токен SHALL оставаться без изменений.
Санитайзинг SHALL применяться ТОЛЬКО к перечисленным человекочитаемым полям.
Санитайзинг SHALL применяться ТОЛЬКО к перечисленным человекочитаемым полям
**плана**. Применение того же санитайзинга к значениям, пришедшим из метабазы —
каноническому названию и названиям кандидатов, — заказано отдельно, см.
`metadata-match`.
`files[].src` система SHALL NOT санитизировать — эти значения обязаны совпадать с
реальными файлами торрента, и расхождение (в т.ч. homoglyph) SHALL оставаться
основанием отклонить план, а не поводом «чинить» путь.
основанием отклонить план, а не поводом «чинить» путь. `director` система SHALL
NOT санитизировать в плане — он не участвует в пути на диске, и его очистка
применяется при рендере отображаемого имени (см. `metadata-match`).
Когда санитайзинг реально изменил значение поля, система SHALL логировать это на
уровне `Debug` (названия не относятся к секретам).
@@ -233,3 +257,26 @@ per-file `season`/`episode` (отдельного скалярного `season`
- **AND** несовпадение src приводит к отклонению плана (эскалация в review), а не к
«починке» пути
#### Scenario: Название из метабазы чистится тем же санитайзингом
- **GIVEN** подтверждённый единичный матч, каноническое название которого содержит
zero-width символ и кириллический двойник внутри латинского слова
- **WHEN** каноническое название подставляется в план
- **THEN** в плане оказывается значение, прошедшее тот же санитайзинг, что и вывод
LLM
#### Scenario: После сверки с базой несанитизированных полей в плане не остаётся
- **GIVEN** план после подтверждённого матча с базой
- **WHEN** оценивается решение auto/review
- **THEN** каждое из полей `title`, `original_title`, `provider_hint` совпадает с
тем, что дал бы санитайзинг этого значения
- **AND** `director` под это требование не подпадает: он чистится при рендере
отображаемого имени
#### Scenario: Повторный санитайзинг ничего не меняет
- **GIVEN** значение, уже прошедшее санитайзинг
- **WHEN** санитайзинг применяется к нему второй раз
- **THEN** значение не изменяется