Files
vesti/openspec/changes/archive/2026-09-16-own-content-hub/tasks.md
T

60 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Tasks: own-content-hub
## 1. Схема БД и реестр источников
- [x] 1.1 Миграция схемы: ALTER TABLE posts ADD COLUMN is_own INTEGER DEFAULT 0, is_own_canonical INTEGER DEFAULT 0; sources ADD COLUMN own INTEGER DEFAULT 0; published ADD COLUMN distributed_dirs TEXT
Проверка: `sqlite3 db/vesti.db "PRAGMA table_info(posts)"` показывает is_own/is_own_canonical; sources.own; published.distributed_dirs
- [x] 1.2 Добавить источник dedinit в sources.yaml (channel: dedinit, own: true, direction: null, lang: ru)
Проверка: `grep -A4 "slug: dedinit" sources/sources.yaml` → есть own: true
- [x] 1.3 Синк реестра в БД (sources.own=1 для dedinit)
Проверка: `sqlite3 db/vesti.db "SELECT slug, own FROM sources WHERE slug='dedinit'"` → dedinit|1
## 2. Краулер
- [x] 2.1 telegram_crawler.py: загрузка own-флага источников; проставление is_own/is_own_canonical для own-источников; медиа скачивается
Проверка: код реализован (store_posts/is_own_source, py_compile OK); интеграционная проверка ждёт бэкфилла 2.3
- [x] 2.2 Форварды в своём канале: чужой форвард сохраняется с is_own=1 + fwd-полями, медиа НЕ скачивается
Проверка: код реализован (skip_media для форвардов); интеграционная проверка после бэкфилла
- [x] 2.3 Бэкфилл своего канала: первый прогон ~1039 постов (медиа по возможности; при лимите — текст без медиа, бэкфилл-флаг) — СДЕЛАНО 2026-09-10 (backfill_dedinit.py, fetched=1040, max_post_id=1092, 846 в БД; ныне 848 is_own)
Проверка: `sqlite3 db/vesti.db "SELECT COUNT(*) FROM posts WHERE is_own=1"` > 0 (до ~1039)
- [x] 2.4 Дедуп: тот же sha256/url во внешнем канале → is_own=0 (упоминание), канонический остаётся is_own_canonical=1
Проверка: код реализован (канон vs упоминание); проверка на реальных данных после бэкфилла
## 3. Классификатор
- [x] 3.1 classify.py: is_own=1 + направление по словарю → relevance=critical, classified=True, method='dict-own' (без LLM при недоступности)
Проверка: тестовый свой пост со словарным попаданием при выключенной Ollama → classified=1 relevance=critical
- [x] 3.2 Поддержка мультинаправлений: классификатор может писать несколько записей classifications (fan-out)
Проверка: пост linux+ai имеет 2 записи classifications
## 4. Публикатор (fan-out)
- [x] 4.1 publisher/bot.py: publish_multi(directions) → публикация карточки в каждый @dedinit_vesti_<dir>_<lang>_bot; возвращает {dir: message_id}
Проверка: dry-run с токеном → map направлений; без токена → dry_run=True (проверено ['linux','ai'])
- [x] 4.2 Атрибуция в карточке (publisher/card.py): для is_own-постов строка «Дед в АйТи (@dedinit)» + ссылка на оригинал, для внешних — без
Проверка: make_card(is_own пост) содержит t.me/dedinit/ и «Дед в АйТи» (проверено); make_card(внешний) — нет
- [x] 4.3 Запись distributed_dirs + tg_message_ids в published при fan-out
Проверка: после approve (TestClient, dry-run) distributed_dirs=JSON([linux, ai]) в published + views
## 5. Веб
- [x] 5.1 Фильтр «Свои» (is_own) в /candidates: параметр own=1|0, бейдж «СВОЙ»
Проверка: TestClient GET /candidates?own=1 → только is_own посты с бейджем «⭐ СВОЙ» (проверено)
- [x] 5.2 Выбор направлений рассылки при approve: чекбоксы (по умолчанию — направления классификации); approve → publish_multi
Проверка: TestClient POST /posts/{id}/approve с dirs=linux,ai → 302 /published, distributed_dirs=[linux,ai] (dry-run) (проверено)
- [x] 5.3 Опубликованные: показ distributed_dirs (в какие каналы разослан) и метрики по каждому
Проверка: /published содержит «Разослан в» с @dedinit_vesti_linux_ru_bot и ai (проверено TestClient)
## 6. Банк статей (news-store)
- [x] 6.1 store.py: frontmatter origin: own + source_url + author для is_own-постов; origin: external для внешних
Проверка: бандл содержит `origin: own` и `source_url: https://t.me/dedinit/<id>`, author «Дед в АйТи» (проверено)
- [x] 6.2 Бандлы по каждому направлению fan-out (bundles/<dir>/<YYYY-MM>/<slug>.md)
Проверка: create_bundle(['linux','ai']) → 2 файла в bundles/linux и bundles/ai (проверено)
## 7. Проверка интеграции и документация
- [x] 7.1 Полный прогон: синк → краулер dedinit → классификатор → веб (approve с fan-out) → бандлы; внешние источники не затронуты (is_own=0 по умолчанию) — СДЕЛАНО (реальные approve 136/137, 2026-09-09; бэкфилл 2026-09-10)
Проверка: counts по is_own в БД, бандлы, /published, runs ok — ждёт бэкфилла 2.3 (реальная сеть)
- [x] 7.2 Обновить STATUS.md / TODO.md / WALKTHROUGH.md (что сделано, как запускать, питфолы)
Проверка: документы отражают новое состояние (обновлено при закрытии сессии)