Files
jellybit/openspec/changes/archive/2026-07-08-review-readiness-preflight/proposal.md
T
avandClaude Opus 4.8 b1bca98738 Ревью: preflight готовности источника для команд ревью (MAJOR-5)
Команды ревью проверяли только наличие раздачи в qBittorrent, но не её
готовность. Недокачанную задачу можно припарковать в deferred, затем
«Распознать заново» → recognizing → авто-раскладка (Rerecognize/Refine/
SetType не ставят force_review) → хардлинки на неполные файлы. Даже ручной
Apply не имел preflight завершённости.

Вводим ensureSourceReady (classify(t.State)==classReady) вместо
ensureSourcePresent во всех командах, которым нужен источник (Relink/
Rerecognize/Refine/SetType), и inline-проверку класса в Apply — последний
рубеж перед хардлинками. Недокачанный источник → отдельный sentinel
ErrNotReady (409) с actionable-текстом «торрент ещё качается» в web и
Telegram, без reconcile (состояние deferred/review легитимно).

Change review-readiness-preflight заархивирован, дельта влита в
openspec/specs/review.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 16:40:49 +03:00

4.4 KiB
Raw Blame History

Why

Команды ревью, которым нужен источник, проверяют лишь наличие раздачи в qBittorrent (ensureSourcePresent), но не её готовность (файлы докачаны). Недокачанную задачу можно легально припарковать в deferred (граф допускает *→deferred), а затем «Распознать заново»: она уходит в recognizing, LLM видит имена ещё не докачанных файлов (qBittorrent отдаёт их до завершения) и при уверенном матче срабатывает авто-раскладка (Rerecognize/Refine/SetType не ставят force_review) — хардлинки создаются на неполные файлы, задача уходит в done, Jellyfin сканирует половину. Даже ручной review → Применить не имеет preflight завершённости. Это обходит смысл состояния completed («готовность только когда файлы на месте») и портит целостность медиатеки — самый опасный из выявленных дефектов жизненного цикла.

What Changes

  • Ввести синхронный preflight готовности источника ensureSourceReady: источник должен не только присутствовать, но и быть в готовом к раскладке классе (classify(t.State) == classReady).
  • Заменить ensureSourcePresent на ensureSourceReady во всех командах ревью, которым нужен источник: Rerecognize, Refine, SetType, Relink. Единый инвариант — команда, вводящая задачу в активную обработку (recognizing) или в раскладку, работает только с готовым источником.
  • Добавить ту же проверку готовности в Apply (сейчас он берёт торрент inline и не смотрит на его класс) — последний рубеж перед созданием хардлинков.
  • Недокачанный источник → отказ отдельным sentinel ErrNotReady (409) с actionable-сообщением «торрент ещё качается», без reconcileToReality: состояние deferred/review/… легитимно, приводить к реальности нечего — просто не даём действовать. Транспорты (HTTP/htmx и Telegram) показывают конкретный текст, а не генерик «действие недоступно».

Capabilities

New Capabilities

Modified Capabilities

  • review: команды ревью, которым нужен источник, SHALL проверять его готовность (файлы докачаны), а не только наличие; недокачанный источник → отказ без разрушающих действий.

Impact

  • Код: internal/worker/errors.go (новый sentinel ErrNotReady), internal/worker/reconcile.go (новый ensureSourceReady, удаление ensureSourcePresent), internal/worker/review.go (замена вызовов в Rerecognize/Refine/SetType/Relink, добавление проверки в Apply).
  • Транспорты: internal/httpapi (classifyErr — кейс ErrNotReady → 409 с текстом «торрент ещё качается»), internal/tgbot (ветка ErrNotReady в обработчике действий). Пользователь видит конкретную причину вместо тихой авто-раскладки неполных файлов; трансляция — на внешней границе.
  • Тесты: internal/worker/review_test.go — сценарии недокачанного источника для затронутых команд.
  • Данные: устраняет создание хардлинков на неполные файлы (целостность медиатеки Jellyfin).