analyst(ET): auto-commit from analyst run_id=504

This commit is contained in:
2026-06-09 21:40:07 +03:00
committed by orchestrator-deployer
parent 67f7a3abfa
commit 852da919b9
4 changed files with 436 additions and 0 deletions

View File

@@ -0,0 +1,137 @@
---
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` (~стр. 474505) выводит `✅`-строку для каждой
стадии `_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` ~стр. 388404).
> Заниженной остаётся **строка стадии** (`_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` (заполняет архитектор).

View File

@@ -0,0 +1,112 @@
---
work_item: ORCH-091
stage: analysis
author_agent: analyst
status: ready-for-review
created_at: 2026-06-09
model_used: claude-opus-4-8
---
# 02 — ТЗ (TRZ): ORCH-091 — Карточка трекера: полнота карты статусов, отражение откатов, суммирование метрик по попыткам
Work Item: **ORCH-091** · Repo: **orchestrator** · Стадия: analysis
> ТЗ описывает **конкретные изменения к реализации**, выведенные из BRD и фактического кода.
> Архитектурное обоснование/решения (выбор ordering-источника для отката, форма агрегата
> метрик, явный лейбл для `cancelled`) — задача архитектора (`06-adr/`).
## 1. Сводка изменения
Три точечные правки в `src/notifications.py` (рендер live-карточки ORCH-067), все аддитивные,
без изменения транспорта, схемы БД, `STAGE_TRANSITIONS` и `QG_CHECKS`:
1. **Полнота карты статусов (Деф.1).** `_STAGE_STATUS_LABEL` должен покрывать все ключи
`STAGE_TRANSITIONS` (источник истины — `src/stages.py`), добавить `deploy-staging`
осмысленный staging-лейбл; нейтральный фолбэк вместо «To Analyse» для неизвестной стадии.
2. **Отражение откатов (Деф.2).** Цикл рендера строк стадий перестаёт показывать `✅` для
стадий, расположенных ПОСЛЕ текущей позиции задачи в конвейере.
3. **Суммирование метрик стадии (Деф.3).** Строка стадии агрегирует ВСЕ `agent_runs` агента
стадии (Σ стоимость/токены/время) вместо последнего прогона; тоталы сходятся с `SUM`.
## 2. Задействованные модули / пути
| Путь | Действие |
|------|----------|
| `src/notifications.py` | изменить: `_STAGE_STATUS_LABEL` (~940), `_DEFAULT_STATUS_LABEL` (~950), `plane_status_label` (~990), `render_task_tracker` (рендер строк стадий ~474505, агрегат метрик ~388404 / `_stage_line` ~445466) |
| `src/stages.py` | **только чтение** — импорт ключей `STAGE_TRANSITIONS` как источника истины для полноты карты (НЕ изменять) |
| `tests/test_tracker_status_line.py` | изменить/дополнить: полнота карты, staging-лейбл, нейтральный фолбэк |
| `tests/test_telegram_tracker.py` (или новый `tests/test_tracker_rollback_metrics.py`) | дополнить/создать: откат + суммирование метрик |
| `CHANGELOG.md` | изменить: запись ORCH-091 |
## 3. Функциональные требования
### FR-1 — Полнота `_STAGE_STATUS_LABEL` по `STAGE_TRANSITIONS` (BR-1)
- Для каждого ключа `STAGE_TRANSITIONS` (`created, analysis, architecture, development,
review, testing, deploy-staging, deploy, done, cancelled`) `plane_status_label` возвращает
непустой осмысленный лейбл.
- Полнота гарантируется **программно** от единого источника `src/stages.py::STAGE_TRANSITIONS`
(итерация/проверка пересечения ключей), а не статичным дублирующим списком (NFR-3).
- Сохранить спецветки `plane_status_label`: `analysis` + открытый brd-clock → `_IN_REVIEW_LABEL`
(без изменений).
### FR-2 — Staging-лейбл для `deploy-staging` (BR-2)
- `stage='deploy-staging'` → осмысленный лейбл (предлагается «Deploying (staging)» или
«⏳ Staging»; финальный текст согласует архитектор с моделью статусов ORCH-066/059).
- НЕ равен «To Analyse» и НЕ равен лейблу `deploy` (`⏸️ Awaiting Deploy …`).
### FR-3 — Нейтральный фолбэк (BR-3)
- Для строки `tasks.stage`, отсутствующей в карте (истинно неизвестная/битая/будущая
стадия), `plane_status_label` возвращает нейтральный лейбл (напр. «В работе» или
капитализированный stage), НЕ «To Analyse».
- `created` сохраняет осмысленный «To Analyse» как реальный первый статус.
- `plane_status_label` остаётся never-raise (любой сбой → безопасный лейбл).
### FR-4 — Отражение откатов в строках стадий (BR-4)
- В `render_task_tracker` строка `✅ <стадия>` НЕ отрисовывается для стадии, позиция которой
в конвейере ПОЗЖЕ текущего `tasks.stage`, даже если у её агента есть завершённый `agent_run`.
- Текущая стадия рисуется активной (`🔄`) по существующей логике `is_active_stage`.
- Стадии ДО текущей позиции (фактически пройденные) сохраняют `` со своими метриками.
- Источник порядка стадий — конвейер `STAGE_TRANSITIONS` (а не индекс в `_TRACKER_STAGES`);
конкретный механизм определения позиции — за архитектором. Учесть, что `deploy-staging`
отсутствует в `_TRACKER_STAGES` и `_STAGE_ACTIVE_AGENT` (обе стадии staging/deploy → агент
`deployer`): решение не должно ломать существующий рендер строки «Внедрение».
### FR-5 — Суммирование метрик стадии по попыткам (BR-5)
- Строка стадии показывает СУММУ по всем `agent_runs` агента стадии (по `task_id`):
- 💰 стоимость = `Σ cost_usd`;
- 🔢 токены = `Σ (input_tokens + output_tokens + cache_read_tokens + cache_creation_tokens)`
(вход — через существующий `_input_total`; формат строки `<in>↓/<out>↑` сохранить);
- ⏱ время = `Σ _duration_seconds(started_at, finished_at)` по всем прогонам стадии.
- Тоталы задачи (💰/🔢/⏱ Агенты) остаются суммой по всем стадиям/попыткам и сходятся с
`SUM(agent_runs)` по `task_id` (инвариант сходимости).
- Модель/эффорт/счётчик «попытка N» в строке стадии сохранить (ORCH-087): при N≥2 показывать
актуально (модель — допускается из последнего прогона; согласовать с архитектором).
## 4. Изменения API
Нет. Эндпоинты не затрагиваются (рендер карточки вызывается из конвейера). Диагностический
блок `GET /queue` не меняется.
## 5. Изменения схемы БД
Нет. Используются существующие колонки `agent_runs` (`cost_usd`, `input_tokens`,
`output_tokens`, `cache_read_tokens`, `cache_creation_tokens`, `started_at`, `finished_at`,
`agent`, `task_id`, `exit_code`) и `tasks` (`stage`, `brd_review_started_at/ended_at`).
## 6. Требования к новым/изменённым QG checks
Нет. `QG_CHECKS` / `check_*` / `_parse_*` / `STAGE_TRANSITIONS` не затрагиваются. Изменение
касается только слоя индикации (карточка), не управляющего слоя конвейера.
## 7. Совместимость / регресс
- **Обратная совместимость:** все существующие метки и строки карточки неизменны (NFR-2):
In Review (brd-clock), Awaiting Deploy (`deploy`), Done, live-overlay ветки (Needs Input /
Blocked / Rejected / Cancelled / Confirm Deploy / Deploying / Monitoring), строка
`Подтверждение BRD`, формат строк стадий и тоталов, эффорт-суффикс.
- **Область раската:** косметика карточки для всех проектов общего инстанса (self-hosting +
enduro-trails). Чисто индикативный слой — управляющий конвейер не затронут.
- **Обратимость:** изменение docs/code-only в одном модуле; откат = revert PR. Kill-switch не
требуется (нет нового поведения конвейера; рендер never-raise деградирует безопасно).
- **Артефакты pipeline:** создаются/обновляются стандартные analysis-доки
(`01..04`); на стадии review — `12-review.md`; на testing — `13-test-report.md`. Новых
типов артефактов не вводится.
- **Анти-стейл/трассировка:** правится код, помеченный ORCH-067/ORCH-087 — перед правкой
читать их ADR (`docs/work-items/ORCH-067|ORCH-087/06-adr/`) и не ломать инварианты
(single-card, never-raise, разделение offline-ядра и live-overlay).

View File

@@ -0,0 +1,111 @@
---
work_item: ORCH-091
stage: analysis
author_agent: analyst
status: ready-for-review
created_at: 2026-06-09
model_used: claude-opus-4-8
---
# 03 — Критерии приёмки (Acceptance Criteria): ORCH-091 — Карточка трекера: статусы, откаты, метрики
Work Item: **ORCH-091** · Repo: **orchestrator** · Стадия: analysis
Формат: каждый критерий имеет **PASS** (что должно быть истинно для приёмки) и **FAIL**
(что считается провалом). Reviewer/тестер проверяет их буквально по файлам репозитория и
по выводу тестов.
---
## AC-1 — Полнота карты статусов по `STAGE_TRANSITIONS` (Деф.1 / BR-1)
**Условие:** для КАЖДОГО ключа `src/stages.py::STAGE_TRANSITIONS` `plane_status_label`
возвращает непустой осмысленный лейбл.
- **PASS:** параметризованный тест итерирует по всем ключам `STAGE_TRANSITIONS` и для каждого
(кроме реального `created`) получает непустой лейбл ≠ `_DEFAULT_STATUS_LABEL`-«To Analyse».
Полнота карты выведена программно из `STAGE_TRANSITIONS`, а не статичным списком в тесте.
- **FAIL:** хотя бы одна стадия из `STAGE_TRANSITIONS` отдаёт «To Analyse» (кроме `created`);
либо полнота проверяется захардкоженным списком, не связанным с `STAGE_TRANSITIONS`.
---
## AC-2 — Staging-лейбл для `deploy-staging` (Деф.1 / BR-2)
**Условие:** `stage='deploy-staging'` даёт осмысленный staging-лейбл.
- **PASS:** `plane_status_label` для строки со `stage='deploy-staging'` возвращает осмысленный
staging-лейбл (напр. «Deploying (staging)» / «⏳ Staging»), отличный от «To Analyse» и от
лейбла стадии `deploy` (`⏸️ Awaiting Deploy …`).
- **FAIL:** возвращает «To Analyse», пустую строку, либо лейбл, неотличимый от `deploy`.
---
## AC-3 — Нейтральный фолбэк для неизвестной стадии (Деф.1 / BR-3)
**Условие:** истинно неизвестная/битая стадия → нейтральный фолбэк, never-raise.
- **PASS:** для строки с заведомо несуществующим `stage` (напр. `"__bogus__"`)
`plane_status_label` возвращает нейтральный лейбл (НЕ «To Analyse») и не бросает исключение;
для битого входа (None/нет ключа `stage`) тоже не падает.
- **FAIL:** неизвестная стадия даёт «To Analyse»; либо функция бросает исключение на
битом/неизвестном входе.
---
## AC-4 — Отражение отката в строках стадий (Деф.2 / BR-4)
**Условие:** после rollback `deploy-staging → development` карточка показывает фактическую
позицию.
- **PASS:** для задачи с завершёнными прогонами reviewer/tester/deployer, но текущим
`stage='development'`, `render_task_tracker` рисует Разработку как активную (`🔄`), а
Тестирование и Внедрение — НЕ как `✅ пройдено`. Стадии до development (Анализ, Архитектура)
остаются `✅`.
- **FAIL:** карточка одновременно показывает `✅ Внедрение/Тестирование/Код-ревью` и
`🔄 Разработка` (картина «Внедрение готово ✅, но идёт Разработка»).
---
## AC-5 — Суммирование метрик стадии по попыткам (Деф.3 / BR-5)
**Условие:** стадия с N попытками показывает СУММУ метрик по всем N `agent_runs`.
- **PASS:** для стадии с N>1 `agent_runs` строка стадии показывает Σ времени, Σ токенов
(`input+output+cache_read+cache_creation`) и Σ стоимости по всем N прогонам. На фикстуре
по образцу ORCH-069 (developer: 3 прогона, суммарно ≈ $3.98) строка «Разработка» отражает
≈ $3.98, а не стоимость последнего прогона. Тоталы задачи (💰/🔢/⏱ Агенты) сходятся с
`SUM(agent_runs)` по `task_id` (по стоимости, токенам, длительностям).
- **FAIL:** строка стадии показывает метрики только последнего прогона (занижение); либо
тоталы задачи не сходятся с `SUM(agent_runs)`.
---
## AC-6 — Регресс существующих меток (NFR-2)
**Условие:** существующие индикаторы карточки не изменены.
- **PASS:** In Review (brd-clock, `_IN_REVIEW_LABEL`), Awaiting Deploy (`deploy`), Done,
live-overlay ветки (Needs Input / Blocked / Rejected / Cancelled / Confirm Deploy /
Deploying / Monitoring), строка `Подтверждение BRD`, формат строк стадий/тоталов и
эффорт-суффикс — рендерятся как прежде; существующие тесты карточки зелёные.
- **FAIL:** изменён текст/формат любой из перечисленных меток; падает существующий тест
карточки.
---
## AC-7 — Тесты и документация (G/AC-7)
**Условие:** добавлены тесты и обновлена документация.
- **PASS:** `pytest tests/ -q` зелёный; добавлены тесты на полноту карты стадий (AC-1/2/3),
суммирование метрик (AC-5), отражение отката (AC-4); `CHANGELOG.md` содержит запись
ORCH-091; `render_task_tracker`/`plane_status_label` остаются never-raise.
- **FAIL:** регресс `pytest tests/ -q`; отсутствует любой из обязательных новых тестов; не
обновлён `CHANGELOG.md`.
---
## Сводная матрица AC ↔ FR/BR
| AC | Покрывает |
|----|-----------|
| AC-1 | BR-1 / FR-1 |
| AC-2 | BR-2 / FR-2 |
| AC-3 | BR-3 / FR-3 |
| AC-4 | BR-4 / FR-4 |
| AC-5 | BR-5 / FR-5 |
| AC-6 | NFR-2 (регресс) |
| AC-7 | NFR-1 + цель G/AC-7 (тесты, доки, never-raise) |

View File

@@ -0,0 +1,76 @@
work_item: ORCH-091
stage: analysis
author_agent: analyst
status: ready-for-review
created_at: 2026-06-09
model_used: claude-opus-4-8
title: "Карточка трекера: полнота статусов, отражение откатов, суммирование метрик по попыткам"
framework: pytest
scope: >
Юнит-покрытие чистых функций src/notifications.py (plane_status_label,
render_task_tracker) и интеграция рендера от состояния БД (tasks + agent_runs).
Вне покрытия: транспорт Telegram (send/edit/delete), live-overlay ветки (сеть),
STAGE_TRANSITIONS/QG/схема БД (не трогаются).
notes: >
Полнота карты статусов должна выводиться программно из src/stages.py::STAGE_TRANSITIONS
(а не из захардкоженного списка стадий). Метрики читаются из таблицы agent_runs:
cost_usd, input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens,
started_at/finished_at. Фикстура-эталон сумм — ORCH-069 (developer: 3 прогона ≈ $3.98).
Полный регресс pytest tests/ -q должен оставаться зелёным; существующие тесты карточки
(test_tracker_status_line, test_telegram_tracker, test_tracker_effort_time) не должны
ломаться.
tests:
- id: TC-01
type: unit
description: "Полнота: для каждого ключа STAGE_TRANSITIONS (программная итерация) plane_status_label возвращает непустой лейбл, не 'To Analyse' (кроме created). AC-1"
module: tests/test_tracker_status_line.py
expected: PASS
- id: TC-02
type: unit
description: "stage='deploy-staging' -> осмысленный staging-лейбл, отличный от 'To Analyse' и от лейбла стадии 'deploy'. AC-2"
module: tests/test_tracker_status_line.py
expected: PASS
- id: TC-03
type: unit
description: "Истинно неизвестная стадия ('__bogus__') -> нейтральный фолбэк (не 'To Analyse'); never-raise на битом/None входе. AC-3"
module: tests/test_tracker_status_line.py
expected: PASS
- id: TC-04
type: unit
description: "Регресс ветки plane_status_label: analysis + открытый brd-clock -> In Review; deploy -> Awaiting Deploy; done -> Done; created -> To Analyse. AC-6"
module: tests/test_tracker_status_line.py
expected: PASS
- id: TC-05
type: integration
description: "Откат deploy-staging->development: задача stage='development' с завершёнными прогонами reviewer/tester/deployer -> Разработка активна (🔄), Тестирование/Внедрение НЕ как ✅; Анализ/Архитектура остаются ✅. AC-4"
module: tests/test_tracker_rollback_metrics.py
expected: PASS
- id: TC-06
type: integration
description: "Суммирование метрик стадии: developer с 3 agent_runs (фикстура ORCH-069) -> строка 'Разработка' показывает Σ стоимости ≈ $3.98, Σ токенов, Σ времени, а не последний прогон. AC-5"
module: tests/test_tracker_rollback_metrics.py
expected: PASS
- id: TC-07
type: integration
description: "Сходимость тоталов: тоталы карточки (💰/🔢/⏱ Агенты) равны SUM(agent_runs) по task_id (cost_usd, токены, длительности) при наличии ретраев. AC-5"
module: tests/test_tracker_rollback_metrics.py
expected: PASS
- id: TC-08
type: integration
description: "render_task_tracker never-raise: битые/частичные строки tasks/agent_runs (NULL timestamps, отсутствующий stage) -> возвращает строку-фолбэк без исключения. NFR-1 / AC-7"
module: tests/test_tracker_rollback_metrics.py
expected: PASS
- id: TC-09
type: unit
description: "Регресс существующих строк карточки: формат строк стадий, эффорт-суффикс (ORCH-087), строка 'Подтверждение BRD', блок тоталов — без изменений. AC-6"
module: tests/test_telegram_tracker.py
expected: PASS