Session close 2026-09-15: gitverse source of truth, gitea mirror, token locations in AGENT.md

This commit is contained in:
2026-09-15 17:47:29 +00:00
parent 0d86f843c3
commit 65c167acc2
4 changed files with 180 additions and 10 deletions
+22 -8
View File
@@ -1,7 +1,7 @@
# Email Assistant — локальный архив и ассистент почты
**Дата:** 2026-09-13
**Фаза:** 1.5–1.7 + Портфель веб-UI (планирование) + Классификация/обработчики (в работе)
**Дата:** 2026-09-15
**Фаза:** 1.5–1.7 + Портфель веб-UI (планирование) + Классификация/обработчики (в работе) + IMAP Realtime Sync (планирование)
**Стек:** Himalaya CLI → Python → SQLite → Ollama (Qwen3:8b) → Radicale (CalDAV) → Telegram
@@ -140,8 +140,22 @@ Hermes cron:
- [x] **Фикс секретов (2026-09-14)**: скрипт теперь сам читает `radicale/.env` (RADICALE_PASS) и `/opt/vesti/.env` (VESTI_BOT_TOKEN) — раньше без ручного export был 401; добавлен stdlib-парсер .env (python-dotenv в системе нет)
- [x] **Живой прогон (2026-09-14)**: письмо 2026/422 → VTODO «Задачи» (204) + VEVENT «Рабочий» (204); повтор — идемпотентно (0 дублей)
- [x] **Cron (2026-09-14)**: `mail-classify-handlers` (6e1e78ceedfd, every 5m) — классификатор (--limit 10) → обработчики; end-to-end проверено: 5 новых «meeting» → 5 VEVENT (201)
- [ ] Живое urgent-письмо → доставка в Telegram (механика готова, токен подхватывается; пока не было urgent-писем)
- [x] **Telegram-секреты**: токен `VESTI_BOT_TOKEN` читается из /opt/vesti/.env; канал-дефолт `@dedinit_vesti` (TELEGRAM_CHAT_ID можно переопределить в .env проекта)
- [x] **Живое urgent-письмо → доставка в Telegram (2026-09-15)**: письмо с id 3216 («RE: Платежи Аврора», Archive/2026/08/3216) помечено `classification: urgent` → `email_handlers.py` с `TELEGRAM_CHAT_ID=281328953` отправил в ЛС (private чат kpa39l) через бота @dedinit_controller_bot — `msg_id=60`, пользователь подтвердил получение; `handled_urgent: true` записан (идемпотентно, повторной отправки нет)
- [x] **Telegram-секреты**: токен `VESTI_BOT_TOKEN` читается из /opt/vesti/.env; канал-дефолт `@dedinit_vesti` — **внимание**: для ЛС нужно явно `TELEGRAM_CHAT_ID=281328953` (private chat kpa39l); зафиксировать дефолт в ЛС — TODO при настройке stream-сервиса
---
## Сделано в сессии 2026-09-15 (IMAP realtime sync — планирование + Telegram-уведомления в ЛС)
- [x] **Выделена авторизация IMAP в отдельную функцию** — `scripts/imap_client.py` (новый): `imap_connect()` (socket+STARTTLS+LOGIN, re-try 5→60с, креды из config/himalaya-config.toml); `mail_archive.py` переведён на неё (sys.path-фикс для cron); проверено живьём: `OK: connected+LOGIN as e.storozhenko @ mail.corpoffice.tech`
- [x] **Логирование авторизации + метрики** (в imap_client.py): JSON-лог `/opt/hermes/email/logs/imap_client.log` (conn_ok/conn_error/auth_ok/auth_failed/session_started/session_ended); `imap_metrics()` (auth_success_rate, conn_ok/err, sessions_active); контекст-менеджер `imap_session`; `--metrics` CLI
- [x] **Telegram-уведомления о важных письмах — в ЛС** (kpa39l): создан `/opt/hermes/email-assistant/.env` с `TELEGRAM_CHAT_ID=281328953`; живой тест: письмо 3216 («RE: Платежи Аврора») помечено urgent → доставка в private chat 281328953 (bot @dedinit_controller_bot, msg_id=60), пользователь подтвердил
- [x] **Найден и исправлен баг доставки**: крон-скрипт `mail-classify-handlers.sh` использовал системный `python3` без httpx → все Telegram-уведомления молча падали (накопилось 10 urgent-писем). Фикс: `PY=/opt/vesti/.venv/bin/python` + `--limit 2` (дозированная отправка backlog, анти-спам)
- [x] **Формат даты в уведомлениях**: добавлены `format_date_for_tg()` (ISO → `02.09.2026 10:49`) и `_unquote_yaml()` (снятие YAML-кавычек в parse_email_md); строка `📅 ДД.ММ.ГГГГ ЧЧ:ММ` в handle_urgent
- [x] **IMAP realtime sync (проект)**: proposal.md + design.md + tasks.md + spec-дельты (imap-realtime-sync, email-attachments, email-classification) — openspec `change 'imap-realtime-sync' is valid`; диагноз rate-limit (не TLS-fingerprinting); 2 микросервиса (imap_stream.py IDLE + change_analyzer.py ChangeLog SQLite), systemd, soft-delete
- [x] **Backlog urgent-писем**: 10 писем в INBOX с `classification: urgent` без `handled_urgent` (июль 2026 — сентябрь 2026, включая срочное «переоформление договоров… отключение интернета до 20-го») — отправляются по 2 за крон-прогон в ЛС
- [x] **Репозиторий переведён на gitverse (источник истины)**: создан приватный `kpa39l/email-assistant` на gitverse.ru (id 336792) через API; remote `gitverse` добавлен; master запушен; **gitea: pull mirror `estorozhenko/email-assistant` ← gitverse (12h, id 54)** — gitea.nixg.ru остаётся зеркалом, не источником
- [x] **AGENT.md создан** — политика репозитория: gitverse = истина, gitea = зеркало, команды пуша, **местоположение токенов** (git-tokens.env, VESTI_BOT_TOKEN, TELEGRAM_CHAT_ID)
### Задача 1: Веб-интерфейс ассистента ⬜
- [ ] FastAPI + SQLite FTS5: список писем (дата/адресант/тэги/папка)
@@ -300,10 +314,10 @@ dav.example.com {
## Конфигурация
- **Репозиторий:** `https://gitea.nixg.ru/hermes/email-assistant`
- **Push mirror на gitverse.ru:** ❌ не настроен
- [ ] Настроить push mirror из gitea.nixg.ru в gitverse.ru
- Требуется: создать репозиторий на gitverse.ru, получить токен, настроить mirror в настройках gitea (Settings → Git Hooks/Mirrors → Add Push Mirror)
- **Репозиторий (источник истины):** `https://gitverse.ru/kpa39l/email-assistant` (private, remote `gitverse`, https с токеном из `/opt/hermes/.hermes/secrets/git-tokens.env`)
- **Gitea (зеркало):** `https://gitea.nixg.ru/estorozhenko/email-assistant` (pull mirror ← gitverse, интервал 12h, id 54). Старый `hermes/email-assistant` — обычный репо, не зеркало.
- **AGENT.md** — политика репозитория/токенов (см. файл)
- ~~Push mirror gitea → gitverse~~ ✅ **сделано 2026-09-15** (pull mirror наоборот: gitverse → gitea)
### Ресурсы проекта (расположение и доступ)