diff --git a/docs/backlog/README.md b/docs/backlog/README.md index 40ae296..a3315a0 100644 --- a/docs/backlog/README.md +++ b/docs/backlog/README.md @@ -30,6 +30,9 @@ Tududi (проект `jellybit`) больше **не** держит беклог - [[идея] Сложные сериальные раздачи: все сезоны разом, паки, спецраскладки](slozhnye-serialnye-razdachi.md) — ИДЕЯ (проработать крайние случаи) - [Аниме с абсолютной нумерацией](anime-absolyutnaya-numeraciya.md) — Релизы аниме часто нумеруют серии сквозным числом (#137) без сезонов, а Jellyfin ждёт… - [Бэкап SQLite](backup-sqlite.md) — architecture +- [Сигнал Jellyfin после отката и удаления файлов](jellyfin-skan-posle-udaleniya.md) — Скан шлётся только на done; после reverted/deleted Jellyfin держит битые записи. Клиент и гейт готовы, но скана нет в openspec-спеках +- [Режиссёр в блоке «Распознано как» на странице загрузки](rezhisser-v-kartochke-zagruzki.md) — На /download/{id} режиссёр всегда прочерк (поля нет в шаблоне); экран ревью его уже выводит +- [Карточка информации о торренте вылезает за границу экрана на мобильном](mobilnaya-verstka-kv-infohash.md) — grid-blowout на .kv из-за неразрывного infohash — страница получает горизонтальный скролл - [Глубокий healthcheck и статус зависимостей](healthcheck-zavisimosti.md) — /healthz проверяет только сам сервис - [НФТ: масштаб до 100 одновременных загрузок (потолок — 1000)](masshtab-100-zagruzok.md) — Зафиксировать в НФТ ориентир 100/1000 загрузок + аудит узких мест (SQLite, воркер, поллинг) - [Обучение на правках человека (few-shot из прошлых ревью)](obuchenie-na-pravkah.md) — Когда человек поправил матч, тип или нумерацию — сохранять это как пример и подмешивать… @@ -40,6 +43,7 @@ Tududi (проект `jellybit`) больше **не** держит беклог ## Низкий +- [Кнопки выглядят как кнопки: `btn-ghost` и рассогласование весов](unifikaciya-knopok-btn-ghost.md) — «Откатить» неотличима от текста: btn-ghost прозрачен, аффорданс только на hover; плюс одно действие имеет разный вес в списке и на странице - [Ревью уведомлений в Telegram (аудит текстов и формата)](telegram-revyu-uvedomleniy.md) — зонтичный проход по всем текстам бота: полнота карточек, единый язык, оформление; порождает под-задачи - [Download id в Telegram моноширинным (code) для tap-to-copy](telegram-download-id-code.md) — слать id как `code`; требует включить parse mode (HTML) в send() + escape всех текстов - [Мгновенные обновления через SSE](sse-obnovleniya.md) — Живые обновления прогресса сейчас на htmx-поллинге (фаза 2 веб-UI) — просто и работает… diff --git a/docs/backlog/jellyfin-skan-posle-udaleniya.md b/docs/backlog/jellyfin-skan-posle-udaleniya.md new file mode 100644 index 0000000..725a460 --- /dev/null +++ b/docs/backlog/jellyfin-skan-posle-udaleniya.md @@ -0,0 +1,59 @@ +# Сигнал 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` надо дописать. diff --git a/docs/backlog/mobilnaya-verstka-kv-infohash.md b/docs/backlog/mobilnaya-verstka-kv-infohash.md new file mode 100644 index 0000000..fa54c67 --- /dev/null +++ b/docs/backlog/mobilnaya-verstka-kv-infohash.md @@ -0,0 +1,56 @@ +# Карточка информации о торренте вылезает за границу экрана на мобильном + +**Приоритет:** средний + +На узком экране блок «Информация о торренте» на `/download/{id}` выталкивает +страницу за вьюпорт — появляется горизонтальный скролл всей страницы. + +## Причина + +Grid-blowout на `.kv` из-за неразрывного infohash: + +- `web/templates/partials/download_main.html:83-86` — `