diff --git a/docs/tasks/SPRINT.md b/docs/tasks/SPRINT.md index b827faf..3827c77 100644 --- a/docs/tasks/SPRINT.md +++ b/docs/tasks/SPRINT.md @@ -10,6 +10,5 @@ - [✨ Брать у TVDB название на языке настройки и оригинальное название](items/tvdb-title-locale.md) — [general].language правит только TMDB и промпт LLM — TVDB отдаёт primary name, и при language=ru в карточку ревью и имя папки попадает 哪吒之魔童降世 вместо «Нэчжа» - [✨ Узаконить confidence-гейт авто-раскладки в спеке и сделать его выключаемым (дефолт 0.7)](items/auto-link-confidence-gate.md) — Решено (B): гейт оставляем как доп. проверку на ревью — выключаемый порог, дефолт 0.85→0.7, записать в спеку -- [🧹 Зафиксировать в спеке разделение Cancel и Dismiss по состояниям](items/dismiss-marker-lost.md) — спека обещает dismiss из любого состояния, код осознанно даёт Cancel для активных и Dismiss для терминальных — расходится буква, а не поведение - [🐞 Тормозить опрос qBittorrent бэкоффом при недоступности и эскалировать устойчивый сбой](items/background-error-noise.md) — недоступный qBittorrent опрашивается каждые 5 с и даёт WARN на каждом тике: нужен экспоненциальный бэкофф до минутного потолка со сбросом по первому успеху и ERROR на устойчивой деградации - [🧹 Закрыть мелочи приёма: NoName в контексте, устаревшие комментарии, лог без причины, bencode-аллокации (N1, N3, N4, N5)](items/ingest-nits.md) — косметика приёма: NoName в контексте, устаревшие комментарии, лог, bencode-аллокации _(ревью 2026-07-08)_ diff --git a/docs/tasks/items/dismiss-marker-lost.md b/docs/tasks/items/dismiss-marker-lost.md deleted file mode 100644 index 5d51272..0000000 --- a/docs/tasks/items/dismiss-marker-lost.md +++ /dev/null @@ -1,69 +0,0 @@ -# 🧹 Зафиксировать в спеке разделение Cancel и Dismiss по состояниям - -- **Тип:** chore -- **Категория:** Ядро продукта -- **Зачем:** спека обещает dismiss из любого состояния, код осознанно даёт Cancel для активных и Dismiss для терминальных — расходится буква, а не поведение - -Найдено аудитом capability **state-reconciliation** (сверка код↔спека). -Пред-существующее, вне scope пачки lifecycle-задач. - -## Суть - -Спека `openspec/specs/state-reconciliation/spec.md` (требование «Ручное -закрытие»): команда `dismiss` доступна из **любого** состояния кроме `deleted` -**во всех транспортах**, и переход SHALL помечаться `error_code = user_dismiss`. - -В веб-UI danger-zone «Закрыть» (dismiss) гейтится только для терминальных -состояний: `Dismissable = IsTerminal() && !deleted && !cancelled` -(`internal/httpapi/download.go:130`, шаблон -`web/templates/partials/download_main.html:99-112`). Для НЕ-терминальных -(`stuck`, `deferred`, `downloading`, `review`) закрытие в UI идёт кнопкой -«Отменить» → `Cancel` (`internal/worker/worker.go:973`), которая пишет **пустой** -`error_code`, а не `user_dismiss`. - -## Насколько больно - -Функционально сценарии проходят: `Cancel` тоже даёт `cancelled` и не трогает -файлы/раздачу, семантика для пользователя идентична. Состояния без доступного -«закрытия» нет (кроме `deleted`/`cancelled`). Теряется только маркер -`user_dismiss` в `error_code` — расхождение с буквой спеки и небольшая потеря -наблюдаемости (в аналитике/логах не отличить «пользователь закрыл активную» от -«пользователь отменил»). Отсюда низкий приоритет. - -## Решение (2026-08-06): B — привести спеку к коду - -Разделение осознанное: `Cancel` — стоп-кран для активных состояний, `Dismiss` — -закрытие терминальных. Требование «Ручное закрытие» уточняется: на -не-терминальных состояниях закрытие из интерфейса реализуется `Cancel`'ом, и -называется, какой `error_code` при этом ожидается. - -Вариант A (звать `Dismiss` из веб-UI на не-терминальных ради единого маркера) -отклонён: он меняет рабочее поведение ради маркера в диагностике. - -Кода задача не трогает: наблюдаемое поведение остаётся прежним, меняется -заявленное. - -## Затрагивает - -- `openspec/specs/state-reconciliation/spec.md` — требование «Ручное закрытие»: - доступность `dismiss` по состояниям и ожидаемый `error_code`; -- дельта-спека change'а — сценарий закрытия не-терминальной загрузки из веб-UI; -- `internal/httpapi/download.go`, `web/templates/partials/download_main.html` — - только чтение, правок не предполагается. - -## Критерии приёмки - -- Требование спеки различает `Cancel` и `Dismiss` по состояниям и называет - `error_code` для каждого пути закрытия (оракул: `openspec validate --strict`). -- В спеке есть сценарий «пользователь закрывает не-терминальную загрузку из - веб-UI» с исходом `cancelled` и названным `error_code` (оракул: тот же - прогон). -- Гейт `Dismissable` в коде и danger-zone шаблона остаются как есть (оракул: - `git diff --stat` в отчёте ревью — файлов под `internal/` и `web/` нет). - -## Ссылки - -- `internal/httpapi/download.go:130` — гейт `Dismissable` -- `web/templates/partials/download_main.html:99-112` — danger-zone -- `internal/worker/worker.go:973` — `Cancel`; `:1001` — `Dismiss` -- `openspec/specs/state-reconciliation/spec.md` — требование «Ручное закрытие»