# Сигнал Jellyfin после отката и удаления файлов **Приоритет:** средний Сейчас пересканирование Jellyfin шлётся **только** при входе в `done`. После отката (`reverted`) или удаления (`deleted`) хардлинки сняты, а Jellyfin продолжает показывать записи с битыми путями до следующего скана по расписанию. Интеграция уже есть целиком, клиент писать не надо: - `internal/jellyfin/jellyfin.go` — клиент, `RefreshLibraries()` (`:76`) → `POST /Library/Refresh`. Тесты — `internal/jellyfin/jellyfin_test.go`. - Конфиг: `internal/config/config.go:99-107` (`Jellyfin{Enabled,URL,APIKey,Proxy,Timeout}`), валидация `:305-308`, пример `config.example.toml:59-64`. - Проводка: `cmd/jellybit/serve.go:137-152` → `wrk.SetScanner(jf)`; интерфейс `internal/worker/worker.go:171-176`. Точка правки — гейт в `transitionErr` (`internal/worker/worker.go:846-852`): `if w.scanner != nil && state == store.StateDone`. Оба пути удаления уже проходят через ту же `transition`: `Undo()` (`internal/worker/review.go:535` → `:574`) и `Delete()` (`:601` → `:657`). То есть база правки = расширить условие; фоновый ctx, `capFileLayout`-скоуп и неблокирующая горутина переиспользуются как есть. ## Что учесть 1. **`StateDeleted` приходит не только от пользователя.** `internal/worker/reconcile.go:30-41` `deriveState()` возвращает `StateDeleted` при `!sourcePresent && !targetPresent` (авто-сверка). Скан там формально уместен, но это уже не «после удаления файлов нами». Решить: гейтить по состоянию (просто, ловит и reconcile) или по факту снятия ссылок (точнее — в `Undo`/`Delete` есть счётчик снятого, но тогда триггер уезжает из единого чекпоинта `transitionErr`). 2. **`StateTargetMissing`** (`reconcile.go:35`) — цель пропала мимо нас. Кандидат по той же логике, надо явно решить, входит или нет. 3. **`Dismiss` идёт мимо чекпоинта:** `internal/worker/worker.go:944` пишет состояние напрямую через `w.store.SetDownloadState`, минуя `transitionErr`. Для dismiss это корректно (файлы не трогаются), но если вешать скан на `cancelled` — не сработает. 4. `Delete()` при ошибке qBittorrent (`internal/worker/review.go:650-652`) возвращается **до** `transition` → ссылки сняты, скана не будет. Идемпотентный повтор дожмёт, но окно рассинхрона есть. 5. Порядок верный: `layouter.Undo` отрабатывает до `transition`, так что скан увидит уже снятые ссылки. ## Спеки — здесь дыра Про Jellyfin-скан в `openspec/specs/` **нет ни слова** (грепом `Library/Refresh|RefreshLibraries|пересканир` — ноль попаданий). Живёт только в рукописных доках: `docs/specs/architecture.md:182-196` («Пересканирование Jellyfin», прямо сказано «После успешной раскладки (вход в `done`)»), `docs/specs/workflow.md:100-102`. → Задача тянет дельту в `file-layout` (пакет `jellyfin` отнесён к этой capability — `architecture.md:44`, код скоупится `capFileLayout`) + правку `docs/specs/architecture.md:182` и `docs/specs/workflow.md:100`, где формулировка «при входе в done» станет неверной. Тесты: `internal/worker/review_test.go:88` `TestScanner_FiresOnDone` + `recordingScanner` (`:81-86`). Негативных тестов «не стреляет на других состояниях» нет → расширение безопасно, но тесты на `reverted`/`deleted` надо дописать.