Files

13 KiB
Raw Permalink Blame History

BRD — ORCH-067: Telegram tracker (bump + статусы Plane + кликабельный номер задачи)

Work Item: ORCH-067 Тип: Багфикс + enhancement Приоритет: высокий Компонент: Telegram live-tracker и уведомления оркестратора (src/notifications.py) Расширяет: открытый баг seq=55 («bump не сработал, регресс ORCH-042»)


1. Бизнес-контекст и проблема

Оркестратор ведёт по одной «живой карточке» (live-tracker) на каждую задачу в Telegram (src/notifications.py). Карточка тихо обновляется на каждом переходе стадии, а отдельными пингами шлются только события, требующие внимания владельца (approve-gate, деплой-фейл, падение агента, ошибка задачи).

Сейчас есть четыре боли:

  1. bump не работает в проде. Диагностика оператора: код режима bump в update_task_tracker корректен (delete старого → sendMessage вниз → repoint tracker_message_id), НО в проде tracker_mode="edit" (дефолт src/config.py:408), а ORCH_TRACKER_MODE=bump не выставлен. Карточка обновляется edit-in-place и остаётся «вверху» ленты, тонет под новыми сообщениями — наблюдатель не видит актуального состояния без скролла.

  2. Карточка показывает внутренние названия стадий, а не Plane-статусы. После ввода осмысленной статусной модели Plane (ORCH-066) карточка по-прежнему рендерит внутренние ярлыки стадий (Анализ/Архитектура/…), а текущий статус задачи в терминах, понятных наблюдателю в Plane (To Analyse → Analysis → In Review → … → Done), в шапке карточки не отражён. Особенно теряется состояние ожидания согласования BRD = Plane-статус In Review: сейчас это лишь строка «/⏸️ Подтверждение BRD … », не выраженная как полноценный статус.

  3. Номер задачи в карточке некликабелен. ORCH-066 в карточке — обычный текст; чтобы открыть задачу в Plane, наблюдателю приходится искать её вручную.

  4. Номер задачи некликабелен и во всех остальных уведомлениях орка (approve-requested, QG-fail, deploy SUCCESS/FAIL, Needs Input, прод-деплой и т. п.) — везде, где упоминается work_item_id, это просто текст.

2. Цель

Сделать live-tracker и уведомления орка наблюдаемыми «из коробки»:

  • bump работает по умолчанию (карточка падает вниз свежим сообщением при каждом обновлении, ровно одна карточка на задачу, без спама и дублей);
  • карточка явно показывает текущий Plane-статус по модели ORCH-066, включая человеческие гейты (⏸️ In Review — согласование BRD, ⏸️ Awaiting Deploy — ожидание Confirm Deploy, ❓ Needs Input — нужны уточнения);
  • номер задачи кликабелен в карточке и во всех Telegram-уведомлениях орка и ведёт на страницу задачи в Plane.

3. Заинтересованные стороны

  • Owner (Слава) — основной потребитель карточки и уведомлений; источник 4 требований.
  • Агенты конвейера — косвенно (карточка отражает их прогресс; поведение агентов не меняется).
  • Другие проекты (enduro-trails) — общий инстанс/БД; изменения не должны вызывать регресс.

4. Объём работ (scope)

4.1. Требование 1 — bump по умолчанию

  • Режим bump должен быть поведением по умолчанию: при каждом обновлении карточка удаляется и пересоздаётся внизу ленты, одна карточка на задачу, тихо (disable_notification), без дублей.
  • Инвариант «одна карточка на задачу» сохраняется в обоих режимах (edit остаётся как опция через env).
  • Транзиентный фейл send не должен обнулять tracker_message_id и плодить дубли (инвариант уже заложен в коде — сохранить).

4.2. Требование 2 — статусы карточки как в Plane (модель ORCH-066)

  • В шапке/верхней части карточки явно отображается текущий Plane-статус задачи по модели ORCH-066.
  • Полный маппинг состояний (имена — финальные из модели ORCH-066):
    To Analyse → Analysis → In Review (⏸️ ожидание согласования BRD) → Architecture →
    Development → Code-Review → Testing → Awaiting Deploy (⏸️ ожидание Confirm Deploy) →
    Deploying → Monitoring after Deploy → Done
    
    Ветки: Needs Input (аналитик задал вопросы), Blocked, Rejected, Cancelled.
  • Человеческие гейты отражаются как ПОЛНОЦЕННЫЕ статусы с паузой:
    • согласование BRD → «⏸️ In Review — ожидание согласования BRD»;
    • ожидание прод-деплоя → «⏸️ Awaiting Deploy — ожидание Confirm Deploy»;
    • вопросы аналитика → « Needs Input — нужны уточнения».
  • Существующая семантика строки «Подтверждение BRD» сохраняется (время ожидания/«твоё время»), но статус карточки при этом явно показывает In Review (approve-pending).

4.3. Требование 3 — кликабельный номер задачи в карточке

  • work_item_id (напр. ORCH-066) в карточке — гиперссылка на страницу задачи Plane: https://<PLANE_WEB_BASE>/<workspace_slug>/projects/<project_id>/issues/<issue_id>/.
  • Источники частей URL:
    • PLANE_WEB_BASE — из конфигурации (env, поле plane_web_url / ORCH_PLANE_WEB_URL; значение прод — plane.mva154.duckdns.org); fail-safe: не задан → номер без ссылки;
    • workspace_slugplane_workspace_slug (уже есть в settings, прод — ag_proj);
    • project_id — резолвится per-task по репозиторию задачи (ORCH / Sandbox);
    • issue_id (UUID) — из БД: колонка tasks.plane_issue_id.
  • Рендер через <a href="...">ORCH-NNN</a> (parse_mode=HTML уже включён); HTML в title/тексте экранируется, чтобы не сломать разметку.

4.4. Требование 4 — кликабельный номер во ВСЕХ уведомлениях орка

  • Единый хелпер (напр. plane_issue_link(work_item_id, plane_issue_id, project_id) -> html) строит кликабельный номер с fail-safe; применяется во всех точках send_telegram/ notify_*, где упоминается work_item_id (approve-requested, QG-fail, deploy SUCCESS/FAIL, Needs Input, прод-деплой, alert'ы launcher/merge_gate/job_reaper/ security_gate/reconciler/main).

5. Вне объёма (out of scope)

  • Транспорт send_telegram / edit_telegram / delete_telegram (parse_mode HTML уже есть) — не трогать.
  • Инвариант «одна карточка на задачу» — не нарушать (не плодить дубли).
  • Логика disable_notification (карточка тихая; пингуют только alert-хелперы) — не трогать.
  • STAGE_TRANSITIONS, Quality Gates, схема БД — НЕ менять.
  • Изменение поведения агентов/конвейера.

6. Зависимости

  • Маппинг статусов (требование 2) опирается на статусную модель ORCH-066. ORCH-066 уже в конвейере на стадии deploy. Эту задачу делать ПОСЛЕ прода ORCH-066, чтобы имена статусов совпали. Если ORCH-066 ещё не в проде на момент разработки — использовать согласованные финальные имена из модели: To Analyse, Analysis, Code-Review, Awaiting Deploy, Deploying, Monitoring after Deploy, In Review, Needs Input, Blocked, Cancelled, Done.
  • Конфигурация plane_web_url / plane_workspace_slug уже существует в src/config.py (ORCH-017); реестр проектов src/projects.py (get_project_by_repo().plane_project_id) уже даёт per-task project_id.

7. Fail-safe (обязательно)

  • Нет PLANE_WEB_BASE / нет plane_issue_id / нет project_id / loopback-база → показывать номер БЕЗ ссылки, не падать.
  • HTML-экранирование пользовательского текста (title и пр.) во всех сообщениях с parse_mode=HTML.
  • Bump: транзиентный фейл send не обнуляет tracker_message_id и не плодит дубли.
  • Любая ошибка построения статуса/ссылки никогда не должна ронять рендер карточки или отправку уведомления (degrade gracefully).

8. Критерии успеха (Definition of Done)

  • Bump работает из коробки: карточка падает вниз при обновлении, одна на задачу.
  • Карточка показывает Plane-статус новой модели, включая ⏸️ In Review (согласование BRD), ⏸️ Awaiting Deploy, ❓ Needs Input.
  • Номер задачи кликабелен в карточке И во всех уведомлениях орка (ведёт на страницу Plane).
  • Fail-safe покрыт тестами (нет URL/plane_id/project → без ссылки, не падает; HTML-экранирование).
  • pytest tests/ -q зелёный.
  • Документация обновлена в том же PR: CLAUDE.md (раздел нотификаций/tracker), CHANGELOG.md, ADR per-work-item.

9. Риски

  • Регресс enduro-trails. Смена дефолта tracker_mode на bump меняет поведение для всех проектов. Митигация: bump уже реализован и протестирован концептуально; инвариант «одна карточка» сохранён; env-переключатель edit остаётся.
  • Поломка HTML-разметки при неэкранированном title → сообщение не доставится. Митигация: обязательное html.escape + тесты.
  • Источник «истинного» Plane-статуса для веток, не выводимых из tasks.stage (Needs Input/Blocked/Rejected/Cancelled, Deploying/Monitoring), при запрете на изменение схемы БД — архитектурное решение (ADR), с обязательным fail-safe (без сети не падать).
  • Self-hosting. Орк правит сам себя; обязательна страховка через staging (8501) перед прод-деплоем; прод-контейнер не ронять в рамках задачи.