From 85c4e3b4344a198e9a2cac8008866b04f2b6b68a Mon Sep 17 00:00:00 2001 From: OG T Date: Wed, 15 Apr 2026 22:28:39 +0800 Subject: [PATCH] =?UTF-8?q?fix(km):=20=E4=BF=AE=E5=BE=A9=20KM=20=E5=AF=AB?= =?UTF-8?q?=E5=85=A5=E5=85=A8=E7=82=BA=20unknown=20=E7=9A=84=E6=A0=B9?= =?UTF-8?q?=E5=9B=A0=20(=E4=B8=89=E5=80=8B=E7=AF=80=E9=BB=9E)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug-A: approval_execution.py 呼叫不存在的 get_incident() → AttributeError 被 except 吞掉 → alertname/alert_category/affected_services 全用預設值 修復: 改用 get_from_working_memory() + get_from_episodic_memory() 雙路徑 Bug-B: _record_to_incident() 從 PG 還原 Incident 時漏掉 notification_type + alert_category 欄位 → km_conversion 讀到 None 修復: 加入這兩個欄位的還原 Bug-C: main.py working_memory_warmup 重建 Incident 時同樣遺漏 notification_type + alert_category 修復: 同步補上 2026-04-15 Claude Sonnet 4.6 Asia/Taipei --- apps/api/src/main.py | 3 +++ apps/api/src/services/approval_execution.py | 6 +++++- apps/api/src/services/incident_service.py | 3 +++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/apps/api/src/main.py b/apps/api/src/main.py index 5a86089a..28928a8d 100644 --- a/apps/api/src/main.py +++ b/apps/api/src/main.py @@ -276,6 +276,9 @@ async def lifespan(_app: FastAPI) -> AsyncGenerator[None, None]: closed_at=record.closed_at, ttl_days=record.ttl_days, vectorized=record.vectorized, + # ADR-073: 分類欄位必須還原,否則 KM 寫入時全為 "unknown" + notification_type=record.notification_type, + alert_category=record.alert_category, ) if await incident_service.save_to_working_memory(incident): restored += 1 diff --git a/apps/api/src/services/approval_execution.py b/apps/api/src/services/approval_execution.py index 4a45f362..e0ddb8ac 100644 --- a/apps/api/src/services/approval_execution.py +++ b/apps/api/src/services/approval_execution.py @@ -628,7 +628,11 @@ class ApprovalExecutionService: if approval.incident_id: try: from src.services.incident_service import get_incident_service - _inc = await get_incident_service().get_incident(approval.incident_id) + _svc = get_incident_service() + # get_from_working_memory (Redis) → fallback get_from_episodic_memory (PG) + _inc = await _svc.get_from_working_memory(approval.incident_id) + if _inc is None: + _inc = await _svc.get_from_episodic_memory(approval.incident_id) if _inc: if _inc.signals: alertname = _inc.signals[0].labels.get("alertname", "unknown") or "unknown" diff --git a/apps/api/src/services/incident_service.py b/apps/api/src/services/incident_service.py index 5b176a49..faa81a16 100644 --- a/apps/api/src/services/incident_service.py +++ b/apps/api/src/services/incident_service.py @@ -680,6 +680,9 @@ class IncidentService: ttl_days=record.ttl_days, persisted_to_pg=True, # 從 PG 讀取,必為 True vectorized=record.vectorized, + # ADR-073: 分類欄位必須從 DB 還原,否則 KM 寫入時全為 "unknown" + notification_type=record.notification_type, + alert_category=record.alert_category, ) # =========================================================================