## Phase 1-3: Control Plane + Contract System - awooop_phase1_control_plane_2026-05-04.sql: 12 張核心表 + RLS - awooop_phase1_batch1_rls_2026-05-04.sql: 全部 FORCE RLS + GRANT - packages/awooop-contracts/: 六合約 JSON Schema + golden fixtures - src/models/awooop_contracts.py: Pydantic v2 contract models(extra=forbid) - src/repositories/contract_repository.py: contract lifecycle(draft→published→active) - src/services/contract_service.py: HMAC publish sig + Redis multi-sig activate - src/services/schema_validator.py: LLM output validator(retry×3, E-SCHEMA-001) ## Phase 2: Tenant Isolation - awooop_phase2_budget_ledger_2026-05-04.sql: budget_ledger + RLS - src/services/budget_service.py: Token Budget Hard Kill 三層防線 - src/core/context.py: PROJECT_ID ContextVar(31 background loop 自動繼承) - src/db/base.py + models.py: project_id 欄位 + RLS set_config 注入 - src/hermes/nl_gateway.py: project_id Redis key 前綴(Phase A 雙寫) - src/services/anomaly_counter.py: per-project 改造(Phase A fallback) ## Phase 4: Platform Shell in Shadow Mode - awooop_phase4_run_state_2026-05-04.sql: run_state + step_journal + idempotency - src/services/run_state_machine.py: 8-state FSM + SKIP LOCKED + stale reaper - src/services/platform_runtime.py: UUID v7 + W3C trace_id + shadow_execute - src/services/audit_sink.py: PII/secret redaction 9 patterns - src/api/v1/platform/runs.py: POST/GET /v1/platform/runs(Router→Service 架構) - src/workers/platform_worker.py: SKIP LOCKED worker + heartbeat + reaper loop - src/main.py: platform router + lifespan worker start/stop ## Phase 5: MCP Gateway 五閘門 - awooop_phase5_mcp_gateway_2026-05-04.sql: 4 表 + RLS - src/plugins/mcp/gateway.py: McpGateway(Gate 1~5, E-MCP-GATE-001~009) - src/plugins/mcp/redaction_middleware.py: 雙層 redaction + 16K 截斷 - src/plugins/mcp/registry.py: __provider name mangling(ADR-116) - src/plugins/mcp/credential_resolver.py: k8s secret ref 解析 - tests/test_mcp_credential_isolation.py: 10 個迴歸測試(secret leak 防再現) ## Phase 6-8: EwoooC + Channel Hub + Approval Token - awooop_phase6_ewoooc_onboarding_2026-05-04.sql: ewoooc tenant + 4 read-only MCP tools - awooop_phase7_channel_hub_2026-05-04.sql: conversation_event + outbound_message - src/services/provider_proxy.py: ProviderProxy + PlatformEnvelope(ADR-115) - src/services/channel_hub.py: Telegram inbound mirror + Progressive Feedback(30s) - src/services/awooop_approval_token.py: HS256 + jti NX replay 防護 + suggest mode Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
111 lines
5.6 KiB
Markdown
111 lines
5.6 KiB
Markdown
# INV-8: Background Loop Catalog
|
||
|
||
**版本**:v1.0 初稿
|
||
**日期**:2026-05-03(台北)
|
||
**來源**:`apps/api/src/main.py` grep asyncio.create_task(實測 31 個)
|
||
**用途**:ADR-123 Background Loop Migration Strategy 的執行基礎
|
||
|
||
---
|
||
|
||
## 概覽
|
||
|
||
| 統計 | 數量 |
|
||
|------|------|
|
||
| 總 background loop | 31 |
|
||
| platform_internal | 2(#27、#30)|
|
||
| legacy_awoooi_default(過渡)| 29 |
|
||
| requires_project_id(Phase 2+ 改造後)| 0(初始)|
|
||
|
||
---
|
||
|
||
## 完整清單
|
||
|
||
> 行號來自 `apps/api/src/main.py`
|
||
> 「頻率」為估計值,需 code review 確認
|
||
|
||
| # | 函數名 | 行號 | 頻率 | 標記 | 改造優先度 | 備註 |
|
||
|---|--------|------|------|------|-----------|------|
|
||
| 1 | `seed_playbooks_from_rules()` | 331 | 啟動一次 | `legacy_awoooi_default` | P3(低)| 只在啟動時跑一次,風險低 |
|
||
| 2 | `backfill_redis_to_pg()` | 341 | 啟動一次 | `legacy_awoooi_default` | P3 | 啟動一次性 backfill |
|
||
| 3 | `ensure_playbook_embeddings_indexed()` | 348 | 啟動一次 | `legacy_awoooi_default` | P3 | 啟動一次性 index 確認 |
|
||
| 4 | `resend_stale_ready_tokens()` | 362 | 每 30s | `legacy_awoooi_default` | P1 | 涉及 approval token,Phase 8 前必改 |
|
||
| 5 | `run_incident_analysis_sweeper()` | 373 | 每 5min | `legacy_awoooi_default` | P2 | 掃描 incident,多 tenant 後需分 project |
|
||
| 6 | `run_asset_scanner_loop()` | 383 | 每 10min | `legacy_awoooi_default` | P2 | K8s asset 掃描 |
|
||
| 7 | `run_rule_catalog_sync_loop()` | 393 | 每 5min | `legacy_awoooi_default` | P2 | 規則 catalog 同步 |
|
||
| 8 | `run_capacity_scanner_loop()` | 403 | 每 15min | `legacy_awoooi_default` | P2 | 容量掃描 |
|
||
| 9 | `run_compliance_scanner_loop()` | 413 | 每 30min | `legacy_awoooi_default` | P2 | 合規掃描 |
|
||
| 10 | `run_aider_event_processor_loop()` | 423 | 每 30s | `legacy_awoooi_default` | P2 | aider 事件處理 |
|
||
| 11 | `run_coverage_evaluator_loop()` | 432 | 每 1h | `legacy_awoooi_default` | P3 | 覆蓋率評估 |
|
||
| 12 | `run_rule_stats_updater_loop()` | 442 | 每 15min | `legacy_awoooi_default` | P3 | 規則統計 |
|
||
| 13 | `run_asset_change_tracker_loop()` | 452 | 每 5min | `legacy_awoooi_default` | P2 | 資產變更追蹤 |
|
||
| 14 | `run_hermes_rule_quality_loop()` | 462 | 每 1h | `legacy_awoooi_default` | P2 | Hermes 規則品質 |
|
||
| 15 | `run_capacity_forecaster_loop()` | 472 | 每 6h | `legacy_awoooi_default` | P3 | 容量預測 |
|
||
| 16 | `run_daily_report_loop()` | 481 | 每日 | `legacy_awoooi_default` | P3 | 每日報告 |
|
||
| 17 | `run_approval_timeout_resolver()` | 490 | 每 30s | `legacy_awoooi_default` | **P0** | 🔴 P1-15:無 trace_id;Phase 8 前必改 |
|
||
| 18 | `run_evolver_loop()` | 499 | 每 1h | `legacy_awoooi_default` | P2 | playbook 進化(飛輪關鍵)|
|
||
| 19 | `run_playbook_generation_governance_loop()` | 507 | 每 30min | `legacy_awoooi_default` | P2 | playbook 生成治理 |
|
||
| 20 | `run_knowledge_decay_loop()` | 519 | 每 6h | `legacy_awoooi_default` | P2 | KM 知識衰退 |
|
||
| 21 | `run_km_backfill_reconciler_loop()` | 529 | 每 1h | `legacy_awoooi_default` | P2 | KM backfill 核對 |
|
||
| 22 | `run_aol_writeback_loop()` | 540 | 每 30s | `legacy_awoooi_default` | P1 | AI 飛輪 AOL writeback,KM 雙路徑 |
|
||
| 23 | `_run_kb_rot_cleaner_loop()` | 585 | 每 6h | `legacy_awoooi_default` | P3 | KB 腐敗清理 |
|
||
| 24 | `run_finetune_export_loop()` | 594 | 每日 | `legacy_awoooi_default` | P3 | finetune 資料匯出 |
|
||
| 25 | `run_proactive_inspector_loop()` | 605 | 每 5min | `legacy_awoooi_default` | P2 | 主動巡檢 |
|
||
| 26 | `run_offline_replay_loop()` | 614 | 每 15min | `legacy_awoooi_default` | P3 | 離線重放 |
|
||
| 27 | `run_ai_slo_watchdog_loop()` | 623 | 每 5min | **`platform_internal`** | N/A(已完成)| SLO watchdog,project_id=__platform__ |
|
||
| 28 | `run_governance_loop()` | 632 | 每 5min | `legacy_awoooi_default` | P2 | AI 治理主循環 |
|
||
| 29 | `run_governance_dispatcher_loop()` | 640 | 每 30s | `legacy_awoooi_default` | P2 | 治理事件派送 |
|
||
| 30 | `_run_model_version_tracker_loop()` | 701 | 每 1h | **`platform_internal`** | N/A(已完成)| model 版本追蹤,platform_resource |
|
||
| 31 | (需確認)| 701+ | TBD | TBD | TBD | grep 計數 = 31,需確認第 31 個 |
|
||
|
||
---
|
||
|
||
## 改造策略(ADR-123)
|
||
|
||
### platform_internal(#27、#30)
|
||
```python
|
||
# main.py 改造示意
|
||
async def _run_with_context(coro, project_id: str):
|
||
ctx_token = project_id_ctx_var.set(project_id)
|
||
try:
|
||
await coro
|
||
finally:
|
||
project_id_ctx_var.reset(ctx_token)
|
||
|
||
# platform_internal loop:
|
||
asyncio.create_task(_run_with_context(
|
||
run_ai_slo_watchdog_loop(), "__platform__"
|
||
))
|
||
```
|
||
|
||
### legacy_awoooi_default(其餘 29 個)
|
||
```python
|
||
# Phase 2 過渡:fallback 到 awoooi
|
||
asyncio.create_task(_run_with_context(
|
||
run_incident_analysis_sweeper(), "awoooi" # 過渡期
|
||
))
|
||
# 退場時程:Phase 4 完成後 90 天內逐一改為真正 multi-tenant
|
||
```
|
||
|
||
---
|
||
|
||
## 改造優先度說明
|
||
|
||
| 優先度 | 說明 | 對應 loop |
|
||
|--------|------|-----------|
|
||
| P0(立即)| 直接影響安全性或正確性 | #17(approval_timeout_resolver)|
|
||
| P1(Phase 4 前)| 影響 AwoooP run state 正確性 | #4、#22 |
|
||
| P2(Phase 6 前)| 影響多 tenant 資料隔離 | #5~16、#18~20、#25、#28~29 |
|
||
| P3(Phase 8 前)| 低頻率、低風險 | #1~3、#11~12、#15~16、#23~24、#26 |
|
||
|
||
---
|
||
|
||
## 驗收標準
|
||
|
||
- [ ] 第 31 個 loop 確認並列入
|
||
- [ ] 全部 31 個 loop 在 main.py 有 logging context(project_id 可見)
|
||
- [ ] `platform_internal` loop 帶 `project_id=__platform__`
|
||
- [ ] `legacy_awoooi_default` loop 帶 `project_id=awoooi`(PR-10)
|
||
- [ ] loop #17(approval_timeout_resolver)已補入 trace_id(PR-10 合併時)
|
||
|
||
*最後更新:2026-05-03(台北)*
|