Привёл набор capabilities в OpenSpec к цепочке обработки, чтобы имя capability отвечало одному поведению. Чисто по спекам, код и поведение системы не меняются. Change refactor-capability-boundaries (архивирован): - recognition разделён на recognition (разбор LLM) + metadata-match (сверка с базами) - review выделен из web-ui + мигрирован из docs/specs/review-ux.md - новые capability из docs/specs: file-layout, download-tracking, notifications - identity очищен до инфра-id; приём (инфохэши, дедуп, ядро приёма) — в ingest - уведомление о рассинхроне перенесено из state-reconciliation в notifications - дубль владения путём и безопасного undo оставлен в state-reconciliation Итог: 11 capabilities, openspec validate --strict проходит (+37/−11 требований). Источник истины по мигрированным темам переехал в openspec/specs (шапки в docs). Снят пункт беклога «Пересмотр набора capabilities». Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
8.4 KiB
ADDED Requirements
Requirement: Сверка с базой по нескольким названиям
При сверке плана с включёнными базами метаданных система SHALL искать по
нескольким названиям в порядке убывания силы ключа: сначала по
original_title, затем по локализованному title, затем по provider_hint.
Поиск SHALL останавливаться, как только очередной запрос дал единичный
сильный матч (ровно один кандидат с совпадением названия и года). Запрос с
названием, нормализованно совпадающим с уже выполненным, система SHALL
пропускать, чтобы не обращаться к базе повторно с тем же ключом.
Кандидаты для ручного выбора в review система SHALL собирать из всех
выполненных заходов с дедупликацией по provider:id и общим потолком.
Scenario: Иностранный фильм находится по оригинальному названию
- GIVEN план с
title«Тёмный рыцарь»,original_title«The Dark Knight», год 2008 - WHEN выполняется сверка с базой
- THEN первый запрос идёт по «The Dark Knight»
- AND при единичном сильном матче дальнейшие запросы (по
title,provider_hint) не выполняются
Scenario: Фолбэк на локализованное название
- GIVEN план, для которого запрос по
original_titleне дал единичного сильного матча - WHEN продолжается сверка
- THEN выполняется запрос по локализованному
title - AND при отсутствии матча и там — запрос по
provider_hint
Scenario: Дублирующий запрос пропускается
- GIVEN план, у которого
original_titleнормализованно совпадает сtitle - WHEN выполняется сверка
- THEN база запрашивается этим названием один раз, повторный заход по
titleне делается
Requirement: Подтверждение матча и каноническое имя
При единичном сильном матче система SHALL брать из записи базы официальный
provider (tmdb|tvdb|tvmaze) и provider_id, а также каноническое название
и год, и подменять ими соответствующие поля плана (для сериала — с учётом внешнего
тега TVDB/IMDb из externals, идущего в имя папки). Матч SHALL считаться
подтверждённым только при ровно одном сильном кандидате; при нуле или нескольких
кандидатах подтверждённого матча быть SHALL NOT (авто-раскладка не разрешается,
кандидаты уходят в review). Работа с базами опциональна: при выключенных базах
сверка не выполняется и подтверждённого матча нет.
Scenario: Единичный матч даёт id и каноническое имя
- GIVEN поиск вернул ровно одного сильного кандидата TMDB для фильма
- WHEN матч подтверждается
- THEN план получает
provider=tmdb,provider_id, каноническое название и год
Scenario: Несколько кандидатов — матч не подтверждён
- GIVEN поиск вернул более одного подходящего кандидата
- WHEN оценивается матч
- THEN подтверждённого матча нет, кандидаты собираются для выбора в review
Requirement: Локаль запроса к TMDB
Запрос поиска к TMDB SHALL передавать параметр language, по умолчанию
ru-RU, со значением, настраиваемым конфигом [metadata.tmdb].language.
Это влияет только на локализованное поле Title/Name; поле
original_title/original_name остаётся на языке оригинала, поэтому
оригинальная сторона сравнения не затрагивается.
Scenario: Локализованный заголовок приходит по-русски
- GIVEN TMDB включён,
languageне задан в конфиге - WHEN выполняется поиск фильма с русской локализацией
- THEN запрос содержит
language=ru-RU - AND в кандидате
Titleприходит на русском, аOriginalTitle— на языке оригинала
Requirement: Нормализация названий при сравнении
Нормализация названий для гейта сильного матча SHALL сводить букву ё к е,
чтобы написания, различающиеся только ё/е, считались одним названием.
Scenario: «Тёмный» и «Темный» совпадают
- GIVEN план с названием «Тёмный рыцарь» и кандидат базы «Темный рыцарь»
- WHEN сравниваются нормализованные названия
- THEN они считаются совпадающими
Requirement: Кандидат несёт URL для внешней проверки
Каждый кандидат внешней базы метаданных (metadata.Candidate) SHALL нести
поле URL — ссылку на страницу элемента (фильма/сериала) на сайте
провайдера. URL SHALL формироваться клиентом провайдера при поиске
(Search) и сохраняться в таблице metadata_candidate. Отображение этой
ссылки на экране ревью — забота review/web-ui, не данного требования.
Формат URL для каждого провайдера:
- TMDB:
https://www.themoviedb.org/movie/{id}(фильм) илиhttps://www.themoviedb.org/tv/{id}(сериал) — тип контента известен из запросаQuery.Type - TVDB:
https://www.thetvdb.com/dereferrer/series/{id} - TVMaze:
https://www.tvmaze.com/shows/{id}— URL SHALL использовать нативный id TVMaze, а не внешний тег (TVDB/IMDb), чтобы ссылка вела на TVMaze-страницу
Scenario: Кандидат TMDB с корректной ссылкой
- GIVEN TMDB найден кандидат-фильм с id
603(«Матрица») - WHEN клиент TMDB формирует Candidate
- THEN
URL=https://www.themoviedb.org/movie/603
Scenario: Кандидат TVMaze с нативной ссылкой
- GIVEN TVMaze найден сериал с id
169(«Фарго»), внешний тег — TVDB id269613 - WHEN клиент TVMaze формирует Candidate
- THEN
URL=https://www.tvmaze.com/shows/169 - AND
TagProvider/TagIDостаютсяtvdb/269613(тег папки Jellyfin не меняется)
Scenario: URL сохраняется в БД
- GIVEN результат поиска с кандидатами
- WHEN кандидаты сохраняются в таблицу
metadata_candidate - THEN значение
urlSHALL быть записано в колонкуurl - AND при последующей загрузке данных ревью url доступен без повторной генерации