feat(governance): 新增 runtime readback implementation review
All checks were successful
Code Review / ai-code-review (push) Successful in 13s
CD Pipeline / tests (push) Successful in 1m26s
CD Pipeline / build-and-deploy (push) Successful in 4m32s
CD Pipeline / post-deploy-checks (push) Successful in 21s

This commit is contained in:
Your Name
2026-06-13 15:37:44 +08:00
parent b05139311b
commit be43b000a9
14 changed files with 2309 additions and 8 deletions

View File

@@ -106,6 +106,9 @@ from src.services.ai_agent_redis_dry_run_gate import (
from src.services.ai_agent_runtime_readback_approval_package import (
load_latest_ai_agent_runtime_readback_approval_package,
)
from src.services.ai_agent_runtime_readback_implementation_review import (
load_latest_ai_agent_runtime_readback_implementation_review,
)
from src.services.ai_agent_report_automation_review import (
load_latest_ai_agent_report_automation_review,
)
@@ -1300,7 +1303,7 @@ async def get_agent_owner_approved_result_capture_readback() -> dict[str, Any]:
response_model=dict[str, Any],
summary="取得 AI Agent runtime readback 批准包",
description=(
"讀取最新已提交的 P2-108 runtime readback approval package"
"讀取最新已提交的 P2-109 runtime readback approval package"
"此端點只回傳 approval packet、canonical readback plan、rollback drill、"
"Telegram 失敗收據 gate 與 operator action"
"不讀 canonical runtime target、不寫 score、不寫 result capture、不寫 learning、不更新 PlayBook trust、"
@@ -1326,6 +1329,36 @@ async def get_agent_runtime_readback_approval_package() -> dict[str, Any]:
) from exc
@router.get(
"/agent-runtime-readback-implementation-review",
response_model=dict[str, Any],
summary="取得 AI Agent runtime readback 實作審查",
description=(
"讀取最新已提交的 P2-110 runtime readback implementation review"
"此端點只回傳 implementation review card、no-write verifier、阻塞原因與 operator action"
"不讀 canonical runtime target、不做 live query、不寫 score、不寫 result capture、不寫 learning、"
"不更新 PlayBook trust、不寫 reviewer queue、不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、"
"不寫 rollback work item、不寫 production target、不讀 secret。"
),
)
async def get_agent_runtime_readback_implementation_review() -> dict[str, Any]:
"""Return the latest read-only runtime readback implementation review."""
try:
payload = await asyncio.to_thread(load_latest_ai_agent_runtime_readback_implementation_review)
return redact_public_lan_topology(payload)
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_runtime_readback_implementation_review_invalid", error=str(exc))
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="AI Agent runtime readback implementation review 無效",
) from exc
@router.get(
"/agent-owner-approved-fixture-dry-run",
response_model=dict[str, Any],

View File

@@ -0,0 +1,364 @@
"""
AI Agent runtime readback implementation review snapshot.
Loads the latest committed P2-110 runtime readback implementation review.
This module validates committed evidence only; it never reads canonical
runtime targets, writes result capture rows, writes scores, writes learning
state, updates PlayBook trust, writes reviewer/Gateway queues, sends Telegram
messages, calls Bot API, writes rollback work items, writes production targets,
reads secrets, or runs destructive operations.
"""
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_runtime_readback_implementation_review_*.json"
_SCHEMA_VERSION = "ai_agent_runtime_readback_implementation_review_v1"
_RUNTIME_AUTHORITY = "runtime_readback_implementation_review_only_no_live_read_or_write"
def load_latest_ai_agent_runtime_readback_implementation_review(
evaluations_dir: Path | None = None,
) -> dict[str, Any]:
"""Load the newest committed runtime readback implementation review."""
directory = evaluations_dir or _DEFAULT_EVALUATIONS_DIR
candidates = sorted(directory.glob(_SNAPSHOT_PATTERN))
if not candidates:
raise FileNotFoundError(f"no AI Agent runtime readback implementation 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_prior_package(payload, str(latest))
_require_review_truth(payload, str(latest))
_require_review_cards(payload, str(latest))
_require_verifier_checks(payload, str(latest))
_require_blockers(payload, str(latest))
_require_operator_actions(payload, str(latest))
_require_display_redaction(payload, str(latest))
_require_no_forbidden_display_terms(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") != _RUNTIME_AUTHORITY:
raise ValueError(f"{label}: runtime_authority must remain {_RUNTIME_AUTHORITY}")
if status.get("current_task_id") != "P2-110":
raise ValueError(f"{label}: current_task_id must be P2-110")
if status.get("next_task_id") != "P2-111":
raise ValueError(f"{label}: next_task_id must be P2-111")
def _require_prior_package(payload: dict[str, Any], label: str) -> None:
prior = payload.get("prior_approval_package") or {}
if prior.get("source_schema_version") != "ai_agent_runtime_readback_approval_package_v1":
raise ValueError(f"{label}: prior_approval_package must chain from P2-109")
required_counts = {
"approval_packet_count": 5,
"canonical_readback_plan_count": 4,
"rollback_drill_lane_count": 4,
"telegram_failure_receipt_gate_count": 4,
"operator_action_count": 5,
"approval_required_packet_count": 3,
"blocked_total_count": 5,
"owner_approval_received_count": 0,
"runtime_readback_execution_count": 0,
"telegram_failure_receipt_send_count": 0,
"bot_api_call_count": 0,
"rollback_work_item_write_count": 0,
"production_write_count": 0,
"secret_read_count": 0,
"destructive_operation_count": 0,
}
mismatches = {
key: {"expected": expected, "actual": prior.get(key)}
for key, expected in required_counts.items()
if prior.get(key) != expected
}
if mismatches:
raise ValueError(f"{label}: P2-109 prior approval package counts mismatch: {mismatches}")
def _require_review_truth(payload: dict[str, Any], label: str) -> None:
truth = payload.get("implementation_review_truth") or {}
required_true = {
"p2_109_approval_package_loaded",
"implementation_review_ready",
"adapter_contract_ready",
"verifier_contract_ready",
"redaction_contract_ready",
"telemetry_receipt_contract_ready",
"owner_review_required_before_runtime",
}
missing = sorted(field for field in required_true if truth.get(field) is not True)
if missing:
raise ValueError(f"{label}: implementation review flags must remain true: {missing}")
required_false = {
"canonical_runtime_readback_enabled",
"live_query_enabled",
"runtime_result_capture_write_enabled",
"runtime_score_write_enabled",
"runtime_learning_write_enabled",
"playbook_trust_write_enabled",
"reviewer_queue_write_enabled",
"gateway_queue_write_enabled",
"telegram_failure_receipt_send_enabled",
"bot_api_call_enabled",
"rollback_work_item_write_enabled",
"production_write_enabled",
"secret_read_enabled",
"destructive_operation_enabled",
}
unsafe = sorted(field for field in required_false if truth.get(field) is not False)
if unsafe:
raise ValueError(f"{label}: runtime read/write/send flags must remain false: {unsafe}")
zero_counts = {
"owner_approval_received_count",
"runtime_readback_execution_count",
"live_query_count_24h",
"result_capture_write_count_24h",
"score_write_count_24h",
"learning_write_count_24h",
"playbook_trust_write_count_24h",
"reviewer_queue_write_count_24h",
"gateway_queue_write_count_24h",
"telegram_failure_receipt_send_count_24h",
"bot_api_call_count_24h",
"rollback_work_item_write_count_24h",
"production_write_count_24h",
"secret_read_count_24h",
"destructive_operation_count_24h",
}
non_zero = sorted(field for field in zero_counts if truth.get(field) != 0)
if non_zero:
raise ValueError(f"{label}: implementation review live counters must remain zero: {non_zero}")
def _require_review_cards(payload: dict[str, Any], label: str) -> None:
cards = payload.get("implementation_review_cards") or []
card_ids = {card.get("card_id") for card in cards}
required = {
"runtime_readback_adapter_contract",
"result_capture_writer_noop_contract",
"critic_reviewer_score_noop_contract",
"telegram_failure_receipt_adapter_contract",
"rollback_work_item_noop_contract",
}
if card_ids != required:
raise ValueError(f"{label}: implementation review cards must match {sorted(required)}")
valid_statuses = {"ready_for_owner_review", "approval_required", "blocked_by_policy"}
valid_tiers = {"high", "critical"}
for card in cards:
card_id = card.get("card_id")
if card.get("status") not in valid_statuses:
raise ValueError(f"{label}: card {card_id} status is invalid")
if card.get("risk_tier") not in valid_tiers:
raise ValueError(f"{label}: card {card_id} risk_tier is invalid")
if card.get("owner_review_required") is not True:
raise ValueError(f"{label}: card {card_id} owner_review_required must remain true")
if card.get("no_write_mode") is not True:
raise ValueError(f"{label}: card {card_id} no_write_mode must remain true")
if not card.get("required_interfaces") or not card.get("blocked_runtime_actions"):
raise ValueError(f"{label}: card {card_id} must list interfaces and blocked runtime actions")
if not _is_redacted_sha256(card.get("evidence_hash")):
raise ValueError(f"{label}: card {card_id} must expose evidence_hash")
def _require_verifier_checks(payload: dict[str, Any], label: str) -> None:
checks = payload.get("no_write_verifier_checks") or []
check_ids = {check.get("check_id") for check in checks}
required = {
"schema_field_parity_check",
"redaction_payload_check",
"zero_write_counter_check",
"failure_receipt_route_check",
"rollback_reference_check",
}
if check_ids != required:
raise ValueError(f"{label}: no-write verifier checks must match {sorted(required)}")
for check in checks:
check_id = check.get("check_id")
if check.get("status") not in {"ready", "blocked_by_policy"}:
raise ValueError(f"{label}: verifier check {check_id} status is invalid")
if check.get("live_query_enabled") is not False:
raise ValueError(f"{label}: verifier check {check_id} live_query_enabled must remain false")
if check.get("runtime_write_allowed") is not False:
raise ValueError(f"{label}: verifier check {check_id} runtime_write_allowed must remain false")
if not check.get("required_evidence"):
raise ValueError(f"{label}: verifier check {check_id} must list required evidence")
if not _is_redacted_sha256(check.get("evidence_hash")):
raise ValueError(f"{label}: verifier check {check_id} must expose evidence_hash")
def _require_blockers(payload: dict[str, Any], label: str) -> None:
blockers = payload.get("implementation_blockers") or []
blocker_ids = {blocker.get("blocker_id") for blocker in blockers}
required = {
"owner_acceptance_missing",
"canonical_runtime_readback_disabled",
"reviewer_queue_write_disabled",
"telegram_receipt_send_disabled",
"rollback_work_item_write_disabled",
}
if blocker_ids != required:
raise ValueError(f"{label}: implementation blockers must match {sorted(required)}")
valid_statuses = {
"blocking_runtime",
"blocking_live_read",
"blocking_queue_write",
"blocking_notification",
"blocking_production_write",
}
for blocker in blockers:
blocker_id = blocker.get("blocker_id")
if blocker.get("severity") not in {"high", "critical"}:
raise ValueError(f"{label}: blocker {blocker_id} severity is invalid")
if blocker.get("status") not in valid_statuses:
raise ValueError(f"{label}: blocker {blocker_id} status is invalid")
if not blocker.get("blocked_action") or not blocker.get("required_resolution"):
raise ValueError(f"{label}: blocker {blocker_id} must explain blocked action and resolution")
if not _is_redacted_sha256(blocker.get("evidence_hash")):
raise ValueError(f"{label}: blocker {blocker_id} must expose evidence_hash")
def _require_operator_actions(payload: dict[str, Any], label: str) -> None:
actions = payload.get("operator_actions") or []
action_types = {action.get("action_type") for action in actions}
required = {
"review_implementation_contract",
"validate_adapter_mapping",
"validate_zero_write_counters",
"review_failure_receipt_mapping",
"reject_or_promote",
}
if action_types != required:
raise ValueError(f"{label}: operator actions must match {sorted(required)}")
for action in actions:
if action.get("runtime_write_allowed") is not False:
raise ValueError(f"{label}: operator action {action.get('action_id')} must not allow runtime write")
if not action.get("operator_instruction"):
raise ValueError(f"{label}: operator action {action.get('action_id')} must include instruction")
def _require_display_redaction(payload: dict[str, Any], label: str) -> None:
contract = payload.get("display_redaction_contract") or {}
if contract.get("redaction_required") is not True:
raise ValueError(f"{label}: display redaction must remain required")
required_false = {
"raw_prompt_display_allowed",
"private_reasoning_display_allowed",
"secret_value_display_allowed",
"raw_telegram_payload_display_allowed",
"work_window_transcript_display_allowed",
}
unsafe = sorted(field for field in required_false if contract.get(field) is not False)
if unsafe:
raise ValueError(f"{label}: display redaction fields must remain false: {unsafe}")
def _require_no_forbidden_display_terms(payload: dict[str, Any], label: str) -> None:
forbidden_terms = {
"工作視窗",
"對話內容",
"批准!繼續",
"In app browser",
"My request for Codex",
"browser_context",
"codex_user_message",
"prompt_text",
"raw prompt",
"private reasoning",
"chain of thought",
"private_reasoning",
"chain_of_thought",
"authorization_header",
"work window transcript",
"internal collaboration transcript",
}
hits: list[str] = []
def walk(value: Any, path: str) -> None:
if isinstance(value, dict):
for key, nested in value.items():
walk(nested, f"{path}.{key}" if path else str(key))
return
if isinstance(value, list):
for index, nested in enumerate(value):
walk(nested, f"{path}[{index}]")
return
if isinstance(value, str):
matched = sorted(term for term in forbidden_terms if term in value)
if matched:
hits.append(f"{path}: {', '.join(matched)}")
walk(payload, "")
if hits:
raise ValueError(f"{label}: forbidden display terms found: {hits}")
def _require_rollup_consistency(payload: dict[str, Any], label: str) -> None:
rollups = payload.get("rollups") or {}
truth = payload.get("implementation_review_truth") or {}
cards = payload.get("implementation_review_cards") or []
checks = payload.get("no_write_verifier_checks") or []
blockers = payload.get("implementation_blockers") or []
actions = payload.get("operator_actions") or []
expected = {
"implementation_review_card_count": len(cards),
"no_write_verifier_check_count": len(checks),
"implementation_blocker_count": len(blockers),
"operator_action_count": len(actions),
"approval_required_card_count": sum(1 for item in cards if item.get("status") == "approval_required"),
"blocked_card_count": sum(1 for item in cards if item.get("status") == "blocked_by_policy"),
"blocked_verifier_check_count": sum(1 for item in checks if item.get("status") == "blocked_by_policy"),
"critical_blocker_count": sum(1 for item in blockers if item.get("severity") == "critical"),
"owner_approval_received_count": truth.get("owner_approval_received_count"),
"runtime_readback_execution_count": truth.get("runtime_readback_execution_count"),
"live_query_count": truth.get("live_query_count_24h"),
"result_capture_write_count": truth.get("result_capture_write_count_24h"),
"score_write_count": truth.get("score_write_count_24h"),
"learning_write_count": truth.get("learning_write_count_24h"),
"playbook_trust_write_count": truth.get("playbook_trust_write_count_24h"),
"reviewer_queue_write_count": truth.get("reviewer_queue_write_count_24h"),
"gateway_queue_write_count": truth.get("gateway_queue_write_count_24h"),
"telegram_failure_receipt_send_count": truth.get("telegram_failure_receipt_send_count_24h"),
"bot_api_call_count": truth.get("bot_api_call_count_24h"),
"rollback_work_item_write_count": truth.get("rollback_work_item_write_count_24h"),
"production_write_count": truth.get("production_write_count_24h"),
"secret_read_count": truth.get("secret_read_count_24h"),
"destructive_operation_count": truth.get("destructive_operation_count_24h"),
}
mismatches = {
key: {"expected": expected_value, "actual": rollups.get(key)}
for key, expected_value in expected.items()
if rollups.get(key) != expected_value
}
if mismatches:
raise ValueError(f"{label}: rollup counts mismatch: {mismatches}")
def _is_redacted_sha256(value: Any) -> bool:
if not isinstance(value, str):
return False
if not value.startswith("sha256:") or len(value) != 71:
return False
return all(char in "0123456789abcdef" for char in value.removeprefix("sha256:"))