Синтезируем контекст из полей самой magnet-ссылки (dn, xl, tr/xs, kt) без сети и дополняем им текст от транспорта: пользовательский текст первым, при пустом — синтез единственный. Обогащённый контекст идёт только в download.Context (его читают recognition и веб-UI); вход namer и отображаемое имя не меняются — строки-факты (Размер:/Трекер:) в display_name не текут. - magnet.Info: поля ExactLength/Sources/Keywords + Info.Context() (синтез, отсев dn-заглушек *-topic-<id>, домен трекера, человекочитаемый размер) - Parse устойчив к ссылке в процент-кодировке (разовый QueryUnescape) - ingest: mergeContext → download.Context, namer на сыром req.Context - Влита дельта capability ingest в openspec/specs, change заархивирован Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
96 lines
6.1 KiB
Markdown
96 lines
6.1 KiB
Markdown
## ADDED Requirements
|
|
|
|
### Requirement: Синтез контекста распознавания из полей magnet
|
|
|
|
При приёме система SHALL извлекать из полей magnet-ссылки дополнительный
|
|
контекст и **дополнять** им контекст, пришедший из транспорта: факты из полей
|
|
SHALL добавляться к пользовательскому тексту (пользовательский текст —
|
|
первым), а при пустом тексте SHALL становиться единственным контекстом.
|
|
Синтез SHALL выполняться только из самой ссылки, без сетевых запросов.
|
|
|
|
В синтез SHALL включаться следующие поля, когда они присутствуют:
|
|
|
|
- `dn` (display name) — как строка названия релиза, **если** это содержательное
|
|
имя, а не заглушка-идентификатор вида `*-topic-<id>` (например
|
|
`rutracker-topic-6514485`); такие заглушки в контекст-название включаться
|
|
SHALL NOT.
|
|
- `xl` (exact length) — как человекочитаемый размер (например «≈ 2.1 GiB»);
|
|
нечисловое/некорректное значение игнорируется.
|
|
- `tr`/`xs` (трекеры / exact source) — как сигнал происхождения по домену
|
|
(хост трекера/источника), помогающий определить язык и тип контента.
|
|
- `kt` (keyword topic) — как ключевые слова.
|
|
|
|
Обогащённый контекст система SHALL сохранять в `download.Context` — его читают
|
|
recognition (LLM-промпт) и веб-UI (страница загрузки). Синтез и слияние SHALL
|
|
выполняться до создания загрузки.
|
|
|
|
Синтезированные строки-факты (размер, домен трекера, ключевые слова) SHALL NOT
|
|
влиять на вывод отображаемого имени (`download.display_name` / параметр
|
|
`rename` qBittorrent): вход вывода имени остаётся прежним (пользовательский
|
|
текст и подсказка `dn`), см. требование «Отображаемое имя торрента из
|
|
контекста».
|
|
|
|
Приём **только по magnet** (пустой текст контекста) SHALL быть штатным
|
|
сценарием во всех транспортах (HTTP, Telegram, CLI).
|
|
|
|
#### Scenario: dn — содержательное имя релиза
|
|
|
|
- **WHEN** magnet содержит `dn` с релиз-именем (например
|
|
`Dune.Part.Two.2024.2160p.BluRay`)
|
|
- **THEN** это имя добавляется в `download.Context`
|
|
- **AND** становится доступно recognition
|
|
|
|
#### Scenario: dn — заглушка-идентификатор темы
|
|
|
|
- **WHEN** `dn` имеет вид `*-topic-<id>` (например `rutracker-topic-6514485`)
|
|
- **THEN** система не включает его как строку-название в контекст
|
|
- **AND** остальные поля magnet (размер, домен трекера) всё равно синтезируются
|
|
|
|
#### Scenario: Размер из xl
|
|
|
|
- **WHEN** magnet содержит корректный числовой `xl`
|
|
- **THEN** в `download.Context` добавляется человекочитаемый размер загрузки
|
|
|
|
#### Scenario: Происхождение по домену трекера
|
|
|
|
- **WHEN** magnet содержит `tr` и/или `xs` с распознаваемым хостом
|
|
- **THEN** в `download.Context` добавляется сигнал происхождения (домен),
|
|
пригодный как подсказка языка/типа контента
|
|
|
|
#### Scenario: Дополнение непустого пользовательского контекста
|
|
|
|
- **WHEN** транспорт передал непустой текст контекста, а magnet несёт поля
|
|
- **THEN** `download.Context` содержит и текст пользователя, и факты из полей
|
|
magnet (текст пользователя не теряется)
|
|
- **AND** текст пользователя идёт первым
|
|
|
|
#### Scenario: Приём только по magnet
|
|
|
|
- **WHEN** magnet принят с пустым текстом контекста
|
|
- **THEN** приём проходит штатно
|
|
- **AND** `download.Context` синтезируется из полей magnet и сохраняется
|
|
|
|
#### Scenario: Строки-факты не становятся отображаемым именем
|
|
|
|
- **GIVEN** голый magnet с заглушкой `dn=rutracker-topic-<id>` и трекером, без
|
|
пользовательского текста
|
|
- **WHEN** выполняется приём
|
|
- **THEN** `download.display_name` не выводится из строк-фактов (не равен
|
|
`Трекер: …`/`Размер: …`)
|
|
- **AND** отображаемое имя определяется прежним путём (подсказка `dn` или его
|
|
отсутствие → без `rename`)
|
|
|
|
#### Scenario: Синтез без сети
|
|
|
|
- **WHEN** выполняется извлечение контекста из полей magnet
|
|
- **THEN** не делается ни одного сетевого запроса (только разбор строки
|
|
ссылки)
|
|
|
|
#### Scenario: Полей для контекста нет
|
|
|
|
- **WHEN** текст пользователя пуст и ни одно пригодное поле magnet не даёт
|
|
содержательного контекста (нет `dn`-имени, `xl`, распознаваемого домена,
|
|
`kt`)
|
|
- **THEN** `download.Context` остаётся пустым
|
|
- **AND** приём проходит штатно (пустой контекст допустим)
|