fix(code-review): P0-1 action fallback 語意修正 + P1-2 reason enum + P2-2 secops 清洗
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 10m7s
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 10m7s
Code Review 發現 (2026-04-17 首席架構師審查):
P0-1 auto_approve.py 條件 1d 語意修正:
- 原:用 `action` 變數(已 fallback = action or kubectl_command)做 kubectl 判斷
→ action="" + kubectl_command="kubectl get pods" → action="kubectl get pods" → 1d 通過
→ _kubectl_cmd 與 action 同值(重複判斷同一來源),掩蓋 action 本身是自然語言的情況
- 修:改用 proposal_data.get("action", "") 原始值(_raw_action)
→ 直接檢查 action 欄位本身,邏輯語意明確
P1-2 auto_approve.py NO_EXECUTABLE_ACTION 新增:
- 新增 AutoApproveReason.NO_EXECUTABLE_ACTION enum 值
- 條件 1d 改用此 reason(原 NO_PLAYBOOK 語意為「無匹配 Playbook」,不適用此場景)
- 避免污染 KM 飛輪學習資料的根因分類(ADR-068)
P2-2 decision_manager.py secops 分支:
- threat_behavior 改用 _parse_debate_summary → 取 diagnosis 欄位
- 與 BUG-A/BUG-C 修復一致,不再傾倒完整 debate_summary 前 150 字
ADR-082: Phase 2 多 Agent 協作
2026-04-17 ogt + Claude Sonnet 4.6(亞太): Code Review 後修正
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -50,6 +50,7 @@ class AutoApproveReason(str, Enum):
|
||||
CRITICAL_OPERATION = "critical_operation" # 關鍵操作
|
||||
LOW_TRUST = "low_trust" # 信任不足
|
||||
NO_PLAYBOOK = "no_playbook" # 無匹配 Playbook
|
||||
NO_EXECUTABLE_ACTION = "no_executable_action" # action 為自然語言,無法執行
|
||||
LOW_SUCCESS_RATE = "low_success_rate" # Playbook 成功率不足
|
||||
INSUFFICIENT_HISTORY = "insufficient_history" # 執行歷史不足
|
||||
|
||||
@@ -294,13 +295,17 @@ class AutoApprovePolicy:
|
||||
# 根因:Solver 經 OpenClaw Nemo 路徑輸出「重啟 Crash Looping Pod」等自然語言
|
||||
# action 非空 → 條件 1c 通過 → auto_approved=True
|
||||
# 但 kubectl_command 為空 → 實際無法執行 → incident 卡在 investigating
|
||||
# 修復:action 必須含 kubectl 關鍵字才可自動執行,否則降級人工審核
|
||||
# 修復:直接讀 proposal_data["action"] 原始值(非 fallback 後的 action 變數)
|
||||
# 避免「action 空 → fallback 成 kubectl_command → action 含 kubectl → 誤放行」
|
||||
# Code Review 2026-04-17: P0-1 修正 action fallback 語意混淆
|
||||
# P1-2 改用 NO_EXECUTABLE_ACTION(避免污染 KM 飛輪學習資料)
|
||||
_raw_action = proposal_data.get("action", "") or ""
|
||||
_kubectl_cmd = proposal_data.get("kubectl_command", "") or ""
|
||||
_has_kubectl = "kubectl" in action.lower() or "kubectl" in _kubectl_cmd.lower()
|
||||
_has_kubectl = "kubectl" in _raw_action.lower() or "kubectl" in _kubectl_cmd.lower()
|
||||
if not _has_kubectl:
|
||||
return self._reject(
|
||||
reason=AutoApproveReason.NO_PLAYBOOK,
|
||||
detail=f"Action '{action[:60]}' is natural language — no kubectl command, requires human review",
|
||||
reason=AutoApproveReason.NO_EXECUTABLE_ACTION,
|
||||
detail=f"Action '{_raw_action[:60] or _kubectl_cmd[:60]}' is natural language — no kubectl command, requires human review",
|
||||
risk_level=risk_level,
|
||||
trust_score=trust_score,
|
||||
confidence=confidence,
|
||||
|
||||
@@ -381,7 +381,7 @@ async def _push_decision_to_telegram(
|
||||
alertname=_alertname,
|
||||
threat_level=_threat_level,
|
||||
resource=target[:60],
|
||||
threat_behavior=reasoning[:150] if reasoning else description[:150],
|
||||
threat_behavior=_smt(_parse_debate_summary(reasoning).get("diagnosis") or reasoning, 150) if reasoning else description[:150],
|
||||
)
|
||||
elif _alert_category == "business":
|
||||
# TYPE-6B:業務/FinOps 資訊告警 — 發到 SRE 群組(無審核按鈕)(ADR-075 Step-5)
|
||||
|
||||
Reference in New Issue
Block a user