Files
awoooi/docs/awooop/inventory/INV-8-background-loop-catalog.md
Your Name 8629ac709b
Some checks failed
run-migration / migrate (push) Failing after 59s
Code Review / ai-code-review (push) Successful in 1m8s
Type Sync Check / check-type-sync (push) Successful in 2m27s
feat(awooop): Phase 1-8 完整實作 — AwoooP Agent Platform 六平面架構
## 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>
2026-05-04 19:31:53 +08:00

111 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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_idPhase 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 tokenPhase 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_idPhase 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 writebackKM 雙路徑 |
| 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 watchdogproject_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立即| 直接影響安全性或正確性 | #17approval_timeout_resolver|
| P1Phase 4 前)| 影響 AwoooP run state 正確性 | #4#22 |
| P2Phase 6 前)| 影響多 tenant 資料隔離 | #5~16、#18~20、#25#28~29 |
| P3Phase 8 前)| 低頻率、低風險 | #1~3、#11~12、#15~16、#23~24、#26 |
---
## 驗收標準
- [ ] 第 31 個 loop 確認並列入
- [ ] 全部 31 個 loop 在 main.py 有 logging contextproject_id 可見)
- [ ] `platform_internal` loop 帶 `project_id=__platform__`
- [ ] `legacy_awoooi_default` loop 帶 `project_id=awoooi`PR-10
- [ ] loop #17approval_timeout_resolver已補入 trace_idPR-10 合併時)
*最後更新2026-05-03台北*