Files
vesti/openspec/changes/own-content-hub/tasks.md
T

5.9 KiB
Raw Blame History

Tasks: own-content-hub

1. Схема БД и реестр источников

  • 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
  • 1.2 Добавить источник dedinit в sources.yaml (channel: dedinit, own: true, direction: null, lang: ru) Проверка: grep -A4 "slug: dedinit" sources/sources.yaml → есть own: true
  • 1.3 Синк реестра в БД (sources.own=1 для dedinit) Проверка: sqlite3 db/vesti.db "SELECT slug, own FROM sources WHERE slug='dedinit'" → dedinit|1

2. Краулер

  • 2.1 telegram_crawler.py: загрузка own-флага источников; проставление is_own/is_own_canonical для own-источников; медиа скачивается Проверка: код реализован (store_posts/is_own_source, py_compile OK); интеграционная проверка ждёт бэкфилла 2.3
  • 2.2 Форварды в своём канале: чужой форвард сохраняется с is_own=1 + fwd-полями, медиа НЕ скачивается Проверка: код реализован (skip_media для форвардов); интеграционная проверка после бэкфилла
  • 2.3 Бэкфилл своего канала: первый прогон ~1039 постов (медиа по возможности; при лимите — текст без медиа, бэкфилл-флаг) Проверка: sqlite3 db/vesti.db "SELECT COUNT(*) FROM posts WHERE is_own=1" > 0 (до ~1039)
  • 2.4 Дедуп: тот же sha256/url во внешнем канале → is_own=0 (упоминание), канонический остаётся is_own_canonical=1 Проверка: код реализован (канон vs упоминание); проверка на реальных данных после бэкфилла

3. Классификатор

  • 3.1 classify.py: is_own=1 + направление по словарю → relevance=critical, classified=True, method='dict-own' (без LLM при недоступности) Проверка: тестовый свой пост со словарным попаданием при выключенной Ollama → classified=1 relevance=critical
  • 3.2 Поддержка мультинаправлений: классификатор может писать несколько записей classifications (fan-out) Проверка: пост linux+ai имеет 2 записи classifications

4. Публикатор (fan-out)

  • 4.1 publisher/bot.py: publish_multi(directions) → публикация карточки в каждый @dedinit_vesti___bot; возвращает {dir: message_id} Проверка: dry-run с токеном → map направлений; без токена → dry_run=True (проверено ['linux','ai'])
  • 4.2 Атрибуция в карточке (publisher/card.py): для is_own-постов строка «Дед в АйТи (@dedinit)» + ссылка на оригинал, для внешних — без Проверка: make_card(is_own пост) содержит t.me/dedinit/ и «Дед в АйТи» (проверено); make_card(внешний) — нет
  • 4.3 Запись distributed_dirs + tg_message_ids в published при fan-out Проверка: после approve (TestClient, dry-run) distributed_dirs=JSON([linux, ai]) в published + views

5. Веб

  • 5.1 Фильтр «Свои» (is_own) в /candidates: параметр own=1|0, бейдж «СВОЙ» Проверка: TestClient GET /candidates?own=1 → только is_own посты с бейджем «⭐ СВОЙ» (проверено)
  • 5.2 Выбор направлений рассылки при approve: чекбоксы (по умолчанию — направления классификации); approve → publish_multi Проверка: TestClient POST /posts/{id}/approve с dirs=linux,ai → 302 /published, distributed_dirs=[linux,ai] (dry-run) (проверено)
  • 5.3 Опубликованные: показ distributed_dirs (в какие каналы разослан) и метрики по каждому Проверка: /published содержит «Разослан в» с @dedinit_vesti_linux_ru_bot и ai (проверено TestClient)

6. Банк статей (news-store)

  • 6.1 store.py: frontmatter origin: own + source_url + author для is_own-постов; origin: external для внешних Проверка: бандл содержит origin: own и source_url: https://t.me/dedinit/<id>, author «Дед в АйТи» (проверено)
  • 6.2 Бандлы по каждому направлению fan-out (bundles///.md) Проверка: create_bundle(['linux','ai']) → 2 файла в bundles/linux и bundles/ai (проверено)

7. Проверка интеграции и документация

  • 7.1 Полный прогон: синк → краулер dedinit → классификатор → веб (approve с fan-out) → бандлы; внешние источники не затронуты (is_own=0 по умолчанию) Проверка: counts по is_own в БД, бандлы, /published, runs ok — ждёт бэкфилла 2.3 (реальная сеть)
  • 7.2 Обновить STATUS.md / TODO.md / WALKTHROUGH.md (что сделано, как запускать, питфолы) Проверка: документы отражают новое состояние (обновлено при закрытии сессии)