# BRD: Единообразные коммент-артефакты в Plane от всех агентов
Work Item ID: **ORCH-016**
Стадия: analysis
Автор: analyst
Дата: 2026-06-05
Ревизия: 2 (учтён фидбэк стейкхолдера от 2026-06-05 — добавить длительность работы агента в коммент)
---
## 1. Бизнес-цель
Стейкхолдер (Слава) должен мочь из ленты комментариев задачи в Plane **за один клик** перейти к артефакту любого агента (ADR, PR, ревью, отчёт тестера, деплой-лог), а не разбирать «шумные» строки без удобной ссылки и человекочитаемого описания.
Помимо ссылок, по комментариям стейкхолдер хочет **видеть, сколько работал каждый агент** (длительность стадии), не открывая БД оркестратора и не лезя в `agent_runs`.
## 2. Мотивация
Сейчас в Plane комменты двух разных стилей:
| Кто пишет | Формат коммента | Источник |
|-----------|-----------------|----------|
| **Аналитик (эталон)** | HTML: человеческое описание стадии + `
` со списком ссылок на артефакты, заголовок «Документы:» | `src/stage_engine.py::_build_analyst_ready_comment` (PR #13) |
| Architect / Developer / Reviewer / Tester / Deployer | Однострочник «{icon} Role готов · 8.5M in / 45.8k out · $7.29» + markdown-ссылки следом | `src/usage.py::usage_comment` + `artifact_links` |
Проблемы второго формата:
1. Нет человеческого описания результата стадии — есть только техническая метрика «tokens/cost».
2. Нет краткого вердикта одной строкой там, где он есть в артефакте (Reviewer `APPROVE/REQUEST_CHANGES`, Tester `PASS/FAIL`, Deployer `SUCCESS/FAILED`).
3. Формат разнится по агентам (где-то «📂 Branch + 🔗 PR», где-то «📄 Test report») — нет единого визуального якоря.
4. **Не видно длительности стадии** — стейкхолдер не понимает, агент отработал за 30 секунд или за 12 минут; это важная метрика для оценки SLA, поведения долгих стадий (testing/deploy) и подозрений на «зависание».
## 3. Целевая аудитория
- **Стейкхолдер задачи (Слава, владелец продукта)** — главный потребитель ленты комментариев в Plane.
- **Reviewer / QA / DevOps по другим проектам (enduro-trails)** — те же ссылки помогут им навигироваться по задачам, не открывая БД оркестратора.
## 4. Scope (что входит)
1. Привести коммент-формат **architect, developer, reviewer, tester, deployer** к единому виду по эталону аналитика:
- заголовок-роль (emoji + имя роли),
- короткое человеческое описание результата стадии (1 предложение),
- кликабельная ссылка(и) на СВОЙ артефакт,
- **одна строка-вердикт** там, где это уместно (Reviewer / Tester / Deployer),
- **одна строка-длительность** работы агента — для всех ролей, включая аналитика.
2. Переиспользовать `settings.gitea_public_url` для кликабельных ссылок (готово в PR #14).
3. Сохранить существующее поведение аналитика (PR #13) — он уже соответствует целевому формату; в идеале — переиспользовать общий хелпер. К аналитику также добавляется строка длительности.
4. Один коммент на агента за прохождение стадии (без спама).
5. Источник длительности — уже существующая метрика `_duration_s` в `src/agents/launcher.py` (или `agent_runs.started_at` / `finished_at`). Новых таблиц/полей в БД не заводим.
## 5. Out of scope (что НЕ трогаем)
- Логика Quality Gates (`src/qg/checks.py`).
- Status-only verdict model (PR #12) — приёмка аналитика через смену статуса Plane на «Approved/Rejected».
- Дедупликация вебхуков (`src/webhooks/_dedup.py`).
- `set_issue_done`, `notify_done`, `notify_qg_failure` — внутренние нотификации остаются как есть.
- Per-agent bot-авторство (PR с `PLANE_BOT_TOKENS`) — сохраняется.
- Изменение схемы БД, конвейера стадий, реестра QG.
## 6. Бизнес-требования
**BR-1.** Каждый агент по завершении своей стадии (вне пути ошибки) пишет в Plane **ровно один** коммент в едином формате.
**BR-2.** Коммент содержит:
- заголовок с emoji-иконкой роли и человекочитаемым названием,
- 1–2 предложения с описанием результата стадии на русском языке,
- кликабельную ссылку (-и) на артефакт(ы) этого агента в Gitea,
- одну строку вердикта (Verdict / Status), если артефакт его содержит,
- **одну строку длительности работы агента** (`Длительность: `), всегда, если значение известно.
**BR-3.** Ссылки строятся через `gitea_public_url` (fallback на `gitea_url`).
**BR-4.** Формат должен быть устойчив: отсутствующий артефакт / отсутствующий вердикт / неизвестная длительность не ломают коммент — соответствующая строка просто опускается.
**BR-5.** Изменение **не нарушает**:
- status-only verdict model (аналитик по-прежнему ждёт смены статуса Plane),
- дедуп комментов и вебхуков,
- работу `set_issue_done` / `notify_done` на финале конвейера,
- per-agent bot-авторство.
**BR-6.** Длительность отображается в человекочитаемой форме (`12s`, `4m 12s`, `1h 03m`), а не в виде голых секунд. Источник — `agent_runs.started_at` / `finished_at` (или уже посчитанный `_duration_s` в `launcher.py`). Новых полей в БД не вводится.
## 7. Ограничения и риски
- **Self-hosting:** оркестратор правит сам себя; деплой только через staging-гейт (порт 8501) → прод-контейнер `orchestrator` не перезапускать в рамках задачи.
- Прод обслуживает другие проекты (enduro-trails) — нельзя сломать комменты в их задачах.
- Plane Bot-авторство (`_headers_for`) должно остаться — коммент пишется под бот-токеном своей роли.
- Reviewer/tester вердикты читаются из артефактов; нужно идемпотентно работать, если артефакт ещё не закоммичен / не доступен в worktree.
## 8. Связки
- PR #13 — `status-only analyst comment with doc links` (эталон формата аналитика).
- PR #14 — `external gitea_public_url for clickable doc links` (источник кликабельных ссылок).
- ADR не требуется: сквозной архитектурный сдвиг отсутствует, меняем только формирование текста коммента в существующем потоке.
## 9. Критерии успеха (high-level)
- Слава открывает любую задачу в Plane и в ленте видит однотипные карточки от каждого агента: «{role} — {описание} → ссылка [Verdict: …] [Длительность: …]».
- По любой ссылке открывается соответствующий документ в Gitea (HTTP 200, корректный путь).
- В каждом статус-комменте присутствует строка «Длительность: …» с человекочитаемым значением (`12s` / `4m 12s` / `1h 03m`).
- Никаких регрессий в существующих тестах `tests/`.