Commit Graph
16 Commits
Author SHA1 Message Date
avandClaude Opus 4.8 c4c0c6bb3f Беклог: груминг трёх задач из Tududi (значок типа, download id code, ревью уведомлений)
Перенос сырых задач проекта jellybit из Tududi в беклог с контекстом и
кросс-ссылками:
- значок типа (фильм/сериал) в списке загрузок;
- download id моноширинным (code) в Telegram — упирается в parse mode + escape;
- зонтичный аудит уведомлений бота.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-11 09:15:56 +03:00
avandClaude Opus 4.8 e8ce828296 Беклог: полный формат ярлыка «Обновить имя» + скрытие cancelled в списке
- Кнопка «Обновить имя» должна давать формат add-шага (Название (режиссёр,
  год), сезон; всё опц. кроме названия) вместо усечённого «Title (Year)».
- Отменённые (cancelled) скрывать в общем списке наравне с удалёнными;
  тумблер «показать удалённые» раскрывает и cancelled, и deleted.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 20:25:11 +03:00
avandClaude Opus 4.8 b8657120fe Приём: усыновление присутствующего в qBittorrent торрента вместо дубль-Add (409)
processCatched перед Add проверяет присутствие торрента в qBittorrent (один
листинг на тик): если раздача уже есть — усыновляем (promote catched→downloading
без повторного Add и без LLM-namer, имя из раздачи), иначе добавляем как раньше.
Это убирает бесконечный цикл дубль-Add → 409 → ретрай и лишние вызовы LLM.
Инвариант приёма «одна активная на infohash» делает различие «наш/чужой»
ненужным. source_type перечитывается под замком (сужение гонки апгрейда F6);
при недоступности qBittorrent тик пропускается без вызова LLM.

Дедуп на приёме (дубль на уже активную задачу) теперь отражается явным ответом
бота «дубль уже активной #id — добавление отменено».

Спека download-tracking обновлена (OpenSpec change заархивирован); закрыта
задача беклога review-f2-promote-without-add.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 18:36:47 +03:00
avandClaude Opus 4.8 7d8a455e47 Логирование: классификация доменных ошибок (500→409/400) + конвенции
Штатные конфликты и промахи ввода возвращались голым fmt.Errorf, поэтому
classifyErr отправлял их в 500 «внутренняя ошибка» вместо 409/400 (и logCmd
писал ERROR вместо DEBUG). Продолжение f8fb4fa (Tier A), по итогам ревью Fable.

Классификация ошибок:
- новый sentinel worker.ErrInvalidInput → 400 для валидации ввода команд
  (refine/set type/ignore/add source/set provider/choose candidate);
- обёртки %w ErrConflict в Cancel/Retry/Defer/Undo (штатный конфликт состояния);
- classifyErr: ErrInvalidInput→400, layout.ErrCollision→409 (коллизия цели
  штатно уводит в review); ветка ErrCollision в tgbot (сообщение + refreshCard);
- logCmd относит ErrInvalidInput и ErrCollision в DEBUG «command rejected».

Конвенции (docs/conventions):
- logging.md: публичные команды воркера = доменная граница (лог один раз,
  logCmd); таблица уровней доменных отказов (граница команды vs асинхронная
  стадия); правило про *url.Error/секреты в URL; канон категории
  state transition; уровень повторяющихся сбоев фоновых циклов;
- errors.md: таблица маппинга ошибка→статус; развилка «транзиентный ответ vs
  персистентная диагностика» решена как (а) — error_msg/reasons на review-экране
  и tg-карточке = операторская поверхность владельца (сырой текст ок, секреты
  запрещены; аудит подтвердил, что секреты туда не текут).

Унификация категории лога state transition: cancel/retry/relink/recovery
переведены с семантических msg на общий state transition (from/to) — весь
жизненный цикл собирается одним jq-фильтром.

Мелочи: reason-коды linkPlan в const-блок; httpapi лог-поля id→download_id и
msg «… failed»; комментарий «почему» у parseIgnored; preview build failure в
ReviewData DEBUG→WARN.

Беклог: задача сведена к остатку (ext.* ERROR-шторм при недоступном qBittorrent
+ эскалация устойчивого сбоя тика), понижена в приоритете.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 14:57:12 +03:00
avandClaude Opus 4.8 864c44aebd Беклог: классификация доменных ошибок (500→409/400) и конвенции логирования
Отложенные Tier B/C по итогам ревью Fable (продолжение f8fb4fa): sentinel-
обёртки ErrConflict/валидации, classifyErr для layout.ErrCollision, единая
категория переходов, правила уровней и *url.Error/секретов в docs/conventions,
решение по сырому err.Error() в reasons/error_msg.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 14:32:09 +03:00
avandClaude Opus 4.8 5c3ef79496 Раскладка: сходимость папки сериала (второй сезон в ту же папку)
При подтверждённом матче база папки (имя+год) наследуется от живой
папки-якоря того же (provider, provider_id) вместо печати заново из выхода
LLM — так второй/последующий сезон ложится в ТУ ЖЕ папку, а не заводит
рядом почти одинаковую. Отдельная сущность «тайтл» не вводится.

- layout: Plan.FolderBase перекрывает базу в папке и именах файлов;
  TitleFolder разбирает dst_path в папку тайтла и базу (снятие тега).
- store: LiveTitleFolders — dst_path живых ссылок того же матча.
- worker: resolveFolderBase (живость якоря — по наличию папки на диске,
  os.Lstat, а не по статусу ссылки в БД) в linkPlan и в превью ревью
  (превью=применение); рассинхрон нескольких живых папок → review из
  linking (deferred→review в графе нет).

Схема БД не менялась. Change series-folder-convergence заархивирован,
требования влиты в openspec/specs/file-layout.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 13:50:49 +03:00
avandClaude Opus 4.8 3f1a928000 Единое окно: полное пользовательское удаление загрузки (delete)
Вторая половина «единого окна»: команда «Удалить» снимает наши библиотечные
хардлинки (гард последней копии осознанно выключен, в отличие от Undo) и сносит
раздачу с файлами из qBittorrent (deleteFiles=true) → терминальный deleted.
Доступна из done/orphaned/target_missing, идемпотентна к отсутствующей стороне;
инициатор различается через error_code=user_delete. Подтверждение обязательно:
веб — danger-секция внизу страницы (hx-confirm + details), Telegram — двухшаговый
inline-confirm. qbt.Delete + layout.Remove (unlink без ErrLastCopy, только свои
ссылки под movies/series). Граф переходов не менялся — рёбра уже были.

OpenSpec: state-reconciliation +1 требование; синк workflow.md; беклог закрыт.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 12:17:51 +03:00
avandClaude Opus 4.8 93a1ba8e7e Тулинг: скилл task-pipeline + два ревьювера качества
Скилл .claude/skills/task-pipeline оркеструет задачу по SDD от беклога до
коммита (opsx explore→propose→ревью спек→apply→ревью кода→archive→чистка
беклога), автономно, с выходом на пользователя только на развилках.

Кастомные ревьюверы .claude/agents: jellybit-review-specs (оптика спек) и
jellybit-review-code (архитектура/инварианты/конвенции/стиль). Подключены как
чекпоинты скилла: на тривиальной задаче — один review-code, на нетривиальной —
оба параллельно.

Частично закрывает беклог-задачу agenty-revyuvery-kachestva: остался ревьювер
наименований (ждёт словарь единого языка).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 11:37:00 +03:00
avandClaude Opus 4.8 2bd2a97bfc Беклог: длинное имя .torrent-файла ломает верстку add-row
Выбор .torrent с длинным именем распирает лейбл файл-пикера (нет ограничения
ширины у .btn-file), поле source сжимается, «Добавить» уезжает. Косметика:
ellipsis на лейбле; фикс-хуки на CSS/шаблон в теле задачи.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 18:36:14 +03:00
avandClaude Opus 4.8 2a5a65f2d5 Приём: пропажа источника у активной загрузки → failed(source_gone) (MAJOR-3)
Раздача активной (downloading) загрузки, исчезнувшая из qBittorrent (удалил
пользователь/другой клиент), делала задачу вечным зомби: поллинг промахивался
по torrentFor, писал Warn и continue каждый тик — состояние не менялось,
уведомления и телеметрии не было, checkTimeouts без торрента не срабатывал.
Пропажей источника у downloading не владел никто (сверка рассинхрона покрывает
только done/target_missing/orphaned, восстановление — failed/stuck).

Активный цикл Poll теперь применяет тот же дебаунс пропажи источника, что и
сверка рассинхрона (source_miss_count / source_missing_threshold): после порога
подряд идущих промахов задача уходит downloading → failed с distinct error_code
source_gone и уведомлением. До порога транзиентная недоступность qBit
(рестарт демона) задачу не роняет. source_gone восстановлению сверкой не
подлежит (удаление намеренно), но штатно retriable — Retry заново отдаёт
сохранённый источник; Retry сбрасывает source_miss_count, чтобы вернувшаяся
задача получила полное грейс-окно, а не упала снова на ближайшем тике.

Ребро downloading → failed уже было в графе, миграций/полей БД нет. Спека
download-tracking дополнена требованием, диаграмма workflow.md — ребром.
Change downloading-source-gone заархивирован.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 18:05:04 +03:00
avandClaude Opus 4.8 bfd469bd43 Беклог: закрыты F1, F6, MAJOR-1/2, MAJOR-4, MINOR-7
Реализованы и прошли ревью параллельной волной (worktree):
- F1 (гард дедуп-дозаписи) + F6 (апгрейд catched-magnet→torrent)
- MAJOR-1/2 (сброс базиса ретрая + простой от last_activity) + клэмп
  last_activity из будущего
- MAJOR-4 (sweep linking + persist→review) + MINOR-7 (transitionErr)

Суть переехала в openspec/specs (ingest, state-reconciliation,
file-layout) и в код. В F2 добавлен указатель на смежное окно
F6↔воркер, найденное этим ревью.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 17:37:44 +03:00
avandClaude Opus 4.8 b1bca98738 Ревью: preflight готовности источника для команд ревью (MAJOR-5)
Команды ревью проверяли только наличие раздачи в qBittorrent, но не её
готовность. Недокачанную задачу можно припарковать в deferred, затем
«Распознать заново» → recognizing → авто-раскладка (Rerecognize/Refine/
SetType не ставят force_review) → хардлинки на неполные файлы. Даже ручной
Apply не имел preflight завершённости.

Вводим ensureSourceReady (classify(t.State)==classReady) вместо
ensureSourcePresent во всех командах, которым нужен источник (Relink/
Rerecognize/Refine/SetType), и inline-проверку класса в Apply — последний
рубеж перед хардлинками. Недокачанный источник → отдельный sentinel
ErrNotReady (409) с actionable-текстом «торрент ещё качается» в web и
Telegram, без reconcile (состояние deferred/review легитимно).

Change review-readiness-preflight заархивирован, дельта влита в
openspec/specs/review.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 16:40:49 +03:00
avandClaude Opus 4.8 a43adea723 Беклог: переоформить path-2 удаления в одну задачу «полное удаление»
Обсудили: для сервиса одного окна основное действие — удалить всё разом (раздачу
+ файлы в библиотеке), чтобы освободить место. Из-за хардлинков иначе место и не
вернуть — снять надо обе ссылки на инод. Задача udalenie-edinoe-okno переписана в
одну конкретную:

- действие «Удалить» на загрузке: снять живые хардлинки (undo-механика, superseded
  пропускаем) + удалить раздачу с файлами из qBittorrent (новый метод qbt);
  осознанно обходим предохранитель последней копии; обязательное подтверждение;
- undo (перераспознать, гард включён) vs delete (освободить место, гард выключен)
  зафиксированы как разные действия;
- терминальное состояние — переиспользуем deleted, инициатора (user/reconcile)
  пишем в лог перехода; в граф добавить ребро done→deleted;
- тайтл-группа и экран состава выкинуты как оверинжиниринг; мультивыбор в списке —
  опциональный шаг.

Реализовать как OpenSpec-change. Приоритет высокий (недостающая половина одного
окна, частый сценарий «досмотрел → освободить место»).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 15:43:26 +03:00
avandClaude Opus 4.8 2ed42b3e18 Беклог: решение по confidence-гейту (вариант B, дефолт 0.7)
Обсудили расхождение спека↔код по авто-раскладке. Решение: гейт по confidence
оставляем — низкий confidence служит доп. проверкой на ревью (LLM могла ошибиться
так, что под ошибку нашёлся самосогласованный матч в базе). Задача
gate-confidence-spec-vs-code переоформлена из «определиться» в конкретную:
сделать порог реально выключаемым (0 = выкл, сейчас 0 молча возвращается к
дефолту), понизить дефолт 0.85→0.7, узаконить confidence в спеке recognition как
конфигурируемое четвёртое условие, дока + тесты. Реализовать как OpenSpec-change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 15:31:05 +03:00
avandClaude Opus 4.8 8ad4273db2 Беклог: ревью задач и приоритетов по итогам сверки с кодом
Прошлись по 34 старым задачам, сверив премисы с текущим кодом и спеками:

- Удалена mashina-sostoyaniy-biblioteka: change state-transition-graph
  (архив 2026-07-08) осознанно отверг внешнюю FSM-библиотеку в пользу
  своего декларативного графа — задача противоречит принятому решению.
- Понижены: masshtab-100-zagruzok (высокий→средний, чисто документный НФТ
  без признаков реальной нагрузки), favicon / telegram-match-metabazy /
  disk-kopii-video-ts-bdmv (средний→низкий).
- Переформулированы под реальный остаток: dobavlenie-edinoe-okno (magnet и
  .torrent-файл уже сделаны — остался фетч .torrent по URL с SSRF-гардом,
  средний→низкий); vneshnie-subtitry (привязка субтитр→серия уже работает —
  сузили до пар VobSub .idx+.sub и потери Lang/Flags в toLayoutPlan).
- Индекс README пересобран под новые ярусы (высокий/средний/низкий = 9/19/19).

Остальные задачи подтверждены кодом как актуальные; повышать нечего.
gate-confidence и дробление udalenie оставлены как темы для обсуждения.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 12:05:41 +03:00
avandClaude Opus 4.8 7a774ad53d Беклог: перенос из Tududi в docs/backlog (файл на задачу + индекс)
Tududi оказался неудобен для ведения беклога проекта — переходим на файлы в
репозитории. Каждая задача — отдельный markdown в docs/backlog/ (48 файлов),
плюс индекс README.md со списком по приоритетам и хуками. Тело файла хранит
исходное описание (контекст, решения, ссылки на спеки/ADR/черновики).

CLAUDE.md: источник истины по беклогу теперь docs/backlog/; Tududi понижен до
инбокса сырых идей. Живые ссылки в спеках (recognition, architecture,
review-ux, jellyfin-layout) «в беклоге (Tududi)» переписаны на прямые ссылки
на файлы беклога.

Перенесённые задачи удалены из Tududi; завершённые оставлены как история.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 11:43:37 +03:00