# 🐞 Обновлять карточку списка после завершения загрузки - **Тип:** fix - **Категория:** Ядро продукта - **Зачем:** завершённая загрузка висит в списке с бейджем «Загружается» до ручной перезагрузки: карточка самополлится только в catched, а прогресс перестаёт поллить, выйдя из downloading — обновлять карточку становится некому Карточка списка показывает состояние, которого уже нет: качание кончилось, задача ушла в распознавание и дальше в ревью, а на экране прежний бейдж и прежний набор действий. Причина видна в коде. Самополлинг карточки включает поле `SelfPoll`, а оно истинно только в `catched` (`internal/httpapi/httpapi.go:664`, `web/templates/partials/card.html:2`). Внутренний фрагмент прогресса поллится, пока состояние `downloading` (`internal/httpapi/live.go:88`, `web/templates/partials/progress.html:1`). Задача, покинувшая `downloading`, не опрашивается уже ничем. На странице `/download/{id}` то же самое: `web/templates/partials/download_main.html:2` самополлится только в `catched` (`internal/httpapi/download.go:116`). Спека нынешнее поведение не запрещает: `live-status` → «Живой прогресс активных загрузок» прямо требует прекращать поллинг прогресса на выходе из `downloading`, а `web-ui` → «Отображение промежуточного состояния catched» заказывает самообновление только для перехода `catched` → `downloading`. Поэтому починка несёт дельту спеки, а не только правку кода. ## Воспроизведение 1. Открыть главную `/`, добавить раздачу, дождаться состояния `downloading`. 2. Страницу не перезагружать. Дождаться, пока qBittorrent доведёт раздачу до 100% и воркер уведёт задачу из `downloading` (в `recognizing`, дальше в `review` или `done`). 3. Наблюдается: бейдж карточки остаётся «Загружается», прогресс-бар замирает на последнем значении, кнопка «Ревью →» не появляется. Фоновых запросов от этой карточки в панели сети больше нет. 4. Ожидается: карточка сама показывает новое состояние — бейдж, набор действий, исчезнувший прогресс. 5. Перезагрузить страницу руками: карточка сразу показывает верное состояние — расходится отображение, а не данные. ## Затрагивает - фрагменты `GET /fragments/downloads/{id}/card` и `GET /fragments/downloads/{id}/progress` (`internal/httpapi/live.go`); - поле `SelfPoll` вида карточки и вида страницы загрузки (`internal/httpapi/httpapi.go`, `internal/httpapi/download.go`); - шаблоны `web/templates/partials/card.html`, `progress.html`, `download_main.html`; - спека `web-ui`, требование «Отображение промежуточного состояния catched» — условие самообновления перестаёт быть привязанным к одной фазе; - спека `live-status`, требование «Живой прогресс активных загрузок» и его сценарий «Завершение останавливает поллинг» — прекращение поллинга прогресса перестаёт означать прекращение обновления карточки. ## Критерии приёмки - Карточка нетерминальной загрузки самополлится, и первый ответ фрагмента после смены состояния несёт новый бейдж (оракул: тест `internal/httpapi` — рендер карточки в `downloading` содержит `hx-get` на `/fragments/downloads/{id}/card`, а подставной читатель, сменивший состояние на `review`, отдаёт карточку с бейджем ревью). - Терминальная карточка себя не опрашивает: фоновых запросов после `done`, `failed`, `cancelled` и `deleted` нет (оракул: тот же тест — в разметке такой карточки нет ни `hx-get`, ни `hx-trigger`). - Появившееся действие видно без перезагрузки: карточка задачи, перешедшей в `review`, несёт кнопку «Ревью →» (оракул: тест фрагмента карточки). - Страница `/download/{id}` обновляет бейдж и блок действий по тому же правилу, что и карточка (оракул: тест `internal/httpapi/download.go` — `SelfPoll` истинен для нетерминальных состояний и ложен для терминальных). - Правило записано в дельта-спеках обеих затронутых capability (оракул: `openspec validate --strict` и шаг канона в `task gate`). ## Рамки Чинится поллингом фрагментов: переход на SSE — отдельная задача `sse-live-updates`, и эта починка её не делает и не отменяет. Расширение самополлинга на все нетерминальные состояния добавляет фоновых запросов к БД — частота и её потолок решаются в предложении, а не молча.