8.1 KiB
8.1 KiB
Dev Report: orchestrator — живой Telegram-трекер задачи (Вариант B+)
Дата: 2026-06-04 Статус: DONE
Задача
Заменить ~15 отдельных ТГ-сообщений на задачу одним живым сообщением-трекером (editMessageText по стадиям). Отдельными сообщениями с пингом — только approve-gate, deploy-fail, agent-fail, error.
Результат (кратко)
- PR: #21 — admin/orchestrator#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-levelhttpx. - Источник модели: конфиг 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().