## 1. Homoglyph-таблица и fold - [x] 1.1 В `internal/recognize` завести курируемую таблицу кирилло-латинских двойников (~15–20 пар, строчные и заглавные) как единственный источник правды - [x] 1.2 Реализовать потокенную `foldHomoglyphs(s string) string`: одно-скриптовый токен не трогаем, в смешанном — доминирующий скрипт по числу буквенных рун, меньшинство мапим по таблице; при равенстве оставляем как есть - [x] 1.3 Юнит-тесты `foldHomoglyphs`: «Hаrold»→«Harold», честная кириллица нетронута, смешанное двуязычное название, равенство скриптов, пустой ввод ## 2. Санитайзинг полей плана (recognition) - [x] 2.1 Реализовать `sanitizeTitle`: strip control/zero-width (C0/C1, U+200B и родственные, BOM), collapse пробелов + trim, затем `foldHomoglyphs` - [x] 2.2 Применить санитайзинг к `title`, `original_title`, `provider_hint` на границе разбора плана — после unmarshal, ДО структурной валидации и сверки; `files[].src` не трогать - [x] 2.3 `slog.Debug` when поле реально переписано (before/after), логгер из ctx - [x] 2.4 Тесты: поля чистятся, `files[].src` неприкосновенны, лог при изменении ## 3. Fold в гейте нормализации (metadata-match) - [x] 3.1 Добавить `foldHomoglyphs` в `normalize` (`internal/recognize/metadata.go`) после `ё→е`, переиспользуя ту же таблицу - [x] 3.2 Тест: план и кандидат, различающиеся лишь скриптом буквы, нормализованно совпадают ## 4. Безгодовой второй проход сверки (metadata-match) - [x] 4.1 Обернуть перебор в `matchMetadata` в два прохода: pass 1 — как сейчас (`Search` с годом), pass 2 — только при `plan.Year > 0` и отсутствии матча в pass 1, тот же перебор `searchKeys × providers` с `Year = 0` - [x] 4.2 Кандидаты копятся через оба прохода с существующей дедупликацией по `provider:id` и потолком `maxCandidates`; гейт `strongMatches` не менять - [x] 4.3 Тесты: кривой год находится без года; при матче в pass 1 второго прохода нет; при `year = 0` второго прохода нет; несколько кандидатов из pass 2 → матч не подтверждён ## 5. Проверка и вычитка - [x] 5.1 `task test` и `task lint` — зелёные - [x] 5.2 `openspec validate --strict sanitize-llm-titles-yearless-retry`