From 418d73540bb920ab21a8d401fed033522225fa27 Mon Sep 17 00:00:00 2001 From: OG T Date: Fri, 17 Apr 2026 14:14:04 +0800 Subject: [PATCH] =?UTF-8?q?fix(telegram):=20BUG-A=20TYPE-1=20+=20BUG-B=20T?= =?UTF-8?q?YPE-4D=20=E8=B3=87=E6=96=99=E5=89=8D=E8=99=95=E7=90=86=EF=BC=88?= =?UTF-8?q?ADR-075=20UI=20=E7=AC=AC=E4=BA=8C=E6=B3=A2=E4=BF=AE=E5=BE=A9?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BUG-A (TYPE-1 純資訊通知): - 舊: message=reasoning[:200] → debate_summary 全文傾倒(診斷/方案/審查/質疑一起出現) - 新: _parse_debate_summary(reasoning) 只取 diagnosis 欄位 + _smt 截斷 200 字 BUG-B (TYPE-4D Config Drift): - 舊: diff_summary=description[:500] → LLM 輸出的 JSON 原文直接顯示在
 區塊
- 新: JSON Catcher — json.loads(description) 成功則格式化「📝建議操作/📖說明/⏪回滾方案」
       失敗 (JSONDecodeError/TypeError/AttributeError) → 平滑降級為純文字截斷

僅修改 decision_manager.py 路由準備段,telegram_gateway.py 模板層零改動。

Co-Authored-By: Claude Sonnet 4.6 
---
 apps/api/src/services/decision_manager.py | 25 +++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/apps/api/src/services/decision_manager.py b/apps/api/src/services/decision_manager.py
index 79a12c4b..5d725667 100644
--- a/apps/api/src/services/decision_manager.py
+++ b/apps/api/src/services/decision_manager.py
@@ -21,6 +21,7 @@ Decision Manager - Phase 6.5 非同步決策狀態機
 """
 
 import asyncio
+import json
 from datetime import UTC, datetime
 from enum import Enum
 from typing import Any, Protocol, runtime_checkable
@@ -312,24 +313,44 @@ async def _push_decision_to_telegram(
         if _notif_type == NotificationType.TYPE_1:
             # 純資訊通知 — 無按鈕
             # 2026-04-12 ogt: Incident 沒有 title 欄位,用 alertname
+            # 2026-04-17 ogt + Claude Sonnet 4.6: BUG-A 修復 — 只取 diagnosis 欄位
+            # 舊:message=reasoning[:200] → 整條 debate_summary 生文字傾倒
+            # 新:解析 debate_summary,只取「診斷:...」部分給 SRE 看
             _info_title = (
                 incident.signals[0].labels.get("alertname", "") or
                 incident.signals[0].alert_name
             ) if incident.signals else "告警通知"
+            _parsed_info = _parse_debate_summary(reasoning)
+            _info_msg = _smt(_parsed_info.get("diagnosis") or description, 200)
             tg_result = await gateway.send_info_notification(
                 incident_id=incident.incident_id,
                 title=_info_title or "告警通知",
-                message=reasoning[:200] if reasoning else description[:200],
+                message=_info_msg,
                 alertname=incident.signals[0].labels.get("alertname", "") if incident.signals else "",
                 severity="info",
             )
         elif _notif_type == NotificationType.TYPE_4_DRIFT:
             # Config Drift 專屬卡片
+            # 2026-04-17 ogt + Claude Sonnet 4.6: BUG-B JSON Catcher
+            # LLM 可能輸出 JSON 結構({"action_title":"...","description":"...","rollback":"..."})
+            # 解析成功 → 格式化可讀文字;失敗 → 平滑降級為原始截斷字串(不可拋出 Exception)
+            try:
+                _drift_data = json.loads(description)
+                _parts: list[str] = []
+                if _drift_data.get("action_title"):
+                    _parts.append(f"📝 建議操作:{_drift_data['action_title']}")
+                if _drift_data.get("description"):
+                    _parts.append(f"📖 說明:{_smt(_drift_data['description'], 200)}")
+                if _drift_data.get("rollback"):
+                    _parts.append(f"⏪ 回滾方案:{_smt(_drift_data['rollback'], 100)}")
+                _diff_text = "\n".join(_parts) if _parts else description[:500]
+            except (json.JSONDecodeError, TypeError, AttributeError):
+                _diff_text = description[:500]
             tg_result = await gateway.send_drift_card(
                 incident_id=incident.incident_id,
                 approval_id=approval_id,
                 resource_name=target[:50],
-                diff_summary=description[:500],
+                diff_summary=_diff_text,
             )
         elif _notif_type == NotificationType.TYPE_8M or _alert_category in ("alertchain_health", "flywheel_health"):
             # TYPE-8M:飛輪/告警鏈路健康異常,發到個人 DM(不發群組)