From be43b000a97f02a951ffdc0b029ae2a038134503 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 13 Jun 2026 15:37:44 +0800 Subject: [PATCH] =?UTF-8?q?feat(governance):=20=E6=96=B0=E5=A2=9E=20runtim?= =?UTF-8?q?e=20readback=20implementation=20review?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/api/src/api/v1/agents.py | 35 +- ..._runtime_readback_implementation_review.py | 364 +++++++++ ..._runtime_readback_implementation_review.py | 132 ++++ ...time_readback_implementation_review_api.py | 48 ++ apps/web/messages/en.json | 76 ++ apps/web/messages/zh-TW.json | 76 ++ .../tabs/automation-inventory-tab.tsx | 240 +++++- apps/web/src/lib/api-client.ts | 158 ++++ docs/LOGBOOK.md | 22 + ...AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md | 6 +- ...T_INTERACTION_LEARNING_PROOF_2026-06-11.md | 8 +- ...back_implementation_review_2026-06-13.json | 415 ++++++++++ ...dback_implementation_review_v1.schema.json | 726 ++++++++++++++++++ ...-04-15-MASTER-ai-autonomous-flywheel-v2.md | 11 + 14 files changed, 2309 insertions(+), 8 deletions(-) create mode 100644 apps/api/src/services/ai_agent_runtime_readback_implementation_review.py create mode 100644 apps/api/tests/test_ai_agent_runtime_readback_implementation_review.py create mode 100644 apps/api/tests/test_ai_agent_runtime_readback_implementation_review_api.py create mode 100644 docs/evaluations/ai_agent_runtime_readback_implementation_review_2026-06-13.json create mode 100644 docs/schemas/ai_agent_runtime_readback_implementation_review_v1.schema.json diff --git a/apps/api/src/api/v1/agents.py b/apps/api/src/api/v1/agents.py index 0617681d3..752b6e2f7 100644 --- a/apps/api/src/api/v1/agents.py +++ b/apps/api/src/api/v1/agents.py @@ -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], diff --git a/apps/api/src/services/ai_agent_runtime_readback_implementation_review.py b/apps/api/src/services/ai_agent_runtime_readback_implementation_review.py new file mode 100644 index 000000000..2f2018699 --- /dev/null +++ b/apps/api/src/services/ai_agent_runtime_readback_implementation_review.py @@ -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:")) diff --git a/apps/api/tests/test_ai_agent_runtime_readback_implementation_review.py b/apps/api/tests/test_ai_agent_runtime_readback_implementation_review.py new file mode 100644 index 000000000..7b28fc4ec --- /dev/null +++ b/apps/api/tests/test_ai_agent_runtime_readback_implementation_review.py @@ -0,0 +1,132 @@ +import copy +import json + +import pytest + +from src.services.ai_agent_runtime_readback_implementation_review import ( + load_latest_ai_agent_runtime_readback_implementation_review, +) + + +def _write_snapshot(tmp_path, payload): + path = tmp_path / "ai_agent_runtime_readback_implementation_review_2026-06-13.json" + path.write_text(json.dumps(payload), encoding="utf-8") + return path + + +def test_load_latest_ai_agent_runtime_readback_implementation_review(): + data = load_latest_ai_agent_runtime_readback_implementation_review() + + assert data["schema_version"] == "ai_agent_runtime_readback_implementation_review_v1" + assert data["program_status"]["current_task_id"] == "P2-110" + assert data["program_status"]["next_task_id"] == "P2-111" + assert data["program_status"]["overall_completion_percent"] == 100 + assert data["prior_approval_package"]["source_schema_version"] == "ai_agent_runtime_readback_approval_package_v1" + assert data["prior_approval_package"]["approval_packet_count"] == 5 + assert data["prior_approval_package"]["blocked_total_count"] == 5 + assert data["implementation_review_truth"]["p2_109_approval_package_loaded"] is True + assert data["implementation_review_truth"]["implementation_review_ready"] is True + assert data["implementation_review_truth"]["adapter_contract_ready"] is True + assert data["implementation_review_truth"]["verifier_contract_ready"] is True + assert data["implementation_review_truth"]["redaction_contract_ready"] is True + assert data["implementation_review_truth"]["telemetry_receipt_contract_ready"] is True + assert data["implementation_review_truth"]["canonical_runtime_readback_enabled"] is False + assert data["implementation_review_truth"]["live_query_enabled"] is False + assert data["implementation_review_truth"]["runtime_result_capture_write_enabled"] is False + assert data["implementation_review_truth"]["telegram_failure_receipt_send_enabled"] is False + assert data["implementation_review_truth"]["bot_api_call_enabled"] is False + assert data["implementation_review_truth"]["rollback_work_item_write_enabled"] is False + assert data["implementation_review_truth"]["runtime_readback_execution_count"] == 0 + assert data["implementation_review_truth"]["live_query_count_24h"] == 0 + assert data["rollups"]["implementation_review_card_count"] == 5 + assert data["rollups"]["no_write_verifier_check_count"] == 5 + assert data["rollups"]["implementation_blocker_count"] == 5 + assert data["rollups"]["operator_action_count"] == 5 + assert data["rollups"]["approval_required_card_count"] == 2 + assert data["rollups"]["blocked_card_count"] == 1 + assert data["rollups"]["blocked_verifier_check_count"] == 1 + assert data["rollups"]["critical_blocker_count"] == 2 + assert data["rollups"]["owner_approval_received_count"] == 0 + assert data["rollups"]["runtime_readback_execution_count"] == 0 + assert data["rollups"]["live_query_count"] == 0 + assert data["rollups"]["result_capture_write_count"] == 0 + assert data["rollups"]["score_write_count"] == 0 + assert data["rollups"]["learning_write_count"] == 0 + assert data["rollups"]["playbook_trust_write_count"] == 0 + assert data["rollups"]["reviewer_queue_write_count"] == 0 + assert data["rollups"]["gateway_queue_write_count"] == 0 + assert data["rollups"]["telegram_failure_receipt_send_count"] == 0 + assert data["rollups"]["bot_api_call_count"] == 0 + assert data["rollups"]["rollback_work_item_write_count"] == 0 + assert data["rollups"]["production_write_count"] == 0 + + +def test_rejects_live_query_enabled(tmp_path): + data = load_latest_ai_agent_runtime_readback_implementation_review() + bad = copy.deepcopy(data) + bad["implementation_review_truth"]["live_query_enabled"] = True + _write_snapshot(tmp_path, bad) + + with pytest.raises(ValueError, match="runtime read/write/send flags"): + load_latest_ai_agent_runtime_readback_implementation_review(tmp_path) + + +def test_rejects_runtime_execution_count(tmp_path): + data = load_latest_ai_agent_runtime_readback_implementation_review() + bad = copy.deepcopy(data) + bad["implementation_review_truth"]["runtime_readback_execution_count"] = 1 + bad["rollups"]["runtime_readback_execution_count"] = 1 + _write_snapshot(tmp_path, bad) + + with pytest.raises(ValueError, match="live counters"): + load_latest_ai_agent_runtime_readback_implementation_review(tmp_path) + + +def test_rejects_card_write_mode(tmp_path): + data = load_latest_ai_agent_runtime_readback_implementation_review() + bad = copy.deepcopy(data) + bad["implementation_review_cards"][0]["no_write_mode"] = False + _write_snapshot(tmp_path, bad) + + with pytest.raises(ValueError, match="no_write_mode"): + load_latest_ai_agent_runtime_readback_implementation_review(tmp_path) + + +def test_rejects_verifier_live_query(tmp_path): + data = load_latest_ai_agent_runtime_readback_implementation_review() + bad = copy.deepcopy(data) + bad["no_write_verifier_checks"][0]["live_query_enabled"] = True + _write_snapshot(tmp_path, bad) + + with pytest.raises(ValueError, match="live_query_enabled"): + load_latest_ai_agent_runtime_readback_implementation_review(tmp_path) + + +def test_rejects_missing_blocker_resolution(tmp_path): + data = load_latest_ai_agent_runtime_readback_implementation_review() + bad = copy.deepcopy(data) + bad["implementation_blockers"][0]["required_resolution"] = "" + _write_snapshot(tmp_path, bad) + + with pytest.raises(ValueError, match="blocked action and resolution"): + load_latest_ai_agent_runtime_readback_implementation_review(tmp_path) + + +def test_rejects_forbidden_display_terms(tmp_path): + data = load_latest_ai_agent_runtime_readback_implementation_review() + bad = copy.deepcopy(data) + bad["operator_actions"][0]["operator_instruction"] = "不得顯示工作視窗內容" + _write_snapshot(tmp_path, bad) + + with pytest.raises(ValueError, match="forbidden display terms"): + load_latest_ai_agent_runtime_readback_implementation_review(tmp_path) + + +def test_rejects_rollup_mismatch(tmp_path): + data = load_latest_ai_agent_runtime_readback_implementation_review() + bad = copy.deepcopy(data) + bad["rollups"]["implementation_review_card_count"] = 999 + _write_snapshot(tmp_path, bad) + + with pytest.raises(ValueError, match="rollup counts"): + load_latest_ai_agent_runtime_readback_implementation_review(tmp_path) diff --git a/apps/api/tests/test_ai_agent_runtime_readback_implementation_review_api.py b/apps/api/tests/test_ai_agent_runtime_readback_implementation_review_api.py new file mode 100644 index 000000000..b899aed43 --- /dev/null +++ b/apps/api/tests/test_ai_agent_runtime_readback_implementation_review_api.py @@ -0,0 +1,48 @@ +from fastapi.testclient import TestClient + +from src.main import app + + +def test_get_ai_agent_runtime_readback_implementation_review_api(): + client = TestClient(app) + response = client.get("/api/v1/agents/agent-runtime-readback-implementation-review") + + assert response.status_code == 200 + data = response.json() + assert data["schema_version"] == "ai_agent_runtime_readback_implementation_review_v1" + assert data["program_status"]["current_task_id"] == "P2-110" + assert data["program_status"]["next_task_id"] == "P2-111" + assert data["program_status"]["overall_completion_percent"] == 100 + assert data["prior_approval_package"]["source_schema_version"] == "ai_agent_runtime_readback_approval_package_v1" + assert data["prior_approval_package"]["approval_packet_count"] == 5 + assert data["implementation_review_truth"]["p2_109_approval_package_loaded"] is True + assert data["implementation_review_truth"]["implementation_review_ready"] is True + assert data["implementation_review_truth"]["adapter_contract_ready"] is True + assert data["implementation_review_truth"]["verifier_contract_ready"] is True + assert data["implementation_review_truth"]["redaction_contract_ready"] is True + assert data["implementation_review_truth"]["telemetry_receipt_contract_ready"] is True + assert data["implementation_review_truth"]["canonical_runtime_readback_enabled"] is False + assert data["implementation_review_truth"]["live_query_enabled"] is False + assert data["implementation_review_truth"]["runtime_result_capture_write_enabled"] is False + assert data["implementation_review_truth"]["reviewer_queue_write_enabled"] is False + assert data["implementation_review_truth"]["telegram_failure_receipt_send_enabled"] is False + assert data["implementation_review_truth"]["bot_api_call_enabled"] is False + assert data["implementation_review_truth"]["rollback_work_item_write_enabled"] is False + assert data["implementation_review_truth"]["runtime_readback_execution_count"] == 0 + assert data["rollups"]["implementation_review_card_count"] == 5 + assert data["rollups"]["no_write_verifier_check_count"] == 5 + assert data["rollups"]["implementation_blocker_count"] == 5 + assert data["rollups"]["operator_action_count"] == 5 + assert data["rollups"]["owner_approval_received_count"] == 0 + assert data["rollups"]["runtime_readback_execution_count"] == 0 + assert data["rollups"]["live_query_count"] == 0 + assert data["rollups"]["result_capture_write_count"] == 0 + assert data["rollups"]["score_write_count"] == 0 + assert data["rollups"]["learning_write_count"] == 0 + assert data["rollups"]["playbook_trust_write_count"] == 0 + assert data["rollups"]["reviewer_queue_write_count"] == 0 + assert data["rollups"]["gateway_queue_write_count"] == 0 + assert data["rollups"]["telegram_failure_receipt_send_count"] == 0 + assert data["rollups"]["bot_api_call_count"] == 0 + assert data["rollups"]["rollback_work_item_write_count"] == 0 + assert data["rollups"]["production_write_count"] == 0 diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index 8ad22f661..83a290958 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -4999,6 +4999,82 @@ "review_failure_receipt_gate": "審查失敗收據 gate", "reject_or_promote": "退回或推進" } + }, + "runtimeReadbackImplementationReview": { + "title": "P2-110 runtime readback 實作審查", + "source": "{generated} · {current} → {next}", + "truthTitle": "實作審查真相", + "priorTitle": "P2-109 批准包承接", + "metrics": { + "overall": "P2-110 進度", + "cards": "實作卡", + "checks": "no-write verifier", + "blockers": "阻塞項", + "actions": "操作選項", + "approvalRequired": "需批准", + "blocked": "阻擋總數", + "criticalBlockers": "關鍵阻塞", + "ownerApprovals": "已收批准", + "executions": "runtime readback", + "liveQueries": "live query", + "telegramSends": "Telegram 發送", + "rollbackWrites": "rollback 寫入", + "liveWrites": "正式寫入" + }, + "flags": { + "packageLoaded": "P2-109 package: {value}", + "reviewReady": "審查 ready: {value}", + "adapterReady": "adapter contract: {value}", + "verifierReady": "verifier contract: {value}", + "receiptReady": "失敗收據 contract: {value}", + "liveQuery": "live query: {value}", + "canonicalRead": "canonical read: {value}", + "resultWrite": "結果寫入: {value}", + "queueWrite": "queue 寫入: {value}", + "telegramSend": "Telegram 發送: {value}", + "rollbackWrite": "rollback 寫入: {value}" + }, + "labels": { + "interfaces": "介面欄位 {count}", + "blockedActions": "阻擋動作 {count}", + "noWriteMode": "no-write: {value}", + "requiredEvidence": "必備證據 {count}", + "liveQuery": "live query: {value}", + "runtimeWrite": "runtime 寫入: {value}", + "blockedAction": "阻擋: {value}", + "blockedUntil": "直到: {value}" + }, + "cardStatuses": { + "ready_for_owner_review": "待 owner 審查", + "approval_required": "需批准", + "blocked_by_policy": "政策阻擋" + }, + "checkStatuses": { + "ready": "可審查", + "blocked_by_policy": "政策阻擋" + }, + "blockerStatuses": { + "blocking_runtime": "阻擋 runtime", + "blocking_live_read": "阻擋 live read", + "blocking_queue_write": "阻擋 queue write", + "blocking_notification": "阻擋通知", + "blocking_production_write": "阻擋正式寫入" + }, + "riskTiers": { + "high": "高風險", + "critical": "關鍵阻擋" + }, + "severities": { + "high": "高", + "critical": "關鍵" + }, + "actionTypes": { + "review_implementation_contract": "審查實作契約", + "validate_adapter_mapping": "核對 adapter 映射", + "validate_zero_write_counters": "確認零寫入", + "review_failure_receipt_mapping": "審查失敗收據", + "reject_or_promote": "退回或推進" + } } } }, diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index 8ad22f661..83a290958 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -4999,6 +4999,82 @@ "review_failure_receipt_gate": "審查失敗收據 gate", "reject_or_promote": "退回或推進" } + }, + "runtimeReadbackImplementationReview": { + "title": "P2-110 runtime readback 實作審查", + "source": "{generated} · {current} → {next}", + "truthTitle": "實作審查真相", + "priorTitle": "P2-109 批准包承接", + "metrics": { + "overall": "P2-110 進度", + "cards": "實作卡", + "checks": "no-write verifier", + "blockers": "阻塞項", + "actions": "操作選項", + "approvalRequired": "需批准", + "blocked": "阻擋總數", + "criticalBlockers": "關鍵阻塞", + "ownerApprovals": "已收批准", + "executions": "runtime readback", + "liveQueries": "live query", + "telegramSends": "Telegram 發送", + "rollbackWrites": "rollback 寫入", + "liveWrites": "正式寫入" + }, + "flags": { + "packageLoaded": "P2-109 package: {value}", + "reviewReady": "審查 ready: {value}", + "adapterReady": "adapter contract: {value}", + "verifierReady": "verifier contract: {value}", + "receiptReady": "失敗收據 contract: {value}", + "liveQuery": "live query: {value}", + "canonicalRead": "canonical read: {value}", + "resultWrite": "結果寫入: {value}", + "queueWrite": "queue 寫入: {value}", + "telegramSend": "Telegram 發送: {value}", + "rollbackWrite": "rollback 寫入: {value}" + }, + "labels": { + "interfaces": "介面欄位 {count}", + "blockedActions": "阻擋動作 {count}", + "noWriteMode": "no-write: {value}", + "requiredEvidence": "必備證據 {count}", + "liveQuery": "live query: {value}", + "runtimeWrite": "runtime 寫入: {value}", + "blockedAction": "阻擋: {value}", + "blockedUntil": "直到: {value}" + }, + "cardStatuses": { + "ready_for_owner_review": "待 owner 審查", + "approval_required": "需批准", + "blocked_by_policy": "政策阻擋" + }, + "checkStatuses": { + "ready": "可審查", + "blocked_by_policy": "政策阻擋" + }, + "blockerStatuses": { + "blocking_runtime": "阻擋 runtime", + "blocking_live_read": "阻擋 live read", + "blocking_queue_write": "阻擋 queue write", + "blocking_notification": "阻擋通知", + "blocking_production_write": "阻擋正式寫入" + }, + "riskTiers": { + "high": "高風險", + "critical": "關鍵阻擋" + }, + "severities": { + "high": "高", + "critical": "關鍵" + }, + "actionTypes": { + "review_implementation_contract": "審查實作契約", + "validate_adapter_mapping": "核對 adapter 映射", + "validate_zero_write_counters": "確認零寫入", + "review_failure_receipt_mapping": "審查失敗收據", + "reject_or_promote": "退回或推進" + } } } }, diff --git a/apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx b/apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx index 696590192..d72836fc6 100644 --- a/apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx +++ b/apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx @@ -58,6 +58,7 @@ import { type AiAgentReportRuntimeReadinessSnapshot, type AiAgentReportTruthActionabilityReviewSnapshot, type AiAgentRuntimeReadbackApprovalPackageSnapshot, + type AiAgentRuntimeReadbackImplementationReviewSnapshot, type AiAgentRuntimeWorkerShadowGateSnapshot, type AiAgentRuntimeVerifierEvidenceReviewSnapshot, type AiAgentRuntimeWriteGateReviewSnapshot, @@ -436,6 +437,7 @@ export function AutomationInventoryTab() { const [ownerApprovedResultCaptureDryRun, setOwnerApprovedResultCaptureDryRun] = useState(null) const [ownerApprovedResultCaptureReadback, setOwnerApprovedResultCaptureReadback] = useState(null) const [runtimeReadbackApprovalPackage, setRuntimeReadbackApprovalPackage] = useState(null) + const [runtimeReadbackImplementationReview, setRuntimeReadbackImplementationReview] = useState(null) const [reportTruthActionabilityReview, setReportTruthActionabilityReview] = useState(null) const [ownerDryRunPackage, setOwnerDryRunPackage] = useState(null) const [hostStatefulInventory, setHostStatefulInventory] = useState(null) @@ -482,6 +484,7 @@ export function AutomationInventoryTab() { apiClient.getAiAgentOwnerApprovedResultCaptureDryRun(), apiClient.getAiAgentOwnerApprovedResultCaptureReadback(), apiClient.getAiAgentRuntimeReadbackApprovalPackage(), + apiClient.getAiAgentRuntimeReadbackImplementationReview(), apiClient.getAiAgentReportTruthActionabilityReview(), apiClient.getAiAgentOwnerApprovedFixtureDryRun(), apiClient.getAiAgentHostStatefulVersionInventory(), @@ -527,6 +530,7 @@ export function AutomationInventoryTab() { ownerApprovedResultCaptureDryRunResult, ownerApprovedResultCaptureReadbackResult, runtimeReadbackApprovalPackageResult, + runtimeReadbackImplementationReviewResult, reportTruthActionabilityReviewResult, ownerDryRunPackageResult, hostStatefulInventoryResult, @@ -569,6 +573,7 @@ export function AutomationInventoryTab() { setOwnerApprovedResultCaptureDryRun(ownerApprovedResultCaptureDryRunResult.status === 'fulfilled' ? ownerApprovedResultCaptureDryRunResult.value : null) setOwnerApprovedResultCaptureReadback(ownerApprovedResultCaptureReadbackResult.status === 'fulfilled' ? ownerApprovedResultCaptureReadbackResult.value : null) setRuntimeReadbackApprovalPackage(runtimeReadbackApprovalPackageResult.status === 'fulfilled' ? runtimeReadbackApprovalPackageResult.value : null) + setRuntimeReadbackImplementationReview(runtimeReadbackImplementationReviewResult.status === 'fulfilled' ? runtimeReadbackImplementationReviewResult.value : null) setReportTruthActionabilityReview(reportTruthActionabilityReviewResult.status === 'fulfilled' ? reportTruthActionabilityReviewResult.value : null) setOwnerDryRunPackage(ownerDryRunPackageResult.status === 'fulfilled' ? ownerDryRunPackageResult.value : null) setHostStatefulInventory(hostStatefulInventoryResult.status === 'fulfilled' ? hostStatefulInventoryResult.value : null) @@ -609,6 +614,7 @@ export function AutomationInventoryTab() { ownerApprovedResultCaptureDryRunResult, ownerApprovedResultCaptureReadbackResult, runtimeReadbackApprovalPackageResult, + runtimeReadbackImplementationReviewResult, reportTruthActionabilityReviewResult, ownerDryRunPackageResult, hostStatefulInventoryResult, @@ -1546,6 +1552,49 @@ export function AutomationInventoryTab() { .slice(0, 4) }, [runtimeReadbackApprovalPackage]) + const visibleRuntimeImplementationCards = useMemo(() => { + if (!runtimeReadbackImplementationReview) return [] + const statusPriority = { blocked_by_policy: 0, approval_required: 1, ready_for_owner_review: 2 } as Record + const riskPriority = { critical: 0, high: 1 } as Record + return [...runtimeReadbackImplementationReview.implementation_review_cards] + .sort((a, b) => { + const leftStatus = statusPriority[a.status] ?? 3 + const rightStatus = statusPriority[b.status] ?? 3 + if (leftStatus !== rightStatus) return leftStatus - rightStatus + const leftRisk = riskPriority[a.risk_tier] ?? 4 + const rightRisk = riskPriority[b.risk_tier] ?? 4 + if (leftRisk !== rightRisk) return leftRisk - rightRisk + return a.card_id.localeCompare(b.card_id) + }) + .slice(0, 5) + }, [runtimeReadbackImplementationReview]) + + const visibleRuntimeImplementationChecks = useMemo(() => { + if (!runtimeReadbackImplementationReview) return [] + const statusPriority = { blocked_by_policy: 0, ready: 1 } as Record + return [...runtimeReadbackImplementationReview.no_write_verifier_checks] + .sort((a, b) => { + const left = statusPriority[a.status] ?? 2 + const right = statusPriority[b.status] ?? 2 + if (left !== right) return left - right + return a.check_id.localeCompare(b.check_id) + }) + .slice(0, 5) + }, [runtimeReadbackImplementationReview]) + + const visibleRuntimeImplementationBlockers = useMemo(() => { + if (!runtimeReadbackImplementationReview) return [] + const severityPriority = { critical: 0, high: 1 } as Record + return [...runtimeReadbackImplementationReview.implementation_blockers] + .sort((a, b) => { + const left = severityPriority[a.severity] ?? 2 + const right = severityPriority[b.severity] ?? 2 + if (left !== right) return left - right + return a.blocker_id.localeCompare(b.blocker_id) + }) + .slice(0, 5) + }, [runtimeReadbackImplementationReview]) + const visibleReportTruthFindings = useMemo(() => { if (!reportTruthActionabilityReview) return [] const priority = { critical: 0, high: 1, medium: 2, low: 3 } as Record @@ -1765,7 +1814,7 @@ export function AutomationInventoryTab() { ) } - if (error || !snapshot || !backlog || !backupTargets || !backupReadiness || !backupPolicy || !offsiteEscrow || !giteaHealth || !observabilityMatrix || !providerRouteMatrix || !deploymentLayout || !proactiveOperations || !interactionLearningProof || !liveReadModelGate || !redisDryRunGate || !learningWritebackPackage || !telegramReceiptPackage || !ownerApprovedLearningDryRun || !runtimeWriteGateReview || !postWriteVerifierPackage || !runtimeVerifierEvidenceReview || !reportAutomationReview || !reportStatusBoard || !reportRuntimeReadiness || !reportRuntimeDryRun || !reportRuntimeFixtureReadback || !runtimeWorkerShadowGate || !operationPermissionModel || !candidateOperationDryRunEvidence || !taskResultAuditTrail || !matchedPlaybookLearningGap || !criticReviewerResultCapture || !ownerApprovedResultCaptureDryRun || !ownerApprovedResultCaptureReadback || !runtimeReadbackApprovalPackage || !reportTruthActionabilityReview || !ownerDryRunPackage || !hostStatefulInventory || !serviceHealthGapMatrix || !serviceHealthNotificationPolicy) { + if (error || !snapshot || !backlog || !backupTargets || !backupReadiness || !backupPolicy || !offsiteEscrow || !giteaHealth || !observabilityMatrix || !providerRouteMatrix || !deploymentLayout || !proactiveOperations || !interactionLearningProof || !liveReadModelGate || !redisDryRunGate || !learningWritebackPackage || !telegramReceiptPackage || !ownerApprovedLearningDryRun || !runtimeWriteGateReview || !postWriteVerifierPackage || !runtimeVerifierEvidenceReview || !reportAutomationReview || !reportStatusBoard || !reportRuntimeReadiness || !reportRuntimeDryRun || !reportRuntimeFixtureReadback || !runtimeWorkerShadowGate || !operationPermissionModel || !candidateOperationDryRunEvidence || !taskResultAuditTrail || !matchedPlaybookLearningGap || !criticReviewerResultCapture || !ownerApprovedResultCaptureDryRun || !ownerApprovedResultCaptureReadback || !runtimeReadbackApprovalPackage || !runtimeReadbackImplementationReview || !reportTruthActionabilityReview || !ownerDryRunPackage || !hostStatefulInventory || !serviceHealthGapMatrix || !serviceHealthNotificationPolicy) { return (
@@ -2115,6 +2164,35 @@ export function AutomationInventoryTab() { + runtimeReadbackApprovalPackage.rollups.rollback_work_item_write_count + runtimeReadbackApprovalPackage.rollups.production_write_count ) + const runtimeImplementationOverall = runtimeReadbackImplementationReview.program_status.overall_completion_percent + const runtimeImplementationCards = runtimeReadbackImplementationReview.rollups.implementation_review_card_count + const runtimeImplementationChecks = runtimeReadbackImplementationReview.rollups.no_write_verifier_check_count + const runtimeImplementationBlockers = runtimeReadbackImplementationReview.rollups.implementation_blocker_count + const runtimeImplementationActions = runtimeReadbackImplementationReview.rollups.operator_action_count + const runtimeImplementationApprovalRequired = runtimeReadbackImplementationReview.rollups.approval_required_card_count + const runtimeImplementationBlocked = ( + runtimeReadbackImplementationReview.rollups.blocked_card_count + + runtimeReadbackImplementationReview.rollups.blocked_verifier_check_count + + runtimeReadbackImplementationReview.rollups.implementation_blocker_count + ) + const runtimeImplementationCriticalBlockers = runtimeReadbackImplementationReview.rollups.critical_blocker_count + const runtimeImplementationOwnerApprovals = runtimeReadbackImplementationReview.rollups.owner_approval_received_count + const runtimeImplementationExecutions = runtimeReadbackImplementationReview.rollups.runtime_readback_execution_count + const runtimeImplementationLiveQueries = runtimeReadbackImplementationReview.rollups.live_query_count + const runtimeImplementationTelegramSends = runtimeReadbackImplementationReview.rollups.telegram_failure_receipt_send_count + const runtimeImplementationRollbackWrites = runtimeReadbackImplementationReview.rollups.rollback_work_item_write_count + const runtimeImplementationLiveWrites = ( + runtimeReadbackImplementationReview.rollups.result_capture_write_count + + runtimeReadbackImplementationReview.rollups.score_write_count + + runtimeReadbackImplementationReview.rollups.learning_write_count + + runtimeReadbackImplementationReview.rollups.playbook_trust_write_count + + runtimeReadbackImplementationReview.rollups.reviewer_queue_write_count + + runtimeReadbackImplementationReview.rollups.gateway_queue_write_count + + runtimeReadbackImplementationReview.rollups.telegram_failure_receipt_send_count + + runtimeReadbackImplementationReview.rollups.bot_api_call_count + + runtimeReadbackImplementationReview.rollups.rollback_work_item_write_count + + runtimeReadbackImplementationReview.rollups.production_write_count + ) const reportTruthOverall = reportTruthActionabilityReview.program_status.overall_completion_percent const reportTruthFindings = reportTruthActionabilityReview.rollups.zero_signal_finding_count const reportTruthCritical = reportTruthActionabilityReview.rollups.critical_finding_count @@ -5062,6 +5140,166 @@ export function AutomationInventoryTab() {
+
+
+
+ + + {t('runtimeReadbackImplementationReview.title')} + +
+ +
+ +
+ } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> +
+ +
+
+ {t('runtimeReadbackImplementationReview.priorTitle')} + + {runtimeReadbackImplementationReview.prior_approval_package.readiness_note} + +
+ + + + +
+
+ +
+ {t('runtimeReadbackImplementationReview.truthTitle')} + + {runtimeReadbackImplementationReview.implementation_review_truth.truth_note} + +
+ + + + + + + + + + + +
+
+
+ +
+ {visibleRuntimeImplementationCards.map(card => ( +
+
+ + {card.display_name} + + +
+ + {card.review_guidance} + +
+ + + + + + +
+
+ ))} +
+ +
+ {visibleRuntimeImplementationChecks.map(check => ( +
+
+ + {check.display_name} + + +
+ + {check.failure_if_missing} + +
+ + + + + +
+
+ ))} +
+ +
+ {visibleRuntimeImplementationBlockers.map(blocker => ( +
+
+ + {blocker.display_name} + + +
+ + {blocker.required_resolution} + +
+ + + + +
+
+ ))} +
+ +
+ {runtimeReadbackImplementationReview.operator_actions.map(action => ( +
+
+ + {action.display_name} + + +
+ + {action.operator_instruction} + +
+ + +
+
+ ))} +
+
+
diff --git a/apps/web/src/lib/api-client.ts b/apps/web/src/lib/api-client.ts index 91faa0086..4ba241af0 100644 --- a/apps/web/src/lib/api-client.ts +++ b/apps/web/src/lib/api-client.ts @@ -445,6 +445,11 @@ export const apiClient = { return handleResponse(res) }, + async getAiAgentRuntimeReadbackImplementationReview() { + const res = await fetch(`${API_BASE_URL}/agents/agent-runtime-readback-implementation-review`) + return handleResponse(res) + }, + async getAiAgentOwnerApprovedFixtureDryRun() { const res = await fetch(`${API_BASE_URL}/agents/agent-owner-approved-fixture-dry-run`) return handleResponse(res) @@ -3977,6 +3982,159 @@ export interface AiAgentRuntimeReadbackApprovalPackageSnapshot { } } +export interface AiAgentRuntimeReadbackImplementationReviewSnapshot { + schema_version: 'ai_agent_runtime_readback_implementation_review_v1' + generated_at: string + program_status: { + overall_completion_percent: number + current_priority: 'P0' | 'P1' | 'P2' | 'P3' + current_task_id: 'P2-110' + next_task_id: 'P2-111' + read_only_mode: true + runtime_authority: 'runtime_readback_implementation_review_only_no_live_read_or_write' + status_note: string + } + source_refs: string[] + prior_approval_package: { + source_schema_version: 'ai_agent_runtime_readback_approval_package_v1' + readback_at: string + approval_packet_count: number + canonical_readback_plan_count: number + rollback_drill_lane_count: number + telegram_failure_receipt_gate_count: number + operator_action_count: number + approval_required_packet_count: number + blocked_total_count: number + owner_approval_received_count: number + runtime_readback_execution_count: number + telegram_failure_receipt_send_count: number + bot_api_call_count: number + rollback_work_item_write_count: number + production_write_count: number + secret_read_count: number + destructive_operation_count: number + readiness_note: string + } + implementation_review_truth: { + p2_109_approval_package_loaded: true + implementation_review_ready: true + adapter_contract_ready: true + verifier_contract_ready: true + redaction_contract_ready: true + telemetry_receipt_contract_ready: true + owner_review_required_before_runtime: true + canonical_runtime_readback_enabled: false + live_query_enabled: false + runtime_result_capture_write_enabled: false + runtime_score_write_enabled: false + runtime_learning_write_enabled: false + playbook_trust_write_enabled: false + reviewer_queue_write_enabled: false + gateway_queue_write_enabled: false + telegram_failure_receipt_send_enabled: false + bot_api_call_enabled: false + rollback_work_item_write_enabled: false + production_write_enabled: false + secret_read_enabled: false + destructive_operation_enabled: false + owner_approval_received_count: number + runtime_readback_execution_count: number + live_query_count_24h: number + result_capture_write_count_24h: number + score_write_count_24h: number + learning_write_count_24h: number + playbook_trust_write_count_24h: number + reviewer_queue_write_count_24h: number + gateway_queue_write_count_24h: number + telegram_failure_receipt_send_count_24h: number + bot_api_call_count_24h: number + rollback_work_item_write_count_24h: number + production_write_count_24h: number + secret_read_count_24h: number + destructive_operation_count_24h: number + truth_note: string + } + implementation_review_cards: Array<{ + card_id: string + display_name: string + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + status: 'ready_for_owner_review' | 'approval_required' | 'blocked_by_policy' + risk_tier: 'high' | 'critical' + implementation_surface: string + required_interfaces: string[] + blocked_runtime_actions: string[] + review_guidance: string + owner_review_required: true + no_write_mode: true + evidence_hash: string + }> + no_write_verifier_checks: Array<{ + check_id: string + display_name: string + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + status: 'ready' | 'blocked_by_policy' + check_scope: string + required_evidence: string[] + failure_if_missing: string + live_query_enabled: false + runtime_write_allowed: false + evidence_hash: string + }> + implementation_blockers: Array<{ + blocker_id: string + display_name: string + severity: 'high' | 'critical' + status: 'blocking_runtime' | 'blocking_live_read' | 'blocking_queue_write' | 'blocking_notification' | 'blocking_production_write' + blocked_until: string + blocked_action: string + required_resolution: string + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + evidence_hash: string + }> + operator_actions: Array<{ + action_id: string + action_type: 'review_implementation_contract' | 'validate_adapter_mapping' | 'validate_zero_write_counters' | 'review_failure_receipt_mapping' | 'reject_or_promote' + display_name: string + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + operator_instruction: string + runtime_write_allowed: false + }> + display_redaction_contract: { + redaction_required: true + frontend_display_policy: string + raw_prompt_display_allowed: false + private_reasoning_display_allowed: false + secret_value_display_allowed: false + raw_telegram_payload_display_allowed: false + work_window_transcript_display_allowed: false + } + rollups: { + implementation_review_card_count: number + no_write_verifier_check_count: number + implementation_blocker_count: number + operator_action_count: number + approval_required_card_count: number + blocked_card_count: number + blocked_verifier_check_count: number + critical_blocker_count: number + owner_approval_received_count: number + runtime_readback_execution_count: number + live_query_count: number + result_capture_write_count: number + score_write_count: number + learning_write_count: number + playbook_trust_write_count: number + reviewer_queue_write_count: number + gateway_queue_write_count: number + telegram_failure_receipt_send_count: number + bot_api_call_count: number + rollback_work_item_write_count: number + production_write_count: number + secret_read_count: number + destructive_operation_count: number + } +} + export interface AiAgentOwnerApprovedFixtureDryRunSnapshot { schema_version: 'ai_agent_owner_approved_fixture_dry_run_v1' generated_at: string diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index 46859fe59..250f0fa68 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -1,3 +1,25 @@ +## 2026-06-13|P2-110 Runtime readback implementation review 本地完成 + +**背景**:P2-109 已把 runtime readback 拆成批准包、canonical readback plan、rollback drill 與 Telegram failure receipt gate;但仍缺少「批准包要如何被實作審查」的 no-write 介面、verifier、阻塞原因與人工下一步。 + +**完成內容**: +- 新增 `ai_agent_runtime_readback_implementation_review_v1` schema、committed snapshot、loader 與 API endpoint `GET /api/v1/agents/agent-runtime-readback-implementation-review`。 +- P2-110 snapshot 固定 5 張 implementation review card、5 個 no-write verifier check、5 個 implementation blocker 與 5 個 operator action。 +- Governance automation inventory 頁新增 P2-110 區塊,顯示 P2-110 進度 `100%`、實作卡 `5`、no-write verifier `5`、阻塞項 `5`、操作選項 `5`、需批准 `2`、阻擋總數 `7`、關鍵阻塞 `2`、owner approval received `0`、runtime readback execution `0`、live query `0`、Telegram failure receipt send `0`、rollback work item write `0` 與 live writes `0`。 +- 更新 MASTER §3.2 / §5、`docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md` 與 `docs/ai/AI_AGENT_INTERACTION_LEARNING_PROOF_2026-06-11.md`,下一步改為 `P2-111` report live delivery approval package。 + +**本地驗證**: +- JSON parse:P2-110 schema / snapshot、`zh-TW.json`、`en.json` 通過。 +- API/service pytest:P2-110 目標組 `9 passed`。 +- Web typecheck:`pnpm --filter @awoooi/web typecheck` 通過。 + +**安全邊界**: +- P2-110 仍是只讀實作審查;不讀 canonical runtime target、不做 live query、不寫 reviewer queue、不寫 rollback work item、不寫 score、不寫 result capture、不寫 learning、不更新 PlayBook trust、不寫 KM、不 runtime append LOGBOOK、不寫 audit DB、不寫 timeline、不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不啟動 runtime worker、不讀 secret、不執行 destructive action。 +- 正式部署、production API readback 與 desktop/mobile browser smoke 尚待 Gitea CD 完成後補記;不得把本地完成視為 production 完成。 + +**下一步**: +- 推送 feature commit 到 Gitea main,等待 deploy marker 後驗證 `GET /api/v1/agents/agent-runtime-readback-implementation-review` 與 `/zh-TW/governance?tab=automation-inventory` desktop/mobile。 + ## 2026-06-13|P2-109 Runtime readback approval package 本地完成與正式驗證 **背景**:P2-107 已把 owner-approved result capture readback / promotion readiness 固定成只讀證據,P2-108 已補日週月報與 Agent 工作狀態總覽;但下一步仍不能直接讀 canonical runtime target 或寫入 runtime。P2-109 先把「批准後要如何進入 runtime readback」拆成可審查批准包、canonical readback plan、rollback drill 與 Telegram failure receipt gate。 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 0055ee84b..6c3758b19 100644 --- a/docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md +++ b/docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md @@ -12,7 +12,7 @@ | Nemotron 實際整合應用 | 30% | 完整回放前仍被關卡擋下 | `blocked_needs_evidence`,下一關是 `refresh_source_evidence_then_5_record_smoke_only` | | 工具 / 服務 / 套件 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 主動溝通、學習與成長證據 | 100% | P2-401A 已完成只讀 contract;P2-403A 已完成互動 / 接手 / 學習 / 成長證據面板;P2-403B 已完成 AgentSession / Redis Streams live read model gate;P2-403C 已完成 Redis Streams consumer group dry-run、handoff envelope、ack / dead-letter / replay gate;P2-403D 已完成 learning writeback approval package;P2-403E 已完成 Telegram receipt approval package;P2-403F 已完成 owner-approved learning dry-run preview、人工操作選項與 fixture-only dry-run 總包;P2-403G 已完成 runtime write gate review;P2-403H 已完成 post-write verifier implementation package;P2-403I 已完成 runtime verifier evidence implementation review;P2-403J 已完成報表真相 / 告警有效性 / 日週月報 / Agent 工作量 / 圖表化報告 / AI 建議 / 風險自動化政策審查;P2-403K / L / M / N 已把 SRE 戰情室路由、報表派送啟動前閘門、no-write dry-run 與 fixture/readback/verifier dry-run 固定;P2-404 已完成 runtime worker shadow / no-write evidence;P2-101 已完成操作類別權限模型;P2-102 已完成 13 類候選操作 dry-run 證據;P2-103 已完成任務結果稽核軌跡;P2-104 已完成 matched PlayBook 學習缺口回查;P2-105 已完成 critic / reviewer 評分與 result capture 契約;P2-106 已完成 owner-approved result capture dry-run;P2-107 已完成 owner-approved result capture readback / promotion readiness;P2-108 已完成日週月報與 Agent 工作狀態總覽;P2-109 已完成 runtime readback approval package,固定 5 個批准包、4 個 canonical readback plan、4 條 rollback drill、4 個 Telegram failure receipt gate 與 5 個 operator action。runtime worker、DB migration、production Redis consumer group、canonical runtime readback、runtime score、result capture write、Telegram 實發、delivery receipt E2E、report delivery、reviewer queue write、Gateway queue write、AI analysis runtime、中低風險 auto worker、KM / LOGBOOK / audit DB / timeline / PlayBook trust 寫入、SDK / 付費服務仍未開 gate | `ai_agent_communication_learning_contract_v1`、`ai_agent_interaction_learning_proof_v1`、`ai_agent_operation_permission_model_v1`、`ai_agent_candidate_operation_dry_run_evidence_v1`、`ai_agent_task_result_audit_trail_v1`、`ai_agent_matched_playbook_learning_gap_v1`、`ai_agent_critic_reviewer_result_capture_v1`、`ai_agent_owner_approved_result_capture_dry_run_v1`、`ai_agent_owner_approved_result_capture_readback_v1`、`ai_agent_report_status_board_v1`、`ai_agent_runtime_readback_approval_package_v1`、`GET /api/v1/agents/agent-operation-permission-model`、`GET /api/v1/agents/agent-candidate-operation-dry-run-evidence`、`GET /api/v1/agents/agent-task-result-audit-trail`、`GET /api/v1/agents/agent-matched-playbook-learning-gap`、`GET /api/v1/agents/agent-critic-reviewer-result-capture`、`GET /api/v1/agents/agent-owner-approved-result-capture-dry-run`、`GET /api/v1/agents/agent-owner-approved-result-capture-readback`、`GET /api/v1/agents/agent-report-status-board`、`GET /api/v1/agents/agent-runtime-readback-approval-package`、`/zh-TW/governance?tab=automation-inventory`、MASTER §3.2.1b / §3.2.1d / §3.4.3 | +| OpenClaw / Hermes / NemoTron 主動溝通、學習與成長證據 | 100% | P2-401A 已完成只讀 contract;P2-403A 已完成互動 / 接手 / 學習 / 成長證據面板;P2-403B 已完成 AgentSession / Redis Streams live read model gate;P2-403C 已完成 Redis Streams consumer group dry-run、handoff envelope、ack / dead-letter / replay gate;P2-403D 已完成 learning writeback approval package;P2-403E 已完成 Telegram receipt approval package;P2-403F 已完成 owner-approved learning dry-run preview、人工操作選項與 fixture-only dry-run 總包;P2-403G 已完成 runtime write gate review;P2-403H 已完成 post-write verifier implementation package;P2-403I 已完成 runtime verifier evidence implementation review;P2-403J 已完成報表真相 / 告警有效性 / 日週月報 / Agent 工作量 / 圖表化報告 / AI 建議 / 風險自動化政策審查;P2-403K / L / M / N 已把 SRE 戰情室路由、報表派送啟動前閘門、no-write dry-run 與 fixture/readback/verifier dry-run 固定;P2-404 已完成 runtime worker shadow / no-write evidence;P2-101 已完成操作類別權限模型;P2-102 已完成 13 類候選操作 dry-run 證據;P2-103 已完成任務結果稽核軌跡;P2-104 已完成 matched PlayBook 學習缺口回查;P2-105 已完成 critic / reviewer 評分與 result capture 契約;P2-106 已完成 owner-approved result capture dry-run;P2-107 已完成 owner-approved result capture readback / promotion readiness;P2-108 已完成日週月報與 Agent 工作狀態總覽;P2-109 已完成 runtime readback approval package;P2-110 本地完成 runtime readback implementation review,固定 5 張實作卡、5 個 no-write verifier、5 個阻塞項與 5 個 operator action。runtime worker、DB migration、production Redis consumer group、canonical runtime readback、live query、runtime score、result capture write、Telegram 實發、delivery receipt E2E、report delivery、reviewer queue write、Gateway queue write、AI analysis runtime、中低風險 auto worker、KM / LOGBOOK / audit DB / timeline / PlayBook trust 寫入、SDK / 付費服務仍未開 gate | `ai_agent_communication_learning_contract_v1`、`ai_agent_interaction_learning_proof_v1`、`ai_agent_operation_permission_model_v1`、`ai_agent_candidate_operation_dry_run_evidence_v1`、`ai_agent_task_result_audit_trail_v1`、`ai_agent_matched_playbook_learning_gap_v1`、`ai_agent_critic_reviewer_result_capture_v1`、`ai_agent_owner_approved_result_capture_dry_run_v1`、`ai_agent_owner_approved_result_capture_readback_v1`、`ai_agent_report_status_board_v1`、`ai_agent_runtime_readback_approval_package_v1`、`ai_agent_runtime_readback_implementation_review_v1`、`GET /api/v1/agents/agent-operation-permission-model`、`GET /api/v1/agents/agent-candidate-operation-dry-run-evidence`、`GET /api/v1/agents/agent-task-result-audit-trail`、`GET /api/v1/agents/agent-matched-playbook-learning-gap`、`GET /api/v1/agents/agent-critic-reviewer-result-capture`、`GET /api/v1/agents/agent-owner-approved-result-capture-dry-run`、`GET /api/v1/agents/agent-owner-approved-result-capture-readback`、`GET /api/v1/agents/agent-report-status-board`、`GET /api/v1/agents/agent-runtime-readback-approval-package`、`GET /api/v1/agents/agent-runtime-readback-implementation-review`、`/zh-TW/governance?tab=automation-inventory`、MASTER §3.2.1b / §3.2.1d / §3.4.3 | | AI Agent 主動營運委派與版本生命週期 | 100% | P2-402A / P2-402B / P2-402C / P2-402D / P2-402E / P2-402F / P2-402G 已完成;已建立 repo-only 版本新鮮度快照、工具採用批准包、Telegram action-required digest policy、Gitea PR 草案 lane、host / K3s / stateful 版本只讀盤點、API 與 governance UI。定期排程、外部版本查詢、工具安裝、CI 變更、套件升級、主機更新、container pull、實際 PR creation、auto merge、Telegram 實發、SSH、kubectl、重啟仍未開 gate | `ai_agent_proactive_operations_contract_v1`、`ai_agent_version_freshness_snapshot_v1`、`ai_agent_tool_adoption_approval_package_v1`、`ai_agent_telegram_action_required_digest_policy_v1`、`ai_agent_gitea_pr_draft_lane_v1`、`ai_agent_host_stateful_version_inventory_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`、`GET /api/v1/agents/agent-telegram-action-required-digest-policy`、`GET /api/v1/agents/agent-gitea-pr-draft-lane`、`GET /api/v1/agents/agent-host-stateful-version-inventory`、`/zh-TW/governance?tab=automation-inventory`、MASTER §3.2.1c | | 本工作清單與分析報告 | 100% | 已完成 | 本 MD 文件 | @@ -20,9 +20,9 @@ AI Agent 自動化工作包目前完成度:**94%**。本工作清單文件本 三 Agent 佈建布局目前完成度:**45%**。第一波已完成只讀 schema / snapshot / API / 測試 / 報告,第二波已接入治理頁自動化盤點 UI;正式 runtime 佈署、Telegram E2E 發送與 AgentSession 工作流仍需逐項 gate。 -三 Agent 主動溝通、學習與成長證據目前完成度:**100%**。已完成只讀契約、互動 / 接手 / 學習 / 成長證據面板、P2-403B live read model gate、P2-403C Redis dry-run gate、P2-403D learning writeback approval package、P2-403E Telegram receipt approval package、P2-403F owner-approved learning dry-run preview、P2-403G runtime write gate review、P2-403H post-write verifier implementation package、P2-403I runtime verifier evidence implementation review、P2-403J 報表真相 / 告警有效性 / 日週月報 / Agent 工作量 / 圖表化報告 / AI 建議 / 風險自動化政策審查、P2-403K/L/M/N 報表與 SRE 戰情室 dry-run 鏈、P2-404 runtime worker shadow / no-write execution evidence gate、P2-101 操作類別權限模型、P2-102 候選操作 dry-run 證據、P2-103 任務結果稽核軌跡、P2-104 matched PlayBook 學習缺口回查、P2-105 critic / reviewer 評分與 result capture 契約、P2-106 owner-approved result capture dry-run、P2-107 owner-approved result capture readback / promotion readiness、P2-108 日週月報與 Agent 工作狀態總覽,以及 P2-109 runtime readback approval package。目前 live AgentSession、Agent message、handoff、canonical runtime readback、runtime score、result capture write、learning write、Telegram receipt、Gateway queue write、reviewer queue write、runtime verifier execution、report delivery、AI analysis runtime、中低風險 auto worker、Telegram 實發、shadow worker live、delivery receipt E2E、KM / LOGBOOK / audit DB / timeline / PlayBook trust runtime 寫入仍全部為 `0`。P2-109 已固定 5 個批准包、4 個 canonical readback plan、4 條 rollback drill、4 個 Telegram failure receipt gate 與 5 個 operator action;真正下一步是 `P2-110`。 +三 Agent 主動溝通、學習與成長證據目前完成度:**100%**。已完成只讀契約、互動 / 接手 / 學習 / 成長證據面板、P2-403B live read model gate、P2-403C Redis dry-run gate、P2-403D learning writeback approval package、P2-403E Telegram receipt approval package、P2-403F owner-approved learning dry-run preview、P2-403G runtime write gate review、P2-403H post-write verifier implementation package、P2-403I runtime verifier evidence implementation review、P2-403J 報表真相 / 告警有效性 / 日週月報 / Agent 工作量 / 圖表化報告 / AI 建議 / 風險自動化政策審查、P2-403K/L/M/N 報表與 SRE 戰情室 dry-run 鏈、P2-404 runtime worker shadow / no-write execution evidence gate、P2-101 操作類別權限模型、P2-102 候選操作 dry-run 證據、P2-103 任務結果稽核軌跡、P2-104 matched PlayBook 學習缺口回查、P2-105 critic / reviewer 評分與 result capture 契約、P2-106 owner-approved result capture dry-run、P2-107 owner-approved result capture readback / promotion readiness、P2-108 日週月報與 Agent 工作狀態總覽、P2-109 runtime readback approval package,以及 P2-110 runtime readback implementation review 本地切片。目前 live AgentSession、Agent message、handoff、canonical runtime readback、live query、runtime score、result capture write、learning write、Telegram receipt、Gateway queue write、reviewer queue write、runtime verifier execution、report delivery、AI analysis runtime、中低風險 auto worker、Telegram 實發、shadow worker live、delivery receipt E2E、KM / LOGBOOK / audit DB / timeline / PlayBook trust runtime 寫入仍全部為 `0`。P2-110 已固定 5 張實作卡、5 個 no-write verifier、5 個阻塞項與 5 個 operator action;真正下一步是 `P2-111`。 -AI Agent 主動營運委派與版本生命週期目前完成度:**100%**。已完成 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、`P2-402E` Gitea PR 草案 lane、`P2-402F` host OS / K3s / stateful services 版本只讀盤點,以及 `P2-402G` governance UI 顯示可委派能力;`P2-403A` 到 `P2-109` 已補互動、學習證據面、live read model gate、Redis dry-run gate、learning writeback approval package、Telegram receipt approval package、owner-approved learning dry-run preview、runtime write gate review、post-write verifier package、runtime verifier evidence review、報表真相、TG 戰情室收斂、日週月報、Agent 工作量、圖表化報告、風險自動化政策、報表 runtime 啟動前閘門、no-write dry-run 證據包、fixture/readback/verifier dry-run 證據包、shadow/no-write execution gate、操作類別權限模型、13 類候選操作 dry-run 證據、任務結果稽核軌跡、matched PlayBook 學習缺口、critic / reviewer result capture、owner-approved result capture dry-run、owner-approved result capture readback / promotion readiness、Agent report status board 與 runtime readback approval package。下一步是 `P2-110`;外部 registry / package source / host probe / SSH / kubectl / 工具安裝 / CI 變更 / 實際 PR creation / Telegram 實發與 learning write 仍需 gate。 +AI Agent 主動營運委派與版本生命週期目前完成度:**100%**。已完成 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、`P2-402E` Gitea PR 草案 lane、`P2-402F` host OS / K3s / stateful services 版本只讀盤點,以及 `P2-402G` governance UI 顯示可委派能力;`P2-403A` 到 `P2-110` 已補互動、學習證據面、live read model gate、Redis dry-run gate、learning writeback approval package、Telegram receipt approval package、owner-approved learning dry-run preview、runtime write gate review、post-write verifier package、runtime verifier evidence review、報表真相、TG 戰情室收斂、日週月報、Agent 工作量、圖表化報告、風險自動化政策、報表 runtime 啟動前閘門、no-write dry-run 證據包、fixture/readback/verifier dry-run 證據包、shadow/no-write execution gate、操作類別權限模型、13 類候選操作 dry-run 證據、任務結果稽核軌跡、matched PlayBook 學習缺口、critic / reviewer result capture、owner-approved result capture dry-run、owner-approved result capture readback / promotion readiness、Agent report status board、runtime readback approval package 與 runtime readback implementation review。下一步是 `P2-111`;外部 registry / package source / host probe / SSH / kubectl / 工具安裝 / CI 變更 / 實際 PR creation / Telegram 實發與 learning write 仍需 gate。 完成度計算模型: diff --git a/docs/ai/AI_AGENT_INTERACTION_LEARNING_PROOF_2026-06-11.md b/docs/ai/AI_AGENT_INTERACTION_LEARNING_PROOF_2026-06-11.md index 2a3f0390d..794d6fb8d 100644 --- a/docs/ai/AI_AGENT_INTERACTION_LEARNING_PROOF_2026-06-11.md +++ b/docs/ai/AI_AGENT_INTERACTION_LEARNING_PROOF_2026-06-11.md @@ -178,19 +178,21 @@ | `docs/evaluations/ai_agent_report_status_board_2026-06-13.json` | P2-108 committed snapshot,完成度 `100%`,日報 / 週報 / 月報 `100%` 可見、3 個 Agent 狀態報告、3 張圖表、4 張統帥問答卡;live delivery / Telegram send / runtime work / auto optimization 全為 `0` | | `docs/schemas/ai_agent_runtime_readback_approval_package_v1.schema.json` | P2-109 runtime readback approval package schema;強制 canonical runtime readback、result capture write、score write、learning write、PlayBook trust write、reviewer queue write、Gateway queue、Telegram failure receipt、Bot API、rollback work item、production write、secret read 與 destructive action 維持未授權 | | `docs/evaluations/ai_agent_runtime_readback_approval_package_2026-06-13.json` | P2-109 committed snapshot,完成度 `100%`,5 個批准包、4 個 canonical readback plan、4 條 rollback drill、4 個 Telegram failure receipt gate、5 個 operator action;runtime readback execution、owner approval received 與所有 live write / send counts 全為 `0` | +| `docs/schemas/ai_agent_runtime_readback_implementation_review_v1.schema.json` | P2-110 runtime readback implementation review schema;強制 canonical runtime readback、live query、runtime readback execution、owner approval received、reviewer queue write、Gateway queue、Telegram failure receipt、Bot API、rollback work item、production write、secret read 與 destructive action 維持未授權 | +| `docs/evaluations/ai_agent_runtime_readback_implementation_review_2026-06-13.json` | P2-110 committed snapshot,完成度 `100%`,5 張 implementation review card、5 個 no-write verifier check、5 個 implementation blocker、5 個 operator action;live query、runtime readback execution、owner approval received 與所有 live write / send counts 全為 `0` | | `GET /api/v1/agents/agent-critic-reviewer-result-capture` | 只讀 API;不寫 score、不寫 result capture、不寫 learning、不更新 PlayBook trust、不送 Telegram | | `apps/api/src/services/ai_agent_interaction_learning_proof.py` | 只讀 loader 與安全驗證 | | `apps/api/src/services/ai_agent_live_read_model_gate.py` | P2-403B 只讀 loader;拒絕 live DB query、Redis consumer、unsafe fields、Telegram 與 writeback | | `GET /api/v1/agents/agent-interaction-learning-proof` | 只讀 API,不啟動 worker、不碰 Redis / DB runtime、不發 Telegram | | `GET /api/v1/agents/agent-live-read-model-gate` | 只讀 API,不連 DB、不讀寫 Redis、不發 Telegram | -| governance UI | 新增證據階梯、目前真相、P2-403B live read gate、P2-403C Redis dry-run gate、P2-403D learning writeback approval package、P2-403E Telegram receipt approval package、P2-403F owner-approved learning dry-run / fixture dry-run、P2-403G runtime write gate review、P2-403H post-write verifier package、P2-403I runtime verifier evidence review、P2-403J 報表真相 / 日週月報 / Agent 工作量 / 圖表 / AI 建議、P2-108 日週月報與 Agent 工作狀態總覽、P2-403L 報表 runtime readiness、P2-403M no-write dry-run、P2-403N fixture readback、P2-404 shadow gate、P2-101 operation permission model、P2-102 candidate dry-run evidence、P2-103 task result audit trail、P2-104 matched PlayBook learning gap、P2-105 critic / reviewer result capture、P2-106 owner-approved result capture dry-run、P2-107 owner-approved result capture readback / promotion readiness、P2-109 runtime readback approval package、Agent lane、可觀測訊號、runtime gates、前端 redaction | +| governance UI | 新增證據階梯、目前真相、P2-403B live read gate、P2-403C Redis dry-run gate、P2-403D learning writeback approval package、P2-403E Telegram receipt approval package、P2-403F owner-approved learning dry-run / fixture dry-run、P2-403G runtime write gate review、P2-403H post-write verifier package、P2-403I runtime verifier evidence review、P2-403J 報表真相 / 日週月報 / Agent 工作量 / 圖表 / AI 建議、P2-108 日週月報與 Agent 工作狀態總覽、P2-403L 報表 runtime readiness、P2-403M no-write dry-run、P2-403N fixture readback、P2-404 shadow gate、P2-101 operation permission model、P2-102 candidate dry-run evidence、P2-103 task result audit trail、P2-104 matched PlayBook learning gap、P2-105 critic / reviewer result capture、P2-106 owner-approved result capture dry-run、P2-107 owner-approved result capture readback / promotion readiness、P2-109 runtime readback approval package、P2-110 runtime readback implementation review、Agent lane、可觀測訊號、runtime gates、前端 redaction | ## 5. 後續優先順序 | 優先 | ID | 工作 | gate | |---:|---|---|---| -| 1 | P2-110 | runtime readback implementation review | 以 P2-109 批准包、canonical readback plan、rollback drill 與 Telegram failure receipt gate 產生下一關 no-write implementation review | -| 2 | P2-111 | report live delivery approval package | 以 P2-108 report status board 與 P2-109 Telegram failure receipt gate 產生下一關派送批准包,仍需維持 no live send / no live write | +| 1 | P2-111 | report live delivery approval package | 以 P2-108 report status board、P2-109 Telegram failure receipt gate 與 P2-110 no-write implementation review 產生下一關派送批准包,仍需維持 no live send / no live write | +| 2 | P2-112 | runtime readback fixture approval | 以 P2-110 implementation review 的 adapter contract / verifier check / blocker 產生下一關 fixture-only runtime readback approval,不讀 canonical runtime target | ## 6. 紅線 diff --git a/docs/evaluations/ai_agent_runtime_readback_implementation_review_2026-06-13.json b/docs/evaluations/ai_agent_runtime_readback_implementation_review_2026-06-13.json new file mode 100644 index 000000000..898feff0a --- /dev/null +++ b/docs/evaluations/ai_agent_runtime_readback_implementation_review_2026-06-13.json @@ -0,0 +1,415 @@ +{ + "schema_version": "ai_agent_runtime_readback_implementation_review_v1", + "generated_at": "2026-06-13T16:26:00+08:00", + "program_status": { + "overall_completion_percent": 100, + "current_priority": "P2", + "current_task_id": "P2-110", + "next_task_id": "P2-111", + "read_only_mode": true, + "runtime_authority": "runtime_readback_implementation_review_only_no_live_read_or_write", + "status_note": "P2-110 承接 P2-109 runtime readback 批准包,將 adapter contract、no-write verifier、阻塞原因與人工審查動作固定為可審查清單;本快照不讀 canonical runtime target、不寫任何 production 或 Telegram 收據。" + }, + "source_refs": [ + "docs/evaluations/ai_agent_runtime_readback_approval_package_2026-06-13.json", + "docs/schemas/ai_agent_runtime_readback_approval_package_v1.schema.json", + "docs/evaluations/ai_agent_owner_approved_result_capture_readback_2026-06-13.json", + "docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md" + ], + "prior_approval_package": { + "source_schema_version": "ai_agent_runtime_readback_approval_package_v1", + "readback_at": "2026-06-13T15:12:00+08:00", + "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, + "readiness_note": "P2-109 已把批准包、canonical readback plan、rollback drill 與 Telegram 失敗收據 gate 固定為 owner review 層;P2-110 只審查實作是否能在 no-write 模式接上。" + }, + "implementation_review_truth": { + "p2_109_approval_package_loaded": true, + "implementation_review_ready": true, + "adapter_contract_ready": true, + "verifier_contract_ready": true, + "redaction_contract_ready": true, + "telemetry_receipt_contract_ready": true, + "owner_review_required_before_runtime": true, + "canonical_runtime_readback_enabled": false, + "live_query_enabled": false, + "runtime_result_capture_write_enabled": false, + "runtime_score_write_enabled": false, + "runtime_learning_write_enabled": false, + "playbook_trust_write_enabled": false, + "reviewer_queue_write_enabled": false, + "gateway_queue_write_enabled": false, + "telegram_failure_receipt_send_enabled": false, + "bot_api_call_enabled": false, + "rollback_work_item_write_enabled": false, + "production_write_enabled": false, + "secret_read_enabled": false, + "destructive_operation_enabled": false, + "owner_approval_received_count": 0, + "runtime_readback_execution_count": 0, + "live_query_count_24h": 0, + "result_capture_write_count_24h": 0, + "score_write_count_24h": 0, + "learning_write_count_24h": 0, + "playbook_trust_write_count_24h": 0, + "reviewer_queue_write_count_24h": 0, + "gateway_queue_write_count_24h": 0, + "telegram_failure_receipt_send_count_24h": 0, + "bot_api_call_count_24h": 0, + "rollback_work_item_write_count_24h": 0, + "production_write_count_24h": 0, + "secret_read_count_24h": 0, + "destructive_operation_count_24h": 0, + "truth_note": "實作審查已可進行,但 canonical runtime readback、live query、result/score/learning/trust write、queue write、Telegram 失敗收據、Bot API、rollback work item 與 production write 全部仍為 0。" + }, + "implementation_review_cards": [ + { + "card_id": "runtime_readback_adapter_contract", + "display_name": "runtime readback adapter contract", + "owner_agent": "openclaw", + "status": "ready_for_owner_review", + "risk_tier": "high", + "implementation_surface": "api_service_adapter", + "required_interfaces": [ + "incident_id", + "approval_id", + "readback_plan_id", + "redacted_evidence_refs", + "owner_acceptance_record" + ], + "blocked_runtime_actions": [ + "canonical_runtime_readback", + "live_query", + "result_capture_write" + ], + "review_guidance": "審查 adapter 欄位是否能映射 P2-109 canonical readback plan;未驗收前只能對照 committed snapshot,不讀正式 runtime target。", + "owner_review_required": true, + "no_write_mode": true, + "evidence_hash": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "card_id": "result_capture_writer_noop_contract", + "display_name": "result capture writer noop contract", + "owner_agent": "openclaw", + "status": "approval_required", + "risk_tier": "critical", + "implementation_surface": "result_capture_writer", + "required_interfaces": [ + "capture_row_template", + "status_chain_digest", + "verifier_receipt_ref", + "rollback_lane_id" + ], + "blocked_runtime_actions": [ + "result_capture_write", + "reviewer_queue_write", + "gateway_queue_write" + ], + "review_guidance": "審查 writer noop 是否完整保留即將寫入的欄位與 rollback 參照;沒有 owner acceptance 不得建立任何 runtime row。", + "owner_review_required": true, + "no_write_mode": true, + "evidence_hash": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "card_id": "critic_reviewer_score_noop_contract", + "display_name": "critic reviewer score noop contract", + "owner_agent": "nemotron", + "status": "approval_required", + "risk_tier": "high", + "implementation_surface": "critic_reviewer_score", + "required_interfaces": [ + "score_fixture_id", + "expected_score", + "reviewer_delta", + "promotion_decision", + "negative_learning_lane" + ], + "blocked_runtime_actions": [ + "score_write", + "learning_write", + "playbook_trust_write" + ], + "review_guidance": "審查評分 fixture 與負向學習 lane 是否能說明 approved 後仍未修復的原因;不得寫入分數或調整 PlayBook trust。", + "owner_review_required": true, + "no_write_mode": true, + "evidence_hash": "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "card_id": "telegram_failure_receipt_adapter_contract", + "display_name": "Telegram failure receipt adapter contract", + "owner_agent": "hermes", + "status": "ready_for_owner_review", + "risk_tier": "high", + "implementation_surface": "telegram_failure_receipt", + "required_interfaces": [ + "war_room_route_id", + "dedupe_fingerprint", + "failure_reason", + "next_manual_action", + "redacted_payload_ref" + ], + "blocked_runtime_actions": [ + "telegram_failure_receipt_send", + "bot_api_call", + "gateway_queue_write" + ], + "review_guidance": "審查失敗收據是否能說清楚批准後沒有自動化的原因與下一步;未開 gate 前不得送 Telegram 或呼叫 Bot API。", + "owner_review_required": true, + "no_write_mode": true, + "evidence_hash": "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + }, + { + "card_id": "rollback_work_item_noop_contract", + "display_name": "rollback work item noop contract", + "owner_agent": "hermes", + "status": "blocked_by_policy", + "risk_tier": "critical", + "implementation_surface": "rollback_work_item", + "required_interfaces": [ + "rollback_owner", + "maintenance_window", + "validation_plan", + "post_write_verifier_ref" + ], + "blocked_runtime_actions": [ + "rollback_work_item_write", + "production_write", + "destructive_operation" + ], + "review_guidance": "rollback work item 仍停在 noop contract;沒有 owner acceptance 與 maintenance window 前不得建立或更新任何 rollback 任務。", + "owner_review_required": true, + "no_write_mode": true, + "evidence_hash": "sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + } + ], + "no_write_verifier_checks": [ + { + "check_id": "schema_field_parity_check", + "display_name": "schema field parity check", + "owner_agent": "openclaw", + "status": "ready", + "check_scope": "adapter_fields_match_p2_109", + "required_evidence": [ + "approval_packet_templates", + "canonical_readback_plans", + "implementation_review_cards" + ], + "failure_if_missing": "runtime readback 實作缺少欄位映射時,批准後仍無法判斷要讀什麼、寫什麼或回滾什麼。", + "live_query_enabled": false, + "runtime_write_allowed": false, + "evidence_hash": "sha256:1111111111111111111111111111111111111111111111111111111111111111" + }, + { + "check_id": "redaction_payload_check", + "display_name": "redaction payload check", + "owner_agent": "hermes", + "status": "ready", + "check_scope": "public_payload_redaction", + "required_evidence": [ + "display_redaction_contract", + "redacted_evidence_refs", + "payload_visibility_policy" + ], + "failure_if_missing": "失敗收據或 operator console 可能外露內部協作內容、私密推理、secret 或原始 Telegram payload。", + "live_query_enabled": false, + "runtime_write_allowed": false, + "evidence_hash": "sha256:2222222222222222222222222222222222222222222222222222222222222222" + }, + { + "check_id": "zero_write_counter_check", + "display_name": "zero write counter check", + "owner_agent": "nemotron", + "status": "ready", + "check_scope": "runtime_counter_guard", + "required_evidence": [ + "live_query_count_24h", + "result_capture_write_count_24h", + "telegram_failure_receipt_send_count_24h", + "production_write_count_24h" + ], + "failure_if_missing": "只讀審查若沒有 0 計數保護,容易把 UI 可見誤判成 runtime 已接通。", + "live_query_enabled": false, + "runtime_write_allowed": false, + "evidence_hash": "sha256:3333333333333333333333333333333333333333333333333333333333333333" + }, + { + "check_id": "failure_receipt_route_check", + "display_name": "failure receipt route check", + "owner_agent": "hermes", + "status": "ready", + "check_scope": "sre_war_room_only_receipt", + "required_evidence": [ + "war_room_route_id", + "dedupe_fingerprint", + "blocked_legacy_routes" + ], + "failure_if_missing": "批准後沒有自動化時,operator 仍看不到原因、下一步與責任人;也可能被送到錯誤群組。", + "live_query_enabled": false, + "runtime_write_allowed": false, + "evidence_hash": "sha256:4444444444444444444444444444444444444444444444444444444444444444" + }, + { + "check_id": "rollback_reference_check", + "display_name": "rollback reference check", + "owner_agent": "openclaw", + "status": "blocked_by_policy", + "check_scope": "rollback_owner_and_window", + "required_evidence": [ + "rollback_owner", + "maintenance_window", + "validation_plan", + "owner_acceptance_record" + ], + "failure_if_missing": "沒有 rollback owner 與維護時窗時,不得讓 runtime writer 或 Telegram 收據暗示已可復原。", + "live_query_enabled": false, + "runtime_write_allowed": false, + "evidence_hash": "sha256:5555555555555555555555555555555555555555555555555555555555555555" + } + ], + "implementation_blockers": [ + { + "blocker_id": "owner_acceptance_missing", + "display_name": "owner acceptance record 尚未建立", + "severity": "critical", + "status": "blocking_runtime", + "blocked_until": "S4.9 / S4.10 owner response accepted", + "blocked_action": "runtime_readback_execution", + "required_resolution": "收到 owner acceptance record,且明確列出 incident scope、rollback owner、validation plan 與 redacted evidence refs。", + "owner_agent": "openclaw", + "evidence_hash": "sha256:6666666666666666666666666666666666666666666666666666666666666666" + }, + { + "blocker_id": "canonical_runtime_readback_disabled", + "display_name": "canonical runtime readback 尚未授權", + "severity": "high", + "status": "blocking_live_read", + "blocked_until": "runtime readback gate accepted", + "blocked_action": "canonical_runtime_readback", + "required_resolution": "先通過 adapter contract、redaction check 與 no-write verifier,再由 owner 決定是否開啟 live read。", + "owner_agent": "nemotron", + "evidence_hash": "sha256:7777777777777777777777777777777777777777777777777777777777777777" + }, + { + "blocker_id": "reviewer_queue_write_disabled", + "display_name": "reviewer queue write 尚未授權", + "severity": "high", + "status": "blocking_queue_write", + "blocked_until": "reviewer queue owner accepted", + "blocked_action": "reviewer_queue_write", + "required_resolution": "確認 queue payload、dedupe key、manual action 與 retry contract 後才能建立 reviewer queue write。", + "owner_agent": "openclaw", + "evidence_hash": "sha256:8888888888888888888888888888888888888888888888888888888888888888" + }, + { + "blocker_id": "telegram_receipt_send_disabled", + "display_name": "Telegram 失敗收據尚未授權", + "severity": "high", + "status": "blocking_notification", + "blocked_until": "AwoooI SRE 戰情室 route accepted", + "blocked_action": "telegram_failure_receipt_send", + "required_resolution": "確認只送 AwoooI SRE 戰情室、payload 已遮蔽、dedupe 生效且失敗才通知。", + "owner_agent": "hermes", + "evidence_hash": "sha256:9999999999999999999999999999999999999999999999999999999999999999" + }, + { + "blocker_id": "rollback_work_item_write_disabled", + "display_name": "rollback work item write 尚未授權", + "severity": "critical", + "status": "blocking_production_write", + "blocked_until": "rollback owner and maintenance window accepted", + "blocked_action": "rollback_work_item_write", + "required_resolution": "完成 rollback owner、維護時窗、驗證計畫與 post-write verifier 收據審查。", + "owner_agent": "hermes", + "evidence_hash": "sha256:abababababababababababababababababababababababababababababababab" + } + ], + "operator_actions": [ + { + "action_id": "review_implementation_contract", + "action_type": "review_implementation_contract", + "display_name": "審查實作契約", + "owner_agent": "openclaw", + "operator_instruction": "先看五張 implementation review card,確認每張卡都能說明要接哪個 adapter、缺哪個 owner decision、禁止哪些 runtime action。", + "runtime_write_allowed": false + }, + { + "action_id": "validate_adapter_mapping", + "action_type": "validate_adapter_mapping", + "display_name": "核對 adapter 欄位映射", + "owner_agent": "nemotron", + "operator_instruction": "核對 P2-109 canonical readback plan 與 P2-110 required_interfaces 是否一一對應,缺欄位就維持 blocked。", + "runtime_write_allowed": false + }, + { + "action_id": "validate_zero_write_counters", + "action_type": "validate_zero_write_counters", + "display_name": "確認 live / write / send 計數為 0", + "owner_agent": "openclaw", + "operator_instruction": "所有 live query、result/score/learning/trust write、queue write、Telegram send、Bot API 與 production write 必須保持 0。", + "runtime_write_allowed": false + }, + { + "action_id": "review_failure_receipt_mapping", + "action_type": "review_failure_receipt_mapping", + "display_name": "審查失敗收據映射", + "owner_agent": "hermes", + "operator_instruction": "確認批准後仍未自動化的情境能產出原因、下一步、責任人與 AwoooI SRE 戰情室 route,但不實際發送。", + "runtime_write_allowed": false + }, + { + "action_id": "reject_or_promote", + "action_type": "reject_or_promote", + "display_name": "拒絕或推進下一關", + "owner_agent": "openclaw", + "operator_instruction": "若任一 blocker 未解,維持 P2-111 前置;只有 owner acceptance 完整時才可進入下一關 no-write runtime fixture。", + "runtime_write_allowed": false + } + ], + "display_redaction_contract": { + "redaction_required": true, + "frontend_display_policy": "前端只顯示實作契約、欄位摘要、阻塞原因與人工下一步;不得顯示內部協作內容、私密推理、secret、authorization header 或原始 Telegram payload。", + "raw_prompt_display_allowed": false, + "private_reasoning_display_allowed": false, + "secret_value_display_allowed": false, + "raw_telegram_payload_display_allowed": false, + "work_window_transcript_display_allowed": false + }, + "rollups": { + "implementation_review_card_count": 5, + "no_write_verifier_check_count": 5, + "implementation_blocker_count": 5, + "operator_action_count": 5, + "approval_required_card_count": 2, + "blocked_card_count": 1, + "blocked_verifier_check_count": 1, + "critical_blocker_count": 2, + "owner_approval_received_count": 0, + "runtime_readback_execution_count": 0, + "live_query_count": 0, + "result_capture_write_count": 0, + "score_write_count": 0, + "learning_write_count": 0, + "playbook_trust_write_count": 0, + "reviewer_queue_write_count": 0, + "gateway_queue_write_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 + } +} diff --git a/docs/schemas/ai_agent_runtime_readback_implementation_review_v1.schema.json b/docs/schemas/ai_agent_runtime_readback_implementation_review_v1.schema.json new file mode 100644 index 000000000..1c8aef92a --- /dev/null +++ b/docs/schemas/ai_agent_runtime_readback_implementation_review_v1.schema.json @@ -0,0 +1,726 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://awoooi.wooo.work/schemas/ai_agent_runtime_readback_implementation_review_v1.schema.json", + "title": "AI Agent Runtime Readback Implementation Review v1", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "generated_at", + "program_status", + "source_refs", + "prior_approval_package", + "implementation_review_truth", + "implementation_review_cards", + "no_write_verifier_checks", + "implementation_blockers", + "operator_actions", + "display_redaction_contract", + "rollups" + ], + "properties": { + "schema_version": { + "const": "ai_agent_runtime_readback_implementation_review_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": { + "const": 100 + }, + "current_priority": { + "const": "P2" + }, + "current_task_id": { + "const": "P2-110" + }, + "next_task_id": { + "const": "P2-111" + }, + "read_only_mode": { + "const": true + }, + "runtime_authority": { + "const": "runtime_readback_implementation_review_only_no_live_read_or_write" + }, + "status_note": { + "type": "string", + "minLength": 1 + } + } + }, + "source_refs": { + "$ref": "#/$defs/string_array" + }, + "prior_approval_package": { + "$ref": "#/$defs/prior_approval_package" + }, + "implementation_review_truth": { + "$ref": "#/$defs/implementation_review_truth" + }, + "implementation_review_cards": { + "type": "array", + "minItems": 5, + "items": { + "$ref": "#/$defs/implementation_review_card" + } + }, + "no_write_verifier_checks": { + "type": "array", + "minItems": 5, + "items": { + "$ref": "#/$defs/no_write_verifier_check" + } + }, + "implementation_blockers": { + "type": "array", + "minItems": 5, + "items": { + "$ref": "#/$defs/implementation_blocker" + } + }, + "operator_actions": { + "type": "array", + "minItems": 5, + "items": { + "$ref": "#/$defs/operator_action" + } + }, + "display_redaction_contract": { + "$ref": "#/$defs/display_redaction_contract" + }, + "rollups": { + "$ref": "#/$defs/rollups" + } + }, + "$defs": { + "string_array": { + "type": "array", + "minItems": 1, + "items": { + "type": "string", + "minLength": 1 + } + }, + "redacted_sha256": { + "type": "string", + "pattern": "^sha256:[0-9a-f]{64}$" + }, + "owner_agent": { + "enum": [ + "openclaw", + "hermes", + "nemotron" + ] + }, + "prior_approval_package": { + "type": "object", + "additionalProperties": false, + "required": [ + "source_schema_version", + "readback_at", + "approval_packet_count", + "canonical_readback_plan_count", + "rollback_drill_lane_count", + "telegram_failure_receipt_gate_count", + "operator_action_count", + "approval_required_packet_count", + "blocked_total_count", + "owner_approval_received_count", + "runtime_readback_execution_count", + "telegram_failure_receipt_send_count", + "bot_api_call_count", + "rollback_work_item_write_count", + "production_write_count", + "secret_read_count", + "destructive_operation_count", + "readiness_note" + ], + "properties": { + "source_schema_version": { + "const": "ai_agent_runtime_readback_approval_package_v1" + }, + "readback_at": { + "type": "string" + }, + "approval_packet_count": { + "const": 5 + }, + "canonical_readback_plan_count": { + "const": 4 + }, + "rollback_drill_lane_count": { + "const": 4 + }, + "telegram_failure_receipt_gate_count": { + "const": 4 + }, + "operator_action_count": { + "const": 5 + }, + "approval_required_packet_count": { + "const": 3 + }, + "blocked_total_count": { + "const": 5 + }, + "owner_approval_received_count": { + "const": 0 + }, + "runtime_readback_execution_count": { + "const": 0 + }, + "telegram_failure_receipt_send_count": { + "const": 0 + }, + "bot_api_call_count": { + "const": 0 + }, + "rollback_work_item_write_count": { + "const": 0 + }, + "production_write_count": { + "const": 0 + }, + "secret_read_count": { + "const": 0 + }, + "destructive_operation_count": { + "const": 0 + }, + "readiness_note": { + "type": "string", + "minLength": 1 + } + } + }, + "implementation_review_truth": { + "type": "object", + "additionalProperties": false, + "required": [ + "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", + "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", + "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", + "truth_note" + ], + "properties": { + "p2_109_approval_package_loaded": { + "const": true + }, + "implementation_review_ready": { + "const": true + }, + "adapter_contract_ready": { + "const": true + }, + "verifier_contract_ready": { + "const": true + }, + "redaction_contract_ready": { + "const": true + }, + "telemetry_receipt_contract_ready": { + "const": true + }, + "owner_review_required_before_runtime": { + "const": true + }, + "canonical_runtime_readback_enabled": { + "const": false + }, + "live_query_enabled": { + "const": false + }, + "runtime_result_capture_write_enabled": { + "const": false + }, + "runtime_score_write_enabled": { + "const": false + }, + "runtime_learning_write_enabled": { + "const": false + }, + "playbook_trust_write_enabled": { + "const": false + }, + "reviewer_queue_write_enabled": { + "const": false + }, + "gateway_queue_write_enabled": { + "const": false + }, + "telegram_failure_receipt_send_enabled": { + "const": false + }, + "bot_api_call_enabled": { + "const": false + }, + "rollback_work_item_write_enabled": { + "const": false + }, + "production_write_enabled": { + "const": false + }, + "secret_read_enabled": { + "const": false + }, + "destructive_operation_enabled": { + "const": false + }, + "owner_approval_received_count": { + "const": 0 + }, + "runtime_readback_execution_count": { + "const": 0 + }, + "live_query_count_24h": { + "const": 0 + }, + "result_capture_write_count_24h": { + "const": 0 + }, + "score_write_count_24h": { + "const": 0 + }, + "learning_write_count_24h": { + "const": 0 + }, + "playbook_trust_write_count_24h": { + "const": 0 + }, + "reviewer_queue_write_count_24h": { + "const": 0 + }, + "gateway_queue_write_count_24h": { + "const": 0 + }, + "telegram_failure_receipt_send_count_24h": { + "const": 0 + }, + "bot_api_call_count_24h": { + "const": 0 + }, + "rollback_work_item_write_count_24h": { + "const": 0 + }, + "production_write_count_24h": { + "const": 0 + }, + "secret_read_count_24h": { + "const": 0 + }, + "destructive_operation_count_24h": { + "const": 0 + }, + "truth_note": { + "type": "string", + "minLength": 1 + } + } + }, + "implementation_review_card": { + "type": "object", + "additionalProperties": false, + "required": [ + "card_id", + "display_name", + "owner_agent", + "status", + "risk_tier", + "implementation_surface", + "required_interfaces", + "blocked_runtime_actions", + "review_guidance", + "owner_review_required", + "no_write_mode", + "evidence_hash" + ], + "properties": { + "card_id": { + "type": "string", + "minLength": 1 + }, + "display_name": { + "type": "string", + "minLength": 1 + }, + "owner_agent": { + "$ref": "#/$defs/owner_agent" + }, + "status": { + "enum": [ + "ready_for_owner_review", + "approval_required", + "blocked_by_policy" + ] + }, + "risk_tier": { + "enum": [ + "high", + "critical" + ] + }, + "implementation_surface": { + "type": "string", + "minLength": 1 + }, + "required_interfaces": { + "$ref": "#/$defs/string_array" + }, + "blocked_runtime_actions": { + "$ref": "#/$defs/string_array" + }, + "review_guidance": { + "type": "string", + "minLength": 1 + }, + "owner_review_required": { + "const": true + }, + "no_write_mode": { + "const": true + }, + "evidence_hash": { + "$ref": "#/$defs/redacted_sha256" + } + } + }, + "no_write_verifier_check": { + "type": "object", + "additionalProperties": false, + "required": [ + "check_id", + "display_name", + "owner_agent", + "status", + "check_scope", + "required_evidence", + "failure_if_missing", + "live_query_enabled", + "runtime_write_allowed", + "evidence_hash" + ], + "properties": { + "check_id": { + "type": "string", + "minLength": 1 + }, + "display_name": { + "type": "string", + "minLength": 1 + }, + "owner_agent": { + "$ref": "#/$defs/owner_agent" + }, + "status": { + "enum": [ + "ready", + "blocked_by_policy" + ] + }, + "check_scope": { + "type": "string", + "minLength": 1 + }, + "required_evidence": { + "$ref": "#/$defs/string_array" + }, + "failure_if_missing": { + "type": "string", + "minLength": 1 + }, + "live_query_enabled": { + "const": false + }, + "runtime_write_allowed": { + "const": false + }, + "evidence_hash": { + "$ref": "#/$defs/redacted_sha256" + } + } + }, + "implementation_blocker": { + "type": "object", + "additionalProperties": false, + "required": [ + "blocker_id", + "display_name", + "severity", + "status", + "blocked_until", + "blocked_action", + "required_resolution", + "owner_agent", + "evidence_hash" + ], + "properties": { + "blocker_id": { + "type": "string", + "minLength": 1 + }, + "display_name": { + "type": "string", + "minLength": 1 + }, + "severity": { + "enum": [ + "high", + "critical" + ] + }, + "status": { + "enum": [ + "blocking_runtime", + "blocking_live_read", + "blocking_queue_write", + "blocking_notification", + "blocking_production_write" + ] + }, + "blocked_until": { + "type": "string", + "minLength": 1 + }, + "blocked_action": { + "type": "string", + "minLength": 1 + }, + "required_resolution": { + "type": "string", + "minLength": 1 + }, + "owner_agent": { + "$ref": "#/$defs/owner_agent" + }, + "evidence_hash": { + "$ref": "#/$defs/redacted_sha256" + } + } + }, + "operator_action": { + "type": "object", + "additionalProperties": false, + "required": [ + "action_id", + "action_type", + "display_name", + "owner_agent", + "operator_instruction", + "runtime_write_allowed" + ], + "properties": { + "action_id": { + "type": "string", + "minLength": 1 + }, + "action_type": { + "enum": [ + "review_implementation_contract", + "validate_adapter_mapping", + "validate_zero_write_counters", + "review_failure_receipt_mapping", + "reject_or_promote" + ] + }, + "display_name": { + "type": "string", + "minLength": 1 + }, + "owner_agent": { + "$ref": "#/$defs/owner_agent" + }, + "operator_instruction": { + "type": "string", + "minLength": 1 + }, + "runtime_write_allowed": { + "const": false + } + } + }, + "display_redaction_contract": { + "type": "object", + "additionalProperties": false, + "required": [ + "redaction_required", + "frontend_display_policy", + "raw_prompt_display_allowed", + "private_reasoning_display_allowed", + "secret_value_display_allowed", + "raw_telegram_payload_display_allowed", + "work_window_transcript_display_allowed" + ], + "properties": { + "redaction_required": { + "const": true + }, + "frontend_display_policy": { + "type": "string", + "minLength": 1 + }, + "raw_prompt_display_allowed": { + "const": false + }, + "private_reasoning_display_allowed": { + "const": false + }, + "secret_value_display_allowed": { + "const": false + }, + "raw_telegram_payload_display_allowed": { + "const": false + }, + "work_window_transcript_display_allowed": { + "const": false + } + } + }, + "rollups": { + "type": "object", + "additionalProperties": false, + "required": [ + "implementation_review_card_count", + "no_write_verifier_check_count", + "implementation_blocker_count", + "operator_action_count", + "approval_required_card_count", + "blocked_card_count", + "blocked_verifier_check_count", + "critical_blocker_count", + "owner_approval_received_count", + "runtime_readback_execution_count", + "live_query_count", + "result_capture_write_count", + "score_write_count", + "learning_write_count", + "playbook_trust_write_count", + "reviewer_queue_write_count", + "gateway_queue_write_count", + "telegram_failure_receipt_send_count", + "bot_api_call_count", + "rollback_work_item_write_count", + "production_write_count", + "secret_read_count", + "destructive_operation_count" + ], + "properties": { + "implementation_review_card_count": { + "const": 5 + }, + "no_write_verifier_check_count": { + "const": 5 + }, + "implementation_blocker_count": { + "const": 5 + }, + "operator_action_count": { + "const": 5 + }, + "approval_required_card_count": { + "const": 2 + }, + "blocked_card_count": { + "const": 1 + }, + "blocked_verifier_check_count": { + "const": 1 + }, + "critical_blocker_count": { + "const": 2 + }, + "owner_approval_received_count": { + "const": 0 + }, + "runtime_readback_execution_count": { + "const": 0 + }, + "live_query_count": { + "const": 0 + }, + "result_capture_write_count": { + "const": 0 + }, + "score_write_count": { + "const": 0 + }, + "learning_write_count": { + "const": 0 + }, + "playbook_trust_write_count": { + "const": 0 + }, + "reviewer_queue_write_count": { + "const": 0 + }, + "gateway_queue_write_count": { + "const": 0 + }, + "telegram_failure_receipt_send_count": { + "const": 0 + }, + "bot_api_call_count": { + "const": 0 + }, + "rollback_work_item_write_count": { + "const": 0 + }, + "production_write_count": { + "const": 0 + }, + "secret_read_count": { + "const": 0 + }, + "destructive_operation_count": { + "const": 0 + } + } + } + } +} 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 3b7f54dfc..815f5d52f 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 @@ -647,6 +647,7 @@ Alert / Sentry / SigNoz / Gitea / Market Watch / Operator | `docs/evaluations/ai_agent_owner_approved_result_capture_readback_2026-06-13.json` + `GET /api/v1/agents/agent-owner-approved-result-capture-readback` | P2-107 owner-approved result capture readback / promotion readiness;承接 P2-106 no-write dry-run,建立 5 個 readback digest、5 個 promotion readiness review、4 條 failure lane、4 個 reviewer queue preview 與 5 個 operator action;canonical runtime readback、owner approval received、readback digest generated、promotion approved、reviewer queue write、score write、result capture write、learning write、PlayBook trust write、Gateway queue、Telegram、production write、secret read 與 destructive action 全部 `0 / false`,下一步 P2-108 | | `docs/evaluations/ai_agent_report_status_board_2026-06-13.json` + `GET /api/v1/agents/agent-report-status-board` | P2-108 日週月報與 Agent 工作狀態總覽;承接 P2-403J / P2-403L-M-N / P2-107,將日報、週報、月報、OpenClaw / Hermes / NemoTron 工作狀態、工作量、圖表與 operator answer cards 收斂到治理頁;三種報告可見完成度 `100%`,Agent 狀態 `3`、圖表 `3`、工作量 `91`、已完成 `79`、待審核 `12`;scheduler、Gateway queue write、Telegram send、讀報回執、AI analysis run、中低風險 auto execution、production optimization write 全部 `0 / false`,下一步 P2-109 | | `docs/evaluations/ai_agent_runtime_readback_approval_package_2026-06-13.json` + `GET /api/v1/agents/agent-runtime-readback-approval-package` | P2-109 runtime readback approval package;承接 P2-107 readback / promotion readiness 與 P2-108 report status board,建立 5 個批准包、4 個 canonical readback plan、4 條 rollback drill、4 個 Telegram failure receipt gate 與 5 個 operator action;canonical runtime readback、runtime readback execution、owner approval received、reviewer queue write、rollback work item write、Gateway queue、Telegram failure receipt、Bot API、score / result capture / learning / trust / production write、secret read 與 destructive action 全部 `0 / false`,下一步 P2-110 | +| `docs/evaluations/ai_agent_runtime_readback_implementation_review_2026-06-13.json` + `GET /api/v1/agents/agent-runtime-readback-implementation-review` | P2-110 runtime readback implementation review;承接 P2-109 approval package,建立 5 張 implementation review card、5 個 no-write verifier check、5 個 implementation blocker 與 5 個 operator action;canonical runtime readback、live query、runtime readback execution、owner approval received、reviewer queue write、rollback work item write、Gateway queue、Telegram failure receipt、Bot API、score / result capture / learning / trust / production write、secret read 與 destructive action 全部 `0 / false`,下一步 P2-111 | | `docs/evaluations/ai_agent_live_read_model_gate_2026-06-11.json` + `GET /api/v1/agents/agent-live-read-model-gate` | P2-403B AgentSession / Redis Streams live read model gate;定義 safe fields、Redis envelope、worker gate、rollback plan 與 no-write smoke,不連 DB、不讀寫 Redis、不啟動 worker | #### 3.2.1c 2026-06-11 AI Agent 主動營運委派與版本生命週期契約 @@ -745,6 +746,7 @@ Repo / registry / release notes / K8s / host / observability / backup evidence 28. 建立 owner-approved result capture readback / promotion readiness。✅ P2-107 已完成;readback digest `5`、promotion review `5`、failure lane `4`、reviewer queue preview `4`、operator action `5`,canonical runtime readback、owner approval received、readback digest generated、promotion approved、reviewer queue write、score / result capture / learning / trust / Gateway / Telegram / production write 仍為 `0 / false`。下一步 P2-108。 29. 建立日週月報與 Agent 工作狀態總覽。✅ P2-108 已完成;日報 / 週報 / 月報可見完成度皆 `100%`,OpenClaw / Hermes / NemoTron 工作狀態報告 `3`,圖表 `3`,operator answer card `4`,工作量 `91`、已完成 `79`、待審核 `12`;scheduler、Gateway queue write、Telegram send、report receipt、AI analysis run、中低風險 auto worker、production optimization write 仍為 `0 / false`。下一步 P2-109。 30. 建立 runtime readback approval package。✅ P2-109 已完成;批准包 `5`、canonical readback plan `4`、rollback drill `4`、Telegram failure receipt gate `4`、operator action `5`,canonical runtime readback、runtime readback execution、owner approval received、reviewer queue write、rollback work item write、Gateway / Telegram failure receipt / Bot API / production write 仍為 `0 / false`。下一步 P2-110。 +31. 建立 runtime readback implementation review。✅ P2-110 本地完成;implementation review card `5`、no-write verifier check `5`、implementation blocker `5`、operator action `5`,approval required card `2`、critical blocker `2`;canonical runtime readback、live query、runtime readback execution、owner approval received、reviewer queue write、rollback work item write、Gateway / Telegram failure receipt / Bot API / production write 仍為 `0 / false`。正式部署待驗證,下一步 P2-111。 #### 3.2.1d 2026-06-11 Agent 互動、學習與成長證據面 @@ -787,6 +789,8 @@ Repo / registry / release notes / K8s / host / observability / backup evidence | `docs/evaluations/ai_agent_report_status_board_2026-06-13.json` + `GET /api/v1/agents/agent-report-status-board` | P2-108 committed snapshot;三種報告 `100%` 可見、3 個 Agent 狀態報告、3 張圖表、4 張統帥問答卡;工作量 `91`、已完成 `79`、待審核 `12`,live delivery / Telegram send / runtime work / auto optimization 全部 `0` | | `docs/schemas/ai_agent_runtime_readback_approval_package_v1.schema.json` | P2-109 runtime readback approval package schema;強制 canonical runtime readback、runtime readback execution、owner approval received、reviewer queue write、rollback work item write、Gateway queue、Telegram failure receipt、Bot API、score write、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive action 全部維持 `0 / false` | | `docs/evaluations/ai_agent_runtime_readback_approval_package_2026-06-13.json` + `GET /api/v1/agents/agent-runtime-readback-approval-package` | P2-109 committed snapshot;5 個批准包、4 個 canonical readback plan、4 條 rollback drill、4 個 Telegram failure receipt gate、5 個 operator action;不讀 canonical runtime target、不寫 reviewer queue、不寫 rollback work item、不送 Telegram、不呼叫 Bot API、不寫 production target、不讀 secret、不執行 destructive action | +| `docs/schemas/ai_agent_runtime_readback_implementation_review_v1.schema.json` | P2-110 runtime readback implementation review schema;強制 canonical runtime readback、live query、runtime readback execution、owner approval received、reviewer queue write、rollback work item write、Gateway queue、Telegram failure receipt、Bot API、score write、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive action 全部維持 `0 / false` | +| `docs/evaluations/ai_agent_runtime_readback_implementation_review_2026-06-13.json` + `GET /api/v1/agents/agent-runtime-readback-implementation-review` | P2-110 committed snapshot;5 張 implementation review card、5 個 no-write verifier check、5 個 implementation blocker、5 個 operator action;不讀 canonical runtime target、不做 live query、不寫 reviewer queue、不寫 rollback work item、不送 Telegram、不呼叫 Bot API、不寫 production target、不讀 secret、不執行 destructive action | | `apps/api/src/services/ai_agent_interaction_learning_proof.py` | 只讀 loader;強制 live flags / DB / Redis / Telegram / transcript / 私有推理全部關閉 | | `GET /api/v1/agents/agent-interaction-learning-proof` | 治理 API;只回傳證據面,不啟動 worker、不碰 live DB/Redis、不發 Telegram | | `docs/schemas/ai_agent_live_read_model_gate_v1.schema.json` | P2-403B live read model gate schema;強制 DB / Redis / worker / Telegram / learning writeback 仍需批准 | @@ -1991,6 +1995,13 @@ Phase 6 完成後 - 政策裁決:P2-109 只允許 owner review 批准包、canonical readback plan、rollback drill 與 failure receipt gate 可視化;不得把批准包或 gate 解讀成 canonical runtime readback、reviewer queue write、Telegram 實發、Bot API 呼叫、rollback work item write 或 live writer 已啟用。 - 本波仍不讀 canonical runtime target、不寫 score、不寫 result capture、不寫 learning、不更新 PlayBook trust、不寫 KM、不 runtime append LOGBOOK、不寫 audit DB、不寫 timeline、不寫 reviewer queue、不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 rollback work item、不啟動 runtime worker、不讀 secret、不執行 destructive action、不回傳內部協作內容;下一步 P2-110。 +### 2026-06-13 16:26 (台北) — §3.2 / §5 — 本地完成 P2-110 runtime readback implementation review — 把批准包轉成實作審查面 + +- 新增 `ai_agent_runtime_readback_implementation_review_v1` schema / committed snapshot / loader / API / 測試,承接 P2-109 的批准包、canonical readback plan、rollback drill 與 Telegram failure receipt gate,定義 5 張 implementation review card、5 個 no-write verifier check、5 個 implementation blocker 與 5 個 operator action。 +- `apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx` 接入 `GET /api/v1/agents/agent-runtime-readback-implementation-review`,治理頁顯示 P2-110 進度 `100%`、實作卡 `5`、no-write verifier `5`、阻塞項 `5`、操作選項 `5`、需批准 `2`、阻擋總數 `7`、關鍵阻塞 `2`、owner approval received `0`、runtime readback execution `0`、live query `0`、Telegram failure receipt send `0`、rollback work item write `0` 與 live writes `0`。 +- 政策裁決:P2-110 只允許 committed implementation review、no-write verifier 與 blocker 可視化;不得把實作審查卡或 operator action 解讀成 canonical runtime readback、live query、reviewer queue write、Telegram 實發、Bot API 呼叫、rollback work item write 或 live writer 已啟用。 +- 本波仍不讀 canonical runtime target、不做 live query、不寫 score、不寫 result capture、不寫 learning、不更新 PlayBook trust、不寫 KM、不 runtime append LOGBOOK、不寫 audit DB、不寫 timeline、不寫 reviewer queue、不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 rollback work item、不啟動 runtime worker、不讀 secret、不執行 destructive action、不回傳內部協作內容;正式部署待驗證,下一步 P2-111。 + ### 2026-06-13 14:18 (台北) — §3.2 / §5 — 完成 P2-107 owner-approved result capture readback / promotion readiness — 把批准後 readback 與升級準備固定成只讀閘門 - 新增 `ai_agent_owner_approved_result_capture_readback_v1` schema / committed snapshot / loader / API / 測試,承接 P2-106 的 no-write template、score fixture 與 dry-run gate,定義 5 個 readback digest、5 個 promotion readiness review、4 條 failure lane、4 個 reviewer queue preview 與 5 個 operator action。