Commit Graph

129 Commits

Author SHA1 Message Date
Your Name
4111ea4f9f fix(ai): remove 188 ollama provider
All checks were successful
Code Review / ai-code-review (push) Successful in 12s
CD Pipeline / tests (push) Successful in 1m13s
CD Pipeline / build-and-deploy (push) Successful in 3m36s
CD Pipeline / post-deploy-checks (push) Successful in 1m20s
2026-05-06 14:34:48 +08:00
Your Name
c2c0b1ec82 fix(alerts): let GCP Ollama finish before cloud fallback
All checks were successful
Code Review / ai-code-review (push) Successful in 10s
CD Pipeline / tests (push) Successful in 1m9s
CD Pipeline / build-and-deploy (push) Successful in 4m21s
CD Pipeline / post-deploy-checks (push) Successful in 1m16s
2026-05-06 05:27:55 +08:00
Your Name
5ed396e390 fix(decision): derive telegram dedup from incident signals
All checks were successful
CD Pipeline / tests (push) Successful in 58s
Code Review / ai-code-review (push) Successful in 10s
CD Pipeline / build-and-deploy (push) Successful in 3m30s
CD Pipeline / post-deploy-checks (push) Successful in 2m19s
2026-05-06 00:19:35 +08:00
Your Name
14bf86a462 fix(awooop): Phase 2 初批 P0 修正 + Phase 1 Task 1.7 integration tests
## P0 安全 / 架構修正

### P0-08 telemetry.py — 移除硬碼 IP assert(ADR-121)
- config.py:新增 OTEL_ALLOWED_ENDPOINTS(預設 192.168.0.188)+ OTEL_FORBIDDEN_ENDPOINTS
- telemetry.py:_validate_endpoint() 改為 config-driven allowlist/forbidlist
- EwoooC 可用 env 覆寫 OTEL_ALLOWED_ENDPOINTS 指向自己的 SigNoz host

### P0-13 mcp_bridge.py — K8s namespace 由 settings 提供
- config.py:新增 AWOOOI_K8S_NAMESPACE(預設 "awoooi-prod")
- mcp_bridge.py:5 處 parameters.get("namespace", "awoooi-prod") → settings.AWOOOI_K8S_NAMESPACE
- EwoooC/Tsenyang 可設自己的 namespace

### P1-24 decision_manager.py — silence key 常數統一
- 新增 from src.services.telegram_gateway import SILENCE_KEY_PREFIX
- f"telegram_silence:{target}" → f"{SILENCE_KEY_PREFIX}{target}"
- 消除跨兩處重複定義(ADR-118 No Island Coding 原則)

## Phase 1 Task 1.7 Integration Tests
- tests/integration/test_awooop_phase1_schema.py:31 個測試案例
  - awooop_projects CHECK 約束(4 cases)
  - revision 不可變性 trigger(5 cases:draft 可改、published 鎖住、身份欄不可改、非法流轉、DELETE 禁止)
  - awooop_published_revisions VIEW draft/published 隔離(2 cases)
  - active_pointer_guard(3 cases:不可指向 draft、可指向 active、跨租戶 mismatch)
  - RLS fail-closed(3 cases:未設/錯設/正確設 project_id)
  - outbox FK + dedup(2 cases)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 13:46:19 +08:00
Your Name
b1ef05fa8c feat(ollama): ADR-110 GCP 三層容災架構(GCP-A → GCP-B → Local → Gemini)
Some checks failed
Code Review / ai-code-review (push) Successful in 50s
CD Pipeline / tests (push) Failing after 1m14s
CD Pipeline / build-and-deploy (push) Has been skipped
CD Pipeline / post-deploy-checks (push) Has been skipped
## 變更摘要
- Primary: http://34.143.170.20:11434 (GCP-A SSD, 9x 載速 + 2x 推理)
- Secondary: http://34.21.145.224:11434 (GCP-B SSD)
- Fallback: http://192.168.0.111:11434 (M1 Pro Local HDD,最後防線)
- 廢止 ADR-105「111 唯一鐵律」,新建 ADR-110

## 核心改動
- config.py: 新增 OLLAMA_SECONDARY_URL;validator 加 GCP IP 白名單(34.143.170.20, 34.21.145.224)
- ollama_failover_manager.py: 三層 Ollama 決策矩陣;並行健康檢查三台;health_111 → health_gcp_a
- ollama_health_monitor.py: host label 萃取改為通用版(支援 GCP 公網 IP)
- failover_alerter.py: 故障/恢復主機動態顯示,不再硬編碼「Ollama 111 (GPU)」
- ollama_auto_recovery.py: notify_recovery 改為 ollama_gcp_a;recovered_host 動態
- k8s/awoooi-prod: configmap + deployment + network-policy 同步更新(egress 加 GCP /32)
- 服務層: 10 個服務檔案硬編碼 192.168.0.111 改為讀 settings.OLLAMA_URL
- 測試: URL 常數更新,新增三層容災場景,GCP IP 白名單驗證測試

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 22:49:23 +08:00
Your Name
b371edb70c fix host alert auto-repair routing and backup false positives 2026-05-02 23:44:12 +08:00
Your Name
da772a1605 fix(decision): block kubectl actions on bare_metal host alerts
All checks were successful
Code Review / ai-code-review (push) Successful in 54s
CD Pipeline / tests (push) Successful in 3m47s
CD Pipeline / build-and-deploy (push) Successful in 13m26s
CD Pipeline / post-deploy-checks (push) Successful in 5m45s
When HostHighCpuLoad / HostOutOfMemory fire on a bare-metal host
(192.168.0.110 et al, where Sentry / ClickHouse / Snuba are eating
CPU), the LLM kept proposing "kubectl rollout restart awoooi-api",
which is a wrong-domain action — restarting awoooi cannot fix a
third-party process's CPU usage on the host. Auto-execute would then
either run the no-op kubectl restart (wasted) or escalate after
ssh_diagnose because no safe action was found, producing the
"AI 自動修復失敗" Telegram noise the user just complained about.

Adds a guard at the top of DecisionManager._auto_execute: if the
incident's primary signal carries host_type=bare_metal AND the
proposed action starts with "kubectl", refuse to execute. The
incident is marked READY with a clear blocked_reason so human
operators see why automation declined, and emergency_escalation
records the event in AOL for audit.

Also patches /home/wooo/monitoring/alerts.yml on 110 (and the new
ops/monitoring/alerts.yml in repo) to add an explicit
auto_repair_action annotation on HostHighCpuLoad / HostOutOfMemory
that hints LLM toward `ssh ... ps aux` rather than kubectl restart.
Prometheus reload returned 200.

Tests: tests/test_decision_manager_bare_metal_kubectl_guard.py
covers (1) bare_metal+kubectl blocked, (2) kubectl get also blocked,
(3) bare_metal+ssh NOT blocked, (4) k8s host_type+kubectl NOT
blocked, (5) missing host_type label NOT blocked.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 17:41:28 +08:00
Your Name
b3a0f0d766 fix(telegram): dedup by fingerprint + 24h TTL to stop repeat alerts
All checks were successful
CD Pipeline / tests (push) Successful in 2m22s
Code Review / ai-code-review (push) Successful in 57s
CD Pipeline / build-and-deploy (push) Successful in 21m3s
CD Pipeline / post-deploy-checks (push) Successful in 5m2s
Telegram 重複發告警鐵證(4 個 agent 真實數據):
- INC-6FE3BD (HostBackupFailed) 24h 內被推 15 次
- INC-FD6E21 (HostHighCpuLoad) 24h 內被推 6 次
- 06:44:18 同秒兩送 = pod 並發 race

根因:
1. `telegram_sent:{incident_id}` dedup key 綁 uuid4 隨機 INC ID,
   同 fingerprint 換新 INC 完全不去重
2. dedup TTL=600s 比 incident_analysis_sweeper 重觸週期 1h、
   alertmanager repeat_interval 4h 都短 → 每輪都過期通過
3. pod restart 走 _resend_unconfirmed_ready_tokens 用同一 incident_id key
   → 重啟必炸一波

修法(不消音、是「AI 認得這是同一事故」):
- decision_manager.py:207-225 dedup key 改 alertname+target fingerprint
- decision_manager.py:573-578 TTL 600s → 86400s (蓋住 sweeper 1h × alertmanager 4h)
- decision_manager.py:3189-3208 pod restart resend 路徑同步改 fingerprint
- incident_analysis_sweeper.py:37-42 sweeper_done TTL 3600s → 86400s

預期:同症狀 24h 內最多發 1 張 decision card;resolved 後 line 220-226
status check 會 early return,不影響復發偵測。

Tests: 35 passed (test_telegram_adr050 + test_decision_manager_docker_prune_routing)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 16:25:48 +08:00
Your Name
84ba3216ee feat(notifications): tag autonomous repair actions with [AUTO] prefix
Some checks failed
Code Review / ai-code-review (push) Successful in 57s
CD Pipeline / tests (push) Successful in 2m36s
CD Pipeline / build-and-deploy (push) Failing after 31m11s
CD Pipeline / post-deploy-checks (push) Has been skipped
Per user request: every AI-driven repair must surface a Telegram trace
even when it succeeds, so nobody can later deny what the autonomy did.
Adds 🤖 [AUTO] markers and an explicit `Actor: leWOOOgo (autonomous)`
line to both success and failure status messages emitted by
_push_auto_repair_result, making them clearly distinguishable from
human-clicked approval cards.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 12:49:43 +08:00
Your Name
3156ff1c69 feat(aiops): add ssh_docker_prune to auto-repair flywheel for disk-full alerts
Adds Group B SSH MCP tool ssh_docker_prune (image+volume+builder prune
with ≥75% disk usage gate) and routes "docker prune" actions through it.
Flips HostDiskUsageHigh from auto_repair=false to true with mcp_provider
routing labels so the flywheel can self-heal next disk-full event without
hitting the emergency_channel Telegram path.

Trigger: 2026-05-01 → 05-02 Telegram alert storm (peak 53/hr) caused by
empty ssh-mcp-key/known_hosts secret rejecting all SSH and forcing every
disk-full alert through "Host key is not trusted → escalate" loop.
known_hosts patched live; this commit closes the playbook gap so the
next occurrence resolves without manual intervention.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 12:31:37 +08:00
Your Name
433f7b068e fix(aiops): close ssh and telegram remediation gaps
All checks were successful
CD Pipeline / tests (push) Successful in 2m7s
Code Review / ai-code-review (push) Successful in 42s
CD Pipeline / build-and-deploy (push) Successful in 13m14s
CD Pipeline / post-deploy-checks (push) Successful in 4m29s
2026-05-01 16:53:02 +08:00
Your Name
11673d80ea fix(aiops): route backup decisions through ssh
Some checks failed
CD Pipeline / tests (push) Successful in 1m35s
Code Review / ai-code-review (push) Successful in 34s
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled
2026-05-01 12:50:01 +08:00
Your Name
f0d14ab6c4 fix(aiops): escalate blocked auto repair
Some checks failed
CD Pipeline / tests (push) Successful in 1m33s
Code Review / ai-code-review (push) Successful in 28s
Deploy Alert Rules / Deploy Prometheus Alert Rules (push) Successful in 40s
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled
2026-04-30 23:49:17 +08:00
Your Name
95110971f3 fix(telegram): close remaining DM alert routes
Some checks failed
CD Pipeline / tests (push) Successful in 1m27s
Code Review / ai-code-review (push) Successful in 29s
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled
2026-04-30 23:02:17 +08:00
Your Name
61f5a6a419 fix(telegram): route alerts to SRE war room
Some checks failed
CD Pipeline / tests (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
Code Review / ai-code-review (push) Has been cancelled
2026-04-30 15:01:23 +08:00
Your Name
80defbed7c fix(aiops): fallback and escalate automation blockers
Some checks failed
CD Pipeline / tests (push) Successful in 2m41s
Code Review / ai-code-review (push) Successful in 24s
CD Pipeline / build-and-deploy (push) Successful in 7m51s
CD Pipeline / post-deploy-checks (push) Failing after 2m15s
2026-04-30 14:13:57 +08:00
Your Name
dccdcdbaf5 fix(flywheel): unblock action safety and Claude fallback
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 9m45s
2026-04-29 21:51:18 +08:00
Your Name
c5753e1c57 fix(critic-review): KMWriter 名實統一 + Alertmanager 修抑制 + drift checker AST 化
critic PR review 揭示已 push commits 的 7 個 blocker,本 commit 全部修復。

## C1 + C2 + M1 + M2 + M3 — KMWriter 真正統一契約(critic 最嚴重 5 條)

### C1 km_writer.py:194 — backfill 自打臉修
- 裸 asyncio.create_task(_backfill_path_a_approval) → await _backfill_path_a_approval_safe()
- 同步 await + 獨立 DLQ km:backfill:dlq + try/except 不阻塞主寫入
- 新增 km_backfill_reconciler_job.py(每 5 分鐘掃 DLQ)+ ENABLE_KM_BACKFILL_RECONCILER flag
- 防 Path B 比 Path A 先完成 → related_approval_id 永遠 NULL 的 race

### C2 km_writer.py:391 — KM_WRITE_AWAIT=false 路徑收緊
- 從 ensure_future(fire-and-forget 比舊版同步寫更糟)
- 改 await writer.write(retry=1, timeout=2.0)(仍 await 但只試一次、超時短)
- docstring 明確標註「緊急回滾用,不保證可靠性」

### M1 decision_manager.py:2178/2203 — 移除 _fire_and_forget 旁路
- 兩處 _fire_and_forget(executor.write_execution_result_to_km(...))
- 改 await asyncio.shield(...) + BaseException 保護(防上層 cancel 中斷)
- KM_WRITE_AWAIT=true 在這條路徑終於真正 await

### M2 incident_service.py:1099 — 自製 path 加 retry+DLQ
- 原本 if settings.KM_WRITE_AWAIT: await asyncio.wait_for else create_task
- 改 3 次指數退避 retry + DLQ 保護(呼叫 km_writer 私有 helper)

### M3 km_writer.py:166 — 冪等聲明對齊實作
- knowledge_repository.create() 加 UPSERT 路徑(pg_insert ON CONFLICT DO UPDATE)
- KnowledgeEntryCreate / KnowledgeEntryRecord 加 path_type 欄位
- migration: ADD COLUMN path_type + partial unique index uix_knowledge_incident_path

## M4 alertmanager.yml — equal: [] 收緊(critic 防爆炸抑制)
- OllamaInstanceDown / KMConverterDown 抑制加 equal: ['cluster'] 約束
- 防多 cluster 場景下任一 Ollama down 誤抑全 AI/SLO 告警

## M5 Alertmanager 版本驗證(已確認 v0.31.1,遠超 v0.22+)

## M6 governance_agent.py — health score 區分 skipped vs ok vs violated
- check_slo_compliance 加 _meta {violated_count, skipped_count, ok_count, all_skipped, status}
- run_self_check: SLO 全 skipped 時獨立發 governance_slo_data_gap 告警
  (不污染 self_failure 計數,因為 no_data 是 emitter 未實作不是治理機制故障)

## M7 scripts/check_config_drift.py — 改 AST 解析
- regex 改 ast.parse 找 Settings ClassDef AnnAssign Field(default=...)
- 避免多行 list / default_factory= / 含跳行字串的 false negative
- 4 欄位(AI_FALLBACK_ORDER / ARGOCD_URL / PROMETHEUS_URL / OLLAMA_URL)全對齊

## 新增測試
- test_km_writer_backfill_reconciler.py: 7 cases(C1 reconciler + safe helper)
- test_km_writer_idempotent.py: 5 cases(M3 path_type 注入 + UPSERT 分支)

## 驗證
- 1585 unit tests 全綠(+13 從 1572)
- amtool check-config SUCCESS(8 inhibit_rules / 2 receivers)
- drift checker AST-based 4 欄位全對齊
- Alertmanager v0.31.1 確認支援新語法

## 期望影響
- KMWriter 名實統一:飛輪閉環 KM 寫入路徑 100% 可靠
- M4 抑制爆炸風險解除
- 治理層不再對 SLO no_data 靜默
- drift checker false negative 風險解除

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 10:44:39 +08:00
Your Name
c22e5f334e feat(km): P1-1 KMWriter 統一契約 + 5 caller 切換 + M4 反查鏈補齊
12-Agent 全景診斷揪出 KM 寫入鏈路 5 條入口無統一契約,fire-and-forget
在 Pod recycle 時會丟失條目。本次抽 KMWriter 強制 7 條契約。

## 7 條契約強制
1. 同步底線:強制 await asyncio.wait_for(timeout)
2. 重試:3 次指數退避 1s/2s/4s(OperationalError / 網路類例外)
3. 失敗回收:3 次後寫 Redis DLQ km:dlq + log
4. 觀測:structlog event + 預留 metric hook(P1-3 補 emitter)
5. 冪等:incident_id + path_type 為 unique key
6. 禁止吞例外:except 必須 log + raise/DLQ
7. M4 反查鏈:payload 含 approval_id 時自動填 related_approval_id 並回填 Path A

## Caller 切換(5 條入口統一介面)
- incident_service.py:1086 Path A(KB extractor + km_conversion)
- approval_execution.py:771 Path B-人工
- decision_manager.py:2178 Path B-自動成功(消除跨類私有方法調用 M1)
- decision_manager.py:2200 Path B-自動失敗(修 B2 早期吞例外)
- playbook_service.py:210 PlaybookKM(兩份 T0 報告都漏的第三條)

## M4 反查鏈補齊
- knowledge.py + models.py: 補 related_approval_id ORM 欄位
- 對齊 phase26_incident_km_integration.sql:20 schema(partial index 已存在)
- approval↔KM 雙向反查鏈完整(dual-path 縫合線)

## Feature Flag (rollback 保險)
- KM_WRITE_AWAIT=true (default): await + timeout + DLQ 強制
- KM_WRITE_AWAIT=false: fire-and-forget(舊行為)

## 測試
- apps/api/tests/test_km_writer.py: 18 測試全綠
  覆蓋 success / timeout / retry / DLQ / 冪等 / KMWriteError /
  on_failure=raise / 反查鏈回填
- 1552 unit tests 全綠(無回歸)

## 驗收
飛輪閉環核心 — KM 寫入不再靜默丟失,AI 學習鏈不斷裂。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 10:44:39 +08:00
Your Name
143c15f052 feat(wave2+km): LLM 動態按鈕啟用 + KM 自動寫入 + AI Router dead code 標記
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 9m52s
- ConfigMap: USE_LLM_DYNAMIC_BUTTONS=true(B2/B3/B4 handler 全就緒)
- decision_manager: auto_execute 失敗路徑補 KM fire-and-forget 寫入
- ai_router: _build_fallback_chain 標記 DEPRECATED 2026-04-28
- tests: test_golden_regression.py 新增 172 行 golden 回歸測試

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 15:27:33 +08:00
Your Name
c1a1be61bd fix(ssh-auto): 主機告警 SSH 自動診斷授權(HostHighCpuLoad 不再卡人工審核)
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 9m7s
根因:SSH_MCP_ALLOWED_HOSTS 未設定 → _ssh_execute() 全部攔截
      + auto_approve 只認 kubectl 不認 ssh → 主機告警永遠降級人工

修復:
- ConfigMap: 補 SSH_MCP_ALLOWED_HOSTS 四主機白名單
- alert_rules: HostHighCpuLoad 等從 NO_ACTION 改為 ssh_diagnose 指令
- auto_approve: _has_executable 加入 ssh 開頭識別
- decision_manager: _ssh_execute() 加入 ssh_diagnose 路由
- ssh_provider: 新增 ssh_diagnose tool(ps aux + free -h + df -h,只讀)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 20:13:07 +08:00
Your Name
cc547736ab feat(wave6-8): P2.1 fusion + P2.2 governance + P2.4 consensus + Wave 7/8 BLOCKER 修復
承接 Wave 6/7/8 多 engineer 在 agent 限額前完成的代碼,補 commit 解 production
HEAD 隱性 import error(decision_fusion 已被 decision_manager 引用但檔案 untracked)。

新增(後端核心):
- decision_fusion.py (562 行) — P2.1 方法 III(OpenClaw + Hermes + Elephant 三 LLM 融合)
- aiops_timeline.py + aiops_timeline_service.py — critic B4 修復
  /api/v1/aiops/timeline endpoint,DB 存取抽到 service 層遵守 leWOOOgo 積木化
- migrations/p2_decision_fusion_columns.sql + rollback — approval_records fusion 欄位

修改(後端整合):
- decision_manager.py — fusion 三斷鏈修補(critic B1+B2+B3):
  · B1: 寫 _evidence_snapshot_ref 到 token.proposal_data
  · B2: fusion 前計算 complexity_score 並寫 token
  · B3: fusion composite 寫 token.proposal_data["decision_fusion"]
- auto_approve.py — fusion + consensus 認識(critic B3+B5):
  · composite > 0.7 → auto_execute_eligible bypass min_confidence
  · source=consensus_engine + score>=0.6 → 規則可信路徑
- consensus_engine.py — db-fix _save_consensus 重用 agent_sessions
- governance_agent.py — db-fix _alert PG 寫入 ai_governance_events
- approval_db.py — fusion 3 欄位 + 2 partial index + CheckConstraint
- db/models.py — schema 對齊 migration
- core/config.py — vuln #1 修復:OLLAMA_URL/_FALLBACK_URL field_validator
  拒絕公網 IP + 外部域名,僅允許私網/loopback/K8s SVC 白名單
- core/feature_flags.py — P2 fusion + consensus flags
- main.py — governance_agent lifespan 啟動
- failover_alerter.py — Wave8-X2: in-memory dedup fallback(Redis 拒絕後不 fail-open)
- ollama_*.py — metrics 整合 + recovery 改善
- auto_repair_service.py — verifier 接線

新增(測試 2438 行):
- test_decision_fusion.py / test_governance_agent.py / test_consensus_integration.py
- test_p2_db_fixes.py / test_wave8_fusion_fixes.py
- test_config_url_validation.py(vuln #1 12 tests)
- test_failover_alerter.py +Wave8-X2 in-memory dedup 補測

驗收: 116 tests pass (decision_fusion + wave8_fusion + config_url + consensus +
                      governance + p2_db_fixes + failover_alerter)

Conflict resolution:
- 3 檔(config.py + auto_approve.py + decision_manager.py)git stash pop 衝突
  保留 stashed (engineer 最終版),補回 ValueError 「公網 IP」字樣對齊 test

Note: 此 commit 解 production HEAD 隱性 import error
仍未修: vuln #4 prompt injection / debugger B14 quota fail-closed
       / B25-B26 drain_pending_tasks / B8 governance fail alert

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Multiple Engineers (Wave 6/7/8) <noreply@anthropic.com>
2026-04-27 08:11:40 +08:00
Your Name
6baa5054bc fix(auto-execute): 修復 kubectl pattern 攔截 + 補 auto_execute KM 寫入
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
問題 1:_ALLOWED_KUBECTL_PATTERN 不允許 resource type keyword
  根因:LLM 輸出 "kubectl rollout restart deployment clickhouse"
        但 pattern 只允許 "kubectl rollout restart clickhouse"(無 deployment 關鍵字)
  結果:_action_safe=False → auto_execute_blocked_unresolved_placeholder
        → 所有 low/medium risk 告警降為人工審核,飛輪完全停轉
  修法:pattern 新增可選的 resource type group(deployment/pod/service/...)
        + re.ASCII flag 防 unicode bypass,12/12 test cases 通過

問題 2:auto_execute 路徑 KM 寫入斷鏈
  根因:_write_execution_result_to_km 只在人工審核路徑呼叫
  修法:auto_execute 完成後補 _fire_and_forget(executor._write_execution_result_to_km)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 09:47:35 +08:00
Your Name
04ff22563e fix(aiops-p1): Playbook 學習閉環 5斷點全修 + DB Migration(ADR-092 B4)
Some checks failed
run-migration / migrate (push) Failing after 14s
CD Pipeline / build-and-deploy (push) Failing after 2m7s
【P0.4 補丁】pre_decision_investigator Prometheus query 欄位缺失
- _build_tool_params() 補 "query" 欄位(prometheus_query tool 必要參數)
- 新增 _build_prometheus_query() — 依告警類型生成 PromQL(CPU/Memory/Crash/Disk/HTTP/Pod/fallback)
- 修復後 D3_METRICS 感官維度實際取得資料(原本 100% 回 missing_query_parameter)

【P1 Playbook 學習閉環 B1-B5 全修】
- B2 db/models.py: ApprovalRecord 新增 matched_playbook_id 欄位 + ix_approval_matched_playbook index
- B2 db/models.py: TimelineEvent 新增 incident_id 欄位(MCP 稽核用)+ index
- B3 approval_db.py: record→ApprovalRequest 補回 incident_id + matched_playbook_id
- B4 approval_repository.py: 同 B3(兩個轉換函式必須同步)
- B5 approval_db.py: approval_request_to_record_data 補 matched_playbook_id → DB 才能存值

【P1.5 KM 寫入】approval_execution.py: fire-and-forget → await wait_for(30s)
- 根因:asyncio.create_task 在 Pod recycle 時被殺,KM 寫入靜默遺失
- 修復:await asyncio.wait_for(..., timeout=30.0) + TimeoutError log

【Migration 文件】adr092_p1_learning_chain_fix.sql
- ALTER TABLE approval_records ADD COLUMN matched_playbook_id VARCHAR(36)
- ALTER TABLE timeline_events ADD COLUMN incident_id VARCHAR(64)
- 執行:psql $DATABASE_URL -f apps/api/migrations/adr092_p1_learning_chain_fix.sql

【附帶 Agent 改動】
- decision_manager: Phase 2 YAML NO_ACTION 優先門(主機層/外部服務跳過 Agent Debate)
- alert_rules.yaml: Sentry/ClickHouse + HostDiskUsageHigh/Critical 新規則
- solver_agent: action_title 語意合成兜底(取代靜默丟棄)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 15:41:35 +08:00
Your Name
7f4088bcd0 fix(aiops-p0): 六大病根 P0 全面修復(ADR-092 B4)
【P0.1】knowledge_extractor_service.py:210 — AttributeError 修復
- Signal.description 欄位不存在(100% 失敗,KM 每天+5 根因)
- 改用 alert_name + annotations.summary 拼接文字

【P0.2+P0.3】Gate 9+11 唯讀指令鬆綁
- blast_radius_calculator: kubectl get/top/describe/logs/version → score=1(非 50)
- operation_parser: 增加 INVESTIGATE 類型識別(唯讀 kubectl 不回 None)
- executor.py: OperationType 新增 INVESTIGATE enum
- approval_execution.py: INVESTIGATE 路徑直接呼叫 execute_kubectl_command

【P0.4】MCP SSH/K8s Provider 修復
- decision_manager: params= → parameters=(符合 MCPToolProvider.execute 簽名)
- decision_manager: MCPToolResult .get() → .success/.output(dataclass 用法)
- decision_manager + ssh_provider: 補入 hosts 120/121(原 default 缺失)
- auto_approve: phase2_agent_debate source bypass confidence 閾值

【P0.5】告警規則語義矛盾修復
- alert_rules.yaml: 8 條 kubectl 查詢規則 RESTART_DEPLOYMENT → NO_ACTION
  (CrashLoopBackOff/PostgreSQL 連線/慢查詢/MinIO 磁碟/K3s 節點/告警鏈路/SSL/CoreDNS 等)
- incident_service.py: cAdvisor/CoreDNS 從 general 拆出獨立分類

【P0.6】proactive_inspector 動態基線 PromQL 全修
- 5 個 MONITORED_METRICS PromQL 全部修正(cadvisor label/datname/blackbox)
- db_connection_pool: datname="awoooi" → "awoooi_prod"
- http_error_rate: 無效 http_requests_total → blackbox probe_success
- cpu/memory: namespace label → name=~"k8s_api_awoooi-api.*"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 15:32:23 +08:00
Your Name
45dbe07188 fix(flywheel): 自動化飛輪六大能力修復(ADR-092 B3)
Some checks failed
run-migration / migrate (push) Failing after 22s
Deploy Alert Rules / Deploy Prometheus Alert Rules (push) Successful in 53s
Type Sync Check / check-type-sync (push) Successful in 2m54s
CD Pipeline / build-and-deploy (push) Has been cancelled
Ansible Lint / lint (push) Has been cancelled
【根因鏈修復】
MCP Provider bugs → PreDecisionInvestigator 失敗 → Agent Debate 無上下文
→ LLM 逾時 → description="待分析" → ADR-091 鐵閘攔截 → tg_sent 未設
→ W-2 Watchdog 誤報「靜默故障」

【六大修復】
1. MCP Provider 三蟲修復
   - ssh_provider: asyncssh.run() → conn.run()
   - prometheus_provider: KeyError 'query' → .get() 容錯
   - k8s_provider: 空 pod_name → 早返回錯誤字典

2. Agent Debate / 決策品質
   - decision_manager: 逾時降級文字改為明確描述(繞過 ADR-091 鐵閘)
   - intent_classifier: LLM 逾時降級至關鍵字分類(非 None)

3. Watchdog 誤報修復(ADR-092 B3)
   - W-2: tg_sent Redis TTL → telegram_message_id IS NULL(DB 真值)
   - W-5 新增: suggested_action IN 空/待分析/NO_ACTION + tg_id IS NULL
   - approval_timeout_resolver: 60min → 15min,batch 50 → 200

4. Config Drift 自動化
   - drift_adopt_service: auto_adopt_if_safe() 六條件安全閘
   - drift.py: 背景任務先嘗試自動採納再發人工 Telegram 卡片

5. Playbook 飛輪穩定
   - playbook_seed_service: 修復幂等性(deprecated 不視為缺失)
   - playbook_evolver: 只載 DRAFT+APPROVED(非全部 294 筆)

6. 可觀測性
   - alert_rule_engine: auto_rule 結構化日誌 + Redis 計數器(pipeline)
   - auto_approve: reject 原因 Redis 計數器
   - heartbeat_report_service: 新增「⚙️ 自動化統計(今日)」區塊

【待人工執行】
psql $DATABASE_URL -f apps/api/migrations/cleanup_duplicate_deprecated_playbooks.sql

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 10:55:50 +08:00
OG T
cf50a5ce25 fix(solver+execution): Checkpoint-1 假成功修復 + Checkpoint-2 K8s 環境感知
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 10m55s
## Checkpoint-1: 假成功根治
- approval_execution.py: execute_approved_action 改返回 bool
  (原返回 None,呼叫端無法判斷 K8s 是否接受指令)
- decision_manager.py auto-execute 路徑: 用 _exec_success 取代硬編 success=True
  修復: K8s 拒絕指令時正確發  而非  自動修復完成

## Checkpoint-2: K8s 環境感知 (Inventory Pre-flight)
- solver_agent.py: 新增 _fetch_k8s_inventory() — 生成 kubectl 指令前先拉
  kubectl get deployments,statefulsets -n awoooi-prod,將真實名稱清單
  注入 Solver prompt,LLM 必須從清單選擇,防止幻覺(awooiii-api 三個 i)
- 超時 5s 或失敗 → 返回 "",prompt 顯示警示但不中斷主流程

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 23:08:23 +08:00
OG T
cbb719b4a1 fix(decision_manager): ADR-091 hotfix — 修復 d5dbfc9 喪屍閘門邏輯漏洞
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 11m9s
d5dbfc9 引入的閘門條件 `not action.strip()` 在 action="待分析" 時
判斷為 False(非空字串),導致閘門失效,喪屍卡片仍然突圍廣播。

根本原因:c759b4e P1 修復讓 suggested_action fallback 為 "待分析"
而非 "",使原本的 empty-string 檢查形同虛設。

修復:改用集合判斷 `_action_text in {"", "待分析", "NO_ACTION", "待分析 - 系統自動保護"}`,
涵蓋所有已知失敗狀態 token,完全封堵喪屍卡片廣播路徑。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 22:44:53 +08:00
OG T
af2adb5b96 fix(telegram): ADR-091 禁止 Agent Debate 分析失敗時廣播「待分析」喪屍卡片
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 10m51s
問題根因:
  GET /incidents 觸發 Phase 2 Agent Debate → LLM 全失敗
  → description="待分析" + action="" → 每隔幾分鐘廣播新 Telegram 卡片
  → 告警疲勞(SRE 最致命的殺手)

架構缺陷 (anti-pattern):
  GET 請求(讀取操作)產生對外廣播副作用 → 違反 RESTful 原則

修復 (_push_decision_to_telegram):
  在 DB 更新完成後、Telegram 推送前加入閘門:
  description="待分析" AND action="" → 靜默退出,絕不廣播

ADR-091 鐵律:
  只有 Alertmanager Webhook POST(真實新告警)可觸發 Telegram 廣播
  Agent Debate 失敗分析 → 靜默 DB 更新,不污染頻道

2026-04-17 ogt + Claude Sonnet 4.6

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 22:26:35 +08:00
OG T
c759b4eeab fix(webhook+decision): ADR-089 async webhook + 超時髒資料修復
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 10m16s
P0 — Webhook async (ADR-089):
- Alertmanager 收到告警立即回 202,不再同步等 90s LLM
- 新增 _process_new_alert_background():LLM 分析/Approval/Incident/Telegram 全進背景
- 根治 Alertmanager Fallback 風暴(超時 → 重送 → 指數退避風暴)

P1 — 超時髒資料 (decision_manager):
- _package_to_proposal_data: blocked_reason 禁止進 desc_parts(禁進卡片)
- _push_decision_to_telegram: suggested_action fallback 改「待分析」,禁止 description 流入

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 16:29:24 +08:00
OG T
1ae9e9f389 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
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>
2026-04-17 15:23:35 +08:00
OG T
f421e652d3 fix(telegram): BUG-C TYPE-3 排版清洗 + 批准/拒絕永遠置頂(ADR-075 UI 第三波修復)
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
Checkpoint 1 — decision_manager.py TYPE-3 root_cause 清洗:
- 舊: root_cause=_smt(reasoning, 500) → debate_summary 全文(診斷/方案/審查/質疑)全部傾倒到 AI 診斷欄
- 新: _parse_debate_summary 只取 diagnosis 欄位 + _smt 截斷 300 字
- 移除 _requires_human 變數(已無用途)

Checkpoint 2 — telegram_gateway.py _build_inline_keyboard 按鈕順序重構:
- 舊: K8s 類別按鈕置頂,批准/拒絕受 requires_human_approval 控制 → 死卡
- 新: [ 批准][ 拒絕] 永遠第一行,K8s/DB/Host 操作按鈕置後
- 移除 requires_human_approval 參數(邏輯已簡化為無條件置頂)

修改範圍: decision_manager.py else 路由段 + _build_inline_keyboard + send_approval_card 簽名,
telegram_gateway.py 模板/訊息格式零改動。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 14:42:29 +08:00
OG T
418d73540b fix(telegram): BUG-A TYPE-1 + BUG-B TYPE-4D 資料前處理(ADR-075 UI 第二波修復)
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 10m25s
BUG-A (TYPE-1 純資訊通知):
- 舊: message=reasoning[:200] → debate_summary 全文傾倒(診斷/方案/審查/質疑一起出現)
- 新: _parse_debate_summary(reasoning) 只取 diagnosis 欄位 + _smt 截斷 200 字

BUG-B (TYPE-4D Config Drift):
- 舊: diff_summary=description[:500] → LLM 輸出的 JSON 原文直接顯示在 <pre> 區塊
- 新: JSON Catcher — json.loads(description) 成功則格式化「📝建議操作/📖說明/回滾方案」
       失敗 (JSONDecodeError/TypeError/AttributeError) → 平滑降級為純文字截斷

僅修改 decision_manager.py 路由準備段,telegram_gateway.py 模板層零改動。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 14:14:10 +08:00
OG T
6baa2e91da fix(telegram): 修復死卡按鈕 + 重複渲染 + 智能截斷三連修
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 10m26s
問題 1 — 批准/拒絕按鈕消失(死卡)
根因:_build_inline_keyboard 有 alert_category 動態按鈕時走 category 路徑,
      approve/reject 行被跳過 → requires_human_approval 卡片無審核扳機
修復:新增 requires_human_approval 參數;True 時強制在動態按鈕後插入批准/拒絕行
影響:decision_manager 傳入 proposal_data.requires_human_review

問題 2 — TYPE-8M 三欄重複渲染
根因:diagnosis/system_impact/probable_cause 全用 reasoning[:100] → 同一段字
修復:新增 _parse_debate_summary(),拆分 debate_summary 的「診斷/方案/安全審查/質疑」
      各欄位填入不同語意的組件

問題 3 — 幽靈截斷「質疑:無(通」
根因:粗暴 [:N] 在括號/中文字中間切斷
修復:新增 _smart_truncate(),在句子邊界(。!?;,)截斷,補 …[截斷] 標記

驗證:verify_telegram_ui.py 全部通過(括號平衡 、欄位不重複 、按鈕存在 )

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 13:57:42 +08:00
OG T
0ab92c20d6 fix(telegram): root_cause 截斷上限 300→500 — 修復「質疑:無(通」幽靈重現
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 10m31s
根因:debate_summary 結構為「診斷(≤220字);方案;安全審查;質疑」
      診斷假設長時總長超過 300 chars → root_cause 截斷在「通」字
修復:300 → 500(Telegram 單卡 4096 限制,安全)

2026-04-17 ogt + Claude Sonnet 4.6

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 13:28:16 +08:00
OG T
b7c2b691bb fix(p2-backlog): 修復 suggested_action「待分析」— action 空時 fallback 到 description
Some checks failed
CD Pipeline / build-and-deploy (push) Failing after 1m26s
根因:_push_decision_to_telegram() 的 suggested_action 只有兩條路:
- action 有值 → 顯示 action[:120]
- action 空   → 顯示「待分析」

但 _package_to_proposal_data() 已從 hypothesis 組出 description
(含「根因:...(信心 X%);方案:...」),此時 action="" 卻還是顯示「待分析」
導致 SRE 在 Telegram 卡片看不到 AI 的診斷結論。

修復:action 空時,優先用 description[:120] 作為 suggested_action
(description 已包含根因摘要,比「待分析」有意義)
fallback chain: action → description → "待分析"

2026-04-17 ogt + Claude Sonnet 4.6

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 11:48:49 +08:00
OG T
0388e50d0e fix(p1-backlog): 修復「待分析」死結與 Telegram 訊息截斷
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 30m25s
問題 1:REQUEST_REVISION → 待分析
  根因:safe_candidates=[] → selected=None → recommended_action=None
        → decision_manager action="" → TG 卡顯示「待分析」(資訊流斷裂)
  修復 coordinator_agent.py:
    無安全候選時回退至 Solver 原始最優方案
    標記「[Reviewer 未核准,僅供參考] {action}」
    SRE 永遠能看到 AI 建議,資訊流絕不中斷

問題 2:debate_summary 在 (blast_radius... 中間截斷顯示 (bl
  根因:root_cause=reasoning[:150] — 150 字元對中文 debate_summary 過短
  修復 decision_manager.py:
    root_cause 截斷 150 → 300
    suggested_action 截斷 80 → 120

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 11:12:02 +08:00
OG T
0c15fa5988 refactor(decision): 狀態機重構 — YAML NO_ACTION 閘門上移至決策路由中樞
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
架構師指令(2026-04-17):通知層禁止查詢業務邏輯。
撤銷 c05bcdb 的 inline YAML 查詢(義大利麵補丁),
將 NO_ACTION / INVALID_TARGET 判斷移至正確位置。

重構方向:
① 移除 _push_decision_to_telegram() 的 inline YAML 查詢
  → 通知層只做 blocked_reason → NotificationType 轉譯(Single Responsibility)

② 新增 decide() 第 4c 步:YAML NO_ACTION 路由閘門
  位置:_dual_engine_analyze() 返回後、auto_approve.evaluate() 之前
  邏輯:
    - NO_ACTION → blocked_reason="YAML: NO_ACTION" + is_informational_only=True
      → 短路跳過 auto_approve + Blast Radius → TYPE-1(或 critical → TYPE-4)
    - INVALID_TARGET → blocked_reason="INVALID_TARGET-..." → 短路 → TYPE-4
    - 閘門查詢失敗 → 靜默降級,繼續正常流程

Checkpoint 覆蓋:
  CP1 上移 YAML 評估層 
  CP2 短路跳過 auto_approve 
  CP3 通知層純粹轉譯 

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 10:20:01 +08:00
OG T
c05bcdbbd4 fix(decision): inline YAML NO_ACTION 補查 — 修復 Phase 2 路徑盲點
Some checks failed
CD Pipeline / build-and-deploy (push) Failing after 4m0s
根因:Phase 2 (agent debate → auto_approve 拒絕 → 直接推 TG) 不經過
      auto_execute() 的 YAML check,Coordinator 不設 blocked_reason。
      PostgreSQL disk / host resource 等 NO_ACTION 規則告警在 Phase 2
      路徑仍顯示「ACTION REQUIRED」卡片(TYPE-3),而非 TYPE-1 資訊卡。

修復:_push_decision_to_telegram() 在 blocked_reason 為空時,補做一次
      alertname inline YAML 查詢,任何路徑(Phase 2 / Expert / Webhook)
      都能正確偵測 NO_ACTION → TYPE-1 / critical NO_ACTION → TYPE-4。

生產驗證觸發:INC-20260416-C365D0 PostgreSQL disk alert 顯示 ACTION REQUIRED
             而非 TYPE-1,確認全景 Code Review 遺漏此執行路徑。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 10:15:28 +08:00
OG T
83ab5e32d7 fix(happy-path): Happy Path 全境加固 — INVALID_TARGET + critical NO_ACTION + 空指令攔截
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
問題 1 (P0) — deployment/unknown 無效重啟:
- alert_rule_engine: 追蹤 _invalid_target flag,回傳 blocked_reason="INVALID_TARGET-..."
- decision_manager: auto_execute 路徑偵測 INVALID_TARGET → 提早返回 + TYPE-4 人工確認
- auto_approve: 新增條件 1c — action 為空字串直接拒絕,防止誤報「即將執行」

問題 2 (P1) — critical+NO_ACTION 靜默:
- decision_manager: blocked_reason 感知層重構
  ① INVALID_TARGET → TYPE-4
  ② NO_ACTION + critical → TYPE-4(升級,SRE 不可錯過)
  ③ NO_ACTION + 非 critical → TYPE-1(維持純資訊卡)

問題 3 (P1) — 規則匹配信心黑洞:
- auto_approve 條件 1c 確保空 action 不通過 auto-approve
  即便 is_rule_based=True 也無法在無指令時自動執行

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 22:57:50 +08:00
OG T
92b39ab840 fix(no-action-notify): YAML NO_ACTION 告警改為 TYPE-1 資訊通知(移除無意義審核按鈕)
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
根因:
- host_resource/postgresql_disk_monitoring YAML 規則設 NO_ACTION
- 但 classify_notification() 不知道 NO_ACTION
- confidence=0.2(感應器無資料)→ 判為 TYPE-4(信心不足需人工審核)
- SRE 看到「審核批准/拒絕」按鈕,卻沒有任何自動修復動作可執行 → 毫無意義

修復:
- _push_decision_to_telegram 偵測 blocked_reason 含 "NO_ACTION"
- 強制 _notif_type = TYPE-1(純資訊通知,無審核按鈕)
- SRE 看到資訊卡「主機 CPU/負載/磁碟告警 (觀察即可)」而非假的審核請求

2026-04-16 ogt + Claude Sonnet 4.6 (台北時區)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 22:37:15 +08:00
OG T
54d6818b8d fix(sensors+rules+dedup): 全景三根因修復 — asyncssh缺失/YAML規則空洞/重複卡片
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
Fix 1: asyncssh 未安裝 → sensors_succeeded 永遠=0
  - apps/api/pyproject.toml 加入 asyncssh>=2.14.0
  - 根因:ssh_provider.py 的 import asyncssh 在 try/except 外,ImportError 直接噴出
  - 效果:15 個 SSH tool 全部恢復可用

Fix 2: YAML 規則空洞 → HostHighLoadAverage/PostgreSQLDiskGrowthRate 落 generic_fallback → restart
  - 合併 host_cpu_high 為 host_resource_alert,覆蓋 25+ 個主機層 alertname
  - 新增 postgresql_disk_monitoring 規則,覆蓋磁碟增長/exporter/vacuum 類告警
  - 所有主機層/磁碟監控告警 → NO_ACTION,禁止 kubectl restart

Fix 3: 同一 incident 被多 pod 同時處理 → 送出 3 張重複 Telegram 卡
  - decision_manager.get_or_create_decision(): ANALYZING 狀態加入早返回
  - 根因:ANALYZING 不在 (READY/EXECUTING/COMPLETED) 條件 → pod-B/C 各自建新 token

2026-04-16 ogt + Claude Sonnet 4.6 (台北時區)
2026-04-16 22:23:49 +08:00
OG T
513232e90b fix(decision_manager): Agent 分析結果覆寫 Webhook 垃圾 action
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 28m30s
根因 (INC-20260416-C365D0 事故完整根因分析):
- Webhook inline LLM 建立 ApprovalRecord.action = "kubectl rollout restart awoooi-prod"
- Agent 分析正確(postgres disk → NO_ACTION)但只發新 Telegram 卡,未覆寫 DB
- 用戶批准 Agent 卡 → 系統查 incident_id → 找到 Webhook 舊 ApprovalRecord
  → 執行垃圾 action(rollout restart 一個磁碟告警!)

修復:
- approval_db.py: 新增 update_action_by_incident_id()(按 incident_id 更新 PENDING 記錄)
- decision_manager.py: Agent 確認 action 後立即覆寫 ApprovalRecord
  若 action="" (NO_ACTION): 存 "NO_ACTION - {description}" 讓用戶知道 Agent 建議觀察
  用戶批准時執行的是 Agent 的正確建議,而非 Webhook 的通用 action

2026-04-16 ogt + Claude Sonnet 4.6(亞太)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 20:07:15 +08:00
OG T
8b2a3df64b fix(telegram): 修復 Telegram 卡片 description 顯示 debug garbage
Some checks failed
CD Pipeline / build-and-deploy (push) Failing after 3m12s
問題:description = debate_summary[:500],用戶看到的是內部審計文字
修復:從 diagnosis.top_hypothesis + action_plan.top_candidate 組出人類可讀摘要
格式:「根因:[描述](信心 X%);方案:[動作]」

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 18:42:13 +08:00
OG T
27ba97e586 fix(ollama): 清除所有硬寫 188:11434 fallback — 全部改指向 111 GPU
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 15m59s
- decision_manager.py: 兩處 getattr fallback 188 → 111
- routes/agent.py: OLLAMA_BASE_URL 188 → 111
- knowledge_extractor_service.py: _OLLAMA_BASE 188 → 111

config.py 預設早已是 111,此次清掉 code 層殘留的 188 硬寫值。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 03:01:31 +08:00
OG T
5a3a649f8a fix(decision): TYPE-1 告警重複洗版兩個根因修復
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
根因 1: TYPE-1 bypass 在 existing_token 檢查之前執行
→ 每次 get_or_create_decision() 不管 token 是否存在,都直接推 TG
→ 修復: existing_token 檢查提前到 TYPE-1 bypass 之前(統一入口)

根因 2: TYPE-1 token TTL 僅 3600s
→ 1h 後 token 過期,下次掃描重新建立並再推 TG
→ 修復: TYPE-1 token TTL 提升至 86400s (24h)

影響: HostBackupFailed 等 TYPE-1 告警每個 incident 只推 1 次(24h 內)

2026-04-16 ogt + Claude Sonnet 4.6

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 02:49:31 +08:00
OG T
62bcc50770 fix(tg+km): 補齊 Telegram 操作紀錄揭露與 KM 分類修復 (ADR-076)
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
Telegram 訊息新增欄位:
- alert_category 分類標籤(🏷️ 主機/K8s/資料庫/服務等)
- playbook_name 顯示匹配到的 Playbook 名稱
- 頻率統計從 count_24h>1 降至 >=1(初次告警也顯示)
- TelegramMessage 新增 alert_category/playbook_name 欄位
- decision_manager → send_approval_card 穿透 playbook_name

KM 修復:
- EntryType.PLAYBOOK → EntryType.AUTO_RUNBOOK(前者不存在,會 AttributeError)
- category "auto_generated" → "ai_system"(前端 i18n 有對應翻譯)
- runbook_generator 同步修正 category
- KM 建立後推 Telegram 通知(best-effort)

DB decision_chain 補欄位:
- 新增 playbook_id / playbook_name / alert_category

2026-04-16 ogt + Claude Sonnet 4.6

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 02:46:17 +08:00
OG T
0760315059 fix(decision-manager): 修正 CAST 語法 + 關閉 shadow_mode
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
decision_chain_persist_failed 根因:
  asyncpg 不支援 :dc::json 語法 (:: 與具名參數 : 衝突)
  改為 CAST(:dc AS jsonb) — asyncpg 標準寫法

configmap:
  AIOPS_P4_SHADOW_MODE: true → false
  真實主動監控啟用 (proactive_inspector 輸出供 PreDecisionInvestigator 讀取)

2026-04-16 Claude Sonnet 4.6 Asia/Taipei

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 01:24:48 +08:00
OG T
457018c0f9 fix(decision-manager): AI 分析結果寫入 incidents.decision_chain (DB 長期保存)
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
修復 Gap: decision token 只有 Redis TTL 12min,AI 診斷歷史永久丟失
  - 新增 _persist_decision_to_db() method
  - get_or_create_decision() 完成後 fire-and-forget 寫入 PG
  - 寫入: ts / confidence / risk_level / provider / source / diagnosis[:200]
  - try/except 吞錯不影響主流程,warning log 追蹤

DB/Cache 分層:
  PG (長期): incidents.decision_chain (歷史) + outcomes + KM entries
  Redis (短期): decision token dedup + working memory + playbook cache

2026-04-16 Claude Sonnet 4.6 Asia/Taipei

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 01:08:30 +08:00
OG T
ecfb7148bf fix(prod): 接通 YAML 規則引擎與自動執行路徑 — 架構核心斷點
Some checks are pending
CD Pipeline / build-and-deploy (push) Has started running
架構斷點根因:
  YAML 規則引擎(alert_rules.yaml)是人工審閱的權威動作來源,
  但自動執行路徑只讀 proposal_data["kubectl_command"](LLM 生成),
  兩者完全脫節 → HostHighCpuLoad 得到 kubectl restart,DockerContainerUnhealthy
  的 SSH 指令被 LLM 的 kubectl 覆蓋。

修復策略:
  在 auto_execute 入口,先查 YAML match_rule:
  1. YAML → NO_ACTION(如 HostHighCpuLoad)→ 立即返回,不執行任何操作
  2. YAML → 非 kubectl 指令(如 ssh docker restart)→ 覆蓋 LLM action,
     後續 infrastructure SSH 路由才能生效

影響:
  - HostHighCpuLoad / NodeCPUUsageHigh → 停止自動執行,降級人工審核
  - DockerContainerUnhealthy → SSH docker restart(若 labels 有 host/container)

2026-04-15 ogt + Claude Sonnet 4.6(亞太): 生產緊急修復第三批

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