# download-tracking Specification ## ADDED Requirements ### Requirement: Пропажа источника у активной загрузки Поллинг активных загрузок (`downloading`) SHALL обнаруживать пропажу источника: если раздача, совпадающая с любым из известных хешей загрузки, отсутствует в выдаче qBittorrent, система SHALL применять **тот же дебаунс пропажи источника**, что и сверка рассинхрона (счётчик `source_miss_count`, порог `[worker].source_missing_threshold`; см. `state-reconciliation` «Дебаунс пропажи источника»). Любое обнаружение раздачи SHALL сбрасывать счётчик. После `N` подряд идущих тиков без раздачи (`N = [worker].source_missing_threshold`) система SHALL переводить загрузку `downloading → failed` с `error_code` `source_gone` и уведомлять автора. До достижения порога загрузка SHALL оставаться в `downloading` (транзиентная недоступность qBittorrent, например рестарт демона, не должна ронять задачу). `source_gone` система SHALL трактовать как отдельную причину, отличную от `qbit_error` (реальная ошибка qBittorrent) и от `magnet_timeout`/`stalled` (наша нетерпеливость). Восстановлению сверкой (`reconcileRecovery`) `source_gone` подлежать SHALL NOT — удаление источника из qBittorrent намеренно, молча воскрешать задачу нельзя. Задача SHALL оставаться штатно восстановимой вручную (`Retry` заново отдаёт сохранённый источник в qBittorrent). Состояние `catched` этим правилом затрагиваться SHALL NOT: у пойманной загрузки раздачи в qBittorrent ещё нет по дизайну (см. «catched не считается пропажей раздачи»), а цикл активных загрузок листает только `downloading`. #### Scenario: Источник пропал у активной загрузки дольше порога - **GIVEN** загрузка в `downloading`, чья раздача удалена из qBittorrent - **WHEN** раздача отсутствует `source_missing_threshold` подряд идущих тиков - **THEN** загрузка переходит в `failed` с `error_code` `source_gone` - **AND** автор загрузки уведомляется #### Scenario: Кратковременная пропажа источника не роняет задачу - **GIVEN** загрузка в `downloading` - **WHEN** раздача отсутствует в qBittorrent меньше `source_missing_threshold` тиков подряд - **THEN** загрузка остаётся в `downloading` #### Scenario: Возврат раздачи сбрасывает счётчик - **GIVEN** загрузка в `downloading` с накопленными промахами источника (меньше порога) - **WHEN** раздача снова обнаружена в qBittorrent - **THEN** счётчик промахов сбрасывается в ноль и загрузка ведётся обычной сверкой состояния #### Scenario: source_gone не воскрешается сверкой - **GIVEN** загрузка в `failed` с `error_code` `source_gone` - **WHEN** её раздача снова появляется в qBittorrent и продвигается - **THEN** сверка восстановления её не трогает — задача остаётся в `failed` до ручного `Retry`