Files
awoooi/docs/adr/ADR-055-knowledge-auto-harvesting.md
OG T 15c7f6fcd3 docs(adr): 起草 ADR-054/055/056/057 — Phase 25 三方向架構決策
ADR-054: DIAGNOSE Privacy-First Routing (已批准)
  - _local_fallback_chain 設計決策
  - NEMOTRON privacy_level=local 首席架構師裁示
  - 全部 local 失敗 → REJECT + Telegram

ADR-055: Knowledge Auto-Harvesting (已批准)
  - AUTO_RUNBOOK DRAFT + ANTI_PATTERN PUBLISHED 設計理由
  - compute_hash() 碰撞風險說明
  - Fire-and-forget GC 防護強制規範

ADR-056: Config Drift Detection 四層架構 (已批准)
  - Detector→Analyzer→Interpreter→Remediator 職責邊界
  - AI 只做意圖分析不做修復決策
  - adopt() 暫停 + _recent_reports Phase 1 限制

ADR-057: adopt() Gitea PR API 實作路徑 (草案,待批准)
  - 解決 API Pod git add -A 安全風險
  - PR review 流程保障

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 00:24:50 +08:00

122 lines
3.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ADR-055: Knowledge Auto-HarvestingAUTO_RUNBOOK + ANTI_PATTERN
> **狀態**: ✅ 已批准
> **日期**: 2026-04-04
> **決策者**: 統帥 + 首席架構師
> **首席架構師評分**: 技術背書
> **關聯 ADR**: ADR-052 (AI Provider Registry), ADR-043 (Knowledge Base)
> **實作**: Phase 25 P1 — commit 3455044
---
## 背景
### 問題陳述
AutoRepair 執行修復後,成功/失敗的知識停留在系統日誌中,無法被後續決策利用。特別是:
1. **成功修復** → 修復步驟應被收錄為可參考的 Runbook
2. **失敗修復** → 失敗模式應被記錄以防止重複嘗試相同方法
Knowledge Base 存在但靠人工填寫,形成知識孤島。
---
## 決策
### D1: AUTO_RUNBOOK — 成功修復自動產生草稿 Runbook
```python
# auto_repair_service.py — execute_auto_repair() 成功後
task = asyncio.create_task(gen.generate_runbook(incident, playbook, result))
self._pending_tasks.add(task)
task.add_done_callback(self._pending_tasks.discard)
```
- EntryType: `AUTO_RUNBOOK`
- EntryStatus: `DRAFT`(需要人工審核後才升為 APPROVED
- Nemotron 生成內容,失敗時有最小化 fallback
**理由**: 自動生成的 Runbook 品質未經驗證,保持 DRAFT 讓 SRE 審核,避免錯誤知識被自動採納。
### D2: ANTI_PATTERN — 失敗修復直接發布防災記錄
```python
# auto_repair_service.py — execute_auto_repair() 失敗後
task = asyncio.create_task(
gen.generate_anti_pattern(incident, playbook, fail_result, symptoms_hash)
)
self._pending_tasks.add(task)
task.add_done_callback(self._pending_tasks.discard)
```
- EntryType: `ANTI_PATTERN`
- EntryStatus: `PUBLISHED`(直接發布,無需人工審核)
- 理由:失敗記錄的目的是「防止重蹈覆轍」,早一秒發布早一秒保護
### D3: SymptomPattern.compute_hash() — O(1) 防災閘門
```python
def compute_hash(self) -> str:
key = (
"|".join(sorted(self.alert_names)) + "||"
+ "|".join(sorted(self.affected_services)) + "||"
+ json.dumps(self.label_patterns, sort_keys=True)
)
return hashlib.sha256(key.encode()).hexdigest()[:16]
```
- 16 字元 hex = 2^64 碰撞空間,工程實踐上足夠
- 碰撞發生最壞結果:某次修復被誤攔截,需人工重試——可接受
### D4: evaluate_auto_repair() 加入 ANTI_PATTERN 閘門
```python
# 症狀提取後、Playbook 匹配前
symptoms_hash = symptoms.compute_hash()
anti_patterns = await get_knowledge_service().check_anti_pattern(symptoms_hash, days=7)
if anti_patterns:
return AutoRepairDecision(
can_auto_repair=False,
reason=f"過去 7 天有失敗案例: {anti_patterns[0].title}",
blocked_by="ANTI_PATTERN",
)
```
閘門位置:診斷症狀後、開始執行前,屬於預防性攔截。
### D5: Fire-and-Forget 必須有 GC 防護
所有 `asyncio.create_task()` 必須:
1. 持有引用至 `self._pending_tasks`
2.`done_callback` 中從集合移除
```python
task = asyncio.create_task(coro)
self._pending_tasks.add(task)
task.add_done_callback(self._pending_tasks.discard)
```
成功分支與失敗分支必須對稱實作,不得有遺漏。
---
## 後果
### 正面影響
- Knowledge Base 自動積累修復經驗,形成正向循環
- 失敗模式即時保護,防止重複損耗
- SRE 工作聚焦於審核而非撰寫
### 負面影響 / 風險
- Nemotron 生成的 Runbook 品質參差,需 SRE 審核成本
- ANTI_PATTERN 直接發布,若症狀 hash 碰撞可能誤攔正常修復
### 未決事項Backlog
- I2: `nvidia.chat()` system prompt 格式是否符合 NIM message format 規範
- M1: ANTI_PATTERN 是否需要 Telegram 確認視窗human-in-the-loop 選項)
- M2: symptoms_hash 16 字元截斷的碰撞監控機制