# ADR-078: GAP-A4 規則模板 Placeholder 解析強化

> **日期**: 2026-04-14（台北傍晚）  
> **狀態**: ✅ Accepted  
> **作者**: Claude Sonnet 4.6（首席架構師）+ 統帥戰場偵察
> **相關**: ADR-064 Rule Engine、ADR-077 MASTER 藍圖收案、GAP-A1 kubectl 注入防護

---

## 問題

MASTER 藍圖收案後，統帥 log 巡察發現**真正的隱性病灶**：

```
auto_execute_blocked_unresolved_placeholder
  action: kubectl rollout restart deployment HostHighCpuLoad   ← target=alertname!
  action: kubectl rollout restart deployment unknown
  action: kubectl scale deployment unknown --replicas=3
```

大量告警在規則引擎路徑產生垃圾指令 → GAP-A1 防注入閘攔下 → 自動修復卡死 → **飛輪沉默 8.3 小時**。

MASTER 藍圖未涵蓋此缺口，命名為 **GAP-A4：規則 Action 模板 Placeholder 解析缺漏**。

---

## 根因

`alert_rule_engine._extract_vars()` 解析邏輯在 Prometheus 告警**缺 `deployment` label** 時：
- 退回 `alertname` 或 `"unknown"` 作為 `target`
- 填入 `{target}` placeholder → 產生 `kubectl rollout restart deployment HostHighCpuLoad`

---

## 決策

### 三層防護

1. **新增 `_strip_pod_suffix()`** — Pod 名稱還原 Deployment/StatefulSet base name
   - Deployment: `awoooi-api-7d6b776f78-4sgjl` → `awoooi-api`
   - StatefulSet: `postgresql-0` → `postgresql`

2. **新增 `_is_bad_target()`** — 垃圾 target 識別
   - 空/unknown/none/null
   - 等於 alertname 本身
   - IP:port、純 IP、含空白/括號/引號

3. **重寫 `_extract_vars()`** — 多層 label 查找（權威優先）
   `deployment` > `app` > `statefulset` > `pod(去後綴)` > `container` > `service` > `target_resource`

4. **`match_rule()` 後置雙驗證**
   - bad target → 清空 `kubectl_command` → 降級 LLM
   - 殘留 `{` 或 `}` → 清空 `kubectl_command` → 降級 LLM

### 降級策略

規則引擎清空 `kubectl_command` 後，`decision_manager` 會自然降級到 LLM 路徑（OpenClaw/NemoTron），LLM 有能力從 log 內容推理真實 deployment 名稱。若 LLM 也無解，進 TYPE-4 人工扶梯。

---

## 結果

- Commit `10b74af`
- 33 個新單元測試，214/214 回歸全綠
- LOG: `rule_kubectl_command_discarded_bad_target` 取代 `auto_execute_blocked_unresolved_placeholder`
- 飛輪恢復運轉可能性大幅提升（LLM 會接手處理無 deployment label 的告警）

---

## 教訓

1. **防注入閘是盡責的守門員**，但會遮蔽上游 bug。遇到大量攔截日誌必須追上游。
2. **測試告警需涵蓋缺 label 的 sad path**。原單元測試只測 happy path。
3. **log 監控不能取代 metrics 告警**。`auto_execute_blocked_unresolved_placeholder` 累積 8.3 小時才被人工發現，應加 Prometheus 告警規則。

---

## 後續

- [ ] 加 Prometheus 告警規則：`rule_kubectl_command_discarded_bad_target` rate > 5/min 觸發 TYPE-8M flywheel_health
- [ ] 補 E2E 測試：真實 Alertmanager 發 HostHighCpuLoad → 驗證 target 正確降級
- [ ] 檢查其他規則（如 SSH 路徑）是否有類似 placeholder 解析問題

---

## 相關

- Memory: [feedback_placeholder_resolution_rule.md](~/.claude/projects/-Users-ogt-awoooi/memory/feedback_placeholder_resolution_rule.md)
- 測試: `apps/api/tests/test_gap_a4_placeholder_resolution.py`
- 源碼: `apps/api/src/services/alert_rule_engine.py:94-180`

*Accepted by 統帥 @ 2026-04-14 台北深夜*
