Голый magnet без dn/контекста заставлял namer звать LLM на пустом входе, и модель галлюцинировала мусорное имя («Unknown»), которое писалось и в display_name, и в rename qBittorrent, а заодно ломало UI-фолбэк на распознанное название. Верное каноническое имя, вычисляемое позже при распознавании, никуда не переливалось. - naming: гард пустого входа в DeriveName (нет контекста и подсказки → "" без вызова LLM) + детерминированный форматтер FormatTitleYear. - qbt: операция RenameTorrent (переименование существующей раздачи). - store: SetDisplayName — обновление имени постфактум без гарда состояния. - worker: refreshDisplayNameLocked/RefreshDisplayName — перелив канонического имени (эффективный план) в display_name + best-effort rename раздачи по реальному t.Hash; авто-триггер при подтверждении матча (choose/manual add). - web-ui: кнопка «Обновить имя» на странице загрузки (htmx-своп заголовка, деградация без JS), видимая при наличии распознавания (вкл. done/orphaned). Спека: дельты ingest/review/web-ui влиты в openspec/specs; change refresh-display-name заархивирован. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
41 lines
3.0 KiB
Markdown
41 lines
3.0 KiB
Markdown
## ADDED Requirements
|
|
|
|
### Requirement: Подтверждение матча обновляет отображаемое имя
|
|
|
|
Система SHALL при подтверждении матча в ревью запускать обновление отображаемого
|
|
имени загрузки по подтверждённому распознаванию (см. capability `ingest`):
|
|
переливать каноническое название (`Title (Year)`) в `download.display_name` и в
|
|
имя раздачи qBittorrent, без нового вызова LLM. Подтверждением матча SHALL
|
|
считаться как выбор кандидата из списка совпадений, так и ручное добавление
|
|
источника по id/URL (оба закрепляют провайдера и каноническое название).
|
|
|
|
Обновление SHALL выполняться после успешного закрепления выбора кандидата и
|
|
SHALL быть best-effort по отношению к qBittorrent: недоступность клиента SHALL
|
|
NOT проваливать команду ревью. Это согласуется с инвариантом «авто-действие
|
|
только при подтверждённом матче».
|
|
|
|
#### Scenario: Выбор кандидата обновляет имя
|
|
|
|
- **GIVEN** загрузка в ревью с пустым или неинформативным `display_name`
|
|
(например, «Unknown») и списком кандидатов
|
|
- **WHEN** пользователь выбирает кандидата, подтверждая матч
|
|
- **THEN** выбор кандидата закрепляется как и прежде
|
|
- **AND** `download.display_name` обновляется каноническим именем кандидата
|
|
`Title (Year)`
|
|
- **AND** раздача в qBittorrent переименовывается в то же имя
|
|
|
|
#### Scenario: Ручное добавление источника обновляет имя
|
|
|
|
- **GIVEN** загрузка в ревью без совпадений в списке
|
|
- **WHEN** пользователь вручную добавляет источник по id/URL, подтверждая матч
|
|
- **THEN** источник закрепляется как и прежде
|
|
- **AND** `download.display_name` и имя раздачи в qBittorrent обновляются
|
|
каноническим названием подтверждённого источника
|
|
|
|
#### Scenario: Недоступность qBittorrent не ломает выбор кандидата
|
|
|
|
- **GIVEN** выбор кандидата в ревью
|
|
- **WHEN** переименование раздачи в qBittorrent завершается ошибкой
|
|
- **THEN** выбор кандидата и обновление `download.display_name` выполнены
|
|
- **AND** команда ревью не возвращает ошибку
|