Ревью: 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:
@@ -0,0 +1,56 @@
|
||||
## 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
|
||||
<!-- нет новых capability -->
|
||||
|
||||
### 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).
|
||||
Reference in New Issue
Block a user