Files
vesti/AGENT.MD
T

7.4 KiB
Raw Blame History

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/пути) фиксировать в файлах проекта.

Запуск / проверка

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).
  • Бэкапы запускаются автоматически по крону — вручную НЕ запускать.