138 lines
12 KiB
Markdown
138 lines
12 KiB
Markdown
---
|
||
work_item: ORCH-091
|
||
stage: analysis
|
||
author_agent: analyst
|
||
status: ready-for-review
|
||
created_at: 2026-06-09
|
||
model_used: claude-opus-4-8
|
||
---
|
||
|
||
# 01 — BRD (бизнес-требования): ORCH-091 — Карточка трекера: фикс «To Analyse» на deploy-staging, отражение откатов, суммирование метрик по попыткам
|
||
|
||
Work Item: **ORCH-091** · Repo: **orchestrator** · Стадия: analysis
|
||
|
||
## 1. Бизнес-контекст и проблема
|
||
|
||
Live Telegram-карточка задачи (ORCH-067, единственная карточка на задачу, рендер
|
||
`src/notifications.py::render_task_tracker`) — основной канал, по которому Owner/Слава
|
||
наблюдают прогресс конвейера. Карточка обязана показывать **честную** текущую картину.
|
||
Объединены три верифицированных по коду и БД прода (09.06) дефекта одной карточки
|
||
(ORCH-072 закрыт как дубль; ORCH-091 расширена до полного объёма):
|
||
|
||
- **Дефект 1 (косметика, но вводит в заблуждение).** Заголовок-строка статуса карточки
|
||
(`📍 <status_label>`) застревает на «To Analyse», когда задача реально на стадии
|
||
`deploy-staging`. Корень верифицирован: словарь `_STAGE_STATUS_LABEL`
|
||
(`src/notifications.py` ~стр. 940) содержит 8 ключей (`created/analysis/architecture/
|
||
development/review/testing/deploy/done`), а реальные значения `tasks.stage` — это ключи
|
||
`STAGE_TRANSITIONS` (`src/stages.py`), среди которых есть `deploy-staging`. Ровно эта
|
||
стадия не покрыта → `.get(stage, _DEFAULT_STATUS_LABEL)` отдаёт дефолт «To Analyse»
|
||
(`_DEFAULT_STATUS_LABEL`, ~стр. 950). Программно проверено: из 9 реальных стадий не
|
||
покрыта **ровно одна** — `deploy-staging` (предпоследняя перед прод-деплоем, видна
|
||
чаще всего). Сам дефолт-«To Analyse» — мина на будущее: любая новая стадия даст ложный
|
||
«первый статус».
|
||
|
||
- **Дефект 2 (ложная картина при откате).** При rollback по конвейеру (напр. merge-gate
|
||
`deploy-staging → development`, ORCH-43; или REQUEST_CHANGES `review → development`)
|
||
верхние строки `✅ пройдено` (Код-ревью / Тестирование / Внедрение) НЕ снимаются, а внизу
|
||
снова `🔄 Разработка`. Абсурд: «Внедрение готово ✅, но идёт Разработка 🔄». Корень:
|
||
цикл рендера в `render_task_tracker` (~стр. 474–505) выводит `✅`-строку для каждой
|
||
стадии `_TRACKER_STAGES`, у чьего агента есть завершённый прогон (`last_done`), без
|
||
учёта позиции стадии относительно текущей.
|
||
|
||
- **Дефект 3 (реальное занижение тоталов, не косметика).** Строка стадии берёт ПОСЛЕДНИЙ
|
||
прогон агента (`run = last_done.get(agent)`, ~стр. 475; `_stage_line`), теряя предыдущие
|
||
попытки. На задаче с ретраями метрики стадии занижены. Верифицировано на ORCH-069
|
||
(`task_id=54`, прод 09.06): developer = 3 прогона Σ $3.98 (карточка показывала ~$0.00 за
|
||
«Разработка»), reviewer = 3 Σ $2.10, tester = 2 Σ $1.03, deployer = 2 Σ $1.59. Источник
|
||
истины — таблица `agent_runs` (`cost_usd`, `input_tokens`, `output_tokens`,
|
||
`cache_read_tokens`, `cache_creation_tokens`, `started_at`/`finished_at`).
|
||
|
||
> **Замечание (факт кода, не противоречие).** Блок тоталов задачи (`💰`/`🔢`/`⏱ Агенты`)
|
||
> в текущем worktree уже суммирует ВСЕ прогоны (`render_task_tracker` ~стр. 388–404).
|
||
> Заниженной остаётся **строка стадии** (`_stage_line` показывает только последний прогон).
|
||
> Требование G4/AC-5 формулируется на уровне строки стадии и инварианта сходимости тоталов
|
||
> с `SUM(agent_runs)` — реализация/архитектура подбора агрегата за архитектором.
|
||
|
||
## 2. Объём (scope)
|
||
|
||
### В объёме
|
||
- Покрытие `_STAGE_STATUS_LABEL` всеми ключами `STAGE_TRANSITIONS` из единого
|
||
программного источника истины (не «на глаз», не дублирующим списком).
|
||
- Осмысленный staging-лейбл для `deploy-staging`, согласованный с моделью статусов
|
||
ORCH-066/059.
|
||
- Нейтральный фолбэк для истинно неизвестной/битой стадии (вместо «To Analyse»).
|
||
- Отражение откатов: снятие `✅` со стадий ПОСЛЕ текущей позиции задачи.
|
||
- Метрика строки стадии = Σ всех `agent_runs` стадии (💰 стоимость / 🔢 токены / ⏱ время),
|
||
с сохранением сходимости тоталов задачи с `SUM(agent_runs)` по `task_id`.
|
||
- Тесты на полноту карты стадий, суммирование метрик, отражение отката; `CHANGELOG.md`.
|
||
|
||
### Вне объёма
|
||
- Изменение `STAGE_TRANSITIONS`, схемы БД, реестра `QG_CHECKS`/`check_*`, транспорта
|
||
нотификаций (`send/edit/delete_telegram`).
|
||
- Live-overlay ветки (Needs Input / Blocked / Rejected / Cancelled / Confirm Deploy /
|
||
Deploying / Monitoring) — работают, не трогаем.
|
||
- Архитектурное решение «как реализовать» (ordering-источник, форма агрегата) —
|
||
зона архитектора (`06-adr/`).
|
||
|
||
## 3. Заинтересованные стороны
|
||
- **Заказчик / приёмка:** Owner (homenet542), Слава (нашёл дефекты 08.06).
|
||
- **Затрагивается:** все наблюдатели карточек конвейера всех проектов (общий прод-инстанс,
|
||
self-hosting). Косметика карточки — для всех репо (orchestrator + enduro-trails).
|
||
|
||
## 4. Бизнес-требования (BR)
|
||
|
||
- **BR-1 (Деф.1, G1)** — `_STAGE_STATUS_LABEL` покрывает КАЖДЫЙ ключ `STAGE_TRANSITIONS`;
|
||
полнота гарантируется программно (итерация по единому источнику истины `src/stages.py`),
|
||
а не статичным списком. Для каждой реальной стадии `plane_status_label` возвращает
|
||
непустой осмысленный лейбл (не дефолт-«To Analyse», кроме реального `created`).
|
||
- **BR-2 (Деф.1, G1)** — `stage='deploy-staging'` → осмысленный staging-лейбл (напр.
|
||
«Deploying (staging)» / «⏳ Staging»), согласованный с моделью статусов ORCH-066/059.
|
||
- **BR-3 (Деф.1, G2)** — фолбэк для истинно неизвестной/битой стадии — нейтральный (напр.
|
||
«В работе» / stage capitalized), НЕ «To Analyse», чтобы будущая стадия не давала ложный
|
||
«первый статус». `plane_status_label` остаётся never-raise.
|
||
- **BR-4 (Деф.2, G3)** — при откате стадии карточка отражает ФАКТИЧЕСКУЮ текущую позицию:
|
||
с стадий ПОСЛЕ точки отката снимается `✅`; текущая стадия отрисовывается как активная
|
||
(`🔄`). Сценарий-эталон: после `deploy-staging → development` Разработка = `🔄`,
|
||
Тестирование/Внедрение — НЕ `✅`.
|
||
- **BR-5 (Деф.3, G4)** — метрика строки стадии = СУММА всех `agent_runs` этой стадии
|
||
(по `task_id` + агент стадии) по трём метрикам: 💰 `Σ cost_usd`, 🔢 `Σ (input + output +
|
||
cache_read + cache_creation)`, ⏱ `Σ (finished_at − started_at)`. Тоталы задачи = суммы по
|
||
всем стадиям и попыткам, сходятся с `SUM(agent_runs)` по `task_id`.
|
||
|
||
## 5. Нефункциональные требования (NFR)
|
||
|
||
- **NFR-1 (надёжность)** — `render_task_tracker` и `plane_status_label` остаются
|
||
**stateless / never-raise**: любая ошибка деградирует к безопасному выводу, конвейер
|
||
никогда не блокируется рендером карточки.
|
||
- **NFR-2 (совместимость / регресс)** — существующие метки и строки НЕ меняются: In Review
|
||
(brd-clock), Awaiting Deploy (`deploy`), Done, live-overlay ветки, строка `Подтверждение
|
||
BRD`, формат строк стадий/тоталов, эффорт-суффикс (ORCH-087). Изменение аддитивно.
|
||
- **NFR-3 (источник истины)** — полнота карты стадий выводится из `STAGE_TRANSITIONS`
|
||
программно; запрещено дублировать перечень стадий руками (анти-рассинхрон на будущее).
|
||
- **NFR-4 (self-hosting)** — изменения только в `src/notifications.py` + тесты + доки; без
|
||
правки `STAGE_TRANSITIONS`/схемы БД/QG; без рестарта прод-контейнера в рамках задачи.
|
||
|
||
## 6. Допущения и ограничения
|
||
- `tasks.stage` принимает строго значения-ключи `STAGE_TRANSITIONS` (включая
|
||
`deploy-staging`, `cancelled`). Это инвариант движка стадий.
|
||
- `cancelled` (ORCH-090) — системный терминал; его статус-лейбл уже рисуется live-overlay
|
||
(`_LIVE_BRANCH_LABELS['cancelled']`). Для offline-фолбэка `plane_status_label` он не
|
||
должен давать «To Analyse» (покрывается BR-3 нейтральным фолбэком; явный лейбл для
|
||
`cancelled` — на усмотрение архитектора, без конфликта с overlay).
|
||
- Источник метрик — `agent_runs`; стадия `deploy-staging` и `deploy` обслуживаются одним
|
||
агентом `deployer` — агрегат по агенту корректно покрывает обе (вопрос разнесения
|
||
staging/prod-прогонов по строкам — зона архитектора, не требование BRD).
|
||
- Telegram-ограничение 48ч на удаление сирот (ORCH-087) — вне объёма.
|
||
|
||
## 7. Критерии успеха
|
||
Карточка показывает корректный статус-заголовок на всех стадиях (включая `deploy-staging`),
|
||
не «лжёт» о пройденных стадиях после отката, и метрики строки стадии + тоталы сходятся с
|
||
`SUM(agent_runs)` по `task_id`. Полный регресс `pytest tests/ -q` зелёный. Детальные
|
||
PASS/FAIL — `03-acceptance-criteria.md`.
|
||
|
||
## 8. Риски
|
||
- Рассинхрон карты стадий с `STAGE_TRANSITIONS` в будущем (митигируется NFR-3 + тест полноты).
|
||
- Регресс существующих меток/строк при правке цикла рендера (митигируется NFR-2 + тесты).
|
||
- Неверная точка отсчёта «позиции» стадии для отката (ordering) → неверное снятие `✅`.
|
||
Детали — `10-tech-risks.md` (заполняет архитектор).
|