# 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:////projects//issues//`. - Источники частей 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`. - Рендер через `ORCH-NNN` (`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) перед прод-деплоем; прод-контейнер не ронять в рамках задачи.