Merge pull request 'feat(notifications): ORCH-042 Telegram tracker bump mode + russification' (#52) from feature/ORCH-042-telegram-live-tracker-bump into main
Some checks failed
CI / test (push) Has been cancelled
Some checks failed
CI / test (push) Has been cancelled
This commit was merged in pull request #52.
This commit is contained in:
7
docs/work-items/ORCH-042/00-business-request.md
Normal file
7
docs/work-items/ORCH-042/00-business-request.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Business Request: Telegram live-tracker: режим bump (карточка падает вниз при обновлении)
|
||||
|
||||
Work Item ID: ORCH-042
|
||||
|
||||
## Description
|
||||
|
||||
TBD
|
||||
65
docs/work-items/ORCH-042/01-brd.md
Normal file
65
docs/work-items/ORCH-042/01-brd.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# 01 — BRD: Telegram live-tracker, режим bump + русификация карточки
|
||||
|
||||
**Work Item:** ORCH-042
|
||||
**Тип:** UX-улучшение (notifications)
|
||||
**Приоритет:** средний
|
||||
**Запрос:** Слава, 05.06. Связь: `feat/telegram-live-tracker` (Variant B+).
|
||||
**Self-hosting:** да — правка самого оркестратора, проходит через его же конвейер (общая БД/очередь с enduro-trails). См. `docs/operations/INFRA.md`.
|
||||
|
||||
## 1. Контекст и проблема
|
||||
|
||||
Live-tracker задачи (`src/notifications.py`) — это ОДНА карточка на задачу в Telegram, которая обновляется на каждом переходе стадии через `editMessageText` (Variant B+). Так сделано СПЕЦИАЛЬНО, чтобы убить старую проблему «~15 отдельных карточек/дублей на задачу».
|
||||
|
||||
Побочный эффект текущего решения: карточка редактируется **на месте в истории чата**. При активной переписке в чате карточка «тонет» вверху и её неудобно искать — приходится скроллить вверх к старому сообщению, чтобы увидеть актуальный статус задачи.
|
||||
|
||||
Дополнительно накопились косметические претензии к тексту карточки: смесь англоязычных меток стадий с русским текстом, неудачная формулировка «Ревью БРД», и финальный технический хвост `deployed` вместо человекочитаемого «Внедрено».
|
||||
|
||||
## 2. Цель
|
||||
|
||||
1. Дать Славе альтернативный режим отображения трекера — **bump**: при каждом обновлении карточка «падает вниз» свежим сообщением (всегда последняя в чате), но БЕЗ возврата к проблеме дублей (по-прежнему ОДНА карточка на задачу) и БЕЗ спама звуками/пингами.
|
||||
2. Привести текст карточки к единому русскому виду и поправить формулировки.
|
||||
|
||||
## 3. Заинтересованные лица
|
||||
|
||||
- **Слава (Owner)** — единственный получатель Telegram-уведомлений; принимает UX.
|
||||
- **Агенты конвейера** — косвенно: трекер обновляется из `notify_*`-хелперов на каждой стадии.
|
||||
|
||||
## 4. Требования (бизнес-уровень)
|
||||
|
||||
### 4.1. Режим работы трекера (флаг)
|
||||
- **BR-1.** Новый конфиг-флаг `ORCH_TRACKER_MODE` с двумя значениями:
|
||||
- `edit` — текущее поведение (редактирование на месте). **Это ДЕФОЛТ** (обратная совместимость, никакой регрессии без явного включения).
|
||||
- `bump` — новый режим «карточка падает вниз».
|
||||
- **BR-2.** Неизвестное/пустое значение флага трактуется как `edit` (безопасный фолбэк, оркестратор не падает).
|
||||
|
||||
### 4.2. Поведение режима bump
|
||||
- **BR-3.** При обновлении карточки в режиме `bump`: старое сообщение удаляется (`deleteMessage`), отправляется новое (`sendMessage`), указатель `tracker_message_id` перенаправляется на новое сообщение. Итог: в чате всегда ровно ОДНА карточка задачи, и она всегда внизу.
|
||||
- **BR-4.** Bump тихий: новое сообщение отправляется с `disable_notification=true` — карточка всплывает внизу, но БЕЗ звука/пинга на каждой стадии (как и сейчас в edit-режиме).
|
||||
- **BR-5.** Первое обновление (карточки ещё нет) в режиме `bump` — просто тихо отправить новое и запомнить id (удалять нечего).
|
||||
|
||||
### 4.3. Устойчивость (критично — не сломать защиту от дублей)
|
||||
- **BR-6.** Fallback: если `deleteMessage` не удался (сообщение старше 48 ч / уже удалено / недоступно) — карточка всё равно отправляется заново, оркестратор НЕ падает.
|
||||
- **BR-7.** Любой сбой нотификации (сеть/таймаут/5xx/Telegram-ошибка) НЕ роняет оркестратор (контракт «never raises» сохраняется) и НЕ плодит дубли карточек в пределах одного обновления.
|
||||
- **BR-8.** Режим `edit` после изменений работает строго как раньше — без регрессий (защита от ~15 дублей сохранена).
|
||||
|
||||
### 4.4. Текстовые правки карточки (применяются в ОБОИХ режимах)
|
||||
- **BR-9.** Метку «Ревью БРД» заменить на «Подтверждение BRD».
|
||||
- **BR-10.** После того как задача переведена в Approved (человеческий gate пройден, время ревью зафиксировано), эмодзи в строке подтверждения BRD заменить на галочку (✅) вместо текущей паузы (⏸️). Пока ждём человека — оставить прежний индикатор ожидания.
|
||||
- **BR-11.** Русифицировать метки стадий карточки: `Analysis → Анализ`, `Architecture → Архитектура`, `Development → Разработка`, `Review → Код ревью`, `Testing → Тестирование`, `Deploy → Внедрение`.
|
||||
- **BR-12.** В итоговой (последней) строке готовой задачи заменить технический `deployed` на «Внедрено».
|
||||
|
||||
## 5. Вне scope
|
||||
- Изменение состава событий, которые шлются ОТДЕЛЬНЫМИ пингами (approve-gate / deploy-fail / agent-fail / error) — остаётся как есть.
|
||||
- Изменение формата метрик (токены/стоимость/длительность), макета строк, логики «попытка N».
|
||||
- Любые изменения в Plane-комментариях агентов (`usage.build_status_comment`).
|
||||
- Хранение истории карточек / несколько карточек на задачу.
|
||||
|
||||
## 6. Влияние на документацию (golden source)
|
||||
- `CHANGELOG.md` — запись в `[Unreleased]`.
|
||||
- `docs/architecture/internals.md` (или соответствующая секция про live-tracker) — описать режимы `edit`/`bump` и `ORCH_TRACKER_MODE`.
|
||||
- `.env.example` — добавить `ORCH_TRACKER_MODE` с пояснением.
|
||||
|
||||
## 7. Критерии успеха (резюме)
|
||||
Слава может выставить `ORCH_TRACKER_MODE=bump` и видеть актуальную карточку всегда внизу чата, одну на задачу, без звона; при откате на `edit` (дефолт) поведение неотличимо от текущего; текст карточки полностью русифицирован по BR-9..BR-12. Полные условия PASS/FAIL — `03-acceptance-criteria.md`.
|
||||
</content>
|
||||
</invoke>
|
||||
118
docs/work-items/ORCH-042/02-trz.md
Normal file
118
docs/work-items/ORCH-042/02-trz.md
Normal file
@@ -0,0 +1,118 @@
|
||||
# 02 — ТЗ: Telegram live-tracker, режим bump + русификация
|
||||
|
||||
**Work Item:** ORCH-042 · См. `01-brd.md`, `03-acceptance-criteria.md`.
|
||||
|
||||
## 1. Задействованные модули `src/`
|
||||
| Файл | Что меняется |
|
||||
|------|--------------|
|
||||
| `src/config.py` | Новое поле `Settings.tracker_mode` (env `ORCH_TRACKER_MODE`). |
|
||||
| `src/notifications.py` | Новый helper `delete_telegram(message_id)`; ветвление `update_task_tracker` по режиму; текстовые правки в `_BRD_LABEL`, `_TRACKER_STAGES`, BRD-строке `render_task_tracker`, `_done_link`. |
|
||||
|
||||
БД — **без изменений** (используется существующая колонка `tasks.tracker_message_id` и хелперы `get_tracker_message_id` / `set_tracker_message_id` в `src/db.py`). API HTTP-эндпоинты оркестратора — **без изменений**. Новые QG checks — **не требуются**.
|
||||
|
||||
## 2. Изменения конфигурации (`src/config.py`)
|
||||
|
||||
Добавить в класс `Settings` (рядом с блоком «Telegram notifications»):
|
||||
|
||||
```python
|
||||
# ORCH-042: режим live-трекера задачи.
|
||||
# edit -> карточка редактируется на месте (editMessageText), ДЕФОЛТ (как было).
|
||||
# bump -> при обновлении старое сообщение удаляется и карточка отправляется
|
||||
# заново вниз чата (deleteMessage + sendMessage + repoint message_id),
|
||||
# тихо (disable_notification). Одна карточка на задачу в обоих режимах.
|
||||
# Неизвестное/пустое значение трактуется как edit (см. notifications).
|
||||
tracker_mode: str = "edit"
|
||||
```
|
||||
|
||||
- `env_prefix = "ORCH_"` уже задан → переменная окружения `ORCH_TRACKER_MODE`.
|
||||
- Резолюция режима — в `notifications`: всё, что не равно (case-insensitive, trimmed) `"bump"`, считается `edit`. Не падать на любом значении.
|
||||
|
||||
## 3. Изменения нотификаций (`src/notifications.py`)
|
||||
|
||||
### 3.1. Новый low-level helper `delete_telegram`
|
||||
Рядом с `send_telegram` / `edit_telegram`. Контракт «never raises».
|
||||
|
||||
```python
|
||||
def delete_telegram(message_id: int) -> bool:
|
||||
"""Delete a Telegram message. Never raises.
|
||||
|
||||
Returns True if the message is gone after the call (deleted now, OR Telegram
|
||||
says it's already not there / can't be deleted -> treat as "no longer our
|
||||
problem", caller proceeds to send a fresh card). Returns False only on a
|
||||
transient failure (network / timeout / 5xx / unknown error) where the old
|
||||
message may still be alive.
|
||||
"""
|
||||
```
|
||||
|
||||
Требования к реализации:
|
||||
- Эндпоинт `https://api.telegram.org/bot{token}/deleteMessage`, тело `{chat_id, message_id}`, `timeout=5`.
|
||||
- Нет токена/chat_id → вернуть `False` (как и прочие helpers при отсутствии кредов — ничего не отправлено, ничего не удалено).
|
||||
- `ok:true` → `True`.
|
||||
- `ok:false` с описанием «уже нет / нельзя удалить» (маркеры: `"message to delete not found"`, `"message can't be deleted"`, `"message_id_invalid"`) → `True` (сообщение и так недоступно; не транзиент).
|
||||
- Прочие `ok:false` (неизвестный 400 / 5xx) и исключения (сеть/таймаут) → `False` + `logger.warning`.
|
||||
- Вынести маркеры в модульную константу (по аналогии с `_GONE_MARKERS`), например `_DELETE_GONE_MARKERS`.
|
||||
|
||||
### 3.2. Ветвление `update_task_tracker` по режиму
|
||||
Сохранить существующий путь `edit` без изменений поведения. Добавить путь `bump`.
|
||||
|
||||
Псевдокод целевой логики:
|
||||
```python
|
||||
def update_task_tracker(task_id: int):
|
||||
try:
|
||||
from .db import get_tracker_message_id, set_tracker_message_id
|
||||
text = render_task_tracker(task_id)
|
||||
mode = (_get_settings().tracker_mode or "edit").strip().lower()
|
||||
mid = get_tracker_message_id(task_id)
|
||||
|
||||
if mode == "bump":
|
||||
# bump: одна карточка, но всегда внизу.
|
||||
if mid is not None:
|
||||
delete_telegram(mid) # best-effort; fallback -> всё равно шлём новое
|
||||
new_mid = send_telegram(text, disable_notification=True)
|
||||
if new_mid is not None:
|
||||
set_tracker_message_id(task_id, new_mid)
|
||||
# send вернул None (нет кредов / транзиент) -> mid не трогаем,
|
||||
# дубля в пределах вызова нет; перерисуется на следующем переходе.
|
||||
return
|
||||
|
||||
# mode == "edit" (ДЕФОЛТ): существующая логика без изменений.
|
||||
... # текущий код edit/EDIT_GONE-fallback as is
|
||||
except Exception as e:
|
||||
logger.warning(f"update_task_tracker({task_id}) failed: {e}")
|
||||
```
|
||||
|
||||
Инварианты bump-ветки:
|
||||
- В пределах ОДНОГО вызова отправляется максимум одно новое сообщение → дублей нет (BR-7).
|
||||
- `set_tracker_message_id` вызывается ТОЛЬКО при успешном `send` (`new_mid is not None`). При сбое send id остаётся прежним; на следующем переходе старый будет удалён (или уже мёртв) и отправлен новый — без накопления карточек.
|
||||
- `delete_telegram` — best-effort: его результат НЕ блокирует отправку новой карточки (BR-6: delete-fail → всё равно шлём новое).
|
||||
- Bump всегда тихий: `disable_notification=True` (BR-4).
|
||||
|
||||
### 3.3. Текстовые правки (общие для обоих режимов)
|
||||
|
||||
| BR | Где | Было | Стало |
|
||||
|----|-----|------|-------|
|
||||
| BR-9 | `_BRD_LABEL` (модульная константа) | `"Ревью БРД"` | `"Подтверждение BRD"` |
|
||||
| BR-10 | `render_task_tracker`, ветка BRD-строки при `review_seconds is not None` | префикс `⏸️` (`⏸️`) | `✅` (`✅`). Ветка ожидания (`review_seconds is None`, с ⏳) — НЕ менять. |
|
||||
| BR-11 | `_TRACKER_STAGES` (метки) | `Analysis / Architecture / Development / Review / Testing / Deploy` | `Анализ / Архитектура / Разработка / Код ревью / Тестирование / Внедрение` |
|
||||
| BR-12 | `_done_link` | `"\U0001f4e6 deployed"` | `"\U0001f4e6 Внедрено"` |
|
||||
|
||||
Примечания:
|
||||
- В `_TRACKER_STAGES` меняется ТОЛЬКО display-label (2-й элемент кортежа). Ключи стадий (`analysis`,…) и имена агентов (`analyst`,…) НЕ трогать — они завязаны на `_STAGE_ACTIVE_AGENT`, `last_done`, БД.
|
||||
- Выравнивание `{label:<13}` и `{_BRD_LABEL:<13}` оставить как есть (все новые русские метки ≤13 символов; «Подтверждение BRD» длиннее — формат просто не паддит, косметика, поведение не ломает).
|
||||
- Метки используются и в «✅ …»-строках завершённых стадий, и в «🔄 … идёт»-строке активной стадии — обе автоматически станут русскими (правка в одном месте).
|
||||
|
||||
## 4. Совместимость и риски
|
||||
- Дефолт `edit` гарантирует нулевую регрессию без явного включения bump (BR-8). Подробно — `10-tech-risks.md` (заводит архитектор/девелопер при необходимости).
|
||||
- Самохостинг: изменения только в коде нотификаций, миграций БД нет, перезапуск self — по стандартной страховке `deploy-staging` (8501) перед prod (см. `CLAUDE.md`).
|
||||
|
||||
## 5. Артефакты pipeline, которые ДОЛЖНЫ быть обновлены в этом же PR
|
||||
- `CHANGELOG.md` → запись в `[Unreleased] / Added` (режим bump) + `Changed` (русификация текста).
|
||||
- `docs/architecture/internals.md` — секция про live-tracker: режимы `edit`/`bump`, `ORCH_TRACKER_MODE`, контракт `delete_telegram`.
|
||||
- `.env.example` — `ORCH_TRACKER_MODE=edit` с комментарием.
|
||||
- Тесты — см. `04-test-plan.yaml`. **Существующие тесты в `tests/test_telegram_tracker.py`, проверяющие англоязычные метки (`"✅ Analysis"`, `"🔄 Deploy"`, `"Review"`) и метку `"Ревью БРД"`, ОБЯЗАТЕЛЬНО обновить под новые русские строки** — иначе регрессия в CI. Это правка существующих ассертов, не изменение контракта.
|
||||
|
||||
## 6. Замечания по реализации (без расширения scope)
|
||||
- Не вводить новых зависимостей; `httpx` уже используется.
|
||||
- Не менять сигнатуры `send_telegram` / `edit_telegram` / `update_task_tracker` (внешние вызовы из `launcher`/`stage_engine` не трогаются).
|
||||
- Не менять состав отдельных пингов (approve-gate / error / deploy-fail / agent-fail).
|
||||
</content>
|
||||
55
docs/work-items/ORCH-042/03-acceptance-criteria.md
Normal file
55
docs/work-items/ORCH-042/03-acceptance-criteria.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# 03 — Критерии приёмки: ORCH-042
|
||||
|
||||
Каждый критерий — однозначное условие PASS/FAIL. Покрытие тестами — `04-test-plan.yaml`.
|
||||
|
||||
## Конфигурация
|
||||
- **AC-1.** `Settings.tracker_mode` существует, дефолт `"edit"`, читается из env `ORCH_TRACKER_MODE`.
|
||||
- PASS: `Settings().tracker_mode == "edit"` без env; `ORCH_TRACKER_MODE=bump` → `"bump"`.
|
||||
- FAIL: поле отсутствует / другой дефолт / не читает env.
|
||||
- **AC-2.** Неизвестное/пустое значение режима трактуется как `edit` (оркестратор не падает).
|
||||
- PASS: `ORCH_TRACKER_MODE=garbage` (или пусто) → `update_task_tracker` идёт по edit-ветке, исключений нет.
|
||||
- FAIL: исключение / выбор bump-ветки на мусоре.
|
||||
|
||||
## Режим edit (регрессия — поведение как было)
|
||||
- **AC-3.** Первый вызов (нет `tracker_message_id`): `sendMessage` тихо (`disable_notification=True`), id сохраняется; `editMessageText` НЕ вызывается.
|
||||
- **AC-4.** Повторный вызов при живом сообщении: `editMessageText` на сохранённый id; новое сообщение НЕ шлётся.
|
||||
- **AC-5.** `edit` вернул `EDIT_GONE` → шлётся НОВОЕ сообщение, id обновляется (fallback как раньше).
|
||||
- **AC-6.** `edit` вернул `EDIT_NOT_MODIFIED` или `EDIT_FAILED` → новое сообщение НЕ шлётся, id не меняется (защита от дублей сохранена).
|
||||
- Все AC-3..AC-6 проверяются при `tracker_mode="edit"` (дефолт). FAIL — любое расхождение с текущим поведением.
|
||||
|
||||
## Режим bump
|
||||
- **AC-7.** Первый вызов в `bump` (нет id): `deleteMessage` НЕ вызывается; `sendMessage` тихо (`disable_notification=True`); возвращённый id сохраняется.
|
||||
- PASS: ровно один `send_telegram(..., disable_notification=True)`, `delete_telegram` не вызван, `get_tracker_message_id == new_id`.
|
||||
- FAIL: вызван delete / громкое сообщение / id не сохранён.
|
||||
- **AC-8.** Повторный вызов в `bump` при существующем id: вызывается `delete_telegram(старый_id)`, затем `send_telegram(..., disable_notification=True)`, затем `tracker_message_id` перенаправляется на новый id.
|
||||
- PASS: порядок delete→send соблюдён, id == новый.
|
||||
- FAIL: нет delete / нет send / id остался старым.
|
||||
- **AC-9.** Bump тихий: новое сообщение всегда с `disable_notification=True`.
|
||||
- FAIL: `disable_notification` False/отсутствует.
|
||||
- **AC-10.** Одна карточка на задачу: за один вызов `update_task_tracker` в bump шлётся НЕ более одного нового сообщения.
|
||||
- FAIL: более одного `send_telegram` за вызов.
|
||||
|
||||
## Устойчивость
|
||||
- **AC-11.** Fallback при delete-fail: если `delete_telegram` вернул False (старое >48ч / транзиент) — новое сообщение всё равно отправляется, id обновляется, исключений нет.
|
||||
- PASS: `delete_telegram→False` → ровно один send → id == новый.
|
||||
- FAIL: send пропущен / исключение всплыло.
|
||||
- **AC-12.** `delete_telegram` классификация (httpx замокан, never raises):
|
||||
- `ok:true` → `True`;
|
||||
- `ok:false` с `"message to delete not found"` / `"message can't be deleted"` / `"message_id_invalid"` → `True`;
|
||||
- неизвестный `ok:false` / 5xx → `False`;
|
||||
- исключение (таймаут/сеть) → `False`;
|
||||
- нет токена/chat_id → `False`, HTTP-вызов не выполняется.
|
||||
- **AC-13.** Транзиентный сбой send в bump (send вернул None): `tracker_message_id` НЕ затирается на None; исключений нет; дублей нет (≤1 попытка send за вызов).
|
||||
- **AC-14.** `update_task_tracker` никогда не выбрасывает исключение ни в одном режиме (контракт «never raises») при любых сбоях БД/сети/Telegram.
|
||||
|
||||
## Текстовые правки (оба режима)
|
||||
- **AC-15.** Метка «Подтверждение BRD» присутствует в карточке там, где раньше была «Ревью БРД»; строки «Ревью БРД» в выводе нет.
|
||||
- **AC-16.** После прохождения approve-gate (зафиксированы `brd_review_started_at` и `brd_review_ended_at`) строка подтверждения BRD начинается с ✅ (не ⏸️). Пока ждём человека (`brd_review_ended_at` пуст) — индикатор ожидания/⏳ сохраняется (не ✅).
|
||||
- **AC-17.** Метки стадий в карточке русские: `Анализ`, `Архитектура`, `Разработка`, `Код ревью`, `Тестирование`, `Внедрение`. Английских меток (`Analysis`/`Architecture`/`Development`/`Review`/`Testing`/`Deploy`) в выводе нет — ни в «✅ …»-строках, ни в «🔄 … идёт».
|
||||
- **AC-18.** Итоговая строка готовой задачи содержит «📦 Внедрено» (не «deployed»).
|
||||
|
||||
## Регрессия и качество
|
||||
- **AC-19.** Состав отдельных пингов не изменён: `notify_approve_requested` шлёт ровно один НЕтихий пинг и стартует BRD-часы; `notify_error` — один НЕтихий пинг; `notify_stage_change` / `notify_agent_started` / `notify_qg_failure` — НЕ шлют отдельных сообщений (только refresh трекера).
|
||||
- **AC-20.** Вся существующая и новая pytest-сюита зелёная (`pytest tests/ -q`). Существующие ассерты в `tests/test_telegram_tracker.py` обновлены под русские метки и «Подтверждение BRD».
|
||||
- **AC-21.** Документация обновлена в ТОМ ЖЕ PR: `CHANGELOG.md`, `docs/architecture/internals.md` (режимы + `ORCH_TRACKER_MODE` + `delete_telegram`), `.env.example` (`ORCH_TRACKER_MODE`). Отсутствие — REQUEST_CHANGES на ревью.
|
||||
</content>
|
||||
160
docs/work-items/ORCH-042/04-test-plan.yaml
Normal file
160
docs/work-items/ORCH-042/04-test-plan.yaml
Normal file
@@ -0,0 +1,160 @@
|
||||
work_item: ORCH-042
|
||||
description: >
|
||||
Режим bump live-трекера (delete+send+repoint, тихо, fallback, never-raises),
|
||||
сохранение режима edit без регрессий, и текстовые правки карточки
|
||||
(Подтверждение BRD, ✅ после approve, русские метки стадий, «Внедрено»).
|
||||
Сеть не трогаем: httpx / низкоуровневые helpers мокаются; изолированная temp-БД.
|
||||
|
||||
tests:
|
||||
# --- config ---
|
||||
- id: TC-01
|
||||
type: unit
|
||||
description: "Settings.tracker_mode по умолчанию 'edit' и читается из ORCH_TRACKER_MODE (AC-1)"
|
||||
module: tests/test_config.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-02
|
||||
type: unit
|
||||
description: "Неизвестное/пустое значение режима -> update_task_tracker идёт по edit-ветке, без исключений (AC-2)"
|
||||
module: tests/test_telegram_tracker.py
|
||||
expected: PASS
|
||||
|
||||
# --- edit mode regression ---
|
||||
- id: TC-03
|
||||
type: unit
|
||||
description: "edit: первый вызов -> sendMessage тихо, id сохранён, editMessageText не вызван (AC-3)"
|
||||
module: tests/test_telegram_tracker.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-04
|
||||
type: unit
|
||||
description: "edit: повторный вызов -> editMessageText на сохранённый id, нового send нет (AC-4)"
|
||||
module: tests/test_telegram_tracker.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-05
|
||||
type: unit
|
||||
description: "edit: EDIT_GONE -> отправка нового, id обновлён (AC-5)"
|
||||
module: tests/test_telegram_tracker.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-06
|
||||
type: unit
|
||||
description: "edit: EDIT_NOT_MODIFIED и EDIT_FAILED -> нового сообщения нет, id не меняется (AC-6)"
|
||||
module: tests/test_telegram_tracker.py
|
||||
expected: PASS
|
||||
|
||||
# --- bump mode ---
|
||||
- id: TC-07
|
||||
type: unit
|
||||
description: "bump: первый вызов (нет id) -> delete не вызван, send тихий, id сохранён (AC-7, AC-9)"
|
||||
module: tests/test_tracker_bump.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-08
|
||||
type: unit
|
||||
description: "bump: повторный вызов -> delete(старый) затем send(тихо), id перенаправлен на новый, порядок delete->send (AC-8, AC-9, AC-10)"
|
||||
module: tests/test_tracker_bump.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-09
|
||||
type: unit
|
||||
description: "bump fallback: delete_telegram->False -> новое всё равно отправлено, id обновлён, без исключений (AC-11)"
|
||||
module: tests/test_tracker_bump.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-10
|
||||
type: unit
|
||||
description: "bump: send вернул None (транзиент) -> id не затёрт на None, ровно одна попытка send, без исключений (AC-13)"
|
||||
module: tests/test_tracker_bump.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-11
|
||||
type: unit
|
||||
description: "bump: одна карточка за вызов -> send_telegram вызван <=1 раза (AC-10)"
|
||||
module: tests/test_tracker_bump.py
|
||||
expected: PASS
|
||||
|
||||
# --- delete_telegram classification ---
|
||||
- id: TC-12
|
||||
type: unit
|
||||
description: "delete_telegram: ok:true -> True (httpx замокан)"
|
||||
module: tests/test_tracker_bump.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-13
|
||||
type: unit
|
||||
description: "delete_telegram: ok:false 'message to delete not found' / 'message can't be deleted' / 'message_id_invalid' -> True (AC-12)"
|
||||
module: tests/test_tracker_bump.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-14
|
||||
type: unit
|
||||
description: "delete_telegram: неизвестный ok:false / 5xx -> False (AC-12)"
|
||||
module: tests/test_tracker_bump.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-15
|
||||
type: unit
|
||||
description: "delete_telegram: исключение (таймаут/сеть) -> False, never raises (AC-12, AC-14)"
|
||||
module: tests/test_tracker_bump.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-16
|
||||
type: unit
|
||||
description: "delete_telegram: нет токена/chat_id -> False, HTTP не вызывается (AC-12)"
|
||||
module: tests/test_tracker_bump.py
|
||||
expected: PASS
|
||||
|
||||
# --- never raises ---
|
||||
- id: TC-17
|
||||
type: unit
|
||||
description: "update_task_tracker никогда не бросает (DB/сеть сбой) в обоих режимах (AC-14)"
|
||||
module: tests/test_tracker_bump.py
|
||||
expected: PASS
|
||||
|
||||
# --- text changes ---
|
||||
- id: TC-18
|
||||
type: unit
|
||||
description: "render: метка 'Подтверждение BRD' присутствует, 'Ревью БРД' отсутствует (AC-15)"
|
||||
module: tests/test_telegram_tracker.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-19
|
||||
type: unit
|
||||
description: "render: approve-gate пройден (brd_review_ended_at задан) -> строка BRD с ✅, не ⏸️ (AC-16)"
|
||||
module: tests/test_telegram_tracker.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-20
|
||||
type: unit
|
||||
description: "render: ожидание человека (brd_review_ended_at пуст) -> индикатор ожидания/⏳, не ✅ (AC-16)"
|
||||
module: tests/test_telegram_tracker.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-21
|
||||
type: unit
|
||||
description: "render: русские метки стадий (Анализ/Архитектура/Разработка/Код ревью/Тестирование/Внедрение), английских нет — в ✅- и 🔄-строках (AC-17)"
|
||||
module: tests/test_telegram_tracker.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-22
|
||||
type: unit
|
||||
description: "render done: итоговая строка содержит '📦 Внедрено', не 'deployed' (AC-18)"
|
||||
module: tests/test_telegram_tracker.py
|
||||
expected: PASS
|
||||
|
||||
# --- separate alerts regression ---
|
||||
- id: TC-23
|
||||
type: unit
|
||||
description: "Состав отдельных пингов не изменён: approve-gate/error шлют 1 нетихий пинг; stage_change/agent_started/qg_failure не шлют (AC-19)"
|
||||
module: tests/test_telegram_tracker.py
|
||||
expected: PASS
|
||||
|
||||
# --- full suite ---
|
||||
- id: TC-24
|
||||
type: integration
|
||||
description: "Вся pytest-сюита зелёная; обновлённые ассерты под русские метки проходят (AC-20)"
|
||||
module: tests/
|
||||
expected: PASS
|
||||
</content>
|
||||
85
docs/work-items/ORCH-042/06-adr/ADR-001-tracker-bump-mode.md
Normal file
85
docs/work-items/ORCH-042/06-adr/ADR-001-tracker-bump-mode.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# ADR-001: Режим bump live-трекера через delete+send+repoint, edit как дефолт
|
||||
|
||||
**Work Item:** ORCH-042 · См. `01-brd.md`, `02-trz.md`, `03-acceptance-criteria.md`, `10-tech-risks.md`.
|
||||
|
||||
## Статус
|
||||
Accepted
|
||||
|
||||
## Контекст
|
||||
|
||||
Live-tracker (`src/notifications.py`, ветка `feat/telegram-live-tracker`, Variant B+) держит **ОДНУ** карточку на задачу и редактирует её на месте (`editMessageText`) на каждом переходе стадии. Это сознательно убило прежнюю боль — «~15 отдельных карточек/дублей на задачу». Защита от дублей — главный инвариант компонента и не должна регрессировать.
|
||||
|
||||
Побочный эффект edit-режима: при активной переписке в чате карточка «тонет» вверху истории — актуальный статус задачи приходится искать скроллом. Слава просит альтернативу: карточка должна всегда быть последней в чате, но без возврата дублей и без звона на каждой стадии.
|
||||
|
||||
Дополнительно — косметика текста карточки (смесь EN-меток стадий с RU-текстом, «Ревью БРД», технический хвост `deployed`). Текстовые правки тривиальны и сами по себе архитектурного решения не требуют; ключевое решение — как реализовать новый режим, не сломав инвариант «одна карточка».
|
||||
|
||||
Ограничения окружения (см. `CLAUDE.md`, `docs/operations/INFRA.md`):
|
||||
- Контракт компонента: `update_task_tracker` и low-level helpers **никогда не бросают** (сбой нотификации не должен валить конвейер).
|
||||
- Self-hosting: правка инструмента, который сейчас в проде и обслуживает другие проекты из общей БД/очереди. Прод-рестарт self — только через `deploy-staging` (8501).
|
||||
- Telegram Bot API: `deleteMessage` не работает для сообщений старше 48 ч и для уже удалённых/недоступных — это нормальный ожидаемый исход, а не ошибка.
|
||||
|
||||
## Решение
|
||||
|
||||
### Р-1. Поведение задаётся конфиг-флагом, дефолт `edit` (нулевая регрессия)
|
||||
Новое поле `Settings.tracker_mode` (env `ORCH_TRACKER_MODE`), значения `edit` | `bump`, **дефолт `edit`**. Резолюция режима — в `notifications`, case-insensitive + trim; всё, что не равно `"bump"` (включая пустое/мусор/None), трактуется как `edit`. Без явного включения bump поведение неотличимо от текущего → нулевая регрессия и безопасный фолбэк (оркестратор не падает на любом значении флага).
|
||||
|
||||
### Р-2. Режим bump = delete + send + repoint, инвариант «одна карточка» сохраняется иначе
|
||||
edit-режим держит одну карточку, *редактируя* её. bump держит одну карточку, *пересоздавая* её внизу:
|
||||
1. если сохранён `tracker_message_id` — best-effort `delete_telegram(старый_id)`;
|
||||
2. `send_telegram(text, disable_notification=True)` — новая карточка внизу, тихо;
|
||||
3. при успехе (`new_mid is not None`) — `set_tracker_message_id` перенаправляется на новый id.
|
||||
|
||||
Итог: в чате всегда ровно одна карточка задачи, и она всегда последняя. За **один** вызов `update_task_tracker` отправляется **не более одного** нового сообщения → дублей в пределах вызова нет.
|
||||
|
||||
### Р-3. delete — best-effort, никогда не блокирует отправку новой карточки
|
||||
Новый low-level helper `delete_telegram(message_id) -> bool` с контрактом «never raises». Семантика возврата — «исчезло ли старое сообщение»:
|
||||
- `ok:true` → `True`;
|
||||
- `ok:false` с маркерами «уже нет / нельзя удалить» (`message to delete not found`, `message can't be deleted`, `message_id_invalid`, вынести в константу `_DELETE_GONE_MARKERS`) → `True` (не транзиент, сообщение и так недоступно);
|
||||
- прочий `ok:false` / 5xx / исключение (сеть/таймаут) → `False` + `logger.warning`;
|
||||
- нет токена/chat_id → `False`, HTTP не выполняется.
|
||||
|
||||
**Результат `delete_telegram` НЕ влияет на решение отправлять новую карточку** — её шлём всегда (BR-6: delete-fail у сообщения >48 ч → всё равно новое). `False` означает лишь «старое, возможно, ещё живо»; на следующем переходе оно будет удалено повторно (или уже мёртво). Накопления карточек это не даёт, т.к. указатель всегда хранит ровно один id.
|
||||
|
||||
### Р-4. repoint только при успешном send (анти-затирание указателя)
|
||||
`set_tracker_message_id` вызывается **только** при `new_mid is not None`. Если send вернул None (нет кредов / транзиент 5xx/таймаут) — id **не трогаем** (не затираем на None): карточка перерисуется на следующем переходе, дубля нет (≤1 попытка send за вызов). Это симметрично существующему edit-fallback, который тоже не плодит сообщения при транзиенте.
|
||||
|
||||
### Р-5. bump всегда тихий
|
||||
Новая карточка отправляется с `disable_notification=True` — всплывает внизу, но без звука/пинга, как и edit сейчас. Состав отдельных НЕтихих пингов (approve-gate / error / deploy-fail / agent-fail) не меняется (вне scope).
|
||||
|
||||
### Р-6. Текстовые правки — в одной точке, общие для обоих режимов
|
||||
Правки (`_BRD_LABEL` → «Подтверждение BRD»; ✅ вместо ⏸️ после approve-gate; русские display-labels в `_TRACKER_STAGES`; `_done_link` → «Внедрено») затрагивают только **отображаемые** строки. Ключи стадий (`analysis`, …) и имена агентов (`analyst`, …) НЕ меняются — они завязаны на `_STAGE_ACTIVE_AGENT`, `last_done`, БД. Правка `_TRACKER_STAGES` в одном месте автоматически русифицирует и «✅ …», и «🔄 … идёт».
|
||||
|
||||
### Что НЕ меняется (границы решения)
|
||||
- БД: миграций нет, используется существующая колонка `tasks.tracker_message_id` и хелперы `get_tracker_message_id` / `set_tracker_message_id`. → `08-data-requirements.md` не требуется.
|
||||
- Инфраструктура / топология / порты / контейнеры — без изменений. → `07-infra-requirements.md` не требуется.
|
||||
- State machine (`src/stages.py`), реестр QG (`src/qg/checks.py`), стадии, компоненты — без изменений. → глобальный (cross-cutting) ADR не требуется, решение локально для компонента notifications.
|
||||
- Сигнатуры `send_telegram` / `edit_telegram` / `update_task_tracker` — без изменений (внешние вызовы из `launcher`/`stage_engine` не трогаются).
|
||||
- Новых зависимостей нет (`httpx` уже используется).
|
||||
|
||||
## Альтернативы
|
||||
|
||||
- **A1. Только bump, без флага.** Отклонено: ломает обратную совместимость и единственного пользователя (Слава может предпочесть edit); рост риска регрессии защиты от дублей. Флаг с дефолтом `edit` даёт мгновенный откат.
|
||||
- **A2. Pin-сообщение (закрепить карточку).** Отклонено: pin не решает «карточка внизу при переписке», шлёт системное уведомление о закреплении (звон), и усложняет API-контракт. Вне духа «тихого» трекера.
|
||||
- **A3. send-then-delete (сначала новое, потом удалить старое).** Отклонено как дефолтный порядок: в окне между send и delete в чате видны ДВЕ карточки; при падении на delete остаётся осиротевшая старая → визуальный дубль. delete-then-send гарантирует ≤1 карточку в любой момент при нормальном пути и ≤1 *новую* отправку за вызов в любом случае.
|
||||
- **A4. Хранить историю/несколько карточек.** Вне scope и противоречит исходному инварианту «одна карточка».
|
||||
|
||||
## Последствия
|
||||
|
||||
**Плюсы**
|
||||
- Слава получает актуальную карточку всегда внизу чата, одну на задачу, без звона.
|
||||
- Нулевая регрессия по умолчанию (edit), мгновенный откат флагом.
|
||||
- Контракт «never raises» и инвариант «одна карточка» сохранены в обоих режимах.
|
||||
- Изменения локальны (`config.py` + `notifications.py`), без миграций и без рестарта-критичных зависимостей.
|
||||
|
||||
**Минусы / ограничения**
|
||||
- bump расходует Telegram API на 2 запроса вместо 1 (delete + send) на переход — для одного получателя несущественно (rate-limit Telegram не угрожает).
|
||||
- При транзиентном delete-fail возможна кратко осиротевшая старая карточка до следующего перехода (она будет вычищена попыткой delete на следующем апдейте) — приемлемо, дублей всё равно не плодит.
|
||||
- bump теряет визуальную «эволюцию на месте» edit-режима (история чата получает по карточке-замене) — но в чате всегда одна актуальная, что и требуется.
|
||||
|
||||
**Риски** — см. `10-tech-risks.md`.
|
||||
|
||||
## Связи
|
||||
- BRD/ТЗ/AC: `docs/work-items/ORCH-042/01-brd.md`, `02-trz.md`, `03-acceptance-criteria.md`; тест-план `04-test-plan.yaml`.
|
||||
- Компонент: live-tracker (`src/notifications.py`), `feat/telegram-live-tracker` (Variant B+).
|
||||
- Контекст self-hosting / staging-страховка: `CLAUDE.md`, `docs/operations/INFRA.md`, `docs/architecture/adr/adr-0003-staging-gate.md`.
|
||||
- Обновляемая дока (в том же PR, стадия development): `CHANGELOG.md`, `docs/architecture/internals.md` (секция live-tracker: режимы + `ORCH_TRACKER_MODE` + `delete_telegram`), `.env.example`.
|
||||
21
docs/work-items/ORCH-042/10-tech-risks.md
Normal file
21
docs/work-items/ORCH-042/10-tech-risks.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# 10 — Технические риски: ORCH-042
|
||||
|
||||
См. `02-trz.md`, `06-adr/ADR-001-tracker-bump-mode.md`, `03-acceptance-criteria.md`.
|
||||
|
||||
Шкала: Вероятность × Влияние ∈ {низк., сред., выс.}.
|
||||
|
||||
| # | Риск | Вер. | Влияние | Митигация | Контроль (AC/TC) |
|
||||
|---|------|------|---------|-----------|-------------------|
|
||||
| R-1 | **Регрессия защиты от дублей** — рефактор `update_task_tracker` ломает edit-ветку, возвращается боль «~15 карточек». | низк. | выс. | edit — дефолт и неизменяемая ветка; bump добавляется отдельной веткой `if mode == "bump"`, edit-код не трогается. Полное покрытие edit-регрессии тестами. | AC-3..AC-6, AC-8; TC-03..TC-06, TC-24 |
|
||||
| R-2 | **Двойная отправка / накопление карточек в bump** — delete и send рассинхронизированы, в чате >1 карточки. | низк. | сред. | Инвариант: ≤1 `send_telegram` за вызов; `set_tracker_message_id` только при успешном send; delete best-effort и не блокирует. | AC-8, AC-10, AC-11; TC-08, TC-09, TC-11 |
|
||||
| R-3 | **Затирание `tracker_message_id` на None** при транзиентном send-fail → потеря указателя, следующий апдейт не найдёт старое. | низк. | сред. | repoint только при `new_mid is not None`; при None id сохраняется как есть. | AC-13; TC-10 |
|
||||
| R-4 | **Нарушение контракта «never raises»** — исключение из `delete_telegram`/новой ветки валит конвейер (групповой риск из-за общей очереди). | низк. | выс. | `delete_telegram` обёрнут try/except → bool; внешний try/except в `update_task_tracker` сохранён; сеть/httpx мокаются в тестах. | AC-12, AC-14; TC-12..TC-17 |
|
||||
| R-5 | **Ложная классифик. delete-ответа** — неизвестный `ok:false` принят за «исчезло» (или наоборот), вечные ретраи/тишина. | низк. | низк. | Явные `_DELETE_GONE_MARKERS` → True; всё прочее (включая 5xx) → False; повтор delete на следующем апдейте безопасен (идемпотентно). | AC-12; TC-13, TC-14 |
|
||||
| R-6 | **Падение CI на старых ассертах** — тесты `tests/test_telegram_tracker.py` проверяют EN-метки/«Ревью БРД». | сред. | сред. | ТЗ §5 явно требует обновить существующие ассерты под русские метки и «Подтверждение BRD» в том же PR. | AC-20; TC-18, TC-21, TC-24 |
|
||||
| R-7 | **Сломанная human-gate индикация** — ✅ показан до прохождения approve-gate (ввод в заблуждение). | низк. | низк. | ✅ только при заданном `brd_review_ended_at`; ветка ожидания (`review_seconds is None`, ⏳) не меняется. | AC-16; TC-19, TC-20 |
|
||||
| R-8 | **Скрытая зависимость от display-label** — русификация `_TRACKER_STAGES` ломает логику, завязанную на текст метки. | низк. | сред. | Меняется только 2-й элемент кортежа (label); ключи стадий и имена агентов (`_STAGE_ACTIVE_AGENT`, `last_done`, БД) не трогаются. | AC-17; TC-21 |
|
||||
| R-9 | **Self-hosting: прод-сбой при выкатке self** — общая БД/очередь, рестарт орка останавливает все проекты. | низк. | выс. | Изменения только в коде нотификаций, миграций БД нет; обязательная страховка `deploy-staging` (8501) перед prod (CLAUDE.md, INFRA.md, adr-0003). Дефолт edit → даже при выкатке поведение не меняется без явного флага. | стадия deploy-staging; `check_staging_status` |
|
||||
| R-10 | **Документация не обновлена** в том же PR (internals.md / .env.example / CHANGELOG) → REQUEST_CHANGES. | сред. | низк. | ТЗ §5 и AC-21 фиксируют список; reviewer проверяет наличие. | AC-21 |
|
||||
|
||||
## Сводный вывод
|
||||
Все риски — **низкие по вероятности** при соблюдении инвариантов из ADR-001 (edit-дефолт, ≤1 send/вызов, repoint-only-on-success, never-raises, правка только display-label). Остаточный групповой self-hosting-риск (R-9) полностью покрывается обязательным `deploy-staging`-гейтом и тем, что дефолтное поведение не меняется. Блокеров для перехода на стадию development нет.
|
||||
56
docs/work-items/ORCH-042/12-review.md
Normal file
56
docs/work-items/ORCH-042/12-review.md
Normal file
@@ -0,0 +1,56 @@
|
||||
---
|
||||
type: review
|
||||
work_item_id: ORCH-042
|
||||
verdict: APPROVED
|
||||
version: 1
|
||||
---
|
||||
|
||||
# Review ORCH-042
|
||||
|
||||
## Summary
|
||||
Telegram live-tracker: добавлен режим `bump` (`ORCH_TRACKER_MODE` / `Settings.tracker_mode`, дефолт `edit`) + русификация и косметика карточки. Реализация точно соответствует `02-trz.md` и `06-adr/ADR-001-tracker-bump-mode.md`. Все 21 критерий приёмки покрыты; `pytest tests/ -q` — **494 passed**. Документация обновлена в том же PR. Замечаний уровня P0/P1/P2 нет.
|
||||
|
||||
## Проверка по осям
|
||||
|
||||
### 1. Соответствие ТЗ
|
||||
- `Settings.tracker_mode = "edit"` + env `ORCH_TRACKER_MODE` — есть (config.py).
|
||||
- `delete_telegram(message_id) -> bool` — контракт «never raises», `_DELETE_GONE_MARKERS` вынесены в константу, классификация ok/gone/transient/no-creds реализована дословно по ТЗ §3.1.
|
||||
- Ветвление `update_task_tracker`: bump = delete(best-effort) → send(silent) → repoint только при `new_mid is not None`; edit-ветка сохранена без изменений (§3.2). Инварианты bump (≤1 send/вызов, анти-затирание указателя, delete не блокирует send, всегда тихо) соблюдены.
|
||||
- Текстовые правки BR-9..BR-12 (`_BRD_LABEL`→«Подтверждение BRD», ✅ вместо ⏸️ после approve-gate, русские display-labels `_TRACKER_STAGES`, `_done_link`→«Внедрено») — на месте; ключи стадий и имена агентов не тронуты.
|
||||
- БД, API, сигнатуры helpers, зависимости — без изменений (как и требовалось).
|
||||
|
||||
### 2. Соответствие ADR (ADR-001)
|
||||
Реализация соответствует решениям Р-1..Р-6: флаг с дефолтом edit (нулевая регрессия), delete+send+repoint, best-effort delete, repoint только при успешном send, всегда тихий bump, текст в одной точке. Выбран порядок delete-then-send (A3 отклонён обоснованно). Глобальные ADR не нарушены; решение локально для компонента notifications, что зафиксировано в ADR.
|
||||
|
||||
### 3. Качество кода
|
||||
- Defensive-контракты «never raises» соблюдены и в helper, и в `update_task_tracker`.
|
||||
- Docstrings содержательные; логирование (`debug`/`warning`) корректно разнесено по случаям.
|
||||
- Security/утечек нет; новых зависимостей нет.
|
||||
|
||||
### 4. Качество тестов
|
||||
- `tests/test_config.py` (AC-1), `tests/test_tracker_bump.py` (AC-7..AC-14: ордеринг delete→send, delete-fail, send=None, ≤1 send, классификация delete_telegram, never-raises), `tests/test_telegram_tracker.py` (AC-2 garbage→edit, AC-15..AC-18 русификация, регрессия edit).
|
||||
- Существующие англоязычные ассерты обновлены под русские метки и «Подтверждение BRD» (AC-20).
|
||||
- Тесты содержательные, не тривиальные. `pytest tests/ -q` → 494 passed.
|
||||
|
||||
## Findings
|
||||
|
||||
### P0 — Blocker
|
||||
- нет
|
||||
|
||||
### P1 — Must fix
|
||||
- нет
|
||||
|
||||
### P2 — Should fix
|
||||
- нет
|
||||
|
||||
### P3 — Nice to have
|
||||
- [ ] В `_TRACKER_STAGES` строчные комментарии-дубли (`# Анализ` и т.п.) после уже русских меток избыточны — косметика, на поведение не влияет.
|
||||
|
||||
## Документация
|
||||
Обновлена в том же PR, полностью соответствует AC-21:
|
||||
- `CHANGELOG.md` — записи в `[Unreleased] / Added` (bump-режим + `delete_telegram`) и `Changed` (русификация). ✅
|
||||
- `docs/architecture/internals.md` — новая секция «Live Telegram tracker»: режимы edit/bump (таблица), `ORCH_TRACKER_MODE`, контракт `delete_telegram`, текстовые правки. ✅
|
||||
- `.env.example` — `ORCH_TRACKER_MODE=edit` с комментарием. ✅
|
||||
- ADR заведён: `06-adr/ADR-001-tracker-bump-mode.md`. ✅
|
||||
|
||||
Изменения `src/` (config.py, notifications.py) полностью отражены в документации — правило «документация = golden source» выполнено.
|
||||
78
docs/work-items/ORCH-042/13-test-report.md
Normal file
78
docs/work-items/ORCH-042/13-test-report.md
Normal file
@@ -0,0 +1,78 @@
|
||||
---
|
||||
type: test-report
|
||||
work_item_id: ORCH-042
|
||||
result: PASS
|
||||
---
|
||||
|
||||
# Test Report — ORCH-042
|
||||
|
||||
Telegram live-tracker: режим `bump` (delete+send+repoint, тихо, fallback, never-raises),
|
||||
сохранение режима `edit` без регрессий, русификация карточки.
|
||||
|
||||
## Окружение
|
||||
- Python: 3.12.13
|
||||
- pytest: 8.3.3
|
||||
- Ветка: feature/ORCH-042-telegram-live-tracker-bump
|
||||
- Дата: 2026-06-06
|
||||
- Prod orchestrator (8500): `/health` → `{"status":"ok"}`, активна задача #40 (ORCH-042, stage=testing)
|
||||
|
||||
## Smoke test API
|
||||
| Endpoint | Результат |
|
||||
|----------|-----------|
|
||||
| GET /health | PASS — `{"status":"ok","service":"orchestrator"}` |
|
||||
| GET /status | PASS — активная задача ORCH-042 (stage=testing) |
|
||||
| GET /queue | PASS — queued:0 running:1 done:99 failed:0, breaker=closed |
|
||||
|
||||
(`curl` в окружении недоступен — smoke выполнен через `urllib`.)
|
||||
|
||||
## Результаты по тест-плану (04-test-plan.yaml)
|
||||
|
||||
| TC ID | Описание | AC | Результат |
|
||||
|-------|----------|----|-----------|
|
||||
| TC-01 | Settings.tracker_mode дефолт 'edit', читается из ORCH_TRACKER_MODE | AC-1 | PASS |
|
||||
| TC-02 | Мусорное/пустое значение → edit-ветка, без исключений | AC-2 | PASS |
|
||||
| TC-03 | edit: первый вызов → send тихо, id сохранён, edit не вызван | AC-3 | PASS |
|
||||
| TC-04 | edit: повтор → editMessageText на сохранённый id, нового send нет | AC-4 | PASS |
|
||||
| TC-05 | edit: EDIT_GONE → отправка нового, id обновлён | AC-5 | PASS |
|
||||
| TC-06 | edit: EDIT_NOT_MODIFIED/EDIT_FAILED → нового нет, id не меняется | AC-6 | PASS |
|
||||
| TC-07 | bump: первый вызов → delete не вызван, send тихий, id сохранён | AC-7,9 | PASS |
|
||||
| TC-08 | bump: повтор → delete(старый)→send(тихо)→repoint, порядок соблюдён | AC-8,9,10 | PASS |
|
||||
| TC-09 | bump fallback: delete→False → новое всё равно отправлено | AC-11 | PASS |
|
||||
| TC-10 | bump: send=None → id не затёрт, ≤1 send | AC-13 | PASS |
|
||||
| TC-11 | bump: одна карточка за вызов (send ≤1) | AC-10 | PASS |
|
||||
| TC-12 | delete_telegram: ok:true → True | AC-12 | PASS |
|
||||
| TC-13 | delete_telegram: gone-маркеры → True | AC-12 | PASS |
|
||||
| TC-14 | delete_telegram: неизвестный ok:false / 5xx → False | AC-12 | PASS |
|
||||
| TC-15 | delete_telegram: исключение → False, never raises | AC-12,14 | PASS |
|
||||
| TC-16 | delete_telegram: нет кредов → False, HTTP не вызван | AC-12 | PASS |
|
||||
| TC-17 | update_task_tracker never raises (оба режима) | AC-14 | PASS |
|
||||
| TC-18 | render: «Подтверждение BRD» есть, «Ревью БРД» нет | AC-15 | PASS |
|
||||
| TC-19 | render: approve-gate пройден → строка BRD с ✅ | AC-16 | PASS |
|
||||
| TC-20 | render: ожидание человека → ⏳, не ✅ | AC-16 | PASS |
|
||||
| TC-21 | render: русские метки стадий, английских нет | AC-17 | PASS |
|
||||
| TC-22 | render done: «📦 Внедрено», не «deployed» | AC-18 | PASS |
|
||||
| TC-23 | состав отдельных пингов не изменён | AC-19 | PASS |
|
||||
| TC-24 | вся pytest-сюита зелёная | AC-20 | PASS |
|
||||
|
||||
Все 24 тест-кейса плана покрыты и пройдены. Критерии AC-1..AC-20 подтверждены
|
||||
тестами; AC-21 (документация) подтверждён на ревью (12-review.md, verdict APPROVED).
|
||||
|
||||
## Вывод pytest
|
||||
|
||||
Целевые модули ORCH-042:
|
||||
```
|
||||
tests/test_config.py tests/test_telegram_tracker.py tests/test_tracker_bump.py
|
||||
52 passed, 1 warning in 1.38s
|
||||
```
|
||||
|
||||
Полный регресс:
|
||||
```
|
||||
======================== 494 passed, 1 warning in 8.57s ========================
|
||||
```
|
||||
|
||||
(Единственный warning — PydanticDeprecatedSince20 в `src/config.py:4`, не связан с
|
||||
ORCH-042, существовал ранее, на результат не влияет.)
|
||||
|
||||
## Итог
|
||||
**PASS** — полный регресс 494/494 зелёный, целевые модули 52/52 PASS, smoke API OK.
|
||||
Задача готова к стадии deploy-staging.
|
||||
Reference in New Issue
Block a user