## 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`