Files
T
avandClaude Opus 4.8 512567c8ba Рефакторинг границ capabilities: цепочка загрузка→матч→ревью→раскладка (openspec)
Привёл набор 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>
2026-07-03 21:17:51 +03:00

7.9 KiB
Raw Blame History

ADDED Requirements

Requirement: Пред-парс имени релиза

Перед вызовом LLM система SHALL выполнять дешёвый пред-парс имени торрента (go-ptn): извлекать черновые название, год, сезон, серию и качество. Результат пред-парса SHALL использоваться как вспомогательный сигнал в промпте и как сторона проверки согласованности при решении auto/review, но НЕ SHALL считаться итоговым распознаванием.

Scenario: Пред-парс даёт черновые поля

  • WHEN на вход распознавания поступает имя релиза Fargo.S02.2015.WEB-DL.1080p
  • THEN пред-парс возвращает черновые title, year, season, quality
  • AND эти значения передаются в промпт LLM как подсказка

Requirement: Разбор сигналов LLM в структурированный план

Система SHALL передавать LLM недоверенные сигналы (имя торрента, дерево файлов с размерами, текстовый контекст и накопленные подсказки, пред-парс) и получать структурированный план в схеме: type (movie|series), title, original_title, year, provider_hint, files[] и confidence. Каждый элемент files[] SHALL нести src, role (main|episode|subtitle|extra|sample|ignore) и, для сериала, per-file season/episode (отдельного скалярного season быть SHALL NOT — так выражаются мультисезонные паки и спецвыпуски). План SHALL приниматься только если каждый files[].src совпадает с реальным файлом торрента.

Scenario: План сериала с per-file нумерацией

  • GIVEN сезон-пак из 10 видеофайлов
  • WHEN LLM возвращает план
  • THEN type = series, а каждый видеофайл несёт свои season/episode

Scenario: Несуществующий src отклоняется

  • GIVEN ответ LLM, где files[].src не совпадает ни с одним файлом торрента
  • WHEN план разбирается
  • THEN такой план не принимается как валидный

Requirement: Провайдер LLM за абстракцией со структурированным выводом

Доступ к LLM SHALL быть за интерфейсом с выбором реализации по полю [llm].type (первый тип — openai-compat). Система SHALL запрашивать JSON-режим (response_format: {"type":"json_object"}), срезать ```-ограждения и валидировать ответ в Go против схемы плана. При ошибке разбора система SHALL ретраить до [llm].max_retries, передавая модели саму ошибку и схему. Если после ретраев ответ не разобран, задача SHALL уходить в review (НЕ в failed) с причиной «ответ LLM не разобран».

Scenario: Неразобранный ответ уходит в review

  • GIVEN LLM, чей ответ не проходит валидацию схемы после всех ретраев
  • WHEN завершается распознавание
  • THEN задача переходит в review с причиной «ответ LLM не разобран»
  • AND задача НЕ переходит в failed

Requirement: Модель уверенности и решение auto/review

Система SHALL раскладывать автоматически (без review) только при выполнении ВСЕГО: (1) подтверждённый единичный сильный матч в базе (metadata-match) с provider_id; (2) структурная валидация без предупреждений (фильм — ровно один основной видеофайл; сериал — число серий бьётся с базой, нумерация S·E консистентна); (3) согласованность пред-парса и LLM по типу/названию/году. Иначе задача SHALL уходить в review с явной причиной. Самооценку LLM (confidence) система SHALL учитывать лишь как вспомогательный сигнал, НЕ как единственный гейт.

Scenario: Нет матча в базе — всегда review

  • GIVEN план без подтверждённого матча в базе (база выключена или матча нет)
  • WHEN принимается решение auto/review
  • THEN задача уходит в review, авто-раскладка не делается

Scenario: Матч и чистая валидация — авто

  • GIVEN подтверждённый единичный матч, чистая структурная валидация и согласованность сигналов
  • WHEN принимается решение
  • THEN допускается авто-раскладка (при отсутствии force_review)

Requirement: Роли файлов на краях раздачи

Система SHALL относить семплы, «экстра» и мусор к роли ignore (эвристики размер/ имя + LLM), а внешние субтитры (.srt, .ass, пары VobSub .idx+.sub) — привязывать к соответствующему видео. Любую неоднозначность нумерации (дыры, дубли, спорные спецвыпуски) система SHALL эскалировать в review, а не разрешать молча.

Scenario: Семпл помечается ignore

  • GIVEN раздача с файлом sample.mkv малого размера
  • WHEN строится план
  • THEN этот файл получает роль ignore и в раскладку не попадает

REMOVED Requirements

Requirement: Сверка с базой по нескольким названиям

Reason: Работа с внешними базами метаданных — отдельное поведение; выделена в capability metadata-match. Migration: Требование перенесено без изменений в metadata-match (см. specs/metadata-match).

Requirement: Локаль запроса к TMDB

Reason: Относится к работе с метабазой (TMDB), выделенной в metadata-match. Migration: Требование перенесено без изменений в metadata-match.

Requirement: Нормализация названий при сравнении

Reason: Нормализация — часть сверки с метабазой, выделенной в metadata-match. Migration: Требование перенесено без изменений в metadata-match.

Requirement: Кандидат несёт URL для внешней проверки

Reason: Кандидат — сущность метабазы; контракт кандидата относится к metadata-match. Migration: Требование перенесено без изменений в metadata-match.