From 4718c7667cd3d2d90b04a2becad747c3920f43ee Mon Sep 17 00:00:00 2001 From: OG T Date: Wed, 15 Apr 2026 21:07:56 +0800 Subject: [PATCH] =?UTF-8?q?feat(Phase=203):=20Evolver=20loop=20=E6=8E=92?= =?UTF-8?q?=E7=A8=8B=20+=20=E6=89=8B=E5=8B=95=E8=A7=B8=E7=99=BC=E7=AB=AF?= =?UTF-8?q?=E9=BB=9E=20=E2=80=94=20=E5=90=88=E4=BD=B5=E6=BC=94=E7=B7=B4?= =?UTF-8?q?=E9=96=98=E9=81=93=E5=AE=8C=E5=B7=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - playbook_evolver.py: 新增 run_evolver_loop()(24h 無限迴圈) - main.py: 掛載 run_evolver_loop asyncio.create_task - api/v1/learning.py: POST /api/v1/learning/evolver/run(Phase 3 exit #6 演練端點) - MASTER §8: 補錄 66c4eda AgentSession + 本次 Evolver 完整退出條件清單 ADR-083 Phase 3 — 2026-04-15 ogt + Claude Sonnet 4.6(亞太) Co-Authored-By: Claude Sonnet 4.6 --- apps/api/src/api/v1/learning.py | 59 ++++++++++++++++++- apps/api/src/main.py | 9 +++ apps/api/src/services/playbook_evolver.py | 20 +++++++ ...-04-15-MASTER-ai-autonomous-flywheel-v2.md | 38 ++++++++++++ 4 files changed, 125 insertions(+), 1 deletion(-) diff --git a/apps/api/src/api/v1/learning.py b/apps/api/src/api/v1/learning.py index a326f874..d187bad3 100644 --- a/apps/api/src/api/v1/learning.py +++ b/apps/api/src/api/v1/learning.py @@ -18,7 +18,7 @@ Phase D-G P0 修正: 新增學習 API 端點 """ import structlog -from fastapi import APIRouter +from fastapi import APIRouter, HTTPException from pydantic import BaseModel from src.services.learning_service import get_learning_service @@ -125,3 +125,60 @@ async def get_recommendation(anomaly_key: str) -> RecommendationResponse: ) return RecommendationResponse(**recommendation) + + +# ============================================================================= +# Evolver Admin Endpoints +# ============================================================================= + + +class EvolverRunResponse(BaseModel): + """Evolver 執行報告回應""" + archived_count: int + merged_count: int + skipped_count: int + archived_ids: list[str] + merged_pairs: list[list[str]] # [[dropped_id, kept_id], ...] + errors: list[str] + total_affected: int + + +@router.post( + "/evolver/run", + response_model=EvolverRunResponse, + summary="手動觸發 Evolver Agent", + description=( + "立即執行 Playbook Evolver:低信任封存 + 休眠封存 + 相似合併。" + "需要 AIOPS_P3_EVOLVER_ENABLED=True,否則返回空報告(HTTP 200)。" + "ADR-083 Phase 3 手動演練端點。" + ), +) +async def run_evolver_now() -> EvolverRunResponse: + """ + 手動觸發 Evolver Agent(Phase 3 exit condition #6 演練端點) + + Returns: + EvolverRunResponse: 合併/封存報告 + """ + try: + from src.services.playbook_evolver import run_evolver + report = await run_evolver() + except Exception as exc: + logger.exception("evolver_manual_run_failed") + raise HTTPException(status_code=500, detail=str(exc)) from exc + + logger.info( + "evolver_manual_run_done", + archived=report.archived_count, + merged=report.merged_count, + skipped=report.skipped_count, + ) + return EvolverRunResponse( + archived_count=report.archived_count, + merged_count=report.merged_count, + skipped_count=report.skipped_count, + archived_ids=report.archived_ids, + merged_pairs=[list(p) for p in report.merged_pairs], + errors=report.errors, + total_affected=report.total_affected, + ) diff --git a/apps/api/src/main.py b/apps/api/src/main.py index f576a65d..1710fa10 100644 --- a/apps/api/src/main.py +++ b/apps/api/src/main.py @@ -345,6 +345,15 @@ async def lifespan(_app: FastAPI) -> AsyncGenerator[None, None]: except Exception as e: logger.warning("approval_timeout_resolver_schedule_failed", error=str(e)) + # ADR-083 Phase 3: Evolver Agent(每日)— Playbook 自動合併 + 低信任封存 + # 2026-04-15 ogt + Claude Sonnet 4.6(亞太): Phase 3 初始建立 + try: + from src.services.playbook_evolver import run_evolver_loop + asyncio.create_task(run_evolver_loop()) + logger.info("evolver_loop_scheduled", interval_sec=86400) + except Exception as e: + logger.warning("evolver_loop_schedule_failed", error=str(e)) + # ADR-083 Phase 3: 知識遺忘 Job(每日)— 30d 未引用 KB entry 標記 archived # 2026-04-15 ogt + Claude Sonnet 4.6(亞太): Phase 3 初始建立 try: diff --git a/apps/api/src/services/playbook_evolver.py b/apps/api/src/services/playbook_evolver.py index fd6e603a..6395820b 100644 --- a/apps/api/src/services/playbook_evolver.py +++ b/apps/api/src/services/playbook_evolver.py @@ -354,3 +354,23 @@ async def schedule_daily_evolver() -> None: ) except Exception: logger.exception("evolver_daily_failed") + + +DAILY_INTERVAL_SEC = 86_400 # 24h + + +async def run_evolver_loop() -> None: + """ + 無限迴圈:每 24 小時執行一次 Evolver Agent。 + 在 main.py startup 以 asyncio.create_task 掛載。 + + ADR-083 Phase 3: Evolver 每日掃描(L4×D3 + L5×D2) + 2026-04-15 ogt + Claude Sonnet 4.6(亞太): Phase 3 初始建立 + """ + while True: + try: + await schedule_daily_evolver() + except Exception as e: + logger.error("evolver_loop_error", error=str(e)) + + await asyncio.sleep(DAILY_INTERVAL_SEC) diff --git a/docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md b/docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md index f5e4a76c..f11264c2 100644 --- a/docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md +++ b/docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md @@ -1559,3 +1559,41 @@ Phase 6 完成後 - [ ] Fine-tune JSONL ≥ 10 條(待 EvidenceSnapshot 累積 7 天後驗證) **下一步:** 推 Gitea → CD 部署 → 7 天生產觀察 Phase 3 退出條件 + +--- + +### 2026-04-15 深夜(台北)Session 2 — Phase 3 AgentSession 學習接線 + Evolver Loop 補完 + +**commit 66c4eda:** `feat(Phase 3): AgentSession 學習接線 — record_agent_session() + orchestrator 辯證訊號` + +| 檔案 | 修改內容 | 對應項目 | +|------|---------|---------| +| `services/learning_service.py` | 新增 `record_agent_session()`:5 Agent 辯證結果寫 Redis analytics + Critic challenges 觸發 Playbook 負向 EWMA | ADR-083 Phase 3 L7×D2 | +| `services/agent_orchestrator.py` | `run_agent_debate()` 成功後 best-effort 呼叫 `record_agent_session()`,辯證品質訊號接入飛輪 | Orchestrator 接線 | + +**本次提交(未推):Phase 3 Evolver Loop + 手動觸發端點** + +| 檔案 | 修改內容 | 對應項目 | +|------|---------|---------| +| `services/playbook_evolver.py` | 新增 `run_evolver_loop()`:無限迴圈 24h 一次,供 main.py `asyncio.create_task` 掛載 | Evolver 每日排程 | +| `main.py` | 掛載 `run_evolver_loop`(每 24h)於 knowledge_decay_loop 之前 | Job 調度補完 | +| `api/v1/learning.py` | 新增 `POST /api/v1/learning/evolver/run`:手動觸發 Evolver,回傳 `EvolverRunResponse`(合併/封存報告)| Phase 3 exit condition #6 演練端點 | + +**Phase 3 退出條件更新(完整版):** +- [x] Root cause 1:fire-and-forget → await +- [x] Root cause 2:matched_playbook_id 永不填充 +- [x] Root cause 3:驗證結果未傳學習 +- [x] 2x EWMA 負向衰減(playbook_repository.py) +- [x] Evolver Agent(playbook_evolver.py) +- [x] Evolver Loop 每日排程(run_evolver_loop + main.py) +- [x] 手動觸發端點(POST /api/v1/learning/evolver/run) +- [x] 診斷 feedback(record_diagnosis_outcome) +- [x] AgentSession 學習接線(record_agent_session + orchestrator) +- [x] 知識遺忘 Job(knowledge_decay_job.py) +- [x] Fine-tune 管線(finetune_exporter.py) +- [ ] Evolver 合併演練 1 次成功(部署後呼叫 POST /learning/evolver/run 驗證) +- [ ] `matched_playbook_id` null 率 = 0(生產驗證 7 天) +- [ ] Playbook trust_score 有 ≥ 1 筆 24h 動態更新(生產驗證) +- [ ] Fine-tune JSONL ≥ 10 條(EvidenceSnapshot 累積 7 天後) + +**下一步:** 推 Gitea → CD 部署 → 呼叫 `POST /api/v1/learning/evolver/run` 完成合併演練 → 7 天生產監控