Files
vesti/AGENT.MD
T

65 lines
7.4 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.
# AGENT.MD — Правила проекта VESTI
## Правило №1: ВСЕ изменения — через OpenSpec
- **Перед каждым планируемым изменением — обязательно grill-with-docs** (интервью по дизайн-дереву: глоссарий в CONTEXT.md + ADR при необходимости). Только после достижения общего понимания с пользователем — создавать change.
- **Любое изменение проекта (багфикс, фича, рефакторинг, конфиг, деплой, docs) оформляется как отдельный change** в `/opt/vesti/openspec/changes/<change-name>/`.
- **НЕ начинать правки кода/файлов, пока change не создан и не провалидирован (`openspec validate` чисто).** Это обязательное требование (у VESTI нет бэкапа — OpenSpec фиксирует состояние и откат).
- **Сразу после правок — обновить STATUS.md/TODO.md и сделать бэкап** (см. «Бэкап» ниже).
- Формат change (как в образцах `tg-crawler-publisher-prototype`, `publisher-service`):
- `.openspec.yaml` (schema: spec-driven, created: дата)
- `proposal.md` — зачем (проблема пользователя)
- `design.md` — как (дизайн, точные правки)
- `tasks.md` — чеклист задач; отмечать `[x]` при выполнении
- CLI `openspec change new` НЕ существует → change создаётся вручную (mkdir + файлы по образцу).
- Проверка: `openspec validate <change-name>` — должно быть чисто.
- После подтверждения пользователем change архивируется.
- Не начинать правки кода, пока change не создан и не провалидирован.
## Стек и архитектура
- Новостной агрегатор: TG-краулер → классификатор (Ollama qwen3:8b-nothink) → веб-модерация → публикация в Telegram.
- Веб: :8400 — страницы /candidates (модерация), /crawlers (статус краулеров, запуск воркера), /sources (управление источниками: add/edit/toggle-pause/delete; источник истины — sources.yaml).
- `vesti-web` (FastAPI+Jinja2, :8400, systemd-юнит) --HTTP POST--> `publisher-service` (FastAPI, Docker-контейнер, :8410) --Bot API (SOCKS5 127.0.0.1:1080)--> Telegram @dedinit_vesti.
- БД: SQLite `/opt/vesti/db/vesti.db` — открывать с WAL + busy_timeout (иначе `database is locked` при фоновом классификаторе).
- Фронтенд: **без внешних CDN** (никаких unpkg/jsdelivr). Bootstrap локален: `web/static/bootstrap.min.css`, htmx запрещён. approve/reject — обычные POST-формы.
- Markdown в шаблонах — фильтр `| markdown` (XSS-safe: escape → nl2br → sane_lists). Сырой вывод текста запрещён.
- Даты в UI — фильтр `| dt` → `ЧЧ:ММ ДД.ММ.ГГГГ` (не ISO `[:16]`).
- Пути бандлов: в БД `published.bundle_path` хранится **относительный** путь от `bundles/` (напр. `linux/2026-09/slug.md`), ссылка в UI `/bundle/<rel>`. Абсолютные пути запрещены (баг двойного слэша — исправлен).
## Секреты и .env
- `.env` в корне (chmod 600). Переменные: `ADMIN_USER`, `ADMIN_PASSWORD` (веб-логин), `VESTI_BOT_TOKEN`, `VESTI_BOT_CHANNELS`, `TG_PROXY`, `PUBLISHER_URL`, api_id/api_hash.
- Значения секретов НЕ показывать, НЕ сохранять, НЕ коммитить (пишется только имя переменной).
- `.env.example` — всегда актуализировать при добавлении переменной.
## Правила работы
- **Не удалять пользовательские файлы.** Перезапись/перемещение — только после явного подтверждения пользователя.
- Дедуп постов: sha256(text) + url. Физически ничего не удаляем — только смена `status`.
- Общение с пользователем — на русском, кратко (статусы), без «всё ок».
- Все ресурсы проекта — в `/opt/vesti` (ничего в домашней директории).
- Документация проекта: STATUS.md (живой), PRD.md, TODO.md, WALKTHROUGH.md — поддерживать актуальными; при закрытии сессии обновлять.
- Ссылки и доступы к ресурсам (URL/SSH/пути) фиксировать в файлах проекта.
## Запуск / проверка
```bash
cd /opt/vesti
sudo systemctl restart vesti-web # веб :8400 (0.0.0.0, uvicorn web.app:app)
docker compose -f services/publisher/docker-compose.yml up -d --build # publisher :8410
curl -s http://127.0.0.1:8410/healthz # ok, bot=dedinit_controller_bot, proxy, channels
.venv/bin/python -m crawler.telegram_crawler --all # краулер (инкрементально)
.venv/bin/python -m crawler.rss_crawler --all # RSS/Atom-краулер (условные GET, etag/modified; rss_state)
.venv/bin/python -m crawler.rss_crawler --source lwn --dry-run # сухой прогон без записи в БД
.venv/bin/python -m crawler.crawl_sources --all # фаза 1: сбор кандидатов в очередь (telegram+rss)
.venv/bin/python -m crawler.worker --workers 8 --limit 200 # фаза 3: параллельная обработка очереди (ThreadPoolExecutor)
MAX_CONCURRENT_LLM=2 .venv/bin/python -m crawler.worker --workers 8 # лимит одновременных LLM-запросов к Ollama
CLASSIFY_TIMEOUT=20 .venv/bin/python -m classifier.classify --db db/vesti.db --limit 200
openspec validate <change-name> # валидация change
```
- Внешний доступ: https://vesti.nixg.ru (Caddy на VPS02: /opt/caddy/Caddyfile, reverse_proxy 10.8.0.2:8400).
## Направления (directions)
linux, tech, politics, games, electronics, llm. Свой канал @dedinit — источник `own: true`, посты is_own=1, fan-out по направлениям с атрибуцией «Дед в АйТи».
## Бэкап (автоматический, вручную НЕ запускать)
- Скрипт: `/opt/vesti/backup.sh` (по образцу `/opt/icq/backup.sh`): архивирует проект → `/opt/vesti/backups/vesti_<дата>.tar.gz`, копирует на Яндекс.Диск `/mnt/yandex-disk/backup/vesti-backups/`.
- Хранение: локально 7 дней, на ЯД 30 дней (ротация в скрипте).
- Запуск: root cron `45 2 * * *` (как у icq). ЯД монтируется автоматически (fstab davfs + @reboot).
- Бэкапы запускаются автоматически по крону — вручную НЕ запускать.