Files
awoooi/docs/superpowers/specs/2026-04-20-aider-watch-v2-design.md
Your Name 8ce8efad29 docs(aider-watch): v2 設計稿 — 完全整合 awoooi AI 自主化飛輪
統帥 2026-04-20 指示「C 路線 + 甲 bot」— v1 獨立個人工具路線與
awoooi MASTER blueprint 全景割裂,違反 feedback_ai_autonomous_direction
北極星(純記錄非自主化)。v2 重新對齊:

- DB:進主 PG,新 migration adr091 的 aider_events 表
- Telegram:走既有 telegram_gateway @tsenyangbot + Redis dedup
- Incident:aider error 自動建 incident 走既有告警鏈
- AI 學習回路:symptom_pattern 抽取 + AI Router feedback hook
- Mac client:薄殼 HTTP POST + 本機 JSONL fallback buffer

v1 產物去向:events.py/redactor.py 搬進 awoooi;其他廢棄。
@NemoTronAwoooI_Bot 轉 sandbox 用,不刪。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 04:04:13 +08:00

17 KiB
Raw Blame History

aider-watch v2 設計稿 — 完全整合 awoooi 飛輪版

建立2026-04-20 @ Asia/Taipei 取代v1 2026-04-19(已 DEPRECATED 觸發:統帥 2026-04-20 指示「C 路線 + 甲 bot」— 把 aider-watch 完全整合進 awoooi AI 自主化飛輪,而非獨立個人工具


0. 為何重寫

v1 把 aider-watch 做成 獨立個人工具

  • 獨立 repo ~/aider-watch
  • 獨立 PG DB aider_watch(放 188 但與 awoooi 平行)
  • 獨立 Telegram bot @NemoTronAwoooI_Bot
  • 被動記錄,無 AI 學習

根本問題:純記錄 ≠ AI 自主化。違反 feedback_ai_autonomous_direction.md🔴🔴🔴 最高鐵律的「AI 自主化北極星」— 設計裡沒有 learning、沒有 auto-repair、沒有 decision feedback loop。

v2 方向(統帥批准):

  • 進 awoooi 主 PG新 migration 一張 aider_events 表)
  • 走 awoooi 既有 Telegram 告警鏈(@tsenyangbot + Redis dedup
  • 接進 AI Router feedback loopPhase 24 ADR-052
  • aider error → 自動建 incident(走既有事件管線)
  • 從 aider events 抽 symptom_pattern → 餵 playbooks 學習
  • Mac client 端保留為薄殼,純 HTTP 推送 + 本機 fallback buffer

§1 架構總覽(全景)

┌──────────── 統帥 Mac (外部 agent, K3s 外)────────────┐
│                                                          │
│  aiderw (Python wrapper)                                 │
│    ├ subprocess aider + stdout tee                       │
│    ├ 退出時 git diff / chat_history.md canonical rebuild │
│    ├ redact secrets本地先做一遍                      │
│    └ HTTP POST events → AWOOOI API (HMAC-signed)         │
│                                                          │
│  本機 fallback: ~/aider-watch/buffer/*.jsonl             │
│    API 不可達時寫這裡launchd flush job 5min 補送)   │
│                                                          │
│  本機只留: live.log (append-only, tail -F 用)            │
│  無本機 PG無本機 report                                │
└──────────────┬───────────────────────────────────────────┘
               │ HTTPS + HMAC-SHA256
               ▼
┌────── AWOOOI API (K3s svc 192.168.0.120:32334) ──────────┐
│                                                          │
│  api/v1/aider_events.py                                  │
│    POST /api/v1/aider/events   (HMAC verified)           │
│    → push Redis stream signals:aider:events              │
│                                                          │
│  jobs/aider_event_processor_job.py  (loop, 5s poll)      │
│    ├ consume Redis stream                                │
│    ├ write aider_events table                            │
│    ├ classify:                                            │
│    │   error / non-zero exit / silent_timeout            │
│    │   → 建 incident走 incident_service              │
│    │     severity: silent=P3, error=P2, multi-error=P1   │
│    │     alert_category: aider_activity                  │
│    │   → incident_service 自己觸發 TG (既有 dedup 生效)  │
│    │                                                      │
│    └ 每 day 聚合: extract symptom_pattern                │
│       → 寫 playbooks.symptom_pattern JSONB               │
│         例: {repo: "awoooi", model: "elephant", error_rate: 0.3} │
│                                                          │
│  services/ai_router.py  (既有, Phase 24)                 │
│    新增 hook: feedback_from_aider_events()               │
│    → 讀過去 7 日 aider_events                          │
│      哪 model × 哪 repo/task 成功率 vs 失敗率            │
│    → 調整 route() 的 provider priority                   │
│                                                          │
│  services/telegram_gateway.py  (既有, 不動)              │
│    incident → TG @tsenyangbot + Redis dedup 10min TTL    │
└──────────────────────────────────────────────────────────┘

關鍵設計決定

  1. aider error → incident → 既有鏈路不做另一套告警機制aider 的錯誤等同 awoooi 其他來源的錯誤,統一 incident table 統一 TG 通道。
  2. Event 進 Redis stream 再處理:沿用 Phase 6.1 Event Bus pattern。API 層快 response<50ms處理在背景。
  3. AI Router feedback 是學習閉環的核心這就是「AI 自主化」的體現 — aider-watch 不只是記錄,是餵給 AI Router 讓 model 選擇越來越準。
  4. symptom_pattern 抽取:日 batch job把 aider 失敗模式抽成 playbook candidate跟 Phase 7 blindspot governance 同一機制)。
  5. Mac 端盡量薄:只做 event capture + HTTP POST + local buffer。所有商業邏輯在 server。

§2 元件清單

2.1 AWOOOI 內新增Server 端)

# 檔案 職責 既有模式參考
S1 apps/api/migrations/adr091_aider_events_schema.sql DB migration 既有 adr090_asset_inventory_foundation.sql
S2 apps/api/src/models/aider.py Pydantic: AiderEvent, AiderSessionStart, AiderFileEdit, AiderError, AiderSessionEnd6 種 + 通用外殼) models/incident.py
S3 apps/api/src/repositories/aider_event_repository.py CRUD aider_events + 聚合查詢 repositories/incident_repository.py
S4 apps/api/src/services/aider_event_service.py 分類、建 incident、抽 symptom_pattern services/incident_service.py
S5 apps/api/src/api/v1/aider_events.py POST webhook + HMAC 驗證 api/v1/webhooks.py (Alertmanager)
S6 apps/api/src/jobs/aider_event_processor_job.py Redis stream consumer + 分類 dispatcher + 日 batch pattern extractor jobs/asset_scanner_job.py
S7 apps/api/src/services/ai_router.py 新增 feedback_from_aider_events() 從 aider_events 聚合統計 → 調整 model priority 既有檔改一個 method
S8 apps/api/src/utils/secret_redactor.py 泛用 secret redactor從 v1 搬過來 目前 awoooi 無,新增
S9 apps/api/src/core/config.py 新增 3 個 settings AIDER_WEBHOOK_SECRET, AIDER_EVENTS_STREAM_KEY, AIDER_PATTERN_EXTRACT_INTERVAL_HOURS 既有 core/config.py
S10 apps/api/src/main.py lifespan 註冊 asyncio.create_task(run_aider_event_processor_loop()) 既有 378-382 pattern

2.2 Mac 端Client

位置awoooi/scripts/aider_watch_client/(進 awoooi repo不是獨立 repo

# 檔案 職責
M1 aider_watch_client/aiderw.py subprocess aider + event capture + HTTP POST
M2 aider_watch_client/parsers.py aider stdout banner / chat_history.md / git numstat從 v1 搬)
M3 aider_watch_client/api_client.py HTTP POST with HMAC + retry + buffer fallback
M4 aider_watch_client/buffer.py JSONL buffer本機 fallback
M5 aider_watch_client/install.sh 在 Mac 安裝pipx or venv+ 註冊 launchd flush job
M6 aider_watch_client/launchd/com.awoooi.aider-flush.plist 每 5min flush buffer

2.3 舊 v1 產物去向

v1 產物 v2 處理
~/aider-watch/aider_watch/events.py apps/api/src/models/aider.py(改為 awoooi 命名)
~/aider-watch/aider_watch/redactor.py apps/api/src/utils/secret_redactor.py + 同一份用於 Mac client
~/aider-watch/aider_watch/telegram.py 廢棄(走 awoooi telegram_gateway
~/aider-watch/aider_watch/config.py ⚠️Mac 端用的部分搬進 aider_watch_client/server 的改讀 awoooi core/config.py
~/aider-watch/aider_watch/wrapper.py(未完成) 簡化搬進 aider_watch_client/aiderw.py
~/aider-watch/bin/aiderw aider_watch_client/bin/aiderw
~/aider-watch/pyproject.toml 改為 aider_watch_client/pyproject.tomlclient 端獨立 pipx 裝)
~/aider-watch/tests/* client 測試留 clientserver 測試改寫走 awoooi pytest 約定
~/aider-watch/schema.sql + install_pg.sh 廢棄v2 用 awoooi migration
~/aider-watch/ repo 本身 保留 1 週作備份2026-04-27 後刪(或歸 archive 分支)

§3 Event Schema與 v1 一致,微調)

7 種 event typeMac 客戶端 POST 的 payload shape

{
  "ts": "2026-04-20T10:15:33+08:00",
  "session_id": "01J7XZ...",            // ULID
  "host": "ogt-mac",                      // 將來多機器區分
  "type": "session_start|file_edit|error|commit|silent_timeout|session_end|raw",
  "payload": { ... type-specific (同 v1 §3) }
}

批次推送POST /api/v1/aider/events body 接受 {"events": [...]} 陣列,最多 50 筆/次,降低 HTTP 往返成本。


§4 DB Schema — awoooi 主 PG 新 migration

Migrationadr091_aider_events_schema.sql

-- aider events raw table單一表event + 一次性 session 元資料合一用 JSONB
-- 設計參考: asset_discovery_run pattern
-- 2026-04-20 @ Asia/Taipei

CREATE TABLE IF NOT EXISTS aider_events (
  id              BIGSERIAL PRIMARY KEY,
  session_id      TEXT NOT NULL,
  ts              TIMESTAMPTZ NOT NULL,
  type            TEXT NOT NULL,                -- session_start / file_edit / error / ...
  host            TEXT DEFAULT 'ogt-mac',
  payload         JSONB NOT NULL,
  incident_id     TEXT,                          -- 若觸發建 incident記 FK
  created_at      TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX aider_events_session_idx ON aider_events(session_id);
CREATE INDEX aider_events_type_ts_idx ON aider_events(type, ts DESC);
CREATE INDEX aider_events_ts_idx ON aider_events(ts DESC);
-- payload GIN for 查 repo / model 統計
CREATE INDEX aider_events_payload_gin ON aider_events USING GIN (payload);

-- 不另外建 sessions 表:從 events 聚合session_start + session_end 配對),
-- 查詢性能可接受session 量 <1000/day避免雙寫漂移。

symptom_pattern 抽取:不新增表,直接寫 playbooks 表的 symptom_pattern JSONB既有

{
  "source": "aider_watch",
  "repo": "awoooi",
  "model": "elephant-alpha",
  "task_kind": "refactor",
  "error_rate": 0.35,
  "evidence_session_ids": ["01J...", "01J..."]
}

§5 API 合約

POST /api/v1/aider/events

Request:

POST /api/v1/aider/events
Content-Type: application/json
X-Aider-Signature: sha256=<HMAC-SHA256 of body using AIDER_WEBHOOK_SECRET>
X-Aider-Client: aiderw/0.2.0

{
  "events": [
    { "ts": "...", "session_id": "...", "type": "session_start", "payload": {...} },
    ...
  ]
}

Response:

  • 202 Accepted{"accepted": N, "stream_id": "redis-id"}(快速 ack不等處理完成
  • 401 Unauthorized → HMAC 驗證失敗
  • 400 Bad Request → schema 驗證失敗,回具體錯誤欄位
  • 429 Too Many Requests → 超過 rate limit預設 120 req/min per client
  • 503 Service Unavailable → Redis 不可達client 必須 fallback 到 buffer

HMAC 驗證

import hmac, hashlib
expected = "sha256=" + hmac.new(
    AIDER_WEBHOOK_SECRET.encode(),
    request.body, hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected, signature):
    abort(401)

§6 AI 學習回路

6.1 incident 自動建立(即時)

aider_event_service.handle_error_event(ev)

  • type in {"error", "session_end with exit≠0", "silent_timeout"}
    • 建 incident:
      • alert_category = "aider_activity"
      • severity = P1 if error_count>=3 else P2 if error else P3 if silent_timeout
      • affected_services = [repo_name]
      • signals = {source: "aider_watch", session_id, model, last_error_message}
    • incident_service 自動觸發既有 Telegram gatewaydedup 10min TTL 自動生效)

6.2 symptom_pattern 日 batch 抽取

aider_event_processor_job.extract_patterns_daily()(每日 02:30 台北):

  • 聚合近 7 日 aider_events
  • group by (repo, model, task_kind)
  • 計算 error_rate / avg_tokens / avg_duration
  • error_rate >= 0.25sample_n >= 3 → 寫 playbook candidate

6.3 AI Router feedback hook每次 route() 呼叫)

ai_router.py 加:

def feedback_from_aider_events(repo: str, task_kind: str) -> dict[str, float]:
    """回傳 {model_name: success_rate} based on past 7 days aider usage."""
    # 從 aider_event_repository 聚合
    return {"elephant-alpha": 0.85, "gemini-pro": 0.92, ...}

AIRouter.route() 內:如果有 feedback data把 provider 權重乘 success_rate


§7 Telegram 整合

100% 複用既有 services/telegram_gateway.py,零新增 bot

  • aider error → incident created → telegram_gateway.send_alert(incident)
  • 訊息格式走 awoooi SOUL.md 標準(不再自訂 🚀/🏁 emoji 模板)
  • Redis dedup telegram_sent:{incident_id} TTL 600s 自動生效
  • bot @tsenyangbotchat_id 從 K8s secret TELEGRAM_CHAT_ID

aider 非 error 事件session_start / file_edit / commit不推 Telegram,只寫 aider_events 表。理由:

  • awoooi Telegram 是 告警通道,不該塞正常活動洗版
  • 統帥要看活動 → 下次加 /api/v1/aider/activity_feed REST 查詢或前端 dashboard
  • 若你堅持要推,單獨開 AIDER_WATCH_PUSH_ACTIVITY flag 預設 false

⚠️ v1 @NemoTronAwoooI_Bot 怎麼處理

  • 這支 bot 2026-04-19 才建,無生產依賴
  • v2 不用它 → 建議 deactivate改用途(例如 aider 測試 sandbox 用)
  • 不刪 botBotFather 刪除不可逆)

§8 錯誤處理 / 降級策略

失敗情境 處理 結果
AWOOOI API 不可達 Mac client 寫 ~/aider-watch/buffer/*.jsonllaunchd flush job 每 5min 重試 不丟資料
HMAC 驗證失敗 API 回 401audit_logMac client 留 buffer 等人工介入 防偽造
Redis stream 滿 自動 trim 10k 筆上限;溢位寫 audit_log warning 不阻塞 API
aider_event_processor 掛 既有 main.py lifespan supervisor 會重啟;消費位置從 Redis stream consumer group 恢復 自癒
incident_service 建 incident 失敗 降級:只寫 aider_events 表,不建 incidentTG 不推可接受event 還在) 不丟資料
secret 外洩 Mac client 進 buffer 前先 redactserver 再 redact 一次depth-in 雙層防線
wrapper 崩潰 aiderw 外層 try/except 全包atexit 補 session_end aider 照跑
aider 本身崩潰 wrapper 收 SIGCHLD → 送 error event + session_end exit≠0 死得清楚

§9 測試策略

遵循 feedback_no_mock_testing.md

層級 範圍 工具 通過標準
Unit (server) models schema, secret_redactor, HMAC 驗證, pattern extractor pytest 100% pass
Unit (client) aiderw parsers, api_client retry, buffer write pytest 100% pass
Integration (server) 真寫 PG aider_events, Redis stream round-trip pytest + real PG (168 test schema) round-trip OK
Integration (client→server) Mac client POST events → server 消費 → 寫 DB → 查詢 本機 pytest + 打 awoooi API 全流程通
E2E happy 真 aiderw 跑一次 aider →events 進 awoooi DB → 若 error 建 incident → TG 收到 手動 TG 收到(走 @tsenyangbot 不是新 bot
E2E degradation 拔網路跑 aiderw → buffer 有檔 → 網路恢復 + flush job 跑 → buffer 清空 + DB 補齊 手動 buffer → DB 無漏
AI Router feedback 灌 10 場 aider session 資料 → 查 ai_router.feedback_from_aider_events 回傳值 → 驗 success_rate 合理 pytest 數值正確

§10 相關 Memory 依據

  • feedback_ai_autonomous_direction.md 🔴🔴🔴 — AI 自主化北極星(這是 v2 存在的根本原因)
  • feedback_alertmanager_awoooi_flow.md — 告警鏈路 Alertmanager→AWOOOI API→TG
  • feedback_telegram_dedup.md — Redis dedup 10min TTL
  • feedback_secrets_leak_incidents_2026-04-18.md — secret 雙層 redact
  • feedback_architecture_review_gates.md 🔴🔴 — 重大方向變更需架構 review本 v2 就是)
  • feedback_solution_adoption_checklist.md — 解決方案導入 7 問(已對照)
  • project_master_aiops_blueprint.md — AI 自主化 MASTER blueprint 全景
  • project_blindspot_governance.md 🔴🔴🔴 — Phase 7 盲區治理symptom_pattern 抽取沿用)
  • project_phase24_ai_router.md — AI Router D1-D14 決策

§11 後續

本設計批准後:

  1. 寫 v2 plan2026-04-20-aider-watch-v2.md
  2. 暫停 ~/aider-watch repo 開發Task 6 不跑 install_pg.sh
  3. 按 v2 plan 執行 server + client 雙半實作
  4. Mac client 部署在 awoooi repo 而非獨立