Files
jellybit/openspec/changes/archive/2026-07-03-refactor-capability-boundaries/proposal.md
T
avandClaude Opus 4.8 512567c8ba Рефакторинг границ capabilities: цепочка загрузка→матч→ревью→раскладка (openspec)
Привёл набор capabilities в OpenSpec к цепочке обработки, чтобы имя capability
отвечало одному поведению. Чисто по спекам, код и поведение системы не меняются.

Change refactor-capability-boundaries (архивирован):
- recognition разделён на recognition (разбор LLM) + metadata-match (сверка с базами)
- review выделен из web-ui + мигрирован из docs/specs/review-ux.md
- новые capability из docs/specs: file-layout, download-tracking, notifications
- identity очищен до инфра-id; приём (инфохэши, дедуп, ядро приёма) — в ingest
- уведомление о рассинхроне перенесено из state-reconciliation в notifications
- дубль владения путём и безопасного undo оставлен в state-reconciliation

Итог: 11 capabilities, openspec validate --strict проходит (+37/−11 требований).
Источник истины по мигрированным темам переехал в openspec/specs (шапки в docs).
Снят пункт беклога «Пересмотр набора capabilities».

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 21:17:51 +03:00

81 lines
6.9 KiB
Markdown

## Why
Деление capabilities в OpenSpec сложилось стихийно по ходу миграции и смешивает
разные заботы в одной спеке: `recognition` держит и разбор через LLM, и работу с
внешними базами; поведение ревью размазано между `web-ui` и не перенесённым
`docs/specs/review-ux.md`; ключевые звенья цепочки (раскладка, отслеживание
загрузки, уведомления) в OpenSpec отсутствуют вовсе. На каждой задаче приходится
гадать, какой capability трогать. Приводим набор capabilities к цепочке
«загрузка → распознавание → матч → ревью → раскладка», где имя capability
отвечает **одному** поведению.
Это чисто спецификационный рефакторинг: **поведение системы не меняется**, код не
трогаем. Меняются только границы и расположение требований.
## What Changes
- **Разделяем `recognition`**: оставляем в нём только разбор сигналов LLM (план,
тип, название, файлы→серии, модель уверенности, решение auto/review); всю работу
с метабазами выносим в новую `metadata-match`.
- **Вводим `review`** как отдельный capability: переносим поведение ревью из
`web-ui` (единый список источников, ручное добавление источника, предпросмотр
полей) и мигрируем `docs/specs/review-ux.md`.
- **Подрезаем `web-ui`** до чистого оформления: статика, шрифты, дизайн-система,
скелет страниц, бейджи, клиентские взаимодействия, превью через единую логику
именования.
- **Мигрируем в OpenSpec** три звена цепочки, живущие пока в `docs/specs`:
`file-layout` (из `jellyfin-layout.md`), `download-tracking` (FSM/поллинг из
`workflow.md`), `notifications` (из `workflow.md` + `architecture.md`).
- **Чистим `identity`** до инфраструктуры id: переносим приёмные требования
(инфохэши, дедуп, атомарный возврат в активное) в `ingest`.
- **Собираем уведомления** в `notifications`: переносим «Уведомление о
рассинхроне» из `state-reconciliation`.
- Не-BREAKING: перенос требований (REMOVED в исходной спеке + ADDED в целевой),
формулировки сохраняем эквивалентными.
## Capabilities
### New Capabilities
- `metadata-match`: поиск записи во внешних базах (TMDB/TVDB/TVMaze) по названиям,
сбор кандидатов, подтверждение единичного сильного матча → `provider`/
`provider_id`/каноническое имя/год, URL кандидата.
- `review`: процесс ревью после распознавания и матча — петля «догадка → подсказка
→ перераспознавание», команды (Применить/Уточнить/Распознать заново/Тип/Игнор/
Позже/Отклонить/Undo/Привязать заново), подсказка vs override, единый список
источников совпадения, ручное добавление источника, предпросмотр (превью=
применение), разделение труда транспортов.
- `file-layout`: целевые имена фильмов/сериалов, сопоставление источник→цель,
хардлинки, санитизация пути и запрет выхода за библиотеку, never-overwrite,
copy-fallback. Владение путём (`superseded`) и безопасный undo (`nlink<=1`)
остаются в `state-reconciliation` (не дублируем — см. design.md).
- `download-tracking`: поллинг qBittorrent и машина состояний загрузки —
`downloading`/`completed`/`stuck`/`failed`, завершение (moving/checking),
таймауты (`magnet_timeout`/`stuck_after`), усыновление по категории/тегу.
- `notifications`: пинги автору загрузки — падения (`failed`/`stuck`, включая
приёмный `qbit_add` мимо поллинга) с дебаунсом, вход в review и готовность,
рассинхрон.
### Modified Capabilities
- `recognition`: убираем требования по метабазам (уезжают в `metadata-match`);
добавляем перенесённый из `docs/specs/recognition.md` разбор сигналов LLM
(пред-парс, схема плана, провайдер LLM, модель уверенности).
- `ingest`: принимает перенесённые из `identity` приёмные требования (множество
инфохэшей, дедуп по любому хешу, атомарный возврат в активное состояние).
- `identity`: убираем приёмные требования — остаётся инфраструктура id (ULID,
нормализация/валидация, корреляция в логах, миграция).
- `web-ui`: убираем ревью-специфику (уезжает в `review`) — остаётся оформление.
- `state-reconciliation`: убираем «Уведомление о рассинхроне» (уезжает в
`notifications`).
## Impact
- Затрагивает только `openspec/specs/**` и `openspec/changes/**`**кода нет**.
- Источник истины по мигрируемым темам переезжает из `docs/specs/`
(`recognition.md`, `review-ux.md`, `jellyfin-layout.md`, `workflow.md`) в
`openspec/specs/` (как пилот `ingest`); в исходных файлах ставим пометку о
переезде, содержимое не дублируем.
- CLAUDE.md и `docs/backlog.md`: снять пункт из беклога, при необходимости
поправить перечисление capabilities.
- Валидация: `openspec validate --strict` для change перед коммитом; после архива
дельты вливаются в `openspec/specs/`.