統帥 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>
17 KiB
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 loop(Phase 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 │
└──────────────────────────────────────────────────────────┘
關鍵設計決定:
- aider error → incident → 既有鏈路:不做另一套告警機制,aider 的錯誤等同 awoooi 其他來源的錯誤,統一 incident table 統一 TG 通道。
- Event 進 Redis stream 再處理:沿用 Phase 6.1 Event Bus pattern。API 層快 response(<50ms),處理在背景。
- AI Router feedback 是學習閉環的核心:這就是「AI 自主化」的體現 — aider-watch 不只是記錄,是餵給 AI Router 讓 model 選擇越來越準。
- symptom_pattern 抽取:日 batch job,把 aider 失敗模式抽成 playbook candidate(跟 Phase 7 blindspot governance 同一機制)。
- 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, AiderSessionEnd(6 種 + 通用外殼) |
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.toml(client 端獨立 pipx 裝) |
~/aider-watch/tests/* |
搬:client 測試留 client,server 測試改寫走 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 type,Mac 客戶端 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
Migration:adr091_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_timeoutaffected_services = [repo_name]signals = {source: "aider_watch", session_id, model, last_error_message}
- incident_service 自動觸發既有 Telegram gateway(dedup 10min TTL 自動生效)
- 建 incident:
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.25且sample_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
@tsenyangbot,chat_id 從 K8s secretTELEGRAM_CHAT_ID讀
aider 非 error 事件(session_start / file_edit / commit):不推 Telegram,只寫 aider_events 表。理由:
- awoooi Telegram 是 告警通道,不該塞正常活動洗版
- 統帥要看活動 → 下次加
/api/v1/aider/activity_feedREST 查詢或前端 dashboard - 若你堅持要推,單獨開
AIDER_WATCH_PUSH_ACTIVITYflag 預設 false
⚠️ v1 @NemoTronAwoooI_Bot 怎麼處理
- 這支 bot 2026-04-19 才建,無生產依賴
- v2 不用它 → 建議 deactivate 或 改用途(例如 aider 測試 sandbox 用)
- 不刪 bot(BotFather 刪除不可逆)
§8 錯誤處理 / 降級策略
| 失敗情境 | 處理 | 結果 |
|---|---|---|
| AWOOOI API 不可達 | Mac client 寫 ~/aider-watch/buffer/*.jsonl;launchd flush job 每 5min 重試 |
不丟資料 |
| HMAC 驗證失敗 | API 回 401,記 audit_log;Mac 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 表,不建 incident;TG 不推(可接受,event 還在) | 不丟資料 |
| secret 外洩 | Mac client 進 buffer 前先 redact;server 再 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→TGfeedback_telegram_dedup.md— Redis dedup 10min TTLfeedback_secrets_leak_incidents_2026-04-18.md— secret 雙層 redactfeedback_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 後續
本設計批准後:
- 寫 v2 plan(
2026-04-20-aider-watch-v2.md) - 暫停
~/aider-watchrepo 開發(Task 6 不跑 install_pg.sh) - 按 v2 plan 執行 server + client 雙半實作
- Mac client 部署在 awoooi repo 而非獨立