Files
jellybit/openspec/changes/archive/2026-07-17-defer-exclude-catched/tasks.md
T
avandClaude Opus 4.8 098695011f Жизненный цикл: Defer запрещён из пре-источникового catched (MAJOR-6)
Команда Defer гардила только IsTerminal() и потому принимала catched
(торрент ещё не добавлен в qBittorrent). Defer из catched уводил задачу
в лимбо → необратимый deleted: processCatched листает только catched и
больше её не подхватывал, а последующие команды через отсутствие
источника выводили deleted (ноль исходящих рёбер), хотя байты .torrent
лежат в download_torrent.

- Worker.Defer отклоняет catched с ErrConflict (транслируется в 409 /
  редирект с сообщением); прочие не-терминальные состояния, где раздача
  уже есть, принимает как раньше.
- Снято мёртвое ребро графа catched → deferred (allowedTransitions);
  инвариант «deferred из каждого не-терминального» уточнён: кроме
  пре-источникового catched. catched — единственное состояние без
  раздачи среди не-терминальных.
- Тесты: Defer из catched отклоняется и не меняет состояние; инвариант
  графа обновлён + негативная проверка ребра.
- OpenSpec: MODIFIED «Команды ревью и их эффекты» (review) с позитивным
  и негативным сценариями; change заархивирован, дельта влита в спеку.
- Беклог: закрыта review-major6-defer-catched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 21:39:01 +03:00

1.7 KiB

1. Код

  • 1.1 internal/worker/review.go — в Defer после GetDownload добавить гард: d.State == store.StateCatchedErrConflict с понятным сообщением (отложить можно только после добавления торрента в qBittorrent), не меняя состояние. Существующий гард IsTerminal() оставить.
  • 1.2 internal/store/download.go — убрать StateDeferred из исходящих StateCatched в allowedTransitions; уточнить комментарий инварианта deferred («из КАЖДОГО не-терминального» → «кроме пре-источникового catched»).

2. Тесты

  • 2.1 internal/worker/review_test.goDefer из catched возвращает ErrConflict, состояние остаётся catched; контроль — Defer из review по-прежнему уводит в deferred (существующий TestDefer).
  • 2.2 internal/store/transition_test.go — обновить инвариант deferred: легальная цель из каждого не-терминального состояния, КРОМЕ catched (и самопереход deferred); добавить проверку, что catched → deferred не легально.

3. Спека

  • 3.1 MODIFIED-требование «Команды ревью и их эффекты» в review; openspec validate --strict зелёный.

4. Проверка

  • 4.1 task test и task lint зелёные; существующие тесты worker/httpapi/store не сломаны.