Беклог: ревью задач и приоритетов по итогам сверки с кодом

Прошлись по 34 старым задачам, сверив премисы с текущим кодом и спеками:

- Удалена mashina-sostoyaniy-biblioteka: change state-transition-graph
  (архив 2026-07-08) осознанно отверг внешнюю FSM-библиотеку в пользу
  своего декларативного графа — задача противоречит принятому решению.
- Понижены: masshtab-100-zagruzok (высокий→средний, чисто документный НФТ
  без признаков реальной нагрузки), favicon / telegram-match-metabazy /
  disk-kopii-video-ts-bdmv (средний→низкий).
- Переформулированы под реальный остаток: dobavlenie-edinoe-okno (magnet и
  .torrent-файл уже сделаны — остался фетч .torrent по URL с SSRF-гардом,
  средний→низкий); vneshnie-subtitry (привязка субтитр→серия уже работает —
  сузили до пар VobSub .idx+.sub и потери Lang/Flags в toLayoutPlan).
- Индекс README пересобран под новые ярусы (высокий/средний/низкий = 9/19/19).

Остальные задачи подтверждены кодом как актуальные; повышать нечего.
gate-confidence и дробление udalenie оставлены как темы для обсуждения.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
av
2026-07-08 12:05:41 +03:00
co-authored by Claude Opus 4.8
parent 7a774ad53d
commit 8ad4273db2
8 changed files with 42 additions and 25 deletions
+7 -8
View File
@@ -21,7 +21,6 @@ Tududi (проект `jellybit`) больше **не** держит беклог
- [Удаление средствами jellybit («единое окно», path 2)](udalenie-edinoe-okno.md) — Распознавание ручного удаления и пометка рассинхрона уже сделаны (state-reconciliation…
- [Ретеншн и очистка БД](retention-ochistka-bd.md) — Терминальные задачи (done/cancelled/failed/reverted), их попытки recognition с сырыми…
- [Eval-харнес распознавания (корпус кейсов + метрика точности)](eval-harness-raspoznavaniya.md) — Распознавание — ядро продукта, но смена модели или правка промпта сейчас вслепую…
- [НФТ: масштаб до 100 одновременных загрузок (потолок — 1000)](masshtab-100-zagruzok.md) — Потолок по нагрузке нигде не зафиксирован: воркер, поллинг qBittorrent, пул LLM-вызовов и…
- [Гейт дозаписи хешей в dedup-ветке CreateDownloadIfNoActive (F1)](review-f1-gate-dozapisi-heshey.md) — dedup-ветка дописывает все хеши в найденную задачу без гарда — риск инварианта ≤1 активной _(ревью 2026-07-08)_
- [Readiness-preflight: запрет авто-раскладки недокачанных файлов (MAJOR-5)](review-major5-readiness-preflight.md) — САМОЕ ОПАСНОЕ: авто-раскладка недокачанных файлов рвёт целостность библиотеки _(ревью 2026-07-08)_
- [Retry/stall семантика: сброс базиса таймаута + простой от начала, а не от возраста торрента (MAJOR-1, MAJOR-2)](review-major1-2-retry-stall.md) — таймаут и простой отсчитываются от возраста торрента, а не от начала загрузки _(ревью 2026-07-08)_
@@ -33,19 +32,15 @@ Tududi (проект `jellybit`) больше **не** держит беклог
- [Агенты-ревьюверы качества (наименования, архитектура, конвенции, стиль)](agenty-revyuvery-kachestva.md) — Набор узких сабагентов-ревьюверов поверх ревью-процесса из CLAUDE
- [[идея] Сила совпадения кандидата и пересмотр распознавания/матчинга](sila-sovpadeniya-kandidata.md) — ИДЕЯ (сперва проработать)
- [История переходов загрузки](istoriya-perehodov-zagruzki.md) — Сохранять полную историю переходов состояний загрузки (что/когда/почему/кто инициировал…
- [Машина состояний на go-библиотеке](mashina-sostoyaniy-biblioteka.md) — Сейчас FSM реализована вручную в worker
- [Привязка уведомлений к источнику в ботах (мульти-бот)](uvedomleniya-multi-bot.md) — Уведомления и запросы подтверждения должен получать тот, кто прислал загрузку: автор…
- [Улучшения UI: показывать матч с записью метабазы в Telegram](telegram-match-metabazy.md) — Web-сторона реализована: страница загрузки /download/{id} и экран ревью показывают, с…
- [[идея] Сложные сериальные раздачи: все сезоны разом, паки, спецраскладки](slozhnye-serialnye-razdachi.md) — ИДЕЯ (проработать крайние случаи)
- [Аниме с абсолютной нумерацией](anime-absolyutnaya-numeraciya.md) — Релизы аниме часто нумеруют серии сквозным числом (#137) без сезонов, а Jellyfin ждёт…
- [Добавление торрентов файлом/ссылкой — «единое окно»](dobavlenie-edinoe-okno.md) — Поддержать источники помимо magnet:
- [Бэкап SQLite](backup-sqlite.md) — architecture
- [Глубокий healthcheck и статус зависимостей](healthcheck-zavisimosti.md) — /healthz проверяет только сам сервис
- [НФТ: масштаб до 100 одновременных загрузок (потолок — 1000)](masshtab-100-zagruzok.md) — Зафиксировать в НФТ ориентир 100/1000 загрузок + аудит узких мест (SQLite, воркер, поллинг)
- [Обучение на правках человека (few-shot из прошлых ревью)](obuchenie-na-pravkah.md) — Когда человек поправил матч, тип или нумерацию — сохранять это как пример и подмешивать…
- [Гейт авто-раскладки по confidence: спека vs код](gate-confidence-spec-vs-code.md) — Аудит спек↔код (2026-07-03) нашёл расхождение в модели уверенности
- [Привязка внешних субтитров к серии (сериалы)](vneshnie-subtitry.md) — Аудит спек↔код (2026-07-03): спека recognition требует «внешние субтитры SHALL…
- [Раздачи-копии диска (DVD/BluRay: VIDEO_TS/BDMV)](disk-kopii-video-ts-bdmv.md) — Иногда для очень редких фильмов скачивается не один видеофайл, а полная копия диска…
- [Сделать фавиконку для jellybit](favicon.md) — мелкая косметика: иконка вкладки/PWA для веб-UI
- [Гейт авто-раскладки по confidence: спека vs код](gate-confidence-spec-vs-code.md) — Расхождение спека↔код: код делает confidence жёстким гейтом вопреки спеке — нужно решение
- [Внешние субтитры: пары VobSub и языковой суффикс](vneshnie-subtitry.md) — Привязка субтитр→серия уже работает; остались пары VobSub .idx+.sub и потеря Lang/Flags
- [Sweep застрявших linking при рестарте + фикс persist-failure (MAJOR-4)](review-major4-sweep-linking.md) — задачи застревают в linking при рестарте; заодно фикс persist-failure _(ревью 2026-07-08)_
- [Defer из catched → лимбо → необратимый deleted (MAJOR-6)](review-major6-defer-catched.md) — Defer из ещё-не-добавленного catched уводит задачу в необратимый deleted _(ревью 2026-07-08)_
- [processCatched: promote-without-add если торрент уже в qBittorrent (F2)](review-f2-promote-without-add.md) — торрент уже в qBittorrent → processCatched зациклен на Add вместо promote _(ревью 2026-07-08)_
@@ -60,12 +55,16 @@ Tududi (проект `jellybit`) больше **не** держит беклог
- [Версии/качество одного тайтла (репаки, апгрейд 1080p → 2160p)](versii-kachestvo-repaki.md) — По калибровке болей (2026-07-02) — не боль, из приоритета выпало
- [[идея] Многоступенчатая верификация привязки](mnogostupenchataya-verifikaciya.md) — ИДЕЯ (требует проработки)
- [Выбор из нескольких находок метабазы в Telegram](telegram-vybor-nahodok.md) — Когда распознавание даёт несколько подходящих кандидатов в метабазе, предлагать их в…
- [Улучшения UI: показывать матч с записью метабазы в Telegram](telegram-match-metabazy.md) — Название/год/провайдер+id в боте уже выводятся; осталась кликабельная ссылка на запись
- [Добавление торрентов файлом/ссылкой — «единое окно» (остаток: URL)](dobavlenie-edinoe-okno.md) — magnet и .torrent-файл приняты; остался фетч .torrent по URL (нужен SSRF-гард)
- [Раздачи-копии диска (DVD/BluRay: VIDEO_TS/BDMV)](disk-kopii-video-ts-bdmv.md) — Иногда для очень редких фильмов скачивается не один видеофайл, а полная копия диска…
- [Проверка свободного места перед copy-fallback](svobodnoe-mesto-copy-fallback.md) — Когда хардлинк невозможен (EXDEV/ENOTSUP/…), layout копирует файл, дублируя место на диске
- [Кэш метабаз (и опционально LLM)](kesh-metabaz.md) — Повторные и ретраящиеся прогоны распознавания бьют TMDB/TVDB/TVMaze одним и тем же…
- [[идея] guessit как сервис-спутник](guessit-sputnik.md) — ИДЕЯ
- [[идея] Завершение загрузки через webhook](webhook-zavershenie-zagruzki.md) — ИДЕЯ (решим по опыту эксплуатации)
- [Авторизация веб-UI (на будущее)](avtorizaciya-web-ui.md) — Решено для v1: без авторизации в доверенной LAN, опц
- [Современный Web-UI как PWA](web-ui-pwa.md) — Переделать веб-интерфейс в современное PWA-приложение (устанавливаемое, отзывчивое…
- [Сделать фавиконку для jellybit](favicon.md) — мелкая косметика: иконка вкладки/PWA для веб-UI
- [Идентичность инфохэшей: split v1/v2 одного торрента + крафт-магнет отравляет владение (F4, F5)](review-f4-f5-infohash-identity.md) — split v1/v2 идентичность и крафт-магнет отравляют владение инфохэшами _(ревью 2026-07-08)_
- [Приём/UI: мелкие фиксы границ и парсинга (F7, F8, F9, F10, N2)](review-f7-f10-ingest-ui-fixes.md) — мелочи приёма/UI: oversized→500, гонки дедупа, парсинг magnet, cap контекста, руны _(ревью 2026-07-08)_
- [Жизненный цикл: мелкие находки (MINOR-8, MINOR-9, NIT-11, NIT-12)](review-lifecycle-minor.md) — claim-token распознавания, I/O под глобальным mutex, мелкие lookup/retry _(ревью 2026-07-08)_
+1 -1
View File
@@ -1,6 +1,6 @@
# Раздачи-копии диска (DVD/BluRay: VIDEO_TS/BDMV)
**Приоритет:** средний
**Приоритет:** низкий
Иногда для очень редких фильмов скачивается не один видеофайл, а полная копия диска — структура VIDEO_TS/ (DVD) или BDMV/ (BluRay). Сейчас распознавание и раскладка заточены под пофайловый разбор, а тут «фильм» — это каталог целиком. Jellyfin такие раскладки поддерживает (папка фильма с вложенным VIDEO_TS/BDMV). Нужно: распознать, что раздача — образ диска (по наличию VIDEO_TS/BDMV), не разбирать её по отдельным VOB/m2ts как серии, разложить весь каталог хардлинками в папку фильма (Название (Год)/VIDEO_TS/…). Крайний, но реальный случай; частота низкая.
+15 -4
View File
@@ -1,7 +1,18 @@
# Добавление торрентов файлом/ссылкой — «единое окно»
# Фетч .torrent по URL — остаток «единого окна»
**Приоритет:** средний
**Приоритет:** низкий
Поддержать источники помимо magnet: .torrent-файл и URL (отдаём их в qBittorrent, без исходящих запросов на пользовательский URL — SSRF исключён). Идеал — одно поле «единого окна»: кидаем туда текст или файл, а сервис сам разбирает, что это (magnet / ссылка / .torrent / сообщение бота), и заводит загрузку.
Приём magnet и `.torrent`-файла уже реализован: ветка `TorrentData → torrent.Parse`
(`internal/ingest/ingest.go`), файл-пикер в веб-форме (`web/templates/index.html`),
приём документа в Telegram (`internal/tgbot`). Осталась одна ветка «единого окна» —
**URL на `.torrent`**: сервис сам скачивает файл по ссылке и заводит загрузку. Была
осознанно вынесена из change `torrent-file-ingest`, потому что требует исходящего
запроса на пользовательский URL → нужен SSRF-гард (allowlist схем/хостов, запрет
приватных сетей, лимит размера/редиректов).
Связано: specs/architecture.md → «Транспорты» (source_type = magnet|torrent|url уже в схеме), пакет ingest (сейчас поддержан только magnet).
Идеал по-прежнему — одно поле, куда кидают текст или файл, а сервис разбирает, что
это (magnet / ссылка на .torrent / .torrent-файл / сообщение бота). Сейчас текстовое
поле идёт только через `magnet.Parse`.
Связано: specs/architecture.md → «Транспорты» (source_type = magnet|torrent|url уже в
схеме), пакет ingest, архив change `torrent-file-ingest`.
+1 -1
View File
@@ -1,5 +1,5 @@
# Сделать фавиконку для jellybit
**Приоритет:** средний
**Приоритет:** низкий
_Описание не заполнено._
@@ -1,7 +0,0 @@
# Машина состояний на go-библиотеке
**Приоритет:** средний
Сейчас FSM реализована вручную в worker. Выбрать подходящую go-библиотеку для описания воркфлоу/машины состояний и перевести переходы на неё — ради декларативности, проверяемости переходов и единого места правды. Кандидаты для оценки: looplab/fsm, qmuntal/stateless (и аналоги). Граф и переходы уже формализованы — переносим один в один.
Связано: specs/workflow.md (текущий граф состояний).
+1 -1
View File
@@ -1,6 +1,6 @@
# НФТ: масштаб до 100 одновременных загрузок (потолок — 1000)
**Приоритет:** высокий
**Приоритет:** средний
Потолок по нагрузке нигде не зафиксирован: воркер, поллинг qBittorrent, пул LLM-вызовов и запись в SQLite спроектированы «на глаз». Записать в НФТ целевой ориентир — архитектура держит до 100 одновременных загрузок в работе (приём → распознавание → раскладка), план-максимум — 1000. Сама запись требования дешева и высокоценна: задаёт рамку для решений ниже. Отдельно (дороже) — аудит узких мест: одиночное соединение SQLite и сериализация записи, конкурентность воркера и лимит параллельных распознаваний, частота/стоимость поллинга и дедуп при наплыве.
+1 -1
View File
@@ -1,6 +1,6 @@
# Улучшения UI: показывать матч с записью метабазы в Telegram
**Приоритет:** средний
**Приоритет:** низкий
Web-сторона реализована: страница загрузки /download/{id} и экран ревью показывают, с какой именно записью метабазы (TMDB/TVDB/IMDb) сматчилась загрузка — провайдер, id и ссылку. Осталось довести то же в Telegram: в уведомлениях/подтверждениях показывать запись матча (название, год, провайдер-id, ссылку), чтобы ошибочную привязку было видно и из бота. Полный выбор источника в вебе уже реализован.
+16 -2
View File
@@ -1,7 +1,21 @@
# Привязка внешних субтитров к серии (сериалы)
# Внешние субтитры: пары VobSub и языковой суффикс
**Приоритет:** средний
Аудит спек↔код (2026-07-03): спека recognition требует «внешние субтитры SHALL привязываться к соответствующему видео». Для фильма работает — раскладка именует субтитр по базе видеофайла. Для сериала связь субтитр→конкретная серия не выражена: в PlanFile нет поля привязки, и нет логики спаривания VobSub .idx+.sub. Смоделировать привязку субтитра к эпизоду (поле на PlanFile или роль с season/episode) и спаривание .idx+.sub, либо — если откладываем — сузить формулировку спеки до реального поведения.
Базовая привязка субтитр→серия для сериала уже работает: `layout.PlanFile` несёт
`Season/Episode`, а `seriesDst` именует субтитр по стему эпизода
(`internal/layout/layout.go`, код старше аудита 2026-07-03). Для фильма тоже —
субтитр именуется по базе видеофайла.
Реальные пробелы, оставшиеся от аудита:
- **Пары VobSub** `.idx`+`.sub` не спариваются — их надо переносить вместе как одну
дорожку.
- **Языковой суффикс теряется:** у `recognize.PlanFile` нет полей `Lang/Flags`, и
`toLayoutPlan` (`internal/httpapi/review.go`) не проставляет язык — субтитр ляжет
без `*.ru.srt`-суффикса, который ждёт Jellyfin.
Смоделировать язык/флаги субтитра сквозь recognize→layout и спаривание `.idx`+`.sub`;
спека recognition уже требует «внешние субтитры SHALL привязываться к видео».
Связано: openspec/specs/recognition, specs/jellyfin-layout.md, пакеты recognize, layout.