Files
jellybit/openspec/changes/archive/2026-07-10-series-folder-convergence/proposal.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

64 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Why
Второй/третий сезон одного сериала должен ложиться в ТУ ЖЕ папку, а не заводить
рядом почти одинаковую. Сейчас имя папки печатается заново из выхода LLM при
каждой раскладке (`layout.BuildLinks` из полей плана), и совпадение
`(provider, provider_id)` не гарантирует совпадение строки папки: LLM может дать
«Fargo» и «Фарго», год сезона вместо года сериала — и верно заматченный второй
сезон уедет в соседнюю папку. Это ядро «проблемы второго сезона»: она **не про
группировку, а про сходимость папки** (см. `docs/drafts/logical-title-model.md`
§3, §5.2).
## What Changes
- Вводим **правило сходимости папки** при построении плана раскладки: при
подтверждённом матче (`provider` и `provider_id` заданы) база папки
(`Название (Год)`) **наследуется** от живых `file_link` других загрузок того
же тайтла, а выход LLM для папки игнорируется.
- Якорь берём из **существующего `dst_path`** живых ссылок (`status IN
linked/copied/exists`) загрузок, чей current recognition имеет тот же
`(provider, provider_id)` — живые пути — истина (переименовали папку → сверка
уводит ссылки в `target_missing`, якорь исчезает, следующая загрузка печатает
заново).
- Унаследованная база применяется **и к папке, и к именам файлов внутри**
(episode/movie stem), чтобы `Fargo (2014) S02E01` совпадало с
`Fargo (2014) S01E01`. Провайдер-тег `[tvdbid-…]` по-прежнему берётся из
текущего `(provider, provider_id)`.
- **Рассинхрон** (несколько РАЗНЫХ живых папок с одним `(provider, provider_id)`,
случившийся до внедрения правила) → загрузка уходит в **review** с явной
причиной, якорь молча не выбираем.
- Отдельная сущность «тайтл» **не вводится**: это join по существующим таблицам
(`file_link → download → recognition(is_current)`), без новых
сущностей/таблиц. Схема БД не меняется.
## Capabilities
### New Capabilities
<!-- нет -->
### Modified Capabilities
- `file-layout`: добавляется правило сходимости базы папки при построении
целевого пути — при подтверждённом матче база наследуется от живых ссылок того
же `(provider, provider_id)`, а не печатается из выхода распознавания; несколько
расходящихся живых папок → уход в review с причиной «рассинхрон» вместо тихого
выбора (по прецеденту коллизии, которая тоже уводит в review из file-layout).
## Impact
- **Код:** `internal/layout` (возможность построить план с унаследованной базой
папки), `internal/worker` (`linkPlan`/построение плана раскладки: lookup якоря,
ветка рассинхрон→review), `internal/store` (новый read-метод: живые целевые
папки по `(provider, provider_id)`, исключая текущую загрузку).
- **Инварианты безопасности данных:** не трогаем. `download` остаётся мостом,
выход распознавания недоверенный, безопасность — на санитизации и проверке
пути под библиотекой. Никаких новых прав на источник.
- **Схема БД:** без изменений (только новый SELECT-join).
- **Границы:** нет якоря → папка из распознавания (как сейчас); нет матча
(`provider=none`) → авто-раскладки нет, всё через review (инвариант); смена
провайдера между сезонами якорь не склеит — редкий случай, штатно review
(осознанная цена, черновик §6.1).
- **Совместимость:** поведение первой загрузки тайтла не меняется; правило
влияет только на последующие вклады при наличии живого якоря.