Ревью: 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>
This commit is contained in:
av
2026-07-08 16:40:49 +03:00
co-authored by Claude Opus 4.8
parent a43adea723
commit b1bca98738
16 changed files with 475 additions and 41 deletions
-1
View File
@@ -22,7 +22,6 @@ Tududi (проект `jellybit`) больше **не** держит беклог
- [Ретеншн и очистка БД](retention-ochistka-bd.md) — Терминальные задачи (done/cancelled/failed/reverted), их попытки recognition с сырыми…
- [Eval-харнес распознавания (корпус кейсов + метрика точности)](eval-harness-raspoznavaniya.md) — Распознавание — ядро продукта, но смена модели или правка промпта сейчас вслепую…
- [Гейт дозаписи хешей в dedup-ветке CreateDownloadIfNoActive (F1)](review-f1-gate-dozapisi-heshey.md) — dedup-ветка дописывает все хеши в найденную задачу без гарда — риск инварианта ≤1 активной _(ревью 2026-07-08)_
- [Readiness-preflight: запрет авто-раскладки недокачанных файлов (MAJOR-5)](review-major5-readiness-preflight.md) — САМОЕ ОПАСНОЕ: авто-раскладка недокачанных файлов рвёт целостность библиотеки _(ревью 2026-07-08)_
- [Retry/stall семантика: сброс базиса таймаута + простой от начала, а не от возраста торрента (MAJOR-1, MAJOR-2)](review-major1-2-retry-stall.md) — таймаут и простой отсчитываются от возраста торрента, а не от начала загрузки _(ревью 2026-07-08)_
- [Восстановление zombie downloading при пропаже источника из qBittorrent (MAJOR-3)](review-major3-zombie-downloading.md) — торрент пропал из qBittorrent в downloading → задача вечный зомби, никто не двигает _(ревью 2026-07-08)_
@@ -1,11 +0,0 @@
# Readiness-preflight: запрет авто-раскладки недокачанных файлов (MAJOR-5)
**Приоритет:** высокий · **Теги:** review-2026-07-08, lifecycle, data-integrity
Ревью Fable 2026-07-08 (жизненный цикл). САМАЯ ОПАСНАЯ — целостность библиотеки. internal/worker/review.go (ensureSourcePresent проверяет присутствие источника, НЕ classify(t.State)==classReady).
Сценарий: задача на 40% в downloading → user «Позже» (deferred, легально: граф допускает *→deferred) → «Распознать заново» (Rerecognize) → ensureSourcePresent проходит (торрент есть) → recognizing → LLM видит имена файлов (qBit отдаёт до завершения) → при уверенном матче res.Decision.Auto && !forceReview (Rerecognize НЕ ставит force_review, только Relink ставит) → авто linking → хардлинки на НЕДОКАЧАННЫЕ файлы → done → Jellyfin сканирует половину. Даже ручной review→Apply не имеет preflight завершённости. Обходит состояние completed, чей смысл (download-tracking «Готовность только когда файлы на месте») — финальность.
Фикс: ensureSourceReady требует classify(t.State)==classReady для Rerecognize/Refine/SetType/Apply; иначе ErrConflict «торрент ещё качается».
Вердикт: полноценный change (новое требование preflight на readiness).