From 2f5986df5c3ede68a87ff6a18c3c61b044adfee7 Mon Sep 17 00:00:00 2001 From: OG T Date: Thu, 26 Mar 2026 19:09:08 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20ADR=20=E6=95=B4=E7=90=86=E8=88=87?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=20(021-029)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ADR 編號修正: - ADR-023 failure-auto-repair → ADR-028 - ADR-025 cicd-ai-integration → ADR-029 新增 ADR: - ADR-021: Playbook 更新驗證 - ADR-022: Sentry 整合架構 - ADR-027: Incident-Approval 同步 - ADR-028: 失敗自動修復閉環 - ADR-029: CI/CD AI 整合 (原 ADR-025) 更新: - ADR-018: LLM 測試策略狀態更新 Co-Authored-By: Claude Opus 4.5 --- docs/adr/ADR-018-llm-testing-strategy.md | 26 +- .../adr/ADR-021-playbook-update-validation.md | 79 +++++ ...ADR-022-sentry-integration-architecture.md | 144 +++++++++ docs/adr/ADR-027-incident-approval-sync.md | 243 +++++++++++++++ docs/adr/ADR-028-failure-auto-repair-loop.md | 282 ++++++++++++++++++ ...tion.md => ADR-029-cicd-ai-integration.md} | 2 +- 6 files changed, 774 insertions(+), 2 deletions(-) create mode 100644 docs/adr/ADR-021-playbook-update-validation.md create mode 100644 docs/adr/ADR-022-sentry-integration-architecture.md create mode 100644 docs/adr/ADR-027-incident-approval-sync.md create mode 100644 docs/adr/ADR-028-failure-auto-repair-loop.md rename docs/adr/{ADR-025-cicd-ai-integration.md => ADR-029-cicd-ai-integration.md} (98%) diff --git a/docs/adr/ADR-018-llm-testing-strategy.md b/docs/adr/ADR-018-llm-testing-strategy.md index 5ffa9afe..2de1458a 100644 --- a/docs/adr/ADR-018-llm-testing-strategy.md +++ b/docs/adr/ADR-018-llm-testing-strategy.md @@ -2,7 +2,7 @@ | 屬性 | 值 | |------|-----| -| **狀態** | 提案中 | +| **狀態** | 延緩 (Deferred) - 方案 A 先行 | | **建立日期** | 2026-03-26 | | **決策者** | 首席架構師 + 統帥 | | **關聯** | Phase 12.3, #68, #69 | @@ -170,3 +170,27 @@ async def test_semantic_similarity(llm_response, golden_response): - [LLM Evaluation Best Practices](https://www.anthropic.com/research/evaluations) - [Property-Based Testing](https://hypothesis.readthedocs.io/) - [Sentence Transformers](https://www.sbert.net/) + +--- + +## 2026-03-26 決策更新 + +**狀態**: 延緩 (Deferred) + +**實際採用方案**: 方案 A - 最小改動優先 + +| 項目 | 實作內容 | +|------|---------| +| 確定性參數 | `temperature: 0.0`, `seed: 42` | +| CI 分層 | LLM 測試移至 Nightly | +| 超時調整 | 300 秒 (CPU 推理) | +| 繁體中文 | System Prompt 強制繁中 | + +**原因**: +1. 三層策略實作成本高 (~1000 行代碼) +2. 方案 A 已解決 CI 不穩定問題 +3. 優先確保 CI 穩定,後續再評估是否需要完整框架 + +**評估文件**: `docs/evaluations/2026-03-26_llm_testing_evaluation.md` + +**後續**: 若方案 A 效果良好,此 ADR 維持 Deferred;若仍有問題,再實施三層策略 diff --git a/docs/adr/ADR-021-playbook-update-validation.md b/docs/adr/ADR-021-playbook-update-validation.md new file mode 100644 index 00000000..6335558f --- /dev/null +++ b/docs/adr/ADR-021-playbook-update-validation.md @@ -0,0 +1,79 @@ +# ADR-021: Playbook 更新驗證策略 + +| 屬性 | 值 | +|------|-----| +| **狀態** | Accepted | +| **建立日期** | 2026-03-26 | +| **決策者** | 首席架構師 | +| **關聯** | Phase 8 P1 修復, leWOOOgo 積木化原則 | + +## 背景 + +Router 層 (`playbooks.py`) 使用 `setattr()` 動態更新 Playbook 欄位,繞過 Pydantic 驗證: + +```python +# ❌ 問題代碼 (Router 層) +update_data = request.model_dump(exclude_unset=True) +for field, value in update_data.items(): + setattr(playbook, field, value) # 無驗證! +``` + +問題: +1. **資料完整性** - 非法狀態值可直接寫入 +2. **違反分層** - Router 層執行業務邏輯 +3. **安全風險** - 可修改 `playbook_id`, `success_count` 等欄位 + +## 決策 + +將更新邏輯移至 Service 層,實作 `update_with_validation()` 方法。 + +### 驗證規則 + +| 規則 | 說明 | +|------|------| +| **禁止修改欄位** | `playbook_id`, `created_at`, `success_count`, `failure_count`, `last_used_at` | +| **狀態轉換** | DRAFT → APPROVED (允許), APPROVED → DEPRECATED (允許), 反向 (禁止) | +| **DEPRECATED 狀態** | 不可修改任何欄位 | + +### 實作 + +```python +# ✅ Service 層 (playbook_service.py) +async def update_with_validation( + self, + playbook_id: str, + update_data: dict, +) -> Playbook | None: + # 1. 過濾禁止修改的欄位 + # 2. 驗證狀態轉換 + # 3. 應用更新 + # 4. 儲存 +``` + +```python +# ✅ Router 層 (playbooks.py) +updated = await service.update_with_validation( + playbook_id=playbook_id, + update_data=request.model_dump(exclude_unset=True), +) +``` + +## 影響 + +| 檔案 | 變更 | +|------|------| +| `src/services/playbook_service.py` | 新增 `update_with_validation()` | +| `src/api/v1/playbooks.py` | 改用 Service 方法 | + +## 替代方案 + +| 方案 | 優點 | 缺點 | 決定 | +|------|------|------|------| +| 維持現狀 (setattr) | 無需改動 | 繞過驗證 | ❌ | +| Pydantic validator | 自動驗證 | 無法檢查狀態轉換 | ❌ | +| **Service 層驗證** | 完整控制 | 需新增方法 | ✅ | + +## 相關 + +- ADR-003: leWOOOgo 積木化架構 +- Skill 02: leWOOOgo Backend Core diff --git a/docs/adr/ADR-022-sentry-integration-architecture.md b/docs/adr/ADR-022-sentry-integration-architecture.md new file mode 100644 index 00000000..b6f66290 --- /dev/null +++ b/docs/adr/ADR-022-sentry-integration-architecture.md @@ -0,0 +1,144 @@ +# ADR-022: Sentry 整合架構 + +| 項目 | 內容 | +|------|------| +| **狀態** | ✅ 已採用 | +| **日期** | 2026-03-26 | +| **決策者** | 首席架構師 + 統帥 | +| **Phase** | Phase 10 | + +## 背景 + +AWOOOI 需要完整的錯誤追蹤能力,補強 SignOz APM 的不足: +- SignOz 專注效能監控 (Traces, Metrics) +- Sentry 專注錯誤追蹤 (Stacktrace, Context, Session Replay) + +## 決策 + +採用 **BFF + AI 分析** 三層架構: + +``` +┌─────────────────────────────────────────────────────────────┐ +│ AWOOOI Web UI │ +│ /errors 頁面 (React + next-intl) │ +└─────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ AWOOOI API (BFF Layer) │ +│ Router: /api/v1/errors/* │ +│ Service: SentryService + ErrorAnalyzerService │ +└─────────────────────────────────────────────────────────────┘ + │ + ┌───────────────┼───────────────┐ + ▼ ▼ +┌──────────────────────┐ ┌──────────────────────────┐ +│ Sentry Self-Hosted │ │ OpenClaw LLM │ +│ 192.168.0.110:9000 │ │ 192.168.0.188:8088 │ +└──────────────────────┘ └──────────────────────────┘ +``` + +## 架構組件 + +### 1. SentryService (`services/sentry_service.py`) + +**職責**: 封裝 Sentry API 呼叫 + +```python +class SentryService: + async def list_projects() -> list[dict] + async def list_issues(query, limit, cursor) -> list[dict] + async def get_issue(issue_id) -> dict + async def get_issue_events(issue_id, limit, full) -> list[dict] + async def get_project_stats(stat, resolution) -> list + def get_issue_url(issue_id) -> str +``` + +**設計原則**: +- Singleton 模式 +- 配置從 `core/config.py` Settings 取得 +- 支援 DI 測試替換 + +### 2. ErrorAnalyzerService (`services/error_analyzer_service.py`) + +**職責**: AI 根因分析 + +```python +class ErrorAnalyzerService: + async def analyze_error( + issue_id, title, level, culprit, + count, stacktrace, context + ) -> tuple[ErrorAnalysisResult | None, str, bool] +``` + +**分析結果**: +- root_cause: 根因分析 +- category: CODE_BUG | DEPENDENCY | CONFIGURATION | ... +- severity: LOW | MEDIUM | HIGH | CRITICAL +- fix_recommendation: 修復建議 +- prevention: 預防措施 +- confidence: 信心度 (0.0-1.0) + +### 3. Router Layer (`api/v1/errors.py`) + +**職責**: HTTP 轉發 (符合 leWOOOgo 積木化) + +| 端點 | 功能 | +|------|------| +| `GET /stats` | 錯誤統計概覽 | +| `GET /issues` | 列出 Issues (分頁、過濾) | +| `GET /issues/{id}` | Issue 詳情 | +| `GET /trends` | 趨勢圖表數據 | +| `POST /issues/{id}/analyze` | 觸發 AI 分析 | + +## 配置管理 + +所有 Sentry 配置集中於 `core/config.py`: + +```python +SENTRY_SELF_HOSTED_URL: str = "http://192.168.0.110:9000" +SENTRY_ORG: str = "sentry" +SENTRY_PROJECT: str = "awoooi-api" +SENTRY_AUTH_TOKEN: str = "" # K8s Secret +``` + +## 與 SignOz 的關係 + +| 工具 | 職責 | 查看時機 | +|------|------|----------| +| **SignOz** | APM + Traces | 慢、效能問題 | +| **Sentry** | Error Tracking | 壞、錯誤堆疊 | + +**互補策略**: 兩者皆部署,各司其職。 + +## 前端整合 + +- 使用 `next-intl` 100% i18n (禁止 hardcode) +- Nothing.tech 視覺規範 (白底、細邊框、無陰影) +- React Hook: `useErrors()` 自動刷新 60 秒 + +## 替代方案 (已拒絕) + +| 方案 | 拒絕原因 | +|------|----------| +| 直接嵌入 Sentry Iframe | 違反視覺主權,無法自訂 UI | +| 前端直接呼叫 Sentry API | 違反 BFF 原則,CORS 問題 | +| 只用 SignOz | 錯誤追蹤能力不足 | + +## 後果 + +### 正面 +- 完整的錯誤追蹤能力 +- AI 輔助根因分析 +- 符合 leWOOOgo 架構 + +### 負面 +- 多一個服務需維護 (Sentry Self-Hosted) +- 額外的 API 呼叫延遲 + +## 相關文件 + +- `project_phase10_arch_review.md` - 架構審查報告 +- `project_sentry_full_integration.md` - 整合計畫 +- ADR-005: BFF Architecture +- ADR-006: AI Fallback Strategy diff --git a/docs/adr/ADR-027-incident-approval-sync.md b/docs/adr/ADR-027-incident-approval-sync.md new file mode 100644 index 00000000..0e01aaca --- /dev/null +++ b/docs/adr/ADR-027-incident-approval-sync.md @@ -0,0 +1,243 @@ +# ADR-027: Incident-Approval 同步架構 + +**狀態**: 批准 +**日期**: 2026-03-26 (台北時區) +**決策者**: 統帥 +**觸發**: 活躍事件顯示 0 + Telegram 告警鏈異常 (2026-03-26 首席架構師審查) + +## 問題陳述 + +``` +事故時間線: +├── 2026-03-26: 活躍事件顯示 0 件,但 Telegram 有新告警 +├── 首席架構師審查: 發現 Incident-Approval 狀態同步機制缺失 +│ +├── CRITICAL-001: Incident + Approval 建立不是原子事務 +│ └─ 後果: 孤兒 Incident、狀態不一致 +│ +├── CRITICAL-002: 雙層寫入非原子 (Redis + PostgreSQL) +│ └─ 後果: 資料遺失、狀態分歧 +│ +├── HIGH-001: Approval 狀態變更未同步 Incident +│ └─ 後果: 前端 get_active 查詢結果錯誤 +│ +├── HIGH-002: Redis TTL 過期導致資料遺失 +│ └─ 後果: 長時間未處理事件消失 +│ +└── HIGH-003: 前端狀態一致性問題 + └─ 後果: 簽核後內容立即消失 +``` + +**核心問題**: +1. Incident 和 Approval 沒有事務保證 +2. Redis (Working Memory) 和 PostgreSQL (Episodic Memory) 同步機制不完整 +3. 狀態變更沒有雙向傳播 + +--- + +## 決策:UnitOfWork + Saga Pattern + +### 為什麼選擇這個方案? + +| 方案 | 優點 | 缺點 | 選擇 | +|------|------|------|------| +| 兩階段提交 (2PC) | 強一致性 | Redis 不支援、效能差 | ❌ | +| **UnitOfWork + Saga** | PostgreSQL 事務 + Redis 補償 | 需處理補償邏輯 | ✅ | +| 事件溯源 | 完整審計軌跡 | 改動太大 | ❌ | +| 最終一致性 | 簡單 | 不適合關鍵業務 | ❌ | + +### 架構設計 + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Incident-Approval 同步架構 (ADR-027) │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Alertmanager │ +│ │ │ +│ ▼ │ +│ IncidentApprovalService.create_with_approval() │ +│ │ │ +│ ├─────────────────────────────────────────┐ │ +│ ▼ ▼ │ +│ UnitOfWork (PostgreSQL) Redis Write │ +│ │ │ │ +│ ├─ incident = Incident.create() │ │ +│ ├─ approval = Approval.create() │ │ +│ │ │ │ +│ ├─────── 事務 commit ─────────────────────┤ │ +│ │ │ │ +│ │ 成功 ────────────────────────────────→ 完成 │ +│ │ │ │ +│ │ 失敗 ────────────────────────────────→ Saga 補償 │ +│ │ (rollback PostgreSQL, │ +│ │ delete Redis keys) │ +│ ▼ │ +│ 同步 Hook │ +│ │ │ +│ └─ on_approval_status_change() │ +│ ├─ update Incident.status │ +│ ├─ refresh Redis TTL │ +│ └─ emit SSE event │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 實作細節 + +### 1. UnitOfWork 模式 (`src/core/unit_of_work.py`) + +```python +class UnitOfWork: + """PostgreSQL 事務管理器""" + + def __init__(self, session_factory): + self.session_factory = session_factory + self._session = None + + async def __aenter__(self): + self._session = self.session_factory() + return self + + async def __aexit__(self, exc_type, exc_val, exc_tb): + if exc_type: + await self.rollback() + else: + await self.commit() + await self._session.close() + + async def commit(self): + await self._session.commit() + + async def rollback(self): + await self._session.rollback() +``` + +### 2. IncidentApprovalService (`src/services/incident_approval_service.py`) + +```python +class IncidentApprovalService: + """Incident-Approval 同步服務 (ADR-027)""" + + async def create_with_approval( + self, + incident_data: IncidentCreate, + approval_data: ApprovalCreate + ) -> tuple[Incident, Approval]: + """原子建立 Incident + Approval""" + + async with UnitOfWork(self.session_factory) as uow: + # 1. PostgreSQL 寫入 + incident = await self.incident_repo.create(uow.session, incident_data) + approval = await self.approval_repo.create(uow.session, approval_data) + + # 2. Redis 寫入 (事務外,需補償) + try: + await self._write_to_redis(incident, approval) + except RedisError as e: + # Saga 補償: rollback PostgreSQL + await uow.rollback() + raise IncidentApprovalCreateError(f"Redis 寫入失敗: {e}") + + return incident, approval + + async def on_approval_status_change( + self, + approval_id: str, + new_status: ApprovalStatus + ): + """Approval 狀態變更 Hook""" + + # 1. 更新 PostgreSQL + approval = await self.approval_repo.update_status(approval_id, new_status) + + # 2. 同步更新關聯 Incident + incident = await self.incident_repo.get_by_approval_id(approval_id) + if incident: + incident_status = self._map_approval_to_incident_status(new_status) + await self.incident_repo.update_status(incident.id, incident_status) + + # 3. 更新 Redis TTL + await self._refresh_redis_ttl(incident.id, approval_id) + + # 4. 觸發 SSE 事件 + await self._emit_status_change_event(incident, approval) +``` + +### 3. 統一常量 (`src/core/constants.py`) + +```python +# TTL 設定 (秒) +INCIDENT_TTL_SECONDS = 7 * 24 * 3600 # 7 天 +APPROVAL_TTL_SECONDS = 7 * 24 * 3600 # 7 天 + +# Redis Key 前綴 +REDIS_KEY_INCIDENT = "incidents:" +REDIS_KEY_APPROVAL = "approvals:" +REDIS_KEY_PENDING = "pending_approvals" + +# 狀態映射 +APPROVAL_TO_INCIDENT_STATUS = { + "pending": "active", + "approved": "resolved", + "rejected": "rejected", + "expired": "expired", +} +``` + +--- + +## 四階段實作計畫 + +| Phase | 內容 | 估時 | 優先級 | +|-------|------|------|--------| +| 1 | UnitOfWork + IncidentApprovalService | 3-4h | P0 | +| 2 | 狀態同步 Hook + TTL 延長 | 2-3h | P0 | +| 3 | 分散式鎖 + TTL 同步 | 2-3h | P1 | +| 4 | 整合測試 | 2h | P1 | + +**總估時**: 9-12h + +--- + +## 驗收標準 + +| 項目 | 狀態 | +|------|------| +| Incident + Approval 原子建立 | 🔲 待實作 | +| PostgreSQL 事務回滾生效 | 🔲 待實作 | +| Redis 補償機制 (Saga) | 🔲 待實作 | +| Approval 狀態變更同步 Incident | 🔲 待實作 | +| TTL 統一管理 | 🔲 待實作 | +| 整合測試通過 | 🔲 待實作 | + +--- + +## 關聯文件 + +- ADR-011: NetworkPolicy 變更治理架構 +- ADR-026: CoreDNS GitOps 管控架構 +- [project_incident_approval_sync.md](~/.claude/projects/-Users-ogt-awoooi/memory/project_incident_approval_sync.md) +- [feedback_incident_approval_sync.md](~/.claude/projects/-Users-ogt-awoooi/memory/feedback_incident_approval_sync.md) + +--- + +## 附錄:驗證指令 + +```bash +# 檢查活躍事件 +curl -s http://localhost:8000/api/v1/incidents/active | jq '.count' + +# 檢查 Redis Incident +redis-cli KEYS "incidents:*" + +# 檢查 PostgreSQL Incident +psql -c "SELECT id, status, created_at FROM incidents WHERE status = 'active'" + +# 驗證同步 +# 1. 建立測試事件 +# 2. 簽核 +# 3. 確認 Incident 狀態同步更新 +``` diff --git a/docs/adr/ADR-028-failure-auto-repair-loop.md b/docs/adr/ADR-028-failure-auto-repair-loop.md new file mode 100644 index 00000000..b43eae0b --- /dev/null +++ b/docs/adr/ADR-028-failure-auto-repair-loop.md @@ -0,0 +1,282 @@ +# ADR-028: 失敗自動修復閉環架構 (Failure Auto-Repair Loop) + +> **狀態**: 📋 Proposed +> **提案日期**: 2026-03-26 +> **決策者**: 統帥 +> **提案者**: 首席架構師 + +## Context + +AWOOOI 行動日誌頁面顯示大量失敗操作,但系統只是「記錄」: + +``` +失敗 → 記錄 → 結束 (死路) +``` + +這違反了 AIOps 產品的核心價值。作為 AI 產品,應該是: + +``` +失敗 → AI 分析 → 自動/人工修復 → 驗證 → 學習 +``` + +## Decision + +實作「失敗自動修復閉環」架構,包含以下核心元件: + +### 1. FailureWatcher Worker + +```python +class FailureWatcher: + """ + 監聽 AuditLog 失敗事件的 Worker + + 消費 Redis Stream: awoooi:audit_logs:failed + """ + + async def handle_failure(self, audit_log: AuditLog): + # 1. AI 分析失敗原因 + analysis = await self.repair_analyzer.analyze(audit_log) + + # 2. 建立修復日誌 + repair_log = await self.create_repair_log(audit_log, analysis) + + # 3. 根據風險等級路由 + if analysis.risk_level == "LOW": + await self.auto_repair(repair_log) + else: + await self.request_approval(repair_log) +``` + +### 2. RepairAnalyzer (OpenClaw 整合) + +```python +class RepairAnalyzer: + """ + 使用 OpenClaw 分析失敗原因並生成修復策略 + """ + + async def analyze(self, audit_log: AuditLog) -> RepairAnalysis: + prompt = f""" + 分析以下 K8s 操作失敗原因: + + 操作類型: {audit_log.operation_type} + 目標資源: {audit_log.target_resource} + 命名空間: {audit_log.namespace} + 錯誤訊息: {audit_log.error_message} + K8s 回應: {audit_log.k8s_response} + + 請提供: + 1. 失敗原因分析 + 2. 建議修復策略 + 3. 風險等級 (LOW/MEDIUM/CRITICAL) + 4. 是否可自動修復 + """ + + return await self.openclaw.analyze(prompt) +``` + +### 3. 資料模型 + +```python +# 擴展 AuditLog +class AuditLog: + # ... 現有欄位 ... + authorization_channel: Mapped[str | None] # "web" | "telegram" | "auto" + authorized_by: Mapped[str | None] + authorized_at: Mapped[datetime | None] + +# 新增 RepairLog +class RepairLog(Base): + __tablename__ = "repair_logs" + + id: Mapped[str] = mapped_column(String(36), primary_key=True) + original_audit_id: Mapped[str] = mapped_column(ForeignKey("audit_logs.id")) + + # AI 分析結果 + failure_reason: Mapped[str] = mapped_column(Text) + repair_strategy: Mapped[str] = mapped_column(Text) + repair_command: Mapped[str | None] = mapped_column(Text) + + # 風險與狀態 + risk_level: Mapped[str] = mapped_column(String(20)) # LOW/MEDIUM/CRITICAL + auto_repaired: Mapped[bool] = mapped_column(default=False) + repair_status: Mapped[str] = mapped_column(String(20)) # pending/executing/success/failed + + # 時間戳 + created_at: Mapped[datetime] + completed_at: Mapped[datetime | None] + + # 關聯 + original_audit: Mapped["AuditLog"] = relationship() +``` + +### 4. 修復流程 + +``` +┌──────────────────────────────────────────────────────────────────┐ +│ 失敗自動修復閉環 │ +├──────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌─────────┐ ┌──────────────┐ ┌─────────────┐ │ +│ │ AuditLog│───▶│FailureWatcher│───▶│RepairAnalyzer│ │ +│ │ (失敗) │ │ (偵測) │ │ (AI 分析) │ │ +│ └─────────┘ └──────────────┘ └──────┬──────┘ │ +│ │ │ +│ ▼ │ +│ ┌───────────────┐ │ +│ │ Trust Engine │ │ +│ │ (風險評估) │ │ +│ └───────┬───────┘ │ +│ │ │ +│ ┌──────────────────┼──────────────────┐ │ +│ │ │ │ │ +│ ▼ ▼ ▼ │ +│ ┌───────────┐ ┌───────────┐ ┌─────────┐│ +│ │ LOW │ │ MEDIUM │ │CRITICAL ││ +│ │ 自動執行 │ │ 單人授權 │ │Multi-Sig││ +│ └─────┬─────┘ └─────┬─────┘ └────┬────┘│ +│ │ │ │ │ +│ ▼ ▼ ▼ │ +│ ┌─────────────┐ ┌─────────────────────────────┐ │ +│ │AutoRepair │ │ 同步推送 │ │ +│ │Executor │ │ • Telegram Bot │ │ +│ │(自動修復) │ │ • Web Dashboard (WebSocket) │ │ +│ └──────┬──────┘ └────────────┬────────────────┘ │ +│ │ │ │ +│ ▼ ▼ │ +│ ┌─────────────┐ ┌─────────────┐ │ +│ │ 揭露通知 │ │ 等待授權 │ │ +│ │ (Dashboard) │ │ (記錄來源) │ │ +│ └─────────────┘ └──────┬──────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────┐ │ +│ │ 執行修復 │ │ +│ └──────┬──────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────┐ │ +│ │ 驗證 │ │ +│ └──────┬──────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────┐ │ +│ │ Playbook │ │ +│ │ 學習萃取 │ │ +│ └─────────────┘ │ +│ │ +└──────────────────────────────────────────────────────────────────┘ +``` + +### 5. 授權來源追蹤 + +| Channel | 說明 | 記錄內容 | +|---------|------|---------| +| `auto` | AI 自動執行 | `authorized_by: "system"` | +| `web` | 前端 Dashboard | `authorized_by: "{user_id}"` | +| `telegram` | Telegram Bot | `authorized_by: "{telegram_user_id}"` | + +### 6. 前端揭露 + +在 Dashboard 新增「AI 自動修復報告」區塊: + +- 過去 24 小時自動修復統計 +- 最近自動修復列表 +- 修復成功/失敗比例 +- 需人工介入的項目 + +### 7. API 端點 + +``` +GET /api/v1/repairs # 修復日誌列表 +GET /api/v1/repairs/{id} # 修復詳情 +POST /api/v1/repairs/{id}/execute # 人工觸發修復 +GET /api/v1/repairs/stats # 統計 (自動/人工比例) +``` + +## Consequences + +### Positive + +1. **AI 真正主動** - 不再等人操作,自動偵測並修復 +2. **透明揭露** - 用戶清楚知道 AI 做了什麼 +3. **授權可追溯** - 記錄每次授權的來源和時間 +4. **降低 MTTR** - 低風險問題秒級自動修復 + +### Negative + +1. **複雜度增加** - 需要新增 Worker、模型、API +2. **風險** - 自動修復可能造成更大問題 (透過 cooldown 緩解) +3. **成本** - 每次分析需要 OpenClaw API 呼叫 + +### Risks + +| 風險 | 機率 | 影響 | 緩解措施 | +|------|------|------|---------| +| 自動修復失敗 | 中 | 中 | 失敗自動升級為人工審批 | +| 修復風暴 | 低 | 高 | Cooldown: 同資源 5 分鐘 3 次上限 | +| AI 誤判風險 | 中 | 中 | 保守分類,有疑問升級為 MEDIUM | + +## Integration Feasibility (首席架構師評估 2026-03-26) + +### 現有架構相容性: ✅ 95% 相容 + +調研結論:系統已具備所有必要基礎設施,可無縫整合。 + +| 組件 | 可復用程度 | 說明 | +|------|----------|------| +| Redis Stream (XREADGROUP) | ✅ 100% | SignalWorker 模式直接複製 | +| Worker 消費循環 | ✅ 100% | 代碼結構完全相同 | +| AuditLog 持久化 | ✅ 90% | 只需新增 3 欄位 | +| Trace Context | ✅ 100% | restore_trace_context() 可用 | +| OpenClaw AI | ✅ 70% | 需新增 analyze_failure() | +| Telegram 推送 | ✅ 80% | 改為推送修復卡片 | + +### 衝突點與緩解 + +| 風險 | 緩解方案 | +|------|---------| +| 重試無限迴圈 | `max_retry_count = 3` | +| OpenClaw 過載 | backpressure queue (max 50) | +| Telegram 風暴 | 10 秒批量聚合 | +| 決策二重性 | DecisionManager 優先 | + +### 模組化驗證 + +``` +✅ leWOOOgo 積木化原則檢查: +├── Protocol 先行: IFailureWatcher, IRepairAnalyzer +├── Router 層乾淨: /api/v1/repairs/* 只做 HTTP 轉發 +├── Service 注入: get_failure_watcher() Singleton +├── Repository 分離: AuditLogRepository.list_failures() +└── Worker 獨立: failure-watcher-worker Deployment +``` + +## Implementation Plan (修訂版) + +| Phase | 內容 | 預估 | 優先級 | +|-------|------|------|--------| +| 18.1 | AuditLog 表擴展 + Migration | 2h | P0 | +| 18.2 | FailureWatcher Service | 6h | P0 | +| 18.3 | FailureWatcherWorker (K8s) | 4h | P0 | +| 18.4 | OpenClaw 失敗分析方法 | 8h | P1 | +| 18.5 | Telegram 修復卡片 | 3h | P1 | +| 18.6 | E2E 測試 + 部署驗證 | 6h | P0 | + +**總計: 29h (~3.6 天)** + +### 工作依賴順序 + +``` +18.1 (DB) ─┬─→ 18.2 (Service) ─┬─→ 18.3 (Worker) ─→ 18.6 (E2E) + │ │ + │ └─→ 18.5 (Telegram) + │ + └─→ 18.4 (OpenClaw) ──────────────────→ 整合到 18.2 +``` + +## References + +- [Memory: Phase 18 Failure Loop](~/.claude/projects/-Users-ogt-awoooi/memory/project_phase18_failure_loop.md) +- [AWOOOI Agentic Workspace Roadmap](../AWOOOI_AGENTIC_WORKSPACE_ROADMAP.md) +- [ADR-009: OpenClaw Agent Teams](./ADR-009-openclaw-agent-teams.md) diff --git a/docs/adr/ADR-025-cicd-ai-integration.md b/docs/adr/ADR-029-cicd-ai-integration.md similarity index 98% rename from docs/adr/ADR-025-cicd-ai-integration.md rename to docs/adr/ADR-029-cicd-ai-integration.md index 39a9b700..1a2928e7 100644 --- a/docs/adr/ADR-025-cicd-ai-integration.md +++ b/docs/adr/ADR-029-cicd-ai-integration.md @@ -1,4 +1,4 @@ -# ADR-025: CI/CD AI 整合架構 (Phase 13.1) +# ADR-029: CI/CD AI 整合架構 (Phase 13.1) | 項目 | 內容 | |------|------|