diff --git a/docs/todo.md b/docs/backlog.md similarity index 67% rename from docs/todo.md rename to docs/backlog.md index 011b56d..478f92e 100644 --- a/docs/todo.md +++ b/docs/backlog.md @@ -1,13 +1,13 @@ -# TODO +# Беклог -Конкретные задачи на будущее, ранжированные по приоритету. Это не план -реализации (он — в [drafts/roadmap.md](drafts/roadmap.md)) и не свалка -идей ([drafts/ideas.md](drafts/ideas.md)): сюда попадает то, что уже решили -сделать, но ещё не сделали. Принятое и реализованное переезжает в -`docs/specs`/`docs/adr`. +Единый список будущих задач по проекту: то, что уже решили сделать, и +идеи, которые ещё надо обдумать. Это не план реализации (он — в +[drafts/roadmap.md](drafts/roadmap.md)) и не источник истины: принятое и +реализованное переезжает в `docs/specs`/`docs/adr`. Приоритет — грубая оценка «ценность / стоимость», не обязательство к -порядку. +порядку. Спекулятивные пункты (ещё без решения «делаем») помечены +_(идея)_ — их сперва надо проработать. ## Высокий @@ -45,6 +45,32 @@ qBittorrent с файлами), подтверждение осознаннос [architecture.md](specs/architecture.md) → «Раскладка файлов», [workflow.md](specs/workflow.md). +### Ревью: выбор источника совпадения и предпросмотр + +Переработать страницу ревью так, чтобы показывать **все** совпавшие +результаты по метабазам списком и дать выбрать из них. Принцип: совпадение +есть **всегда** — мы лишь выбираем источник. Поэтому матч нейронки — это +отдельная строка в том же списке (наравне с кандидатами TMDB/TVDB), а не +особый режим. + +Возможности экрана: + +- список кандидатов из баз + строка «распознано нейронкой»; +- выбрать один кандидат, переключиться на другой, отменить матч с базой в + пользу нейронки; +- добавить кандидат вручную (по id/url базы), когда автопоиск промахнулся; +- при выборе/переключении — **предпросмотр полей** (название, режиссёр, + год) и **предпросмотр раскладки** (целевые пути) до применения. + +Развивает «показывать матч с записью метабазы» (web-сторона), пересекается +с «Расширенной информацией о загрузке» (детальный экран) и быстрым выбором +в Telegram. Веб остаётся точкой точных правок. + +Связано: [review-ux.md](specs/review-ux.md) (выбор кандидата, «без базы», +переключатель типа), [recognition.md](specs/recognition.md) (кандидаты +матча, провайдер-id), [«Улучшения UI: показывать матч»](#улучшения-ui-показывать-матч-с-записью-метабазы), +пакет `httpapi`. + ### Наблюдаемость: метрики и учёт стоимости LLM Сейчас единственное окно в систему — `slog`. Нет быстрых ответов на @@ -98,6 +124,33 @@ qBittorrent с файлами), подтверждение осознаннос ## Средний +### Главная: список загрузок вместо таблицы + +Переделать главную страницу из таблицы в **список** карточек. Для каждой +загрузки: название (как распознали при добавлении в qBittorrent), `infohash` +с кнопкой быстрого копирования, статус и кнопки действий. Контекст (исходное +сообщение/magnet) спрятать под спойлер или вынести на отдельный детальный +экран (см. «Расширенная информация о загрузке»). Естественно сочетается с +фильтром/поиском/пагинацией по мере роста БД. + +Связано: [«Расширенная информация о загрузке в web-UI»](#расширенная-информация-о-загрузке-в-web-ui), +[«Список загрузок: фильтр, поиск, пагинация»](#список-загрузок-фильтр-поиск-пагинация), +[review-ux.md](specs/review-ux.md), пакет `httpapi`. + +### Расширенная информация о загрузке в web-UI + +Отдельная страница просмотра одной загрузки — целиком отображение того, что +лежит в БД по задаче: актуальный статус (текущее состояние + лог переходов), +исходный контекст и magnet, распознанные данные и матч в метабазе (см. +«показывать матч»), а также **точная раскладка, если есть** — целевые пути и +созданные хардлинки. Помогает разбираться, когда что-то пошло не так, без +чтения логов сервера. Сюда же выносится контекст с карточки в списке +загрузок. + +Связано: [«Главная: список загрузок»](#главная-список-загрузок-вместо-таблицы), +[review-ux.md](specs/review-ux.md), [architecture.md](specs/architecture.md) +→ «Хранилище» (`download`/`recognition`/`file_link`), пакет `httpapi`. + ### Машина состояний на go-библиотеке Сейчас FSM реализована вручную в `worker`. Выбрать подходящую go-библиотеку @@ -139,16 +192,29 @@ qBittorrent с файлами), подтверждение осознаннос [jellyfin-layout.md](specs/jellyfin-layout.md) (раскладка, идемпотентность), [workflow.md](specs/workflow.md) (повторный прогон загрузки). -### Улучшения UI клиентов: показывать матч с записью метабазы +### Улучшения UI: показывать матч с записью метабазы Во всех транспортах (веб, Telegram) показывать, **с какой именно записью** метабазы (TMDB/TVDB) сматчилась загрузка: название, год, провайдер-id, ссылку. Сейчас результат распознавания непрозрачен — пользователь не видит, -к чему привязались, и не может быстро поймать ошибочный матч. +к чему привязались, и не может быстро поймать ошибочный матч. На web-стороне +развивается в полноценный выбор источника — см. [«Ревью: выбор источника +совпадения»](#ревью-выбор-источника-совпадения-и-предпросмотр). Связано: [review-ux.md](specs/review-ux.md), [recognition.md](specs/recognition.md) (матч в базе), [architecture.md](specs/architecture.md) → «Транспорты». +### Аниме с абсолютной нумерацией + +Релизы аниме часто нумеруют серии сквозным числом (`#137`) без сезонов, а +Jellyfin ждёт `SxxEyy`. Нужен пересчёт абсолютной нумерации в сезон/серию — +надёжнее всего через TVDB (там есть absolute order). Отдельный крайний +случай распознавания; на стороне ревью — веб-хелпер «absolute → S·E». + +Связано: [recognition.md](specs/recognition.md) (конвейер, сезон-паки), +[jellyfin-layout.md](specs/jellyfin-layout.md) (нумерация серий), +[review-ux.md](specs/review-ux.md) (крайние сценарии). + ### Добавление торрентов файлом/ссылкой — «единое окно» Поддержать источники помимо magnet: `.torrent`-файл и URL (отдаём их в @@ -204,24 +270,31 @@ qBittorrent, без исходящих запросов на пользоват верификации, но дешевле: учимся на уже собранных `hint`/`override`. Связано: [recognition.md](specs/recognition.md) (конвейер, промпт), -[«Многоступенчатая верификация»](#многоступенчатая-верификация-привязки-тема-для-размышления), +[«Многоступенчатая верификация»](#многоступенчатая-верификация-привязки-идея), [architecture.md](specs/architecture.md) → «Хранилище» (`hint`, `override`). ### Список загрузок: фильтр, поиск, пагинация Прямое следствие роста БД (см. «Ретеншн»): плоский список загрузок со временем становится непригоден. Нужны фильтр по состоянию, поиск по -названию и пагинация. Естественно ложится на экран расширенной информации. +названию и пагинация. Естественно ложится на список-карточки главной и на +экран расширенной информации. -Связано: [«Расширенная информация о загрузке в web-UI»](#расширенная-информация-о-загрузке-в-web-ui), +Частный случай как разумный дефолт: на главной **по умолчанию скрывать +загрузки в статусе `deleted`** (терминальные, удалённые из источника и +цели — шум в ленте), с переключателем/фильтром «показать всё». Маленькая +часть, может приехать раньше полноценного фильтра. + +Связано: [«Главная: список загрузок»](#главная-список-загрузок-вместо-таблицы), +[«Расширенная информация о загрузке в web-UI»](#расширенная-информация-о-загрузке-в-web-ui), пакет `httpapi`. ## Низкий -### Многоступенчатая верификация привязки (тема для размышления) +### Многоступенчатая верификация привязки _(идея)_ -Идея: несколько раз извлекать данные из раздачи и контекста разными -промптами, искать в метабазах, затем сводить результаты в общий вердикт +Несколько раз извлекать данные из раздачи и контекста разными промптами, +искать в метабазах, затем сводить результаты в общий вердикт (голосование/консенсус) — выше точность ценой нескольких вызовов LLM и запросов к базам. Требует проработки: когда включать, как мерджить расхождения, стоимость/латентность. @@ -229,21 +302,14 @@ qBittorrent, без исходящих запросов на пользоват Связано: [recognition.md](specs/recognition.md) (конвейер и модель уверенности). -### Расширенная информация о загрузке в web-UI - -Экран просмотра деталей одной загрузки: исходный контекст и magnet, лог -переходов состояний, распознанные данные и матч в метабазе (см. «показывать -матч»), целевые пути и созданные хардлинки. Помогает разбираться, когда -что-то пошло не так, без чтения логов сервера. - -Связано: [review-ux.md](specs/review-ux.md), пакет `httpapi`. - ### Выбор из нескольких находок метабазы в Telegram Когда распознавание даёт несколько подходящих кандидатов в метабазе, предлагать их в Telegram списком (кнопки) для ручного выбора, а не молча -брать первый/лучший. Веб остаётся точкой точных правок, бот — быстрый выбор -из готового короткого списка. +брать первый/лучший. Веб остаётся точкой точных правок (полный выбор +источника — см. [«Ревью: выбор источника +совпадения»](#ревью-выбор-источника-совпадения-и-предпросмотр)), бот — +быстрый выбор из готового короткого списка. Связано: [review-ux.md](specs/review-ux.md) (боты — быстрые действия, веб — точные правки), [recognition.md](specs/recognition.md) (кандидаты матча). @@ -268,6 +334,35 @@ qBittorrent, без исходящих запросов на пользоват Связано: [recognition.md](specs/recognition.md) (сверка с базой), пакеты `metadata`, `llm`. +### guessit как сервис-спутник _(идея)_ + +`go-ptn` слабее питоновского `guessit`. Если точности пред-парса не +хватит — завернуть `guessit` в крошечный HTTP-сервис (один файл, +поставляется рядом с бинарём jellybit) и спрашивать его на шаге +пред-парса. Сохраняет «доставку копированием»: два файла вместо одного. + +Связано: [recognition.md](specs/recognition.md) → «На будущее» (пред-парс). + +### Завершение загрузки через webhook _(идея)_ + +Сейчас завершение ловим поллингом qBittorrent раз в несколько секунд. +Альтернатива: «Run external program on torrent completion» в qBittorrent +дёргает эндпоинт jellybit. Реагирует быстрее, но связывает нас с конфигом +qBittorrent. Решим по опыту эксплуатации. + +Связано: [architecture.md](specs/architecture.md) → «Отслеживание загрузки», +пакет `worker`. + +### Авторизация веб-UI (на будущее) + +Решено для v1: без авторизации в доверенной LAN, опц. allowlist подсетей +(`http.trusted_subnets`) — как умеет qBittorrent. Если понадобится защита: +токен/Basic в самом приложении или вынос за reverse-proxy с +аутентификацией. + +Связано: [architecture.md](specs/architecture.md) → «Транспорты» (доступ к +веб-UI), пакет `httpapi`. + ### Современный Web-UI как PWA Переделать веб-интерфейс в современное PWA-приложение (устанавливаемое, diff --git a/docs/drafts/ideas.md b/docs/drafts/ideas.md deleted file mode 100644 index 45be2ca..0000000 --- a/docs/drafts/ideas.md +++ /dev/null @@ -1,42 +0,0 @@ -# Идеи и нерешённое - -Свалка мыслей на будущее. Ни к чему не обязывает; принятое переезжает в -specs/adr. - -## guessit как сервис-спутник - -`go-ptn` слабее питоновского `guessit`. Если точности пред-парса не -хватит — завернуть `guessit` в крошечный HTTP-сервис (один файл, -поставляется рядом с бинарём jellybit) и спрашивать его на шаге -пред-парса. Сохраняет «доставку копированием»: два файла вместо одного. - -## Аниме с абсолютной нумерацией - -Релизы аниме часто нумеруют серии сквозным числом (`#137`) без сезонов, а -Jellyfin ждёт `SxxEyy`. Нужен пересчёт абсолютной нумерации в -сезон/серию — надёжнее всего через TVDB (там есть absolute order). -Отдельный крайний случай распознавания. - -## Завершение загрузки через webhook - -Сейчас принято — поллинг qBittorrent раз в несколько секунд. -Альтернатива: «Run external program on torrent completion» в qBittorrent -дёргает эндпоинт jellybit. Реагирует быстрее, но связывает нас с конфигом -qBittorrent. Решим по опыту эксплуатации. - -## Нотификации о готовности - -Когда раскладка завершена (или нужен review) — уведомить: Telegram, -возможно ntfy/Apprise. Естественно ложится на Telegram-транспорт. - -## Доступ к веб-UI - -Решено для v1: без авторизации в доверенной LAN, опц. allowlist подсетей -(`http.trusted_subnets`) — как умеет qBittorrent. На будущее, если -понадобится защита: токен/Basic в самом приложении или вынос за -reverse-proxy с аутентификацией. - -## Повторный прогон распознавания - -Возможность переоткрыть загрузку, поправить контекст и перераспознать без -перекачивания — полезно, когда LLM ошибся, а файлы уже скачаны. diff --git a/docs/specs/architecture.md b/docs/specs/architecture.md index ca6796d..be7db30 100644 --- a/docs/specs/architecture.md +++ b/docs/specs/architecture.md @@ -61,7 +61,7 @@ reject / defer / undo) — команды к `worker`: (server-rendered). В v1 **без авторизации** (доверенная LAN). Поле `http.trusted_subnets` зарезервировано, но **пока не применяется**: деплой только в локальную сеть без доступа из интернета, поэтому - allowlist-middleware и авторизацию отложили — [drafts/ideas.md](../drafts/ideas.md). + allowlist-middleware и авторизацию отложили — [backlog.md](../backlog.md#авторизация-веб-ui-на-будущее). - **Telegram-бот** — переслать magnet/сообщение бота; текст становится контекстом. Доступ — по `telegram.allowed_user_ids` (пусто = запрет всем, fail-closed). Бот же шлёт **пинги** о входе в review/готовности. diff --git a/docs/specs/jellyfin-layout.md b/docs/specs/jellyfin-layout.md index 1d06ebc..9301c7c 100644 --- a/docs/specs/jellyfin-layout.md +++ b/docs/specs/jellyfin-layout.md @@ -94,4 +94,4 @@ inode общий — диск не дублируется. сезонам. - **Несколько аудиодорожек** — обычно внутри mkv, не наша забота. - **Аниме с абсолютной нумерацией** — пересчёт в S·E, отдельная проработка - ([drafts/ideas.md](../drafts/ideas.md)). + ([backlog.md](../backlog.md#аниме-с-абсолютной-нумерацией)). diff --git a/docs/specs/recognition.md b/docs/specs/recognition.md index 9e2145c..907e2bf 100644 --- a/docs/specs/recognition.md +++ b/docs/specs/recognition.md @@ -129,10 +129,10 @@ notes пояснения, неоднозначности 00`), двойные серии (`SxxEyy-Eyy`) — через per-file season/episode; любая неоднозначность → review. - Аниме с абсолютной нумерацией — отдельный крайний случай, см. - [drafts/ideas.md](../drafts/ideas.md). + [backlog.md](../backlog.md#аниме-с-абсолютной-нумерацией). ## На будущее `go-ptn` слабее питоновского `guessit`. Если точности пред-парса не хватит — завернуть `guessit` лёгким сервисом-спутником (один файл рядом с -бинарём). См. [drafts/ideas.md](../drafts/ideas.md). +бинарём). См. [backlog.md](../backlog.md#guessit-как-сервис-спутник-идея). diff --git a/docs/specs/review-ux.md b/docs/specs/review-ux.md index e627f82..6469b60 100644 --- a/docs/specs/review-ux.md +++ b/docs/specs/review-ux.md @@ -109,7 +109,7 @@ Telegram = одобрить / подсказать / выбрать кандид provider-id и каноническое имя). - **База пустая (рус/аниме)** → «без базы» или ручной id/url. Аниме с абсолютной нумерацией → веб-хелпер «absolute → S·E» (см. - [drafts/ideas.md](../drafts/ideas.md)). + [backlog.md](../backlog.md#аниме-с-абсолютной-нумерацией)). - **Не тот тип (movie↔series)** → переключатель пересобирает форму плана. - **Мусор (sample/extra/дубли дорожек)** → роль «игнор». - **Полный провал** (LLM ничего не вытащил) → веб-«ручной режим»: выбрать