display_name: слоистое разрешение полей + сохранение режиссёра из контекста
Единый источник полей отображаемого имени и один рендер полного ярлыка на всех путях (старт и «Обновить имя»/авто-перелив). Раньше старт давал полный «Название (режиссёр, год). Сезон N» но выбрасывал структуру, а перелив по распознаванию — усечённый «Title (Year)». - Слоистое разрешение скаляров имени: override → recognition(+match) → новый базовый слой «контекст» (download.parsed_context, JSON naming.Fields). - naming: публичные Fields/Label/Derive, вынесен единый рендер; удалён FormatTitleYear. Сводка сезонов вынесена в recognize.SeasonSummary. - Режиссёр из метабазы (решение A2): TMDB/TVDB credits через опциональный metadata.DirectorProvider; авто-матч кладёт в plan.Director, ручной выбор кандидата тянет credits и пиннит ovrDirector. Метабаза бьёт контекст. - refreshDisplayNameLocked строит полный ярлык из эффективных полей; инфо-панель ревью показывает загруженного режиссёра. - Миграция 0011_parsed_context + ER-схема. Всё косметика: на пути/раскладку не влияет, приём/вывод имени не валятся (best-effort). Закрывает беклог-задачу «Кнопка „Обновить имя“: полный формат ярлыка». OpenSpec: archive/2026-07-11-field-resolution-display-name (ingest, recognition, metadata-match, review). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
## Why
|
||||
|
||||
Отображаемое имя (`download.display_name`) сейчас выводится по двум расходящимся
|
||||
правилам. На шаге добавления `naming` извлекает из контекста структуру
|
||||
(тип/название/год/**режиссёр**/сезон) и рендерит **полный** ярлык
|
||||
«Название (режиссёр, год). Сезон N», но структуру после рендера **выбрасывает**.
|
||||
А обновление имени по распознаванию (ручная кнопка «Обновить имя» и авто-перелив
|
||||
при матче) даёт **усечённый** `Title (Year)` — без режиссёра и сезона. В итоге
|
||||
режиссёр, добытый из контекста, теряется, а перелив ухудшает уже показанное имя.
|
||||
|
||||
Причина расхождения — у распознавания нет поля режиссёра, а извлечение из
|
||||
контекста нигде не сохраняется. Решаем в общем виде: поля имени приходят из
|
||||
разных источников в разное время (контекст — на старте; метабаза — при
|
||||
распознавании; правки — в ревью), поэтому вводим **единый слоистый источник** и
|
||||
**одну** функцию рендера ярлыка.
|
||||
|
||||
## What Changes
|
||||
|
||||
- **Слоистое разрешение скалярных полей имени** (тип, название, ориг. название,
|
||||
год, режиссёр, сезон-для-ярлыка): эффективное значение поля — первый непустой
|
||||
слой сверху вниз `override` (человек) → `recognition` (LLM + матч метабазы) →
|
||||
**новый базовый слой «контекст»** (извлечение `naming` на старте). Слои
|
||||
`override`→`recognition` уже существуют (`effectivePlan`/`applyOverrides`);
|
||||
добавляем нижний слой и единый хелпер разрешения.
|
||||
- **Извлечение из контекста становится persistent.** Структуру, которую `naming`
|
||||
извлекает на шаге добавления, сохраняем у загрузки в новой JSON-колонке
|
||||
(`download.parsed_context`), чтобы переиспользовать без повторного вызова LLM.
|
||||
- **Режиссёр из метабазы.** Подтверждённый матч TMDB/TVDB несёт режиссёра
|
||||
(credits), он вкладывается в план так же, как уже вкладываются каноничные
|
||||
название/год, и в разрешении бьёт контекстного (более проверенный источник).
|
||||
- **Единый рендер ярлыка display_name.** Одна функция строит полный ярлык
|
||||
«Название (режиссёр, год)» (+ для сериала сводка сезонов «. Сезон N» /
|
||||
«. Сезоны 1–3» / «спецвыпуски») из эффективных полей и зовётся и на старте, и
|
||||
при обновлении по распознаванию. Усечённый формат `Title (Year)` при обновлении
|
||||
убирается. Это закрывает беклог-задачу «Кнопка „Обновить имя“: полный формат».
|
||||
- **Инфо-часть ревью** показывает загруженного режиссёра (ранее — пустое
|
||||
зарезервированное место).
|
||||
|
||||
Всё перечисленное — косметика отображения: не влияет на пути файлов,
|
||||
распознавание или раскладку. Приём и вывод имени по-прежнему не валят загрузку.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
(нет — вводится слой внутри существующих capability, новых доменов нет)
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `ingest`: извлечение из контекста сохраняется у загрузки (`parsed_context`);
|
||||
обновление отображаемого имени переходит с `Title (Year)` на полный ярлык из
|
||||
эффективных полей (слоистое разрешение + сводка сезонов).
|
||||
- `recognition`: план несёт опциональное скалярное поле `director` (источник —
|
||||
подтверждённый матч, не LLM); режиссёр — недоверенное косметическое поле.
|
||||
- `metadata-match`: подтверждённый матч и кандидат несут режиссёра (TMDB/TVDB
|
||||
credits), когда он доступен, для вывода имени.
|
||||
- `review`: подтверждение матча обновляет имя полным ярлыком; инфо-часть
|
||||
выбранного источника показывает загруженного режиссёра.
|
||||
|
||||
## Impact
|
||||
|
||||
- Код: `internal/naming` (публичный рендер из эффективных полей, экспорт
|
||||
извлечённой структуры), `internal/recognize` (`Plan.Director`),
|
||||
`internal/metadata` (`Candidate.Director` + выборка credits в клиентах
|
||||
TMDB/TVDB), `internal/worker` (сохранение `parsed_context` на старте; хелпер
|
||||
`effectiveFields`; полный формат в `refreshDisplayNameLocked`),
|
||||
`internal/store` (миграция goose: колонка `download.parsed_context`; чтение/
|
||||
запись), `internal/httpapi` (инфо-часть режиссёра; переиспользование
|
||||
`seasonSummary`).
|
||||
- БД: новая колонка `download.parsed_context` (TEXT, JSON) — обновить ER-схему
|
||||
`docs/specs/database.md`.
|
||||
- Внешние вызовы: дополнительный запрос credits к TMDB/TVDB при подтверждённом
|
||||
матче (best-effort, недоступность не валит распознавание).
|
||||
- Беклог: закрывается `docs/backlog/knopka-obnovit-imya-polnyj-format.md`.
|
||||
Reference in New Issue
Block a user