# `addReq` не пересобирается из свежего `source_type` перед `Add` (окно namer'а) **Приоритет:** средний · **Теги:** review-2026-07-17, lifecycle Найдено аудитом capability **download-tracking** (сверка код↔спека после пачки lifecycle-задач). Пред-существующее, вне scope задачи F3/cancel-cleanup — T4 осознанно вынес это за рамки и задокументировал в своём design.md. ## Суть `processCatched` (`internal/worker/worker.go:442-517`) строит `addReq` из записи `cur`, перечитанной под замком на `:447-455`, **до** вызова namer'а (LLM, секунды, вне замка, `:463-478`). Затем на `:484-491` под замком перечитывается `before`, но `addReq` из него **не пересобирается** — проверяется только `state == catched`. Если апгрейд пойманной magnet-задачи до `.torrent` (`UpgradeCatchedMagnetToTorrent`, `internal/store/download.go:392`) отработает именно в окне namer'а (приём принял `.torrent` с тем же infohash, `state` остаётся `catched`), воркер добавит **magnet-ссылку из устаревшего снимка**, хотя в БД уже `source_type=torrent`. Спека (`openspec/specs/download-tracking/spec.md`, раздел про добавление по `source_type`) требует перечитывать `source_type` **под блокировкой переходов непосредственно перед добавлением** — сейчас это требование в окне namer'а нарушается. ## Насколько больно Ограниченно и самоисцеляемо: на закрытом трекере magnet без метаданных зависнет в `metaDL` → предохранитель `magnet_timeout` → `failed`; ручной `Retry` перечитает актуальный `source_type` и добьёт. Данные не страдают, инвариант «источник неприкосновенен» не задет. Окно узкое (апгрейд должен лечь ровно в LLM-вызов по тому же infohash). Поэтому средний, не высокий. ## Развилка (решить до кода) - **A — ужесточить код (соответствие букве спеки, закрыть окно):** после re-read `before` под замком (`:484`) пересобирать `addReq`/`hint` из `before`, если `source_type` изменился. Нюанс: `sourceAddParts` читает байты `.torrent` — это тяжёлый вызов, держать под замком нельзя (спека: тяжёлое — вне блокировки), плюс подсказка имени для `.torrent` иная (метаданные раздачи vs имя из magnet), т.е. при апгрейде корректно был бы и повторный namer. Не однострочник. - **B — смягчить спеку (принять реальность):** признать, что рациональ («не полагаться на снимок, снятый ранее вне блокировки») уже выполнен первым re-read под замком на `:447`, и переформулировать требование как «перечитывать `source_type` под блокировкой после тик-снимка», явно приняв узкое namer-окно как самоисцеляемое через `Retry`. Рекомендация — начать с B (дёшево, отражает фактическое осознанное поведение), A завести только если узкое окно окажется реальной болью в эксплуатации. ## Ссылки - `internal/worker/worker.go:442-517` — `processCatched` - `internal/store/download.go:392` — `UpgradeCatchedMagnetToTorrent` - `openspec/specs/download-tracking/spec.md` — требование про `source_type` - Тест `TestProcessCatchedReReadsSourceTypeUnderLock` покрывает апгрейд между тик-снимком и re-read, но **не** окно namer'а.