# 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) перед
  прод-деплоем; прод-контейнер не ронять в рамках задачи.
