docs(adr): ADR-091 Telegram 子系統 Round 3 全景審計正式文件
- 11 按鈕 × handler 覆蓋矩陣定版
- 三缺一鐵律(callback格式+handler+能力)升級 ADR 層級
- callback_data 雙格式(nonce vs INFO)正式認定
- Long Polling by design 確認
- approval 三戳鐵律(editMarkup + editText + DB message_id)
- NO_ACTION 不誤標 FAILED 救 MASTER §7.1 #11
對應 commits 877c847 → 4b8be32,git tag v7.3.0
Memory: project_phase7_round3_telegram_subsystem.md
This commit is contained in:
111
docs/adr/ADR-091-telegram-subsystem-round3.md
Normal file
111
docs/adr/ADR-091-telegram-subsystem-round3.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# ADR-091: Telegram 子系統全景審計與 UX 黑洞修復(Phase 7 Round 3)
|
||||
|
||||
**日期**: 2026-04-19
|
||||
**狀態**: ✅ 已實施(commits `877c847` → `4b8be32`,git tag `v7.3.0`)
|
||||
**上游**: [ADR-090 監控盲區治理](./ADR-090-monitoring-blindspot-governance.md)、[MASTER Blueprint §7.1](../superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md)
|
||||
**Memory**: `project_phase7_round3_telegram_subsystem.md`
|
||||
|
||||
## Context(背景)
|
||||
|
||||
2026-04-18 深夜統帥連續截圖 Telegram 卡片異常:按鈕按了無反應、卡片永遠顯示「執行中」、responsibility 欄位顯示「未知」、drift 卡片內文與 description 互相矛盾。統帥原話:「**根本他媽的沒有盤查過所有的 Telegram 的按鈕!你就是做爽的而已!**」
|
||||
|
||||
過往每遇 Telegram bug 都是點對點補丁,從未做過**全景 × 全按鈕型別 × handler 覆蓋矩陣**的完整盤查。本 Round 強制要求:先做全景矩陣,再批次修。
|
||||
|
||||
## Decision(決策)
|
||||
|
||||
### 1. 建立 Telegram callback 按鈕 × Handler 覆蓋矩陣
|
||||
|
||||
11 個按鈕型別 vs handler 覆蓋現況:
|
||||
|
||||
| 按鈕型別 | Callback 格式 | Handler 狀態(修前) | 修後 |
|
||||
|---------|--------------|--------------------|------|
|
||||
| approve / reject / tune / silence | 4-part nonce | ✅ 原有 | ✅ |
|
||||
| view | 2-part INFO | 🔴 未在 INFO_ACTIONS 白名單 | ✅ 加入(TG-1) |
|
||||
| drift_view | 4-part nonce | 🔴 無 handler(UX 黑洞) | ✅ 專屬分派(TG-2) |
|
||||
| drift_adopt | 4-part nonce | 🔴 無 handler | ✅ 呼叫 `drift_adopt_service` |
|
||||
| drift_revert | 4-part nonce | 🔴 無 handler | ✅ 呼叫 `drift_remediator.revert` |
|
||||
| scale / secops_authorize / secops_isolate | 4-part nonce | 🔴 定義但無 handler | ⏸ 下輪補 spec 或移除 |
|
||||
|
||||
### 2. 鐵律:新增按鈕前必通過三缺一檢查
|
||||
|
||||
由 `feedback_no_ghost_buttons.md` 升級為 ADR 層級規範:
|
||||
|
||||
> **發送任何 Telegram callback 按鈕前,必須通過:**
|
||||
> 1. callback_data 格式在 `parse_callback_data` 支援(nonce or INFO)
|
||||
> 2. 有對應 handler 分支
|
||||
> 3. handler 所需能力(MCP / service)真實存在
|
||||
>
|
||||
> **三缺一,絕不發送**。沒有 handler 的按鈕 = UX 黑洞 = 用戶認為系統當機。
|
||||
|
||||
### 3. callback_data 雙格式正式認定
|
||||
|
||||
| 語義 | 格式 | 範例 | 適用 |
|
||||
|------|------|------|------|
|
||||
| 寫操作 | `{action}:{approval_id}:{timestamp}:{random}` | `approve:abc:1234:xyz` | 防重放(nonce) |
|
||||
| 讀操作 | `{action}:{incident_id}` | `view:inc_123` | INFO_ACTIONS 白名單 |
|
||||
| **特例:drift** | 走 nonce 格式,語義讀/寫混合 | `drift_view:abc:1234:xyz` | handle_callback Step 1.85 專屬分派 |
|
||||
|
||||
INFO_ACTIONS 白名單位於 [`security_interceptor.py`](../../apps/api/src/services/security_interceptor.py) line 438。新增讀操作按鈕必須加入此集合。
|
||||
|
||||
### 4. Long Polling 正式採用(非 Webhook)
|
||||
|
||||
- `getWebhookInfo` 回 URL=空是 **by design**
|
||||
- 單 Pod Leader Election(Redis lock)避免多 Pod 搶 getUpdates 409
|
||||
- `/api/v1/telegram/webhook` endpoint 已標註 `[已棄用]`,保留作退路
|
||||
|
||||
### 5. Approval 執行完成三戳鐵律
|
||||
|
||||
approval 執行完後必須同時完成三件事,否則卡片永遠「執行中」:
|
||||
|
||||
1. `editMessageReplyMarkup` 移除按鈕
|
||||
2. `editMessageText` 加上 ✅/❌ 結果 + KM/Playbook 增量戳
|
||||
3. `approval_records.telegram_message_id` 寫入 DB(不只 Redis)
|
||||
|
||||
### 6. NO_ACTION 不是 FAILED
|
||||
|
||||
OpenClaw 決策為 `NO_ACTION`(調查用)時走 noop 分支標 `SUCCESS`,不進 verifier FAILED path,救 MASTER §7.1 #11 auto_execute 成功率。
|
||||
|
||||
### 7. Responsibility 正規化
|
||||
|
||||
primary_responsibility 欄位不可留空/None/invalid;空值一律 fallback `INFRA` 或 `BE`。
|
||||
|
||||
## Consequences(後果)
|
||||
|
||||
### 正面
|
||||
|
||||
- **9 bugs 中 7 修**(TG-1/2/4 + AP-1/2/3 + Extra NO_ACTION),2 延後(TG-3 refactor、TG-5 by-design)
|
||||
- **全景盤點成為標準工作流**:未來新增按鈕/handler 必先畫矩陣
|
||||
- **UX 黑洞鐵律上 ADR**:三缺一絕不發送,防止下次再出現無 handler 按鈕
|
||||
- **NO_ACTION 真實率可測**:MASTER §7.1 #11 不再被誤標污染
|
||||
|
||||
### 負面 / 未完
|
||||
|
||||
- `scale / secops_authorize / secops_isolate` 按鈕仍在定義但無 handler,下輪補 action spec 或移除
|
||||
- TG-3 handler 重複分派(approve 邏輯散落 4 處)為純 refactor,本輪跳過
|
||||
- Webhook endpoint 標註棄用但未刪除(保留退路)
|
||||
|
||||
### 需觀察(24h 真實 traffic)
|
||||
|
||||
```sql
|
||||
-- 三條閉環驗證
|
||||
SELECT COUNT(*) FROM notification_outcomes;
|
||||
SELECT COUNT(*) FROM approval_records WHERE telegram_message_id IS NOT NULL;
|
||||
SELECT COUNT(*) FROM automation_operation_log WHERE operation_type='notification_formatted';
|
||||
```
|
||||
|
||||
## 5 Commits 時序
|
||||
|
||||
1. [`877c847`](https://gitea.wooo.work/owen/awoooi/commit/877c847) feat(telegram): drift 按鈕 3 handler + drift card message_id Redis 存(TG-2 + TG-4)
|
||||
2. [`2e988bd`](https://gitea.wooo.work/owen/awoooi/commit/2e988bd) fix: drift 執行結果 reply_to 原卡片 + audit log
|
||||
3. [`fdce0a3`](https://gitea.wooo.work/owen/awoooi/commit/fdce0a3) fix(approval): NO_ACTION 走 noop 分支標 SUCCESS
|
||||
4. [`68a42a3`](https://gitea.wooo.work/owen/awoooi/commit/68a42a3) refactor(openclaw): 幻覺驗證抽成 helper,sweeper + webhook 雙路徑呼叫
|
||||
5. [`4b8be32`](https://gitea.wooo.work/owen/awoooi/commit/4b8be32) fix: TG-1 INFO_ACTIONS view + AP-1/2/3 approval 三修
|
||||
|
||||
**Git tag**: `v7.3.0` at `4b8be32`
|
||||
|
||||
## 相關文件
|
||||
|
||||
- MASTER §8 Changelog 2026-04-19 條目:`docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md`
|
||||
- Memory 全彙總:`~/.claude/projects/-Users-ogt-awoooi/memory/project_phase7_round3_telegram_subsystem.md`
|
||||
- 鬼魂按鈕鐵律(feedback):`feedback_no_ghost_buttons.md`
|
||||
- 上一輪修復:`project_phase7_round2_flywheel_fixes.md`(ADR-090 實施 Round 2)
|
||||
Reference in New Issue
Block a user