Веб-UI: режиссёр в блоке «Распознано как» на странице загрузки

На /download/{id} поле «Режиссёр» было захардкожено прочерком, хотя экран
ревью режиссёра уже выводит: слоистое разрешение полей ярлыка было заперто в
неэкспортируемом worker.effectiveDisplayName. Из-за этого билдеры вью видели
только слой распознавания+матч (rd.Plan.Director) без слоя контекста — то же
на экране ревью.

Вынес разрешение в экспортируемую naming.EffectiveFields(parsedContext, plan)
LabelFields с методом Label(): выбор слоя по сырым значениям (как прежде),
выбранные скаляры возвращаются очищенными (sanitize идемпотентен, display_name
побайтно тот же). effectiveDisplayName стал тонкой обёрткой; страница загрузки
и экран ревью берут режиссёра из той же функции — согласованно с заголовком.

OpenSpec: web-ui (ADDED «Режиссёр в блоке распознавания страницы загрузки»),
review (MODIFIED «Инфо и предпросмотр выбранного источника» — слоистое
разрешение с фолбэком на контекст). Change заархивирован. Беклог: закрыта
rezhisser-v-kartochke-zagruzki.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
av
2026-07-17 21:21:27 +03:00
co-authored by Claude Opus 4.8
parent 0354a8c96b
commit 5948f4d219
16 changed files with 612 additions and 93 deletions
-1
View File
@@ -31,7 +31,6 @@ Tududi (проект `jellybit`) больше **не** держит беклог
- [Аниме с абсолютной нумерацией](anime-absolyutnaya-numeraciya.md) — Релизы аниме часто нумеруют серии сквозным числом (#137) без сезонов, а Jellyfin ждёт…
- [Бэкап SQLite](backup-sqlite.md) — architecture
- [Сигнал Jellyfin после отката и удаления файлов](jellyfin-skan-posle-udaleniya.md) — Скан шлётся только на done; после reverted/deleted Jellyfin держит битые записи. Клиент и гейт готовы, но скана нет в openspec-спеках
- [Режиссёр в блоке «Распознано как» на странице загрузки](rezhisser-v-kartochke-zagruzki.md) — На /download/{id} режиссёр всегда прочерк (поля нет в шаблоне); экран ревью его уже выводит
- [Глубокий healthcheck и статус зависимостей](healthcheck-zavisimosti.md) — /healthz проверяет только сам сервис
- [НФТ: масштаб до 100 одновременных загрузок (потолок — 1000)](masshtab-100-zagruzok.md) — Зафиксировать в НФТ ориентир 100/1000 загрузок + аудит узких мест (SQLite, воркер, поллинг)
- [Обучение на правках человека (few-shot из прошлых ревью)](obuchenie-na-pravkah.md) — Когда человек поправил матч, тип или нумерацию — сохранять это как пример и подмешивать…
@@ -1,50 +0,0 @@
# Режиссёр в блоке «Распознано как» на странице загрузки
**Приоритет:** средний
На странице `/download/{id}` в блоке «Распознано как» режиссёр всегда показан
прочерком — поля просто нет:
`web/templates/partials/download_main.html:40` содержит захардкоженное
`<dt>Режиссёр</dt><dd><span class="faint">—</span></dd>`.
Экран ревью режиссёра уже выводит (`internal/httpapi/review.go:49/122`,
`review_source_block.html:59`) — это сделано в change про слоистое разрешение
полей display_name; страницу загрузки он не тронул.
Данные для вывода есть: `Plan.Director` (`internal/recognize/recognize.go:91`)
персистится в JSON-колонке `recognition.plan`, а страница загрузки уже получает
эффективный план через `Reviewer.ReviewData(...)`
(`internal/httpapi/download.go:89`) — `rd.Plan` уже с наложенными override
(`internal/worker/review.go:987`, `:1271`).
## Развилка (решить до кода)
`rd.Plan.Director` — это слой «override → распознавание+матч», **без слоя
контекста**. Полное слоистое разрешение живёт в неэкспортируемом
`effectiveDisplayName(d, plan)` (`internal/worker/review.go:1118`, fallback
`plan.Director → ctxf.Director` на `:1127-1130`) и отдаёт готовую строку, а не
поля.
- **A (минимум, ~3 строки):** поле `Director` в `downloadDetailView`
(`internal/httpapi/download.go:37`) + присвоение `view.Director =
rd.Plan.Director` рядом с `:143`. Но при распознавании без матча режиссёр из
контекста не покажется, хотя в заголовке страницы (display name) он уже есть →
видимая нестыковка «в заголовке есть, в поле прочерк».
- **B (правильный):** вынести слоистое разрешение в экспортируемое
`naming.Fields`/`EffectiveFields(d, plan)`, переиспользовать в
`effectiveDisplayName` и в **обоих** билдерах вью. Чинит заодно ту же дыру в
`internal/httpapi/review.go:122`.
Рекомендация — B: A оставляет ровно тот баг, который заводили.
## Спеки
- `openspec/specs/web-ui/spec.md` — про блок «Распознано как» на `/download/{id}`
режиссёра нет вообще → нужна дельта.
- `openspec/specs/review/spec.md:255-289` — сценарий «Режиссёр показан, когда
доступен» ограничен экраном ревью и формулировкой «из подтверждённого
матча/кандидата»; вариант B потребует правки формулировки.
- `openspec/specs/recognition/spec.md:62-69` — режиссёр опционален и best-effort,
пустое значение штатно.
Связано: [[ubiquitous-language-slovar]].