Commit Graph

517 Commits

Author SHA1 Message Date
OG T
670cd5df86 refactor(flywheel): 首席架構師審查修正 C1/C2/I1/I2/I3/I4/M1
Some checks are pending
CD Pipeline / build-and-deploy (push) Has started running
C1 — Repository 層修正 (積木化鐵律):
  新增 PlaybookEmbeddingRepository (pgvector UPSERT)
  playbook_embedding_service 改透過 Repository 存取 DB,不再直接 db.execute(text(...))

C2 — Router 層業務邏輯移入 Service 層:
  create_incident_for_approval + extract_affected_services (去掉底線前綴) 移入 incident_service.py
  webhooks.py 改從 incident_service import,自身不再含業務邏輯

I1 — _infra_jobs 提升為 module-level frozenset (_INFRA_JOB_NAMES),避免每次呼叫重建

I2 — _persist_embeddings_to_db 補齊 PlaybookRAGService / list[Playbook] 型別標注

I3 — embedding 格式顯式化: "[" + ",".join(str(float(x)) for x in embedding) + "]"
  防止 pgvector 因格式差異靜默解析失敗

I4 — import asyncio 移至 main.py 頂層,移除 try 區塊內重複 import

M1 — similarity.py: 移除死代碼 `if union > 0 else 0.0`
  union 在兩個集合都非空時不可能為 0

2026-04-10 Asia/Taipei — Claude Sonnet 4.6
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 11:35:10 +08:00
OG T
49bfbd573c feat(test): B5 整合測試框架 — 真實 DB, 5/5 通過
Some checks failed
CD Pipeline / build-and-deploy (push) Failing after 2m34s
新增:
- docker-compose.test.yml: CI 用臨時 pgvector PostgreSQL (port 15432)
- tests/factories.py: Incident/Approval/Knowledge/RAG 測試資料工廠
- tests/integration/test_b5_core_flows.py: 5 個 E2E 整合測試 (5/5 PASSED 1.03s)
- tests/integration/setup_test_schema.sql: CI schema 初始化 SQL
- cd.yaml: 新增 Integration Tests B5 step
- scripts/sync_dev_db.py: dev DB 同步工具

修正:
- .env.test: DATABASE_URL 指向 awoooi_dev (本機設定, gitignore 不入庫)

禁止 Mock 鐵律: 所有 DB 測試使用真實 PostgreSQL, 無 SQLite/MagicMock

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 11:22:57 +08:00
OG T
ab6f6faa32 feat(phase32): 實作 review_push + gitea_webhook 改用本地 Ollama 審查
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
- local_code_review_service: 新增 review_push() 方法
  使用 qwen2.5-coder:7b 審查 push event(非 PR)
- gitea_webhook_service: _call_openclaw_push_review 改用本地推理
  OpenClaw 無 push-review 端點(404) → 改用 LocalCodeReviewService

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 11:09:11 +08:00
OG T
b24fae313e fix(drift_narrator): 補寫 narrative_text 到 DB + drift_repository.update_narrative
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
2026-04-10 11:06:50 +08:00
OG T
c6edfb5614 fix(flywheel): 四階段系統性修復 AUTO_REPAIR NO_MATCH 斷層
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
Phase 1 — affected_services 污染根治
  - webhooks.py: _extract_affected_services() 從 labels 精準萃取服務名
    (component > job > pod deployment name > clean target_resource > [])
  - create_incident_for_approval: alert_labels 完整保留進 Signal
  - alert_name 從 alertname 取,不再用 "custom"

Phase 2 — Playbook alertname 變體擴充
  - alert_rules.yaml: 5 條規則新增 HostHighCpuLoad、KubePodCrashLooping 等變體
  - scripts/update_playbook_alert_variants.py: Redis index 已執行更新 

Phase 3 — Jaccard 通用型 Playbook 豁免
  - similarity.py: affected_services=[] → 1.0 豁免(基礎設施 Playbook 不針對特定服務)
  - severity_range=[] → 1.0 豁免(適用所有嚴重度)

Phase 4 — Playbook Embedding 持久化(冷啟動修復)
  - migrations/flywheel_playbook_embeddings.sql: pgvector 持久化表
  - services/playbook_embedding_service.py: 啟動時重建 Redis 向量快取 + 同步 DB
  - main.py: lifespan 啟動時 asyncio.create_task 非阻塞執行

2026-04-10 Asia/Taipei — Claude Sonnet 4.6
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 11:04:56 +08:00
OG T
1c4bdedc64 fix(drift_narrator): send_text → send_notification + DriftLevel case fix
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 14m43s
2026-04-10 10:48:36 +08:00
OG T
5c2db65ea1 refactor(rag): C1 修正 — 新增 rag_chunk_repository,Service 不再直接存 DB
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
- 新增 src/repositories/rag_chunk_repository.py
  search_chunks / insert_chunk / delete_by_source_id / get_stats
- KnowledgeRAGService 移除所有 get_db_context 直接呼叫
  改委派 rag_repo.search_chunks / insert_chunk / delete_by_source_id / get_stats
- 移除 unused Any import

leWOOOgo 合規評分: 62 → 95/100

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 10:43:53 +08:00
OG T
cc8cabebf9 refactor(rag): 架構審查修正 — leWOOOgo 合規 + 去重 + httpx 關機
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
- C2: _run_index() 業務邏輯移入 KnowledgeRAGService.index_all_sources()
      Router 層只做 background_tasks.add_task(_run_index) 轉發
- C3: glob("*.md") → rglob("*.md") — 掃描巢狀子目錄
- C4: docstring 修正 Ollama 188 → 111
- I2: index_document() 先刪舊版本 (_delete_by_source_id) 避免重複累積
- I3: debug endpoint 改用 settings.OLLAMA_URL 取代硬碼 IP
- I4: main.py shutdown 加入 get_knowledge_rag_service().close()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 10:39:14 +08:00
OG T
af7b1591c1 feat(rag): phase35 ivfflat 向量索引 — 5814 chunks 已建立
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
已在 prod 執行: idx_rag_chunks_embedding (lists=100, cosine)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 10:33:32 +08:00
OG T
09a8c3a90b fix(rag): 修正 debug endpoint 與訊息文字 — Ollama 188→111
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 10:28:04 +08:00
OG T
68e9ef5d26 fix(drift_narrator): DriftItem.severity → drift_level.value 欄位名稱修正
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
2026-04-10 10:24:41 +08:00
OG T
974f84511b fix(rag): embed 改用 settings.OLLAMA_URL — K3s NetworkPolicy 擋住直連 188:11434
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
nomic-embed-text 在 111 也有,改走 OLLAMA_URL (111) 避開 NetworkPolicy

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 10:14:33 +08:00
OG T
b51f1b011c debug(rag): /rag/debug 顯示完整 Ollama 錯誤訊息
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 10:13:52 +08:00
OG T
6786da89c8 debug(rag): 加入 /rag/debug 診斷端點 — 確認容器路徑 + Ollama 連線
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 13m14s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 09:54:56 +08:00
OG T
b261a51685 feat(rag): Dockerfile 加入 docs/ + .agents/skills/ — RAG 索引來源
Some checks failed
CD Pipeline / build-and-deploy (push) Failing after 2m11s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 09:16:51 +08:00
OG T
3ed52b0424 fix(rag): _run_index 修正 index_document 簽名不符 — 讀檔內容再傳 service
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 13m3s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 09:00:26 +08:00
OG T
0ee5d532ba feat(rag): 新增 RAG Router + 掛載到 main.py (Phase 33 ADR-067)
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 13m11s
- rag.py: POST /index, POST /query, GET /stats 三端點
- stats 委派給 KnowledgeRAGService.get_stats()(leWOOOgo 合規)
- main.py: include_router rag_v1.router

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 07:34:06 +08:00
OG T
e605b7192b feat(rag): Phase 33 RAG API 端點 — /knowledge/rag/index + query + stats
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 14m35s
ADR-067 Phase 33: pgvector RAG 三個 HTTP 端點
- POST /knowledge/rag/index — 索引文件到 rag_chunks
- GET /knowledge/rag/query — embed→knn→生成答案
- GET /knowledge/rag/stats — chunks 統計 (透過 Service 層)
- 修正: rag_stats 移至 KnowledgeRAGService.get_stats() (leWOOOgo 積木化)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 02:00:59 +08:00
OG T
63e840ae42 feat(ollama): Phase 31-34 ADR-067 — Log摘要/PR審查/RAG知識庫/圖片分析
Some checks are pending
CD Pipeline / build-and-deploy (push) Has started running
Phase 31: log_summary_service.py — deepseek-r1:14b K8s Pod日誌異常摘要
  - 觸發: signoz_webhook 告警時背景呼叫
  - Redis快取 log_summary:{pod}:{date} TTL 24h
  - 敏感資料regex遮蔽

Phase 32: local_code_review_service.py — qwen2.5-coder:7b PR自動審查
  - Fallback: Gemini (diff > 50KB 或 Ollama超時)
  - semaphore 最多2個同時審查
  - 雙寫: Redis TTL 7d + pr_reviews表 (phase29 migration)

Phase 33: knowledge_rag_service.py — nomic-embed-text 768維 pgvector RAG
  - 向量化(188) + 生成(111) 雙Ollama
  - rag_chunks表 (phase28 migration)
  - 初期線性搜尋,>100筆啟用ivfflat索引

Phase 34: image_analysis_service.py — llava:latest Telegram圖片分析
  - download_and_analyze: Bot API getFile → 下載 → llava → 回應
  - Rate limit: 每chat_id每分鐘3次 (Redis sliding window)
  - telegram.py webhook新增photo分支

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 01:50:22 +08:00
OG T
89015d4527 feat(phase30): Drift 報告 AI 人話摘要 (ADR-067)
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
- 新增 DriftNarratorService — qwen2.5:7b-instruct (Ollama 111)
  - 觸發條件: high >= 1 or medium >= 3(HPA replicas 白名單)
  - Redis 快取: drift_narrative:{report_id} TTL 1h
  - LLM 失敗時 graceful fallback 結構化文字
- drift.py _analyze_and_notify: 接入 narrator(Phase 30 標記)
- Migration: drift_reports.narrative_text TEXT (已在 prod 執行)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 01:37:43 +08:00
OG T
a30713b292 fix(chat): NemoClaw 禁止自稱 DeepSeek + 強制繁體中文
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 13m36s
- 明確禁止透露底層模型身分
- 強制繁體中文(禁簡體)
- 補充 SRE 專長範圍定義

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 01:18:18 +08:00
OG T
e672635edf fix(test): 更新 TestHistoryMessageFormat 適配 Phase 27 雙層策略
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 01:12:00 +08:00
OG T
88ac1c7f50 feat(phase27): 歷史按鈕雙層頻率統計 + DB frequency_snapshot 持久化
Some checks failed
CD Pipeline / build-and-deploy (push) Failing after 1m44s
- telegram_gateway: _send_incident_history 改為 Phase 27 雙層策略
  Layer 1: DB frequency_snapshot (建立時刻永久快照)
  Layer 2: Redis AnomalyCounter disposition 累積統計 (35d TTL)
  修復舊版呼叫 record_anomaly() 導致誤計數的 bug
- 新增 migration: phase27_incident_frequency_snapshot.sql (已在 prod 執行)
- CLAUDE.md: 精簡至 123 行,減少 Token 消耗

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 01:06:51 +08:00
OG T
9846a6cc93 feat(incident): Phase 27 frequency_snapshot DB 持久化 — incidents 表新增 JSONB 欄位
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
frequency_stats 原僅存 Redis(TTL 35天),Pod 重啟或超期即失
- incidents.frequency_snapshot JSONB:建立 incident 時寫入快照,永久保存
- incident_repository: _record_to_incident 還原 IncidentFrequencyStats
- _incident_to_record_data 序列化 frequency_stats 快照到 DB
- Migration: phase27_incident_frequency_snapshot.sql 已執行完成

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 01:05:41 +08:00
OG T
ae90c36cd7 fix(telegram): _send_incident_history 加入 freq=None fallback — 無頻率統計資料
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
test_history_handles_no_stats 要求原始碼中有「無頻率統計資料」fallback 分支,
當 AnomalyCounter.record_anomaly() 回傳 None 時顯示此訊息而非繼續處理。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 01:01:19 +08:00
OG T
e59f8181b3 fix(telegram): 歷史按鈕改從 AnomalyCounter(Redis) 讀頻率,修復永遠顯示「無頻率統計資料」
Some checks failed
CD Pipeline / build-and-deploy (push) Failing after 1m45s
根本原因: frequency_stats 從未持久化到 DB,get_by_id() 回傳永遠是 None
修復: 用 AnomalyCounter.derive_key_from_incident() 推導 anomaly_key,
直接從 Redis 查即時頻率與處置分佈統計

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 00:56:23 +08:00
OG T
e2c6ca598e fix(approval_db): update_telegram_message 用 raw SQL + CAST BIGINT 避免 int32 overflow
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
telegram_chat_id 為 BIGINT (5619078117 > 2^31-1),SQLAlchemy ORM 會推斷為 $N::INTEGER
改用 raw SQL + CAST(:telegram_chat_id AS BIGINT) 繞過型別推斷

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 00:53:50 +08:00
OG T
dbb8104557 fix(drift): kubectl not found + RBAC services/configmaps/ingresses
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
drift_detector 用 kubectl 比對 Git YAML vs K8s 實際狀態,但:
1. API image 沒有 kubectl binary → No such file or directory: 'kubectl'
2. awoooi-executor ClusterRole 缺少 services/configmaps/ingresses list 權限

修復:
- Dockerfile: apt install curl + download kubectl v1.29.0 amd64
- 07-rbac.yaml: 加入 services/configmaps (core) + ingresses (networking.k8s.io) get/list/watch

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 00:49:56 +08:00
OG T
0571ad15d5 fix(signoz_webhook): AIDataImpact.value 大寫 → .lower() 轉 DataImpact
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
AIDataImpact enum value 為 'NONE'/'READ_ONLY' 等大寫,
DataImpact enum value 為 'none'/'read_only' 等小寫,
轉換時補 .lower() 避免 ValueError。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 00:38:29 +08:00
OG T
c132fd423a fix(drift): COPY k8s/ 進 API image — drift_detector Git state 比對
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
drift_detector 的 GitStateReader 需要讀 k8s/*.yaml 來比對 K8s 實際狀態,
但 API Pod 沒有此目錄導致 k8s_dir_not_found,掃描結果永遠為空。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 00:23:54 +08:00
OG T
5d591c4639 fix(drift_repository): CAST(:param AS jsonb) 取代 :param::jsonb
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
asyncpg 不支援 named param 混用 :: cast 語法,導致 PostgresSyntaxError。
改用 CAST() 函數語法,與 SQLAlchemy text() named params 相容。

影響: drift_reports 現在可正常寫入 DB

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 00:22:43 +08:00
OG T
7e498621e0 fix(signoz_webhook): AIBlastRadius → BlastRadius 型別轉換
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
blast_radius 欄位傳入 AIBlastRadius 物件導致 Pydantic validation error,
approval 無法存進 DB(Telegram 仍送出但無法批准)。

修法:明確轉換 AIBlastRadius → BlastRadius,data_impact enum 用 .value 橋接。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 00:15:40 +08:00
OG T
a303b5ef91 feat(chat): NemoClaw 改接 Ollama 111 deepseek-r1:14b
Some checks failed
CD Pipeline / build-and-deploy (push) Failing after 4m6s
2026-04-09 ogt: 棄用 Claude Haiku,改用本地 deepseek-r1:14b
- 端點: http://192.168.0.111:11434
- 過濾 <think>...</think> 推理區塊,只回傳結論
- timeout 120s(14b 推理較慢)
- 完全免費,不計入 Claude API 費用

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 23:38:57 +08:00
OG T
62cb274735 feat(host_aggregator+k8s): 新增 121 K3s Worker 主機監控
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
HOST_CONFIGS 加入 192.168.0.121(K3s Worker):
- K3s API tcp:6443
- awoooi-api NodePort tcp:32334
- awoooi-web NodePort tcp:32335

NetworkPolicy 補開 121 egress: 6443/32334/32335
NodePort 服務實際在 121(mon1),非 120(mon)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 23:36:36 +08:00
OG T
2bc2a2f174 test(integration): drift API + DB 持久化整合測試
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
覆蓋 GET /drift/reports、POST /drift/internal/scan
驗證掃描後 DB 有新資料(B5 整合測試框架擴充)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 23:36:17 +08:00
OG T
fc9d0f9c1f fix(host_aggregator): total=1 時 total//2=0 導致服務全 up 仍顯示 unhealthy
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
112(Kali) 和 120(K3s) 各只有 1 個服務,down_count=0 >= total//2=0
永遠成立 → 永遠 unhealthy。改為 total > 1 才套用 >=half 門檻。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 23:35:37 +08:00
OG T
d324dd7aed fix(telegram): 移除所有告警訊息欄位截斷限制,放寬至 Telegram 4096 字元硬限
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
問題:root_cause[:50/100]、suggested_action[:80]、suggestion[:50]、
note[:150]、fix_action[:100]、impact[:150]、hypothesis[:200]
以及 message[:900]/[:1000] 導致告警內容顯示不完整。

修復:移除欄位截斷,整體上限改為 4096(Telegram API 硬限制)。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 23:32:51 +08:00
OG T
eb46079b4a fix(telegram): root_cause 顯示長度 50→100 字元,符合 SOUL.md 鐵律
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
SOUL.md 明定根因摘要上限 100 字元,但程式碼兩處 IncidentApprovalCard
均截在 [:50],導致告警卡片訊息被截斷。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 23:30:58 +08:00
OG T
c92cdeea0f feat(drift): B4 drift_reports DB 持久化 + CronJob 修復
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 12m17s
- drift_repository.py: DriftReportRepository (save/get/list/update)
- drift.py router: 移除 in-memory dict,改用 DB repository
- drift-cronjob.yaml: 修正 SA/NetworkPolicy/NodePort 問題
- allow-intra-namespace NetworkPolicy (已套用至 prod)
- migrate-phase8/9: symptoms_hash + drift_reports migration Job YAML

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 20:28:55 +08:00
OG T
b1e207ffae fix(host_aggregator): E2E驗證後修正 HOST_CONFIGS — Ollama位置+NodePort+Nginx
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
從 K3s Pod 內 Python socket 實測確認後修正:
- 110: 加 Prometheus(9090) Grafana(3002),移除 GH Runner(3000 refused)
- 112: 移除 SSH:22 (K3s Pod NetworkPolicy 未開)
- 120: 移除 awoooi NodePort(只在121不在120)
- 188: 移除 Ollama(在111非188) 和 Nginx:443(Pod內打不通)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 20:27:46 +08:00
OG T
21567a7a6d fix(host_aggregator): 修正四台主機 probe 端點錯誤導致全部顯示 unhealthy
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 12m1s
- 110: Harbor http→tcp(5000), Docker 2375→Gitea tcp(3001)
- 120: K3s 6443 https(401誤判)→tcp, 移除 Traefik 80(closed)
- 188: OpenClaw 8089→8088 (實際端口)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 19:52:34 +08:00
OG T
8c2983b70a fix(api+web): CORS 補 K3s NodePort origins + sign 補 signer_id/name
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
CORS (config.py):
- 補 http://192.168.0.125:32335 (K3s VIP NodePort)
- 補 http://192.168.0.120:32335 + 121:32335 (K3s nodes)
- 修前: 內網瀏覽器開 :32335 打 API 全 CORS blocked
  (incidents Failed to fetch / monitoring 無法連線根因)

sign body (pending-approvals-card.tsx):
- signer: 'web-ui' → signer_id: CURRENT_USER.id + signer_name: CURRENT_USER.name
- 修前: POST /approvals/{id}/sign 回 403 (缺必填欄位 422 誤報為 403)
  — 實際是 422 Field required signer_id + signer_name

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 19:50:48 +08:00
OG T
34f0228d92 fix(executor): K8s ClusterIP 10.43.0.1 不可達 — 加 K8S_API_SERVER_URL 覆蓋 + migration job
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 12m0s
問題: in-cluster config 讀到 10.43.0.1:443,但 K3s Pod 內 iptables/kube-proxy
      沒把流量導到實際 API server,導致 Connection refused,批准後 kubectl 永遠失敗

修復:
- executor.py: load_incluster_config() 後讀 K8S_API_SERVER_URL env 覆蓋 host
- 04-configmap.yaml: 設 K8S_API_SERVER_URL=https://192.168.0.120:6443
- migrate-sprint5r-telegram-message-id.yaml: approval_records 新增兩欄 migration job

E2E 驗證: kubectl rollout restart deployment/awoooi-worker success=True 

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 19:10:27 +08:00
OG T
ebccb88278 fix(approval_db): 修復 incident_id 篩選查空 DB 欄位而非 JSON 導致執行斷路
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
get_all_approvals(incident_id=...) 原本在應用層過濾
a.metadata.get("incident_id"),但 ApprovalRecord.incident_id
是直接欄位,不在 extra_metadata JSON,導致永遠返回空列表,
Telegram 批准後出現 telegram_approval_not_found_by_incident,
審批從未實際執行。改為 .where(ApprovalRecord.incident_id == incident_id)
DB 層直接篩選,同時效能更佳。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 19:05:48 +08:00
OG T
896bef94ee fix(web): pending-approvals-card 加防重複點擊 + loading 狀態
linter 自動強化: actioningId state 防止同一張卡重複操作
- disabled + opacity 0.6 + cursor not-allowed
- loading 時按鈕顯示 '...'
- finally() 確保 actioningId 清除

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 18:38:08 +08:00
OG T
890e2a9568 fix(review): 架構審查修復 — P0 import crash + i18n 零 hardcode + 靜默錯誤
P0:
- proposal_service.py: 補 get_redis + INCIDENT_KEY_PREFIX import
  (修前: resolve_incident_after_approval 必 NameError crash)

P1 i18n:
- page.tsx: 拓撲群組移除 emoji,改用 tTopo() i18n key
- page.tsx: 主機標籤 (DevOps金庫等) 改 tTopo() i18n
- ai-model-status.tsx: 加 useTranslations,AI 模型狀態 → t('aiModelStatus')
- disposition-mini.tsx: 查看完整報表 → t('viewAllReport')
- recent-activity.tsx: 查看活動串流 → t('viewAllAlerts')

P2 品質:
- pending-approvals-card.tsx: approve/reject 加 r.ok 檢查+錯誤顯示,查看全部授權加路由+i18n
- page-tabs.tsx: TabSkeleton 載入中... → t('loading')
- page.tsx: ↑5% → tDashboard('trendUp', {pct}) 動態值
- page.tsx: Prometheus '23' hardcode → '-- targets'

i18n 新增 key (zh-TW + en 同步):
- dashboard: viewAllAlerts/viewAllAuth/viewAllReport/aiModelStatus/loading/trendUp
- topology: groupExternal/allReachable/investigating/hostDevops/hostAiData/hostK3sMaster/hostK3sWorker

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 18:34:50 +08:00
OG T
1483218bab feat(approval): 批准/拒絕後立即回應 Telegram + 持久化 message_id 到 DB
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 13m9s
問題:按下 TG 批准/拒絕按鈕後完全沒有任何回應,使用者不知道是否成功。
      Telegram message_id 只存 Redis 24h TTL,過期後無法追蹤。

修正:
- approval_records 加 telegram_message_id / telegram_chat_id 欄位(已 ALTER TABLE)
- approval_db.update_telegram_message() — 持久化 message_id 到 DB
- decision_manager: 發送告警卡片後同時寫 Redis + DB
- telegram_gateway._notify_approval_result() — 批准/拒絕後:
    1. editMessageReplyMarkup 移除批准/拒絕按鈕,保留資訊按鈕
    2. sendMessage reply_to 在原訊息下回覆狀態行
    3. fallback: send_notification 發新訊息
- _handle_group_command: chat_id 改為 _chat_id 消除 IDE lint

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 18:19:31 +08:00
OG T
2c7d5d049c fix(openclaw): Nemotron tool call 回填 kubectl_command,讓批准後執行器能解析
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
根本問題:Nemotron 產生的 restart_deployment(deployment_name=sentry) tool call
只存在 nemotron_tools[],沒有回填到 proposal["kubectl_command"]。
proposal_service 拿到的 kubectl_command 是空的,approval_records.action 存空值,
parse_operation_from_action 永遠返回 None,execute_approved_action 永遠 skip。

修正:Nemotron (和 Gemini fallback) 成功後,將 tool call 轉換為 kubectl 指令
並回填 proposal["kubectl_command"],讓 proposal_service 能取到可執行指令。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 18:15:01 +08:00
OG T
ae9780837d fix(proposal): action 優先用 kubectl_command,修復批准後永遠 skip 執行的根本 bug
根本問題:approval_records.action 存的是 LLM action_title(中文標題,如「重啟 sentry 服務」),
parse_operation_from_action() 無法解析,導致 execute_approved_action() 每次都 skip。

修正:action 優先取 llm_proposal["kubectl_command"](可執行的 kubectl 指令),
僅在沒有 kubectl_command 時才 fallback 到 action_title。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 18:13:22 +08:00
OG T
d8c2969341 feat(telegram): AI 鏈路透明化 — 告警訊息顯示 OpenClaw + Tool Calling 模型/後端
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 12m12s
- nemotron.py: 偵測 OllamaToolProvider vs NvidiaProvider,記錄 tool_model/tool_backend
- openclaw.py: 傳播 nemotron_tool_model/nemotron_tool_backend 到 proposal
- decision_manager.py: 從 proposal_data 提取並傳給 send_approval_card()
- telegram_gateway.py: TelegramMessage 新增兩個欄位,format_with_nemotron 顯示
  "🔧 Tool Calling: llama3.1:8b (Ollama 本機)" 或 "NVIDIA 雲端"

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