From 42622a5bad27ba16a7395a9e23eb1c2b5305b5ce Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 11 Jun 2026 13:25:51 +0800 Subject: [PATCH] =?UTF-8?q?feat(governance):=20=E6=96=B0=E5=A2=9E=20Agent?= =?UTF-8?q?=20=E5=B7=A5=E5=85=B7=E6=8E=A1=E7=94=A8=E6=89=B9=E5=87=86?= =?UTF-8?q?=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/api/src/api/v1/agents.py | 31 ++ ...ai_agent_tool_adoption_approval_package.py | 178 +++++++ ..._ai_agent_proactive_operations_contract.py | 6 +- ...agent_proactive_operations_contract_api.py | 6 +- ...ai_agent_tool_adoption_approval_package.py | 207 ++++++++ ...gent_tool_adoption_approval_package_api.py | 40 ++ docs/LOGBOOK.md | 24 + ...AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md | 6 +- ...I_AGENT_PROACTIVE_OPERATIONS_2026-06-11.md | 35 +- ...OL_ADOPTION_APPROVAL_PACKAGE_2026-06-11.md | 72 +++ ...active_operations_contract_2026-06-11.json | 18 +- ..._adoption_approval_package_2026-06-11.json | 471 +++++++++++++++++ ...l_adoption_approval_package_v1.schema.json | 474 ++++++++++++++++++ ...-04-15-MASTER-ai-autonomous-flywheel-v2.md | 19 +- 14 files changed, 1555 insertions(+), 32 deletions(-) create mode 100644 apps/api/src/services/ai_agent_tool_adoption_approval_package.py create mode 100644 apps/api/tests/test_ai_agent_tool_adoption_approval_package.py create mode 100644 apps/api/tests/test_ai_agent_tool_adoption_approval_package_api.py create mode 100644 docs/ai/AI_AGENT_TOOL_ADOPTION_APPROVAL_PACKAGE_2026-06-11.md create mode 100644 docs/evaluations/ai_agent_tool_adoption_approval_package_2026-06-11.json create mode 100644 docs/schemas/ai_agent_tool_adoption_approval_package_v1.schema.json diff --git a/apps/api/src/api/v1/agents.py b/apps/api/src/api/v1/agents.py index 2ec79a30a..ee81f3714 100644 --- a/apps/api/src/api/v1/agents.py +++ b/apps/api/src/api/v1/agents.py @@ -58,6 +58,9 @@ from src.services.ai_agent_deployment_layout import ( from src.services.ai_agent_proactive_operations_contract import ( load_latest_ai_agent_proactive_operations_contract, ) +from src.services.ai_agent_tool_adoption_approval_package import ( + load_latest_ai_agent_tool_adoption_approval_package, +) from src.services.ai_agent_version_freshness_snapshot import ( load_latest_ai_agent_version_freshness_snapshot, ) @@ -614,6 +617,34 @@ async def get_agent_version_freshness_snapshot() -> dict[str, Any]: ) from exc +@router.get( + "/agent-tool-adoption-approval-package", + response_model=dict[str, Any], + summary="取得 AI Agent 工具採用批准包", + description=( + "讀取最新已提交的 Renovate / OSV-Scanner / Trivy / Syft / Grype 工具採用批准包;" + "此端點不安裝工具、不寫 CI workflow、不下載漏洞資料庫、不查外部 registry、不升級套件、" + "不寫 lockfile、不 build/pull image、不建立 Gitea PR、不 auto merge、不發 Telegram、" + "不呼叫付費服務、不修改生產路由。" + ), +) +async def get_agent_tool_adoption_approval_package() -> dict[str, Any]: + """Return the latest read-only AI Agent tool adoption approval package.""" + try: + return await asyncio.to_thread(load_latest_ai_agent_tool_adoption_approval_package) + except FileNotFoundError as exc: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=str(exc), + ) from exc + except (json.JSONDecodeError, ValueError) as exc: + logger.error("ai_agent_tool_adoption_approval_package_invalid", error=str(exc)) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="AI Agent 工具採用批准包無效", + ) from exc + + @router.get( "/runtime-surface-inventory", response_model=dict[str, Any], diff --git a/apps/api/src/services/ai_agent_tool_adoption_approval_package.py b/apps/api/src/services/ai_agent_tool_adoption_approval_package.py new file mode 100644 index 000000000..89322004d --- /dev/null +++ b/apps/api/src/services/ai_agent_tool_adoption_approval_package.py @@ -0,0 +1,178 @@ +""" +AI Agent tool adoption approval package snapshot. + +Loads the latest committed, read-only approval package for adopting tools such +as Renovate, OSV-Scanner, Trivy, Syft, and Grype. This module never installs +tools, writes CI workflows, downloads vulnerability databases, queries +registries, creates PRs, sends Telegram messages, or changes production. +""" + +from __future__ import annotations + +import json +from pathlib import Path +from typing import Any + +from src.services.snapshot_paths import default_evaluations_dir + +_DEFAULT_EVALUATIONS_DIR = default_evaluations_dir(Path(__file__)) +_SNAPSHOT_PATTERN = "ai_agent_tool_adoption_approval_package_*.json" +_SCHEMA_VERSION = "ai_agent_tool_adoption_approval_package_v1" +_RUNTIME_AUTHORITY = "approval_package_only_no_tool_install_or_ci_change" + + +def load_latest_ai_agent_tool_adoption_approval_package( + evaluations_dir: Path | None = None, +) -> dict[str, Any]: + """Load the newest committed AI Agent tool adoption approval package.""" + directory = evaluations_dir or _DEFAULT_EVALUATIONS_DIR + candidates = sorted(directory.glob(_SNAPSHOT_PATTERN)) + if not candidates: + raise FileNotFoundError( + f"no AI Agent tool adoption approval package snapshots found in {directory}" + ) + + latest = candidates[-1] + with latest.open(encoding="utf-8") as handle: + payload = json.load(handle) + + if not isinstance(payload, dict): + raise ValueError(f"{latest}: expected JSON object") + _require_schema(payload, _SCHEMA_VERSION, str(latest)) + _require_read_only_boundaries(payload, str(latest)) + _require_rollup_consistency(payload, str(latest)) + _require_tool_safety(payload, str(latest)) + return payload + + +def _require_schema(payload: dict[str, Any], expected: str, label: str) -> None: + actual = payload.get("schema_version") + if actual != expected: + raise ValueError(f"{label}: expected schema_version={expected}, got {actual!r}") + + +def _require_read_only_boundaries(payload: dict[str, Any], label: str) -> None: + program_status = payload.get("program_status") or {} + if program_status.get("read_only_mode") is not True: + raise ValueError(f"{label}: program_status.read_only_mode must be true") + if program_status.get("runtime_authority") != _RUNTIME_AUTHORITY: + raise ValueError(f"{label}: runtime_authority must stay {_RUNTIME_AUTHORITY}") + + boundaries = payload.get("approval_boundaries") or {} + blocked_flags = { + "tool_install_allowed", + "ci_workflow_change_allowed", + "external_registry_lookup_allowed", + "vulnerability_database_download_allowed", + "package_upgrade_allowed", + "lockfile_write_allowed", + "docker_build_allowed", + "image_pull_allowed", + "gitea_pr_creation_allowed", + "auto_merge_allowed", + "telegram_direct_send_allowed", + "paid_service_enabled", + "production_route_change_allowed", + "secret_plaintext_allowed", + } + allowed = sorted(flag for flag in blocked_flags if boundaries.get(flag) is not False) + if allowed: + raise ValueError(f"{label}: approval boundaries must remain false: {allowed}") + + +def _require_rollup_consistency(payload: dict[str, Any], label: str) -> None: + tools = payload.get("tool_candidates") or [] + sources = payload.get("source_evidence") or [] + lanes = payload.get("adoption_lanes") or [] + rollups = payload.get("rollups") or {} + + expected_counts = { + "tool_count": len(tools), + "source_evidence_count": len(sources), + "adoption_lane_count": len(lanes), + } + mismatched = { + key: {"expected": expected, "actual": rollups.get(key)} + for key, expected in expected_counts.items() + if rollups.get(key) != expected + } + if mismatched: + raise ValueError(f"{label}: rollup counts must match payload sections: {mismatched}") + + expected_lists = { + "approval_required_tool_ids": sorted( + tool.get("tool_id") + for tool in tools + if tool.get("adoption_status") == "approval_required" + ), + "ci_change_required_tool_ids": sorted( + tool.get("tool_id") for tool in tools if tool.get("ci_change_required") is True + ), + "secret_required_tool_ids": sorted( + tool.get("tool_id") for tool in tools if _requires_secret_review(tool) + ), + "external_data_required_tool_ids": sorted( + tool.get("tool_id") for tool in tools if _requires_external_data_gate(tool) + ), + } + for key, expected in expected_lists.items(): + if sorted(rollups.get(key) or []) != expected: + raise ValueError(f"{label}: rollups.{key} mismatch") + + zero_rollups = { + "tool_install_allowed_count", + "ci_change_allowed_count", + "auto_merge_allowed_count", + "telegram_direct_send_count", + } + nonzero = sorted(key for key in zero_rollups if rollups.get(key) != 0) + if nonzero: + raise ValueError(f"{label}: rollout safety counters must remain 0: {nonzero}") + + +def _require_tool_safety(payload: dict[str, Any], label: str) -> None: + source_ids = {source.get("source_id") for source in payload.get("source_evidence") or []} + unsafe_tools = [ + tool.get("tool_id") + for tool in payload.get("tool_candidates") or [] + if tool.get("adoption_status") != "approval_required" + or not tool.get("approval_requirements") + or not tool.get("blocked_until_approval") + or not set(tool.get("official_source_refs") or []).issubset(source_ids) + or not tool.get("rollback_plan") + ] + if unsafe_tools: + raise ValueError(f"{label}: tools must stay approval-bound: {unsafe_tools}") + + unsafe_lanes = [ + lane.get("lane_id") + for lane in payload.get("adoption_lanes") or [] + if not lane.get("approval_gate") or not lane.get("blocked_now") + ] + if unsafe_lanes: + raise ValueError(f"{label}: adoption lanes need approval gates: {unsafe_lanes}") + + missing_required_fields = [ + field.get("field_id") + for field in payload.get("approval_packet_fields") or [] + if field.get("required") is True and not field.get("description") + ] + if missing_required_fields: + raise ValueError(f"{label}: approval fields need descriptions: {missing_required_fields}") + + +def _requires_secret_review(tool: dict[str, Any]) -> bool: + requirement = str(tool.get("secret_requirement") or "").lower() + return "credentials" in requirement or "token" in requirement + + +def _requires_external_data_gate(tool: dict[str, Any]) -> bool: + requirement = str(tool.get("external_data_requirement") or "").lower() + if requirement.startswith("no external"): + return False + return ( + "currently blocked" in requirement + or "metadata required" in requirement + or "database required" in requirement + or "db required" in requirement + ) diff --git a/apps/api/tests/test_ai_agent_proactive_operations_contract.py b/apps/api/tests/test_ai_agent_proactive_operations_contract.py index ae7fc7c4a..8865d6367 100644 --- a/apps/api/tests/test_ai_agent_proactive_operations_contract.py +++ b/apps/api/tests/test_ai_agent_proactive_operations_contract.py @@ -13,9 +13,9 @@ def test_load_latest_ai_agent_proactive_operations_contract_reads_committed_snap data = load_latest_ai_agent_proactive_operations_contract() assert data["schema_version"] == "ai_agent_proactive_operations_contract_v1" - assert data["program_status"]["overall_completion_percent"] == 42 - assert data["program_status"]["current_task_id"] == "P2-402B" - assert data["program_status"]["next_task_id"] == "P2-402C" + assert data["program_status"]["overall_completion_percent"] == 55 + assert data["program_status"]["current_task_id"] == "P2-402C" + assert data["program_status"]["next_task_id"] == "P2-402D" assert data["program_status"]["read_only_mode"] is True assert data["program_status"]["runtime_authority"] == "contract_only_no_version_or_runtime_update" assert data["approval_boundaries"]["runtime_version_update_allowed"] is False diff --git a/apps/api/tests/test_ai_agent_proactive_operations_contract_api.py b/apps/api/tests/test_ai_agent_proactive_operations_contract_api.py index 0e161656c..860901cff 100644 --- a/apps/api/tests/test_ai_agent_proactive_operations_contract_api.py +++ b/apps/api/tests/test_ai_agent_proactive_operations_contract_api.py @@ -16,9 +16,9 @@ def test_ai_agent_proactive_operations_contract_endpoint_returns_committed_snaps assert response.status_code == 200 data = response.json() assert data["schema_version"] == "ai_agent_proactive_operations_contract_v1" - assert data["program_status"]["overall_completion_percent"] == 42 - assert data["program_status"]["current_task_id"] == "P2-402B" - assert data["program_status"]["next_task_id"] == "P2-402C" + assert data["program_status"]["overall_completion_percent"] == 55 + assert data["program_status"]["current_task_id"] == "P2-402C" + assert data["program_status"]["next_task_id"] == "P2-402D" assert data["program_status"]["read_only_mode"] is True assert data["approval_boundaries"]["runtime_version_update_allowed"] is False assert data["approval_boundaries"]["package_upgrade_allowed"] is False diff --git a/apps/api/tests/test_ai_agent_tool_adoption_approval_package.py b/apps/api/tests/test_ai_agent_tool_adoption_approval_package.py new file mode 100644 index 000000000..7929e2b96 --- /dev/null +++ b/apps/api/tests/test_ai_agent_tool_adoption_approval_package.py @@ -0,0 +1,207 @@ +from __future__ import annotations + +import json + +import pytest + +from src.services.ai_agent_tool_adoption_approval_package import ( + load_latest_ai_agent_tool_adoption_approval_package, +) + + +def test_load_latest_ai_agent_tool_adoption_approval_package_reads_committed_snapshot(): + data = load_latest_ai_agent_tool_adoption_approval_package() + + assert data["schema_version"] == "ai_agent_tool_adoption_approval_package_v1" + assert data["program_status"]["overall_completion_percent"] == 55 + assert data["program_status"]["current_task_id"] == "P2-402C" + assert data["program_status"]["next_task_id"] == "P2-402D" + assert data["program_status"]["read_only_mode"] is True + assert ( + data["program_status"]["runtime_authority"] + == "approval_package_only_no_tool_install_or_ci_change" + ) + assert data["approval_boundaries"]["tool_install_allowed"] is False + assert data["approval_boundaries"]["ci_workflow_change_allowed"] is False + assert data["approval_boundaries"]["external_registry_lookup_allowed"] is False + assert data["approval_boundaries"]["vulnerability_database_download_allowed"] is False + assert data["approval_boundaries"]["gitea_pr_creation_allowed"] is False + assert data["approval_boundaries"]["telegram_direct_send_allowed"] is False + assert data["rollups"]["tool_count"] == len(data["tool_candidates"]) == 5 + assert data["rollups"]["source_evidence_count"] == len(data["source_evidence"]) == 5 + assert data["rollups"]["adoption_lane_count"] == len(data["adoption_lanes"]) == 4 + assert data["rollups"]["tool_install_allowed_count"] == 0 + assert data["rollups"]["ci_change_allowed_count"] == 0 + assert data["rollups"]["auto_merge_allowed_count"] == 0 + assert data["rollups"]["telegram_direct_send_count"] == 0 + assert set(data["rollups"]["approval_required_tool_ids"]) == { + "renovate_gitea", + "osv_scanner", + "trivy", + "syft", + "grype", + } + assert set(data["rollups"]["secret_required_tool_ids"]) == { + "renovate_gitea", + "trivy", + "syft", + "grype", + } + assert "syft" not in data["rollups"]["external_data_required_tool_ids"] + + +def test_ai_agent_tool_adoption_approval_package_rejects_tool_install_allowed(tmp_path): + snapshot = _snapshot() + snapshot["approval_boundaries"]["tool_install_allowed"] = True + (tmp_path / "ai_agent_tool_adoption_approval_package_2026-06-11.json").write_text( + json.dumps(snapshot), + encoding="utf-8", + ) + + with pytest.raises(ValueError, match="approval boundaries"): + load_latest_ai_agent_tool_adoption_approval_package(tmp_path) + + +def test_ai_agent_tool_adoption_approval_package_rejects_rollup_mismatch(tmp_path): + snapshot = _snapshot() + snapshot["rollups"]["tool_count"] = 99 + (tmp_path / "ai_agent_tool_adoption_approval_package_2026-06-11.json").write_text( + json.dumps(snapshot), + encoding="utf-8", + ) + + with pytest.raises(ValueError, match="rollup counts"): + load_latest_ai_agent_tool_adoption_approval_package(tmp_path) + + +def test_ai_agent_tool_adoption_approval_package_rejects_non_approval_tool(tmp_path): + snapshot = _snapshot() + snapshot["tool_candidates"][0]["adoption_status"] = "enabled" + snapshot["rollups"]["approval_required_tool_ids"] = [] + (tmp_path / "ai_agent_tool_adoption_approval_package_2026-06-11.json").write_text( + json.dumps(snapshot), + encoding="utf-8", + ) + + with pytest.raises(ValueError, match="approval-bound"): + load_latest_ai_agent_tool_adoption_approval_package(tmp_path) + + +def test_ai_agent_tool_adoption_approval_package_rejects_unknown_source_ref(tmp_path): + snapshot = _snapshot() + snapshot["tool_candidates"][0]["official_source_refs"] = ["unknown_source"] + (tmp_path / "ai_agent_tool_adoption_approval_package_2026-06-11.json").write_text( + json.dumps(snapshot), + encoding="utf-8", + ) + + with pytest.raises(ValueError, match="approval-bound"): + load_latest_ai_agent_tool_adoption_approval_package(tmp_path) + + +def _snapshot() -> dict: + return { + "schema_version": "ai_agent_tool_adoption_approval_package_v1", + "generated_at": "2026-06-11T23:35:00+08:00", + "program_status": { + "overall_completion_percent": 55, + "current_priority": "P2", + "current_task_id": "P2-402C", + "next_task_id": "P2-402D", + "read_only_mode": True, + "runtime_authority": "approval_package_only_no_tool_install_or_ci_change", + "status_note": "測試。", + }, + "source_evidence": [ + { + "source_id": "renovate_gitea_platform_docs", + "tool_id": "renovate_gitea", + "name": "Renovate Gitea platform docs", + "url": "https://docs.renovatebot.com/modules/platform/gitea/", + "retrieved_at": "2026-06-11T23:35:00+08:00", + "evidence_type": "official_documentation", + "usage_boundary": "測試。", + } + ], + "agent_review_matrix": [ + { + "agent_id": "openclaw", + "role": "測試。", + "allowed_now": ["讀取批准包"], + "blocked_until_approval": ["安裝工具"], + "output": "verdict", + } + ], + "adoption_lanes": [ + { + "lane_id": "dependency_update_pr_lane", + "display_name": "Dependency update PR lane", + "owner_agent": "hermes", + "tool_ids": ["renovate_gitea"], + "approval_gate": "approval_required", + "planned_output": "approval package", + "blocked_now": ["PR creation"], + } + ], + "tool_candidates": [ + { + "tool_id": "renovate_gitea", + "display_name": "Renovate for Gitea", + "category": "dependency_update_pr", + "owner_agent": "hermes", + "adoption_status": "approval_required", + "risk_tier": "high", + "cost_profile": "runner cost requires approval", + "secret_requirement": "Gitea bot token required after approval.", + "external_data_requirement": "Package registry metadata required after approval; currently blocked.", + "ci_change_required": True, + "official_source_refs": ["renovate_gitea_platform_docs"], + "intended_scope": ["dependency update PR draft"], + "approval_requirements": ["bot token storage plan"], + "blocked_until_approval": ["PR creation"], + "recommendation": "測試。", + "rollback_plan": "測試。", + } + ], + "approval_packet_fields": [ + { + "field_id": "operator_approval_id", + "required": True, + "owner_agent": "openclaw", + "description": "測試。", + } + ], + "approval_boundaries": { + "tool_install_allowed": False, + "ci_workflow_change_allowed": False, + "external_registry_lookup_allowed": False, + "vulnerability_database_download_allowed": False, + "package_upgrade_allowed": False, + "lockfile_write_allowed": False, + "docker_build_allowed": False, + "image_pull_allowed": False, + "gitea_pr_creation_allowed": False, + "auto_merge_allowed": False, + "telegram_direct_send_allowed": False, + "paid_service_enabled": False, + "production_route_change_allowed": False, + "secret_plaintext_allowed": False, + }, + "rollups": { + "tool_count": 1, + "source_evidence_count": 1, + "adoption_lane_count": 1, + "approval_required_tool_ids": ["renovate_gitea"], + "ci_change_required_tool_ids": ["renovate_gitea"], + "secret_required_tool_ids": ["renovate_gitea"], + "external_data_required_tool_ids": ["renovate_gitea"], + "sbom_tool_ids": [], + "vulnerability_scan_tool_ids": [], + "update_pr_tool_ids": ["renovate_gitea"], + "tool_install_allowed_count": 0, + "ci_change_allowed_count": 0, + "auto_merge_allowed_count": 0, + "telegram_direct_send_count": 0, + "next_approval_task_ids": ["P2-402D"], + }, + } diff --git a/apps/api/tests/test_ai_agent_tool_adoption_approval_package_api.py b/apps/api/tests/test_ai_agent_tool_adoption_approval_package_api.py new file mode 100644 index 000000000..5507ba423 --- /dev/null +++ b/apps/api/tests/test_ai_agent_tool_adoption_approval_package_api.py @@ -0,0 +1,40 @@ +from __future__ import annotations + +from fastapi import FastAPI +from fastapi.testclient import TestClient + +from src.api.v1.agents import router + + +def test_agent_tool_adoption_approval_package_endpoint_returns_committed_snapshot(): + app = FastAPI() + app.include_router(router, prefix="/api/v1") + client = TestClient(app) + + response = client.get("/api/v1/agents/agent-tool-adoption-approval-package") + + assert response.status_code == 200 + data = response.json() + assert data["schema_version"] == "ai_agent_tool_adoption_approval_package_v1" + assert data["program_status"]["overall_completion_percent"] == 55 + assert data["program_status"]["current_task_id"] == "P2-402C" + assert data["program_status"]["next_task_id"] == "P2-402D" + assert data["program_status"]["read_only_mode"] is True + assert data["approval_boundaries"]["tool_install_allowed"] is False + assert data["approval_boundaries"]["ci_workflow_change_allowed"] is False + assert data["approval_boundaries"]["external_registry_lookup_allowed"] is False + assert data["approval_boundaries"]["vulnerability_database_download_allowed"] is False + assert data["approval_boundaries"]["gitea_pr_creation_allowed"] is False + assert data["approval_boundaries"]["telegram_direct_send_allowed"] is False + assert data["rollups"]["tool_count"] == 5 + assert data["rollups"]["source_evidence_count"] == 5 + assert data["rollups"]["adoption_lane_count"] == 4 + assert data["rollups"]["tool_install_allowed_count"] == 0 + assert data["rollups"]["ci_change_allowed_count"] == 0 + assert data["rollups"]["auto_merge_allowed_count"] == 0 + assert data["rollups"]["telegram_direct_send_count"] == 0 + assert any(tool["tool_id"] == "renovate_gitea" for tool in data["tool_candidates"]) + assert any(tool["tool_id"] == "osv_scanner" for tool in data["tool_candidates"]) + assert any(tool["tool_id"] == "trivy" for tool in data["tool_candidates"]) + assert any(tool["tool_id"] == "syft" for tool in data["tool_candidates"]) + assert any(tool["tool_id"] == "grype" for tool in data["tool_candidates"]) diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index 0d100214b..9b93d71ff 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -28,6 +28,30 @@ - 本階段沒有 force push、沒有 destructive git、沒有讀取或輸出 Secret payload、沒有 SSH、沒有 active scan、沒有改 Alertmanager rule / receiver、沒有手動重啟 production service;部署由既有 Gitea CD 完成。 - IwoooS 整體仍維持 `64%`;active runtime gate 仍為 `0`;owner response received / accepted 仍為 `0 / false`。 +## 2026-06-11|P2-402C AI Agent 工具採用批准包 + +**背景**:統帥要求 OpenClaw / Hermes / NemoTron 針對所有工具、套件、服務、主機與 AI Agent 版本管理做主動監控、管理、備份、優化配置與定期更新評估;本波接續 P2-402B repo-only 版本新鮮度快照,先建立 Renovate / OSV-Scanner / Trivy / Syft / Grype 的採用批准包,避免尚未授權就安裝工具、改 CI 或查外部資料。 + +**完成內容:** +- 新增 `ai_agent_tool_adoption_approval_package_v1` schema。 +- 新增 committed snapshot:`docs/evaluations/ai_agent_tool_adoption_approval_package_2026-06-11.json`。 +- 新增只讀 loader:`apps/api/src/services/ai_agent_tool_adoption_approval_package.py`。 +- 新增治理 API:`GET /api/v1/agents/agent-tool-adoption-approval-package`。 +- 新增 loader / API / safety boundary / rollup mismatch / unknown source ref 測試。 +- 新增分析報告:`docs/ai/AI_AGENT_TOOL_ADOPTION_APPROVAL_PACKAGE_2026-06-11.md`。 +- 同步 `AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md`、`AI_AGENT_PROACTIVE_OPERATIONS_2026-06-11.md` 與 MASTER §3.2.1c。 + +**完成度與下一步:** +- P2-402C:`100%`。 +- AI Agent 主動營運與版本生命週期整體:`55%`。 +- Current task:`P2-402C`。 +- Next task:`P2-402D` Telegram action-required digest policy。 + +**安全邊界:** +- 本波只做批准包與只讀 API。 +- 未安裝 Renovate / OSV-Scanner / Trivy / Syft / Grype。 +- 未修改 CI workflow、未查外部 registry、未下載 vulnerability DB、未升級套件、未寫 lockfile、未 build/pull image、未建立 Gitea PR、未 auto merge、未發 Telegram、未改 production route。 + ## 2026-06-11|P0 Telegram 重複告警靜音第二波修復 **背景**:第一波已修復 Alertmanager 缺少 `project_id` 導致 RLS fail-closed、告警被 degraded accepted no-retry 吃掉的主斷點。後續正式 logs 又確認另一條靜音路徑:同一指紋第一次告警進入背景 AI 分析後,第二次同指紋告警會被 `alertmanager_llm_inflight_suppressed` 擋下,只記錄 DB event,不送 Telegram,使用者仍會感覺「告警完全沒有出現」。 diff --git a/docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md b/docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md index 6df5b290f..d85cc50a5 100644 --- a/docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md +++ b/docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md @@ -13,7 +13,7 @@ | 工具 / 服務 / 套件 AI 自動化 | 92% | P0 已完成;P1 服務 / runtime / 監控 / provider / service health / 備份 / DR / 套件與供應鏈只讀基線已完成;P1-007 失敗限定通知合約與前端 redaction 合約已完成;下一主線是 P2-004 依賴 / 供應鏈漂移監控 | 狀態分類、盤點 schema、權限矩陣、靜態盤點種子、只讀 API、UI 骨架、驗證、自動化待辦 schema / 快照 / API / 分組 UI、Backup / DR 目標盤點、準備度矩陣、備份通知政策、Backup / DR 證據 UI、復原演練批准包模板、異地 / escrow 準備度狀態、任務批准邊界、確定性進度彙總、Python 套件 / 供應鏈只讀基線、JS pnpm/npm 只讀基線、Docker build surface 只讀基線、CVE / license / drift 嚴重度政策、定期依賴漂移與外部資料來源檢查設計、依賴升級批准包模板、runtime_surface_inventory_v1 schema / snapshot / API / UI、gitea_workflow_runner_health_v1 schema / snapshot / API / UI、observability_contract_matrix_v1 schema / snapshot / API / UI、ai_provider_route_matrix_v1 schema / snapshot / API / UI、service_health_gap_matrix_v1 schema / snapshot / API / UI、service health evidence cards UI、service_health_failure_notification_policy_v1 schema / snapshot / API / UI 已完成 | | OpenClaw / Hermes / NemoTron 佈建布局 | 45% | P1-401 / P1-402 已完成;仍是只讀 layout 與治理頁顯示,不是 runtime deploy | `ai_agent_deployment_layout_v1` schema、`ai_agent_deployment_layout_2026-06-11.json`、`GET /api/v1/agents/agent-deployment-layout`、治理頁自動化盤點 UI、`AI_AGENT_DEPLOYMENT_LAYOUT_2026-06-11.md` | | OpenClaw / Hermes / NemoTron 主動溝通與學習契約 | 35% | P2-401A 已完成只讀 contract;runtime worker、DB migration、Telegram 實發、SDK / 付費服務仍未開 gate | `ai_agent_communication_learning_contract_v1` schema、`ai_agent_communication_learning_contract_2026-06-11.json`、`GET /api/v1/agents/agent-communication-learning-contract`、MASTER §3.2.1b / §3.4.3 | -| AI Agent 主動營運委派與版本生命週期 | 42% | P2-402A / P2-402B 已完成;已建立 repo-only 版本新鮮度快照與 API。定期排程、外部版本查詢、套件升級、主機更新、container pull、auto merge、Telegram 實發仍未開 gate | `ai_agent_proactive_operations_contract_v1`、`ai_agent_version_freshness_snapshot_v1`、`GET /api/v1/agents/agent-proactive-operations-contract`、`GET /api/v1/agents/agent-version-freshness-snapshot`、MASTER §3.2.1c | +| AI Agent 主動營運委派與版本生命週期 | 55% | P2-402A / P2-402B / P2-402C 已完成;已建立 repo-only 版本新鮮度快照、工具採用批准包與 API。定期排程、外部版本查詢、工具安裝、CI 變更、套件升級、主機更新、container pull、auto merge、Telegram 實發仍未開 gate | `ai_agent_proactive_operations_contract_v1`、`ai_agent_version_freshness_snapshot_v1`、`ai_agent_tool_adoption_approval_package_v1`、`GET /api/v1/agents/agent-proactive-operations-contract`、`GET /api/v1/agents/agent-version-freshness-snapshot`、`GET /api/v1/agents/agent-tool-adoption-approval-package`、MASTER §3.2.1c | | 本工作清單與分析報告 | 100% | 已完成 | 本 MD 文件 | AI Agent 自動化工作包目前完成度:**92%**。本工作清單文件本身完成度:**100%**。 @@ -22,7 +22,7 @@ AI Agent 自動化工作包目前完成度:**92%**。本工作清單文件本 三 Agent 主動溝通與學習契約目前完成度:**35%**。已完成只讀 schema / snapshot / API / 測試與 MASTER 同步;下一步依優先順序推 `P2-401B` AgentSession / Redis Streams migration 與 worker gate,但在批准前仍不得啟動 runtime loop。 -AI Agent 主動營運委派與版本生命週期目前完成度:**42%**。已完成 12 類版本 domain、24 類可委派能力、5 種 cadence、8 類 MCP、4 類 RAG memory、只讀 API,以及 `P2-402B` repo-only daily version freshness snapshot schema / committed snapshot / API / 測試;下一步是 `P2-402C` Renovate / OSV / Trivy / Syft / Grype 工具採用批准包,外部 registry / package source / host probe / Telegram 實發仍需 gate。 +AI Agent 主動營運委派與版本生命週期目前完成度:**55%**。已完成 12 類版本 domain、24 類可委派能力、5 種 cadence、8 類 MCP、4 類 RAG memory、只讀 API、`P2-402B` repo-only daily version freshness snapshot,以及 `P2-402C` Renovate / OSV-Scanner / Trivy / Syft / Grype 工具採用批准包;下一步是 `P2-402D` Telegram action-required digest policy,外部 registry / package source / host probe / 工具安裝 / CI 變更 / Telegram 實發仍需 gate。 完成度計算模型: @@ -953,7 +953,7 @@ UI: | P2-401E | 待辦 | 0 | Nemotron | sanitized replay scorer 與 5-record smoke 設計 | NemoTron replay smoke 批准包 | cost / data approval | | P2-402A | 完成 | 100 | Hermes + OpenClaw + Nemotron | 定義 AI Agent 主動營運委派與版本生命週期:12 類版本 domain、24 類可委派能力、MCP/RAG/Telegram policy | `ai_agent_proactive_operations_contract_v1` / snapshot / 只讀 API / MASTER 同步 | 只讀;不啟用排程、不升級、不 host update、不 pull image、不 auto merge、不發 Telegram | | P2-402B | 完成 | 100 | Hermes | 建立 repo-only daily version freshness snapshot | `ai_agent_version_freshness_snapshot_v1` / snapshot / 只讀 API / 測試;12 類 repo-only source、5 個 daily step、3 Agent role | 只讀;workflow schedule 未啟用、外部 lookup 未開、不得升級或發 Telegram | -| P2-402C | 待辦 | 0 | OpenClaw | 建立 Renovate / OSV / Trivy / Syft / Grype 工具採用批准包 | 工具 / 費用 / secret / CI 變更批准包 | tool install + CI change approval | +| P2-402C | 完成 | 100 | OpenClaw | 建立 Renovate / OSV-Scanner / Trivy / Syft / Grype 工具採用批准包 | `ai_agent_tool_adoption_approval_package_v1` / snapshot / 只讀 API / 測試;5 工具、5 官方來源、4 採用 lane、6 批准欄位 | 只讀;tool install、CI change、external lookup、vulnerability DB、PR、Telegram 全部未啟用 | | P2-402D | 待辦 | 0 | OpenClaw | 建立 Telegram action-required digest policy | critical / action-required / failure-only digest | Telegram Gateway E2E | | P2-402E | 待辦 | 0 | Hermes | 設計 Gitea PR 草案 lane | grouping、automerge=false、tests、rollback、owner response | bot / branch policy approval | | P2-402F | 待辦 | 0 | OpenClaw | 建立 host OS / K3s / stateful services 版本只讀盤點 | host / K3s / DB / Redis / MinIO / Gitea 版本矩陣 | host readonly probe + maintenance window approval | diff --git a/docs/ai/AI_AGENT_PROACTIVE_OPERATIONS_2026-06-11.md b/docs/ai/AI_AGENT_PROACTIVE_OPERATIONS_2026-06-11.md index 7542c9395..e15539ef2 100644 --- a/docs/ai/AI_AGENT_PROACTIVE_OPERATIONS_2026-06-11.md +++ b/docs/ai/AI_AGENT_PROACTIVE_OPERATIONS_2026-06-11.md @@ -1,7 +1,7 @@ # AI Agent 主動營運委派與版本生命週期分析報告 > 日期:2026-06-11(台北時間) -> 文件定位:P2-402A / P2-402B 只讀契約摘要。權威細節以 MASTER §3.2.1c、`ai_agent_proactive_operations_contract_v1` 與 `ai_agent_version_freshness_snapshot_v1` 為準。 +> 文件定位:P2-402A / P2-402B / P2-402C 只讀契約摘要。權威細節以 MASTER §3.2.1c、`ai_agent_proactive_operations_contract_v1`、`ai_agent_version_freshness_snapshot_v1` 與 `ai_agent_tool_adoption_approval_package_v1` 為準。 ## 1. 本波完成度 @@ -9,7 +9,8 @@ |---|---:|---| | 主動營運委派契約 | 100% | 已完成 schema / snapshot / API / 測試 | | Repo-only 版本新鮮度快照 | 100% | P2-402B 已完成 schema / committed snapshot / API / 測試 | -| 整體主動營運與版本生命週期 | 42% | 已完成架構、邊界與 repo-only freshness;runtime 排程與更新尚未開 gate | +| 工具採用批准包 | 100% | P2-402C 已完成 Renovate / OSV-Scanner / Trivy / Syft / Grype schema / committed snapshot / API / 測試 | +| 整體主動營運與版本生命週期 | 55% | 已完成架構、repo-only freshness 與工具採用批准包;runtime 排程、工具安裝、CI 變更與更新仍未開 gate | ## 2. 可交給 AI Agent 的工作分類 @@ -34,6 +35,9 @@ | `docs/schemas/ai_agent_version_freshness_snapshot_v1.schema.json` | Repo-only 版本新鮮度 schema;所有外部查詢與更新權限預設 false | | `docs/evaluations/ai_agent_version_freshness_snapshot_2026-06-11.json` | 12 類 repo-only source、5 個 daily step、3 Agent role、5 個 action-required source | | `GET /api/v1/agents/agent-version-freshness-snapshot` | 只讀 API;不觸發掃描、不查外部、不改 repo、不發 Telegram | +| `docs/schemas/ai_agent_tool_adoption_approval_package_v1.schema.json` | 工具採用批准包 schema;工具安裝、CI 變更、外部查詢、漏洞 DB、PR、Telegram 全部預設 false | +| `docs/evaluations/ai_agent_tool_adoption_approval_package_2026-06-11.json` | Renovate / OSV-Scanner / Trivy / Syft / Grype 官方來源、採用 lane、批准欄位、rollback plan | +| `GET /api/v1/agents/agent-tool-adoption-approval-package` | 只讀 API;不安裝工具、不改 CI、不查外部、不建 PR、不發 Telegram | ## 4. P2-402B Repo-only 版本新鮮度快照 @@ -48,18 +52,29 @@ 本波只把「每天要看哪些 repo 內版本來源」定義成可驗證資料面。每日排程、外部 registry 查詢、主機/K3s live probe、Telegram digest 與 Gitea PR lane 都仍是下一階段 gate。 -## 5. 下一步優先順序 +## 5. P2-402C 工具採用批准包 + +| 工具 | 主責 Agent | 建議角色 | 目前狀態 | +|---|---|---|---| +| Renovate for Gitea | Hermes | 依賴更新 PR 草案、grouping、automerge=false | 只建立批准包;bot token、workflow、PR 全部未啟用 | +| OSV-Scanner | OpenClaw | 依賴漏洞 advisory lookup 候選 | 只建立批准包;外部查詢與 DB lookup 未啟用 | +| Trivy | OpenClaw | Container / filesystem / IaC / SBOM scanner 候選 | 只建立批准包;不安裝、不下載 DB、不掃 image | +| Syft | Hermes | SBOM 產生候選 | 只建立批准包;不產 SBOM artifact、不上傳 artifact | +| Grype | OpenClaw | Syft SBOM / image vulnerability cross-check 候選 | 只建立批准包;不安裝、不下載 DB、不送 Telegram | + +P2-402C 的重點是把「哪些工具可被採用、採用前要填哪些批准欄位、風險與 rollback 如何定義」固定成資料契約。它不是工具導入本身;工具安裝、CI workflow、外部 registry / vulnerability DB、Gitea PR、Telegram 實發都維持 blocked。 + +## 6. 下一步優先順序 | ID | 優先 | 任務 | 關卡 | |---|---|---|---| -| P2-402B | 0 | repo-only daily version freshness snapshot | 已完成,只讀;workflow schedule 未啟用 | -| P2-402C | 1 | Renovate / OSV / Trivy / Syft / Grype 採用批准包 | tool install / CI approval | -| P2-402D | 2 | Telegram action-required digest policy | Telegram Gateway E2E | -| P2-402E | 3 | Gitea PR 草案 lane | bot / branch policy approval | -| P2-402F | 4 | host OS / K3s / stateful services 版本只讀盤點 | host probe / maintenance approval | -| P2-402G | 5 | governance UI 顯示可委派能力 | frontend UI approval | +| P2-402C | 0 | Renovate / OSV-Scanner / Trivy / Syft / Grype 採用批准包 | 已完成,只讀;tool install / CI change 未啟用 | +| P2-402D | 1 | Telegram action-required digest policy | Telegram Gateway E2E | +| P2-402E | 2 | Gitea PR 草案 lane | bot / branch policy approval | +| P2-402F | 3 | host OS / K3s / stateful services 版本只讀盤點 | host probe / maintenance approval | +| P2-402G | 4 | governance UI 顯示可委派能力 | frontend UI approval | -## 6. 仍維持 false 的安全邊界 +## 7. 仍維持 false 的安全邊界 - `runtime_version_update_allowed=false` - `package_upgrade_allowed=false` diff --git a/docs/ai/AI_AGENT_TOOL_ADOPTION_APPROVAL_PACKAGE_2026-06-11.md b/docs/ai/AI_AGENT_TOOL_ADOPTION_APPROVAL_PACKAGE_2026-06-11.md new file mode 100644 index 000000000..4992607d3 --- /dev/null +++ b/docs/ai/AI_AGENT_TOOL_ADOPTION_APPROVAL_PACKAGE_2026-06-11.md @@ -0,0 +1,72 @@ +# AI Agent 工具採用批准包工作報告 + +> 日期:2026-06-11(台北時間) +> 狀態:P2-402C 已完成;整體 AI Agent 主動營運與版本生命週期完成度 55%。 +> 邊界:本文件與對應 API 只提供批准包,不安裝工具、不改 CI、不查外部 registry、不下載漏洞 DB、不建立 PR、不 auto merge、不發 Telegram、不改 production route。 + +## 1. 本波完成項目 + +| 項目 | 狀態 | 產出 | +|---|---|---| +| 工具採用 schema | 完成 | `docs/schemas/ai_agent_tool_adoption_approval_package_v1.schema.json` | +| 工具採用 snapshot | 完成 | `docs/evaluations/ai_agent_tool_adoption_approval_package_2026-06-11.json` | +| API loader | 完成 | `apps/api/src/services/ai_agent_tool_adoption_approval_package.py` | +| 只讀 API | 完成 | `GET /api/v1/agents/agent-tool-adoption-approval-package` | +| 測試 | 完成 | loader / API / safety boundary / rollup mismatch / unknown source ref | +| 主契約同步 | 完成 | `ai_agent_proactive_operations_contract_v1` 完成度 55%,current `P2-402C`,next `P2-402D` | + +## 2. 官方來源與工具角色 + +| 工具 | 官方來源 | 主責 Agent | 專業角色 | 採用前必過關卡 | +|---|---|---|---|---| +| Renovate for Gitea | | Hermes | 依賴更新 PR 草案、grouping、automerge=false、reviewer policy | Gitea bot token、workflow、branch policy、PR storm rollback | +| OSV-Scanner | | OpenClaw | 依賴漏洞 advisory lookup 候選 | 外部查詢、cache TTL、false-positive、severity mapping | +| Trivy | | OpenClaw | container / filesystem / IaC / SBOM / Kubernetes scanner 候選 | DB cache、runner cost、registry credential、image/build 邊界 | +| Syft | | Hermes | SBOM 產生候選 | SBOM schema、artifact retention、redaction、storage path | +| Grype | | OpenClaw | Syft SBOM / image vulnerability cross-check 候選 | vulnerability DB cache、suppression、duplicate handling、Telegram gate | + +## 3. Agent 分工 + +| Agent | 本波可做 | 本波不可做 | +|---|---|---| +| Hermes | 彙整官方來源、工具欄位、Gitea PR lane 草案、SBOM artifact policy 草案 | 建立 bot token、寫 workflow、產 SBOM、建立 PR | +| OpenClaw | 仲裁 secret / CI / 費用 / false-positive / blast-radius,要求 HITL approval | 自行批准工具啟用、改 CI runner、改 Alertmanager / Telegram route、auto merge | +| NemoTron | 建立離線 replay 欄位,評估 scanner output 如何影響 AI Agent / prompt / tool-call 品質 | 新增 SDK、呼叫付費模型、開 shadow/canary、改 provider route | + +## 4. 後續代辦與優先順序 + +| 優先 | ID | 工作 | 完成標準 | 目前狀態 | +|---:|---|---|---|---| +| 1 | P2-402D | Telegram action-required digest policy | 定義 critical / action-required / failure-only,禁止成功洗版,接 Telegram Gateway E2E gate | 待辦 | +| 2 | P2-402E | Gitea PR 草案 lane | Renovate grouping、automerge=false、測試要求、rollback、owner response | 待辦 | +| 3 | P2-402F | host OS / K3s / stateful services 版本只讀盤點 | 主機、K3s、PostgreSQL、Redis、MinIO、Harbor、Gitea 只讀版本矩陣 | 待辦 | +| 4 | P2-402G | Governance UI 顯示可委派能力 | 前端顯示 autonomy level、gate、owner、Telegram policy,無執行按鈕 | 待辦 | +| 5 | 候選池 | SBOM artifact policy | Syft / Trivy artifact 格式、保存、redaction、消費者規則 | 未排正式編號 | +| 6 | 候選池 | Scanner false-positive policy | OSV / Trivy / Grype 差異、suppression、severity mapping、owner SLA | 未排正式編號 | +| 7 | 候選池 | Version history / RAG 回寫 | 每次版本觀測、批准、失敗、rollback 回寫 `version_history` / `upgrade_outcomes` | 未排正式編號 | + +## 5. 現在仍維持 false 的邊界 + +- `tool_install_allowed=false` +- `ci_workflow_change_allowed=false` +- `external_registry_lookup_allowed=false` +- `vulnerability_database_download_allowed=false` +- `package_upgrade_allowed=false` +- `lockfile_write_allowed=false` +- `docker_build_allowed=false` +- `image_pull_allowed=false` +- `gitea_pr_creation_allowed=false` +- `auto_merge_allowed=false` +- `telegram_direct_send_allowed=false` +- `paid_service_enabled=false` +- `production_route_change_allowed=false` +- `secret_plaintext_allowed=false` + +## 6. 進度同步方式 + +每推進一個正式 task,必須同步更新四個地方: + +1. `docs/evaluations/ai_agent_proactive_operations_contract_2026-06-11.json` 的完成度、current task、next task。 +2. `docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md` 的狀態、百分比、關卡。 +3. `docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md` 的 §3.2.1c 與 changelog。 +4. `docs/LOGBOOK.md` 的正式工作紀錄、驗證結果與 deployment evidence。 diff --git a/docs/evaluations/ai_agent_proactive_operations_contract_2026-06-11.json b/docs/evaluations/ai_agent_proactive_operations_contract_2026-06-11.json index e3750b0b5..2bca560c1 100644 --- a/docs/evaluations/ai_agent_proactive_operations_contract_2026-06-11.json +++ b/docs/evaluations/ai_agent_proactive_operations_contract_2026-06-11.json @@ -2,13 +2,13 @@ "schema_version": "ai_agent_proactive_operations_contract_v1", "generated_at": "2026-06-11T21:30:00+08:00", "program_status": { - "overall_completion_percent": 42, + "overall_completion_percent": 55, "current_priority": "P2", - "current_task_id": "P2-402B", - "next_task_id": "P2-402C", + "current_task_id": "P2-402C", + "next_task_id": "P2-402D", "read_only_mode": true, "runtime_authority": "contract_only_no_version_or_runtime_update", - "status_note": "P2-402B 已建立 repo-only 版本新鮮度快照與只讀 API;本波仍不啟用排程、不升級套件、不更新主機、不 pull image、不 auto merge、不發 Telegram。" + "status_note": "P2-402C 已建立 Renovate / OSV-Scanner / Trivy / Syft / Grype 工具採用批准包、schema、snapshot、只讀 API 與測試;本波仍不安裝工具、不改 CI、不查外部 registry、不下載漏洞 DB、不建立 PR、不發 Telegram。" }, "external_source_evidence": [ { @@ -619,16 +619,16 @@ "completion_percent": 100, "owner_agent": "Hermes", "summary": "建立 repo-only daily version freshness snapshot schema、committed snapshot、只讀 API 與測試;不查外部 registry、不改 workflow。", - "next_gate": "P2-402C_tool_adoption_approval_package" + "next_gate": "P2-402C_completed" }, { "task_id": "P2-402C", "priority": "P2", - "status": "planned", - "completion_percent": 0, + "status": "done", + "completion_percent": 100, "owner_agent": "OpenClaw", - "summary": "建立 Renovate / OSV / Trivy / Syft / Grype 工具採用批准包。", - "next_gate": "tool_install_ci_change_and_secret_approval_required" + "summary": "建立 Renovate / OSV-Scanner / Trivy / Syft / Grype 工具採用批准包、官方來源 evidence、採用 lane、批准欄位、schema、snapshot、只讀 API 與測試。", + "next_gate": "P2-402D_telegram_action_required_digest_policy" }, { "task_id": "P2-402D", diff --git a/docs/evaluations/ai_agent_tool_adoption_approval_package_2026-06-11.json b/docs/evaluations/ai_agent_tool_adoption_approval_package_2026-06-11.json new file mode 100644 index 000000000..e1018c472 --- /dev/null +++ b/docs/evaluations/ai_agent_tool_adoption_approval_package_2026-06-11.json @@ -0,0 +1,471 @@ +{ + "schema_version": "ai_agent_tool_adoption_approval_package_v1", + "generated_at": "2026-06-11T23:35:00+08:00", + "program_status": { + "overall_completion_percent": 55, + "current_priority": "P2", + "current_task_id": "P2-402C", + "next_task_id": "P2-402D", + "read_only_mode": true, + "runtime_authority": "approval_package_only_no_tool_install_or_ci_change", + "status_note": "P2-402C 建立 Renovate / OSV-Scanner / Trivy / Syft / Grype 工具採用批准包;本波只保留官方來源與採用門檻,不安裝工具、不改 CI、不下載漏洞 DB、不建立 PR、不發 Telegram。" + }, + "source_evidence": [ + { + "source_id": "renovate_gitea_platform_docs", + "tool_id": "renovate_gitea", + "name": "Renovate Gitea platform docs", + "url": "https://docs.renovatebot.com/modules/platform/gitea/", + "retrieved_at": "2026-06-11T23:35:00+08:00", + "evidence_type": "official_documentation", + "usage_boundary": "只用於確認 Renovate 支援 Gitea 與 autodiscover / PR 權限需求;本波不啟用 bot、不寫 workflow、不建立 PR。" + }, + { + "source_id": "osv_scanner_usage_docs", + "tool_id": "osv_scanner", + "name": "OSV-Scanner usage docs", + "url": "https://google.github.io/osv-scanner/usage/", + "retrieved_at": "2026-06-11T23:35:00+08:00", + "evidence_type": "official_documentation", + "usage_boundary": "只用於確認 OSV-Scanner V2 使用面;本波不下載漏洞資料、不掃描專案、不呼叫外部查詢。" + }, + { + "source_id": "trivy_docs", + "tool_id": "trivy", + "name": "Trivy official docs", + "url": "https://trivy.dev/", + "retrieved_at": "2026-06-11T23:35:00+08:00", + "evidence_type": "official_documentation", + "usage_boundary": "只用於確認 Trivy 可作為漏洞 / IaC / SBOM / Kubernetes 類掃描候選;本波不安裝、不掃描、不下載 vulnerability DB。" + }, + { + "source_id": "anchore_syft_docs", + "tool_id": "syft", + "name": "Anchore Syft open source docs", + "url": "https://anchore.com/opensource/", + "retrieved_at": "2026-06-11T23:35:00+08:00", + "evidence_type": "official_documentation", + "usage_boundary": "只用於確認 Syft 是 SBOM 產生候選;本波不安裝、不產 SBOM、不寫 artifact。" + }, + { + "source_id": "anchore_grype_docs", + "tool_id": "grype", + "name": "Anchore Grype open source docs", + "url": "https://anchore.com/opensource/", + "retrieved_at": "2026-06-11T23:35:00+08:00", + "evidence_type": "official_documentation", + "usage_boundary": "只用於確認 Grype 是 container / filesystem vulnerability scanner 候選;本波不安裝、不掃描、不下載資料庫。" + } + ], + "agent_review_matrix": [ + { + "agent_id": "hermes", + "role": "彙整官方來源、repo-only freshness source、CI 變更點與 evidence refs。", + "allowed_now": [ + "讀 committed snapshot", + "整理工具採用批准欄位", + "產出比較表與 next gate" + ], + "blocked_until_approval": [ + "安裝工具", + "寫 workflow", + "下載漏洞資料庫", + "建立 Renovate PR" + ], + "output": "tool adoption evidence packet" + }, + { + "agent_id": "openclaw", + "role": "仲裁工具採用風險、secret / 費用 / CI / false-positive / blast-radius 邊界。", + "allowed_now": [ + "審核採用門檻", + "要求 HITL approval", + "定義 rollback 與 failure-only notification 條件" + ], + "blocked_until_approval": [ + "批准自己的工具啟用", + "改 CI runner", + "改 Alertmanager 或 Telegram route", + "auto merge" + ], + "output": "HITL approval package verdict" + }, + { + "agent_id": "nemotron", + "role": "離線比較掃描器輸出如何影響 AI Agent / model / prompt / tool-call replay 評分。", + "allowed_now": [ + "建立離線 replay 欄位", + "標記 scanner assumption risk", + "建議多工具交叉驗證策略" + ], + "blocked_until_approval": [ + "新增 SDK", + "呼叫付費模型", + "shadow/canary", + "production provider route" + ], + "output": "offline scanner-assumption review note" + } + ], + "adoption_lanes": [ + { + "lane_id": "dependency_update_pr_lane", + "display_name": "Dependency update PR lane", + "owner_agent": "hermes", + "tool_ids": [ + "renovate_gitea" + ], + "approval_gate": "gitea_bot_token_branch_policy_and_ci_workflow_approval", + "planned_output": "Renovate config / grouping / automerge=false / reviewer policy approval package", + "blocked_now": [ + "建立 bot token", + "寫 renovate config", + "啟用 autodiscover", + "建立 PR", + "auto merge" + ] + }, + { + "lane_id": "vulnerability_lookup_lane", + "display_name": "Vulnerability lookup lane", + "owner_agent": "openclaw", + "tool_ids": [ + "osv_scanner", + "trivy", + "grype" + ], + "approval_gate": "external_source_cache_rate_limit_and_false_positive_policy_approval", + "planned_output": "CVE / OSV / advisory lookup approval package with cache and suppression policy", + "blocked_now": [ + "下載 vulnerability DB", + "查外部 advisory", + "掃描 image / filesystem", + "把 scanner output 當唯一事實" + ] + }, + { + "lane_id": "sbom_generation_lane", + "display_name": "SBOM generation lane", + "owner_agent": "hermes", + "tool_ids": [ + "syft", + "trivy" + ], + "approval_gate": "artifact_retention_and_sbom_schema_approval", + "planned_output": "SPDX / CycloneDX / JSON artifact policy and storage path approval package", + "blocked_now": [ + "安裝 Syft", + "產生 SBOM artifact", + "上傳 artifact", + "保存 package payload 超出批准範圍" + ] + }, + { + "lane_id": "container_crosscheck_lane", + "display_name": "Container scanner cross-check lane", + "owner_agent": "openclaw", + "tool_ids": [ + "trivy", + "syft", + "grype" + ], + "approval_gate": "container_scan_runbook_and_dedup_policy_approval", + "planned_output": "Trivy vs Syft+Grype cross-check runbook and false-positive review policy", + "blocked_now": [ + "docker build", + "image pull", + "registry push", + "改 Harbor / ArgoCD / production route" + ] + } + ], + "tool_candidates": [ + { + "tool_id": "renovate_gitea", + "display_name": "Renovate for Gitea", + "category": "dependency_update_pr", + "owner_agent": "hermes", + "adoption_status": "approval_required", + "risk_tier": "high", + "cost_profile": "open_source_self_hosted_candidate; runner usage and maintenance cost require approval", + "secret_requirement": "Gitea bot token / repo permission required after approval; no token is created or read in this package.", + "external_data_requirement": "Package registry metadata required after approval; currently blocked.", + "ci_change_required": true, + "official_source_refs": [ + "renovate_gitea_platform_docs" + ], + "intended_scope": [ + "dependency update PR draft", + "grouping", + "automerge=false", + "reviewer assignment" + ], + "approval_requirements": [ + "Gitea bot identity and token storage plan", + "branch naming and PR grouping policy", + "automerge=false hard gate", + "rate limit and schedule policy", + "rollback plan for bad PR storm" + ], + "blocked_until_approval": [ + "renovate config write", + "workflow schedule activation", + "bot token creation", + "PR creation", + "auto merge" + ], + "recommendation": "Adopt only after P2-402E Gitea PR lane and branch policy approval; do not enable during P2-402C.", + "rollback_plan": "Disable workflow / bot token, close generated PRs, revert Renovate config commit; no production route change allowed." + }, + { + "tool_id": "osv_scanner", + "display_name": "OSV-Scanner", + "category": "vulnerability_lookup", + "owner_agent": "openclaw", + "adoption_status": "approval_required", + "risk_tier": "medium", + "cost_profile": "free_public_candidate; network and rate-limit policy still require approval", + "secret_requirement": "No project secret required for public lookup candidate; cache policy required.", + "external_data_requirement": "OSV vulnerability database lookup required after approval; currently blocked.", + "ci_change_required": true, + "official_source_refs": [ + "osv_scanner_usage_docs" + ], + "intended_scope": [ + "dependency vulnerability lookup", + "lockfile / manifest advisory matching", + "approval package evidence" + ], + "approval_requirements": [ + "network egress and cache TTL policy", + "false-positive suppression process", + "severity mapping to dependency_risk_policy_v1", + "failure-only notification policy", + "artifact retention boundary" + ], + "blocked_until_approval": [ + "external advisory lookup", + "vulnerability DB query", + "CI workflow write", + "package upgrade" + ], + "recommendation": "Adopt as first vulnerability lookup candidate after cache/rate-limit approval; keep output advisory-only until OpenClaw review.", + "rollback_plan": "Remove workflow step and cached advisory artifacts; keep prior repo-only freshness snapshot as fallback." + }, + { + "tool_id": "trivy", + "display_name": "Trivy", + "category": "container_iac_vulnerability_scan", + "owner_agent": "openclaw", + "adoption_status": "approval_required", + "risk_tier": "high", + "cost_profile": "open_source_candidate; DB download, cache, runner time and false-positive review cost require approval", + "secret_requirement": "No plaintext secret allowed; registry credentials only after dedicated secret policy approval.", + "external_data_requirement": "Vulnerability DB and optional registry/image metadata required after approval; currently blocked.", + "ci_change_required": true, + "official_source_refs": [ + "trivy_docs" + ], + "intended_scope": [ + "container image vulnerability scan", + "filesystem scan", + "IaC / Kubernetes config scan", + "SBOM or misconfiguration signal" + ], + "approval_requirements": [ + "runner cache and DB update policy", + "image pull/build boundary", + "registry credential handling", + "false-positive triage and suppression owner", + "cross-check with Syft / Grype before action-required escalation" + ], + "blocked_until_approval": [ + "trivy install", + "vulnerability DB download", + "filesystem scan", + "image scan", + "Kubernetes live scan", + "CI workflow write" + ], + "recommendation": "Adopt after OSV baseline and SBOM artifact policy; use as primary container/IaC scanner only with OpenClaw gating.", + "rollback_plan": "Disable scan job, remove scanner cache, keep prior Dockerfile surface inventory; do not change images or deployments." + }, + { + "tool_id": "syft", + "display_name": "Syft", + "category": "sbom_generation", + "owner_agent": "hermes", + "adoption_status": "approval_required", + "risk_tier": "medium", + "cost_profile": "open_source_candidate; runner time and artifact storage require approval", + "secret_requirement": "No secret required for repo filesystem SBOM; registry credentials blocked until approved.", + "external_data_requirement": "No external vulnerability DB needed for local SBOM generation; package cataloging scope still requires approval.", + "ci_change_required": true, + "official_source_refs": [ + "anchore_syft_docs" + ], + "intended_scope": [ + "SBOM generation from filesystem", + "container image SBOM after image policy approval", + "SPDX / CycloneDX / JSON artifact candidate" + ], + "approval_requirements": [ + "SBOM schema and artifact retention decision", + "redaction and private package payload policy", + "artifact storage path", + "consumer policy for Grype / external scanners" + ], + "blocked_until_approval": [ + "syft install", + "SBOM artifact write", + "image cataloging", + "artifact upload" + ], + "recommendation": "Adopt as SBOM source of truth candidate before broad scanner rollout; never treat SBOM as remediation approval.", + "rollback_plan": "Delete generated artifacts by retention policy and disable SBOM step; no package or image mutation." + }, + { + "tool_id": "grype", + "display_name": "Grype", + "category": "vulnerability_scan_from_sbom_or_image", + "owner_agent": "openclaw", + "adoption_status": "approval_required", + "risk_tier": "medium", + "cost_profile": "open_source_candidate; DB download, cache, runner time and triage cost require approval", + "secret_requirement": "No plaintext secret allowed; registry credentials blocked until image scan policy approval.", + "external_data_requirement": "Vulnerability DB required after approval; currently blocked.", + "ci_change_required": true, + "official_source_refs": [ + "anchore_grype_docs" + ], + "intended_scope": [ + "scan Syft SBOM", + "scan image/filesystem after approval", + "cross-check Trivy vulnerability signal" + ], + "approval_requirements": [ + "Syft SBOM input policy", + "vulnerability DB cache policy", + "severity and fix-available mapping", + "false-positive and duplicate handling", + "OpenClaw review before action-required Telegram digest" + ], + "blocked_until_approval": [ + "grype install", + "vulnerability DB download", + "image/filesystem scan", + "CI workflow write", + "Telegram digest send" + ], + "recommendation": "Adopt as cross-check scanner paired with Syft and Trivy; use disagreement as review signal, not automatic blocker.", + "rollback_plan": "Disable Grype step and remove DB cache; preserve Syft SBOM artifact policy separately." + } + ], + "approval_packet_fields": [ + { + "field_id": "operator_approval_id", + "required": true, + "owner_agent": "openclaw", + "description": "人工批准 ID;未填不得安裝工具、改 CI 或查外部。" + }, + { + "field_id": "secret_storage_plan", + "required": true, + "owner_agent": "openclaw", + "description": "Gitea bot token / registry credentials / cache token 的存放與注入規則;不得記錄明文。" + }, + { + "field_id": "ci_runner_cost_and_cache_plan", + "required": true, + "owner_agent": "hermes", + "description": "runner 時間、cache 目錄、DB 更新頻率、artifact retention 與清理策略。" + }, + { + "field_id": "false_positive_triage_policy", + "required": true, + "owner_agent": "openclaw", + "description": "掃描器差異、誤報、suppression、severity mapping 與 owner response 流程。" + }, + { + "field_id": "telegram_digest_gate", + "required": true, + "owner_agent": "openclaw", + "description": "P2-402D 才能啟用 action-required digest;成功掃描不得洗版。" + }, + { + "field_id": "rollback_and_disable_plan", + "required": true, + "owner_agent": "hermes", + "description": "出現 PR storm、DB download failure、runner overload 或大量 false-positive 時的停用流程。" + } + ], + "approval_boundaries": { + "tool_install_allowed": false, + "ci_workflow_change_allowed": false, + "external_registry_lookup_allowed": false, + "vulnerability_database_download_allowed": false, + "package_upgrade_allowed": false, + "lockfile_write_allowed": false, + "docker_build_allowed": false, + "image_pull_allowed": false, + "gitea_pr_creation_allowed": false, + "auto_merge_allowed": false, + "telegram_direct_send_allowed": false, + "paid_service_enabled": false, + "production_route_change_allowed": false, + "secret_plaintext_allowed": false + }, + "rollups": { + "tool_count": 5, + "source_evidence_count": 5, + "adoption_lane_count": 4, + "approval_required_tool_ids": [ + "renovate_gitea", + "osv_scanner", + "trivy", + "syft", + "grype" + ], + "ci_change_required_tool_ids": [ + "renovate_gitea", + "osv_scanner", + "trivy", + "syft", + "grype" + ], + "secret_required_tool_ids": [ + "renovate_gitea", + "trivy", + "syft", + "grype" + ], + "external_data_required_tool_ids": [ + "renovate_gitea", + "osv_scanner", + "trivy", + "grype" + ], + "sbom_tool_ids": [ + "syft", + "trivy" + ], + "vulnerability_scan_tool_ids": [ + "osv_scanner", + "trivy", + "grype" + ], + "update_pr_tool_ids": [ + "renovate_gitea" + ], + "tool_install_allowed_count": 0, + "ci_change_allowed_count": 0, + "auto_merge_allowed_count": 0, + "telegram_direct_send_count": 0, + "next_approval_task_ids": [ + "P2-402D", + "P2-402E", + "P2-402F", + "P2-402G" + ] + } +} diff --git a/docs/schemas/ai_agent_tool_adoption_approval_package_v1.schema.json b/docs/schemas/ai_agent_tool_adoption_approval_package_v1.schema.json new file mode 100644 index 000000000..c71fdffaa --- /dev/null +++ b/docs/schemas/ai_agent_tool_adoption_approval_package_v1.schema.json @@ -0,0 +1,474 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://awoooi.wooo.work/schemas/ai_agent_tool_adoption_approval_package_v1.schema.json", + "title": "AI Agent Tool Adoption Approval Package v1", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "generated_at", + "program_status", + "source_evidence", + "agent_review_matrix", + "adoption_lanes", + "tool_candidates", + "approval_packet_fields", + "approval_boundaries", + "rollups" + ], + "properties": { + "schema_version": { + "const": "ai_agent_tool_adoption_approval_package_v1" + }, + "generated_at": { + "type": "string" + }, + "program_status": { + "type": "object", + "additionalProperties": false, + "required": [ + "overall_completion_percent", + "current_priority", + "current_task_id", + "next_task_id", + "read_only_mode", + "runtime_authority", + "status_note" + ], + "properties": { + "overall_completion_percent": { + "type": "integer", + "minimum": 0, + "maximum": 100 + }, + "current_priority": { + "type": "string" + }, + "current_task_id": { + "type": "string" + }, + "next_task_id": { + "type": "string" + }, + "read_only_mode": { + "const": true + }, + "runtime_authority": { + "const": "approval_package_only_no_tool_install_or_ci_change" + }, + "status_note": { + "type": "string" + } + } + }, + "source_evidence": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "source_id", + "tool_id", + "name", + "url", + "retrieved_at", + "evidence_type", + "usage_boundary" + ], + "properties": { + "source_id": { + "type": "string" + }, + "tool_id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "url": { + "type": "string" + }, + "retrieved_at": { + "type": "string" + }, + "evidence_type": { + "type": "string" + }, + "usage_boundary": { + "type": "string" + } + } + } + }, + "agent_review_matrix": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "agent_id", + "role", + "allowed_now", + "blocked_until_approval", + "output" + ], + "properties": { + "agent_id": { + "type": "string" + }, + "role": { + "type": "string" + }, + "allowed_now": { + "type": "array", + "items": { + "type": "string" + } + }, + "blocked_until_approval": { + "type": "array", + "items": { + "type": "string" + } + }, + "output": { + "type": "string" + } + } + } + }, + "adoption_lanes": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "lane_id", + "display_name", + "owner_agent", + "tool_ids", + "approval_gate", + "planned_output", + "blocked_now" + ], + "properties": { + "lane_id": { + "type": "string" + }, + "display_name": { + "type": "string" + }, + "owner_agent": { + "type": "string" + }, + "tool_ids": { + "type": "array", + "items": { + "type": "string" + } + }, + "approval_gate": { + "type": "string" + }, + "planned_output": { + "type": "string" + }, + "blocked_now": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "tool_candidates": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "tool_id", + "display_name", + "category", + "owner_agent", + "adoption_status", + "risk_tier", + "cost_profile", + "secret_requirement", + "external_data_requirement", + "ci_change_required", + "official_source_refs", + "intended_scope", + "approval_requirements", + "blocked_until_approval", + "recommendation", + "rollback_plan" + ], + "properties": { + "tool_id": { + "type": "string" + }, + "display_name": { + "type": "string" + }, + "category": { + "type": "string" + }, + "owner_agent": { + "type": "string" + }, + "adoption_status": { + "enum": [ + "approval_required", + "defer_until_gate", + "rejected" + ] + }, + "risk_tier": { + "enum": [ + "low", + "medium", + "high" + ] + }, + "cost_profile": { + "type": "string" + }, + "secret_requirement": { + "type": "string" + }, + "external_data_requirement": { + "type": "string" + }, + "ci_change_required": { + "type": "boolean" + }, + "official_source_refs": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + }, + "intended_scope": { + "type": "array", + "items": { + "type": "string" + } + }, + "approval_requirements": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + }, + "blocked_until_approval": { + "type": "array", + "items": { + "type": "string" + } + }, + "recommendation": { + "type": "string" + }, + "rollback_plan": { + "type": "string" + } + } + } + }, + "approval_packet_fields": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "field_id", + "required", + "owner_agent", + "description" + ], + "properties": { + "field_id": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "owner_agent": { + "type": "string" + }, + "description": { + "type": "string" + } + } + } + }, + "approval_boundaries": { + "type": "object", + "additionalProperties": false, + "required": [ + "tool_install_allowed", + "ci_workflow_change_allowed", + "external_registry_lookup_allowed", + "vulnerability_database_download_allowed", + "package_upgrade_allowed", + "lockfile_write_allowed", + "docker_build_allowed", + "image_pull_allowed", + "gitea_pr_creation_allowed", + "auto_merge_allowed", + "telegram_direct_send_allowed", + "paid_service_enabled", + "production_route_change_allowed", + "secret_plaintext_allowed" + ], + "properties": { + "tool_install_allowed": { + "const": false + }, + "ci_workflow_change_allowed": { + "const": false + }, + "external_registry_lookup_allowed": { + "const": false + }, + "vulnerability_database_download_allowed": { + "const": false + }, + "package_upgrade_allowed": { + "const": false + }, + "lockfile_write_allowed": { + "const": false + }, + "docker_build_allowed": { + "const": false + }, + "image_pull_allowed": { + "const": false + }, + "gitea_pr_creation_allowed": { + "const": false + }, + "auto_merge_allowed": { + "const": false + }, + "telegram_direct_send_allowed": { + "const": false + }, + "paid_service_enabled": { + "const": false + }, + "production_route_change_allowed": { + "const": false + }, + "secret_plaintext_allowed": { + "const": false + } + } + }, + "rollups": { + "type": "object", + "additionalProperties": false, + "required": [ + "tool_count", + "source_evidence_count", + "adoption_lane_count", + "approval_required_tool_ids", + "ci_change_required_tool_ids", + "secret_required_tool_ids", + "external_data_required_tool_ids", + "sbom_tool_ids", + "vulnerability_scan_tool_ids", + "update_pr_tool_ids", + "tool_install_allowed_count", + "ci_change_allowed_count", + "auto_merge_allowed_count", + "telegram_direct_send_count", + "next_approval_task_ids" + ], + "properties": { + "tool_count": { + "type": "integer", + "minimum": 0 + }, + "source_evidence_count": { + "type": "integer", + "minimum": 0 + }, + "adoption_lane_count": { + "type": "integer", + "minimum": 0 + }, + "approval_required_tool_ids": { + "type": "array", + "items": { + "type": "string" + } + }, + "ci_change_required_tool_ids": { + "type": "array", + "items": { + "type": "string" + } + }, + "secret_required_tool_ids": { + "type": "array", + "items": { + "type": "string" + } + }, + "external_data_required_tool_ids": { + "type": "array", + "items": { + "type": "string" + } + }, + "sbom_tool_ids": { + "type": "array", + "items": { + "type": "string" + } + }, + "vulnerability_scan_tool_ids": { + "type": "array", + "items": { + "type": "string" + } + }, + "update_pr_tool_ids": { + "type": "array", + "items": { + "type": "string" + } + }, + "tool_install_allowed_count": { + "const": 0 + }, + "ci_change_allowed_count": { + "const": 0 + }, + "auto_merge_allowed_count": { + "const": 0 + }, + "telegram_direct_send_count": { + "const": 0 + }, + "next_approval_task_ids": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } +} 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 3e610aa5e..1c8d98f67 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 @@ -670,19 +670,23 @@ Repo / registry / release notes / K8s / host / observability / backup evidence | 檔案 / API | 用途 | |---|---| | `docs/schemas/ai_agent_proactive_operations_contract_v1.schema.json` | 主動營運委派、版本生命週期、MCP、RAG、Telegram policy、approval boundary 契約 | -| `docs/evaluations/ai_agent_proactive_operations_contract_2026-06-11.json` | 12 類版本 domain、24 類可委派能力、5 種 cadence、8 類 MCP、4 類 RAG memory;完成度 `42%` | +| `docs/evaluations/ai_agent_proactive_operations_contract_2026-06-11.json` | 12 類版本 domain、24 類可委派能力、5 種 cadence、8 類 MCP、4 類 RAG memory;完成度 `55%` | | `apps/api/src/services/ai_agent_proactive_operations_contract.py` | 只讀 loader;強制 runtime update / package upgrade / host upgrade / workflow schedule / auto merge / Telegram direct send 全部 false | | `GET /api/v1/agents/agent-proactive-operations-contract` | 治理 API;只回傳 committed snapshot,不啟用排程、不升級、不呼叫付費服務 | | `docs/schemas/ai_agent_version_freshness_snapshot_v1.schema.json` | P2-402B repo-only 版本新鮮度 schema;鎖定 schedule / external lookup / upgrade / Telegram / PR / host probe 全部 false | | `docs/evaluations/ai_agent_version_freshness_snapshot_2026-06-11.json` | P2-402B committed snapshot:12 類 repo-only 版本來源、5 個每日設計步驟、3 Agent 角色、5 個 action-required source | | `GET /api/v1/agents/agent-version-freshness-snapshot` | 只讀 API;回傳 repo-only freshness snapshot,不觸發掃描、不查外部、不改 repo、不送 Telegram | +| `docs/schemas/ai_agent_tool_adoption_approval_package_v1.schema.json` | P2-402C 工具採用批准包 schema;鎖定 tool install / CI change / external lookup / vulnerability DB / PR / Telegram 全部 false | +| `docs/evaluations/ai_agent_tool_adoption_approval_package_2026-06-11.json` | P2-402C committed snapshot:Renovate / OSV-Scanner / Trivy / Syft / Grype 官方來源、採用 lane、批准欄位與 rollback gate | +| `GET /api/v1/agents/agent-tool-adoption-approval-package` | 只讀 API;只回傳工具採用批准包,不安裝工具、不改 CI、不查外部、不建 PR、不發 Telegram | **採用順序:** 1. 先做 repo-only daily freshness:manifest / lockfile / Dockerfile / K8s YAML / runbook / snapshot。✅ P2-402B 已建立 committed snapshot/API;每日排程仍未授權。 -2. 再評估 external primary source weekly watch:Renovate、OSV-Scanner、Trivy、Syft、Grype、Kubernetes skew policy、Docker Scout。下一步 P2-402C 只建立工具採用批准包。 -3. 再進 Gitea PR 草案 lane:grouping、automerge=false、tests、rollback、owner response。 -4. 最後才進人工批准後的 dry-run / smoke / canary / production rollout。 +2. 再評估 external primary source weekly watch:Renovate、OSV-Scanner、Trivy、Syft、Grype、Kubernetes skew policy、Docker Scout。✅ P2-402C 已建立工具採用批准包;工具安裝、CI 變更、外部查詢仍未授權。 +3. 建立 Telegram action-required digest policy,先定義 critical / action-required / failure-only 通知門檻,禁止成功洗版。下一步 P2-402D。 +4. 再進 Gitea PR 草案 lane:grouping、automerge=false、tests、rollback、owner response。 +5. 最後才進人工批准後的 dry-run / smoke / canary / production rollout。 #### 3.2.2 核心缺口與災難場景 @@ -1318,6 +1322,7 @@ Repo / registry / release notes / K8s / host / observability / backup evidence | 主動溝通與學習契約 | `docs/evaluations/ai_agent_communication_learning_contract_2026-06-11.json` + `GET /api/v1/agents/agent-communication-learning-contract` | 先固定 OpenClaw / Hermes / NemoTron 主動溝通、MCP、RAG、學習與 redaction 邊界;不啟動 runtime worker | L4×D2 / L7×D4 | | 主動營運委派與版本生命週期契約 | `docs/evaluations/ai_agent_proactive_operations_contract_2026-06-11.json` + `GET /api/v1/agents/agent-proactive-operations-contract` | 先固定 12 類版本 domain、24 類可委派能力、MCP/RAG/Telegram 邊界;不啟用排程、不自動升版 | L4×D2 / L7×D4 / L6×D6 | | Repo-only 版本新鮮度快照 | `docs/evaluations/ai_agent_version_freshness_snapshot_2026-06-11.json` + `GET /api/v1/agents/agent-version-freshness-snapshot` | P2-402B:讓 Hermes 可每日產生 repo-only freshness evidence packet;目前只讀 API,不啟用 schedule、不查外部、不升級 | L4×D2 / L7×D4 / L6×D6 | +| 工具採用批准包 | `docs/evaluations/ai_agent_tool_adoption_approval_package_2026-06-11.json` + `GET /api/v1/agents/agent-tool-adoption-approval-package` | P2-402C:讓 OpenClaw / Hermes / NemoTron 用官方來源評估 Renovate / OSV-Scanner / Trivy / Syft / Grype;目前只讀 API,不安裝工具、不改 CI、不查外部、不建 PR、不發 Telegram | L4×D2 / L7×D4 / L6×D6 | **退出條件(量化)** @@ -1695,6 +1700,12 @@ Phase 6 完成後 - 更新 `ai_agent_proactive_operations_contract_2026-06-11.json`:整體完成度 `42%`,current task `P2-402B`,next task `P2-402C`。 - 本波仍不啟用 workflow schedule、不查外部 registry/CVE、不安裝或升級套件、不寫 lockfile、不 build/pull image、不 probe host、不建立 PR、不發 Telegram;P2-402C 才建立 Renovate / OSV / Trivy / Syft / Grype 工具採用批准包。 +### 2026-06-11 23:35 (台北) — §3.2 / §5 — 完成 P2-402C 工具採用批准包 — 回應統帥要求讓 Agent 主動管理套件、工具與服務版本但先走批准制 + +- 新增 `ai_agent_tool_adoption_approval_package_v1` schema / committed snapshot / loader / API / 測試,定義 Renovate / OSV-Scanner / Trivy / Syft / Grype 的官方來源、採用 lane、secret / CI / external data gate、rollback plan 與 Agent 分工。 +- 更新 `ai_agent_proactive_operations_contract_2026-06-11.json`:整體完成度 `55%`,current task `P2-402C`,next task `P2-402D`。 +- 本波仍不安裝工具、不改 CI、不查外部 registry、不下載 vulnerability DB、不升級套件、不寫 lockfile、不 build/pull image、不建立 Gitea PR、不 auto merge、不發 Telegram;P2-402D 才建立 Telegram action-required digest policy。 + ### 2026-04-15 (台北) — 全檔 — 建立 v2 骨架,§0/§1 完成 — 統帥批准「單 MASTER + 4 道閘門」結構 - 從 v1(plans/2026-04-15-MASTER-ai-autonomous-flywheel.md)繼承核心發現