analyst(ET): auto-commit from analyst run_id=413
This commit is contained in:
73
docs/work-items/ORCH-080/01-brd.md
Normal file
73
docs/work-items/ORCH-080/01-brd.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# 01-BRD — ORCH-080: убрать Telegram link-preview (логотип Plane) в уведомлениях трекера
|
||||
|
||||
Work Item ID: ORCH-080
|
||||
Эпик: ORCH-052 (под-задача ORCH-52g)
|
||||
Тип: Доработка (UX уведомлений)
|
||||
Приоритет: LOW (косметика)
|
||||
Зона: `src/notifications.py`
|
||||
|
||||
## 1. Контекст и проблема
|
||||
|
||||
Каждая задача в Telegram сопровождается одной live-карточкой трекера (`src/notifications.py`,
|
||||
ORCH-042/066/067). С ORCH-067 в карточке появился **кликабельный номер задачи** —
|
||||
`<a href="https://plane.mva154.duckdns.org/.../issues/<id>/">ORCH-NNN</a>`.
|
||||
|
||||
Telegram по умолчанию разворачивает **link-preview** (web page preview) для первой ссылки
|
||||
в сообщении. Из-за ссылки на Plane под каждым сообщением трекера раскрывается крупный
|
||||
баннер-превью **«Plane — Modern project management»**.
|
||||
|
||||
**Жалоба (Слава, 08.06):** баннер уродует ленту чата и дублируется на каждой задаче/каждом
|
||||
обновлении карточки (особенно заметно в дефолтном режиме `bump`, где карточка пересоздаётся
|
||||
на каждом переходе).
|
||||
|
||||
## 2. Диагностика (код-аудит `src/notifications.py`)
|
||||
|
||||
| Функция | Эндпоинт | Текущий JSON-payload | Превью |
|
||||
|---------|----------|----------------------|--------|
|
||||
| `send_telegram()` (стр. 52-62) | `POST /sendMessage` | `chat_id`, `text`, `parse_mode: HTML`, `disable_notification` | **разворачивается** (нет `disable_web_page_preview`) |
|
||||
| `edit_telegram()` (стр. 165-174) | `POST /editMessageText` | `chat_id`, `message_id`, `text`, `parse_mode: HTML` | **разворачивается** (нет `disable_web_page_preview`) |
|
||||
|
||||
Причина баннера: оба payload **не содержат** ключ `disable_web_page_preview`. Telegram Bot API
|
||||
по умолчанию (отсутствие ключа) включает превью.
|
||||
|
||||
`delete_telegram()` (`/deleteMessage`) превью не порождает — правки не требует.
|
||||
|
||||
## 3. Бизнес-цель
|
||||
|
||||
Карточка трекера и уведомления в Telegram **не должны** показывать баннер link-preview Plane,
|
||||
при этом ссылка на задачу **остаётся кликабельной**.
|
||||
|
||||
## 4. Бизнес-требования
|
||||
|
||||
- **BR-1.** В payload `sendMessage` (`send_telegram`) присутствует `disable_web_page_preview: True`.
|
||||
- **BR-2.** В payload `editMessageText` (`edit_telegram`) присутствует `disable_web_page_preview: True`.
|
||||
- **BR-3.** Баннер-превью Plane больше не появляется ни под карточкой трекера (оба режима
|
||||
`bump`/`edit`), ни под отдельными notify-сообщениями, которые идут через `send_telegram`
|
||||
(`notify_approve_requested`, `notify_error`, alert'ы стадий) — все они используют тот же
|
||||
низкоуровневый примитив.
|
||||
- **BR-4.** Кликабельная ссылка `<a href>` на задачу в Plane сохраняется (`parse_mode: HTML`
|
||||
не меняется).
|
||||
- **BR-5.** Контракт **never-raise** сохранён: отправка/редактирование никогда не валит
|
||||
оркестратор; `pytest` зелёный.
|
||||
|
||||
## 5. Не-цели (вне скоупа)
|
||||
|
||||
- Не менять текст/формат/верстку карточки.
|
||||
- Не трогать `parse_mode` (HTML нужен для `<a href>`).
|
||||
- Не трогать bump/edit-логику (`update_task_tracker`), репойнт `tracker_message_id`,
|
||||
delete-семантику.
|
||||
- Не вводить флаги/конфиг — поведение «без превью» безусловное (превью никому не нужно).
|
||||
- Не трогать схему БД.
|
||||
|
||||
## 6. Заинтересованные лица
|
||||
|
||||
- **Слава (Owner)** — инициатор, конечный наблюдатель ленты Telegram.
|
||||
|
||||
## 7. Грабли / координация
|
||||
|
||||
- Файл `src/notifications.py` затрагивает также ORCH-067 (и потенциально другие задачи эпика).
|
||||
Сверить, что правки (две строки) не конфликтуют при merge.
|
||||
- Один репозиторий с ORCH-74 → по ORCH-026 действует сериализация merge.
|
||||
Запускать **после** того как ORCH-74 доедет в `main` (или когда конвейер свободен),
|
||||
чтобы не плодить параллельный merge в `orchestrator`.
|
||||
- Деплой — штатный через **Confirm Deploy** (self-hosting, ORCH-059).
|
||||
102
docs/work-items/ORCH-080/02-trz.md
Normal file
102
docs/work-items/ORCH-080/02-trz.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# 02-TRZ — ORCH-080: убрать Telegram link-preview в уведомлениях трекера
|
||||
|
||||
Work Item ID: ORCH-080
|
||||
Зона изменений: `src/notifications.py` (две строки)
|
||||
|
||||
## 1. Задействованные модули `src/`
|
||||
|
||||
- `src/notifications.py` — **единственный** изменяемый модуль:
|
||||
- `send_telegram(text, disable_notification=False)` — обёртка `POST .../sendMessage`.
|
||||
- `edit_telegram(message_id, text)` — обёртка `POST .../editMessageText`.
|
||||
|
||||
Косвенно затронуты (поведение улучшается без изменения их кода — они вызывают изменённые
|
||||
примитивы): `update_task_tracker` (bump+edit), `notify_approve_requested`, `notify_error`,
|
||||
а также вызовы `send_telegram` из `launcher`/`stage_engine` (alert'ы деплоя/падений).
|
||||
|
||||
## 2. Изменения кода
|
||||
|
||||
### 2.1. `send_telegram()` — добавить ключ в JSON-payload `httpx.post`
|
||||
|
||||
В словаре `json={...}` вызова `sendMessage` (текущие стр. 55-60) добавить строку:
|
||||
|
||||
```python
|
||||
"disable_web_page_preview": True,
|
||||
```
|
||||
|
||||
Итоговый payload:
|
||||
```python
|
||||
json={
|
||||
"chat_id": s.telegram_chat_id,
|
||||
"text": text,
|
||||
"parse_mode": "HTML",
|
||||
"disable_notification": disable_notification,
|
||||
"disable_web_page_preview": True,
|
||||
},
|
||||
```
|
||||
|
||||
### 2.2. `edit_telegram()` — добавить ключ в JSON-payload `httpx.post`
|
||||
|
||||
В словаре `json={...}` вызова `editMessageText` (текущие стр. 168-173) добавить строку:
|
||||
|
||||
```python
|
||||
"disable_web_page_preview": True,
|
||||
```
|
||||
|
||||
Итоговый payload:
|
||||
```python
|
||||
json={
|
||||
"chat_id": s.telegram_chat_id,
|
||||
"message_id": message_id,
|
||||
"text": text,
|
||||
"parse_mode": "HTML",
|
||||
"disable_web_page_preview": True,
|
||||
},
|
||||
```
|
||||
|
||||
> Примечание: Telegram Bot API исторически принимает top-level `disable_web_page_preview`
|
||||
> для `sendMessage`/`editMessageText` (актуальная схема также поддерживает
|
||||
> `link_preview_options.is_disabled`, но top-level флаг остаётся валиден и совместим).
|
||||
> Используем top-level флаг — минимальная, обратносовместимая правка, как указано в задаче.
|
||||
|
||||
## 3. Изменения API
|
||||
|
||||
Нет изменений внутреннего HTTP API оркестратора. Меняется только тело исходящих запросов к
|
||||
Telegram Bot API (добавлен один булев ключ в payload двух методов).
|
||||
|
||||
## 4. Изменения схемы БД
|
||||
|
||||
Нет.
|
||||
|
||||
## 5. Требования к новым QG checks
|
||||
|
||||
Нет. Новые Quality Gate проверки не вводятся.
|
||||
|
||||
## 6. Конфиг / флаги
|
||||
|
||||
Нет. Поведение «без превью» — безусловное (kill-switch не требуется: превью трекера
|
||||
не нужно никому, риск регрессии нулевой; правка обратимая одной строкой).
|
||||
`parse_mode`, `disable_notification`, bump/edit-логика — без изменений.
|
||||
|
||||
## 7. Артефакты, обновляемые по pipeline
|
||||
|
||||
- `CHANGELOG.md` — запись в `## [Unreleased]` (тип `fix:` — косметика UX уведомлений).
|
||||
- Документация: правка `src/notifications.py` затрагивает поведение, описанное в
|
||||
`CLAUDE.md` (раздел «Нотификации / Telegram live-tracker») и
|
||||
`docs/architecture/README.md` (компонент Notifications). Достаточно короткой ремарки,
|
||||
что карточка/уведомления шлются без web-page-preview (по желанию архитектора — определить
|
||||
объём в ADR; ADR не обязателен для столь малой косметики, решение за архитектором).
|
||||
|
||||
## 8. Контракты-инварианты (не нарушать)
|
||||
|
||||
- **never-raise**: обе функции по-прежнему ловят все исключения (`try/except: pass`/`return`)
|
||||
и не валят оркестратор.
|
||||
- Возвращаемые значения не меняются: `send_telegram` → `message_id|None`,
|
||||
`edit_telegram` → `EDIT_*`.
|
||||
- `parse_mode: "HTML"` сохранён в обоих payload (иначе `<a href>` сломается).
|
||||
- `disable_notification` в `send_telegram` сохранён (карточка тихая).
|
||||
- Инвариант «одна карточка на задачу» (bump/edit) не затрагивается.
|
||||
|
||||
## 9. Commit / ветка
|
||||
|
||||
- Ветка: `feature/ORCH-080-orch-52g-telegram-link-preview` (существует).
|
||||
- Commit: `fix: disable Telegram link-preview in tracker notifications (ORCH-080)`.
|
||||
59
docs/work-items/ORCH-080/03-acceptance-criteria.md
Normal file
59
docs/work-items/ORCH-080/03-acceptance-criteria.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# 03-Acceptance Criteria — ORCH-080
|
||||
|
||||
Work Item ID: ORCH-080
|
||||
|
||||
Каждый критерий имеет явное условие PASS/FAIL.
|
||||
|
||||
## AC-1 — `disable_web_page_preview` в payload `sendMessage`
|
||||
|
||||
- **PASS:** JSON-payload вызова `httpx.post(.../sendMessage)` в `send_telegram()` содержит
|
||||
ключ `"disable_web_page_preview"` со значением `True`.
|
||||
- **FAIL:** ключ отсутствует или `False`.
|
||||
- **Проверка:** unit-тест (мок `httpx`) инспектирует `httpx.post.call_args.kwargs["json"]`.
|
||||
|
||||
## AC-2 — `disable_web_page_preview` в payload `editMessageText`
|
||||
|
||||
- **PASS:** JSON-payload вызова `httpx.post(.../editMessageText)` в `edit_telegram()` содержит
|
||||
ключ `"disable_web_page_preview"` со значением `True`.
|
||||
- **FAIL:** ключ отсутствует или `False`.
|
||||
- **Проверка:** unit-тест (мок `httpx`) инспектирует `httpx.post.call_args.kwargs["json"]`.
|
||||
|
||||
## AC-3 — баннер link-preview Plane исчез в карточке трекера
|
||||
|
||||
- **PASS:** в реальном чате Telegram карточка трекера задачи (режимы `bump` и `edit`)
|
||||
больше не показывает баннер «Plane — Modern project management».
|
||||
- **FAIL:** баннер всё ещё разворачивается.
|
||||
- **Проверка:** ручная верификация на staging (8501) после деплоя — наблюдение карточки в
|
||||
Telegram. Автоматически косвенно покрыто AC-1/AC-2 (payload содержит флаг).
|
||||
|
||||
## AC-4 — ссылка на задачу остаётся кликабельной
|
||||
|
||||
- **PASS:** в карточке/уведомлениях номер задачи `ORCH-NNN` остаётся кликабельной ссылкой
|
||||
`<a href=...>` на issue в Plane; `parse_mode: "HTML"` сохранён в обоих payload.
|
||||
- **FAIL:** `parse_mode` изменён/удалён, либо ссылка перестала рендериться как `<a href>`.
|
||||
- **Проверка:** unit-тест проверяет, что `"parse_mode": "HTML"` присутствует в обоих payload;
|
||||
существующие тесты ссылок (`test_notify_issue_links.py`) остаются зелёными.
|
||||
|
||||
## AC-5 — сохранены существующие поля payload
|
||||
|
||||
- **PASS:** `send_telegram` payload по-прежнему содержит `chat_id`, `text`, `parse_mode`,
|
||||
`disable_notification`; `edit_telegram` payload — `chat_id`, `message_id`, `text`,
|
||||
`parse_mode`. Возвращаемые значения функций не изменились
|
||||
(`send_telegram → message_id|None`, `edit_telegram → EDIT_*`).
|
||||
- **FAIL:** любое из перечисленных полей удалено/переименовано, либо изменился контракт
|
||||
возврата.
|
||||
- **Проверка:** unit-тесты payload + существующие тесты трекера/классификации исходов.
|
||||
|
||||
## AC-6 — never-raise сохранён, pytest зелёный
|
||||
|
||||
- **PASS:** при сетевой/HTTP-ошибке `send_telegram`/`edit_telegram` не бросают исключение
|
||||
(возврат `None`/`EDIT_FAILED`); вся сюита `pytest tests/ -q` зелёная.
|
||||
- **FAIL:** любое исключение наружу или красный pytest.
|
||||
- **Проверка:** существующие тесты never-raise (`test_resilience.py`,
|
||||
`test_telegram_tracker.py`) + полный прогон.
|
||||
|
||||
## AC-7 — документация обновлена в том же PR
|
||||
|
||||
- **PASS:** `CHANGELOG.md` содержит запись об ORCH-080; при необходимости — короткая ремарка
|
||||
в `CLAUDE.md`/`docs/architecture/README.md` о подавлении link-preview.
|
||||
- **FAIL:** функционал изменён, документация не обновлена (Reviewer → REQUEST_CHANGES).
|
||||
76
docs/work-items/ORCH-080/04-test-plan.yaml
Normal file
76
docs/work-items/ORCH-080/04-test-plan.yaml
Normal file
@@ -0,0 +1,76 @@
|
||||
work_item: ORCH-080
|
||||
description: >
|
||||
Подавление Telegram link-preview (disable_web_page_preview: True) в payload
|
||||
send_telegram (sendMessage) и edit_telegram (editMessageText). Сохранить
|
||||
parse_mode HTML, disable_notification, never-raise и контракты возврата.
|
||||
|
||||
tests:
|
||||
- id: TC-01
|
||||
type: unit
|
||||
description: >
|
||||
send_telegram() кладёт "disable_web_page_preview": True в JSON-payload
|
||||
httpx.post(.../sendMessage). Проверка через мок httpx и инспекцию
|
||||
httpx.post.call_args.kwargs["json"].
|
||||
module: tests/test_link_preview_disabled.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-02
|
||||
type: unit
|
||||
description: >
|
||||
edit_telegram() кладёт "disable_web_page_preview": True в JSON-payload
|
||||
httpx.post(.../editMessageText). Проверка через мок httpx и инспекцию
|
||||
payload.
|
||||
module: tests/test_link_preview_disabled.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-03
|
||||
type: unit
|
||||
description: >
|
||||
Регрессия parse_mode: оба payload (sendMessage и editMessageText)
|
||||
по-прежнему содержат "parse_mode": "HTML" — ссылка <a href> остаётся
|
||||
кликабельной (AC-4).
|
||||
module: tests/test_link_preview_disabled.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-04
|
||||
type: unit
|
||||
description: >
|
||||
Регрессия полей send_telegram: payload содержит chat_id, text,
|
||||
parse_mode, disable_notification; disable_notification прокидывается
|
||||
из аргумента (True/False) без изменений (AC-5).
|
||||
module: tests/test_link_preview_disabled.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-05
|
||||
type: unit
|
||||
description: >
|
||||
Контракты возврата не изменились: send_telegram возвращает message_id
|
||||
при ok:true, None при отсутствии креденшелов/ошибке; edit_telegram
|
||||
возвращает EDIT_OK при ok:true (AC-5, AC-6).
|
||||
module: tests/test_link_preview_disabled.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-06
|
||||
type: unit
|
||||
description: >
|
||||
never-raise: при httpx.post бросающем исключение send_telegram->None и
|
||||
edit_telegram->EDIT_FAILED, без проброса исключения (AC-6).
|
||||
module: tests/test_link_preview_disabled.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-07
|
||||
type: integration
|
||||
description: >
|
||||
Полный прогон существующей сюиты трекера/уведомлений остаётся зелёным
|
||||
(нет регрессий bump/edit-логики, классификации исходов, ссылок):
|
||||
pytest tests/test_telegram_tracker.py tests/test_tracker_bump.py
|
||||
tests/test_notify_issue_links.py tests/test_resilience.py.
|
||||
module: tests/test_telegram_tracker.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-08
|
||||
type: integration
|
||||
description: >
|
||||
Вся сюита pytest tests/ -q зелёная (общая регрессия, AC-6).
|
||||
module: tests/
|
||||
expected: PASS
|
||||
Reference in New Issue
Block a user