Команды ревью проверяли только наличие раздачи в 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>
5.4 KiB
MODIFIED Requirements
Requirement: Команды ревью и их эффекты
Экран ревью SHALL предоставлять команды: Применить (создать хардлинки по
эффективному плану), Уточнить (добавить подсказку → перераспознать),
Распознать заново (повторный прогон без новой подсказки), Игнор файла,
Позже (deferred), Отклонить (cancelled), Undo (снять созданные
ссылки → reverted) и Привязать заново (из
reverted/cancelled/target_missing → перераспознавание с ручным
подтверждением). Экран ревью MUST NOT содержать команду переключения типа
movie↔series: тип показывается read-only, а его корректировка выполняется
мягкой подсказкой через Уточнить. Команды из любого транспорта SHALL
сериализоваться worker'ом под единой блокировкой; применяется последняя валидная
команда.
Команды, которым нужен источник (Применить, Уточнить, Распознать
заново, Привязать заново, а также фиксация типа), SHALL синхронно (без
дебаунса) проверять перед действием, что источник не только присутствует в
qBittorrent, но и готов к раскладке — раздача в готовом классе состояния
(uploading/stalledUP/pausedUP/… с учётом различий имён qBit v4/v5),
т.е. файлы докачаны. Если источник ещё качается (любое downloading-подобное
или переходное moving/checking состояние), команда SHALL отказывать с
конфликтом и причиной «торрент ещё качается», НЕ создавая хардлинки и НЕ меняя
состояние загрузки (её нахождение в review/deferred/… легитимно, приводить
к реальности нечего). Отсутствие источника в qBittorrent SHALL по-прежнему
приводить состояние к реальности (orphaned/deleted) и отказывать. Так
недокачанная задача не может пройти через перераспознавание в авто-раскладку
или ручное применение и захардлинкать неполные файлы, обойдя финальность
состояния completed.
Scenario: Применение создаёт раскладку
- GIVEN загрузка в
reviewс эффективным планом - WHEN пользователь выбирает «Применить»
- THEN создаются хардлинки по плану, задача переходит к раскладке
Scenario: Отклонить и привязать заново
- GIVEN загрузка в
review - WHEN пользователь «Отклонить», затем «Привязать заново»
- THEN задача уходит в
cancelled, а затем снова на распознавание с ручным подтверждением (авто-раскладка не делается)
Scenario: Тип не переключается кнопкой
- GIVEN загрузка в
reviewс распознанным типом - WHEN пользователь открывает экран ревью
- THEN отдельной команды/кнопки переключения movie↔series на экране нет
- AND тип показан read-only в инфо-части выбранного источника
Scenario: Недокачанный источник отклоняет перераспознавание
- GIVEN загрузка припаркована в
deferred, а её раздача в qBittorrent ещё качается (downloading, файлы не докачаны) - WHEN пользователь выбирает «Распознать заново» (или «Уточнить»/«Привязать заново»/фиксацию типа)
- THEN команда отклоняется с конфликтом и причиной «торрент ещё качается»
- AND загрузка остаётся в
deferred, хардлинки не создаются, авто-раскладка не запускается
Scenario: Недокачанный источник отклоняет ручное применение
- GIVEN загрузка в
review, чья раздача в qBittorrent ещё качается - WHEN пользователь выбирает «Применить»
- THEN команда отклоняется с конфликтом «торрент ещё качается», хардлинки на неполные файлы не создаются, состояние загрузки не меняется