## 1. Код

- [x] 1.1 В `processCatched` (`internal/worker/worker.go`), на обычном пути
  добавления, ПОСЛЕ вывода имени и НЕПОСРЕДСТВЕННО перед `qbt.Add`: под `w.mu`
  перечитать запись и, если `state != catched`, `add` не делать и загрузку
  пропустить (D1)
- [x] 1.2 Там же (вне `w.mu`) добавить свежий листинг присутствия любого из
  infohash загрузки в qBittorrent перед `add` (переиспользовать `qbt.Torrents`);
  при присутствии — `add` не делать, пропустить (усыновит следующий тик); при
  СБОЕ листинга — `add` не делать, `WARN`, повтор на следующем тике (D2, Б1)
- [x] 1.3 При неуспехе `PromoteCatched` после успешного `add` — под `w.mu`
  перечитать состояние: только если `state != catched` (подтверждённая отмена) —
  удалить добавленный торрент с данными `qbt.Delete(ctx, HashList, true)`; `WARN`
  об оставленном/удалённом торренте; `ERROR` при сбое удаления. Если `state ==
  catched` (транзиентный сбой БД) или re-read упал — НЕ удалять, `WARN`
  «promote failed, will retry» (D3, Б2). Решение по состоянию, не по тексту
  ошибки (см. errors.md)
- [x] 1.4 Убедиться, что путь уборки достижим только после подтверждённого
  отсутствия перед `add` (негативный инвариант «удаляем только своё»)

## 2. Тесты

- [x] 2.1 Обновить `TestProcessCatchedCancelledDuringAddSkipsPromote`: отмена во
  время namer → `qbt.Add` НЕ вызывается (re-read перед add), состояние остаётся
  `cancelled` (было: Add вызывался)
- [x] 2.2 Новый тест: отмена в окне ПОСЛЕ `add` (hook на `Add`, ставящий
  `cancelled`) → `qbt.Delete` вызван с `deleteFiles=true` по infohash загрузки,
  состояние `cancelled`
- [x] 2.3 Новый тест (негативный инвариант): infohash появился в qBittorrent во
  время namer (hook на namer) → перед `add` листинг видит присутствие → `qbt.Add`
  НЕ вызывается, `qbt.Delete` НЕ вызывается (чужие данные не трогаем)
- [x] 2.4 Новый тест (Б2): сбой `PromoteCatched` при `state == catched`
  (транзиентная ошибка БД, без отмены) → торрент НЕ удаляется (`qbt.Delete` не
  вызван)
- [x] 2.6 Новый тест (Б1, safety-critical): свежий листинг перед `add` упал
  (второй вызов `Torrents`) → `Add`/`Delete` НЕ вызваны, остаётся `catched`
- [x] 2.5 Регрессия: штатный успех (нет отмены) по-прежнему добавляет и
  промоутит (`TestProcessCatchedAddsToQbit`); усыновление присутствующего и сбой
  листинга тика (`TestProcessCatchedListErrorKeepsCatched`) — без изменений

## 3. Спека

- [x] 3.1 MODIFIED-требование «Добавление пойманной загрузки в qBittorrent» в
  `download-tracking`; `openspec validate cancel-during-add-cleanup --strict`
