From a482b36dae32be43a54d71bd13029dbb3d712571 Mon Sep 17 00:00:00 2001 From: claude-bot Date: Tue, 9 Jun 2026 01:19:58 +0300 Subject: [PATCH] architect(ET): auto-commit from architect run_id=414 --- .../ADR-001-disable-telegram-link-preview.md | 63 +++++++++++++++++++ docs/work-items/ORCH-080/10-tech-risks.md | 22 +++++++ 2 files changed, 85 insertions(+) create mode 100644 docs/work-items/ORCH-080/06-adr/ADR-001-disable-telegram-link-preview.md create mode 100644 docs/work-items/ORCH-080/10-tech-risks.md diff --git a/docs/work-items/ORCH-080/06-adr/ADR-001-disable-telegram-link-preview.md b/docs/work-items/ORCH-080/06-adr/ADR-001-disable-telegram-link-preview.md new file mode 100644 index 0000000..0ff2088 --- /dev/null +++ b/docs/work-items/ORCH-080/06-adr/ADR-001-disable-telegram-link-preview.md @@ -0,0 +1,63 @@ +# ADR-001: Подавление Telegram link-preview в низкоуровневых примитивах нотификаций + +## Статус +Accepted + +## Контекст +С ORCH-067 карточка трекера и notify-сообщения несут кликабельный номер задачи +`ORCH-NNN`. Telegram +Bot API по умолчанию (при отсутствии ключа `disable_web_page_preview`) разворачивает +web-page-preview для первой ссылки в сообщении — под каждым сообщением трекера +раскрывается баннер «Plane — Modern project management». В дефолтном режиме `bump` +(ORCH-067) карточка пересоздаётся на каждом переходе, поэтому баннер дублируется на +каждой задаче и каждом обновлении, засоряя ленту (жалоба Owner, 08.06). + +Код-аудит (`src/notifications.py`) подтвердил причину: JSON-payload обоих +низкоуровневых примитивов — `send_telegram()` (`POST /sendMessage`, стр. 55-60) и +`edit_telegram()` (`POST /editMessageText`, стр. 168-173) — **не содержит** ключ +`disable_web_page_preview`. Все вышестоящие нотификации (`update_task_tracker` в обоих +режимах, `notify_approve_requested`, `notify_error`, alert'ы стадий из +`launcher`/`stage_engine`) проходят через эти два примитива. + +## Решение +Добавить `"disable_web_page_preview": True` в JSON-payload `httpx.post` обоих примитивов: +`send_telegram()` и `edit_telegram()`. Изменение — **на уровне низкоуровневого +примитива**, а не на уровне каждого вызова, потому что: + +1. **Единая точка** — все исходящие сообщения трекера/нотификаций идут через эти две + функции; правка двух строк гасит баннер у ВСЕХ потребителей (карточка `bump`/`edit`, + notify-хелперы, alert'ы) без изменения их кода. +2. **Безусловно, без флага** — превью Plane не нужно никому (это не данные, а навигация + по ссылке, которая остаётся кликабельной). Kill-switch не вводится: риск регрессии + нулевой, правка обратима одной строкой. Это согласуется с принципом «минимум + зависимостей/конфигурации». +3. **Top-level флаг, а не `link_preview_options.is_disabled`** — top-level + `disable_web_page_preview` остаётся валиден и обратносовместим в Bot API; это + минимальная правка без введения вложенной структуры. + +`parse_mode: "HTML"` сохраняется в обоих payload (иначе `` перестанет +рендериться — ссылка должна остаться кликабельной). `disable_notification`, +bump/edit-логика, repoint `tracker_message_id`, delete-семантика, контракты возврата +(`send_telegram → message_id|None`, `edit_telegram → EDIT_*`) — не затрагиваются. + +## Последствия +**Плюсы:** +- Баннер link-preview исчезает под карточкой трекера (оба режима) и под всеми + notify/alert-сообщениями — одна правда в двух примитивах. +- Ссылка на задачу остаётся кликабельной (HTML сохранён). +- Нулевой риск: ключ аддитивный, контракты примитивов и инвариант «одна карточка на + задачу» не меняются; `never-raise` (`try/except`) сохранён. + +**Минусы / ограничения:** +- Поведение безусловное — нет конфигурации «вернуть превью». Сознательный выбор: + превью трекера не имеет ценности, флаг был бы лишней поверхностью. + +**Не затрагивается:** `STAGE_TRANSITIONS`, реестр `QG_CHECKS`, схема БД, `parse_mode`, +`disable_notification`, транспортные хелперы `delete_telegram`/repoint-логика. Глобальный +ADR не требуется — решение локально для `src/notifications.py`, не сквозное. + +## Self-hosting +Изменение не требует немедленного рестарта прод-контейнера и не меняет топологию. +Деплой — штатный через staging (8501) → `Confirm Deploy` (ORCH-059). По ORCH-026 +(сериализация merge одного репо) задача мержится после освобождения конвейера +`orchestrator` (координация с ORCH-074 — см. BRD §7). diff --git a/docs/work-items/ORCH-080/10-tech-risks.md b/docs/work-items/ORCH-080/10-tech-risks.md new file mode 100644 index 0000000..e68556c --- /dev/null +++ b/docs/work-items/ORCH-080/10-tech-risks.md @@ -0,0 +1,22 @@ +# 10-Tech Risks — ORCH-080 + +Work Item ID: ORCH-080 +Зона: `src/notifications.py` (две строки в `send_telegram`/`edit_telegram`) + +Косметическая правка UX (LOW). Топология, схема БД, стадии, QG — не меняются. +Риск регрессии оценён как **нулевой**; ниже — остаточные пункты для внимания. + +| # | Риск | Вероятность | Влияние | Митигация | +|---|------|-------------|---------|-----------| +| R-1 | Опечатка ключа/значения (`disable_web_page_preview`) — баннер не гаснет | Низкая | Низкое (косметика) | unit-тест AC-1/AC-2 инспектирует `httpx.post.call_args.kwargs["json"]`; ручная верификация на staging (AC-3) | +| R-2 | Случайное удаление `parse_mode: "HTML"` → ссылка `` ломается | Очень низкая | Среднее (теряется кликабельность) | AC-4: unit-тест на наличие `parse_mode: "HTML"` в обоих payload; `test_notify_issue_links.py` остаётся зелёным | +| R-3 | Merge-конфликт с ORCH-067/ORCH-074 в `src/notifications.py` | Низкая | Низкое | По ORCH-026 сериализация merge одного репо; запуск после доезда ORCH-74 в `main` (BRD §7); pre-merge rebase (ORCH-043) | +| R-4 | Регрессия контракта возврата примитивов (`message_id|None` / `EDIT_*`) | Очень низкая | Среднее | Правка строго аддитивна (новый ключ в payload), возвраты не трогаются; AC-5 + существующие тесты трекера | +| R-5 | Telegram депрекейтит top-level `disable_web_page_preview` в пользу `link_preview_options` | Очень низкая | Низкое (forward-compat) | Top-level флаг остаётся валиден и обратносовместим; миграция на `link_preview_options.is_disabled` — отдельная задача при необходимости | + +## Инварианты, которые НЕЛЬЗЯ нарушить +- `never-raise` обоих примитивов (`try/except` сохранён). +- `parse_mode: "HTML"` в обоих payload (иначе `` ломается). +- `disable_notification` в `send_telegram` (карточка тихая). +- Инвариант «одна карточка на задачу» (bump/edit) — не затрагивается. +- Контракты возврата: `send_telegram → message_id|None`, `edit_telegram → EDIT_*`.