Команды ревью проверяли только наличие раздачи в 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>
4.4 KiB
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(новый sentinelErrNotReady),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).