Беклог: 3 пункта из аудита спек↔код + правка формулировки per-download (docs)
По итогам аудита соответствия спек и кода (11 сабагентов, по одному на capability): Беклог: - новый пункт: гейт авто-раскладки по confidence (спека говорит «вспомогательный сигнал», код делает жёсткий AutoThreshold=0.85) — определиться, что правда - новый пункт: привязка внешних субтитров к серии (спека требует, для сериала связь субтитр→эпизод и пары .idx/.sub в коде не выражены) - новый пункт: раздачи-копии диска DVD/BluRay (VIDEO_TS/BDMV — каталог целиком, не пофайловый разбор) - дополнен существующий баг TVDB /series/: спека metadata-match теперь тоже кодифицирует баг — фикс должен править и требование Спеки (правка на точность, поведение не меняется): - download-tracking, review: «per-download блокировка» → «единая блокировка воркера» (по факту глобальный w.mu, а не per-download) openspec validate --strict — проходит. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+59
-1
@@ -291,6 +291,57 @@ qBittorrent, без исходящих запросов на пользоват
|
|||||||
[«Многоступенчатая верификация»](#многоступенчатая-верификация-привязки-идея),
|
[«Многоступенчатая верификация»](#многоступенчатая-верификация-привязки-идея),
|
||||||
[architecture.md](specs/architecture.md) → «Хранилище» (`hint`, `override`).
|
[architecture.md](specs/architecture.md) → «Хранилище» (`hint`, `override`).
|
||||||
|
|
||||||
|
### Гейт авто-раскладки по `confidence`: спека vs код
|
||||||
|
|
||||||
|
Аудит спек↔код (2026-07-03) нашёл расхождение в модели уверенности.
|
||||||
|
Спека `recognition` (унаследовано из `recognition.md`) утверждает, что
|
||||||
|
самооценка LLM `confidence` — **вспомогательный сигнал, НЕ единственный гейт**:
|
||||||
|
при подтверждённом матче в базе + чистой структурной валидации + согласованности
|
||||||
|
сигналов авто-раскладка допускается. Код же (`internal/recognize/validate.go`,
|
||||||
|
`confidence < AutoThreshold`, дефолт 0.85) делает `confidence` **жёстким
|
||||||
|
блокирующим условием**: план с матчем и чистой валидацией, но `confidence` 0.5
|
||||||
|
уйдёт в review вопреки сценарию спеки. Нужно определиться, что правда: либо
|
||||||
|
признать порог `AutoThreshold` в спеке как легитимный гейт (скорее так — код его
|
||||||
|
осознанно ввёл конфигом), либо ослабить код. Заодно `AutoThreshold` как
|
||||||
|
конфигурируемый гейт спекой не описан.
|
||||||
|
|
||||||
|
Связано: `openspec/specs/recognition` (требование «Модель уверенности и решение
|
||||||
|
auto/review»),
|
||||||
|
[ADR-2026-06-13-auto-link-requires-db-match](adr/ADR-2026-06-13-auto-link-requires-db-match.md),
|
||||||
|
пакет `recognize`.
|
||||||
|
|
||||||
|
### Привязка внешних субтитров к серии (сериалы)
|
||||||
|
|
||||||
|
Аудит спек↔код (2026-07-03): спека `recognition` требует «внешние субтитры SHALL
|
||||||
|
привязываться к соответствующему видео». Для **фильма** это работает — раскладка
|
||||||
|
именует субтитр по базе видеофайла. Для **сериала** связь субтитр→конкретная
|
||||||
|
серия не выражена: в `PlanFile` (`internal/recognize`) нет поля привязки, и нет
|
||||||
|
логики спаривания VobSub `.idx`+`.sub`. Нужно смоделировать привязку субтитра к
|
||||||
|
эпизоду (поле на `PlanFile` или роль с указанием `season`/`episode`) и спаривание
|
||||||
|
`.idx`+`.sub`, либо — если поддержку откладываем — сузить формулировку спеки до
|
||||||
|
реального поведения.
|
||||||
|
|
||||||
|
Связано: `openspec/specs/recognition` (требование «Роли файлов на краях»),
|
||||||
|
[jellyfin-layout.md](specs/jellyfin-layout.md) (имена субтитров), пакеты
|
||||||
|
`recognize`, `layout`.
|
||||||
|
|
||||||
|
### Раздачи-копии диска (DVD/BluRay: VIDEO_TS/BDMV)
|
||||||
|
|
||||||
|
Иногда для очень редких фильмов скачивается не один видеофайл, а **полная копия
|
||||||
|
диска** — структура `VIDEO_TS/` (DVD: `VIDEO_TS.IFO`, `VTS_01_1.VOB`…) или
|
||||||
|
`BDMV/` (BluRay: `BDMV/STREAM/*.m2ts`, `index.bdmv`). Сейчас распознавание и
|
||||||
|
раскладка заточены под пофайловый разбор (один main-видеофайл фильма / серии
|
||||||
|
сериала), а тут «фильм» — это **каталог целиком**. Jellyfin такие раскладки
|
||||||
|
поддерживает (папка фильма с вложенным `VIDEO_TS`/`BDMV`), нам нужно: распознать,
|
||||||
|
что раздача — это образ диска (по наличию `VIDEO_TS`/`BDMV`), не пытаться
|
||||||
|
разбирать её по отдельным VOB/m2ts как серии, и разложить весь каталог диска
|
||||||
|
хардлинками в папку фильма Jellyfin (`Название (Год)/VIDEO_TS/…`). Крайний, но
|
||||||
|
реальный случай для редких изданий; частота низкая, поэтому в «Среднем».
|
||||||
|
|
||||||
|
Связано: [recognition.md](specs/recognition.md) (роли файлов, что игнорируем),
|
||||||
|
[jellyfin-layout.md](specs/jellyfin-layout.md) (раскладка фильма, крайние
|
||||||
|
случаи), пакеты `recognize`, `layout`.
|
||||||
|
|
||||||
## Низкий
|
## Низкий
|
||||||
|
|
||||||
### Баг: ссылка на запись TVDB всегда `/series/` (для фильмов ведёт не туда)
|
### Баг: ссылка на запись TVDB всегда `/series/` (для фильмов ведёт не туда)
|
||||||
@@ -307,8 +358,15 @@ URL кандидата хардкодит `.../dereferrer/series/{id}` (там
|
|||||||
виден в UI. Фикс — подставлять тип запроса в URL (одна строка); заодно
|
виден в UI. Фикс — подставлять тип запроса в URL (одна строка); заодно
|
||||||
свериться, что `providerURL` не расходится по типам.
|
свериться, что `providerURL` не расходится по типам.
|
||||||
|
|
||||||
|
> Аудит спек↔код (2026-07-03) подтвердил баг и выявил, что спека
|
||||||
|
> `metadata-match` теперь тоже «узаконивает» его: требование «Кандидат несёт
|
||||||
|
> URL» задаёт для TVDB единственный формат `/dereferrer/series/{id}` без
|
||||||
|
> различения типа. Фикс должен править и код, и это требование (movie-вариант
|
||||||
|
> по аналогии с TMDB).
|
||||||
|
|
||||||
Связано: [recognition.md](specs/recognition.md) (сверка с базой, кандидаты),
|
Связано: [recognition.md](specs/recognition.md) (сверка с базой, кандидаты),
|
||||||
пакеты `metadata`, `httpapi`.
|
`openspec/specs/metadata-match` (требование «Кандидат несёт URL»), пакеты
|
||||||
|
`metadata`, `httpapi`.
|
||||||
|
|
||||||
### Мгновенные обновления через SSE
|
### Мгновенные обновления через SSE
|
||||||
|
|
||||||
|
|||||||
@@ -78,12 +78,13 @@ Worker SHALL периодически сверять раздачи qBittorrent
|
|||||||
- **WHEN** worker сверяет qBittorrent с БД
|
- **WHEN** worker сверяет qBittorrent с БД
|
||||||
- **THEN** для раздачи заводится загрузка в состоянии `downloading`
|
- **THEN** для раздачи заводится загрузка в состоянии `downloading`
|
||||||
|
|
||||||
### Requirement: Переходы состояний под per-download блокировкой
|
### Requirement: Переходы состояний сериализуются воркером
|
||||||
|
|
||||||
Все переходы состояний загрузки SHALL проходить через worker под per-download
|
Все переходы состояний загрузки SHALL сериализоваться worker'ом под единой
|
||||||
блокировкой, чтобы два транспорта не гонялись за одно состояние. Состояние SHALL
|
блокировкой (поллинг-цикл и команды всех транспортов проходят через неё), чтобы
|
||||||
быть персистентным в SQLite; активность загрузки SHALL выводиться только из
|
два источника перехода не гонялись за одно состояние. Состояние SHALL быть
|
||||||
`state`, без отдельного флага.
|
персистентным в SQLite; активность загрузки SHALL выводиться только из `state`,
|
||||||
|
без отдельного флага.
|
||||||
|
|
||||||
#### Scenario: Команды сериализуются
|
#### Scenario: Команды сериализуются
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ movie↔series), **Игнор файла**, **Позже** (`deferred`), **От
|
|||||||
(`cancelled`), **Undo** (снять созданные ссылки → `reverted`) и **Привязать
|
(`cancelled`), **Undo** (снять созданные ссылки → `reverted`) и **Привязать
|
||||||
заново** (из `reverted`/`cancelled`/`target_missing` → перераспознавание с ручным
|
заново** (из `reverted`/`cancelled`/`target_missing` → перераспознавание с ручным
|
||||||
подтверждением). Команды из любого транспорта SHALL сериализоваться worker'ом под
|
подтверждением). Команды из любого транспорта SHALL сериализоваться worker'ом под
|
||||||
per-download блокировкой; применяется последняя валидная команда. Команды,
|
единой блокировкой; применяется последняя валидная команда. Команды,
|
||||||
которым нужен источник, SHALL проверять его наличие синхронно перед действием.
|
которым нужен источник, SHALL проверять его наличие синхронно перед действием.
|
||||||
|
|
||||||
#### Scenario: Применение создаёт раскладку
|
#### Scenario: Применение создаёт раскладку
|
||||||
|
|||||||
Reference in New Issue
Block a user