Синтезируем контекст из полей самой 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>
45 lines
3.4 KiB
Markdown
45 lines
3.4 KiB
Markdown
## 1. Парсинг полей magnet
|
||
|
||
- [x] 1.1 Расширить `magnet.Info` полями `ExactLength int64` (из `xl`),
|
||
`Sources []string` (из `xs`), `Keywords []string` (из `kt`)
|
||
- [x] 1.2 В `Parse` заполнить новые поля из `vals`; `xl` парсить строго как
|
||
десятичное целое (байты), при ошибке — оставлять 0 (best-effort)
|
||
- [x] 1.3 Тесты парсинга: magnet с `xl`/`xs`/`kt`, гибридный, невалидный `xl`,
|
||
отсутствие полей
|
||
- [x] 1.4 Устойчивость `Parse` к ссылке, скопированной целиком в
|
||
процент-кодировке (`magnet%3A%3F…`): разовый `QueryUnescape` на фолбек-пути +
|
||
тест; тест на реальной рутрекер-ссылке (dn с кириллицей → Context)
|
||
|
||
## 2. Синтез контекста из полей
|
||
|
||
- [x] 2.1 Реализовать `func (Info) Context() string` (или `SynthContext`) в
|
||
пакете `magnet`: строки-факты через `\n` — название (`dn`, если не заглушка),
|
||
`Размер:` из `xl` (человекочитаемо), `Трекер:`/происхождение из домена
|
||
`tr`/`xs`, `Ключевые слова:` из `kt`
|
||
- [x] 2.2 Детектор заглушки `dn` вида `*-topic-<id>` (не включать как название)
|
||
- [x] 2.3 Helper нормализации домена трекера/источника из URL (`tr`/`xs`)
|
||
- [x] 2.4 Тесты синтеза: содержательный `dn`; `dn`-заглушка `rutracker-topic-*`;
|
||
только размер; только домен; все поля вместе; пустой `Info` → пустая строка;
|
||
проверить отсутствие сетевых вызовов (чистая функция)
|
||
|
||
## 3. Слияние в ingest
|
||
|
||
- [x] 3.1 В `Ingest` собрать `enrichedContext = join(nonEmpty(req.Context,
|
||
info.Context()))` — пользовательский текст первым, синтез следом
|
||
- [x] 3.2 Класть `enrichedContext` **только** в `download.Context` (вместо
|
||
сырого `req.Context`); вызов `namer.DeriveName(ctx, req.Context,
|
||
info.DisplayName)` оставить как есть — namer синтез НЕ получает
|
||
- [x] 3.3 Тесты ingest: magnet-only (пустой `req.Context`) → `download.Context`
|
||
синтезирован; непустой текст + поля → оба присутствуют, текст первым; пустой
|
||
текст и бедный magnet → пустой контекст, приём проходит
|
||
- [x] 3.4 Регресс-тест: голый rutracker-magnet (`dn=rutracker-topic-<id>`,
|
||
только `tr`, без текста) → `download.display_name` НЕ равен `Трекер: …`
|
||
(именование не деградирует), а `download.Context` содержит домен трекера
|
||
|
||
## 4. Транспорты и проверка
|
||
|
||
- [x] 4.1 Убедиться, что приём голого magnet (пустой контекст) штатно проходит
|
||
в `httpapi` и `tgbot` (при необходимости — тест на пустой `context`)
|
||
- [x] 4.2 `task test` и `task lint` зелёные
|
||
- [x] 4.3 `openspec validate magnet-context-extraction --strict` проходит
|