docs: проект переведён на канон документов версии 4

- каталог задач: PLAN.md → ROADMAP.md с каноническими секциями, все 44
  записи получили тип, заголовки приведены к форме своего типа
- расхождения, найденные судьями канона: исключения инварианта «источник
  неприкосновенен», инвариант про один активный infohash, UTC в logging.md,
  поведение из architecture.md заменено ссылками на спеки
- триггеры профиля ревью переписаны под умолчание standard
This commit is contained in:
av
2026-08-06 13:32:06 +03:00
parent 905a1ee4d3
commit 66d39297c5
66 changed files with 334 additions and 204 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
{
"canon": 2,
"canon": 4,
"migrations": "internal/store/migrations"
}
@@ -1,6 +1,9 @@
# Авто-раскладка только при подтверждённом матче в метабазе
- **Дата:** 2026-06-13
- **Источник:** архивного `design.md` нет — решение принято до перехода
проекта на OpenSpec (первый архивный change — `2026-06-28`); первичный
материал — история git
## Контекст
+3
View File
@@ -1,6 +1,9 @@
# Docker как единица деплоя, образ собирается на сервере
- **Дата:** 2026-06-13
- **Источник:** архивного `design.md` нет — решение принято до перехода
проекта на OpenSpec (первый архивный change — `2026-06-28`); первичный
материал — история git
- **Статус:** заменено на ADR-2026-07-24-local-image-build
## Контекст
@@ -1,6 +1,9 @@
# Go и доставка одним бинарём
- **Дата:** 2026-06-13
- **Источник:** архивного `design.md` нет — решение принято до перехода
проекта на OpenSpec (первый архивный change — `2026-06-28`); первичный
материал — история git
## Контекст
+3
View File
@@ -1,6 +1,9 @@
# Хардлинки вместо копирования и симлинков
- **Дата:** 2026-06-13
- **Источник:** архивного `design.md` нет — решение принято до перехода
проекта на OpenSpec (первый архивный change — `2026-06-28`); первичный
материал — история git
## Контекст
@@ -1,6 +1,8 @@
# Конвейер ревью: гейт, generative-проходы и обязательный триаж
- **Дата:** 2026-07-23
- **Источник:** архивного `design.md` нет — решение процессное, change'ем jellybit
не велось
## Контекст
@@ -1,6 +1,8 @@
# Образ собирается локально и едет на сервер через docker save/load
- **Дата:** 2026-07-24
- **Источник:** архивного `design.md` нет — решение деплойное, change'ем jellybit
не велось
## Контекст
+17 -12
View File
@@ -53,16 +53,20 @@ retry / delete / dismiss) идут командами к `worker`.
## Внешние границы и форматы
- **qBittorrent WebUI API** — единственный способ качать: источник (magnet, URL,
`.torrent`) **отдаём ему**, сами по пользовательскому URL не ходим (SSRF
исключён). Пути берём из API (`save_path` + относительные имена из
`/torrents/files`), не из константы.
- **LLM** — OpenAI-совместимый Chat Completions (`[llm].type = "openai-compat"`),
структурированный вывод через `response_format: json_object`; валидация ответа
своя, в Go.
- **qBittorrent WebUI API** — единственный способ качать: источник **отдаём
ему**, сами по пользовательскому URL не ходим (SSRF исключён). Какие виды
источника принимаются и как разбираются —
[ingest](../openspec/specs/ingest/spec.md); способ добавления по
`source_type` — [download-tracking](../openspec/specs/download-tracking/spec.md);
откуда берутся пути файлов —
[file-layout](../openspec/specs/file-layout/spec.md).
- **LLM** — OpenAI-совместимый Chat Completions за интерфейсом (`[llm].type`);
контракт вызова, формат вывода и разбор ответа —
[recognition](../openspec/specs/recognition/spec.md).
- **Метабазы** — TMDB, TVDB, TVMaze (последняя без ключа, только сериалы).
- **Jellyfin** — один вызов `POST /Library/Refresh`, авторизация заголовком
`X-Emby-Token`.
- **Jellyfin** — HTTP-триггер пересканирования медиатеки, опционален; когда он
дёргается и по каким переходам —
[file-layout](../openspec/specs/file-layout/spec.md).
- **Telegram Bot API** — приём сообщений и исходящие карточки/пинги.
- **Сообщение торрент-бота** — чужой текстовый формат, разбирается парсером
`tgbot`; наблюдения по формату — в
@@ -90,8 +94,9 @@ retry / delete / dismiss) идут командами к `worker`.
задаче, застрявшей в промежуточном состоянии; логи в stdout контейнера.
Автоматического алертинга нет, метрик нет — только уведомления в Telegram о
падении загрузки и о рассинхроне.
- **Характер потока:** непрерывный фон (тик поллинга qBittorrent, по умолчанию
5 с, и периодическая сверка) плюс редкие события по запросу человека. Объём —
- **Характер потока:** непрерывный фон (тик поллинга qBittorrent — период в
[database.md](database.md) → «Настройки с числовым значением» — и
периодическая сверка) плюс редкие события по запросу человека. Объём —
единицы загрузок в день, десятки одновременно; ориентир масштаба и его аудит —
задача в беклоге.
@@ -101,7 +106,7 @@ retry / delete / dismiss) идут командами к `worker`.
| Что | Где |
| --- | --- |
| Время | `store.Now()` — единственный источник, всегда UTC; формат хранения — RFC 3339 |
| Время | `store.Now()` — единственный источник меток времени в данных, всегда UTC; формат хранения — RFC 3339. Вторая санкционированная точка wall-clock — timestamp-часть ULID в `ident.NewID` (исключение в `.golangci.yml`) |
| Идентификаторы | `internal/ident` — генерация и нормализация ULID; `ident.Parse` на каждой входной границе |
| Целевые имена и превью раскладки | `internal/naming` — одна логика для превью в UI и для реального применения |
| Разбор источника | `internal/magnet` и `internal/torrent`; инфохэш извлекается только здесь |
+6 -4
View File
@@ -6,9 +6,6 @@
Краткая выжимка и инварианты — в [CLAUDE.md](../../CLAUDE.md), раздел
«Конвенции кода».
> Каркас. Загрузчик `internal/config/config.go` уже грузит TOML; валидация
> на старте — в работе (`TODO`), обкатывается на следующем шаге.
## Принципы
- **Конфигурация — только TOML.** Env-переменные для конфига **не
@@ -41,7 +38,7 @@
```toml
[worker]
poll_interval = "5s" # как часто опрашивать qBittorrent; Go-duration (s/m/h)
magnet_timeout = "30m" # ждать метаданные magnet не дольше; Go-duration
magnet_timeout = "24h" # ждать метаданные magnet не дольше; Go-duration
source_missing_threshold = 3 # тиков сверки без раздачи, чтобы счесть источник удалённым
[recognition]
@@ -51,6 +48,11 @@ auto_confidence_threshold = 0.85 # порог авто-раскладки бе
max_retries = 3 # попыток получить валидный ответ LLM; целое ≥ 0
```
Значения в примере — иллюстрация формы комментария. Действующие умолчания и их
смысл живут одним домом — таблица «Настройки с числовым значением» в
[../database.md](../database.md); `config.example.toml` — источник истины по
составу полей.
Секретные поля оставляем пустыми — значение приходит из деплоя (см.
«Секреты»).
+1 -1
View File
@@ -2,7 +2,7 @@
Как мы устраиваем таблицы и ключи в SQLite. Актуальная схема —
[../database.md](../database.md); обоснование выбора ULID —
`openspec/changes/ulid-identity/design.md` (после архивации — в истории git).
[архивный design.md change'а `ulid-identity`](../../openspec/changes/archive/2026-07-02-ulid-identity/design.md).
**Механизировано:** `AUTOINCREMENT` и `DEFAULT (datetime('now'))` в новых
миграциях (`internal/archrules`), время мимо `store.Now()` (`forbidigo`).
+1 -1
View File
@@ -97,7 +97,7 @@ jellybit — **приложение, а не библиотека**: внешн
в review/failed: коллизия, рассинхрон, сбой ФС) и `reasons` распознавания,
сохранённые в БД и показываемые на экране ревью и в Telegram-карточке. Это
**операторская поверхность владельца**: сервис однопользовательский в
доверенной LAN (см. [architecture.md](../architecture.md)), эти поля —
доверенном контуре (см. [security.md](../security.md) → «Периметр»), эти поля —
диагностический контекст для того, кто разбирает задачу. Здесь сырой текст
ошибки (пути, фрагмент ответа LLM/qBittorrent) **допустим и полезен** — но:
- **секреты запрещены** абсолютно (токены/ключи/пароли/`Authorization`) — так
+4 -3
View File
@@ -74,9 +74,10 @@ OpenSpec-спеках (`### Requirement` с `SHALL`).
- Поле — `time` (ключ по умолчанию `slog`).
- UTC, RFC 3339 с долями секунды, суффикс `Z`:
`2026-06-28T11:23:45.123456Z`.
- Логи — **в UTC** (это явный TZ, не нарушает инвариант проекта): даёт
однозначный порядок событий и лексикографическую сортировку. Бизнес-логика
по-прежнему работает в `Europe/Moscow` — UTC только в логах.
- Логи — **в UTC**, как и хранение в БД: это даёт однозначный порядок событий и
лексикографическую сортировку. Часовой пояс есть только у **отображения** в
веб-UI (`[general].timezone`, дефолт `UTC`) — см.
[database.md](../database.md); бизнес-логика в локальной зоне не работает.
## Поля: словарь имён
+9 -3
View File
@@ -1,7 +1,7 @@
# Паспорт проекта
Зачем это и для кого. [architecture.md](architecture.md) отвечает «как
устроено», [tasks/PLAN.md](tasks/PLAN.md) — «в каком порядке», паспорт —
устроено», [tasks/ROADMAP.md](tasks/ROADMAP.md) — «что уже умеет», паспорт —
«зачем и для кого».
## Цель
@@ -44,8 +44,14 @@ Jellyfin, без ручного переименования и без ката
- **Не медиасервер.** Обложки, метаданные, учёт просмотренного и сам просмотр —
забота Jellyfin. Мы отвечаем только за то, чтобы файл лежал там, где Jellyfin
его правильно опознает.
- **Не хранилище медиа.** Данные живут в раздаче; мы создаём только хардлинки и
не владеем ни одним байтом контента.
- **Не хранилище медиа.** Данные живут в раздаче, мы создаём хардлинки и не
дублируем контент намеренно. Два исключения хранилищем нас не делают, но байты
у нас появляются: copy-fallback, когда хардлинк невозможен
([file-layout](../openspec/specs/file-layout/spec.md)), и состояние
`orphaned`, где библиотечная ссылка осталась последней копией
([state-reconciliation](../openspec/specs/state-reconciliation/spec.md)).
Сохранность мы и в этих случаях на себя не берём — резервных копий медиа у нас
нет.
- **Не мультипользовательский сервис.** Контур один, оператор один; разграничение
доступа сводится к allowlist Telegram (см. [security.md](security.md)).
+3 -3
View File
@@ -17,9 +17,9 @@ LLM-эндпоинта на живых раздачах. Автоматичес
это отдельная задача (eval-харнес распознавания), до неё числа здесь единичные
и приведены как условия, а не как статистика.
Зафиксированные образцы чужих форматов лежат прямо в тестах пакета-разборщика
(`internal/tgbot/parse_test.go`, `internal/magnet`, `internal/torrent`) — там
они заодно и проверяются; каталог `testdata/` под них не заводился.
Зафиксированные образцы чужих форматов лежат прямо в тестах пакета-разборщика
там они заодно и проверяются; где именно и почему без каталога `testdata/`, см.
[CLAUDE.md](../../CLAUDE.md) → «Запреты».
## Записи
+3 -1
View File
@@ -72,4 +72,6 @@ cправка: /help, index (https://exfreedomist.com/stats/)
- Как выглядит сообщение для сериала-сезонника и для аниме — образцов не
снимали, а именно на них строится самый сложный случай раскладки.
- Что бот присылает при неудачном поиске и при слишком длинном описании
(обрезка Telegram — 4096 символов на сообщение).
(лимит Telegram на текст сообщения — 4096 символов UTF-16, по документации
Bot API `sendMessage`; сами обрезанные сообщения мы не наблюдали, поведение
бота на обрезке неизвестно).
+23 -15
View File
@@ -70,10 +70,12 @@ Go-сервиса и что здесь уже проскакивало. Устр
снаружи LAN.
- **«Ошибка на htmx-пути возвращает 200».** Так и задумано —
[conventions/web-ui.md](conventions/web-ui.md).
- **«Решение auto/review должно опираться на `confidence` модели».** Наоборот:
авто только при подтверждённом матче в базе —
- **«Решение auto/review должно опираться на `confidence` модели».** Неверно в
форме «вместо матча»: авто только при подтверждённом матче в базе —
[ADR-2026-06-13-auto-link-requires-db-match](adr/ADR-2026-06-13-auto-link-requires-db-match.md).
Самооценка LLM плохо откалибрована и поддаётся инъекции.
Самооценка LLM плохо откалибрована и поддаётся инъекции. Порог `confidence`
при этом существует **дополнительным** блокирующим условием поверх матча —
его наличие дефектом не является.
- **«Копировать надёжнее, чем хардлинк» / «взять симлинк».** Хардлинк —
осознанный выбор ради неприкосновенности источника и недублирования диска,
[ADR-2026-06-13-hardlinks](adr/ADR-2026-06-13-hardlinks.md); copy — только
@@ -129,19 +131,25 @@ Go-сервиса и что здесь уже проскакивало. Устр
### Триггеры профиля
Уточняет умолчания конвейера, не отменяет их.
Уточняет умолчания конвейера, не отменяет их. Рабочее умолчание — `standard`;
миграция схемы и публичный контракт ступень **не** поднимают: их проверяют
проходы, которые в `standard` и так есть.
**Новым понятием или структурной единицей здесь считается** (→ `wide`): новый
пакет `internal/*`; новая capability в `openspec/specs/`; новый транспорт приёма
или уведомлений рядом с REST, веб-UI, ботом и CLI; новый провайдер метабазы за
существующим интерфейсом; новое состояние в графе переходов загрузки; перенос
ответственности между `worker`, `recognition`, `layout` и `store`.
**Правила идентичности, слияния и разбора живут здесь** (→ `deep`): владение
раздачей по инфохэшу и сверка с qBittorrent (`ident`, `internal/store`,
`state-reconciliation`); построение целевых путей и санитизация имён
(`internal/layout`, `naming`); разбор недоверенного входа — bencode, magnet,
текст контекста, ответ LLM (`internal/torrent`, `internal/magnet`,
`internal/tgbot/parse.go`, разбор ответа модели); выбор кандидата метабазы и
слияние его полей с догадкой LLM (`internal/metadata`, `metadata-match`);
merge-раскладка при повторном добавлении раздачи.
- **`deep`** — есть миграция в `internal/store/migrations/`; появляется новый
пакет `internal/*`; меняется сигнатура публичной команды воркера; трогается
раскладка файлов, построение целевых путей или удаление ссылок; трогается
разбор недоверенного входа.
- **`standard`** — меняется поведение, видимое снаружи: REST-эндпоинт,
htmx-путь, набор или семантика состояний загрузки, формат сообщения бота,
поле конфига.
- **`quick`** — всё остальное: локальный багфикс, документация, тесты.
- **Независимая реализация (`reimpl`)** запускается, когда узел одновременно
новый и имеет внешний оракул в виде спеки: новый парсер, новый провайдер за
существующим интерфейсом, новая стадия конвейера распознавания.
- «Поведение, видимое снаружи» здесь включает **тексты и карточки Telegram**
для единственного пользователя это и есть интерфейс.
+42 -40
View File
@@ -1,8 +1,8 @@
# Беклог
Что **можно взять**. Одна задача = один файл `items/<slug>.md`
+ строка здесь. Целей тут нет — они в [PLAN.md](PLAN.md): беклог — то, что берут,
план — то, подо что берут. Порядка внутри секции нет: «что делать
+ строка здесь. Целей тут нет — они в [ROADMAP.md](ROADMAP.md): беклог — то, что
берут, роадмап — то, подо что берут. Порядка внутри секции нет: «что делать
дальше» отвечает набор спринта. Ведётся скиллом `tasks`.
Секции «блокеры» здесь нет и не заводится: блокер — это состояние
@@ -10,43 +10,45 @@
человека, а его следы — вопросами в файлах задач.
## Ядро продукта
- [Аниме с абсолютной нумерацией](items/anime-absolute-numbering.md) — аниме со сквозной нумерацией (#137) не раскладывается в SxxEyy, который ждёт Jellyfin — нужен пересчёт абсолютной нумерации
- [`addReq` не пересобирается из свежего `source_type` перед `Add` (окно namer'а)](items/catched-source-type-refresh.md) — При апгрейде magnet→.torrent в окне namer'а добавится magnet из устаревшего снимка; самоисцеляется через magnet_timeout→failed→Retry _(аудит 2026-07-17)_
- [Раздачи-копии диска (DVD/BluRay: VIDEO_TS/BDMV)](items/disc-image-releases.md) — раздача-образ диска (VIDEO_TS/BDMV) сейчас разбирается пофайлово вместо раскладки каталога целиком — редкий, но реальный случай
- [Веб-UI зовёт Cancel вместо Dismiss на не-терминальных → теряется `user_dismiss`](items/dismiss-marker-lost.md) — Функционально ок (Cancel даёт cancelled), но маркер user_dismiss в error_code теряется; расхождение с буквой спеки _(аудит 2026-07-17)_
- [Фетч .torrent по URL — остаток «единого окна»](items/torrent-url-fetch.md) — magnet и .torrent-файл приняты; остался фетч .torrent по URL (нужен SSRF-гард)
- [Confidence-гейт авто-раскладки: узаконить в спеке + сделать выключаемым (дефолт 0.7)](items/auto-link-confidence-gate.md) — Решено (B): гейт оставляем как доп. проверку на ревью — выключаемый порог, дефолт 0.85→0.7, записать в спеку
- [[idea] guessit как сервис-спутник](items/guessit-sidecar.md) — go-ptn слабее питоновского guessit — если точности пред-парса не хватит, завернуть guessit в сервис-спутник рядом с бинарём
- [Согласование канона нумерации серий с провайдером тега](items/episode-numbering-canon.md) — Косметика/редкость: порядок просмотра ок, но у тайтлов со спорным порядком (Бибоп) Jellyfin подтягивает не те подписи серий, если канон файлов ≠ дефолтный порядок провайдера тега
- [Раздачи с докачиванием (merge при повторном добавлении)](items/merge-incremental-redownload.md) — повторная заливка сериала целиком должна доложить недостающие эпизоды merge-раскладкой, не трогая существующие ссылки — блокирует типовой сценарий свежих сериалов
- [[idea] Многоступенчатая верификация привязки](items/multi-pass-verification.md) — несколько проходов распознавания с консенсусом подняли бы точность ценой стоимости/латентности — проработать, когда включать и как мерджить расхождения
- [Обучение на правках человека (few-shot из прошлых ревью)](items/learn-from-user-corrections.md) — правки человека (матч/тип/нумерация) не переиспользуются — few-shot из прошлых ревью поднял бы точность на «своих» трекерах без смены модели
- [Идентичность инфохэшей: split v1/v2 одного торрента + крафт-магнет отравляет владение (F4, F5)](items/infohash-identity-integrity.md) — split v1/v2 идентичность и крафт-магнет отравляют владение инфохэшами _(ревью 2026-07-08)_
- [Нити приёма: NoName в контексте, устаревшие комментарии, лог без причины, bencode-аллокации (N1, N3, N4, N5)](items/ingest-nits.md) — косметика приёма: NoName в контексте, устаревшие комментарии, лог, bencode-аллокации _(ревью 2026-07-08)_
- [[idea] Сила совпадения кандидата и пересмотр распознавания/матчинга](items/candidate-match-strength.md) — у кандидата метабазы нет метрики силы совпадения — список кандидатов на ревью нечем отсортировать по уверенности (сперва проработать процесс матчинга)
- [[idea] Сложные сериальные раздачи: все сезоны разом, паки, спецраскладки](items/complex-series-releases.md) — сложные раздачи (все сезоны разом, паки, смешанная нумерация) целостно не проработаны — распознавание/ревью/раскладка заточены под один сезон
- [Мгновенные обновления через SSE](items/sse-live-updates.md) — живые обновления на htmx-поллинге дают задержку и холостые запросы — SSE убрал бы то и другое (поллинг работает, поэтому улучшение, не блокер)
- [Проверка свободного места перед copy-fallback](items/free-space-check-copy-fallback.md) — copy-fallback при невозможности хардлинка может упереться в переполненный диск посреди раскладки — нет проверки места до копирования
- [Ревью уведомлений в Telegram (аудит текстов и формата)](items/telegram-messages-audit.md) — зонтичный проход по всем текстам бота: полнота карточек, единый язык, оформление; порождает под-задачи
- [Привязка уведомлений к источнику в ботах (мульти-бот)](items/notification-source-binding.md) — пинги и ревью должен получать автор загрузки в своём транспорте — нет привязки загрузки к источнику/отправителю (нужно для мульти-бота)
- [Версии/качество одного тайтла (репаки, апгрейд 1080p → 2160p)](items/title-versions-repacks.md) — По калибровке болей (2026-07-02) — не боль, из приоритета выпало
- [Внешние субтитры: пары VobSub и языковой суффикс](items/external-subtitles.md) — Привязка субтитр→серия уже работает; остались пары VobSub .idx+.sub и потеря Lang/Flags
- [Современный Web-UI как PWA](items/web-ui-pwa.md) — текущий server-rendered UI функционален — PWA (устанавливаемое, удобное с телефона) это улучшение большого объёма, не блокер
- [Полный редактор маппинга «файл → серия» и ручной режим ревью](items/review-mapping-editor.md) — правка S·E, «нумеровать подряд» и ручной режим при полном провале LLM были запланированы объёмом Ф5 и не заведены задачей — в ревью сегодня можно только подсказать текстом
- [Крайние случаи именования: многофайловый фильм, редакции, двойная серия](items/naming-edge-cases.md) — стэкинг частей (part1/cd1), редакции [edition-…] и двойная серия SxxEyy-Eyy описаны нарративом, но в file-layout не заказаны — раскладка таких раздач не определена
- [Локаль TVDB: перевод названия и оригинальное название](items/tvdb-title-locale.md) — [general].language правит только TMDB и промпт LLM — TVDB отдаёт primary name, и при language=ru в карточку ревью и имя папки попадает 哪吒之魔童降世 вместо «Нэчжа»
- [✨ Пересчитывать абсолютную нумерацию аниме в SxxEyy](items/anime-absolute-numbering.md) — аниме со сквозной нумерацией (#137) не раскладывается в SxxEyy, который ждёт Jellyfin — нужен пересчёт абсолютной нумерации
- [🐞 Пересобирать `addReq` из свежего `source_type` перед `Add` (окно namer'а)](items/catched-source-type-refresh.md) — При апгрейде magnet→.torrent в окне namer'а добавится magnet из устаревшего снимка; самоисцеляется через magnet_timeout→failed→Retry _(аудит 2026-07-17)_
- [✨ Раскладывать раздачу-копию диска (VIDEO_TS/BDMV) каталогом целиком](items/disc-image-releases.md) — раздача-образ диска (VIDEO_TS/BDMV) сейчас разбирается пофайлово вместо раскладки каталога целиком — редкий, но реальный случай
- [🐞 Не терять маркер `user_dismiss` при закрытии не-терминальной загрузки из веб-UI](items/dismiss-marker-lost.md) — Функционально ок (Cancel даёт cancelled), но маркер user_dismiss в error_code теряется; расхождение с буквой спеки _(аудит 2026-07-17)_
- [✨ Принимать ссылку на .torrent и скачивать файл самим (нужен SSRF-гард)](items/torrent-url-fetch.md) — magnet и .torrent-файл приняты; остался фетч .torrent по URL (нужен SSRF-гард)
- [✨ Узаконить confidence-гейт авто-раскладки в спеке и сделать его выключаемым (дефолт 0.7)](items/auto-link-confidence-gate.md) — Решено (B): гейт оставляем как доп. проверку на ревью — выключаемый порог, дефолт 0.85→0.7, записать в спеку
- [✨ Докладывать недостающие эпизоды merge-раскладкой при повторной заливке](items/merge-incremental-redownload.md) — повторная заливка сериала целиком должна доложить недостающие эпизоды merge-раскладкой, не трогая существующие ссылки — блокирует типовой сценарий свежих сериалов
- [✨ Подмешивать прошлые правки человека в промпт распознавания (few-shot)](items/learn-from-user-corrections.md) — правки человека (матч/тип/нумерация) не переиспользуются — few-shot из прошлых ревью поднял бы точность на «своих» трекерах без смены модели
- [🐞 Связать v1/v2-хеши одного торрента и не доверять паре xt из магнета (F4, F5)](items/infohash-identity-integrity.md) — split v1/v2 идентичность и крафт-магнет отравляют владение инфохэшами _(ревью 2026-07-08)_
- [🧹 Закрыть мелочи приёма: NoName в контексте, устаревшие комментарии, лог без причины, bencode-аллокации (N1, N3, N4, N5)](items/ingest-nits.md) — косметика приёма: NoName в контексте, устаревшие комментарии, лог, bencode-аллокации _(ревью 2026-07-08)_
- [✨ Слать живые обновления через SSE вместо htmx-поллинга](items/sse-live-updates.md) — живые обновления на htmx-поллинге дают задержку и холостые запросы — SSE убрал бы то и другое (поллинг работает, поэтому улучшение, не блокер)
- [✨ Проверять свободное место перед copy-fallback](items/free-space-check-copy-fallback.md) — copy-fallback при невозможности хардлинка может упереться в переполненный диск посреди раскладки — нет проверки места до копирования
- [ Слать уведомления автору загрузки в его транспорт (мульти-бот)](items/notification-source-binding.md) — пинги и ревью должен получать автор загрузки в своём транспорте — нет привязки загрузки к источнику/отправителю (нужно для мульти-бота)
- [✨ Заменять разложенную версию тайтла новой (репаки, апгрейд 1080p → 2160p)](items/title-versions-repacks.md) — По калибровке болей (2026-07-02) — не боль, из приоритета выпало
- [✨ Спаривать VobSub .idx+.sub и проставлять языковой суффикс субтитра](items/external-subtitles.md) — Привязка субтитр→серия уже работает; остались пары VobSub .idx+.sub и потеря Lang/Flags
- [✨ Переделать веб-UI в устанавливаемое PWA](items/web-ui-pwa.md) — текущий server-rendered UI функционален — PWA (устанавливаемое, удобное с телефона) это улучшение большого объёма, не блокер
- [✨ Править на ревью маппинг «файл → серия» и раскладывать вручную при провале LLM](items/review-mapping-editor.md) — правка S·E, «нумеровать подряд» и ручной режим при полном провале LLM были запланированы объёмом Ф5 и не заведены задачей — в ревью сегодня можно только подсказать текстом
- [✨ Заказать спекой крайние случаи именования: многофайловый фильм, редакции, двойная серия](items/naming-edge-cases.md) — стэкинг частей (part1/cd1), редакции [edition-…] и двойная серия SxxEyy-Eyy описаны нарративом, но в file-layout не заказаны — раскладка таких раздач не определена
- [✨ Брать у TVDB название на языке настройки и оригинальное название](items/tvdb-title-locale.md) — [general].language правит только TMDB и промпт LLM — TVDB отдаёт primary name, и при language=ru в карточку ревью и имя папки попадает 哪吒之魔童降世 вместо «Нэчжа»
- [🔬 Канон нумерации серий и порядок у провайдера тега](items/episode-numbering-canon.md) — Косметика/редкость: порядок просмотра ок, но у тайтлов со спорным порядком (Бибоп) Jellyfin подтягивает не те подписи серий, если канон файлов ≠ дефолтный порядок провайдера тега
- [🔬 Тексты и формат уведомлений в Telegram](items/telegram-messages-audit.md) — зонтичный проход по всем текстам бота: полнота карточек, единый язык, оформление; порождает под-задачи
- [🔬 guessit как сервис-спутник](items/guessit-sidecar.md) — go-ptn слабее питоновского guessit — если точности пред-парса не хватит, завернуть guessit в сервис-спутник рядом с бинарём
- [🔬 Многоступенчатая верификация привязки](items/multi-pass-verification.md) — несколько проходов распознавания с консенсусом подняли бы точность ценой стоимости/латентности — проработать, когда включать и как мерджить расхождения
- [🔬 Сила совпадения кандидата и пересмотр распознавания/матчинга](items/candidate-match-strength.md) — у кандидата метабазы нет метрики силы совпадения — список кандидатов на ревью нечем отсортировать по уверенности (сперва проработать процесс матчинга)
- [🔬 Сложные сериальные раздачи: все сезоны разом, паки, спецраскладки](items/complex-series-releases.md) — сложные раздачи (все сезоны разом, паки, смешанная нумерация) целостно не проработаны — распознавание/ревью/раскладка заточены под один сезон
## Инфраструктура
- [Агенты-ревьюверы качества (наименования, архитектура, конвенции, стиль)](items/quality-review-agents.md) — конвейер ревью переехал в плагин `av-dev-pipeline`; осталась калибровка проходов на этом проекте и ревьювер наименований (ждёт словарь единого языка)
- [Авторизация веб-UI (на будущее)](items/web-ui-auth.md) — для v1 решено без авторизации (доверенная LAN, опц. allowlist подсетей) — задел на случай, если понадобится защита
- [Бэкап SQLite](items/sqlite-backup.md) — architecture требует бекапить data-том, но стратегия не описана — сбой или редеплой стирают всё in-flight состояние (проще, пока БД маленькая)
- [Eval-харнес распознавания (корпус кейсов + метрика точности)](items/recognition-eval-harness.md) — смена модели или правка промпта распознавания сейчас вслепую — нет корпуса кейсов и метрики точности, регрессии не видно
- [Глубокий healthcheck и статус зависимостей](items/deep-healthcheck-dependencies.md) — /healthz проверяет только сам сервис — недоступность qBittorrent/LLM/метабазы видна лишь по застрявшим задачам, нет readiness и бейджа в UI
- [История переходов загрузки](items/download-transition-history.md) — хранится только текущий статус загрузки — разбор «как сюда попали» идёт по логам сервера, нет таблицы истории переходов
- [Кэш метабаз (и опционально LLM)](items/metadata-cache.md) — повторные и ретраящиеся прогоны бьют TMDB/TVDB/TVMaze одним запросом — кэш с TTL сэкономил бы лимиты и ускорил «Распознать заново»
- [НФТ: масштаб до 100 одновременных загрузок (потолок — 1000)](items/scale-100-downloads.md) — Зафиксировать в НФТ ориентир 100/1000 загрузок + аудит узких мест (SQLite, воркер, поллинг)
- [Шум ERROR фоновых циклов при недоступной зависимости](items/background-error-noise.md) — Остаток задачи логирования: ext.* ERROR-шторм при недоступном qBittorrent + эскалация устойчивого сбоя тика _(ревью Fable)_
- [Ретеншн и очистка БД](items/db-retention-cleanup.md) — терминальные задачи и сырые ответы LLM копятся вечно — без авточистки список загрузок и БД деградируют по мере эксплуатации
- [Словарь единого языка (ubiquitous language)](items/ubiquitous-language-glossary.md) — наименования домена расходятся между спеками, UI и кодом — нет единого глоссария (на нём же стоит агент-ревьювер наименований)
- [[idea] Завершение загрузки через webhook](items/completion-webhook.md) — завершение сейчас ловим поллингом qBittorrent — webhook реагировал бы быстрее, но связывает нас с его конфигом (решим по опыту эксплуатации)
- [[idea] Кандидаты в конвенции кода](items/convention-candidates.md) — накоплен список кандидатов (внешние клиенты, конкурентность, тесты, CLI, время) — надо решить, что из них стало реальным трением, а что выдумано вперёд
- [🧹 Откалибровать проходы ревью и завести ревьювер наименований](items/quality-review-agents.md) — конвейер ревью переехал в плагин `av-dev-pipeline`; осталась калибровка проходов на этом проекте и ревьювер наименований (ждёт словарь единого языка)
- [✨ Закрыть веб-UI авторизацией, когда доверенной LAN станет мало](items/web-ui-auth.md) — для v1 решено без авторизации (доверенная LAN, опц. allowlist подсетей) — задел на случай, если понадобится защита
- [🧹 Бэкапить SQLite по расписанию с ротацией](items/sqlite-backup.md) — architecture требует бекапить data-том, но стратегия не описана — сбой или редеплой стирают всё in-flight состояние (проще, пока БД маленькая)
- [🧹 Завести eval-харнес распознавания: корпус кейсов и метрику точности](items/recognition-eval-harness.md) — смена модели или правка промпта распознавания сейчас вслепую — нет корпуса кейсов и метрики точности, регрессии не видно
- [✨ Проверять в healthcheck доступность qBittorrent, LLM и метабаз и показывать её в UI](items/deep-healthcheck-dependencies.md) — /healthz проверяет только сам сервис — недоступность qBittorrent/LLM/метабазы видна лишь по застрявшим задачам, нет readiness и бейджа в UI
- [✨ Хранить историю переходов загрузки отдельной таблицей](items/download-transition-history.md) — хранится только текущий статус загрузки — разбор «как сюда попали» идёт по логам сервера, нет таблицы истории переходов
- [🧹 Кэшировать ответы метабаз с TTL (и опционально LLM)](items/metadata-cache.md) — повторные и ретраящиеся прогоны бьют TMDB/TVDB/TVMaze одним запросом — кэш с TTL сэкономил бы лимиты и ускорил «Распознать заново»
- [🐞 Не штормить ERROR при недоступном qBittorrent и эскалировать устойчивый сбой тика](items/background-error-noise.md) — Остаток задачи логирования: ext.* ERROR-шторм при недоступном qBittorrent + эскалация устойчивого сбоя тика _(ревью Fable)_
- [✨ Чистить БД от терминальных задач и сырых ответов LLM старше срока хранения](items/db-retention-cleanup.md) — терминальные задачи и сырые ответы LLM копятся вечно — без авточистки список загрузок и БД деградируют по мере эксплуатации
- [🧹 Свести термины домена в словарь единого языка](items/ubiquitous-language-glossary.md) — наименования домена расходятся между спеками, UI и кодом — нет единого глоссария (на нём же стоит агент-ревьювер наименований)
- [🔬 Потолок нагрузки: 100 одновременных загрузок, план-максимум 1000](items/scale-100-downloads.md) — Зафиксировать в НФТ ориентир 100/1000 загрузок + аудит узких мест (SQLite, воркер, поллинг)
- [🔬 Завершение загрузки через webhook](items/completion-webhook.md) — завершение сейчас ловим поллингом qBittorrent — webhook реагировал бы быстрее, но связывает нас с его конфигом (решим по опыту эксплуатации)
- [🔬 Кандидаты в конвенции кода](items/convention-candidates.md) — накоплен список кандидатов (внешние клиенты, конкурентность, тесты, CLI, время) — надо решить, что из них стало реальным трением, а что выдумано вперёд
-22
View File
@@ -1,22 +0,0 @@
# План
Оглавление целей. Цель — файл `[goal]` в `items/`; её задачи
здесь **не перечисляются** — перечень даёт `tasks.py list --goal <слаг>`.
В первой секции («порядок») очередь значима и обосновывается
прозой; в остальных порядка нет — это тематические цели.
## порядок
Пусто. Фазы Ф0–Ф6 прежней дорожной карты (каркас, приём и трекинг,
распознавание, раскладка и ревью, метаданные, Telegram и UX, деплой) закрыты —
сквозной путь работает и развёрнут; закрытый шаг планом больше не является.
Что было сделано и когда — по архиву `openspec/changes/archive/`.
Следующая упорядоченная очередь появится, когда она понадобится.
## темы
- [[goal] Точность распознавания](items/recognition-accuracy.md) — смена модели или правка промпта сегодня вслепую — нет ни метрики, ни способа переиспользовать уже сделанные человеком правки
- [[goal] Сложные раздачи](items/complex-releases.md) — типовая раздача раскладывается, а всё, что сложнее одного сезона одного тайтла, упирается в ручной разбор
- [[goal] Эксплуатационная прочность](items/operational-resilience.md) — сервис работает, но не переживает роста: база копится вечно, бэкапа нет, отказ зависимости виден только по застрявшим задачам
- [[goal] Интерфейсы приёма и ревью](items/ingest-and-review-interfaces.md) — путь «принести раздачу и подтвердить догадку» упирается в незакрытые куски интерфейсов, а не в логику
- [[goal] Целостность состояния и приёма](items/state-integrity.md) — известные окна рассинхрона и потери маркеров: каждое по отдельности самоисцеляется, вместе — источник необъяснимых состояний
- [[goal] Процесс и качество разработки](items/dev-process-quality.md) — наименования домена расходятся между спеками, UI и кодом, а конвейер ревью не откалиброван — растёт цена каждой следующей задачи
+34
View File
@@ -0,0 +1,34 @@
# Роадмап
Что приложение уже умеет и чего ещё не умеет. Цель — файл типа `goal` в
`items/`; её задачи здесь **не перечисляются** — перечень даёт
`tasks.py list --goal <слаг>`. В `Запланировано` очередь значима и
обосновывается прозой; в `Направлениях` порядка нет; `Сопровождение` — то, чем
держат проект, а не возможности приложения; в `Готово` строку с датой пишет
`close --implemented`.
## Запланировано
Пусто. Фазы Ф0–Ф6 прежней дорожной карты (каркас, приём и трекинг,
распознавание, раскладка и ревью, метаданные, Telegram и UX, деплой) закрыты —
сквозной путь работает и развёрнут; закрытый шаг планом больше не является.
Следующая упорядоченная очередь появится, когда она понадобится.
## Направления
- [🎯 Раздача узнаётся верно, и точность этого измерима](items/recognition-accuracy.md) — смена модели или правка промпта сегодня вслепую — нет ни метрики, ни способа переиспользовать уже сделанные человеком правки
- [🎯 Раскладывается не только типовая раздача](items/complex-releases.md) — типовая раздача раскладывается, а всё, что сложнее одного сезона одного тайтла, упирается в ручной разбор
- [🎯 Раздача приносится и подтверждается из любого транспорта](items/ingest-and-review-interfaces.md) — путь «принести раздачу и подтвердить догадку» упирается в незакрытые куски интерфейсов, а не в логику
- [🎯 По записи загрузки видно, как она сюда попала](items/state-integrity.md) — известные окна рассинхрона и потери маркеров: каждое по отдельности самоисцеляется, вместе — источник необъяснимых состояний
## Сопровождение
- [🎯 Сервис переживает рост и потерю тома](items/operational-resilience.md) — сервис работает, но не переживает роста: база копится вечно, бэкапа нет, отказ зависимости виден только по застрявшим задачам
- [🎯 Домен называется одинаково везде, ревью откалибровано](items/dev-process-quality.md) — наименования домена расходятся между спеками, UI и кодом, а конвейер ревью не откалиброван — растёт цена каждой следующей задачи
## Готово
Пусто. Фазы Ф0–Ф6 велись прозой и целями в роадмапе не числились, поэтому
строк с датами за ними нет; что было сделано и когда — по архиву
`openspec/changes/archive/`. Первую строку сюда впишет `close --implemented`
на первой достигнутой цели.
+3 -2
View File
@@ -1,6 +1,7 @@
# Аниме с абсолютной нумерацией
# ✨ Пересчитывать абсолютную нумерацию аниме в SxxEyy
- **Секция:** ядро продукта
- **Тип:** feature
- **Категория:** Ядро продукта
- **Зачем:** аниме со сквозной нумерацией (#137) не раскладывается в SxxEyy, который ждёт Jellyfin — нужен пересчёт абсолютной нумерации
- **Теги:** goal:complex-releases
@@ -1,6 +1,7 @@
# Confidence-гейт авто-раскладки: узаконить в спеке + сделать выключаемым (дефолт 0.7)
# ✨ Узаконить confidence-гейт авто-раскладки в спеке и сделать его выключаемым (дефолт 0.7)
- **Секция:** ядро продукта
- **Тип:** feature
- **Категория:** Ядро продукта
- **Зачем:** Решено (B): гейт оставляем как доп. проверку на ревью — выключаемый порог, дефолт 0.85→0.7, записать в спеку
- **Теги:** goal:recognition-accuracy
@@ -35,7 +36,12 @@
вспомогательный сигнал». Добавить сценарий: матч + чистая валидация +
согласованность, но `confidence` ниже порога → review.
4. **Конфиг-конвенция/дока:** описать ключ в `docs/conventions/config.md` (диапазон
[0,1], 0 = выкл, дефолт 0.7).
[0,1], 0 = выкл, дефолт 0.7) и поправить значение в таблице «Настройки с
числовым значением» [docs/database.md](../../database.md) — дом числа там, и
при смене дефолта оно разъедется первым. Формулировки инварианта в
`CLAUDE.md` и ложноположительного в `docs/review.md` уже приведены к
«единственным гейтом не является» (канон 4, 2026-08-06) — переписывать их
задача не должна.
5. **Тесты:** `decide` с `threshold=0` (гейт выключен, авто при чистых 1–3);
confidence ниже/выше порога при выполненных 1–3.
6. Точное число порога откалибровать позже — для этого есть задача
+3 -2
View File
@@ -1,6 +1,7 @@
# Шум ERROR фоновых циклов при недоступной зависимости
# 🐞 Не штормить ERROR при недоступном qBittorrent и эскалировать устойчивый сбой тика
- **Секция:** инфраструктура
- **Тип:** fix
- **Категория:** Инфраструктура
- **Зачем:** Остаток задачи логирования: ext.* ERROR-шторм при недоступном qBittorrent + эскалация устойчивого сбоя тика _(ревью Fable)_
- **Теги:** goal:operational-resilience
+3 -2
View File
@@ -1,6 +1,7 @@
# [idea] Сила совпадения кандидата и пересмотр распознавания/матчинга
# 🔬 Сила совпадения кандидата и пересмотр распознавания/матчинга
- **Секция:** ядро продукта
- **Тип:** research
- **Категория:** Ядро продукта
- **Зачем:** у кандидата метабазы нет метрики силы совпадения — список кандидатов на ревью нечем отсортировать по уверенности (сперва проработать процесс матчинга)
- **Теги:** goal:recognition-accuracy
@@ -1,6 +1,7 @@
# `addReq` не пересобирается из свежего `source_type` перед `Add` (окно namer'а)
# 🐞 Пересобирать `addReq` из свежего `source_type` перед `Add` (окно namer'а)
- **Секция:** ядро продукта
- **Тип:** fix
- **Категория:** Ядро продукта
- **Зачем:** При апгрейде magnet→.torrent в окне namer'а добавится magnet из устаревшего снимка; самоисцеляется через magnet_timeout→failed→Retry _(аудит 2026-07-17)_
- **Теги:** goal:state-integrity
+3 -2
View File
@@ -1,6 +1,7 @@
# [idea] Завершение загрузки через webhook
# 🔬 Завершение загрузки через webhook
- **Секция:** инфраструктура
- **Тип:** research
- **Категория:** Инфраструктура
- **Зачем:** завершение сейчас ловим поллингом qBittorrent — webhook реагировал бы быстрее, но связывает нас с его конфигом (решим по опыту эксплуатации)
- **Теги:** goal:ingest-and-review-interfaces
+3 -2
View File
@@ -1,6 +1,7 @@
# [goal] Сложные раздачи
# 🎯 Раскладывается не только типовая раздача
- **Секция:** темы
- **Тип:** goal
- **Секция:** Направления
- **Зачем:** типовая раздача раскладывается, а всё, что сложнее одного сезона одного тайтла, упирается в ручной разбор
- **Теги:** decomposed
+3 -2
View File
@@ -1,6 +1,7 @@
# [idea] Сложные сериальные раздачи: все сезоны разом, паки, спецраскладки
# 🔬 Сложные сериальные раздачи: все сезоны разом, паки, спецраскладки
- **Секция:** ядро продукта
- **Тип:** research
- **Категория:** Ядро продукта
- **Зачем:** сложные раздачи (все сезоны разом, паки, смешанная нумерация) целостно не проработаны — распознавание/ревью/раскладка заточены под один сезон
- **Теги:** goal:complex-releases
+3 -2
View File
@@ -1,6 +1,7 @@
# [idea] Кандидаты в конвенции кода
# 🔬 Кандидаты в конвенции кода
- **Секция:** Инфраструктура
- **Тип:** research
- **Категория:** Инфраструктура
- **Зачем:** накоплен список кандидатов (внешние клиенты, конкурентность, тесты, CLI, время) — надо решить, что из них стало реальным трением, а что выдумано вперёд
- **Теги:** goal:dev-process-quality
+3 -2
View File
@@ -1,6 +1,7 @@
# Ретеншн и очистка БД
# ✨ Чистить БД от терминальных задач и сырых ответов LLM старше срока хранения
- **Секция:** инфраструктура
- **Тип:** feature
- **Категория:** Инфраструктура
- **Зачем:** терминальные задачи и сырые ответы LLM копятся вечно — без авточистки список загрузок и БД деградируют по мере эксплуатации
- **Теги:** goal:operational-resilience
@@ -1,6 +1,7 @@
# Глубокий healthcheck и статус зависимостей
# ✨ Проверять в healthcheck доступность qBittorrent, LLM и метабаз и показывать её в UI
- **Секция:** инфраструктура
- **Тип:** feature
- **Категория:** Инфраструктура
- **Зачем:** /healthz проверяет только сам сервис — недоступность qBittorrent/LLM/метабазы видна лишь по застрявшим задачам, нет readiness и бейджа в UI
- **Теги:** goal:operational-resilience
+3 -2
View File
@@ -1,6 +1,7 @@
# [goal] Процесс и качество разработки
# 🎯 Домен называется одинаково везде, ревью откалибровано
- **Секция:** темы
- **Тип:** goal
- **Секция:** Сопровождение
- **Зачем:** наименования домена расходятся между спеками, UI и кодом, а конвейер ревью не откалиброван — растёт цена каждой следующей задачи
- **Теги:** decomposed
+3 -2
View File
@@ -1,6 +1,7 @@
# Раздачи-копии диска (DVD/BluRay: VIDEO_TS/BDMV)
# ✨ Раскладывать раздачу-копию диска (VIDEO_TS/BDMV) каталогом целиком
- **Секция:** ядро продукта
- **Тип:** feature
- **Категория:** Ядро продукта
- **Зачем:** раздача-образ диска (VIDEO_TS/BDMV) сейчас разбирается пофайлово вместо раскладки каталога целиком — редкий, но реальный случай
- **Теги:** goal:complex-releases
+3 -2
View File
@@ -1,6 +1,7 @@
# Веб-UI зовёт Cancel вместо Dismiss на не-терминальных → теряется `user_dismiss`
# 🐞 Не терять маркер `user_dismiss` при закрытии не-терминальной загрузки из веб-UI
- **Секция:** ядро продукта
- **Тип:** fix
- **Категория:** Ядро продукта
- **Зачем:** Функционально ок (Cancel даёт cancelled), но маркер user_dismiss в error_code теряется; расхождение с буквой спеки _(аудит 2026-07-17)_
- **Теги:** goal:state-integrity
@@ -1,6 +1,7 @@
# История переходов загрузки
# ✨ Хранить историю переходов загрузки отдельной таблицей
- **Секция:** инфраструктура
- **Тип:** feature
- **Категория:** Инфраструктура
- **Зачем:** хранится только текущий статус загрузки — разбор «как сюда попали» идёт по логам сервера, нет таблицы истории переходов
- **Теги:** goal:state-integrity
+3 -2
View File
@@ -1,6 +1,7 @@
# Согласование канона нумерации серий с провайдером тега
# 🔬 Канон нумерации серий и порядок у провайдера тега
- **Секция:** ядро продукта
- **Тип:** research
- **Категория:** Ядро продукта
- **Зачем:** Косметика/редкость: порядок просмотра ок, но у тайтлов со спорным порядком (Бибоп) Jellyfin подтягивает не те подписи серий, если канон файлов ≠ дефолтный порядок провайдера тега
- **Теги:** goal:complex-releases
+3 -2
View File
@@ -1,6 +1,7 @@
# Внешние субтитры: пары VobSub и языковой суффикс
# ✨ Спаривать VobSub .idx+.sub и проставлять языковой суффикс субтитра
- **Секция:** ядро продукта
- **Тип:** feature
- **Категория:** Ядро продукта
- **Зачем:** Привязка субтитр→серия уже работает; остались пары VobSub .idx+.sub и потеря Lang/Flags
- **Теги:** goal:complex-releases
@@ -1,6 +1,7 @@
# Проверка свободного места перед copy-fallback
# Проверять свободное место перед copy-fallback
- **Секция:** ядро продукта
- **Тип:** feature
- **Категория:** Ядро продукта
- **Зачем:** copy-fallback при невозможности хардлинка может упереться в переполненный диск посреди раскладки — нет проверки места до копирования
- **Теги:** goal:operational-resilience
+3 -2
View File
@@ -1,6 +1,7 @@
# [idea] guessit как сервис-спутник
# 🔬 guessit как сервис-спутник
- **Секция:** ядро продукта
- **Тип:** research
- **Категория:** Ядро продукта
- **Зачем:** go-ptn слабее питоновского guessit — если точности пред-парса не хватит, завернуть guessit в сервис-спутник рядом с бинарём
- **Теги:** goal:recognition-accuracy
@@ -1,6 +1,7 @@
# Идентичность инфохэшей: split v1/v2 одного торрента + крафт-магнет отравляет владение (F4, F5)
# 🐞 Связать v1/v2-хеши одного торрента и не доверять паре xt из магнета (F4, F5)
- **Секция:** ядро продукта
- **Тип:** fix
- **Категория:** Ядро продукта
- **Зачем:** split v1/v2 идентичность и крафт-магнет отравляют владение инфохэшами _(ревью 2026-07-08)_
- **Теги:** goal:state-integrity
@@ -1,6 +1,7 @@
# [goal] Интерфейсы приёма и ревью
# 🎯 Раздача приносится и подтверждается из любого транспорта
- **Секция:** темы
- **Тип:** goal
- **Секция:** Направления
- **Зачем:** путь «принести раздачу и подтвердить догадку» упирается в незакрытые куски интерфейсов, а не в логику
- **Теги:** decomposed
+3 -2
View File
@@ -1,6 +1,7 @@
# Нити приёма: NoName в контексте, устаревшие комментарии, лог без причины, bencode-аллокации (N1, N3, N4, N5)
# 🧹 Закрыть мелочи приёма: NoName в контексте, устаревшие комментарии, лог без причины, bencode-аллокации (N1, N3, N4, N5)
- **Секция:** ядро продукта
- **Тип:** chore
- **Категория:** Ядро продукта
- **Зачем:** косметика приёма: NoName в контексте, устаревшие комментарии, лог, bencode-аллокации _(ревью 2026-07-08)_
- **Теги:** goal:state-integrity
@@ -1,6 +1,7 @@
# Обучение на правках человека (few-shot из прошлых ревью)
# ✨ Подмешивать прошлые правки человека в промпт распознавания (few-shot)
- **Секция:** ядро продукта
- **Тип:** feature
- **Категория:** Ядро продукта
- **Зачем:** правки человека (матч/тип/нумерация) не переиспользуются — few-shot из прошлых ревью поднял бы точность на «своих» трекерах без смены модели
- **Теги:** goal:recognition-accuracy
@@ -1,6 +1,7 @@
# Раздачи с докачиванием (merge при повторном добавлении)
# ✨ Докладывать недостающие эпизоды merge-раскладкой при повторной заливке
- **Секция:** ядро продукта
- **Тип:** feature
- **Категория:** Ядро продукта
- **Зачем:** повторная заливка сериала целиком должна доложить недостающие эпизоды merge-раскладкой, не трогая существующие ссылки — блокирует типовой сценарий свежих сериалов
- **Теги:** goal:complex-releases
+3 -2
View File
@@ -1,6 +1,7 @@
# Кэш метабаз (и опционально LLM)
# 🧹 Кэшировать ответы метабаз с TTL (и опционально LLM)
- **Секция:** инфраструктура
- **Тип:** chore
- **Категория:** Инфраструктура
- **Зачем:** повторные и ретраящиеся прогоны бьют TMDB/TVDB/TVMaze одним запросом — кэш с TTL сэкономил бы лимиты и ускорил «Распознать заново»
- **Теги:** goal:operational-resilience
+3 -2
View File
@@ -1,6 +1,7 @@
# [idea] Многоступенчатая верификация привязки
# 🔬 Многоступенчатая верификация привязки
- **Секция:** ядро продукта
- **Тип:** research
- **Категория:** Ядро продукта
- **Зачем:** несколько проходов распознавания с консенсусом подняли бы точность ценой стоимости/латентности — проработать, когда включать и как мерджить расхождения
- **Теги:** goal:recognition-accuracy
+3 -2
View File
@@ -1,6 +1,7 @@
# Крайние случаи именования: многофайловый фильм, редакции, двойная серия
# ✨ Заказать спекой крайние случаи именования: многофайловый фильм, редакции, двойная серия
- **Секция:** Ядро продукта
- **Тип:** feature
- **Категория:** Ядро продукта
- **Зачем:** стэкинг частей (part1/cd1), редакции [edition-…] и двойная серия SxxEyy-Eyy описаны нарративом, но в file-layout не заказаны — раскладка таких раздач не определена
- **Теги:** goal:complex-releases
@@ -1,6 +1,7 @@
# Привязка уведомлений к источнику в ботах (мульти-бот)
# ✨ Слать уведомления автору загрузки в его транспорт (мульти-бот)
- **Секция:** ядро продукта
- **Тип:** feature
- **Категория:** Ядро продукта
- **Зачем:** пинги и ревью должен получать автор загрузки в своём транспорте — нет привязки загрузки к источнику/отправителю (нужно для мульти-бота)
- **Теги:** goal:ingest-and-review-interfaces
+3 -2
View File
@@ -1,6 +1,7 @@
# [goal] Эксплуатационная прочность
# 🎯 Сервис переживает рост и потерю тома
- **Секция:** темы
- **Тип:** goal
- **Секция:** Сопровождение
- **Зачем:** сервис работает, но не переживает роста: база копится вечно, бэкапа нет, отказ зависимости виден только по застрявшим задачам
- **Теги:** decomposed
+3 -2
View File
@@ -1,6 +1,7 @@
# Агенты-ревьюверы качества (наименования, архитектура, конвенции, стиль)
# 🧹 Откалибровать проходы ревью и завести ревьювер наименований
- **Секция:** инфраструктура
- **Тип:** chore
- **Категория:** Инфраструктура
- **Зачем:** конвейер ревью переехал в плагин `av-dev-pipeline`; осталась калибровка проходов на этом проекте и ревьювер наименований (ждёт словарь единого языка)
- **Теги:** goal:dev-process-quality
+3 -2
View File
@@ -1,6 +1,7 @@
# [goal] Точность распознавания
# 🎯 Раздача узнаётся верно, и точность этого измерима
- **Секция:** темы
- **Тип:** goal
- **Секция:** Направления
- **Зачем:** смена модели или правка промпта сегодня вслепую — нет ни метрики, ни способа переиспользовать уже сделанные человеком правки
- **Теги:** decomposed
+3 -2
View File
@@ -1,6 +1,7 @@
# Eval-харнес распознавания (корпус кейсов + метрика точности)
# 🧹 Завести eval-харнес распознавания: корпус кейсов и метрику точности
- **Секция:** инфраструктура
- **Тип:** chore
- **Категория:** Инфраструктура
- **Зачем:** смена модели или правка промпта распознавания сейчас вслепую — нет корпуса кейсов и метрики точности, регрессии не видно
- **Теги:** goal:recognition-accuracy
+3 -2
View File
@@ -1,6 +1,7 @@
# Полный редактор маппинга «файл → серия» и ручной режим ревью
# ✨ Править на ревью маппинг «файл → серия» и раскладывать вручную при провале LLM
- **Секция:** Ядро продукта
- **Тип:** feature
- **Категория:** Ядро продукта
- **Зачем:** правка S·E, «нумеровать подряд» и ручной режим при полном провале LLM были запланированы объёмом Ф5 и не заведены задачей — в ревью сегодня можно только подсказать текстом
- **Теги:** goal:ingest-and-review-interfaces
+3 -2
View File
@@ -1,6 +1,7 @@
# НФТ: масштаб до 100 одновременных загрузок (потолок — 1000)
# 🔬 Потолок нагрузки: 100 одновременных загрузок, план-максимум 1000
- **Секция:** инфраструктура
- **Тип:** research
- **Категория:** Инфраструктура
- **Зачем:** Зафиксировать в НФТ ориентир 100/1000 загрузок + аудит узких мест (SQLite, воркер, поллинг)
- **Теги:** goal:operational-resilience
+3 -2
View File
@@ -1,6 +1,7 @@
# Бэкап SQLite
# 🧹 Бэкапить SQLite по расписанию с ротацией
- **Секция:** инфраструктура
- **Тип:** chore
- **Категория:** Инфраструктура
- **Зачем:** architecture требует бекапить data-том, но стратегия не описана — сбой или редеплой стирают всё in-flight состояние (проще, пока БД маленькая)
- **Теги:** goal:operational-resilience
+3 -2
View File
@@ -1,6 +1,7 @@
# Мгновенные обновления через SSE
# ✨ Слать живые обновления через SSE вместо htmx-поллинга
- **Секция:** ядро продукта
- **Тип:** feature
- **Категория:** Ядро продукта
- **Зачем:** живые обновления на htmx-поллинге дают задержку и холостые запросы — SSE убрал бы то и другое (поллинг работает, поэтому улучшение, не блокер)
- **Теги:** goal:ingest-and-review-interfaces
+3 -2
View File
@@ -1,6 +1,7 @@
# [goal] Целостность состояния и приёма
# 🎯 По записи загрузки видно, как она сюда попала
- **Секция:** темы
- **Тип:** goal
- **Секция:** Направления
- **Зачем:** известные окна рассинхрона и потери маркеров: каждое по отдельности самоисцеляется, вместе — источник необъяснимых состояний
- **Теги:** decomposed
+3 -2
View File
@@ -1,6 +1,7 @@
# Ревью уведомлений в Telegram (аудит текстов и формата)
# 🔬 Тексты и формат уведомлений в Telegram
- **Секция:** ядро продукта
- **Тип:** research
- **Категория:** Ядро продукта
- **Зачем:** зонтичный проход по всем текстам бота: полнота карточек, единый язык, оформление; порождает под-задачи
- **Теги:** goal:ingest-and-review-interfaces
+3 -2
View File
@@ -1,6 +1,7 @@
# Версии/качество одного тайтла (репаки, апгрейд 1080p → 2160p)
# ✨ Заменять разложенную версию тайтла новой (репаки, апгрейд 1080p → 2160p)
- **Секция:** ядро продукта
- **Тип:** feature
- **Категория:** Ядро продукта
- **Зачем:** По калибровке болей (2026-07-02) — не боль, из приоритета выпало
- **Теги:** goal:complex-releases
+3 -2
View File
@@ -1,6 +1,7 @@
# Фетч .torrent по URL — остаток «единого окна»
# ✨ Принимать ссылку на .torrent и скачивать файл самим (нужен SSRF-гард)
- **Секция:** ядро продукта
- **Тип:** feature
- **Категория:** Ядро продукта
- **Зачем:** magnet и .torrent-файл приняты; остался фетч .torrent по URL (нужен SSRF-гард)
- **Теги:** goal:ingest-and-review-interfaces
+3 -2
View File
@@ -1,6 +1,7 @@
# Локаль TVDB: перевод названия и оригинальное название
# ✨ Брать у TVDB название на языке настройки и оригинальное название
- **Секция:** Ядро продукта
- **Тип:** feature
- **Категория:** Ядро продукта
- **Зачем:** [general].language правит только TMDB и промпт LLM — TVDB отдаёт primary name, и при language=ru в карточку ревью и имя папки попадает 哪吒之魔童降世 вместо «Нэчжа»
- **Теги:** goal:recognition-accuracy
@@ -1,6 +1,7 @@
# Словарь единого языка (ubiquitous language)
# 🧹 Свести термины домена в словарь единого языка
- **Секция:** инфраструктура
- **Тип:** chore
- **Категория:** Инфраструктура
- **Зачем:** наименования домена расходятся между спеками, UI и кодом — нет единого глоссария (на нём же стоит агент-ревьювер наименований)
- **Теги:** goal:dev-process-quality
+3 -2
View File
@@ -1,6 +1,7 @@
# Авторизация веб-UI (на будущее)
# ✨ Закрыть веб-UI авторизацией, когда доверенной LAN станет мало
- **Секция:** инфраструктура
- **Тип:** feature
- **Категория:** Инфраструктура
- **Зачем:** для v1 решено без авторизации (доверенная LAN, опц. allowlist подсетей) — задел на случай, если понадобится защита
- **Теги:** goal:ingest-and-review-interfaces
+3 -2
View File
@@ -1,6 +1,7 @@
# Современный Web-UI как PWA
# ✨ Переделать веб-UI в устанавливаемое PWA
- **Секция:** ядро продукта
- **Тип:** feature
- **Категория:** Ядро продукта
- **Зачем:** текущий server-rendered UI функционален — PWA (устанавливаемое, удобное с телефона) это улучшение большого объёма, не блокер
- **Теги:** goal:ingest-and-review-interfaces