diff --git a/docs/backlog/README.md b/docs/backlog/README.md index a3315a0..c603012 100644 --- a/docs/backlog/README.md +++ b/docs/backlog/README.md @@ -32,7 +32,6 @@ Tududi (проект `jellybit`) больше **не** держит беклог - [Бэкап SQLite](backup-sqlite.md) — architecture - [Сигнал Jellyfin после отката и удаления файлов](jellyfin-skan-posle-udaleniya.md) — Скан шлётся только на done; после reverted/deleted Jellyfin держит битые записи. Клиент и гейт готовы, но скана нет в openspec-спеках - [Режиссёр в блоке «Распознано как» на странице загрузки](rezhisser-v-kartochke-zagruzki.md) — На /download/{id} режиссёр всегда прочерк (поля нет в шаблоне); экран ревью его уже выводит -- [Карточка информации о торренте вылезает за границу экрана на мобильном](mobilnaya-verstka-kv-infohash.md) — grid-blowout на .kv из-за неразрывного infohash — страница получает горизонтальный скролл - [Глубокий healthcheck и статус зависимостей](healthcheck-zavisimosti.md) — /healthz проверяет только сам сервис - [НФТ: масштаб до 100 одновременных загрузок (потолок — 1000)](masshtab-100-zagruzok.md) — Зафиксировать в НФТ ориентир 100/1000 загрузок + аудит узких мест (SQLite, воркер, поллинг) - [Обучение на правках человека (few-shot из прошлых ревью)](obuchenie-na-pravkah.md) — Когда человек поправил матч, тип или нумерацию — сохранять это как пример и подмешивать… @@ -43,7 +42,6 @@ Tududi (проект `jellybit`) больше **не** держит беклог ## Низкий -- [Кнопки выглядят как кнопки: `btn-ghost` и рассогласование весов](unifikaciya-knopok-btn-ghost.md) — «Откатить» неотличима от текста: btn-ghost прозрачен, аффорданс только на hover; плюс одно действие имеет разный вес в списке и на странице - [Ревью уведомлений в Telegram (аудит текстов и формата)](telegram-revyu-uvedomleniy.md) — зонтичный проход по всем текстам бота: полнота карточек, единый язык, оформление; порождает под-задачи - [Download id в Telegram моноширинным (code) для tap-to-copy](telegram-download-id-code.md) — слать id как `code`; требует включить parse mode (HTML) в send() + escape всех текстов - [Мгновенные обновления через SSE](sse-obnovleniya.md) — Живые обновления прогресса сейчас на htmx-поллинге (фаза 2 веб-UI) — просто и работает… @@ -61,6 +59,4 @@ Tududi (проект `jellybit`) больше **не** держит беклог - [Авторизация веб-UI (на будущее)](avtorizaciya-web-ui.md) — Решено для v1: без авторизации в доверенной LAN, опц - [Современный Web-UI как PWA](web-ui-pwa.md) — Переделать веб-интерфейс в современное PWA-приложение (устанавливаемое, отзывчивое… - [Идентичность инфохэшей: 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)_ - [Нити приёма: NoName в контексте, устаревшие комментарии, лог без причины, bencode-аллокации (N1, N3, N4, N5)](review-ingest-nits.md) — косметика приёма: NoName в контексте, устаревшие комментарии, лог, bencode-аллокации _(ревью 2026-07-08)_ diff --git a/docs/backlog/mobilnaya-verstka-kv-infohash.md b/docs/backlog/mobilnaya-verstka-kv-infohash.md deleted file mode 100644 index fa54c67..0000000 --- a/docs/backlog/mobilnaya-verstka-kv-infohash.md +++ /dev/null @@ -1,56 +0,0 @@ -# Карточка информации о торренте вылезает за границу экрана на мобильном - -**Приоритет:** средний - -На узком экране блок «Информация о торренте» на `/download/{id}` выталкивает -страницу за вьюпорт — появляется горизонтальный скролл всей страницы. - -## Причина - -Grid-blowout на `.kv` из-за неразрывного infohash: - -- `web/templates/partials/download_main.html:83-86` — `
` с - `
{{.}}
` для каждого инфохэша. -- `web/static/css/jellybit.css:448-451` — `.kv{grid-template-columns:auto 1fr}`, - у `.kv dd` **нет** `overflow-wrap`/`word-break`/`min-width:0`. Трек `1fr` = - `minmax(auto,1fr)`, его автоминимум = min-content = весь 40-символьный хэш. - -Арифметика на 360px: доступно ≈302px, требуется ≈380px (`dt` «infohash» nowrap -≈52px + gap 16px + хэш ≈312px) → переполнение ~78px. `overflow-x:hidden` на -`body`/`html` нигде нет, поэтому блок физически ломает страницу. - -Недавние коммиты про ellipsis (`44c5952` — только `.btn-file`) и `.type-ico` -(`3f80d36`) этот блок не трогали. - -## Что уже защищено (не виновники) - -- `jellybit.css:283-285` — `.src-full{word-break:break-all}` → magnet уже чинится. -- `jellybit.css:365-366` — `.table-wrap{overflow-x:auto}` + `table.tbl{min-width:560px}` - → таблица раскладки скроллится внутри себя. Страницу не ломает, но 560px - принудительного горизонтального скролла на мобильном — отдельная заноза. -- `.fname`/`.link-to` (`:374`, `:378-379`), `.card-title` (`:205`), - `.review-title` (`:298`) — `word-break` есть. - -## Развилки - -- **(а) точечно:** `.kv dd{overflow-wrap:anywhere;min-width:0}` + - `.kv dd.mono{word-break:break-all}`. -- **(б) в медиа-запросе** перевести `.kv` в одну колонку - (`grid-template-columns:1fr`, `dd{text-align:left}`) — заодно снимает - проблему `dt{white-space:nowrap}`. - -Учесть: `.kv` используется **и** в блоке «Распознано как» -(`download_main.html:34-43`) — правка затронет оба, то есть чинится и потенциально -длинный `RecTitle`. Страховку `body{overflow-x:hidden}` как единственную меру не -брать — маскирует, а не лечит. - -Мобильных стилей почти нет: единственный `@media (max-width:640px)` — -`jellybit.css:477-492` (14 правил), ни `.kv`, ни `.table-wrap` в нём не упомянуты. - -## Спеки - -`openspec/specs/web-ui/spec.md:237-247` («Блок информации о торренте») требований -к адаптивности не содержит → либо чистый bugfix, либо дельта с требованием -переноса длинных значений. - -Связано: [[web-ui-pwa]] (крупная переделка, этот фикс — точечный). diff --git a/docs/backlog/review-f7-f10-ingest-ui-fixes.md b/docs/backlog/review-f7-f10-ingest-ui-fixes.md deleted file mode 100644 index ab40783..0000000 --- a/docs/backlog/review-f7-f10-ingest-ui-fixes.md +++ /dev/null @@ -1,17 +0,0 @@ -# Приём/UI: мелкие фиксы границ и парсинга (F7, F8, F9, F10, N2) - -**Приоритет:** низкий · **Теги:** ingest, review-2026-07-08 - -Ревью Fable 2026-07-08 (приём). Пачка независимых простых фиксов. - -F7 — oversized .torrent через веб → 500 вместо 400. ingest.go:148-151 отдаёт plain fmt.Errorf «torrent too large», classifyErr (httpapi.go:753-770) → default → 500. Web MaxBytesReader пропускает MaxTorrentSize+1MiB. Фикс: sentinel-ошибка размера → 400. (Telegram ок — pre-check doc.FileSize.) - -F8 — fast-path attach гонка с cancel. ingest.go:85-90,205-217: FindActiveByInfohash (без tx) вернул catched, параллельно cancel → attached() отдаёт Deduplicated=true (stale «уже в работе»), ничего не активно. Фикс: убрать ранний return, дедуп-решение только в CreateDownloadIfNoActive (уже re-check под BEGIN IMMEDIATE). - -F9 — magnet parsing. magnet.go:46-51: HasPrefix «urn:btih:» регистрозависим → magnet:?xt=URN:BTIH:… отклоняется (RFC 2141: URN регистронезависим; scheme уже матчится EqualFold :91). tgbot/parse.go:11: magnet:\?[^\s]+ приклеивает хвостовую пунктуацию (точка/скобка) → xt последним → длина 41 → отказ. Фикс: case-insensitive префикс; trim хвостовых .,;:)]}>» в ParseMessage. - -F10 — cap размера context из веб-формы. httpapi.go:405,412-414: multipart-бюджет на всё тело; без файла поле context ~9MiB → download.context в БД, рендер, LLM-промпты. REST 64KiB, Telegram лимит подписи — открыт только web. Фикс: cap Context в Ingest (одно место) ~16KiB с маркером. - -N2 — shorten() режет по байтам не рунам (httpapi.go:713-718): кириллические source_ref-заголовки (частый случай) рвутся посреди руны → U+FFFD. Фикс: рунобезопасная обрезка. - -Вердикт: все простые фиксы. diff --git a/docs/backlog/review-lifecycle-minor.md b/docs/backlog/review-lifecycle-minor.md deleted file mode 100644 index 3559c11..0000000 --- a/docs/backlog/review-lifecycle-minor.md +++ /dev/null @@ -1,15 +0,0 @@ -# Жизненный цикл: мелкие находки (MINOR-8, MINOR-9, NIT-11, NIT-12) - -**Приоритет:** низкий · **Теги:** review-2026-07-08, lifecycle - -Ревью Fable 2026-07-08 (жизненный цикл). Мелкие находки. - -MINOR-8 — recognition claim-token отсутствует. review.go:160-177: задача в recognizing, LLM в полёте (вне w.mu); user Cancel→Relink (recognizing→cancelled→recognizing revive). Старый вызов завершается, finishRecognition re-check d.State==recognizing — true, но это НОВЫЙ claim → устаревший результат коммитится (recognizing→review); свежий прогон отбрасывает себя. Импакт низкий (входы почти идентичны), но потерянный LLM-вызов + результат приписан не той попытке. Фикс: claim-token (updated_at на момент claim, или id строки recognition). - -MINOR-9 — I/O под глобальным w.mu. worker.go:677-734 (Retry: torrentByInfohash + qbt.Add под mu), review.go: ensureSourcePresent (сеть) в Relink/Rerecognize/Refine/SetType, Apply (torrentByInfohash + layouter.Apply FS I/O), Undo (FS I/O) — держат w.mu целиком. Нарушает своё же правило «медленные вызовы вне блокировки» (processCatched/recognizeOne его соблюдают). Медленный/зависший qBit → каждый клик ревью = глобальный стопор поллинга и всех команд транспортов. Корректность ок (lock даёт race-free preflight), только liveness. Для one-user home-сервера — можно осознанно waive; худший — Retry с qbt.Add под mu при зависшем qBit. Фикс если делать: probe-вне-lock + re-validate-под-lock (как processCatched). - -NIT-11 — byHash индексирует и усечённый 40-hex t.Hash v2-only торрентов (worker.go:444-452). Хранение усечённых хешей отклоняется (discover.go:98-111), но lookup-мапа всё ещё ключует t.Hash → v1-хеш одной задачи теоретически == усечённый-v2 t.Hash другого торрента → матч не тому. Требует 160-бит коллизию (космологические шансы). Фикс: исключить t.Hash из мапы, когда есть infohash_v1/v2 (зеркалить torrentHashes). - -NIT-12 — Retry на failed/qbit_error (missingFiles) с живым errored-торрентом: alive=true → без re-Add → downloading → следующий тик classErrored → снова failed (+ дебаунс уведомления). Честно, но user-hostile: retry выглядит сломанным, реальное лекарство (recheck/fix в qBit) не подсказано. Фикс: отклонять retry (или форсить recheck) когда живой торрент classErrored. (Связано с задачей retry/stall семантики.) - -Вердикт: MINOR-8/NIT-11/NIT-12 — простые фиксы; MINOR-9 — change или осознанный waive. diff --git a/docs/backlog/unifikaciya-knopok-btn-ghost.md b/docs/backlog/unifikaciya-knopok-btn-ghost.md deleted file mode 100644 index 7901140..0000000 --- a/docs/backlog/unifikaciya-knopok-btn-ghost.md +++ /dev/null @@ -1,64 +0,0 @@ -# Кнопки выглядят как кнопки: `btn-ghost` и рассогласование весов - -**Приоритет:** низкий - -Кнопка «Откатить» в списке загрузок неотличима от текста/ссылки. Это **не** -разметка — там уже `