Files
awoooi/docs/adr/ADR-086-telegram-ui-notification-cleanup.md
OG T ba8cf6105d docs(adr): ADR-086 Telegram UI 清洗規範 + ADR-087 AutoApprove kubectl 閘門
ADR-086: Telegram 通知卡片 UI 清洗規範
- _parse_debate_summary() 設計決定與各 TYPE 欄位清洗規則
- TYPE-3 鍵盤重構:批准/拒絕永遠第一行
- 技術債:_parse_debate_summary 提升模組層級(P1-1)

ADR-087: AutoApprove 安全強化 — kubectl 強制執行閘門
- 條件 1d 設計:_raw_action 語意 + NO_EXECUTABLE_ACTION reason
- Solver Nemo 格式 kubectl 驗證
- 降級指令改為真實 kubectl 唯讀調查
- min_trust_score=0 保留理由記錄(TrustEngine 記憶體持久化技術債)
- P0-2 風險記錄:kubectl exec 未加入 _DESTRUCTIVE_PATTERNS

2026-04-17 ogt + Claude Sonnet 4.6(亞太): Session 技術債清理

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 15:25:34 +08:00

3.7 KiB
Raw Blame History

ADR-086: Telegram 通知卡片 UI 清洗規範

狀態: 已接受
日期: 2026-04-17
作者: ogt + Claude Sonnet 4.6
關聯: ADR-071通知類型定義、ADR-075Telegram 通知標準)


背景

Phase 2 多 Agent 協作ADR-082上線後5-Agent debate 的輸出格式為:

診斷:{hypothesis};方案:{action};安全審查:{verdict};質疑:{critic}

decision_manager.py 路由層在準備 Telegram 卡片資料時,多個分支直接截斷 reasoning 字串,導致完整 debate_summary 傾倒到 UI 欄位,使用者在 Telegram 看到:

  • TYPE-1純資訊message=reasoning[:200] → 顯示「診斷:...;方案:...;安全審查:...;質疑:...」
  • TYPE-4DConfig Driftdiff_summary=description[:500] → 顯示 LLM 輸出的 JSON 原文
  • TYPE-3人工審核root_cause=_smt(reasoning, 500) → 顯示完整 debate_summary 前 500 字
  • TYPE-5S資安threat_behavior=reasoning[:150] → 顯示 debate_summary 開頭

決策

1. _parse_debate_summary() 標準化清洗函數

decision_manager.py 函數體內定義(後續應提升為模組層級 — P1-1 技術債):

def _parse_debate_summary(reasoning: str) -> dict[str, str]:
    result = {"diagnosis": "", "plan": "", "review": "", "critic": ""}
    for part in reasoning.split(""):
        part = part.strip()
        if part.startswith("診斷:"):   result["diagnosis"] = part[3:]
        elif part.startswith("方案:"): result["plan"] = part[3:]
        elif part.startswith("安全審查:"): result["review"] = part[5:]
        elif part.startswith("質疑:"): result["critic"] = part[3:]
    return result

2. 各 TYPE 分支修正規則

TYPE 欄位 修正前 修正後
TYPE-1 message reasoning[:200] _parse_debate_summary(reasoning)["diagnosis"] + _smt(..., 200)
TYPE-4D diff_summary description[:500] JSON Catcherjson.loads → 格式化;失敗 → description[:500]
TYPE-3 root_cause _smt(reasoning, 500) _parse_debate_summary(reasoning)["diagnosis"] + _smt(..., 300)
TYPE-5S threat_behavior reasoning[:150] _parse_debate_summary(reasoning)["diagnosis"] + _smt(..., 150)

3. TYPE-3 鍵盤按鈕重構

原問題動態按鈕K8s 操作類)可能蓋台 [批准][拒絕],使審核按鈕不可見。

新規則telegram_gateway.py:_build_inline_keyboard()

  1. 第一行永遠是 [✅ 批准][❌ 拒絕](無條件)
  2. 第二行以後K8s/DB/Host 類操作按鈕(每行最多 3 個)
  3. 最後一行:[📋 詳情][🔕 忽略]

移除 requires_human_approval 參數——由有無 _dynamic_buttons 決定佈局,不再需要額外條件。


後果

  • TYPE-1:純資訊通知只顯示 AI 診斷摘要,不顯示完整辯論過程
  • TYPE-3:批准/拒絕永遠可見,不會被操作按鈕覆蓋
  • TYPE-4DConfig Drift 卡片顯示結構化的「建議操作/說明/回滾方案」三段式
  • TYPE-5S:資安告警的威脅行為欄位只顯示診斷結論

技術債

項目 優先 說明
_parse_debate_summary 提升為模組層級 P1 目前定義在函數體內,無法在同模組其他地方重用
import re as _re 移出函數體 P2 目前在函數體內 import每次呼叫重建閉包

相關 Commits

Commit 說明
6baa2e9 TYPE-8M 三連修(第一波)
418d735 BUG-A TYPE-1 + BUG-B TYPE-4D第二波
f421e65 BUG-C TYPE-3 + 按鈕置頂(第三波)
fb225c5 P2-2 TYPE-5S secops 分支清洗Code Review 補完)