165 Commits
Author SHA1 Message Date
avandClaude Opus 4.8 3d3448d050 Уточнил детали реализации review-source-selection по итогам разбора (openspec)
Зафиксировал в design/tasks: []SourceOption в ReviewData (нейронка первой),
общая деривация overridesForSource, предпросмотр всех источников на сервере
с раскрытием по клику, секция «Раскладка» остаётся отдельной для активного
источника.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 09:57:13 +03:00
avandClaude Opus 4.8 e7fe88a986 Завёл change review-source-selection: выбор источника и предпросмотр в ревью (openspec)
Переработка экрана ревью: единый список источников (нейронка наравне с
кандидатами баз), выбор/переключение/снятие в пользу нейронки, ручное
добавление по id/URL, предпросмотр полей и целевых путей до применения.
Дизайн отревьюен: единая деривация «источник → overrides» (preview==apply,
чинит залипший override title/year). Ограничились существующими capabilities.

Беклог: добавил две идеи — «Пересмотр набора capabilities и рефакторинг спек»
и «Сила совпадения кандидата / пересмотр распознавания и матчинга».

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 09:52:48 +03:00
avandClaude Opus 4.8 3df7f88fdc Убрал из беклога учёт стоимости и метрики LLM (docs)
Разные провайдеры и мониторинг запросов к LLM закрыты внешним LLM Gateway
(bifrost) на сервере; для наблюдения за состоянием пока достаточно slog.
Заодно поправил висячую ссылку на удалённый раздел в «Истории переходов».

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 09:03:14 +03:00
avandClaude Opus 4.8 5075f6b116 Убрал из беклога реализованную задачу идентичности на ULID (docs)
Раздел «Идентичность загрузки: ULID + множество инфохэшей» закрыт коммитом
37f2f64 и заархивированным change ulid-identity — удаляю из беклога.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 08:57:50 +03:00
avandClaude Fable 5 37f2f6481a Идентичность на ULID: download_infohash, guarded-дедуп, миграция (ulid-identity)
Все сущности переехали с INTEGER AUTOINCREMENT на TEXT ULID (lowercase,
internal/ident — единая точка генерации и разбора; oklog/ulid). Инфохэши
загрузки — множество (download_infohash, v1/v2 гибридных торрентов): дедуп
и сопоставление в поллинге по любому из хешей, magnet-парсер отдаёт оба
хеша гибридной ссылки, усечённый v2-хеш v2-only раздач не хранится.

Инвариант «не более одной активной загрузки на infohash» вместо снятого
unique-индекса держат guarded-методы store в одной write-транзакции
(_txlock=immediate): CreateDownloadIfNoActive (приём/adopt, с доносом
недостающих хешей), ActivateIfNoOtherActive (retry/recovery/relink, отказ
до побочных эффектов), guarded AddInfohashes; SetDownloadState отклоняет
терминал→активное как механический бэкстоп.

Миграция 0006 — первая Go-миграция goose: пересоздание таблиц при
включённых FK, backfill ULID с timestamp из created_at (хронология id
сохранена), разнос infohash, удаление idempotency_key. BREAKING: формат id
в URL/логах/Telegram, REST-поля id (string) и infohashes (список).

Новая конвенция docs/conventions/database.md (без числовых PK), корреляция
в логах grep'ом по голому ULID, ER-схема обновлена. Спеки: новая capability
identity, MODIFIED в state-reconciliation; change заархивирован. Пройдены
ревью дизайна и кода (по 8 углов), все находки исправлены с
регрессионными тестами.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 21:25:00 +03:00
avandClaude Fable 5 b808ceff25 Переработал черновик логической модели и беклог по итогам разбора (docs)
Итог explore-сессии: сущность title не вводим — download остаётся мостом
qBittorrent ↔ файлы, «второй сезон» решается правилом сходимости папки,
группировка тайтла вычисляется. Черновик перекроен под это решение
(отвергнутые варианты и триггер пересмотра зафиксированы), задачи беклога
обновлены и приоритезированы по калибровке болей.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 21:24:39 +03:00
avandClaude Opus 4.8 b420aa4c9d Убрал из беклога реализованные UI/UX-задачи (docs)
Сделаны в change web-ui-list-detail и убраны из беклога:
- «Главная: список загрузок вместо таблицы»
- «Расширенная информация о загрузке в web-UI»
- «Список загрузок: фильтр, поиск, пагинация»
- «Полировка веб-UI: список и карточка загрузки»

«Улучшения UI: показывать матч» сужено до Telegram (web-сторона сделана).
Поправлены перекрёстные ссылки в оставшихся пунктах, чтобы не висли на
удалённые якоря.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 09:58:01 +03:00
avandClaude Opus 4.8 c0b5ab7295 UI/UX списка и карточки загрузки: серверные фильтр/поиск/пагинация, матч-ссылка, имя раздачи (web-ui-list-detail)
- Список: серверные фильтр по группе состояний, поиск и пагинация (GET
  f/q/page/all, по 25), сортировка по времени добавления в qBittorrent
  (added_on) с фолбеком на created_at и tie-break по id.
- Заголовок загрузки = имя раздачи (display_name) → распознанное название →
  усечённый источник; сырой magnet вынесен в блок «Информация о торренте».
- Матч метабазы показан ссылкой на запись (страница загрузки и ревью);
  URL берётся у выбранного кандидата либо строится по provider+id и типу.
- Полировка вёрстки; клиентская JS-фильтрация убрана (всё серверное, без JS).
- Миграция 0005 (display_name, source_added_at); воркер однократно
  фиксирует source_added_at при поллинге/усыновлении; ER-схема обновлена.
- OpenSpec: дельты влиты в specs/{web-ui,ingest}, change заархивирован.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 09:50:24 +03:00
av 2a9bf7efb0 Добавил несколько идей в беклог 2026-07-01 08:36:32 +03:00
avandClaude Opus 4.8 ef75a0d302 Живые обновления прогресса и раздел «Раздача» (live-status)
Воркер ведёт in-memory снимок телеметрии раздач (прогресс, скорость, ETA,
рейтинг, сиды/пиры, отдано) под отдельным RWMutex, обновляя его на каждом
тике поллинга сразу после построения byHash — без лишних вызовов qBittorrent
и без хранения в БД (волатильно). qbt.Torrent дополнен полями телеметрии.

Веб-UI читает снимок через узкий контракт LiveStatus: карточки активных
загрузок показывают живой прогресс-бар (htmx-поллинг фрагмента every 3s,
точечно — без сброса фильтров), на странице загрузки появилась секция
«Раздача» для сидирующих задач. Начальный кадр рендерится сразу со
значениями; при отсутствии данных UI деградирует штатно.

Капабилити live-status (OpenSpec), web-ui дополнен. Change заархивирован.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 20:38:25 +03:00
avandClaude Opus 4.8 b646381cf9 Включил плагин frontend-design (claude)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 19:59:58 +03:00
avandClaude Opus 4.8 4e2593ac31 Перенос дизайна в server-rendered веб-UI (web-ui)
Новая capability web-ui: презентационный перенос готового дизайна
(семантический HTML + единый jellybit.css, тёмная тема по настройке ОС)
в html/template без шага сборки.

- Встроенная (go:embed) отдача статики под /static с Cache-Control и
  cache-busting (?v=<hash> по содержимому css/js).
- Шрифты IBM Plex self-hosted (@font-face, cyrillic+latin), без CDN.
- Наколеночный менеджер зависимостей: вендор (htmx + шрифты) не хранится
  в репо (gitignore), идемпотентно добывается `task assets` по
  web/assets.manifest с проверкой sha256; task build/run зависят от assets.
- Общие партиалы: шапка, бейдж статуса (карта всех 14 состояний),
  виджет «файл источника → раскладка» (общий для review и download).
- Страницы: список с фильтром/поиском, ревью, новая страница просмотра
  загрузки (/download/{id}). deleted скрыт по умолчанию.
- Превью раскладки берётся из единой логики internal/layout
  (buildFileRows), без дублирования правил имён в шаблонах.
- Убраны meta-refresh и инлайн-стили; copyHash на vanilla с fallback
  на execCommand и честной индикацией (целевой деплой — HTTP LAN).

Вне scope (отдельный change): живые обновления прогресса и раздел
раздачи, клиентский режим ручной раскладки файл→серия (с Alpine.js).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 19:59:19 +03:00
avandClaude Opus 4.8 d190072647 Единый беклог задач вместо todo.md и ideas.md (docs)
Слил docs/todo.md и docs/drafts/ideas.md в docs/backlog.md: единый список
будущих задач по приоритетам (Высокий/Средний/Низкий), спекулятивные пункты
помечены _(идея)_. Реализованное из ideas.md (повторное распознавание,
нотификации) не переносил.

Добавил задачи: переработка ревью (выбор источника совпадения с
предпросмотром), главная как список карточек вместо таблицы, отдельная
страница просмотра загрузки (поднял из «Расширенной информации»), скрытие
deleted-загрузок по умолчанию.

Ссылки на drafts/ideas.md из docs/specs/* перенаправлены на backlog.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 15:31:27 +03:00
avandClaude Opus 4.8 70d8758646 Восстановление зависших загрузок и уведомления о падении (state-reconciliation)
Долгий metaDL больше не убивается агрессивным таймаутом: дефолт
magnet_timeout 30m → 24h (страховочный предохранитель), базис отсчёта —
added_on из qBittorrent, а не created_at (переживает retry/усыновление).

Авто-восстановление: фоновая сверка возвращает в поток задачи, упавшие по
нашей нетерпеливости (magnet_timeout/stalled), когда источник ожил и
продвинулся за условие падения (downloading/completed по статусу торрента);
qbit_error не воскрешается. Конфликт idempotency (infohash занят другой
активной задачей) — оставляем в failed.

Уведомления: любой переход в failed/stuck пингует автора (включая приёмный
qbit_add через ingest), с дебаунсом против спама при флаппинге stalled.
Ручной retry добавлен в веб-UI и Telegram; Retry перецепляется к живому
торренту вместо слепого Add.

Дельта state-reconciliation влита в живые спеки; обновлён workflow.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 14:51:57 +03:00
avandClaude dfa182a5a9 Ссылки на внешние базы в ревью (recognition)
Каждый кандидат внешней базы метаданных (TMDB/TVDB/TVMaze) теперь несёт
URL на страницу элемента — при ревью можно кликнуть и проверить матч.
URL формируется клиентом провайдера при поиске, сохраняется в БД
(metadata_candidate.url) и отображается ссылкой в веб-интерфейсе.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-29 20:09:20 +03:00
avandClaude Opus 4.8 6b7c090ce4 Владение целевым путём при повторной раскладке (state-reconciliation)
Завершённая загрузка ложно «воскресала» из deleted в orphaned, когда её
целевой путь переиспользовала другая загрузка (повторная закачка того же
фильма в другом качестве): сверка проверяла лишь существование пути, не
проверяя, что файл по нему — наша раскладка.

Вводим инвариант «один целевой путь — один владелец»:

- при успешной раскладке на освободившийся чужой путь владение переходит
  к новой загрузке — прежние file_link на этот путь помечаются статусом
  superseded и перестают считаться целью при сверке;
- deleted исключён из desyncStates — терминальное состояние больше не
  переоценивается (источник к нему не вернётся из-за идемпотентности,
  цель отбирается переходом владения);
- Undo снимает только реально свои разложенные ссылки (superseded
  пропускает — файл по пути теперь чужой хардлинк);
- ошибку перехода владения трактуем как некритичную (WARN-and-continue):
  файлы уже разложены, рассинхрон чужих задач исправит следующий тик.

Без миграции схемы (status — TEXT). Дельта влита в основную спеку,
обновлены workflow.md и jellyfin-layout.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 18:10:05 +03:00
avandClaude Opus 4.8 783664622c Сделал пароль qBittorrent опциональным (config)
qBittorrent может работать без аутентификации (обход авторизации для
доверенной подсети) — пустой пароль валиден.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 12:25:14 +03:00
avandClaude Opus 4.8 4fc8c41b3a Поиск по нескольким названиям при сверке с базой (recognition)
Сверка с метабазой промахивалась на иностранных фильмах с русским
релиз-именем (кейс «Тёмный рыцарь»): поиск шёл по одной строке
provider_hint||title и игнорировал original_title, а базы индексированы
прежде всего по оригинальным названиям.

- matchMetadata ищет по ключам original_title → title → provider_hint с
  ранним стопом на первом единичном сильном матче; пустые и
  нормализованно-дублирующие ключи пропускаются, кандидаты для review
  копятся из всех заходов.
- Промпт требует всегда заполнять title и original_title (дублировать при
  отсутствии оригинала / российском контенте; при неуверенности дублировать,
  не выдумывать). Разбор остаётся мягким к пустому original_title.
- TMDB-поиск передаёт language (по умолчанию ru-RU, настраивается
  [metadata.tmdb].language); original_title не зависит от локали.
- Нормализация названий сводит ё→е.

Инварианты не ослаблены: авто только при подтверждённом единичном матче +
структурной валидации + согласованности сигналов.

Capability recognition впервые перенесена в OpenSpec; change архивирован.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 12:16:47 +03:00
avandClaude Opus 4.8 cc7e51b3a4 Обработка рассинхрона состояния с реальностью (state-reconciliation)
Распознаём ручное удаление источника (раздача в qBittorrent) и/или цели
(разложенные хардлинки) и отражаем его в состоянии задачи, без автодействий.

- Новая capability state-reconciliation (OpenSpec): фоновая сверка по матрице
  «источник × цель» → состояния target_missing/orphaned/deleted, переходы и
  самовосстановление (healing).
- worker: reconcileDesync в Poll (только разложенные/desync-задачи), дебаунс
  пропажи источника (порог [worker].source_missing_threshold) и синхронный
  preflight перед действиями (relink/recognize/apply/undo) — не доверяем
  state в БД.
- layout.Undo: отказ снять последнюю копию (nlink<=1 или нет источника),
  отказ всего батча без частичного отката (ErrLastCopy).
- store: единый список terminalStates для IsTerminal и FindActiveByInfohash
  (иначе семантика «активности» разъезжается), столбец source_miss_count,
  миграция 0003.
- httpapi/web и Telegram: показ новых состояний и уведомления о рассинхроне.
- Доки: workflow.md, jellyfin-layout.md, database.md (+0003), config.

Change заархивирован в openspec/changes/archive, дельта влита в openspec/specs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 11:07:09 +03:00
av f9d7fd9216 Добавил схему базы данных 2026-06-29 10:29:37 +03:00
av 02e24799ad Актуализировал README 2026-06-28 21:29:08 +03:00
av 3d5df62d62 Конвенция для обработки ошибок + рефакторинг кода 2026-06-28 21:22:12 +03:00
av c6daba46d9 Записал илеи конвенций на будущее 2026-06-28 21:10:44 +03:00
av 84ffe0733e Добавил конвенции для конфигурации и сделал рефакторинг кода 2026-06-28 20:53:10 +03:00
av 9cfccc7b4a Логирование: ревью всего кода и рефакторинг в соответствии с конвенциями 2026-06-28 20:13:40 +03:00
av c739a20749 Добавил конвенции для логирования 2026-06-28 19:26:36 +03:00
av 2011fdd740 Дополнил правила 2026-06-28 12:39:41 +03:00
av 694a9f4bef Архивация спеки 2026-06-28 12:27:50 +03:00
av d8ef7063f4 Добавил реализацию 2026-06-28 12:20:10 +03:00
av 4f2fb5998a Добавил спеки для выведения имени загрузки при добавлении торрента 2026-06-28 12:00:16 +03:00
av b269cdf8ca Добавил каркас OpenSpec 2026-06-28 11:21:42 +03:00
av 4a00c83392 Добавил еще идеи в todo 2026-06-16 15:39:46 +03:00
av 1e8000429a Todo про рассинхрон данных 2026-06-15 12:03:42 +03:00
av 70b3c7ae14 Добавил todo с доработками 2026-06-15 11:50:49 +03:00
av d727966f29 ADR про распознавание контента 2026-06-15 11:38:18 +03:00
av d149cb7481 Синхронизация документации и кода 2026-06-15 11:27:03 +03:00
av b1f97c105a Разделил хранимые данные по слоям: config, data, cache 2026-06-15 10:58:05 +03:00
av 157f626c2e Сделал для http запросов уровень логирования DEBUG 2026-06-15 08:55:29 +03:00
av e297f0fb84 Фикс повторного распознавания 2026-06-15 07:57:22 +03:00
av 16a82572e7 Добавил ручную перепривязку 2026-06-15 07:42:50 +03:00
av 093211c9c7 Добавил обновление библиотеки jellyfin после добавления медиа 2026-06-15 07:33:21 +03:00
av fff0960915 Фикс не найденного торрента при ревью 2026-06-14 20:54:47 +03:00
av 0e69a86a89 Обновил readme 2026-06-14 19:48:39 +03:00
av 81ed58ecff Добавил логи 2026-06-14 19:37:09 +03:00
av d4bf8a8cad Фикс отображения путей 2026-06-14 19:09:50 +03:00
av 5fb2f4df43 Добавил прокси для Телеграм 2026-06-14 18:56:04 +03:00
av 2dbbb1b706 Добавил распознавание файлов для проверки 2026-06-14 17:21:15 +03:00
av 4e077d878e Добавил "усыновление" существующих торрентов при добавлении тега или
категории
2026-06-14 17:06:59 +03:00
av 7f7f5f69d4 Добавил выбор из кандидатов, если LLM не уверена в раскладке 2026-06-14 16:43:50 +03:00
av 4af3ad2dde Добавил сборку 2026-06-14 16:10:21 +03:00