Files
jellybit/openspec/changes/archive/2026-07-07-magnet-context-extraction/specs/ingest/spec.md
T
avandClaude Opus 4.8 e9ec26d09a Ingest: контекст распознавания из полей magnet-ссылки
Синтезируем контекст из полей самой 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>
2026-07-07 20:38:01 +03:00

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** приём проходит штатно (пустой контекст допустим)