159 lines
13 KiB
Markdown
159 lines
13 KiB
Markdown
# 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_slug` — `plane_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) перед
|
||
прод-деплоем; прод-контейнер не ронять в рамках задачи.
|