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

3.7 KiB
Raw Blame History

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

# 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 — 失敗修復直接發布防災記錄

# 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) 防災閘門

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 閘門

# 症狀提取後、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 中從集合移除
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 字元截斷的碰撞監控機制