feat(governance): 新增 Agent 日週月報風險自動化審查
All checks were successful
CD Pipeline / tests (push) Successful in 1m28s
Code Review / ai-code-review (push) Successful in 14s
CD Pipeline / build-and-deploy (push) Successful in 3m59s
CD Pipeline / post-deploy-checks (push) Successful in 1m30s

This commit is contained in:
Your Name
2026-06-12 10:46:56 +08:00
parent 867d3e1472
commit a2bcf03124
19 changed files with 1541 additions and 43 deletions

View File

@@ -0,0 +1,154 @@
"""
AI Agent report automation review snapshot.
Loads the latest committed P2-403J daily / weekly / monthly report, workload,
chart, and risk-tier automation policy review. This module never schedules a
live report, sends Telegram, writes optimization changes, or starts an
automation worker.
"""
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_report_automation_review_*.json"
_SCHEMA_VERSION = "ai_agent_report_automation_review_v1"
def load_latest_ai_agent_report_automation_review(
evaluations_dir: Path | None = None,
) -> dict[str, Any]:
"""Load the newest committed AI Agent report automation review snapshot."""
directory = evaluations_dir or _DEFAULT_EVALUATIONS_DIR
candidates = sorted(directory.glob(_SNAPSHOT_PATTERN))
if not candidates:
raise FileNotFoundError(f"no AI Agent report automation review 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, str(latest))
_require_report_contract(payload, str(latest))
_require_runtime_boundaries(payload, str(latest))
_require_rollup_consistency(payload, str(latest))
return payload
def _require_schema(payload: dict[str, Any], label: str) -> None:
if payload.get("schema_version") != _SCHEMA_VERSION:
raise ValueError(f"{label}: expected schema_version={_SCHEMA_VERSION}")
status = payload.get("program_status") or {}
if status.get("read_only_mode") is not True:
raise ValueError(f"{label}: program_status.read_only_mode must be true")
if status.get("runtime_authority") != "reporting_and_risk_policy_review_only_no_live_execution":
raise ValueError(
f"{label}: runtime_authority must remain reporting_and_risk_policy_review_only_no_live_execution"
)
def _require_report_contract(payload: dict[str, Any], label: str) -> None:
cadences = payload.get("report_cadences") or []
cadence_ids = {cadence.get("cadence_id") for cadence in cadences}
if cadence_ids != {"daily", "weekly", "monthly"}:
raise ValueError(f"{label}: report cadences must include daily, weekly, monthly")
agent_ids = {agent.get("agent_id") for agent in payload.get("agent_workload_metrics") or []}
if agent_ids != {"openclaw", "hermes", "nemotron"}:
raise ValueError(f"{label}: workload metrics must include OpenClaw, Hermes, NemoTron")
if not payload.get("report_charts"):
raise ValueError(f"{label}: report charts must not be empty")
if not payload.get("analysis_recommendations"):
raise ValueError(f"{label}: analysis recommendations must not be empty")
risk_ids = {tier.get("risk_id") for tier in (payload.get("risk_tier_policy") or {}).get("risk_tiers") or []}
if not {"low", "medium", "high", "critical"}.issubset(risk_ids):
raise ValueError(f"{label}: risk tier policy must include low, medium, high, critical")
def _require_runtime_boundaries(payload: dict[str, Any], label: str) -> None:
truth = payload.get("report_truth") or {}
if truth.get("high_risk_requires_approval") is not True:
raise ValueError(f"{label}: high risk approval gate must remain true")
if truth.get("medium_low_auto_policy_defined") is not True:
raise ValueError(f"{label}: medium / low auto policy must be defined")
zero_counts = {
"report_delivery_count_24h",
"report_read_receipt_count_24h",
"live_auto_optimization_count_24h",
"live_medium_low_auto_execution_count_24h",
}
non_zero = sorted(key for key in zero_counts if truth.get(key) != 0)
if non_zero:
raise ValueError(f"{label}: live report / automation counts must remain zero: {non_zero}")
false_flags = {
"report_delivery_enabled",
"ai_analysis_after_report_enabled",
"medium_low_auto_execution_enabled",
}
unsafe_truth = sorted(flag for flag in false_flags if truth.get(flag) is not False)
if unsafe_truth:
raise ValueError(f"{label}: live report automation flags must remain false: {unsafe_truth}")
boundaries = payload.get("approval_boundaries") or {}
unsafe_boundaries = sorted(
key
for key, value in boundaries.items()
if key != "high_risk_requires_human_approval" and value is not False
)
if unsafe_boundaries:
raise ValueError(f"{label}: approval boundaries must remain false: {unsafe_boundaries}")
if boundaries.get("high_risk_requires_human_approval") is not True:
raise ValueError(f"{label}: high_risk_requires_human_approval must remain true")
def _require_rollup_consistency(payload: dict[str, Any], label: str) -> None:
rollups = payload.get("rollups") or {}
workload = payload.get("agent_workload_metrics") or []
recommendations = payload.get("analysis_recommendations") or []
charts = payload.get("report_charts") or []
cadences = payload.get("report_cadences") or []
expected = {
"report_cadence_count": len(cadences),
"agent_count": len(workload),
"chart_count": len(charts),
"recommendation_count": len(recommendations),
"workload_unit_total": sum(item.get("work_units_total", 0) for item in workload),
"workload_done_total": sum(item.get("work_units_done", 0) for item in workload),
"workload_waiting_approval_total": sum(item.get("work_units_waiting_approval", 0) for item in workload),
"live_report_delivery_count": 0,
"live_auto_optimization_count": 0,
}
for risk in ("low", "medium", "high", "critical"):
expected[f"{risk}_risk_recommendation_count"] = len(
[item for item in recommendations if item.get("risk_tier") == risk]
)
mismatched = {
key: {"expected": value, "actual": rollups.get(key)}
for key, value in expected.items()
if rollups.get(key) != value
}
if mismatched:
raise ValueError(f"{label}: rollup counts must match payload sections: {mismatched}")
approval_required = sorted(
item.get("recommendation_id")
for item in recommendations
if item.get("approval_required") is True
)
if sorted(rollups.get("approval_required_recommendation_ids") or []) != approval_required:
raise ValueError(f"{label}: approval_required_recommendation_ids mismatch")
if rollups.get("current_auto_execution_enabled_count") != 0:
raise ValueError(f"{label}: current auto execution count must remain zero")