## ADDED Requirements ### Requirement: Сходимость базы папки при подтверждённом матче Система SHALL при построении плана раскладки для загрузки с подтверждённым матчем (заданы `provider` и `provider_id`) наследовать **базу имени** (`Название (Год)` — строку без provider-тега) от существующей на диске папки-якоря того же тайтла, а НЕ печатать её заново из выхода распознавания. Кандидаты в якорь — целевые пути (`dst_path`) ссылок со статусом `linked`/`copied`/`exists` **других** загрузок (не текущей), чей current recognition имеет тот же `(provider, provider_id)`. Истина — папка на диске, а не запись в БД: кандидат SHALL считаться живым якорем, только если его папка тайтла реально существует на файловой системе. Статус ссылки в БД недостаточен — при ручном/Jellyfin-переименовании папки запись `file_link` какое-то время остаётся `linked` (загрузка лишь позже уходит в `target_missing` по сверке), а `dst_path` указывает на уже несуществующий путь. Поэтому кандидат, чья папка тайтла отсутствует на диске, в якоря НЕ берётся; если живых якорей не осталось, следующая загрузка снова печатает базу из распознавания. Унаследованная база SHALL применяться **и к папке сериала/фильма, и к именам файлов внутри** (episode/movie stem), чтобы серии разных сезонов совпадали по базе (`Fargo (2014) S02E01` рядом с `Fargo (2014) S01E01`). Provider-тег на папке (`[tvdbid-…]`) по-прежнему SHALL строиться из текущего `(provider, provider_id)`. База тайтла извлекается из папки-якоря снятием хвостового provider-тега ` [...]`; извлечённая база прогоняется через ту же санитизацию, что и печатаемая. Если папку-якорь нельзя разобрать (сегмент не под корнем библиотеки, база пуста), кандидат в якоря НЕ берётся (безопасный fallback на печать из распознавания), а не даёт искажённую базу. Наследование SHALL происходить только при подтверждённом матче. Нет живого якоря (первая загрузка тайтла) → база печатается из распознавания, как прежде. Нет матча (`provider` пуст / `none`) → авто-раскладки нет (инвариант), база не наследуется — папку на ревью выбирает человек. Правило не вводит новых сущностей и не меняет схему БД: это выборка по существующим `file_link → download → recognition(is_current)` плюс проверка существования папки на диске. Безопасность по-прежнему держится на санитизации и проверке пути под библиотекой, а не на доверии к выходу распознавания. Разрешение базы SHALL быть единым для авто-раскладки и ручного «Применить», а также для **предпросмотра** раскладки на ревью — чтобы превью показывало ту же папку/имена, что даст применение (инвариант «превью = применение»). В предпросмотре разрешение выполняется без побочных эффектов (в review из-за рассинхрона переводит только применение, не показ). #### Scenario: Второй сезон ложится в папку первого - **GIVEN** первый сезон уже разложен в `series/Фарго (2014) [tvdbid-269613]/Season 01/…` (ссылки живые) - **AND** новая загрузка со вторым сезоном имеет матч TVDB `269613`, но распознавание дало название «Fargo» и год `2017` - **WHEN** строится план раскладки второго сезона - **THEN** база наследуется от живого якоря: папка = `series/Фарго (2014) [tvdbid-269613]/` - **AND** серия ложится как `Season 02/Фарго (2014) S02E01.mkv` (база в имени файла — унаследованная, а не из выхода LLM) #### Scenario: Нет живого якоря — печатаем из распознавания - **GIVEN** ни у одной загрузки нет живых ссылок с тем же `(provider, provider_id)` - **WHEN** строится план раскладки при подтверждённом матче - **THEN** база берётся из распознавания (название+год), как прежде — первая загрузка «печатает» имя папки #### Scenario: Нет матча — сходимость не применяется - **GIVEN** у загрузки нет подтверждённого матча (`provider` пуст / `none`) - **WHEN** обрабатывается раскладка - **THEN** авто-наследования базы не происходит, загрузка идёт через review (папку выбирает человек) #### Scenario: Папка-якорь переименована на диске — печатаем заново - **GIVEN** у загрузки-кандидата статус ссылок ещё `linked`, но её папка тайтла на диске переименована/удалена (по `dst_path` папки нет) - **WHEN** строится план раскладки новой загрузки с тем же матчем - **THEN** отсутствующая на диске папка в якоря не берётся - **AND** при отсутствии других живых якорей база печатается из распознавания #### Scenario: Превью на ревью совпадает с применением - **GIVEN** есть живой якорь тайтла, а распознавание текущей загрузки дало иную базу - **WHEN** на ревью открывается предпросмотр целевой раскладки - **THEN** превью показывает папку/имена с унаследованной базой якоря — те же, что даст «Применить» ### Requirement: Рассинхрон живых папок тайтла уходит в review Система MUST NOT молча выбирать якорь при обнаружении **нескольких РАЗНЫХ** живых целевых папок с одним `(provider, provider_id)` (рассинхрон, случившийся до внедрения правила сходимости): такая загрузка SHALL уходить в `review` с явной причиной «рассинхрон папок тайтла», чтобы человек выбрал/свёл папку вручную (по прецеденту коллизии, которая тоже уводит в review из раскладки). #### Scenario: Две живые папки одного матча → review - **GIVEN** для матча TVDB `269613` существуют две разные живые папки (`Фарго (2014) …` и `Fargo (2017) …`) - **WHEN** строится план раскладки новой загрузки с этим матчем - **THEN** раскладка не выполняется, задача переходит в `review` с причиной рассинхрона папок тайтла