mirror of
https://gitverse.ru/kpa39l/vesti.git
synced 2026-09-29 18:05:03 +00:00
openspec: архив 14 завершённых change-ов (веб-фиксы, crawler-queue, own-content-hub, publisher-service); спеки влиты в openspec/specs
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
## Purpose
|
||||
|
||||
Классификация постов по направлениям локальным LLM + словарный фильтр. Дополняется
|
||||
приоритетом «своего контента» и поддержкой мультинаправлений для fan-out.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Приоритет своего контента
|
||||
Классификатор MUST обрабатывать посты с `is_own=1` как «сильные кандидаты»: при наличии
|
||||
направления по словарю — relevance=critical, classified=True — даже если LLM недоступна
|
||||
(фолбэк без LLM, пост не теряется). Для внешних постов поведение без изменений.
|
||||
|
||||
#### Scenario: Свой пост, LLM недоступна
|
||||
- **WHEN** пост is_own=1, словарь дал направление, но Ollama недоступна
|
||||
- **THEN** пост получает direction (словарь), relevance=critical, classified=True,
|
||||
method='dict-own' (не требует LLM)
|
||||
|
||||
#### Scenario: Свой пост без направления по словарю
|
||||
- **WHEN** пост is_own=1, словарь не дал направление
|
||||
- **THEN** классификации нет (classified=False) до LLM; пост не теряется (остаётся в очереди)
|
||||
|
||||
### Requirement: Мультинаправления
|
||||
Классификатор MUST уметь возвращать несколько направлений для поста (для маппинга fan-out);
|
||||
основное направление хранится в posts.direction, дополнительные — в classifications
|
||||
(таблица уже позволяет несколько классификаций на пост).
|
||||
|
||||
#### Scenario: Пост про Linux + AI
|
||||
- **WHEN** пост упоминает и линукс, и нейросети
|
||||
- **THEN** в classifications может быть несколько записей (linux, ai); fan-out использует
|
||||
оба при подтверждении
|
||||
@@ -0,0 +1,21 @@
|
||||
## Purpose
|
||||
|
||||
Банк статей: markdown-бандлы с frontmatter + медиа. Дополняется пометкой происхождения
|
||||
своего контента и ссылкой на оригинал.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Атрибуция в бандле
|
||||
Бандл поста с is_own=1 MUST содержать в frontmatter `origin: own`, ссылку на оригинал
|
||||
(`source_url` = t.me/dedinit/<id>) и имя автора («Дед в АйТи»). Бандл внешнего поста —
|
||||
как раньше (origin: external, source_url=url источника).
|
||||
|
||||
#### Scenario: Бандл своего поста
|
||||
- **WHEN** create_bundle вызывается для поста is_own=1
|
||||
- **THEN** frontmatter содержит origin: own, source: dedinit, source_url:
|
||||
https://t.me/dedinit/<tg_post_id>, author: Дед в АйТи
|
||||
|
||||
#### Scenario: Бандл внешнего поста в нескольких направлениях
|
||||
- **WHEN** пост (свой или внешний) опубликован в несколько направлений
|
||||
- **THEN** бандл создаётся по каждому направлению (bundles/<dir>/<YYYY-MM>/<slug>.md),
|
||||
обе записи ссылаются на один и тот же original post_id
|
||||
@@ -0,0 +1,32 @@
|
||||
## Purpose
|
||||
|
||||
Чтение публичных Telegram-каналов через Telethon (MTProto) для сбора новостей с метриками
|
||||
популярности. Дополняется поддержкой «своих» источников (own: true) — контент пользователя.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Источники своего контента
|
||||
Краулер MUST распознавать источники с `own: true` в sources.yaml и для их постов
|
||||
проставлять `is_own=1`, `is_own_canonical=1`. Для таких источников медиа MUST
|
||||
скачиваться (контент принадлежит пользователю).
|
||||
|
||||
#### Scenario: Краулинг своего канала
|
||||
- **WHEN** источник slug=dedinit имеет own: true
|
||||
- **THEN** посты сохраняются с is_own=1 и is_own_canonical=1; медиа скачивается;
|
||||
инкрементальный обход и дедуп работают как обычно
|
||||
|
||||
#### Scenario: Чужой форвард в своём канале
|
||||
- **WHEN** пост в своём канале — форвард из чужого канала
|
||||
- **THEN** пост сохраняется с is_own=1 (это пост пользователя, он его переслал) и с
|
||||
fwd_from_channel_id/fwd_from_post_id; медиа не скачивается (содержимое чужое),
|
||||
атрибуция оригинала сохраняется в fwd-полях
|
||||
|
||||
### Requirement: Канонический экземпляр своего контента
|
||||
Если пост пользователя (is_own=1) позже встречается во внешнем канале (тот же sha256/url),
|
||||
внешний экземпляр MUST сохраняться как «упоминание» с is_own=0; каноническим остаётся
|
||||
первичный (is_own_canonical=1).
|
||||
|
||||
#### Scenario: Свой пост запостили в чужой канал
|
||||
- **WHEN** краулер находит в чужом канале пост с текстом, совпадающим с is_own-постом
|
||||
- **THEN** создаётся запись is_own=0 (упоминание) без дублирования контента; веб видит
|
||||
оба экземпляра, но кандидатом на публикацию считается канонический (is_own_canonical)
|
||||
@@ -0,0 +1,43 @@
|
||||
## Purpose
|
||||
|
||||
Публикация отобранных новостей через Bot API в тематические Telegram-каналы. Дополняется
|
||||
автораспространением своего контента (fan-out) по нескольким направлениям.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Автораспространение (fan-out)
|
||||
Подтверждение СВОЕГО поста (is_own=1) MUST публиковать карточку во ВСЕ тематические
|
||||
каналы @dedinit_vesti_<direction>_<lang>_bot, соответствующие выбранным направлениям
|
||||
(по умолчанию — все направления классификации поста). Каждая карточка MUST содержать
|
||||
атрибуцию «Дед в АйТи» (@dedinit) и ссылку на оригинал t.me/dedinit/<post_id>.
|
||||
|
||||
#### Scenario: Мульти-публикация
|
||||
- **WHEN** подтверждается свой пост с направлениями [linux, ai]
|
||||
- **THEN** карточка отправляется в @dedinit_vesti_linux_ru_bot и @dedinit_vesti_ai_ru_bot;
|
||||
обе содержат ссылку на оригинал
|
||||
|
||||
#### Scenario: Чужой пост — без fan-out
|
||||
- **WHEN** подтверждается внешний пост (is_own=0)
|
||||
- **THEN** публикуется только в канал своего направления, без атрибуции автора
|
||||
|
||||
### Requirement: Публикация по списку направлений
|
||||
Публикатор MUST поддерживать `publish_multi(directions)` — публикацию карточки по списку
|
||||
направлений, возвращающую map {direction: message_id}. При пустом списке направлений
|
||||
MUST публиковать в направление по умолчанию (direction поста).
|
||||
|
||||
#### Scenario: Список направлений рассылки
|
||||
- **WHEN** publish_multi вызывается с directions=[linux, ai]
|
||||
- **THEN** возвращается {linux: message_id1, ai: message_id2}; каждая публикация
|
||||
записывается в published с distributed_dirs
|
||||
|
||||
#### Scenario: Пустой список направлений
|
||||
- **WHEN** publish_multi вызывается без directions
|
||||
- **THEN** публикация идёт в канал направления поста (direction по умолчанию), без fan-out
|
||||
|
||||
### Requirement: Метрики по каждому направлению
|
||||
Для опубликованных карточек MUST собираться views через Bot API по каждому направлению
|
||||
(каждому message_id), чтобы веб показывал эффективность рассылки по лентам.
|
||||
|
||||
#### Scenario: Метрики fan-out
|
||||
- **WHEN** пост разослан в [linux, ai] и каналы набирают просмотры
|
||||
- **THEN** get_views вызывается для каждого message_id; views хранятся по направлению
|
||||
@@ -0,0 +1,28 @@
|
||||
## Purpose
|
||||
|
||||
Веб-интерфейс управления VESTI. Дополняется фильтром «Свои», бейджем и выбором
|
||||
направлений рассылки для своего контента.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Фильтр «Свои»
|
||||
Веб MUST давать фильтр постов по `is_own` (все/только свои/только внешние) и показывать
|
||||
бейдж «СВОЙ» у постов is_own=1. Для своего поста при подтверждении MUST отображаться
|
||||
выбор направлений рассылки (по умолчанию — все направления классификации поста).
|
||||
|
||||
#### Scenario: Фильтр своих постов
|
||||
- **WHEN** админ выбирает фильтр «Свои»
|
||||
- **THEN** показываются только посты is_own=1 с бейджем «СВОЙ» и чекбоксами направлений
|
||||
|
||||
#### Scenario: Подтверждение своего поста
|
||||
- **WHEN** админ подтверждает свой пост с выбранными направлениями [linux, ai]
|
||||
- **THEN** публикация идёт в оба канала (fan-out), результат виден в опубликованных с
|
||||
distributed_dirs
|
||||
|
||||
### Requirement: Список распространения
|
||||
Веб MUST показывать для опубликованного поста, в какие направления/каналы он был
|
||||
разослан (distributed_dirs) и метрики (views) по каждому каналу.
|
||||
|
||||
#### Scenario: Просмотр распространения
|
||||
- **WHEN** админ открывает опубликованный пост (свой)
|
||||
- **THEN** видит список @dedinit_vesti_<dir>_<lang>_bot с views по каждому
|
||||
Reference in New Issue
Block a user