feat(governance): 新增 Agent 版本新鮮度快照
This commit is contained in:
@@ -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_version_freshness_snapshot import (
|
||||
load_latest_ai_agent_version_freshness_snapshot,
|
||||
)
|
||||
from src.services.ai_provider_route_matrix import (
|
||||
load_latest_ai_provider_route_matrix,
|
||||
)
|
||||
@@ -584,6 +587,33 @@ async def get_agent_proactive_operations_contract() -> dict[str, Any]:
|
||||
) from exc
|
||||
|
||||
|
||||
@router.get(
|
||||
"/agent-version-freshness-snapshot",
|
||||
response_model=dict[str, Any],
|
||||
summary="取得 AI Agent repo-only 版本新鮮度快照",
|
||||
description=(
|
||||
"讀取最新已提交的 AI Agent repo-only 版本新鮮度快照;此端點不啟用每日排程、"
|
||||
"不查外部 registry/CVE、不安裝或升級套件、不寫 lockfile、不 build/pull image、"
|
||||
"不 probe 主機、不建立 PR、不發 Telegram、不呼叫付費服務、不修改生產路由。"
|
||||
),
|
||||
)
|
||||
async def get_agent_version_freshness_snapshot() -> dict[str, Any]:
|
||||
"""Return the latest read-only AI Agent version freshness snapshot."""
|
||||
try:
|
||||
return await asyncio.to_thread(load_latest_ai_agent_version_freshness_snapshot)
|
||||
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_version_freshness_snapshot_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],
|
||||
|
||||
180
apps/api/src/services/ai_agent_version_freshness_snapshot.py
Normal file
180
apps/api/src/services/ai_agent_version_freshness_snapshot.py
Normal file
@@ -0,0 +1,180 @@
|
||||
"""
|
||||
AI Agent version freshness snapshot.
|
||||
|
||||
Loads the latest committed, read-only version freshness snapshot for OpenClaw,
|
||||
Hermes, and NemoTron. This module never enables schedules, queries external
|
||||
registries, installs or upgrades packages, writes lockfiles, builds or pulls
|
||||
images, probes hosts, creates PRs, sends Telegram messages, or changes
|
||||
production routing.
|
||||
"""
|
||||
|
||||
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_version_freshness_snapshot_*.json"
|
||||
_SCHEMA_VERSION = "ai_agent_version_freshness_snapshot_v1"
|
||||
_RUNTIME_AUTHORITY = "repo_only_snapshot_no_external_lookup_or_update"
|
||||
|
||||
|
||||
def load_latest_ai_agent_version_freshness_snapshot(
|
||||
evaluations_dir: Path | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""Load the newest committed AI Agent version freshness snapshot."""
|
||||
directory = evaluations_dir or _DEFAULT_EVALUATIONS_DIR
|
||||
candidates = sorted(directory.glob(_SNAPSHOT_PATTERN))
|
||||
if not candidates:
|
||||
raise FileNotFoundError(
|
||||
f"no AI Agent version freshness 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_source_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}")
|
||||
|
||||
scan_boundaries = payload.get("scan_boundaries") or {}
|
||||
if scan_boundaries.get("read_only_repo_snapshot_allowed") is not True:
|
||||
raise ValueError(f"{label}: read_only_repo_snapshot_allowed must be true")
|
||||
|
||||
blocked_scan_flags = {
|
||||
"schedule_activation_allowed",
|
||||
"workflow_write_allowed",
|
||||
"external_registry_lookup_allowed",
|
||||
"external_cve_lookup_allowed",
|
||||
"package_installation_allowed",
|
||||
"package_upgrade_allowed",
|
||||
"lockfile_write_allowed",
|
||||
"docker_build_allowed",
|
||||
"image_pull_allowed",
|
||||
"host_probe_allowed",
|
||||
"auto_pr_allowed",
|
||||
"auto_merge_allowed",
|
||||
"telegram_direct_send_allowed",
|
||||
"paid_external_service_allowed",
|
||||
"production_route_change_allowed",
|
||||
}
|
||||
enabled_scan_flags = sorted(
|
||||
flag for flag in blocked_scan_flags if scan_boundaries.get(flag) is not False
|
||||
)
|
||||
if enabled_scan_flags:
|
||||
raise ValueError(f"{label}: scan boundaries must remain false: {enabled_scan_flags}")
|
||||
|
||||
approval_boundaries = payload.get("approval_boundaries") or {}
|
||||
blocked_approval_flags = {
|
||||
"daily_schedule_enabled",
|
||||
"external_source_lookup_allowed",
|
||||
"package_or_model_upgrade_allowed",
|
||||
"host_or_k3s_probe_allowed",
|
||||
"telegram_digest_send_allowed",
|
||||
"gitea_pr_creation_allowed",
|
||||
"production_route_change_allowed",
|
||||
}
|
||||
enabled_approval_flags = sorted(
|
||||
flag
|
||||
for flag in blocked_approval_flags
|
||||
if approval_boundaries.get(flag) is not False
|
||||
)
|
||||
if enabled_approval_flags:
|
||||
raise ValueError(
|
||||
f"{label}: approval boundaries must remain false: {enabled_approval_flags}"
|
||||
)
|
||||
|
||||
|
||||
def _require_rollup_consistency(payload: dict[str, Any], label: str) -> None:
|
||||
sources = payload.get("freshness_sources") or []
|
||||
agents = payload.get("agent_roles") or []
|
||||
steps = payload.get("daily_snapshot_design") or []
|
||||
rollups = payload.get("rollups") or {}
|
||||
|
||||
expected_counts = {
|
||||
"source_count": len(sources),
|
||||
"repo_only_source_count": sum(
|
||||
1 for source in sources if source.get("source_type") == "repo_only"
|
||||
),
|
||||
"agent_count": len(agents),
|
||||
"daily_step_count": len(steps),
|
||||
}
|
||||
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}")
|
||||
|
||||
action_required = sorted(
|
||||
source.get("source_id")
|
||||
for source in sources
|
||||
if source.get("status") == "action_required"
|
||||
or source.get("action_required") is True
|
||||
)
|
||||
if sorted(rollups.get("action_required_source_ids") or []) != action_required:
|
||||
raise ValueError(f"{label}: rollups.action_required_source_ids mismatch")
|
||||
|
||||
blocked_external_lookup = sorted(
|
||||
source.get("source_id")
|
||||
for source in sources
|
||||
if source.get("external_lookup_allowed") is False
|
||||
)
|
||||
if sorted(rollups.get("blocked_external_lookup_source_ids") or []) != blocked_external_lookup:
|
||||
raise ValueError(f"{label}: rollups.blocked_external_lookup_source_ids mismatch")
|
||||
|
||||
mutation_allowed_count = sum(
|
||||
1 for source in sources if source.get("mutation_allowed") is True
|
||||
)
|
||||
if rollups.get("mutation_allowed_source_count") != mutation_allowed_count:
|
||||
raise ValueError(f"{label}: rollups.mutation_allowed_source_count mismatch")
|
||||
|
||||
if rollups.get("schedule_enabled_count") != 0:
|
||||
raise ValueError(f"{label}: rollups.schedule_enabled_count must remain 0")
|
||||
if rollups.get("telegram_direct_send_count") != 0:
|
||||
raise ValueError(f"{label}: rollups.telegram_direct_send_count must remain 0")
|
||||
|
||||
|
||||
def _require_source_safety(payload: dict[str, Any], label: str) -> None:
|
||||
unsafe_sources = [
|
||||
source.get("source_id")
|
||||
for source in payload.get("freshness_sources") or []
|
||||
if source.get("source_type") != "repo_only"
|
||||
or source.get("external_lookup_allowed") is not False
|
||||
or source.get("mutation_allowed") is not False
|
||||
or not source.get("evidence_refs")
|
||||
or not source.get("next_action")
|
||||
]
|
||||
if unsafe_sources:
|
||||
raise ValueError(f"{label}: freshness sources must stay repo-only: {unsafe_sources}")
|
||||
|
||||
unsafe_steps = [
|
||||
step.get("step_id")
|
||||
for step in payload.get("daily_snapshot_design") or []
|
||||
if step.get("allowed_now") is not True
|
||||
]
|
||||
if unsafe_steps:
|
||||
raise ValueError(f"{label}: daily snapshot design steps must stay read-only: {unsafe_steps}")
|
||||
@@ -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"] == 30
|
||||
assert data["program_status"]["current_task_id"] == "P2-402A"
|
||||
assert data["program_status"]["next_task_id"] == "P2-402B"
|
||||
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"]["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
|
||||
|
||||
@@ -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"] == 30
|
||||
assert data["program_status"]["current_task_id"] == "P2-402A"
|
||||
assert data["program_status"]["next_task_id"] == "P2-402B"
|
||||
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"]["read_only_mode"] is True
|
||||
assert data["approval_boundaries"]["runtime_version_update_allowed"] is False
|
||||
assert data["approval_boundaries"]["package_upgrade_allowed"] is False
|
||||
|
||||
175
apps/api/tests/test_ai_agent_version_freshness_snapshot.py
Normal file
175
apps/api/tests/test_ai_agent_version_freshness_snapshot.py
Normal file
@@ -0,0 +1,175 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
|
||||
import pytest
|
||||
|
||||
from src.services.ai_agent_version_freshness_snapshot import (
|
||||
load_latest_ai_agent_version_freshness_snapshot,
|
||||
)
|
||||
|
||||
|
||||
def test_load_latest_ai_agent_version_freshness_snapshot_reads_committed_snapshot():
|
||||
data = load_latest_ai_agent_version_freshness_snapshot()
|
||||
|
||||
assert data["schema_version"] == "ai_agent_version_freshness_snapshot_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"]["read_only_mode"] is True
|
||||
assert (
|
||||
data["program_status"]["runtime_authority"]
|
||||
== "repo_only_snapshot_no_external_lookup_or_update"
|
||||
)
|
||||
assert data["scan_boundaries"]["read_only_repo_snapshot_allowed"] is True
|
||||
assert data["scan_boundaries"]["schedule_activation_allowed"] is False
|
||||
assert data["scan_boundaries"]["external_registry_lookup_allowed"] is False
|
||||
assert data["scan_boundaries"]["package_upgrade_allowed"] is False
|
||||
assert data["scan_boundaries"]["lockfile_write_allowed"] is False
|
||||
assert data["scan_boundaries"]["telegram_direct_send_allowed"] is False
|
||||
assert data["approval_boundaries"]["daily_schedule_enabled"] is False
|
||||
assert data["approval_boundaries"]["package_or_model_upgrade_allowed"] is False
|
||||
assert data["rollups"]["source_count"] == len(data["freshness_sources"]) == 12
|
||||
assert data["rollups"]["repo_only_source_count"] == 12
|
||||
assert data["rollups"]["agent_count"] == 3
|
||||
assert data["rollups"]["daily_step_count"] == 5
|
||||
assert data["rollups"]["mutation_allowed_source_count"] == 0
|
||||
assert data["rollups"]["schedule_enabled_count"] == 0
|
||||
assert data["rollups"]["telegram_direct_send_count"] == 0
|
||||
assert "javascript_workspace_manifests" in data["rollups"]["action_required_source_ids"]
|
||||
assert "dockerfiles" in data["rollups"]["action_required_source_ids"]
|
||||
|
||||
|
||||
def test_ai_agent_version_freshness_snapshot_rejects_schedule_activation(tmp_path):
|
||||
snapshot = _snapshot()
|
||||
snapshot["scan_boundaries"]["schedule_activation_allowed"] = True
|
||||
(tmp_path / "ai_agent_version_freshness_snapshot_2026-06-11.json").write_text(
|
||||
json.dumps(snapshot),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError, match="scan boundaries"):
|
||||
load_latest_ai_agent_version_freshness_snapshot(tmp_path)
|
||||
|
||||
|
||||
def test_ai_agent_version_freshness_snapshot_rejects_rollup_mismatch(tmp_path):
|
||||
snapshot = _snapshot()
|
||||
snapshot["rollups"]["source_count"] = 99
|
||||
(tmp_path / "ai_agent_version_freshness_snapshot_2026-06-11.json").write_text(
|
||||
json.dumps(snapshot),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError, match="rollup counts"):
|
||||
load_latest_ai_agent_version_freshness_snapshot(tmp_path)
|
||||
|
||||
|
||||
def test_ai_agent_version_freshness_snapshot_rejects_external_lookup_source(tmp_path):
|
||||
snapshot = _snapshot()
|
||||
snapshot["freshness_sources"][0]["external_lookup_allowed"] = True
|
||||
(tmp_path / "ai_agent_version_freshness_snapshot_2026-06-11.json").write_text(
|
||||
json.dumps(snapshot),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError, match="blocked_external_lookup_source_ids|repo-only"):
|
||||
load_latest_ai_agent_version_freshness_snapshot(tmp_path)
|
||||
|
||||
|
||||
def _snapshot() -> dict:
|
||||
return {
|
||||
"schema_version": "ai_agent_version_freshness_snapshot_v1",
|
||||
"generated_at": "2026-06-11T22:45:00+08:00",
|
||||
"program_status": {
|
||||
"overall_completion_percent": 42,
|
||||
"current_priority": "P2",
|
||||
"current_task_id": "P2-402B",
|
||||
"next_task_id": "P2-402C",
|
||||
"read_only_mode": True,
|
||||
"runtime_authority": "repo_only_snapshot_no_external_lookup_or_update",
|
||||
"status_note": "測試。",
|
||||
},
|
||||
"scan_boundaries": {
|
||||
"read_only_repo_snapshot_allowed": True,
|
||||
"schedule_activation_allowed": False,
|
||||
"workflow_write_allowed": False,
|
||||
"external_registry_lookup_allowed": False,
|
||||
"external_cve_lookup_allowed": False,
|
||||
"package_installation_allowed": False,
|
||||
"package_upgrade_allowed": False,
|
||||
"lockfile_write_allowed": False,
|
||||
"docker_build_allowed": False,
|
||||
"image_pull_allowed": False,
|
||||
"host_probe_allowed": False,
|
||||
"auto_pr_allowed": False,
|
||||
"auto_merge_allowed": False,
|
||||
"telegram_direct_send_allowed": False,
|
||||
"paid_external_service_allowed": False,
|
||||
"production_route_change_allowed": False,
|
||||
},
|
||||
"agent_roles": [
|
||||
{
|
||||
"agent_id": "hermes",
|
||||
"role": "測試。",
|
||||
"autonomy_level": "L1_report_only",
|
||||
"outputs": ["snapshot"],
|
||||
"approval_gate": "read_only",
|
||||
}
|
||||
],
|
||||
"repo_scan_summary": {
|
||||
"javascript_workspace_count": 1,
|
||||
"javascript_direct_dependency_count": 2,
|
||||
"python_manifest_count": 1,
|
||||
"dockerfile_count": 1,
|
||||
"runtime_surface_count": 1,
|
||||
"committed_inventory_refs": ["docs/evaluations/example.json"],
|
||||
"stale_committed_inventory_refs": ["docs/evaluations/example.json"],
|
||||
},
|
||||
"daily_snapshot_design": [
|
||||
{
|
||||
"step_id": "collect",
|
||||
"sequence": 1,
|
||||
"owner_agent": "hermes",
|
||||
"allowed_now": True,
|
||||
"planned_output": "snapshot",
|
||||
"blocked_now": ["upgrade"],
|
||||
}
|
||||
],
|
||||
"freshness_sources": [
|
||||
{
|
||||
"source_id": "javascript_workspace_manifests",
|
||||
"domain": "javascript_packages",
|
||||
"source_type": "repo_only",
|
||||
"owner_agent": "hermes",
|
||||
"status": "action_required",
|
||||
"freshness_basis": "manifest",
|
||||
"current_signal": "test",
|
||||
"external_lookup_allowed": False,
|
||||
"mutation_allowed": False,
|
||||
"action_required": True,
|
||||
"evidence_refs": ["package.json"],
|
||||
"next_action": "review",
|
||||
}
|
||||
],
|
||||
"approval_boundaries": {
|
||||
"daily_schedule_enabled": False,
|
||||
"external_source_lookup_allowed": False,
|
||||
"package_or_model_upgrade_allowed": False,
|
||||
"host_or_k3s_probe_allowed": False,
|
||||
"telegram_digest_send_allowed": False,
|
||||
"gitea_pr_creation_allowed": False,
|
||||
"production_route_change_allowed": False,
|
||||
},
|
||||
"rollups": {
|
||||
"source_count": 1,
|
||||
"repo_only_source_count": 1,
|
||||
"agent_count": 1,
|
||||
"daily_step_count": 1,
|
||||
"action_required_source_ids": ["javascript_workspace_manifests"],
|
||||
"blocked_external_lookup_source_ids": ["javascript_workspace_manifests"],
|
||||
"mutation_allowed_source_count": 0,
|
||||
"schedule_enabled_count": 0,
|
||||
"telegram_direct_send_count": 0,
|
||||
"next_approval_task_ids": ["P2-402C"],
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from src.api.v1.agents import router
|
||||
|
||||
|
||||
def test_ai_agent_version_freshness_snapshot_endpoint_returns_committed_snapshot():
|
||||
app = FastAPI()
|
||||
app.include_router(router, prefix="/api/v1")
|
||||
client = TestClient(app)
|
||||
|
||||
response = client.get("/api/v1/agents/agent-version-freshness-snapshot")
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["schema_version"] == "ai_agent_version_freshness_snapshot_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"]["read_only_mode"] is True
|
||||
assert data["scan_boundaries"]["schedule_activation_allowed"] is False
|
||||
assert data["scan_boundaries"]["external_registry_lookup_allowed"] is False
|
||||
assert data["scan_boundaries"]["package_upgrade_allowed"] is False
|
||||
assert data["scan_boundaries"]["telegram_direct_send_allowed"] is False
|
||||
assert data["approval_boundaries"]["daily_schedule_enabled"] is False
|
||||
assert data["rollups"]["source_count"] == 12
|
||||
assert data["rollups"]["repo_only_source_count"] == 12
|
||||
assert data["rollups"]["mutation_allowed_source_count"] == 0
|
||||
assert data["rollups"]["schedule_enabled_count"] == 0
|
||||
assert any(
|
||||
source["source_id"] == "agent_model_governance_snapshots"
|
||||
for source in data["freshness_sources"]
|
||||
)
|
||||
@@ -297,6 +297,24 @@
|
||||
- Nginx reload / restart、DNS 修改、TLS renew、ArgoCD sync、kubectl、SSH 主機修改、workflow 修改、runner 啟用、secret rotation、active scan、agent-bounty runtime、payout / withdrawal、deploy 或 runtime execution:本階段全部未執行。
|
||||
- IwoooS 整體仍維持 `64%`;active runtime gate 仍為 `0`;owner response received / accepted 仍為 `0 / false`。
|
||||
|
||||
## 2026-06-11|P2-402B Repo-only 版本新鮮度快照
|
||||
|
||||
**背景**:統帥批准繼續推進 AI Agent 主動更新版本情報與可委派營運工作。本波承接 P2-402A,不直接啟用 schedule、不查外部 registry、不升級套件或模型、不 probe 主機、不發 Telegram,而是先建立 repo-only daily version freshness snapshot 的正式資料面與 API。
|
||||
|
||||
**完成內容:**
|
||||
- 新增 `docs/schemas/ai_agent_version_freshness_snapshot_v1.schema.json`,定義 repo-only 版本新鮮度快照、3 Agent 角色、daily snapshot design、freshness sources、approval boundaries 與 rollups。
|
||||
- 新增 `docs/evaluations/ai_agent_version_freshness_snapshot_2026-06-11.json`,覆蓋 12 類 repo-only source:JavaScript、Python、pnpm lockfile、Dockerfile、K8s、Gitea workflow、observability、Ansible host manifest、committed evaluation snapshots、Agent/model governance、backup/DR、public web/admin surfaces。
|
||||
- 新增 `apps/api/src/services/ai_agent_version_freshness_snapshot.py`,只讀載入最新 committed snapshot,並強制 `schedule_activation_allowed`、`external_registry_lookup_allowed`、`package_upgrade_allowed`、`lockfile_write_allowed`、`docker_build_allowed`、`image_pull_allowed`、`host_probe_allowed`、`telegram_direct_send_allowed` 等維持 false。
|
||||
- 新增 `GET /api/v1/agents/agent-version-freshness-snapshot`,只回傳 committed snapshot;不觸發掃描、不查外部、不改 repo、不發 Telegram。
|
||||
- 更新 `docs/evaluations/ai_agent_proactive_operations_contract_2026-06-11.json`:整體 AI Agent 主動營運與版本生命週期完成度調整為 `42%`,current task `P2-402B`,next task `P2-402C`。
|
||||
- 更新 MASTER §3.2.1c / §5、`docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md` 與 `docs/ai/AI_AGENT_PROACTIVE_OPERATIONS_2026-06-11.md`。
|
||||
- 新增 `apps/api/tests/test_ai_agent_version_freshness_snapshot.py` 與 `apps/api/tests/test_ai_agent_version_freshness_snapshot_api.py`。
|
||||
|
||||
**完成度與下一步:**
|
||||
- P2-402B repo-only 版本新鮮度快照:`100%`。
|
||||
- 整體 AI Agent 主動營運與版本生命週期:`42%`。
|
||||
- 下一步:`P2-402C` Renovate / OSV / Trivy / Syft / Grype 工具採用批准包;仍不得直接安裝工具、改 CI、查外部、升級套件、建立 PR 或送 Telegram。
|
||||
|
||||
## 2026-06-11|OpenClaw / Hermes / NemoTron 佈建布局第一波
|
||||
|
||||
**背景**:統帥要求將 OpenClaw、Hermes、NemoTron 依各自專長安排到所有主機、套件、工具、服務、專案、網站前後台,並納入主動學習、互相溝通、持續成長與 Telegram Bot 告警鏈路。本波先建立可驗證的只讀佈建布局,避免把尚未批准的 runtime deploy、SDK/API、Telegram 發送或主機操作誤當已授權。
|
||||
|
||||
@@ -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 主動營運委派與版本生命週期 | 30% | P2-402A 已完成只讀 contract;定期排程、外部版本查詢、套件升級、主機更新、container pull、auto merge、Telegram 實發仍未開 gate | `ai_agent_proactive_operations_contract_v1` schema、`ai_agent_proactive_operations_contract_2026-06-11.json`、`GET /api/v1/agents/agent-proactive-operations-contract`、MASTER §3.2.1c |
|
||||
| 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 |
|
||||
| 本工作清單與分析報告 | 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 主動營運委派與版本生命週期目前完成度:**30%**。已完成 12 類版本 domain、24 類可委派能力、5 種 cadence、8 類 MCP、4 類 RAG memory 與只讀 API;下一步是 `P2-402B` repo-only daily version freshness snapshot,外部 registry / package source / host probe / Telegram 實發仍需 gate。
|
||||
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。
|
||||
|
||||
完成度計算模型:
|
||||
|
||||
@@ -952,7 +952,7 @@ UI:
|
||||
| P2-401D | 待辦 | 0 | Hermes | RAG Hot / Warm / Cold memory ingestion、dedupe、freshness、redaction policy | RAG 記憶治理提案 | schema migration + owner review |
|
||||
| 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 | 待辦 | 0 | Hermes | 建立 repo-only daily version freshness snapshot | manifest / lockfile / Dockerfile / K8s YAML / snapshot freshness | workflow schedule approval |
|
||||
| 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-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 |
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
# AI Agent 主動營運委派與版本生命週期分析報告
|
||||
|
||||
> 日期:2026-06-11(台北時間)
|
||||
> 文件定位:P2-402A 只讀契約摘要。權威細節以 MASTER §3.2.1c 與 `ai_agent_proactive_operations_contract_v1` 為準。
|
||||
> 文件定位:P2-402A / P2-402B 只讀契約摘要。權威細節以 MASTER §3.2.1c、`ai_agent_proactive_operations_contract_v1` 與 `ai_agent_version_freshness_snapshot_v1` 為準。
|
||||
|
||||
## 1. 本波完成度
|
||||
|
||||
| 範圍 | 完成度 | 狀態 |
|
||||
|---|---:|---|
|
||||
| 主動營運委派契約 | 100% | 已完成 schema / snapshot / API / 測試 |
|
||||
| 整體主動營運與版本生命週期 | 30% | 已完成架構與邊界;runtime 排程與更新尚未開 gate |
|
||||
| Repo-only 版本新鮮度快照 | 100% | P2-402B 已完成 schema / committed snapshot / API / 測試 |
|
||||
| 整體主動營運與版本生命週期 | 42% | 已完成架構、邊界與 repo-only freshness;runtime 排程與更新尚未開 gate |
|
||||
|
||||
## 2. 可交給 AI Agent 的工作分類
|
||||
|
||||
@@ -30,19 +31,35 @@
|
||||
| `docs/schemas/ai_agent_proactive_operations_contract_v1.schema.json` | 主動營運委派與版本生命週期 schema |
|
||||
| `docs/evaluations/ai_agent_proactive_operations_contract_2026-06-11.json` | 12 類版本 domain、24 類可委派能力、5 種 cadence、8 類 MCP、4 類 RAG memory |
|
||||
| `GET /api/v1/agents/agent-proactive-operations-contract` | 只讀 API;不啟用排程、不升級、不發 Telegram |
|
||||
| `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 |
|
||||
|
||||
## 4. 下一步優先順序
|
||||
## 4. P2-402B Repo-only 版本新鮮度快照
|
||||
|
||||
| Source | 主責 | 狀態 | 下一步 |
|
||||
|---|---|---|---|
|
||||
| JavaScript workspace manifests | Hermes | action_required | P2-402C 前只比較 repo specifier / lockfile,不查 npm registry |
|
||||
| Python package manifests | Hermes | action_required | 只讀比較 pyproject / requirements,不 pip / uv install |
|
||||
| Dockerfiles | Hermes | action_required | P2-402C 評估 Trivy / Syft / Grype / Docker Scout 採用,不 build / pull |
|
||||
| Committed evaluation snapshots | Hermes | action_required | 將 2026-06-04~06-05 舊基線列入 stale refs,不假裝是外部最新 |
|
||||
| Agent / model governance snapshots | NemoTron | action_required | 只做離線 freshness note,不進 shadow / canary / production route |
|
||||
| K8s / Gitea / observability / Ansible / backup / web surfaces | OpenClaw + Hermes | baseline_ready / planned_next | 分別等待 P2-402D / P2-402F / P2-402G gate |
|
||||
|
||||
本波只把「每天要看哪些 repo 內版本來源」定義成可驗證資料面。每日排程、外部 registry 查詢、主機/K3s live probe、Telegram digest 與 Gitea PR lane 都仍是下一階段 gate。
|
||||
|
||||
## 5. 下一步優先順序
|
||||
|
||||
| ID | 優先 | 任務 | 關卡 |
|
||||
|---|---|---|---|
|
||||
| P2-402B | 1 | repo-only daily version freshness snapshot | workflow schedule approval |
|
||||
| P2-402C | 2 | Renovate / OSV / Trivy / Syft / Grype 採用批准包 | tool install / CI approval |
|
||||
| P2-402D | 3 | Telegram action-required digest policy | Telegram Gateway E2E |
|
||||
| P2-402E | 4 | Gitea PR 草案 lane | bot / branch policy approval |
|
||||
| P2-402F | 5 | host OS / K3s / stateful services 版本只讀盤點 | host probe / maintenance approval |
|
||||
| P2-402G | 6 | governance UI 顯示可委派能力 | frontend UI approval |
|
||||
| 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 |
|
||||
|
||||
## 5. 仍維持 false 的安全邊界
|
||||
## 6. 仍維持 false 的安全邊界
|
||||
|
||||
- `runtime_version_update_allowed=false`
|
||||
- `package_upgrade_allowed=false`
|
||||
@@ -54,3 +71,6 @@
|
||||
- `secret_plaintext_allowed=false`
|
||||
- `paid_external_service_allowed=false`
|
||||
- `production_route_change_allowed=false`
|
||||
- `external_registry_lookup_allowed=false`
|
||||
- `daily_schedule_enabled=false`
|
||||
- `gitea_pr_creation_allowed=false`
|
||||
|
||||
@@ -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": 30,
|
||||
"overall_completion_percent": 42,
|
||||
"current_priority": "P2",
|
||||
"current_task_id": "P2-402A",
|
||||
"next_task_id": "P2-402B",
|
||||
"current_task_id": "P2-402B",
|
||||
"next_task_id": "P2-402C",
|
||||
"read_only_mode": true,
|
||||
"runtime_authority": "contract_only_no_version_or_runtime_update",
|
||||
"status_note": "本快照定義 AI Agent 可主動處理的營運工作與版本生命週期;本波不啟用排程、不升級套件、不更新主機、不 pull image、不 auto merge、不發 Telegram。"
|
||||
"status_note": "P2-402B 已建立 repo-only 版本新鮮度快照與只讀 API;本波仍不啟用排程、不升級套件、不更新主機、不 pull image、不 auto merge、不發 Telegram。"
|
||||
},
|
||||
"external_source_evidence": [
|
||||
{
|
||||
@@ -612,15 +612,15 @@
|
||||
"summary": "定義 AI Agent 主動營運委派與版本生命週期契約、schema、snapshot、只讀 API 與文件同步。",
|
||||
"next_gate": "正式部署驗證"
|
||||
},
|
||||
{
|
||||
"task_id": "P2-402B",
|
||||
"priority": "P2",
|
||||
"status": "planned",
|
||||
"completion_percent": 0,
|
||||
"owner_agent": "Hermes",
|
||||
"summary": "建立 repo-only daily version freshness snapshot,不查外部 registry、不改 workflow。",
|
||||
"next_gate": "workflow_schedule_approval_required"
|
||||
},
|
||||
{
|
||||
"task_id": "P2-402B",
|
||||
"priority": "P2",
|
||||
"status": "done",
|
||||
"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"
|
||||
},
|
||||
{
|
||||
"task_id": "P2-402C",
|
||||
"priority": "P2",
|
||||
|
||||
@@ -0,0 +1,427 @@
|
||||
{
|
||||
"schema_version": "ai_agent_version_freshness_snapshot_v1",
|
||||
"generated_at": "2026-06-11T22:45:00+08:00",
|
||||
"program_status": {
|
||||
"overall_completion_percent": 42,
|
||||
"current_priority": "P2",
|
||||
"current_task_id": "P2-402B",
|
||||
"next_task_id": "P2-402C",
|
||||
"read_only_mode": true,
|
||||
"runtime_authority": "repo_only_snapshot_no_external_lookup_or_update",
|
||||
"status_note": "P2-402B 建立 repo-only 版本新鮮度快照格式與 API;本波不啟用每日排程、不查外部 registry、不升級套件/模型、不 pull image、不建立 PR、不發 Telegram。"
|
||||
},
|
||||
"scan_boundaries": {
|
||||
"read_only_repo_snapshot_allowed": true,
|
||||
"schedule_activation_allowed": false,
|
||||
"workflow_write_allowed": false,
|
||||
"external_registry_lookup_allowed": false,
|
||||
"external_cve_lookup_allowed": false,
|
||||
"package_installation_allowed": false,
|
||||
"package_upgrade_allowed": false,
|
||||
"lockfile_write_allowed": false,
|
||||
"docker_build_allowed": false,
|
||||
"image_pull_allowed": false,
|
||||
"host_probe_allowed": false,
|
||||
"auto_pr_allowed": false,
|
||||
"auto_merge_allowed": false,
|
||||
"telegram_direct_send_allowed": false,
|
||||
"paid_external_service_allowed": false,
|
||||
"production_route_change_allowed": false
|
||||
},
|
||||
"agent_roles": [
|
||||
{
|
||||
"agent_id": "hermes",
|
||||
"role": "讀取 repo 內 manifest / lockfile / Dockerfile / K8s / workflow / committed snapshot,產生 version freshness evidence packet。",
|
||||
"autonomy_level": "L1_report_only",
|
||||
"outputs": [
|
||||
"repo-only version freshness snapshot",
|
||||
"stale source list",
|
||||
"next approval package inputs"
|
||||
],
|
||||
"approval_gate": "read_only_repo_snapshot_allowed"
|
||||
},
|
||||
{
|
||||
"agent_id": "openclaw",
|
||||
"role": "仲裁 stale / action_required 訊號,判斷是否進入 P2-402C 工具採用批准包或 P2-402D Telegram digest policy。",
|
||||
"autonomy_level": "L2_approval_package_only",
|
||||
"outputs": [
|
||||
"risk note",
|
||||
"approval boundary check",
|
||||
"human review packet"
|
||||
],
|
||||
"approval_gate": "human_review_required_before_any_update"
|
||||
},
|
||||
{
|
||||
"agent_id": "nemotron",
|
||||
"role": "離線檢查 Agent / model / replay / prompt governance 快照是否過期,協助建立模型評測 replay 清單。",
|
||||
"autonomy_level": "L1_report_only",
|
||||
"outputs": [
|
||||
"offline model freshness note",
|
||||
"replay candidate list"
|
||||
],
|
||||
"approval_gate": "offline_replay_only_until_shadow_gate"
|
||||
}
|
||||
],
|
||||
"repo_scan_summary": {
|
||||
"javascript_workspace_count": 6,
|
||||
"javascript_direct_dependency_count": 51,
|
||||
"python_manifest_count": 6,
|
||||
"dockerfile_count": 2,
|
||||
"runtime_surface_count": 22,
|
||||
"committed_inventory_refs": [
|
||||
"docs/evaluations/javascript_package_inventory_2026-06-04.json",
|
||||
"docs/evaluations/package_supply_chain_inventory_2026-06-04.json",
|
||||
"docs/evaluations/dependency_drift_check_plan_2026-06-04.json",
|
||||
"docs/evaluations/docker_build_surface_inventory_2026-06-04.json",
|
||||
"docs/evaluations/runtime_surface_inventory_2026-06-05.json",
|
||||
"docs/evaluations/ai_agent_proactive_operations_contract_2026-06-11.json"
|
||||
],
|
||||
"stale_committed_inventory_refs": [
|
||||
"docs/evaluations/javascript_package_inventory_2026-06-04.json",
|
||||
"docs/evaluations/package_supply_chain_inventory_2026-06-04.json",
|
||||
"docs/evaluations/dependency_drift_check_plan_2026-06-04.json",
|
||||
"docs/evaluations/docker_build_surface_inventory_2026-06-04.json",
|
||||
"docs/evaluations/runtime_surface_inventory_2026-06-05.json"
|
||||
]
|
||||
},
|
||||
"daily_snapshot_design": [
|
||||
{
|
||||
"step_id": "collect_repo_version_sources",
|
||||
"sequence": 1,
|
||||
"owner_agent": "hermes",
|
||||
"allowed_now": true,
|
||||
"planned_output": "freshness_sources[] with evidence_refs and repo-only current_signal",
|
||||
"blocked_now": [
|
||||
"external registry lookup",
|
||||
"host probe",
|
||||
"package install",
|
||||
"lockfile write"
|
||||
]
|
||||
},
|
||||
{
|
||||
"step_id": "compare_committed_inventory_age",
|
||||
"sequence": 2,
|
||||
"owner_agent": "hermes",
|
||||
"allowed_now": true,
|
||||
"planned_output": "stale_committed_inventory_refs and action_required source ids",
|
||||
"blocked_now": [
|
||||
"rewrite historical snapshots",
|
||||
"claim latest upstream version",
|
||||
"query package registries"
|
||||
]
|
||||
},
|
||||
{
|
||||
"step_id": "openclaw_boundary_review",
|
||||
"sequence": 3,
|
||||
"owner_agent": "openclaw",
|
||||
"allowed_now": true,
|
||||
"planned_output": "approval boundary decision for P2-402C / P2-402D / P2-402F",
|
||||
"blocked_now": [
|
||||
"approve own changes",
|
||||
"enable auto merge",
|
||||
"change production route"
|
||||
]
|
||||
},
|
||||
{
|
||||
"step_id": "nemotron_offline_agent_model_review",
|
||||
"sequence": 4,
|
||||
"owner_agent": "nemotron",
|
||||
"allowed_now": true,
|
||||
"planned_output": "offline model / agent snapshot freshness note",
|
||||
"blocked_now": [
|
||||
"shadow traffic",
|
||||
"canary traffic",
|
||||
"production provider routing"
|
||||
]
|
||||
},
|
||||
{
|
||||
"step_id": "emit_action_required_digest_draft",
|
||||
"sequence": 5,
|
||||
"owner_agent": "hermes",
|
||||
"allowed_now": true,
|
||||
"planned_output": "AwoooP / Telegram digest draft only; no send",
|
||||
"blocked_now": [
|
||||
"Telegram direct send",
|
||||
"Alertmanager route change",
|
||||
"workflow schedule activation"
|
||||
]
|
||||
}
|
||||
],
|
||||
"freshness_sources": [
|
||||
{
|
||||
"source_id": "javascript_workspace_manifests",
|
||||
"domain": "javascript_packages",
|
||||
"source_type": "repo_only",
|
||||
"owner_agent": "hermes",
|
||||
"status": "action_required",
|
||||
"freshness_basis": "package.json workspace manifests + previous javascript_package_inventory snapshot",
|
||||
"current_signal": "6 workspaces / 51 direct dependencies; prior inventory is 2026-06-04 and should be refreshed by repo-only scanner before any registry comparison.",
|
||||
"external_lookup_allowed": false,
|
||||
"mutation_allowed": false,
|
||||
"action_required": true,
|
||||
"evidence_refs": [
|
||||
"package.json",
|
||||
"apps/web/package.json",
|
||||
"packages/shared-types/package.json",
|
||||
"packages/lewooogo-core/package.json",
|
||||
"packages/eslint-config/package.json",
|
||||
"packages/tsconfig/package.json",
|
||||
"pnpm-lock.yaml",
|
||||
"docs/evaluations/javascript_package_inventory_2026-06-04.json"
|
||||
],
|
||||
"next_action": "P2-402C 前先建立 registry/tool 採用批准包;未批准前只能比較 repo 內 specifier 與 lockfile。"
|
||||
},
|
||||
{
|
||||
"source_id": "python_package_manifests",
|
||||
"domain": "python_packages",
|
||||
"source_type": "repo_only",
|
||||
"owner_agent": "hermes",
|
||||
"status": "action_required",
|
||||
"freshness_basis": "pyproject.toml / requirements.txt manifests + package_supply_chain_inventory snapshot",
|
||||
"current_signal": "6 Python manifest surfaces;apps/api pyproject and requirements are high-impact and still require read-only drift refresh.",
|
||||
"external_lookup_allowed": false,
|
||||
"mutation_allowed": false,
|
||||
"action_required": true,
|
||||
"evidence_refs": [
|
||||
"apps/api/pyproject.toml",
|
||||
"apps/api/requirements.txt",
|
||||
"apps/sensor/requirements.txt",
|
||||
"packages/lewooogo-brain/pyproject.toml",
|
||||
"packages/lewooogo-data/pyproject.toml",
|
||||
"scripts/aider_watch_client/pyproject.toml",
|
||||
"docs/evaluations/package_supply_chain_inventory_2026-06-04.json"
|
||||
],
|
||||
"next_action": "只讀比較 dependency specifiers;不得 pip/uv install,不得重寫 requirements。"
|
||||
},
|
||||
{
|
||||
"source_id": "pnpm_lockfile",
|
||||
"domain": "javascript_lockfile",
|
||||
"source_type": "repo_only",
|
||||
"owner_agent": "hermes",
|
||||
"status": "baseline_ready",
|
||||
"freshness_basis": "pnpm-lock.yaml importer consistency",
|
||||
"current_signal": "P1-202 snapshot reported 0 manifest/lock mismatch; P2-402B keeps this as repo-only baseline, not upstream latest evidence.",
|
||||
"external_lookup_allowed": false,
|
||||
"mutation_allowed": false,
|
||||
"action_required": false,
|
||||
"evidence_refs": [
|
||||
"pnpm-lock.yaml",
|
||||
"docs/evaluations/javascript_package_inventory_2026-06-04.json"
|
||||
],
|
||||
"next_action": "Future daily run may fail only on repo mismatch; remediation still requires approval package."
|
||||
},
|
||||
{
|
||||
"source_id": "dockerfiles",
|
||||
"domain": "container_images",
|
||||
"source_type": "repo_only",
|
||||
"owner_agent": "hermes",
|
||||
"status": "action_required",
|
||||
"freshness_basis": "Dockerfile FROM / COPY --from / build-time fetch surfaces",
|
||||
"current_signal": "2 Dockerfiles; prior inventory shows 0 digest-pinned image refs and 2 action_required surfaces.",
|
||||
"external_lookup_allowed": false,
|
||||
"mutation_allowed": false,
|
||||
"action_required": true,
|
||||
"evidence_refs": [
|
||||
"apps/api/Dockerfile",
|
||||
"apps/web/Dockerfile",
|
||||
"docs/evaluations/docker_build_surface_inventory_2026-06-04.json"
|
||||
],
|
||||
"next_action": "P2-402C 工具批准包需評估 Trivy / Syft / Grype / Docker Scout;本波不 build、不 pull、不查 registry。"
|
||||
},
|
||||
{
|
||||
"source_id": "k8s_prod_manifests",
|
||||
"domain": "kubernetes_k3s_components",
|
||||
"source_type": "repo_only",
|
||||
"owner_agent": "openclaw",
|
||||
"status": "baseline_ready",
|
||||
"freshness_basis": "committed k8s/awoooi-prod manifests and runtime_surface_inventory",
|
||||
"current_signal": "22 runtime surfaces mapped; live K3s / version skew remains outside P2-402B and requires P2-402F gate.",
|
||||
"external_lookup_allowed": false,
|
||||
"mutation_allowed": false,
|
||||
"action_required": false,
|
||||
"evidence_refs": [
|
||||
"k8s/awoooi-prod/kustomization.yaml",
|
||||
"k8s/awoooi-prod/06-deployment-api.yaml",
|
||||
"k8s/awoooi-prod/05-deployment-web.yaml",
|
||||
"k8s/awoooi-prod/08-deployment-worker.yaml",
|
||||
"docs/evaluations/runtime_surface_inventory_2026-06-05.json"
|
||||
],
|
||||
"next_action": "P2-402F 才能建立 host/K3s/stateful 只讀版本盤點;本波不 kubectl、不 host probe。"
|
||||
},
|
||||
{
|
||||
"source_id": "gitea_workflows",
|
||||
"domain": "ci_cd_and_runner_tools",
|
||||
"source_type": "repo_only",
|
||||
"owner_agent": "hermes",
|
||||
"status": "baseline_ready",
|
||||
"freshness_basis": ".gitea/workflows committed YAML",
|
||||
"current_signal": "可讀取 workflow schedule / runner / image refs;P2-402B 不新增或修改 schedule。",
|
||||
"external_lookup_allowed": false,
|
||||
"mutation_allowed": false,
|
||||
"action_required": false,
|
||||
"evidence_refs": [
|
||||
".gitea/workflows/cd.yaml",
|
||||
".gitea/workflows/agent-market-watch.yaml",
|
||||
".gitea/workflows/e2e-health.yaml"
|
||||
],
|
||||
"next_action": "若要啟用 daily freshness schedule,需 P2-402D notification policy 與 workflow approval。"
|
||||
},
|
||||
{
|
||||
"source_id": "observability_manifests",
|
||||
"domain": "observability_stack",
|
||||
"source_type": "repo_only",
|
||||
"owner_agent": "openclaw",
|
||||
"status": "baseline_ready",
|
||||
"freshness_basis": "Prometheus / Alertmanager / SigNoz committed configs",
|
||||
"current_signal": "只讀檢查 alert and scrape config refs;不改 Alertmanager route,不發通知。",
|
||||
"external_lookup_allowed": false,
|
||||
"mutation_allowed": false,
|
||||
"action_required": false,
|
||||
"evidence_refs": [
|
||||
"k8s/monitoring/prometheus.yml",
|
||||
"ops/alertmanager/alertmanager.yml",
|
||||
"ops/signoz/otel-collector-config-phase-o.yaml"
|
||||
],
|
||||
"next_action": "P2-402D 定義 failure-only digest 後,才能接 Telegram/AwoooP 通知。"
|
||||
},
|
||||
{
|
||||
"source_id": "ansible_host_manifests",
|
||||
"domain": "host_os_packages",
|
||||
"source_type": "repo_only",
|
||||
"owner_agent": "openclaw",
|
||||
"status": "planned_next",
|
||||
"freshness_basis": "infra/ansible inventory and playbooks",
|
||||
"current_signal": "Repo contains host roles and playbooks, but live package/kernel/K3s versions require P2-402F host readonly probe approval.",
|
||||
"external_lookup_allowed": false,
|
||||
"mutation_allowed": false,
|
||||
"action_required": false,
|
||||
"evidence_refs": [
|
||||
"infra/ansible/inventory/hosts.yml",
|
||||
"infra/ansible/playbooks/site.yml",
|
||||
"infra/ansible/roles/runner-guardrails/tasks/main.yml"
|
||||
],
|
||||
"next_action": "P2-402F 建立 host OS / K3s / stateful version inventory;未批准前不得 SSH probe、apt upgrade、restart 或 reboot。"
|
||||
},
|
||||
{
|
||||
"source_id": "committed_evaluation_snapshots",
|
||||
"domain": "governance_snapshots",
|
||||
"source_type": "repo_only",
|
||||
"owner_agent": "hermes",
|
||||
"status": "action_required",
|
||||
"freshness_basis": "docs/evaluations committed JSON snapshots",
|
||||
"current_signal": "Core package / Docker / drift / runtime snapshots are 2026-06-04~2026-06-05 baselines; P2-402B establishes the 2026-06-11 freshness envelope.",
|
||||
"external_lookup_allowed": false,
|
||||
"mutation_allowed": false,
|
||||
"action_required": true,
|
||||
"evidence_refs": [
|
||||
"docs/evaluations/javascript_package_inventory_2026-06-04.json",
|
||||
"docs/evaluations/package_supply_chain_inventory_2026-06-04.json",
|
||||
"docs/evaluations/dependency_drift_check_plan_2026-06-04.json",
|
||||
"docs/evaluations/docker_build_surface_inventory_2026-06-04.json",
|
||||
"docs/evaluations/runtime_surface_inventory_2026-06-05.json"
|
||||
],
|
||||
"next_action": "每日快照正式啟用前,先由 committed API 顯示 stale refs;不得假裝已查到外部最新版本。"
|
||||
},
|
||||
{
|
||||
"source_id": "agent_model_governance_snapshots",
|
||||
"domain": "ai_agents_models",
|
||||
"source_type": "repo_only",
|
||||
"owner_agent": "nemotron",
|
||||
"status": "action_required",
|
||||
"freshness_basis": "agent-market / NemoTron / OpenClaw committed governance evidence",
|
||||
"current_signal": "Agent market and Nemotron replay sources remain gate-bound; repo-only snapshot may only flag stale committed evidence.",
|
||||
"external_lookup_allowed": false,
|
||||
"mutation_allowed": false,
|
||||
"action_required": true,
|
||||
"evidence_refs": [
|
||||
"docs/evaluations/ai_agent_proactive_operations_contract_2026-06-11.json",
|
||||
"docs/ai/AI_AGENT_PROACTIVE_OPERATIONS_2026-06-11.md",
|
||||
"docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md"
|
||||
],
|
||||
"next_action": "P2-402C/P2-402D 之前不得新增 SDK、shadow/canary、production route 或付費 market source。"
|
||||
},
|
||||
{
|
||||
"source_id": "backup_dr_tooling_refs",
|
||||
"domain": "backup_dr_tooling",
|
||||
"source_type": "repo_only",
|
||||
"owner_agent": "openclaw",
|
||||
"status": "planned_next",
|
||||
"freshness_basis": "backup scripts / DR runbooks / readiness snapshots",
|
||||
"current_signal": "Repo-only source can track script refs, but live backup outcome remains separate and must use current production evidence.",
|
||||
"external_lookup_allowed": false,
|
||||
"mutation_allowed": false,
|
||||
"action_required": false,
|
||||
"evidence_refs": [
|
||||
"scripts/backup/backup-gitea.sh",
|
||||
"docs/runbooks/BACKUP-STATUS.md",
|
||||
"docs/runbooks/FULL-STACK-COLD-START-SOP.md"
|
||||
],
|
||||
"next_action": "Keep backup/DR live truth separate; no automatic restore, prune, or backup mutation from version freshness snapshot."
|
||||
},
|
||||
{
|
||||
"source_id": "public_web_admin_surfaces",
|
||||
"domain": "public_web_admin_surfaces",
|
||||
"source_type": "repo_only",
|
||||
"owner_agent": "hermes",
|
||||
"status": "baseline_ready",
|
||||
"freshness_basis": "apps/web routes, i18n messages, and API client refs",
|
||||
"current_signal": "Can detect whether governance UI knows the latest committed API; no browser automation or UI deploy change is implied.",
|
||||
"external_lookup_allowed": false,
|
||||
"mutation_allowed": false,
|
||||
"action_required": false,
|
||||
"evidence_refs": [
|
||||
"apps/web/src/lib/api-client.ts",
|
||||
"apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx",
|
||||
"apps/web/messages/zh-TW.json",
|
||||
"apps/web/messages/en.json"
|
||||
],
|
||||
"next_action": "P2-402G 才接 UI 顯示;本波只提供 API,不改前端頁面。"
|
||||
}
|
||||
],
|
||||
"approval_boundaries": {
|
||||
"daily_schedule_enabled": false,
|
||||
"external_source_lookup_allowed": false,
|
||||
"package_or_model_upgrade_allowed": false,
|
||||
"host_or_k3s_probe_allowed": false,
|
||||
"telegram_digest_send_allowed": false,
|
||||
"gitea_pr_creation_allowed": false,
|
||||
"production_route_change_allowed": false
|
||||
},
|
||||
"rollups": {
|
||||
"source_count": 12,
|
||||
"repo_only_source_count": 12,
|
||||
"agent_count": 3,
|
||||
"daily_step_count": 5,
|
||||
"action_required_source_ids": [
|
||||
"javascript_workspace_manifests",
|
||||
"python_package_manifests",
|
||||
"dockerfiles",
|
||||
"committed_evaluation_snapshots",
|
||||
"agent_model_governance_snapshots"
|
||||
],
|
||||
"blocked_external_lookup_source_ids": [
|
||||
"javascript_workspace_manifests",
|
||||
"python_package_manifests",
|
||||
"pnpm_lockfile",
|
||||
"dockerfiles",
|
||||
"k8s_prod_manifests",
|
||||
"gitea_workflows",
|
||||
"observability_manifests",
|
||||
"ansible_host_manifests",
|
||||
"committed_evaluation_snapshots",
|
||||
"agent_model_governance_snapshots",
|
||||
"backup_dr_tooling_refs",
|
||||
"public_web_admin_surfaces"
|
||||
],
|
||||
"mutation_allowed_source_count": 0,
|
||||
"schedule_enabled_count": 0,
|
||||
"telegram_direct_send_count": 0,
|
||||
"next_approval_task_ids": [
|
||||
"P2-402C",
|
||||
"P2-402D",
|
||||
"P2-402E",
|
||||
"P2-402F",
|
||||
"P2-402G"
|
||||
]
|
||||
}
|
||||
}
|
||||
424
docs/schemas/ai_agent_version_freshness_snapshot_v1.schema.json
Normal file
424
docs/schemas/ai_agent_version_freshness_snapshot_v1.schema.json
Normal file
@@ -0,0 +1,424 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://awoooi.wooo.work/schemas/ai_agent_version_freshness_snapshot_v1.schema.json",
|
||||
"title": "AI Agent Version Freshness Snapshot v1",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"schema_version",
|
||||
"generated_at",
|
||||
"program_status",
|
||||
"scan_boundaries",
|
||||
"agent_roles",
|
||||
"repo_scan_summary",
|
||||
"daily_snapshot_design",
|
||||
"freshness_sources",
|
||||
"approval_boundaries",
|
||||
"rollups"
|
||||
],
|
||||
"properties": {
|
||||
"schema_version": {
|
||||
"const": "ai_agent_version_freshness_snapshot_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": "repo_only_snapshot_no_external_lookup_or_update"
|
||||
},
|
||||
"status_note": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scan_boundaries": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"read_only_repo_snapshot_allowed",
|
||||
"schedule_activation_allowed",
|
||||
"workflow_write_allowed",
|
||||
"external_registry_lookup_allowed",
|
||||
"external_cve_lookup_allowed",
|
||||
"package_installation_allowed",
|
||||
"package_upgrade_allowed",
|
||||
"lockfile_write_allowed",
|
||||
"docker_build_allowed",
|
||||
"image_pull_allowed",
|
||||
"host_probe_allowed",
|
||||
"auto_pr_allowed",
|
||||
"auto_merge_allowed",
|
||||
"telegram_direct_send_allowed",
|
||||
"paid_external_service_allowed",
|
||||
"production_route_change_allowed"
|
||||
],
|
||||
"properties": {
|
||||
"read_only_repo_snapshot_allowed": {
|
||||
"const": true
|
||||
},
|
||||
"schedule_activation_allowed": {
|
||||
"const": false
|
||||
},
|
||||
"workflow_write_allowed": {
|
||||
"const": false
|
||||
},
|
||||
"external_registry_lookup_allowed": {
|
||||
"const": false
|
||||
},
|
||||
"external_cve_lookup_allowed": {
|
||||
"const": false
|
||||
},
|
||||
"package_installation_allowed": {
|
||||
"const": false
|
||||
},
|
||||
"package_upgrade_allowed": {
|
||||
"const": false
|
||||
},
|
||||
"lockfile_write_allowed": {
|
||||
"const": false
|
||||
},
|
||||
"docker_build_allowed": {
|
||||
"const": false
|
||||
},
|
||||
"image_pull_allowed": {
|
||||
"const": false
|
||||
},
|
||||
"host_probe_allowed": {
|
||||
"const": false
|
||||
},
|
||||
"auto_pr_allowed": {
|
||||
"const": false
|
||||
},
|
||||
"auto_merge_allowed": {
|
||||
"const": false
|
||||
},
|
||||
"telegram_direct_send_allowed": {
|
||||
"const": false
|
||||
},
|
||||
"paid_external_service_allowed": {
|
||||
"const": false
|
||||
},
|
||||
"production_route_change_allowed": {
|
||||
"const": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"agent_roles": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"agent_id",
|
||||
"role",
|
||||
"autonomy_level",
|
||||
"outputs",
|
||||
"approval_gate"
|
||||
],
|
||||
"properties": {
|
||||
"agent_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"role": {
|
||||
"type": "string"
|
||||
},
|
||||
"autonomy_level": {
|
||||
"type": "string"
|
||||
},
|
||||
"outputs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"approval_gate": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"repo_scan_summary": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"javascript_workspace_count",
|
||||
"javascript_direct_dependency_count",
|
||||
"python_manifest_count",
|
||||
"dockerfile_count",
|
||||
"runtime_surface_count",
|
||||
"committed_inventory_refs",
|
||||
"stale_committed_inventory_refs"
|
||||
],
|
||||
"properties": {
|
||||
"javascript_workspace_count": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"javascript_direct_dependency_count": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"python_manifest_count": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"dockerfile_count": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"runtime_surface_count": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"committed_inventory_refs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"stale_committed_inventory_refs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"daily_snapshot_design": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"step_id",
|
||||
"sequence",
|
||||
"owner_agent",
|
||||
"allowed_now",
|
||||
"planned_output",
|
||||
"blocked_now"
|
||||
],
|
||||
"properties": {
|
||||
"step_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"sequence": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"owner_agent": {
|
||||
"type": "string"
|
||||
},
|
||||
"allowed_now": {
|
||||
"const": true
|
||||
},
|
||||
"planned_output": {
|
||||
"type": "string"
|
||||
},
|
||||
"blocked_now": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"freshness_sources": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"source_id",
|
||||
"domain",
|
||||
"source_type",
|
||||
"owner_agent",
|
||||
"status",
|
||||
"freshness_basis",
|
||||
"current_signal",
|
||||
"external_lookup_allowed",
|
||||
"mutation_allowed",
|
||||
"action_required",
|
||||
"evidence_refs",
|
||||
"next_action"
|
||||
],
|
||||
"properties": {
|
||||
"source_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"domain": {
|
||||
"type": "string"
|
||||
},
|
||||
"source_type": {
|
||||
"const": "repo_only"
|
||||
},
|
||||
"owner_agent": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"enum": [
|
||||
"baseline_ready",
|
||||
"action_required",
|
||||
"planned_next"
|
||||
]
|
||||
},
|
||||
"freshness_basis": {
|
||||
"type": "string"
|
||||
},
|
||||
"current_signal": {
|
||||
"type": "string"
|
||||
},
|
||||
"external_lookup_allowed": {
|
||||
"const": false
|
||||
},
|
||||
"mutation_allowed": {
|
||||
"const": false
|
||||
},
|
||||
"action_required": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"evidence_refs": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"next_action": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"approval_boundaries": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"daily_schedule_enabled",
|
||||
"external_source_lookup_allowed",
|
||||
"package_or_model_upgrade_allowed",
|
||||
"host_or_k3s_probe_allowed",
|
||||
"telegram_digest_send_allowed",
|
||||
"gitea_pr_creation_allowed",
|
||||
"production_route_change_allowed"
|
||||
],
|
||||
"properties": {
|
||||
"daily_schedule_enabled": {
|
||||
"const": false
|
||||
},
|
||||
"external_source_lookup_allowed": {
|
||||
"const": false
|
||||
},
|
||||
"package_or_model_upgrade_allowed": {
|
||||
"const": false
|
||||
},
|
||||
"host_or_k3s_probe_allowed": {
|
||||
"const": false
|
||||
},
|
||||
"telegram_digest_send_allowed": {
|
||||
"const": false
|
||||
},
|
||||
"gitea_pr_creation_allowed": {
|
||||
"const": false
|
||||
},
|
||||
"production_route_change_allowed": {
|
||||
"const": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"rollups": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"source_count",
|
||||
"repo_only_source_count",
|
||||
"agent_count",
|
||||
"daily_step_count",
|
||||
"action_required_source_ids",
|
||||
"blocked_external_lookup_source_ids",
|
||||
"mutation_allowed_source_count",
|
||||
"schedule_enabled_count",
|
||||
"telegram_direct_send_count",
|
||||
"next_approval_task_ids"
|
||||
],
|
||||
"properties": {
|
||||
"source_count": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"repo_only_source_count": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"agent_count": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"daily_step_count": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"action_required_source_ids": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"blocked_external_lookup_source_ids": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"mutation_allowed_source_count": {
|
||||
"const": 0
|
||||
},
|
||||
"schedule_enabled_count": {
|
||||
"const": 0
|
||||
},
|
||||
"telegram_direct_send_count": {
|
||||
"const": 0
|
||||
},
|
||||
"next_approval_task_ids": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -670,14 +670,17 @@ 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;完成度 `30%` |
|
||||
| `docs/evaluations/ai_agent_proactive_operations_contract_2026-06-11.json` | 12 類版本 domain、24 類可委派能力、5 種 cadence、8 類 MCP、4 類 RAG memory;完成度 `42%` |
|
||||
| `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 |
|
||||
|
||||
**採用順序:**
|
||||
|
||||
1. 先做 repo-only daily freshness:manifest / lockfile / Dockerfile / K8s YAML / runbook / snapshot。
|
||||
2. 再評估 external primary source weekly watch:Renovate、OSV-Scanner、Trivy、Syft、Grype、Kubernetes skew policy、Docker Scout。
|
||||
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。
|
||||
|
||||
@@ -1314,6 +1317,7 @@ Repo / registry / release notes / K8s / host / observability / backup evidence
|
||||
| 決策路由 | `services/decision_manager.py` | 新路徑:收到 EvidenceSnapshot → 送 Orchestrator → 等 Coordinator 結果 | L4×D2 |
|
||||
| 主動溝通與學習契約 | `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 |
|
||||
|
||||
**退出條件(量化)**
|
||||
|
||||
@@ -1685,6 +1689,12 @@ Phase 6 完成後
|
||||
- 新增 `ai_agent_proactive_operations_contract_v1` committed snapshot:12 類版本 domain、24 類可委派能力、5 種 cadence、8 類 MCP、4 類 RAG memory。
|
||||
- 新增 `GET /api/v1/agents/agent-proactive-operations-contract`;本波只讀,完成度 30%,未授權排程、升級、host update、container pull、auto merge、Telegram direct send、付費服務或 production route。
|
||||
|
||||
### 2026-06-11 22:45 (台北) — §3.2 / §5 — 完成 P2-402B repo-only 版本新鮮度快照 — 回應統帥要求讓 Agent 定期掌握套件、服務、工具、主機版本狀態
|
||||
|
||||
- 新增 `ai_agent_version_freshness_snapshot_v1` schema / committed snapshot / loader / API / 測試,定義 12 類 repo-only version source、5 個 daily snapshot design step、3 Agent 角色與 action-required source。
|
||||
- 更新 `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-04-15 (台北) — 全檔 — 建立 v2 骨架,§0/§1 完成 — 統帥批准「單 MASTER + 4 道閘門」結構
|
||||
|
||||
- 從 v1(plans/2026-04-15-MASTER-ai-autonomous-flywheel.md)繼承核心發現
|
||||
|
||||
Reference in New Issue
Block a user