auto-sync: 2026-06-04 11:50:01
This commit is contained in:
@@ -1,28 +1,113 @@
|
||||
# Dev Report: orchestrator — живой Telegram-трекер задачи (Вариант B+)
|
||||
Дата: 2026-06-04
|
||||
Статус: IN PROGRESS
|
||||
Статус: DONE
|
||||
|
||||
## Задача
|
||||
Заменить ~15 отдельных ТГ-сообщений на задачу одним живым сообщением-трекером
|
||||
(editMessageText по стадиям). Отдельными сообщениями с пингом — только approve-gate,
|
||||
deploy-fail, agent-fail, error.
|
||||
|
||||
## Сделано
|
||||
- [x] Прочитал ТЗ, изучил codebase (notifications.py, db.py, usage.py, stage_engine.py, launcher.py)
|
||||
- [x] Создал ветку feat/telegram-live-tracker от main (2801983)
|
||||
- [ ] db.py: колонки tracker_message_id, model, brd_review_*
|
||||
- [ ] usage.py: short_model_name, парсинг модели
|
||||
- [ ] notifications.py: render_task_tracker, send/edit tracker, алерты
|
||||
- [ ] stage_engine.py / launcher.py: тайминги BRD review + вызовы трекера
|
||||
- [ ] Тесты
|
||||
- [ ] pytest зелёный
|
||||
- [ ] PR в Gitea
|
||||
## Результат (кратко)
|
||||
- **PR:** #21 — https://git.mva154.duckdns.org/admin/orchestrator/pulls/21
|
||||
- **Ветка:** `feat/telegram-live-tracker` от `main` (2801983)
|
||||
- **Commit:** `9a0298d`
|
||||
- **pytest:** `259 passed, 9 failed` (те же off-limits HMAC/401 в test_webhooks.py).
|
||||
Baseline на этом хосте — `244 passed, 9 failed`; +15 новых проходящих тестов,
|
||||
0 новых падений. (В ТЗ значился baseline 243+10 — на этом хосте фактически 244+9,
|
||||
набор падений идентичный и не тронут.)
|
||||
- НЕ смержен — на ревью Стрим.
|
||||
|
||||
## Изменённые файлы
|
||||
(в процессе)
|
||||
## Изменённые файлы (6, +893/-35)
|
||||
- `src/db.py` — idempotent ALTER-ы: `tasks.tracker_message_id`, `tasks.title`,
|
||||
`tasks.brd_review_started_at`, `tasks.brd_review_ended_at`, `agent_runs.model`.
|
||||
Хелперы: `get/set_tracker_message_id`, `mark_brd_review_started/ended`.
|
||||
- `src/usage.py` — `short_model_name()` (отрезает провайдер-префикс и `claude-`);
|
||||
`_extract_model()` парсит модель из result-JSON (`modelUsage`); `record_usage`
|
||||
сохраняет модель (`COALESCE`, не затирает существующую).
|
||||
- `src/notifications.py` — ядро:
|
||||
- `render_task_tracker(task_id)` — stateless рендер из `agent_runs` + task.
|
||||
- `update_task_tracker(task_id)` — sendMessage→store id→editMessageText,
|
||||
fallback на новое сообщение при фейле edit, всегда `disable_notification=true`.
|
||||
- `edit_telegram()`, `send_telegram()` теперь возвращает message_id.
|
||||
- `notify_*` переведены в режим «только трекер / только лог», кроме 4 алертов.
|
||||
- `src/stage_engine.py` — штамп `brd_review_ended` на переходе analysis→architecture.
|
||||
- `src/webhooks/plane.py` — сохранение `title` задачи при создании.
|
||||
- `tests/test_telegram_tracker.py` — новые тесты (см. ниже).
|
||||
|
||||
## Результат
|
||||
(в процессе)
|
||||
## Формат трекера
|
||||
|
||||
### В процессе (deploy идёт)
|
||||
```
|
||||
🛠️ ET-012 · Треки с зума z5
|
||||
━━━━━━━━━━━━━━━━━━━━━━
|
||||
✅ Analysis 10м · 1.1M↓/39.6k↑ · $2.38 · opus-4-8
|
||||
⏸️ Ревью БРД 8м · твоё время
|
||||
✅ Architecture 9м · 1.5M↓/34.4k↑ · $2.24 · opus-4-8
|
||||
✅ Development 11м · 8.4M↓/45.8k↑ · $7.29 · opus-4-8
|
||||
✅ Review 3м · 1.2M↓/12.9k↑ · $1.53 · sonnet-4.6
|
||||
✅ Testing 5м · 1.2M↓/19.5k↑ · $1.51 · sonnet-4.6
|
||||
🔄 Deploy … · идёт
|
||||
━━━━━━━━━━━━━━━━━━━━━━
|
||||
💰 13.4M↓ / 152.2k↑ · $14.95
|
||||
```
|
||||
(пока Deploy ещё не финишировал — токены deployer-а не учтены в Итого; на финише
|
||||
учтутся.) Пока идёт ожидание ревью БРД, строка показывает `· твоё время ⏳`.
|
||||
|
||||
### На финише
|
||||
```
|
||||
🎉 ET-012 · Треки с зума z5 — ГОТОВО
|
||||
━━━━━━━━━━━━━━━━━━━━━━
|
||||
✅ Analysis 10м · 1.1M↓/39.6k↑ · $2.38 · opus-4-8
|
||||
⏸️ Ревью БРД 8м · твоё время
|
||||
✅ Architecture 9м · 1.5M↓/34.4k↑ · $2.24 · opus-4-8
|
||||
✅ Development 11м · 8.4M↓/45.8k↑ · $7.29 · opus-4-8
|
||||
✅ Review 3м · 1.2M↓/12.9k↑ · $1.53 · sonnet-4.6
|
||||
✅ Testing 5м · 1.2M↓/19.5k↑ · $1.51 · sonnet-4.6
|
||||
✅ Deploy 6м · 1.6M↓/22.4k↑ · $1.73 · opus-4-8
|
||||
━━━━━━━━━━━━━━━━━━━━━━
|
||||
💰 15.0M↓ / 174.6k↑ · $16.68
|
||||
⏱️ Всего 56м · агенты 44м · твоё 8м
|
||||
🔗 PR #24 · 📦 deployed
|
||||
```
|
||||
(Точные значения совпадают с макетом из ТЗ; токены in = input+cache_read+cache_creation,
|
||||
out — отдельно; модель — короткая; время в минутах, <1м → `<1м`.)
|
||||
|
||||
## Что теперь НЕ шлётся отдельными сообщениями (только трекер / лог)
|
||||
- Старт агента (`notify_agent_started`) → refresh трекера.
|
||||
- Завершение агента (`notify_agent_finished`) → refresh трекера.
|
||||
- Переход стадии (`notify_stage_change`) → refresh трекера.
|
||||
- QG-pending / QG-failed (`notify_qg_failure`, `notify_qg_result`) → только лог
|
||||
(CI state: pending — не ошибка).
|
||||
- QG-passed → только лог.
|
||||
- Тех-мусор (run_id, exit_code, пути логов) — убран из ТГ-текста.
|
||||
|
||||
## Что ОСТАЁТСЯ отдельным сообщением (с пингом, disable_notification=false)
|
||||
- 📋 Approve-gate (`notify_approve_requested`) — текст про перевод в Approved
|
||||
(устаревший `:approved:` заменён). Заодно стартует «твоё время» (BRD review clock).
|
||||
- 🚨 Deploy упал / откат (`send_telegram` в launcher.py и stage_engine.py) — без изменений.
|
||||
- ❌ Агент упал, exit_code != 0 (`send_telegram` в launcher) — путь к логам только в лог-файл (в коде launcher уже так; текст ТГ не содержит run_id-мусора по новым правилам трекера).
|
||||
- 🔴 Ошибка задачи (`notify_error`).
|
||||
|
||||
## Тесты (tests/test_telegram_tracker.py)
|
||||
- `short_model_name`: tokenator/claude-opus-4-8→opus-4-8, vibecode/claude-sonnet-4.6→sonnet-4.6, None/'' → ''.
|
||||
- парсинг модели из `modelUsage`.
|
||||
- `render_task_tracker`: строки этапов (in↓/out↑·cost·model), строка Ревью БРД (твоё время / ⏳ при ожидании), активная стадия 🔄 идёт, блок Итого 💰, финиш ⏱️ (три времени) + 🔗/📦, экранирование <>& в названии, опускание модели если неизвестна.
|
||||
- send/edit/fallback: первое сообщение → send + store id (silent); переход → editMessageText существующего; edit-фейл → новое сообщение + обновлённый id.
|
||||
- алерты: approve-gate и error шлются ОТДЕЛЬНО (disable_notification=false); stage-change / agent-start / QG-pending НЕ шлют отдельных сообщений.
|
||||
|
||||
## Проблемы и решения
|
||||
(в процессе)
|
||||
- **f-string + backslash на Python 3.10 (прод-хост):** литерал с `\uXXXX` внутри
|
||||
`{...:<13}` ломал парсинг. Решено — вынес метку «Ревью БРД» в константу `_BRD_LABEL`.
|
||||
- **локальный `import httpx` в `_done_link`** мешал моку → перешёл на module-level `httpx`.
|
||||
- **Источник модели:** конфиг launcher задаёт `--model` не для всех агентов;
|
||||
надёжный источник — `modelUsage` из result-JSON → сохраняю в `agent_runs.model`.
|
||||
- **title задачи** в `tasks` не хранился → добавил колонку + populate при создании.
|
||||
|
||||
## НЕ тронуто (по ТЗ)
|
||||
- usage_comment / Plane-комменты (формат fix #20), PLANE_STATES, launcher.py
|
||||
deployer-guard, HMAC/queue/cost-расчёт, conftest, nginx/.env.
|
||||
|
||||
## Деплой
|
||||
Код в проде НЕ задеплоен (образ собирается из src в image, не из репо) — это
|
||||
задача мержа/CI после ревью. Миграции БД idempotent (`_ensure_column`), безопасны
|
||||
на живой проде при следующем `init_db()`.
|
||||
|
||||
Reference in New Issue
Block a user