Commit Graph

3678 Commits

Author SHA1 Message Date
OG T
25cc0fb4b2 fix(ci): 使用正確的 Telegram Secret 名稱
OPENCLAW_TG_BOT_TOKEN, OPENCLAW_TG_CHAT_ID (已存在)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 12:20:42 +08:00
OG T
a61ea2f14d feat(ci): Phase 18.3 Daily E2E Health Check
每日 08:30 (台北) 自動執行 E2E 驗證:
- Alert → AI → Approval → Execution 完整流程
- Safe Mode 防護 (dry_run=true)
- 失敗時 Telegram 通知

需配置 Secrets:
- TELEGRAM_BOT_TOKEN
- TELEGRAM_CHAT_ID

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 12:20:14 +08:00
OG T
1cc34e1fc8 fix(api): Phase 18.1 修復 - Mock Response 正規化遺漏
問題: _generate_mock_response() 直接使用原始 target_resource,
導致 URL (如 https://api.awoooi.wooo.work) 未正規化為有效 K8s 名稱

修復: 在 _generate_mock_response() 開頭加入 normalize_resource_name()
- 將 URL/域名轉換為有效 deployment 名稱
- 更新 namespace 為正確值 (awoooi-prod)

測試: E2E 驗證待部署後執行

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 12:07:16 +08:00
OG T
505ff7a809 docs: LLM 測試評估 + Ollama GPU 問題發現
評估結果:
- Ollama 使用 CPU 推理 (VRAM=0GB)
- 生成速度 0.45 tok/s (正常 10-20x)
- 這是 CI LLM 測試失敗的根因

決策:
- ADR-018 三層框架暫緩整合
- 優先修復 Ollama GPU 問題
- 再實施方案 A (seed 參數)

新增:
- docs/evaluations/2026-03-26_llm_testing_evaluation.md
- feedback_solution_adoption_checklist.md (7問評估清單)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 11:47:49 +08:00
OG T
96c3ddd8c4 feat(api): Phase 18.1 K8s 資源名稱驗證 (ADR-016)
三層防禦架構確保 kubectl 指令有效:
1. Webhook 入口正規化 (webhooks.py)
2. OpenClaw 產生指令前驗證 (openclaw.py)
3. 靜態映射表 + 模糊匹配 (k8s_naming.py, resource_resolver.py)

新增:
- src/utils/k8s_naming.py: RFC 1123 正規化 + 靜態映射
- src/services/resource_resolver.py: MCP K8s Tool 動態驗證
- docs/adr/ADR-016-k8s-resource-naming.md: 契約文檔
- scripts/e2e_tool_call_verification.py: E2E 驗證腳本 v2.0

修改:
- webhooks.py: Phase 18.1.7 入口正規化
- openclaw.py: Phase 18.1.6 產生指令前驗證
- Skill 03 v1.4: 新增 K8s 資源驗證章節

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 11:22:47 +08:00
OG T
fe7fd7a3e0 feat(tests): ADR-018 LLM 測試策略三層架構
問題: LLM 測試因模型波動導致 CI 失敗

解決方案: 三層測試策略
- Tier 1 (CI): Schema 驗證 + Golden Responses
- Tier 2 (Nightly): 屬性測試 + Live LLM
- Tier 3 (Weekly): 語意相似度測試

新增檔案:
- ADR-018-llm-testing-strategy.md
- tests/llm_testing/ 框架
  - schema_validators.py: Pydantic Schema 驗證
  - property_validators.py: kubectl/風險等級驗證
  - golden_responses.py: 預錄回應管理
- tests/test_llm_tier1_schema.py: 35 個 Tier 1 測試

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 11:17:00 +08:00
OG T
281175921c docs: 更新 LOGBOOK - Phase 7.5-7.6 完成
- 新增 Phase 7.5-7.6 進度紀錄
- 更新當前狀態

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 11:09:55 +08:00
OG T
2e75a20150 feat(api): Phase 7.5-7.6 Playbook 整合決策與自動萃取
Phase 7.5: DecisionManager 三軌決策
- 新增 Playbook 優先匹配 (similarity >= 85%)
- 三軌決策順序: Playbook > LLM > Expert System
- 整合 PlaybookService 推薦引擎

Phase 7.6: 自動萃取機制
- approval_execution.py 成功執行後觸發萃取
- 條件: RESOLVED/CLOSED + effectiveness >= 4
- 滿分 (5) 自動核准 Playbook

測試:
- 13 個 Playbook 單元測試全部通過
- 修復 Incident 模型欄位對應 (reasoning_steps)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 11:09:25 +08:00
OG T
6f99113888 docs: 更新 LOGBOOK - #7 Playbook + ADR 審計 + Phase 13 審查 2026-03-26 10:54:46 +08:00
OG T
698687f092 feat(api): #7 Playbook 萃取功能 (Phase 7.1-7.4)
實作內容:
- models/playbook.py: Playbook 資料模型 + Request/Response
- repositories/playbook_repository.py: Redis 雙層儲存
- repositories/interfaces.py: IPlaybookRepository Protocol
- services/playbook_service.py: 業務邏輯 (萃取/推薦/核准)
- api/v1/playbooks.py: REST API 端點

API 端點:
- POST /playbooks/extract/{incident_id} - 從成功案例萃取
- POST /playbooks/recommend - 症狀匹配推薦
- POST /playbooks/{id}/approve - 人工核准
- GET/PATCH/DELETE /playbooks/{id} - CRUD

遵循 leWOOOgo 積木化: Router → Service → Repository

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 10:54:13 +08:00
OG T
8a163609bf docs(adr): 更新 ADR-006/009/015 狀態
ADR-015: 標記為「已實作」 (Phase 16 R1 完成)
ADR-009: 標記為「已實作」 (Phase 9.1-9.5 全部完成)
ADR-006: 新增智能路由整合章節 (Phase 13.3)

首席架構師 ADR 審計 P0/P1 完成

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 10:45:29 +08:00
OG T
648e100e3c fix(tests): 修復測試 lint 錯誤 + TelegramGateway 方法呼叫
修復項目:
1. 新增 conftest.py 確保環境變數在 settings 前載入
2. test_github_webhook.py 移除重複的 os.environ 設定 (E402)
3. test_smart_router.py 排序 import (I001)
4. github_webhook.py 修正 send_message → send_notification

Phase 13.1 首席架構師審查修復

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 10:37:45 +08:00
OG T
a22ee766da fix(tests): 修復 lint 錯誤 (I001, F401)
- test_smart_router.py: 移除未使用的 pytest import
- test_github_webhook.py: 修正 import 排序

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 10:16:04 +08:00
OG T
0003098c55 docs(adr): ADR-017 LLMOps Observability 三層觀測架構
建立 Phase 15 LLMOps 觀測架構決策文件,記錄:
- 三層觀測架構 (Langfuse + SignOz + Sentry)
- Langfuse 整合與 Deep Linking 實作
- Redis Streams Trace Context 傳遞機制
- 取樣率策略與成本估算

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 10:13:12 +08:00
OG T
24e35fee1b docs(adr): ADR-016 智能路由 (Smart Routing)
新增 Intent + Complexity → Model Selection 架構決策文件,
作為 ADR-006 (AI Fallback) 的補充,實現動態模型選擇。

- IntentClassifier: 關鍵字優先 + LLM 備援
- ComplexityScorer: 規則引擎加權評分
- AIRouter: 整合路由決策

Phase 13.3 #85-87

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 10:13:05 +08:00
OG T
42659a271a docs(adr): ADR-014 Dependency Governance 依賴治理
建立前端依賴治理規範文件,.dependency-cruiser.cjs 已參照此 ADR。

內容包含:
- Layer Model 四層架構定義
- Feature Isolation 規則說明
- CI 整合配置 (pnpm dep-check)
- Severity 分級策略

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 10:12:43 +08:00
OG T
0060a33e31 feat(api): Phase 13.1 #74 GitHub Webhook → OpenClaw 整合
- POST /api/v1/webhooks/github endpoint
- 處理 pull_request 和 push 事件
- 驗證 X-Hub-Signature-256
- Telegram 通知整合
- GitHubWebhookService 封裝 Redis 操作 (leWOOOgo 合規)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 10:08:54 +08:00
OG T
957150a156 fix(api): 移除 intent_classifier 未使用 import (F401)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 10:06:43 +08:00
OG T
92ee07ad4b refactor(api): Phase 17 agents.py Router 層違規修復
- 建立 AgentService 封裝所有 Redis 操作
- 定義 IAgentTaskRepository Protocol 介面支援 DI
- Router 層改用 AgentService,不再直接 get_redis()
- 符合 leWOOOgo 積木化原則 (Router → Service → Repository)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 10:02:31 +08:00
OG T
e7f361db50 refactor(api): Phase 17 metrics.py Router 層違規修復
移除 Router 層直接 DB 存取,遵循 leWOOOgo 積木化原則:
- 新增 IMetricsRepository Protocol (interfaces.py)
- 新增 MetricsDBRepository 封裝 DB 查詢
- 新增 MetricsService 封裝業務邏輯
- Router 層只做 HTTP 轉發

架構: Router → Service → Repository → PostgreSQL

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 10:01:57 +08:00
OG T
58b4004a18 feat(api): Phase 13.3 智能路由 (#85-87)
- IntentClassifier: 意圖分類 (告警/部署/查詢/維運/審查)
- ComplexityScorer: 複雜度評分 (1-5 分)
- AIRouter: 動態模型選擇 (整合 Intent + Complexity)
- 測試: 完整單元測試覆蓋

Phase 13.3 設計: project_phase13_3_smart_router.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 10:01:04 +08:00
OG T
496c569d51 docs: 紅區治理 + 部署文檔更新
- RED_ZONES.md: Tier 3/2 紅區清單
- setup-hooks.sh: Git Hook 安裝腳本
- infrastructure docs: 部署拓撲更新

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 09:55:58 +08:00
OG T
604e38cf07 docs: Phase 14 紅區治理 + Skills 01/03 更新
- CLAUDE.md: 紅區治理章節
- Skills 01/03: 版本更新
- ADR/Architecture: 標準化

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 09:55:47 +08:00
OG T
9ea246c7c2 docs(logbook): Phase 12.4 取消 + 狀態更新
統帥裁定: 現有 Ollama→Gemini→Claude fallback 已足夠

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 09:55:09 +08:00
OG T
163d94a35b docs(skills): Phase 14.2 CI/CD 架構審查 + dependency-cruiser 整合
- Skill 04: Runner 殭屍進程修復 + cancel-in-progress: false
- Skill 05: 新增 SRE QA 內容
- Skill 06: dependency-cruiser 依賴治理 (Layer Model + ADR-014)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 09:53:56 +08:00
OG T
45c3656004 fix(api): 修正 langfuse_client import 排序 (I001)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 09:37:09 +08:00
OG T
46ab6a838a fix(api): 修復 ruff lint 錯誤
- langfuse_client.py: import Callable from collections.abc
- telemetry.py: import block 格式化

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 09:27:00 +08:00
OG T
0172dad197 feat(ci): Phase 14.2 dependency-cruiser 整合
- 新增 pnpm dep-check 腳本
- CI lint job 新增 Dependency Check 步驟
- 修復 tsPreCompilationDeps (monorepo 相容)

83 模組、57 依賴、0 違規 

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 09:18:51 +08:00
OG T
31f554962e fix(ci): 改用 cancel-in-progress: false 避免 Runner 衝突
Runner 被取消時不會清理 _diag/pages,導致下一次 run 檔案衝突
改為排隊等待而非取消

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 01:08:07 +08:00
OG T
ac294c1e3c fix(ci): 清理 _diag/pages 避免 log 檔衝突
Runner 並行執行時 _diag/pages/*.log 會產生衝突
新增清理該目錄的步驟

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 01:07:07 +08:00
OG T
8ee2437a7f fix(ci): Runner 暫存目錄清理 - 永久修復
- 每個 Job 開始前清理 $RUNNER_TEMP/*
- 新增 crontab 每小時自動清理
- 新增 ~/bin/runner-cleanup.sh 腳本

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 01:05:49 +08:00
OG T
df6ba33a1d fix(k8s): NetworkPolicy 新增 Langfuse LLMOps 連線規則
Phase 15.1 必要: 允許 Pod 連接 Langfuse (192.168.0.110:3100)

變更:
- 新增 port 3100 (Langfuse HTTP API)
- 更新版本 v1.0 → v1.1
- 更新註解說明

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 01:01:20 +08:00
OG T
414e59d55f docs: Phase 15 觀測架構更新 Skills 04/05
Skill 04 v1.5:
- 新增 Phase 15 三層觀測架構章節
- Deep Linking URL 格式說明
- Trace Context 傳遞架構圖

Skill 05 v1.3:
- 新增 Phase 15 觀測性測試章節
- 三系統健康檢查腳本
- Trace Context 驗證測試

參考:
- project_phase15_langfuse.md (Phase 15 完整記錄)
- project_phase17_tech_debt.md (技術債規劃)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 00:58:27 +08:00
OG T
60f8d770dd docs: Phase 15 首席架構師審查通過 + Phase 17 技術債規劃
審查結果:
- 架構分層:  通過
- leWOOOgo 5 問:  通過
- 依賴注入:  通過
- 測試: 46/46 通過

Phase 17 技術債 (統帥批准):
- agents.py: Router 直接存取 Redis
- metrics.py: Router 直接存取 DB

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 00:54:40 +08:00
OG T
b6cff31653 feat(api): Phase 15.3 Deep Linking 三系統互連
實現 Sentry ↔ SignOz ↔ Langfuse 零斷鏈觀測:

新增 deep_linking.py:
- SignOz Trace URL 生成器
- Langfuse Trace URL 生成器
- Sentry Issue URL 生成器
- get_all_links() 統一取得所有連結

整合點:
- main.py: Sentry before_send 注入 otel_trace_id + signoz_trace_url
- langfuse_client.py: 自動注入 OTEL trace_id 到 metadata
- openclaw.py: SignOz span 記錄 langfuse.trace_id 反向連結

架構圖:
┌─────────┐ trace_id ┌─────────┐ trace_id ┌──────────┐
│ Sentry  │◄────────►│ SignOz  │◄────────►│ Langfuse │
│ Errors  │          │ Traces  │          │ LLMOps   │
└─────────┘          └─────────┘          └──────────┘

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 00:48:28 +08:00
OG T
0d31ccb911 feat(api): Phase 15.2 Redis Trace Context 傳遞
實現 Redis Streams 跨服務追蹤零斷鏈:
- telemetry.py: 新增 get_trace_context() + restore_trace_context()
- webhooks.py: Producer 注入 _trace_id, _span_id 到 Redis
- signal_worker.py: Consumer 還原 Trace Context 建立子 Span

架構: API → Redis Streams → Worker 完整追蹤鏈
格式: W3C Trace Context (traceparent)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 00:40:20 +08:00
OG T
1ac8965a7a feat(api): Phase 15.1 Langfuse LLMOps 整合 + 模型升級
## 新功能
- Langfuse 自建部署 (192.168.0.110:3100)
- langfuse_client.py - LLM 呼叫追蹤包裝
- OpenClaw 整合 Langfuse trace

## 模型升級 (統帥批准)
- 生產預設: llama3.2:3b → qwen2.5:7b-instruct
- 摘要任務: llama3.2:3b (速度優先)

## 配置更新
- requirements.txt: +langfuse>=2.0.0
- config.py: +LANGFUSE_* 設定
- models.json: 更新 Ollama 模型配置
- K8s: Secret + ConfigMap 更新

## 審查通過
- 模組化檢查 
- 核心測試 31/31 

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 00:32:19 +08:00
OG T
31fabe8d61 fix(ci): 修復 CI 失敗問題
- lewooogo-core: 新增 placeholder 測試檔 (vitest)
- api: 修復 I001 import 排序 (ruff --fix)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-25 23:57:24 +08:00
OG T
2fb011470e refactor(api): Phase 16 R3.4 完整 Repository 層整合
- incident_repository: 新增 get_status(), update_status() 方法
- incidents.py: feedback + debug 端點全面改用 Repository
- 消除所有 Router 層直接 DB 存取 (符合積木化鐵律)
- trust_engine.py: 修復 import 順序 lint 警告
- pre-commit hook: 修正誤判問題 (排除刪除行+註解行)
- LOGBOOK: 更新 Phase 16 完成狀態

驗證結果: 31/31 測試通過

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-25 23:47:01 +08:00
OG T
e0584bc181 refactor(api): Phase 16 R2 封存死代碼 + RiskLevel 統一
封存 (866 行):
- routes/approvals.py → _archived/routes/ (477 行,未註冊死代碼)
- services/approval.py → _archived/services/ (389 行,僅被死代碼使用)

合併 RiskLevel:
- models/approval.py 新增 HIGH (從 trust_engine.py 合併)
- trust_engine.py 改 import from models/approval.py
- 保留舊定義為註解供回滾

更新 services/__init__.py:
- 移除已封存模組的 import (註解保留回滾路徑)

驗證:
- RiskLevel 統一: models 與 trust_engine 使用同一 class
- 24 個 action_parsing 測試通過

回滾指令見 _archived/README.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-25 23:14:24 +08:00
OG T
0afaea63f8 fix(api): Phase 16 R4 測試修復 - ParsedOperation 向後兼容
問題:
- test_action_parsing.py 導入路徑未更新 (舊: approvals.py)
- ParsedOperation dataclass 不支援 tuple 解包

修復:
- 更新測試導入至 src.services.operation_parser
- 新增 ParsedOperation.__iter__() 支援 tuple 解包

測試: 24/24 passed (100%)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-25 23:00:03 +08:00
OG T
4b3d98cd0b fix(api): 修復 Repository 層 lint 錯誤
- 移除未使用的 imports
- 修正 import 排序

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-25 22:25:52 +08:00
OG T
663b80ab29 chore: 加強 .gitignore 防止 Claude Code 干擾 CI/CD
新增忽略:
- .claude/scheduled_tasks.lock
- .cursor/
- .agents/memory/

防止 worktrees 等 AI 工具暫存檔干擾 checkout

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-25 22:17:08 +08:00
OG T
27f20f4155 fix(git): 移除誤提交的 .claude/worktrees 目錄
此目錄已在 .gitignore 中,但之前被意外 commit
這導致 CI/CD 的 checkout 步驟出現 submodule 錯誤

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-25 22:12:54 +08:00
OG T
716b94f60a feat(api): Phase 16 R4.2 抽取 ApprovalExecutionService
Strangler Fig Pattern: 從 approvals.py 抽取執行編排邏輯

新增:
- src/services/approval_execution.py (271 行)
- ApprovalExecutionService class
- 整合 OperationParser + Executor + Timeline + Notifications

瘦身成果:
- approvals.py: 1097 → 787 行 (-310 行)
- R4 總計: 移除 310 行內嵌業務邏輯

CI/CD 修復:
- 移除危險的 rm -f ~/actions-runner-* 指令
- 改用 checkout clean: true + workspace 內清理

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-25 22:04:15 +08:00
OG T
aefd351e20 docs: 更新 LOGBOOK Phase 16 R4.1 進度
- OperationParser 抽取完成
- approvals.py 瘦身 1097 → 988 行
- Runner diag log 衝突問題記錄

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-25 21:57:38 +08:00
OG T
31cf2ddbe7 feat(api): Phase 16 R4.1 抽取 OperationParser 模組
Strangler Fig Pattern: 從 approvals.py 抽取操作解析邏輯

新增:
- src/services/operation_parser.py
- ParsedOperation dataclass
- 支援中英文指令解析 (kubectl/自然語言)

瘦身 approvals.py: 移除 117 行內嵌邏輯

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-25 21:52:27 +08:00
OG T
39eca4535b fix(ci): 清理 Runner diag logs 避免 "file already exists" 衝突
Pre-flight Check 加入清理步驟:
- rm -f ~/actions-runner-awoooi/_diag/pages/*.log
- rm -f ~/actions-runner-awoooi-2/_diag/pages/*.log

同時修復 CI 和 CD workflow

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-25 21:49:17 +08:00
OG T
0e22680547 fix(cd): 清理 worktree 目錄避免 submodule 衝突
Deploy job 增加 rm -rf .claude/worktrees 清理步驟
解決 "no submodule mapping found" 錯誤

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-25 21:46:51 +08:00
OG T
f6a28d235c feat(api): Phase 16 R3.4 ApprovalDBService DI 重構
變更:
- ApprovalDBService 新增 __init__(repository) 建構子
- get_approval() 支援 Repository 注入
- get_pending_approvals() 支援 Repository 注入
- get_approval_service(use_repository=True) 啟用 DI

絞殺者模式:
- use_repository=False (預設): 內嵌 DB 操作
- use_repository=True: 使用 ApprovalDBRepository

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-25 21:26:23 +08:00