## 1. Preflight готовности источника - [x] 1.1 В `internal/worker/errors.go` добавить sentinel `var ErrNotReady = errors.New(...)` (отдельный от `ErrConflict`). - [x] 1.2 В `internal/worker/reconcile.go` добавить `ensureSourceReady(ctx, d, op)`: найти торрент через `torrentByInfohash`; нет источника → `reconcileToReality(false)` + `ErrConflict «источник удалён из qBittorrent»`; есть, но `classify(t.State) != classReady` → `ErrNotReady «op: торрент ещё качается»` без `reconcileToReality`. - [x] 1.3 Заменить `ensureSourcePresent` на `ensureSourceReady` в командах `Rerecognize`, `Refine`, `SetType`, `Relink` (`internal/worker/review.go`); удалить осиротевший `ensureSourcePresent`. - [x] 1.4 В `Apply` добавить проверку класса на уже полученном торренте (`classify(t.State) != classReady → ErrNotReady «торрент ещё качается»`), без второго запроса к qBittorrent. ## 2. Трансляция ошибки в транспортах - [x] 2.1 `internal/httpapi` `classifyErr`: кейс `errors.Is(err, worker.ErrNotReady) → 409, «торрент ещё качается, дождитесь докачки»` (отдельно от генерик-`ErrConflict`). - [x] 2.2 `internal/tgbot`: в обработчике callback-действий ветка `errors.Is(err, worker.ErrNotReady)` → сообщение «Торрент ещё качается…», иначе прежний `opErr(...)`. ## 3. Тесты - [x] 3.1 Тест: недокачанный источник (`downloading`-класс) отклоняет `Rerecognize`/`Refine`/`SetType`/`Relink` с `ErrNotReady`, состояние задачи не меняется, авто-раскладка не запускается. - [x] 3.2 Тест: недокачанный источник отклоняет `Apply` — хардлинки не создаются, состояние не меняется. - [x] 3.3 Тест: готовый источник (`classReady`) пропускает те же команды как раньше (регресс не сломан); отсутствие источника по-прежнему приводит к реальности и отказывает. - [x] 3.4 Тест транспорта: `classifyErr(ErrNotReady) == 409` с конкретным текстом (`internal/httpapi`). ## 4. Ревью и сверка - [x] 4.1 `task test` и `task lint` зелёные. - [x] 4.2 Ревью кода (второй чекпоинт) перед archive. - [x] 4.3 `openspec validate review-readiness-preflight --strict` зелёный; удалить `docs/backlog/review-major5-readiness-preflight.md` из беклога и строку из индекса (суть переехала в спеку).