From 1d375f55ba7b0489fe1f829b1f588f4d2a931fd1 Mon Sep 17 00:00:00 2001 From: Anton Vakhrushev Date: Fri, 7 Aug 2026 15:17:29 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B7=D0=B0=D0=BA=D1=80=D1=8B=D1=82=D0=B0=20?= =?UTF-8?q?=D0=B7=D0=B0=D0=B4=D0=B0=D1=87=D0=B0=20tvdb-title-locale?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - вопрос о неподтверждённой форме ответа TVDB вынесен разведкой tvdb-search-response-live-check: закрытие задачи стёрло бы его вместе с файлом --- docs/tasks/BACKLOG.md | 1 + docs/tasks/SPRINT.md | 1 - .../items/tvdb-search-response-live-check.md | 72 +++++++++++++++++++ docs/tasks/items/tvdb-title-locale.md | 63 ---------------- 4 files changed, 73 insertions(+), 64 deletions(-) create mode 100644 docs/tasks/items/tvdb-search-response-live-check.md delete mode 100644 docs/tasks/items/tvdb-title-locale.md diff --git a/docs/tasks/BACKLOG.md b/docs/tasks/BACKLOG.md index 09b0d98..16acce5 100644 --- a/docs/tasks/BACKLOG.md +++ b/docs/tasks/BACKLOG.md @@ -24,6 +24,7 @@ - [✨ Переделать веб-UI в устанавливаемое PWA](items/web-ui-pwa.md) — текущий server-rendered UI функционален — PWA (устанавливаемое, удобное с телефона) это улучшение большого объёма, не блокер - [✨ Править на ревью маппинг «файл → серия» и раскладывать вручную при провале LLM](items/review-mapping-editor.md) — правка S·E, «нумеровать подряд» и ручной режим при полном провале LLM были запланированы объёмом Ф5 и не заведены задачей — в ревью сегодня можно только подсказать текстом - [✨ Заказать спекой крайние случаи именования: многофайловый фильм, редакции, двойная серия](items/naming-edge-cases.md) — стэкинг частей (part1/cd1), редакции [edition-…] и двойная серия SxxEyy-Eyy описаны нарративом, но в file-layout не заказаны — раскладка таких раздач не определена +- [🔬 Форма ответа поиска TheTVDB и семантика параметра language](items/tvdb-search-response-live-check.md) — форма ответа поиска TheTVDB принята по swagger 4.7.10 и живым прогоном не подтверждена — при иной форме разбор молча уходит в фолбэк, гейт зелёный, локализованное название не работает - [🔬 Канон нумерации серий и порядок у провайдера тега](items/episode-numbering-canon.md) — Косметика/редкость: порядок просмотра ок, но у тайтлов со спорным порядком (Бибоп) Jellyfin подтягивает не те подписи серий, если канон файлов ≠ дефолтный порядок провайдера тега - [🔬 Тексты и формат уведомлений в Telegram](items/telegram-messages-audit.md) — зонтичный проход по всем текстам бота: полнота карточек, единый язык, оформление; порождает под-задачи - [🔬 guessit как сервис-спутник](items/guessit-sidecar.md) — go-ptn слабее питоновского guessit — если точности пред-парса не хватит, завернуть guessit в сервис-спутник рядом с бинарём diff --git a/docs/tasks/SPRINT.md b/docs/tasks/SPRINT.md index e8cf8d6..5005351 100644 --- a/docs/tasks/SPRINT.md +++ b/docs/tasks/SPRINT.md @@ -8,6 +8,5 @@ ## Набор -- [✨ Брать у TVDB название на языке настройки и оригинальное название](items/tvdb-title-locale.md) — [general].language правит только TMDB и промпт LLM — TVDB отдаёт primary name, и при language=ru в карточку ревью и имя папки попадает 哪吒之魔童降世 вместо «Нэчжа» - [✨ Узаконить confidence-гейт авто-раскладки в спеке и сделать его выключаемым (дефолт 0.7)](items/auto-link-confidence-gate.md) — Решено (B): гейт оставляем как доп. проверку на ревью — выключаемый порог, дефолт 0.85→0.7, записать в спеку - [🐞 Тормозить опрос qBittorrent бэкоффом при недоступности и эскалировать устойчивый сбой](items/background-error-noise.md) — недоступный qBittorrent опрашивается каждые 5 с и даёт WARN на каждом тике: нужен экспоненциальный бэкофф до минутного потолка со сбросом по первому успеху и ERROR на устойчивой деградации diff --git a/docs/tasks/items/tvdb-search-response-live-check.md b/docs/tasks/items/tvdb-search-response-live-check.md new file mode 100644 index 0000000..d0b3afc --- /dev/null +++ b/docs/tasks/items/tvdb-search-response-live-check.md @@ -0,0 +1,72 @@ +# 🔬 Форма ответа поиска TheTVDB и семантика параметра language + +- **Тип:** research +- **Категория:** Ядро продукта +- **Зачем:** форма ответа поиска TheTVDB принята по swagger 4.7.10 и живым прогоном не подтверждена — при иной форме разбор молча уходит в фолбэк, гейт зелёный, локализованное название не работает +- **Теги:** goal:recognition-accuracy, sprint:2026-08-06 + +Задача `tvdb-title-locale` научила клиент TVDB брать локализованное название из +блока переводов ответа `/search` и заполнять `OriginalTitle` primary name'ом. Но +живым прогоном форма ответа не сверялась: `CLAUDE.md` → «Запреты» запрещает +ходить в боевые метабазы из отладочных прогонов и расходовать лимиты ключа. +Форма взята из публичной документации (swagger TheTVDB v4, версия `4.7.10`) и +записана в [docs/research/tvdb-search-translations.md](../../research/tvdb-search-translations.md) +как **условие, а не замер**. + +Разведка нужна потому, что ошибка предположения **не наблюдаема**: разбор уйдёт в +тотальный фолбэк, `Title` станет равен primary name, то есть исход побайтно +совпадёт с поведением до задачи. Гейт зелёный, карточка ревью прежняя, фича не +работает. Единственный след — DEBUG-строка «в выдаче не разобрался ни один блок +переводов». + +## Вопрос + +Какова реальная форма блока переводов в ответе `/search` TheTVDB v4 — карта +«трёхбуквенный код языка → название» или иная, — и правда ли параметр `language` +этого эндпоинта сужает выдачу по основному языку записи, а не выбирает перевод? + +## Куда ляжет ответ + +- [docs/research/tvdb-search-translations.md](../../research/tvdb-search-translations.md): + предположения заменяются наблюдениями с датой прогона, а строка «живым + прогоном не подтверждено» — результатом. Условие пересмотра там уже записано. +- Решение по трём развилкам, оставшимся от `tvdb-title-locale`: + 1. **Критерий приёмки про параметр языка в запросе.** Задача требовала, чтобы + запрос поиска содержал параметр языка из `[general].language`. При + реализации критерий отменён: по документации параметр — фильтр («Restrict + results to a specific primary language»), и его передача отсекла бы ровно + иноязычные записи, ради которых задача заводилась. Тест сейчас проверяет + обратное — что параметра нет. Критерий менял исполнитель, а не приёмщик; + нужно решение человека: переписать критерий под факт, отвергнуть решение + или подтвердить семантику прогоном и решить по факту. Рекомендация — + подтвердить прогоном, затем переписать критерий. + 2. **Форма блока `translations`.** Подтвердить карту и трёхбуквенность ключей + либо починить разбор под реальную форму. + 3. **Граница авто-раскладки сдвинулась в обе стороны.** Заполнение + `OriginalTitle` даёт кандидату TVDB два названия вместо одного. Логика + гейта не менялась, вход изменился: запись, которую отсекал иероглифический + primary name, теперь может пройти по переводу (review → авто), а две разные + записи могут совпасть с планом разными названиями (авто → review — + франшиза с одним русским названием и годами в пределах ±1). Рекомендация — + принять как есть: движение вниз ведёт к человеку, движение вверх и есть + польза задачи, и это ровно то, как уже работает TMDB. Альтернатива — + сравнивать у TVDB только по `OriginalTitle`, но тогда пропадает польза от + совпадения по переводу. + +## Рамки + +Оракул уже написан и лежит в репозитории — прогоняется вручную, человеком, под +своим ключом: + +``` +TVDB_API_KEY=… go test ./internal/metadata/ -run Integration -v +``` + +Он печатает `Title` и `OriginalTitle` для `Fargo` и для иноязычной записи +`Ne Zha` (movie 131155, primary name `哪吒之魔童降世`, русский перевод «Нэчжа»). +Расхождение `Title` и `OriginalTitle` у второй записи подтверждает форму; +совпадение означает, что перевод не доехал. + +Автоматическим прогоном разведка не делается: лимиты ключа беречь, в гейт этот +тест не заводить. Кода менять не требуется — исход разведки это запись; правка +разбора, если форма окажется иной, заводится отдельной задачей. diff --git a/docs/tasks/items/tvdb-title-locale.md b/docs/tasks/items/tvdb-title-locale.md deleted file mode 100644 index 9816067..0000000 --- a/docs/tasks/items/tvdb-title-locale.md +++ /dev/null @@ -1,63 +0,0 @@ -# ✨ Брать у TVDB название на языке настройки и оригинальное название - -- **Тип:** feature -- **Категория:** Ядро продукта -- **Зачем:** [general].language правит только TMDB и промпт LLM — TVDB отдаёт primary name, и при language=ru в карточку ревью и имя папки попадает 哪吒之魔童降世 вместо «Нэчжа» -- **Теги:** goal:recognition-accuracy - -Кандидат от TVDB начинает приходить с названием на языке `[general].language` -и с отдельно заполненным оригинальным названием — как это уже делает TMDB. - -Сегодня глобальная настройка до клиента TVDB не доезжает вовсе: -`TVDBConfig` (`internal/metadata/tvdb.go`) поля языка не имеет, `serve.go` -собирает провайдер без него, `Search` шлёт только `query`/`type`/`year`, а из -ответа разбирает единственное поле `name` — это primary name записи, то есть -название на языке оригинала. Блок переводов не читается, `OriginalTitle` TVDB -не заполняет вовсе, хотя это ось сравнения при матче. Наблюдаемый случай — -[movie 131155](https://www.thetvdb.com/movies/131155-): primary name -`哪吒之魔童降世`, русский перевод у записи есть («Нэчжа»), но до нас не доходит. - -Что сделать: - -- прокинуть локаль в `TVDBConfig` из `cfg.ContentLanguage()`, диалект вывести - внутри `tvdb.go` — знание диалекта принадлежит тому, кто на нём говорит - ([ADR решения 2 в архиве](../../../openspec/changes/archive/2026-07-24-content-language-switch/design.md)); -- разобрать переводы в выдаче поиска (точные имена полей — `name_translated` и - блок `translations`; форму сверить с живым API через `TVDB_API_KEY=… go test - ./internal/metadata/ -run Integration`, наугад не писать); -- фолбэк на primary name, когда перевода на нужный язык нет, — молчаливой - пустоты в `Title` быть не должно; -- заполнить `OriginalTitle` primary name'ом; -- заказать поведение спекой: требование «Локаль запроса к TMDB» - ([metadata-match](../../../openspec/specs/metadata-match/spec.md)) написано - только под TMDB — либо обобщается на провайдеров, либо получает соседа. - -## Затрагивает - -- `internal/metadata/tvdb.go` — `TVDBConfig` (поле языка), строка запроса - `Search`, разбор переводов и `OriginalTitle` в кандидате; -- `cmd/jellybit/serve.go` — сборка провайдера TVDB из конфига; -- `openspec/specs/metadata-match/spec.md` — требование «Локаль запроса к TMDB»: - обобщается на провайдеров либо получает соседа под TVDB; -- внешний контракт: поиск TVDB (`/search`) и его блок переводов — формат - сверяется живым прогоном под `TVDB_API_KEY`, наугад не пишется. - -## Критерии приёмки - -- Запрос поиска TVDB содержит параметр языка, выведенный из `[general].language` - (оракул: тест на `httptest`-сервере в `tvdb_test.go` — проверяет строку - запроса при `language = ru` и при незаданном, как это сделано для TMDB). -- При наличии перевода `Candidate.Title` приходит на языке настройки, при - отсутствии — равен primary name (оракул: два случая в одном табличном тесте на - фикстуре ответа). -- `Candidate.OriginalTitle` у TVDB непуст и равен primary name (оракул: тот же - тест; плюс интеграционный прогон за `TVDB_API_KEY` печатает оба поля). -- Дельта-спека `metadata-match` заказывает локаль TVDB и фолбэк на оригинал - (оракул: `openspec validate --strict`). - -## Рамки - -Матч и гейт авто-раскладки не трогаются — локализованное название косметическое, -сравнение идёт по оригинальному; менять из-за него поведение выборки нельзя. -Живой API дёргается только вручную под env-гейтом, лимиты ключа беречь. TVMaze -вне охвата — переводов не отдаёт.