Files
jellybit/openspec/changes/archive/2026-07-10-series-folder-convergence/specs/file-layout/spec.md
T
avandClaude Opus 4.8 5c3ef79496 Раскладка: сходимость папки сериала (второй сезон в ту же папку)
При подтверждённом матче база папки (имя+год) наследуется от живой
папки-якоря того же (provider, provider_id) вместо печати заново из выхода
LLM — так второй/последующий сезон ложится в ТУ ЖЕ папку, а не заводит
рядом почти одинаковую. Отдельная сущность «тайтл» не вводится.

- layout: Plan.FolderBase перекрывает базу в папке и именах файлов;
  TitleFolder разбирает dst_path в папку тайтла и базу (снятие тега).
- store: LiveTitleFolders — dst_path живых ссылок того же матча.
- worker: resolveFolderBase (живость якоря — по наличию папки на диске,
  os.Lstat, а не по статусу ссылки в БД) в linkPlan и в превью ревью
  (превью=применение); рассинхрон нескольких живых папок → review из
  linking (deferred→review в графе нет).

Схема БД не менялась. Change series-folder-convergence заархивирован,
требования влиты в openspec/specs/file-layout.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 13:50:49 +03:00

8.6 KiB
Raw Blame History

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 с причиной рассинхрона папок тайтла