feat(api): Sprint 4 Phase A+B — 告警處置統計資料層+寫入層

Phase A: 資料層
- A1: IncidentFrequencyStats 新增 4 欄位 (human_approved/manual_resolved/cold_start_trust/total_resolution)
- A2: AnomalyCounter.record_disposition() — Redis HINCRBY 原子遞增
- A3: get_disposition_stats() — HGETALL 回傳處置分佈
- AnomalyFrequency dataclass 擴充 + to_dict() 同步
- _record_anomaly_impl() 整合 disposition stats

Phase B: 寫入層觸發點接線
- B1: 自動修復成功 → record_disposition("auto_repair")
- B2: 冷啟動信任成功 → record_disposition("cold_start_trust")
  - AutoRepairDecision 新增 is_cold_start flag
  - execute_auto_repair() 接收並區分處置類型
- B3: 人工批准執行成功 → record_disposition("human_approved")
  - 新增 _get_anomaly_key_from_approval() helper
- B4: 手動處理推斷 → resolve_incident() 排除法判定
  - 若 resolved 且無 auto/human/cold_start 紀錄 → manual_resolved

安全設計: 所有 disposition 記錄走 try/except,失敗不阻塞主流程

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
OG T
2026-04-07 11:54:46 +08:00
parent e82d3802c5
commit 9253281d46
6 changed files with 195 additions and 0 deletions

View File

@@ -245,6 +245,28 @@ class IncidentFrequencyStats(BaseModel):
description="最後一次修復是否成功",
)
# 2026-04-07 Claude Code: Sprint 4 — 告警處置統計 (A1)
human_approved_count: int = Field(
default=0,
ge=0,
description="人工按批准後執行次數",
)
manual_resolved_count: int = Field(
default=0,
ge=0,
description="無系統修復紀錄但 resolved 次數",
)
cold_start_trust_count: int = Field(
default=0,
ge=0,
description="首次信任自動放行次數",
)
total_resolution_count: int = Field(
default=0,
ge=0,
description="總處置次數 (auto + human + manual + cold_start)",
)
# =============================================================================
# Incident Outcome (CPO 要求:回饋循環)