Раскладка: сходимость папки сериала (второй сезон в ту же папку)
При подтверждённом матче база папки (имя+год) наследуется от живой папки-якоря того же (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>
This commit is contained in:
@@ -40,6 +40,20 @@ func titleYear(title string, year int) (string, error) {
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// planBase выбирает базу имени плана: унаследованная от живого якоря
|
||||
// FolderBase (правило сходимости папки) перекрывает Title/Year. База в любом
|
||||
// случае санитизируется (FolderBase пришла с диска — прогон идемпотентен).
|
||||
func planBase(p Plan) (string, error) {
|
||||
if p.FolderBase != "" {
|
||||
b := sanitizeComponent(p.FolderBase)
|
||||
if b == "" {
|
||||
return "", fmt.Errorf("layout: empty folder base after sanitization (%q)", p.FolderBase)
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
return titleYear(p.Title, p.Year)
|
||||
}
|
||||
|
||||
// folderName добавляет provider-тег к базе: "Название (Год) [tmdbid-123]".
|
||||
func folderName(base, providerTag string) string {
|
||||
tag := sanitizeComponent(providerTag)
|
||||
@@ -49,6 +63,19 @@ func folderName(base, providerTag string) string {
|
||||
return fmt.Sprintf("%s [%s]", base, tag)
|
||||
}
|
||||
|
||||
// folderBase восстанавливает базу имени ("Название (Год)") из имени папки
|
||||
// тайтла, снимая хвостовой provider-тег " [...]" (любой, а не только текущий:
|
||||
// у переоценённого якоря тег мог остаться старым). Тег без пробела перед "["
|
||||
// или незакрытый — не трогаем. Результат санитизируется; пустой → "" (вызывающий
|
||||
// трактует как «нет якоря»).
|
||||
func folderBase(folder string) string {
|
||||
base := folder
|
||||
if i := strings.LastIndex(folder, " ["); i >= 0 && strings.HasSuffix(folder, "]") {
|
||||
base = folder[:i]
|
||||
}
|
||||
return sanitizeComponent(base)
|
||||
}
|
||||
|
||||
// seasonFolder — "Season 00" (спецвыпуски) / "Season 01" / ...
|
||||
func seasonFolder(season int) string {
|
||||
return fmt.Sprintf("Season %02d", season)
|
||||
|
||||
Reference in New Issue
Block a user