From 280e0fbef0d5dccb10f1efe2cc18cf423544254e Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 14 Jun 2026 08:59:22 +0800 Subject: [PATCH] =?UTF-8?q?feat(governance):=20=E6=96=B0=E5=A2=9E=20releas?= =?UTF-8?q?e=20authorization=20readback=20gate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/api/src/api/v1/agents.py | 34 ++ ...ure_release_authorization_readback_gate.py | 438 +++++++++++++++ ...ure_release_authorization_readback_gate.py | 126 +++++ ...release_authorization_readback_gate_api.py | 31 ++ apps/web/messages/en.json | 38 ++ apps/web/messages/zh-TW.json | 38 ++ .../tabs/automation-inventory-tab.tsx | 210 +++++++- apps/web/src/lib/api-client.ts | 223 ++++++++ docs/LOGBOOK.md | 27 + ...AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md | 21 +- ...uthorization_readback_gate_2026-06-14.json | 507 ++++++++++++++++++ ...authorization_readback_gate_v1.schema.json | 100 ++++ ...-04-15-MASTER-ai-autonomous-flywheel-v2.md | 9 + 13 files changed, 1791 insertions(+), 11 deletions(-) create mode 100644 apps/api/src/services/ai_agent_result_capture_release_authorization_readback_gate.py create mode 100644 apps/api/tests/test_ai_agent_result_capture_release_authorization_readback_gate.py create mode 100644 apps/api/tests/test_ai_agent_result_capture_release_authorization_readback_gate_api.py create mode 100644 docs/evaluations/ai_agent_result_capture_release_authorization_readback_gate_2026-06-14.json create mode 100644 docs/schemas/ai_agent_result_capture_release_authorization_readback_gate_v1.schema.json diff --git a/apps/api/src/api/v1/agents.py b/apps/api/src/api/v1/agents.py index 64ada8db..0fdcaf4d 100644 --- a/apps/api/src/api/v1/agents.py +++ b/apps/api/src/api/v1/agents.py @@ -148,6 +148,9 @@ from src.services.ai_agent_result_capture_final_release_candidate_readback impor from src.services.ai_agent_result_capture_release_authorization_hold import ( load_latest_ai_agent_result_capture_release_authorization_hold, ) +from src.services.ai_agent_result_capture_release_authorization_readback_gate import ( + load_latest_ai_agent_result_capture_release_authorization_readback_gate, +) from src.services.ai_agent_result_capture_post_release_verifier_rollback_gate import ( load_latest_ai_agent_result_capture_post_release_verifier_rollback_gate, ) @@ -2153,6 +2156,37 @@ async def get_agent_result_capture_release_authorization_hold() -> dict[str, Any ) from exc +@router.get( + "/agent-result-capture-release-authorization-readback-gate", + response_model=dict[str, Any], + summary="取得 AI Agent result capture release authorization readback gate", + description=( + "讀取最新已提交的 P2-135 release authorization readback gate;" + "此端點只回傳 release authorization readback、rollback release readback、maintenance window readback hold、" + "live apply release readback hold、blocked release readback transition 與 operator handoff," + "不授權 owner release、不批准 maintenance window、不確認 rollback owner、不通過 release authorization、" + "不釋放 rollback release 或 live apply、不套用 writer、不寫 receipt、不寫 result capture、learning、PlayBook trust、" + "reviewer queue、Gateway queue,不送 Telegram、不呼叫 Bot API、不讀 secret。" + ), +) +async def get_agent_result_capture_release_authorization_readback_gate() -> dict[str, Any]: + """Return the latest read-only release authorization readback gate.""" + try: + payload = await asyncio.to_thread(load_latest_ai_agent_result_capture_release_authorization_readback_gate) + 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_result_capture_release_authorization_readback_gate_invalid", error=str(exc)) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="AI Agent result capture release authorization readback gate 無效", + ) from exc + + @router.get( "/agent-owner-approved-fixture-dry-run", response_model=dict[str, Any], diff --git a/apps/api/src/services/ai_agent_result_capture_release_authorization_readback_gate.py b/apps/api/src/services/ai_agent_result_capture_release_authorization_readback_gate.py new file mode 100644 index 00000000..21ed611d --- /dev/null +++ b/apps/api/src/services/ai_agent_result_capture_release_authorization_readback_gate.py @@ -0,0 +1,438 @@ +""" +AI Agent result capture release authorization readback gate snapshot. + +Loads the latest committed P2-135 release authorization readback gate. +This module validates committed evidence only; it never authorizes owner +release, approves maintenance windows, confirms rollback owners, passes +release authorization, releases live apply, applies writers, writes receipts, +writes result captures, writes learning records, updates PlayBook trust, writes +reviewer / Gateway queues, sends Telegram messages, reads secrets, or performs +destructive operations. +""" + +from __future__ import annotations + +import json +import re +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_result_capture_release_authorization_readback_gate_*.json" +_SCHEMA_VERSION = "ai_agent_result_capture_release_authorization_readback_gate_v1" +_RUNTIME_AUTHORITY = "result_capture_release_authorization_readback_gate_only_no_live_write" + + +def load_latest_ai_agent_result_capture_release_authorization_readback_gate( + evaluations_dir: Path | None = None, +) -> dict[str, Any]: + """Load the newest committed release authorization readback gate.""" + directory = evaluations_dir or _DEFAULT_EVALUATIONS_DIR + candidates = sorted(directory.glob(_SNAPSHOT_PATTERN)) + if not candidates: + raise FileNotFoundError(f"no AI Agent result capture release authorization readback gate 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") + + label = str(latest) + _require_schema(payload, label) + _require_prior(payload, label) + _require_truth(payload, label) + _require_authorization_readbacks(payload, label) + _require_rollback_readbacks(payload, label) + _require_maintenance_holds(payload, label) + _require_live_apply_holds(payload, label) + _require_blocked_transitions(payload, label) + _require_actions(payload, label) + _require_display_redaction(payload, label) + _require_no_forbidden_display_terms(payload, label) + _require_rollup_consistency(payload, label) + 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 {} + expected = { + "current_priority": "P2", + "current_task_id": "P2-135", + "next_task_id": "P2-136", + "read_only_mode": True, + "runtime_authority": _RUNTIME_AUTHORITY, + "overall_completion_percent": 100, + } + mismatches = _mismatches(status, expected) + if mismatches: + raise ValueError(f"{label}: program_status mismatch: {mismatches}") + if not status.get("status_note"): + raise ValueError(f"{label}: program_status.status_note is required") + + +def _require_prior(payload: dict[str, Any], label: str) -> None: + prior = payload.get("prior_release_authorization_hold") or {} + expected = { + "schema_version": "ai_agent_result_capture_release_authorization_hold_v1", + "release_authorization_hold_count": 5, + "rollback_authorization_hold_count": 5, + "release_window_hold_count": 5, + "live_apply_authorization_hold_count": 5, + "blocked_authorization_transition_count": 6, + "operator_action_count": 5, + "approval_required_total": 8, + "blocked_total": 9, + "owner_release_authorized_count": 0, + "owner_release_approved_count": 0, + "maintenance_window_approved_count": 0, + "rollback_owner_confirmed_count": 0, + "post_release_verifier_ready_count": 0, + "final_release_candidate_approved_count": 0, + "final_release_candidate_pass_count": 0, + "release_authorization_granted_count": 0, + "release_authorization_pass_count": 0, + "rollback_release_pass_count": 0, + "live_apply_release_pass_count": 0, + "writer_apply_count": 0, + "execution_apply_count": 0, + "receipt_write_count": 0, + "result_capture_write_count": 0, + "learning_write_count": 0, + "playbook_trust_write_count": 0, + "reviewer_queue_write_count": 0, + "gateway_queue_write_count": 0, + "telegram_send_count": 0, + "bot_api_call_count": 0, + "report_receipt_write_count": 0, + } + mismatches = _mismatches(prior, expected) + if mismatches: + raise ValueError(f"{label}: prior_release_authorization_hold mismatch: {mismatches}") + if not prior.get("readiness_note"): + raise ValueError(f"{label}: prior_release_authorization_hold.readiness_note is required") + + +def _require_truth(payload: dict[str, Any], label: str) -> None: + truth = payload.get("release_authorization_readback_truth") or {} + required_true = { + "p2_134_release_authorization_hold_loaded", + "release_authorization_readback_ready", + "rollback_release_readback_ready", + "maintenance_window_readback_hold_active", + "live_apply_release_readback_hold_active", + "owner_authorization_review_still_required", + "release_verifier_review_still_required", + "rollback_owner_review_required", + "redaction_review_required", + "release_authorization_readback_only", + } + missing = sorted(field for field in required_true if truth.get(field) is not True) + if missing: + raise ValueError(f"{label}: release authorization readback flags must remain true: {missing}") + + required_false = { + "owner_release_authorized", + "owner_release_approved", + "maintenance_window_approved", + "rollback_owner_confirmed", + "post_release_verifier_ready", + "final_release_candidate_approved", + "final_release_candidate_passed", + "release_authorization_granted", + "release_authorization_passed", + "rollback_release_passed", + "live_apply_release_passed", + "writer_apply_enabled", + "execution_apply_enabled", + "receipt_write_enabled", + "reviewer_queue_write_enabled", + "gateway_queue_write_enabled", + "telegram_send_enabled", + "bot_api_call_enabled", + "report_receipt_write_enabled", + "result_capture_write_enabled", + "learning_write_enabled", + "playbook_trust_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}: release authorization readback live/send/write flags must remain false: {unsafe}") + + zero_counts = { + "owner_release_authorized_count", + "owner_release_approved_count", + "maintenance_window_approved_count", + "rollback_owner_confirmed_count", + "post_release_verifier_ready_count", + "final_release_candidate_approved_count", + "final_release_candidate_pass_count", + "release_authorization_granted_count", + "release_authorization_pass_count", + "rollback_release_pass_count", + "live_apply_release_pass_count", + "writer_apply_count", + "execution_apply_count", + "receipt_write_count", + "reviewer_queue_write_count", + "gateway_queue_write_count", + "telegram_send_count", + "bot_api_call_count", + "report_receipt_write_count", + "result_capture_write_count", + "learning_write_count", + "playbook_trust_write_count", + "production_write_count", + "secret_read_count", + "destructive_operation_count", + } + non_zero = sorted(field for field in zero_counts if truth.get(field) != 0) + if non_zero: + raise ValueError(f"{label}: release authorization readback live counters must remain zero: {non_zero}") + if not truth.get("truth_note"): + raise ValueError(f"{label}: release_authorization_readback_truth.truth_note is required") + + +def _require_authorization_readbacks(payload: dict[str, Any], label: str) -> None: + items = payload.get("release_authorization_readbacks") or [] + _require_ids( + items, + "readback_id", + { + "release_authorization_readback_result_capture", + "release_authorization_readback_learning", + "release_authorization_readback_playbook_trust", + "release_authorization_readback_reviewer_queue", + "release_authorization_readback_gateway_queue", + }, + label, + "release authorization readbacks", + ) + for item in items: + item_id = item.get("readback_id") + if item.get("readback_mode") != "release_authorization_readback_gate": + raise ValueError(f"{label}: release authorization readback {item_id} mode is invalid") + if item.get("owner_release_authorized") is not False: + raise ValueError(f"{label}: release authorization readback {item_id} must stay unauthorized") + if item.get("release_authorization_granted") is not False or item.get("release_authorization_passed") is not False: + raise ValueError(f"{label}: release authorization readback {item_id} must stay ungranted and unpassed") + _require_valid_status(item, label, f"release authorization readback {item_id}") + if not item.get("readback_summary") or not _is_redacted_sha256(item.get("evidence_hash")): + raise ValueError(f"{label}: release authorization readback {item_id} must include summary and redacted evidence_hash") + + +def _require_rollback_readbacks(payload: dict[str, Any], label: str) -> None: + items = payload.get("rollback_release_readbacks") or [] + _require_count(items, 5, label, "rollback release readbacks") + for item in items: + item_id = item.get("readback_id") + if item.get("readback_mode") != "rollback_release_readback_gate": + raise ValueError(f"{label}: rollback release readback {item_id} mode is invalid") + if item.get("rollback_owner_required") is not True: + raise ValueError(f"{label}: rollback release readback {item_id} must require rollback owner") + if item.get("rollback_owner_confirmed") is not False or item.get("rollback_release_passed") is not False or item.get("rollback_release_enabled") is not False: + raise ValueError(f"{label}: rollback release readback {item_id} must stay unconfirmed, unpassed, and disabled") + _require_valid_status(item, label, f"rollback release readback {item_id}") + if not item.get("readback_summary"): + raise ValueError(f"{label}: rollback release readback {item_id}.readback_summary is required") + + +def _require_maintenance_holds(payload: dict[str, Any], label: str) -> None: + items = payload.get("maintenance_window_readback_holds") or [] + _require_count(items, 5, label, "maintenance window readback holds") + for item in items: + item_id = item.get("hold_id") + if item.get("hold_mode") != "maintenance_window_readback_hold": + raise ValueError(f"{label}: maintenance window readback hold {item_id} mode is invalid") + if item.get("owner_release_authorized") is not False or item.get("maintenance_window_approved") is not False: + raise ValueError(f"{label}: maintenance window readback hold {item_id} must keep owner release and maintenance unapproved") + if item.get("final_release_candidate_passed") is not False: + raise ValueError(f"{label}: maintenance window readback hold {item_id} must keep final candidate unpassed") + _require_valid_status(item, label, f"maintenance window readback hold {item_id}") + if not item.get("hold_reason"): + raise ValueError(f"{label}: maintenance window readback hold {item_id}.hold_reason is required") + + +def _require_live_apply_holds(payload: dict[str, Any], label: str) -> None: + items = payload.get("live_apply_release_readback_holds") or [] + _require_count(items, 5, label, "live apply release readback holds") + for item in items: + item_id = item.get("hold_id") + if item.get("hold_mode") != "live_apply_release_readback_hold": + raise ValueError(f"{label}: live apply release readback hold {item_id} mode is invalid") + if item.get("release_authorization_granted") is not False or item.get("release_authorization_passed") is not False: + raise ValueError(f"{label}: live apply release readback hold {item_id} must stay ungranted and unpassed") + if item.get("live_apply_release_passed") is not False or item.get("live_apply_release_enabled") is not False: + raise ValueError(f"{label}: live apply release readback hold {item_id} must stay unpassed and disabled") + _require_valid_status(item, label, f"live apply release readback hold {item_id}") + if not item.get("release_condition"): + raise ValueError(f"{label}: live apply release readback hold {item_id}.release_condition is required") + + +def _require_blocked_transitions(payload: dict[str, Any], label: str) -> None: + items = payload.get("blocked_release_readback_transitions") or [] + _require_count(items, 6, label, "blocked release readback transitions") + critical_count = 0 + for item in items: + item_id = item.get("blocker_id") + if item.get("severity") == "critical": + critical_count += 1 + if item.get("status") not in {"approval_required", "blocked_by_policy"}: + raise ValueError(f"{label}: blocked release readback transition {item_id} status is invalid") + if not item.get("blocked_action") or not item.get("blocked_until") or not _is_redacted_sha256(item.get("evidence_hash")): + raise ValueError(f"{label}: blocked release readback transition {item_id} must include blocked action, until, and evidence hash") + if critical_count != 5: + raise ValueError(f"{label}: expected 5 critical release readback blockers, got {critical_count}") + + +def _require_actions(payload: dict[str, Any], label: str) -> None: + items = payload.get("operator_actions") or [] + _require_count(items, 5, label, "operator actions") + for item in items: + item_id = item.get("action_id") + if item.get("runtime_write_allowed") is not False: + raise ValueError(f"{label}: operator action {item_id} must not allow runtime writes") + if item.get("status") not in {"ready_for_operator_review", "approval_required"}: + raise ValueError(f"{label}: operator action {item_id} status is invalid") + if not item.get("operator_instruction"): + raise ValueError(f"{label}: operator action {item_id}.operator_instruction is required") + + +def _require_display_redaction(payload: dict[str, Any], label: str) -> None: + contract = payload.get("display_redaction_contract") or {} + expected = { + "redaction_required": True, + "raw_prompt_display_allowed": False, + "private_reasoning_display_allowed": False, + "secret_value_display_allowed": False, + "raw_runtime_payload_display_allowed": False, + "internal_collaboration_content_display_allowed": False, + } + mismatches = _mismatches(contract, expected) + if mismatches: + raise ValueError(f"{label}: display_redaction_contract mismatch: {mismatches}") + if not contract.get("frontend_display_policy"): + raise ValueError(f"{label}: display_redaction_contract.frontend_display_policy is required") + + +def _require_no_forbidden_display_terms(payload: dict[str, Any], label: str) -> None: + forbidden_terms = { + "work_window_transcript", + "session_id", + "browser_context", + "authorization_header", + "raw Telegram payload", + "private reasoning", + "raw prompt", + "chain-of-thought", + "批准!繼續", + "My request for Codex", + "In app browser", + } + display_blob = json.dumps( + { + "program_status": payload.get("program_status"), + "release_authorization_readbacks": payload.get("release_authorization_readbacks"), + "rollback_release_readbacks": payload.get("rollback_release_readbacks"), + "maintenance_window_readback_holds": payload.get("maintenance_window_readback_holds"), + "live_apply_release_readback_holds": payload.get("live_apply_release_readback_holds"), + "operator_actions": payload.get("operator_actions"), + "display_redaction_contract": payload.get("display_redaction_contract"), + }, + ensure_ascii=False, + ) + leaked = sorted(term for term in forbidden_terms if term in display_blob) + if leaked: + raise ValueError(f"{label}: forbidden display terms leaked: {leaked}") + + +def _require_rollup_consistency(payload: dict[str, Any], label: str) -> None: + rollups = payload.get("rollups") or {} + expected = { + "release_authorization_readback_count": 5, + "rollback_release_readback_count": 5, + "maintenance_window_readback_hold_count": 5, + "live_apply_release_readback_hold_count": 5, + "blocked_release_readback_transition_count": 6, + "operator_action_count": 5, + "approval_required_authorization_readback_count": 2, + "blocked_authorization_readback_count": 1, + "approval_required_rollback_readback_count": 2, + "blocked_rollback_readback_count": 1, + "approval_required_maintenance_window_count": 2, + "blocked_maintenance_window_count": 1, + "approval_required_live_apply_readback_count": 2, + "blocked_live_apply_readback_count": 1, + "critical_blocker_count": 5, + "owner_release_authorized_count": 0, + "owner_release_approved_count": 0, + "maintenance_window_approved_count": 0, + "rollback_owner_confirmed_count": 0, + "post_release_verifier_ready_count": 0, + "final_release_candidate_approved_count": 0, + "final_release_candidate_pass_count": 0, + "release_authorization_granted_count": 0, + "release_authorization_pass_count": 0, + "rollback_release_pass_count": 0, + "live_apply_release_pass_count": 0, + "writer_apply_count": 0, + "execution_apply_count": 0, + "receipt_write_count": 0, + "reviewer_queue_write_count": 0, + "gateway_queue_write_count": 0, + "telegram_send_count": 0, + "bot_api_call_count": 0, + "report_receipt_write_count": 0, + "result_capture_write_count": 0, + "learning_write_count": 0, + "playbook_trust_write_count": 0, + "production_write_count": 0, + "secret_read_count": 0, + "destructive_operation_count": 0, + } + mismatches = _mismatches(rollups, expected) + if mismatches: + raise ValueError(f"{label}: rollups mismatch: {mismatches}") + + +def _require_valid_status(item: dict[str, Any], label: str, item_label: str) -> None: + if item.get("status") not in {"ready_for_owner_review", "approval_required", "blocked_by_policy"}: + raise ValueError(f"{label}: {item_label} status is invalid") + + +def _require_ids( + items: list[dict[str, Any]], + id_field: str, + expected_ids: set[str], + label: str, + item_label: str, +) -> None: + actual_ids = {str(item.get(id_field)) for item in items} + if actual_ids != expected_ids: + raise ValueError(f"{label}: {item_label} ids mismatch: expected={sorted(expected_ids)} actual={sorted(actual_ids)}") + + +def _require_count(items: list[dict[str, Any]], expected_count: int, label: str, item_label: str) -> None: + if len(items) != expected_count: + raise ValueError(f"{label}: expected {expected_count} {item_label}, got {len(items)}") + + +def _mismatches(data: dict[str, Any], expected: dict[str, Any]) -> dict[str, dict[str, Any]]: + mismatches: dict[str, dict[str, Any]] = {} + for key, expected_value in expected.items(): + actual_value = data.get(key) + if actual_value != expected_value: + mismatches[key] = {"expected": expected_value, "actual": actual_value} + return mismatches + + +def _is_redacted_sha256(value: object) -> bool: + return isinstance(value, str) and re.fullmatch(r"sha256:[0-9a-f]{64}", value) is not None diff --git a/apps/api/tests/test_ai_agent_result_capture_release_authorization_readback_gate.py b/apps/api/tests/test_ai_agent_result_capture_release_authorization_readback_gate.py new file mode 100644 index 00000000..5d4529fe --- /dev/null +++ b/apps/api/tests/test_ai_agent_result_capture_release_authorization_readback_gate.py @@ -0,0 +1,126 @@ +from __future__ import annotations + +import copy +import json +from pathlib import Path + +import pytest + +from src.services.ai_agent_result_capture_release_authorization_readback_gate import ( + load_latest_ai_agent_result_capture_release_authorization_readback_gate, +) + + +def test_load_latest_release_authorization_readback_gate_snapshot() -> None: + snapshot = load_latest_ai_agent_result_capture_release_authorization_readback_gate() + + assert snapshot["schema_version"] == "ai_agent_result_capture_release_authorization_readback_gate_v1" + assert snapshot["program_status"]["current_task_id"] == "P2-135" + assert snapshot["program_status"]["next_task_id"] == "P2-136" + assert snapshot["program_status"]["overall_completion_percent"] == 100 + assert snapshot["program_status"]["runtime_authority"] == "result_capture_release_authorization_readback_gate_only_no_live_write" + + rollups = snapshot["rollups"] + assert rollups["release_authorization_readback_count"] == 5 + assert rollups["rollback_release_readback_count"] == 5 + assert rollups["maintenance_window_readback_hold_count"] == 5 + assert rollups["live_apply_release_readback_hold_count"] == 5 + assert rollups["blocked_release_readback_transition_count"] == 6 + assert rollups["operator_action_count"] == 5 + assert ( + rollups["approval_required_authorization_readback_count"] + + rollups["approval_required_rollback_readback_count"] + + rollups["approval_required_maintenance_window_count"] + + rollups["approval_required_live_apply_readback_count"] + ) == 8 + assert ( + rollups["blocked_authorization_readback_count"] + + rollups["blocked_rollback_readback_count"] + + rollups["blocked_maintenance_window_count"] + + rollups["blocked_live_apply_readback_count"] + + rollups["critical_blocker_count"] + ) == 9 + + assert rollups["owner_release_authorized_count"] == 0 + assert rollups["release_authorization_granted_count"] == 0 + assert rollups["release_authorization_pass_count"] == 0 + assert rollups["rollback_release_pass_count"] == 0 + assert rollups["live_apply_release_pass_count"] == 0 + assert rollups["writer_apply_count"] == 0 + assert rollups["execution_apply_count"] == 0 + assert rollups["receipt_write_count"] == 0 + assert rollups["reviewer_queue_write_count"] == 0 + assert rollups["gateway_queue_write_count"] == 0 + assert rollups["telegram_send_count"] == 0 + assert rollups["bot_api_call_count"] == 0 + assert rollups["report_receipt_write_count"] == 0 + assert rollups["result_capture_write_count"] == 0 + assert rollups["learning_write_count"] == 0 + assert rollups["playbook_trust_write_count"] == 0 + assert rollups["production_write_count"] == 0 + + +def test_release_authorization_readback_truth_keeps_all_live_paths_closed() -> None: + snapshot = load_latest_ai_agent_result_capture_release_authorization_readback_gate() + truth = snapshot["release_authorization_readback_truth"] + + assert truth["p2_134_release_authorization_hold_loaded"] is True + assert truth["release_authorization_readback_ready"] is True + assert truth["live_apply_release_readback_hold_active"] is True + assert truth["owner_release_authorized"] is False + assert truth["owner_release_approved"] is False + assert truth["maintenance_window_approved"] is False + assert truth["rollback_owner_confirmed"] is False + assert truth["post_release_verifier_ready"] is False + assert truth["final_release_candidate_approved"] is False + assert truth["release_authorization_granted"] is False + assert truth["release_authorization_passed"] is False + assert truth["rollback_release_passed"] is False + assert truth["live_apply_release_passed"] is False + assert truth["writer_apply_enabled"] is False + assert truth["gateway_queue_write_enabled"] is False + assert truth["telegram_send_enabled"] is False + assert truth["production_write_enabled"] is False + assert truth["secret_read_enabled"] is False + assert truth["destructive_operation_enabled"] is False + + +def test_rejects_granted_release_authorization(tmp_path: Path) -> None: + snapshot = copy.deepcopy(load_latest_ai_agent_result_capture_release_authorization_readback_gate()) + snapshot["release_authorization_readback_truth"]["release_authorization_granted"] = True + _write_snapshot(tmp_path, snapshot) + + with pytest.raises(ValueError, match="must remain false"): + load_latest_ai_agent_result_capture_release_authorization_readback_gate(tmp_path) + + +def test_rejects_live_apply_release_enabled(tmp_path: Path) -> None: + snapshot = copy.deepcopy(load_latest_ai_agent_result_capture_release_authorization_readback_gate()) + snapshot["live_apply_release_readback_holds"][0]["live_apply_release_enabled"] = True + _write_snapshot(tmp_path, snapshot) + + with pytest.raises(ValueError, match="must stay unpassed and disabled"): + load_latest_ai_agent_result_capture_release_authorization_readback_gate(tmp_path) + + +def test_rejects_rollup_drift(tmp_path: Path) -> None: + snapshot = copy.deepcopy(load_latest_ai_agent_result_capture_release_authorization_readback_gate()) + snapshot["rollups"]["release_authorization_readback_count"] = 4 + _write_snapshot(tmp_path, snapshot) + + with pytest.raises(ValueError, match="rollups mismatch"): + load_latest_ai_agent_result_capture_release_authorization_readback_gate(tmp_path) + + +def test_rejects_forbidden_display_terms(tmp_path: Path) -> None: + snapshot = copy.deepcopy(load_latest_ai_agent_result_capture_release_authorization_readback_gate()) + snapshot["operator_actions"][0]["operator_instruction"] = "不要顯示 work_window_transcript" + _write_snapshot(tmp_path, snapshot) + + with pytest.raises(ValueError, match="forbidden display terms leaked"): + load_latest_ai_agent_result_capture_release_authorization_readback_gate(tmp_path) + + +def _write_snapshot(directory: Path, payload: dict) -> None: + path = directory / "ai_agent_result_capture_release_authorization_readback_gate_2099-01-01.json" + path.write_text(json.dumps(payload, ensure_ascii=False), encoding="utf-8") diff --git a/apps/api/tests/test_ai_agent_result_capture_release_authorization_readback_gate_api.py b/apps/api/tests/test_ai_agent_result_capture_release_authorization_readback_gate_api.py new file mode 100644 index 00000000..0604866a --- /dev/null +++ b/apps/api/tests/test_ai_agent_result_capture_release_authorization_readback_gate_api.py @@ -0,0 +1,31 @@ +from __future__ import annotations + +from fastapi.testclient import TestClient + +from src.main import app + + +def test_release_authorization_readback_gate_endpoint() -> None: + client = TestClient(app) + + response = client.get("/api/v1/agents/agent-result-capture-release-authorization-readback-gate") + + assert response.status_code == 200 + payload = response.json() + assert payload["schema_version"] == "ai_agent_result_capture_release_authorization_readback_gate_v1" + assert payload["program_status"]["current_task_id"] == "P2-135" + assert payload["program_status"]["next_task_id"] == "P2-136" + assert payload["program_status"]["overall_completion_percent"] == 100 + assert payload["program_status"]["runtime_authority"] == "result_capture_release_authorization_readback_gate_only_no_live_write" + assert payload["rollups"]["release_authorization_readback_count"] == 5 + assert payload["rollups"]["rollback_release_readback_count"] == 5 + assert payload["rollups"]["maintenance_window_readback_hold_count"] == 5 + assert payload["rollups"]["live_apply_release_readback_hold_count"] == 5 + assert payload["rollups"]["blocked_release_readback_transition_count"] == 6 + assert payload["rollups"]["operator_action_count"] == 5 + assert payload["rollups"]["owner_release_authorized_count"] == 0 + assert payload["rollups"]["release_authorization_granted_count"] == 0 + assert payload["rollups"]["release_authorization_pass_count"] == 0 + assert payload["rollups"]["gateway_queue_write_count"] == 0 + assert payload["rollups"]["telegram_send_count"] == 0 + assert payload["rollups"]["production_write_count"] == 0 diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index bb95dc64..52a6609d 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -6081,6 +6081,44 @@ "runtimeWriteAllowed": "runtime 寫入允許={value}" } }, + "resultCaptureReleaseAuthorizationReadbackGate": { + "title": "P2-135 釋出授權讀回關卡", + "source": "產生 {generated};目前 {current};下一步 {next}", + "priorTitle": "前一關釋出授權保留", + "truthTitle": "釋出授權讀回真相", + "metrics": { + "overall": "完成度", + "readbacks": "授權讀回", + "rollbackReadbacks": "回滾讀回", + "maintenanceHolds": "維護窗口保留", + "liveApplyHolds": "正式套用保留", + "blockers": "已阻擋讀回", + "actions": "操作選項", + "approvalRequired": "需批准", + "blocked": "阻擋", + "liveWrites": "正式寫入 / 發送" + }, + "flags": { + "p2Loaded": "已載入 P2-134={value}", + "readbackReady": "釋出授權讀回已就緒={value}", + "liveApplyHoldActive": "正式套用讀回保留啟用={value}" + }, + "labels": { + "ownerReleaseAuthorized": "負責人釋出授權={value}", + "maintenanceApproved": "維護窗口批准={value}", + "candidatePassed": "最終候選通過={value}", + "authorizationGranted": "釋出授權已核發={value}", + "authorizationPassed": "釋出授權通過={value}", + "gatewayWrites": "Gateway 寫入={value}", + "rollbackRequired": "需要回滾 owner={value}", + "rollbackConfirmed": "回滾 owner 已確認={value}", + "rollbackPassed": "回滾釋出通過={value}", + "rollbackEnabled": "回滾釋出啟用={value}", + "liveApplyReleasePassed": "正式套用釋出通過={value}", + "liveApplyReleaseEnabled": "正式套用釋出啟用={value}", + "runtimeWriteAllowed": "runtime 寫入允許={value}" + } + }, "resultCaptureOwnerReleaseApprovalGate": { "title": "P2-131 owner release approval gate", "source": "產生 {generated};目前 {current};下一步 {next}", diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index bb95dc64..52a6609d 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -6081,6 +6081,44 @@ "runtimeWriteAllowed": "runtime 寫入允許={value}" } }, + "resultCaptureReleaseAuthorizationReadbackGate": { + "title": "P2-135 釋出授權讀回關卡", + "source": "產生 {generated};目前 {current};下一步 {next}", + "priorTitle": "前一關釋出授權保留", + "truthTitle": "釋出授權讀回真相", + "metrics": { + "overall": "完成度", + "readbacks": "授權讀回", + "rollbackReadbacks": "回滾讀回", + "maintenanceHolds": "維護窗口保留", + "liveApplyHolds": "正式套用保留", + "blockers": "已阻擋讀回", + "actions": "操作選項", + "approvalRequired": "需批准", + "blocked": "阻擋", + "liveWrites": "正式寫入 / 發送" + }, + "flags": { + "p2Loaded": "已載入 P2-134={value}", + "readbackReady": "釋出授權讀回已就緒={value}", + "liveApplyHoldActive": "正式套用讀回保留啟用={value}" + }, + "labels": { + "ownerReleaseAuthorized": "負責人釋出授權={value}", + "maintenanceApproved": "維護窗口批准={value}", + "candidatePassed": "最終候選通過={value}", + "authorizationGranted": "釋出授權已核發={value}", + "authorizationPassed": "釋出授權通過={value}", + "gatewayWrites": "Gateway 寫入={value}", + "rollbackRequired": "需要回滾 owner={value}", + "rollbackConfirmed": "回滾 owner 已確認={value}", + "rollbackPassed": "回滾釋出通過={value}", + "rollbackEnabled": "回滾釋出啟用={value}", + "liveApplyReleasePassed": "正式套用釋出通過={value}", + "liveApplyReleaseEnabled": "正式套用釋出啟用={value}", + "runtimeWriteAllowed": "runtime 寫入允許={value}" + } + }, "resultCaptureOwnerReleaseApprovalGate": { "title": "P2-131 owner release approval gate", "source": "產生 {generated};目前 {current};下一步 {next}", 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 e46cfb47..3e2d9f86 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 @@ -82,6 +82,7 @@ import { type AiAgentResultCapturePostReleaseVerifierRollbackGateSnapshot, type AiAgentResultCaptureFinalReleaseCandidateReadbackSnapshot, type AiAgentResultCaptureReleaseAuthorizationHoldSnapshot, + type AiAgentResultCaptureReleaseAuthorizationReadbackGateSnapshot, type AiAgentResultCaptureWriterImplementationReviewSnapshot, type AiAgentOwnerApprovedFixturePromotionGateSnapshot, type AiAgentRuntimeWorkerShadowGateSnapshot, @@ -487,6 +488,7 @@ export function AutomationInventoryTab() { const [resultCapturePostReleaseVerifierRollbackGate, setResultCapturePostReleaseVerifierRollbackGate] = useState(null) const [resultCaptureFinalReleaseCandidateReadback, setResultCaptureFinalReleaseCandidateReadback] = useState(null) const [resultCaptureReleaseAuthorizationHold, setResultCaptureReleaseAuthorizationHold] = useState(null) + const [resultCaptureReleaseAuthorizationReadbackGate, setResultCaptureReleaseAuthorizationReadbackGate] = useState(null) const [reportTruthActionabilityReview, setReportTruthActionabilityReview] = useState(null) const [ownerDryRunPackage, setOwnerDryRunPackage] = useState(null) const [hostStatefulInventory, setHostStatefulInventory] = useState(null) @@ -558,6 +560,7 @@ export function AutomationInventoryTab() { apiClient.getAiAgentResultCapturePostReleaseVerifierRollbackGate(), apiClient.getAiAgentResultCaptureFinalReleaseCandidateReadback(), apiClient.getAiAgentResultCaptureReleaseAuthorizationHold(), + apiClient.getAiAgentResultCaptureReleaseAuthorizationReadbackGate(), apiClient.getAiAgentReportTruthActionabilityReview(), apiClient.getAiAgentOwnerApprovedFixtureDryRun(), apiClient.getAiAgentHostStatefulVersionInventory(), @@ -628,6 +631,7 @@ export function AutomationInventoryTab() { resultCapturePostReleaseVerifierRollbackGateResult, resultCaptureFinalReleaseCandidateReadbackResult, resultCaptureReleaseAuthorizationHoldResult, + resultCaptureReleaseAuthorizationReadbackGateResult, reportTruthActionabilityReviewResult, ownerDryRunPackageResult, hostStatefulInventoryResult, @@ -695,6 +699,7 @@ export function AutomationInventoryTab() { setResultCapturePostReleaseVerifierRollbackGate(resultCapturePostReleaseVerifierRollbackGateResult.status === 'fulfilled' ? resultCapturePostReleaseVerifierRollbackGateResult.value : null) setResultCaptureFinalReleaseCandidateReadback(resultCaptureFinalReleaseCandidateReadbackResult.status === 'fulfilled' ? resultCaptureFinalReleaseCandidateReadbackResult.value : null) setResultCaptureReleaseAuthorizationHold(resultCaptureReleaseAuthorizationHoldResult.status === 'fulfilled' ? resultCaptureReleaseAuthorizationHoldResult.value : null) + setResultCaptureReleaseAuthorizationReadbackGate(resultCaptureReleaseAuthorizationReadbackGateResult.status === 'fulfilled' ? resultCaptureReleaseAuthorizationReadbackGateResult.value : null) setReportTruthActionabilityReview(reportTruthActionabilityReviewResult.status === 'fulfilled' ? reportTruthActionabilityReviewResult.value : null) setOwnerDryRunPackage(ownerDryRunPackageResult.status === 'fulfilled' ? ownerDryRunPackageResult.value : null) setHostStatefulInventory(hostStatefulInventoryResult.status === 'fulfilled' ? hostStatefulInventoryResult.value : null) @@ -760,6 +765,7 @@ export function AutomationInventoryTab() { resultCapturePostReleaseVerifierRollbackGateResult, resultCaptureFinalReleaseCandidateReadbackResult, resultCaptureReleaseAuthorizationHoldResult, + resultCaptureReleaseAuthorizationReadbackGateResult, reportTruthActionabilityReviewResult, ownerDryRunPackageResult, hostStatefulInventoryResult, @@ -2002,7 +2008,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 || !runtimeReadbackImplementationReview || !reportLiveDeliveryApprovalPackage || !runtimeReadbackFixtureApproval || !runtimeReadbackPromotionGate || !ownerApprovedFixturePromotionGate || !canonicalRuntimeReadbackOwnerAcceptance || !failureReceiptNoSendReplay || !reviewerQueueNoWriteReadback || !resultCaptureNoWriteReadback || !resultCapturePromotionApprovalGate || !ownerApprovedResultCapturePromotionDryRun || !resultCaptureWriteGateReview || !resultCaptureWriterImplementationReview || !resultCaptureWriterDryRunFixture || !resultCaptureWriterDryRunReadback || !resultCaptureOwnerPromotionReview || !resultCaptureOwnerApprovedExecutionRehearsal || !resultCaptureOwnerAcceptanceMaintenanceGate || !resultCaptureOwnerAcceptanceReadbackPreflightHold || !resultCaptureOwnerApprovedPreflightReleasePackage || !resultCaptureOwnerApprovedReleaseReadinessReadback || !resultCaptureOwnerReleaseApprovalGate || !resultCapturePostReleaseVerifierRollbackGate || !resultCaptureFinalReleaseCandidateReadback || !resultCaptureReleaseAuthorizationHold || !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 || !reportLiveDeliveryApprovalPackage || !runtimeReadbackFixtureApproval || !runtimeReadbackPromotionGate || !ownerApprovedFixturePromotionGate || !canonicalRuntimeReadbackOwnerAcceptance || !failureReceiptNoSendReplay || !reviewerQueueNoWriteReadback || !resultCaptureNoWriteReadback || !resultCapturePromotionApprovalGate || !ownerApprovedResultCapturePromotionDryRun || !resultCaptureWriteGateReview || !resultCaptureWriterImplementationReview || !resultCaptureWriterDryRunFixture || !resultCaptureWriterDryRunReadback || !resultCaptureOwnerPromotionReview || !resultCaptureOwnerApprovedExecutionRehearsal || !resultCaptureOwnerAcceptanceMaintenanceGate || !resultCaptureOwnerAcceptanceReadbackPreflightHold || !resultCaptureOwnerApprovedPreflightReleasePackage || !resultCaptureOwnerApprovedReleaseReadinessReadback || !resultCaptureOwnerReleaseApprovalGate || !resultCapturePostReleaseVerifierRollbackGate || !resultCaptureFinalReleaseCandidateReadback || !resultCaptureReleaseAuthorizationHold || !resultCaptureReleaseAuthorizationReadbackGate || !reportTruthActionabilityReview || !ownerDryRunPackage || !hostStatefulInventory || !serviceHealthGapMatrix || !serviceHealthNotificationPolicy) { return (
@@ -3182,6 +3188,40 @@ export function AutomationInventoryTab() { + resultCaptureReleaseAuthorizationHold.rollups.playbook_trust_write_count + resultCaptureReleaseAuthorizationHold.rollups.production_write_count ) + const resultCaptureReleaseReadbackOverall = resultCaptureReleaseAuthorizationReadbackGate.program_status.overall_completion_percent + const resultCaptureReleaseReadbacks = resultCaptureReleaseAuthorizationReadbackGate.rollups.release_authorization_readback_count + const resultCaptureReleaseReadbackRollbacks = resultCaptureReleaseAuthorizationReadbackGate.rollups.rollback_release_readback_count + const resultCaptureReleaseReadbackMaintenanceHolds = resultCaptureReleaseAuthorizationReadbackGate.rollups.maintenance_window_readback_hold_count + const resultCaptureReleaseReadbackLiveApplyHolds = resultCaptureReleaseAuthorizationReadbackGate.rollups.live_apply_release_readback_hold_count + const resultCaptureReleaseReadbackBlockedTransitions = resultCaptureReleaseAuthorizationReadbackGate.rollups.blocked_release_readback_transition_count + const resultCaptureReleaseReadbackActions = resultCaptureReleaseAuthorizationReadbackGate.rollups.operator_action_count + const resultCaptureReleaseReadbackApprovalRequired = ( + resultCaptureReleaseAuthorizationReadbackGate.rollups.approval_required_authorization_readback_count + + resultCaptureReleaseAuthorizationReadbackGate.rollups.approval_required_rollback_readback_count + + resultCaptureReleaseAuthorizationReadbackGate.rollups.approval_required_maintenance_window_count + + resultCaptureReleaseAuthorizationReadbackGate.rollups.approval_required_live_apply_readback_count + ) + const resultCaptureReleaseReadbackBlocked = ( + resultCaptureReleaseAuthorizationReadbackGate.rollups.blocked_authorization_readback_count + + resultCaptureReleaseAuthorizationReadbackGate.rollups.blocked_rollback_readback_count + + resultCaptureReleaseAuthorizationReadbackGate.rollups.blocked_maintenance_window_count + + resultCaptureReleaseAuthorizationReadbackGate.rollups.blocked_live_apply_readback_count + + resultCaptureReleaseAuthorizationReadbackGate.rollups.critical_blocker_count + ) + const resultCaptureReleaseReadbackLiveWrites = ( + resultCaptureReleaseAuthorizationReadbackGate.rollups.writer_apply_count + + resultCaptureReleaseAuthorizationReadbackGate.rollups.execution_apply_count + + resultCaptureReleaseAuthorizationReadbackGate.rollups.receipt_write_count + + resultCaptureReleaseAuthorizationReadbackGate.rollups.reviewer_queue_write_count + + resultCaptureReleaseAuthorizationReadbackGate.rollups.gateway_queue_write_count + + resultCaptureReleaseAuthorizationReadbackGate.rollups.telegram_send_count + + resultCaptureReleaseAuthorizationReadbackGate.rollups.bot_api_call_count + + resultCaptureReleaseAuthorizationReadbackGate.rollups.report_receipt_write_count + + resultCaptureReleaseAuthorizationReadbackGate.rollups.result_capture_write_count + + resultCaptureReleaseAuthorizationReadbackGate.rollups.learning_write_count + + resultCaptureReleaseAuthorizationReadbackGate.rollups.playbook_trust_write_count + + resultCaptureReleaseAuthorizationReadbackGate.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 @@ -7893,6 +7933,174 @@ export function AutomationInventoryTab() {
+
+
+
+ + + {t('resultCaptureReleaseAuthorizationReadbackGate.title')} + +
+ +
+ +
+ } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> +
+ +
+
+ {t('resultCaptureReleaseAuthorizationReadbackGate.priorTitle')} +

+ {resultCaptureReleaseAuthorizationReadbackGate.prior_release_authorization_hold.readiness_note} +

+
+ + + +
+
+ +
+ {t('resultCaptureReleaseAuthorizationReadbackGate.truthTitle')} +

+ {resultCaptureReleaseAuthorizationReadbackGate.release_authorization_readback_truth.truth_note} +

+
+ + + + + + +
+
+
+ +
+ {resultCaptureReleaseAuthorizationReadbackGate.release_authorization_readbacks.slice(0, 5).map(readback => ( +
+
+ + {readback.display_name} + + +
+ + {readback.readback_summary} + +
+ + + + + +
+
+ ))} +
+ +
+ {resultCaptureReleaseAuthorizationReadbackGate.rollback_release_readbacks.slice(0, 5).map(readback => ( +
+
+ + {readback.display_name} + + +
+ + {readback.readback_summary} + +
+ + + + +
+
+ ))} +
+ +
+ {resultCaptureReleaseAuthorizationReadbackGate.maintenance_window_readback_holds.slice(0, 5).map(hold => ( +
+
+ + {hold.display_name} + + +
+ + {hold.hold_reason} + +
+ + + +
+
+ ))} +
+ +
+ {resultCaptureReleaseAuthorizationReadbackGate.live_apply_release_readback_holds.slice(0, 5).map(hold => ( +
+
+ + {hold.display_name} + + +
+ + {hold.release_condition} + +
+ + + +
+
+ ))} +
+ +
+ {resultCaptureReleaseAuthorizationReadbackGate.operator_actions.slice(0, 5).map(action => ( +
+
+ + {action.action_id} + + +
+ + {action.operator_instruction} + +
+ + +
+
+ ))} +
+
+
diff --git a/apps/web/src/lib/api-client.ts b/apps/web/src/lib/api-client.ts index 8282eccb..e1de7e8d 100644 --- a/apps/web/src/lib/api-client.ts +++ b/apps/web/src/lib/api-client.ts @@ -570,6 +570,11 @@ export const apiClient = { return handleResponse(res) }, + async getAiAgentResultCaptureReleaseAuthorizationReadbackGate() { + const res = await fetch(`${API_BASE_URL}/agents/agent-result-capture-release-authorization-readback-gate`) + return handleResponse(res) + }, + async getAiAgentOwnerApprovedFixtureDryRun() { const res = await fetch(`${API_BASE_URL}/agents/agent-owner-approved-fixture-dry-run`) return handleResponse(res) @@ -8398,6 +8403,224 @@ export interface AiAgentResultCaptureReleaseAuthorizationHoldSnapshot { } } +export interface AiAgentResultCaptureReleaseAuthorizationReadbackGateSnapshot { + schema_version: 'ai_agent_result_capture_release_authorization_readback_gate_v1' + generated_at: string + program_status: { + overall_completion_percent: number + current_priority: 'P0' | 'P1' | 'P2' | 'P3' + current_task_id: 'P2-135' + next_task_id: 'P2-136' + read_only_mode: true + runtime_authority: 'result_capture_release_authorization_readback_gate_only_no_live_write' + status_note: string + } + source_refs: string[] + prior_release_authorization_hold: { + schema_version: string + release_authorization_hold_count: number + rollback_authorization_hold_count: number + release_window_hold_count: number + live_apply_authorization_hold_count: number + blocked_authorization_transition_count: number + operator_action_count: number + approval_required_total: number + blocked_total: number + owner_release_authorized_count: number + owner_release_approved_count: number + maintenance_window_approved_count: number + rollback_owner_confirmed_count: number + post_release_verifier_ready_count: number + final_release_candidate_approved_count: number + final_release_candidate_pass_count: number + release_authorization_granted_count: number + release_authorization_pass_count: number + rollback_release_pass_count: number + live_apply_release_pass_count: number + writer_apply_count: number + execution_apply_count: number + receipt_write_count: number + result_capture_write_count: number + learning_write_count: number + playbook_trust_write_count: number + reviewer_queue_write_count: number + gateway_queue_write_count: number + telegram_send_count: number + bot_api_call_count: number + report_receipt_write_count: number + readiness_note: string + } + release_authorization_readback_truth: { + p2_134_release_authorization_hold_loaded: boolean + release_authorization_readback_ready: boolean + rollback_release_readback_ready: boolean + maintenance_window_readback_hold_active: boolean + live_apply_release_readback_hold_active: boolean + owner_authorization_review_still_required: boolean + release_verifier_review_still_required: boolean + rollback_owner_review_required: boolean + redaction_review_required: boolean + release_authorization_readback_only: boolean + owner_release_authorized: boolean + owner_release_approved: boolean + maintenance_window_approved: boolean + rollback_owner_confirmed: boolean + post_release_verifier_ready: boolean + final_release_candidate_approved: boolean + final_release_candidate_passed: boolean + release_authorization_granted: boolean + release_authorization_passed: boolean + rollback_release_passed: boolean + live_apply_release_passed: boolean + writer_apply_enabled: boolean + execution_apply_enabled: boolean + receipt_write_enabled: boolean + reviewer_queue_write_enabled: boolean + gateway_queue_write_enabled: boolean + telegram_send_enabled: boolean + bot_api_call_enabled: boolean + report_receipt_write_enabled: boolean + result_capture_write_enabled: boolean + learning_write_enabled: boolean + playbook_trust_write_enabled: boolean + production_write_enabled: boolean + secret_read_enabled: boolean + destructive_operation_enabled: boolean + owner_release_authorized_count: number + owner_release_approved_count: number + maintenance_window_approved_count: number + rollback_owner_confirmed_count: number + post_release_verifier_ready_count: number + final_release_candidate_approved_count: number + final_release_candidate_pass_count: number + release_authorization_granted_count: number + release_authorization_pass_count: number + rollback_release_pass_count: number + live_apply_release_pass_count: number + writer_apply_count: number + execution_apply_count: number + receipt_write_count: number + reviewer_queue_write_count: number + gateway_queue_write_count: number + telegram_send_count: number + bot_api_call_count: number + report_receipt_write_count: number + result_capture_write_count: number + learning_write_count: number + playbook_trust_write_count: number + production_write_count: number + secret_read_count: number + destructive_operation_count: number + truth_note: string + } + release_authorization_readbacks: Array<{ + readback_id: string + display_name: string + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + source_authorization_hold: string + status: 'ready_for_owner_review' | 'approval_required' | 'blocked_by_policy' + readback_mode: 'release_authorization_readback_gate' + owner_release_authorized: false + release_authorization_granted: false + release_authorization_passed: false + readback_summary: string + evidence_hash: string + }> + rollback_release_readbacks: Array<{ + readback_id: string + display_name: string + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + status: 'ready_for_owner_review' | 'approval_required' | 'blocked_by_policy' + readback_mode: 'rollback_release_readback_gate' + rollback_owner_required: true + rollback_owner_confirmed: false + rollback_release_passed: false + rollback_release_enabled: false + readback_summary: string + }> + maintenance_window_readback_holds: Array<{ + hold_id: string + display_name: string + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + status: 'ready_for_owner_review' | 'approval_required' | 'blocked_by_policy' + hold_mode: 'maintenance_window_readback_hold' + owner_release_authorized: false + maintenance_window_approved: false + final_release_candidate_passed: false + hold_reason: string + }> + live_apply_release_readback_holds: Array<{ + hold_id: string + display_name: string + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + status: 'ready_for_owner_review' | 'approval_required' | 'blocked_by_policy' + hold_mode: 'live_apply_release_readback_hold' + release_authorization_granted: false + release_authorization_passed: false + live_apply_release_passed: false + live_apply_release_enabled: false + release_condition: string + }> + operator_actions: Array<{ + action_id: string + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + status: 'ready_for_operator_review' | 'approval_required' + operator_instruction: string + runtime_write_allowed: false + }> + display_redaction_contract: { + redaction_required: true + raw_prompt_display_allowed: false + private_reasoning_display_allowed: false + secret_value_display_allowed: false + raw_runtime_payload_display_allowed: false + internal_collaboration_content_display_allowed: false + frontend_display_policy: string + } + rollups: { + release_authorization_readback_count: number + rollback_release_readback_count: number + maintenance_window_readback_hold_count: number + live_apply_release_readback_hold_count: number + blocked_release_readback_transition_count: number + operator_action_count: number + approval_required_authorization_readback_count: number + blocked_authorization_readback_count: number + approval_required_rollback_readback_count: number + blocked_rollback_readback_count: number + approval_required_maintenance_window_count: number + blocked_maintenance_window_count: number + approval_required_live_apply_readback_count: number + blocked_live_apply_readback_count: number + critical_blocker_count: number + owner_release_authorized_count: number + owner_release_approved_count: number + maintenance_window_approved_count: number + rollback_owner_confirmed_count: number + post_release_verifier_ready_count: number + final_release_candidate_approved_count: number + final_release_candidate_pass_count: number + release_authorization_granted_count: number + release_authorization_pass_count: number + rollback_release_pass_count: number + live_apply_release_pass_count: number + writer_apply_count: number + execution_apply_count: number + receipt_write_count: number + reviewer_queue_write_count: number + gateway_queue_write_count: number + telegram_send_count: number + bot_api_call_count: number + report_receipt_write_count: number + result_capture_write_count: number + learning_write_count: number + playbook_trust_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 fe043945..eb040714 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -1,3 +1,29 @@ +## 2026-06-14|P2-135 釋出授權讀回關卡本地完成 + +**背景**:P2-134 已把 release authorization hold 正式驗證完成;但授權保留仍不得被誤讀成 owner release authorized、release authorization granted / passed、rollback release passed 或 live apply release passed。P2-135 因此只建立 release authorization readback gate,把 release authorization hold、rollback authorization hold、release window hold、live-apply authorization hold 與 blocked authorization transition 讀回成下一關可審核狀態,不接受口頭批准、不核發 release authorization、不釋放 rollback release 或 live apply、不套用 writer、不寫 receipt、不寫 result capture / learning / PlayBook trust / reviewer queue / Gateway queue,也不送 Telegram 或呼叫 Bot API。 + +**完成內容**: +- 新增 `ai_agent_result_capture_release_authorization_readback_gate_v1` schema、committed snapshot、loader 與 API endpoint `GET /api/v1/agents/agent-result-capture-release-authorization-readback-gate`。 +- P2-135 snapshot 固定 5 個 release authorization readback、5 個 rollback release readback、5 個 maintenance window readback hold、5 個 live-apply release readback hold、6 個 blocked release readback transition 與 5 個 operator action。 +- Governance automation inventory 頁新增 P2-135 區塊,顯示 P2-135 進度 `100%`、授權讀回 `5`、回滾讀回 `5`、維護窗口保留 `5`、正式套用保留 `5`、已阻擋讀回 `6`、operator action `5`、需批准 `8`、阻擋 `9`、正式寫入 / 發送 `0`。 +- Release authorization readback truth 固定為 `result_capture_release_authorization_readback_gate_only_no_live_write`;owner release authorized、owner release approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、final release candidate approved、final release candidate passed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API、report receipt、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive operation 仍全部維持 `0 / false`。 + +**本地驗證**: +- JSON parse:P2-135 schema / snapshot、`zh-TW.json`、`en.json` 通過。 +- Python 編譯:P2-135 loader 與 `agents.py` 通過。 +- API/service pytest:P2-135 + P2-134 regression `14 passed`。 +- Web typecheck:`pnpm --filter @awoooi/web typecheck` 通過。 + +**CD 狀態同步**: +- P2-135 目前仍是本地完成,尚未宣稱正式部署完成。 +- 下一步會先跑 Web production build、`git diff --check`、文件 secrets sanity、owner-response guard 與 security mirror guard,再推送 Gitea main、等待 CD,最後以正式 API 與 Browser desktop / mobile smoke 驗證。 + +**安全邊界**: +- P2-135 仍是 release authorization readback gate;不接受口頭批准、不把 authorization readback 解讀成 owner release authorized、不批准維護窗口、不確認 rollback owner、不通過 final candidate、不核發 release authorization、不通過 release authorization、不通過 rollback release、不釋放 live apply、不套用 writer、不執行正式寫入、不寫 receipt、不寫 result capture、不寫 learning、不更新 PlayBook trust、不寫 reviewer queue、不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 report receipt、不讀 canonical runtime target、不做 live query、不寫 production target、不讀 secret、不執行 destructive action、不回傳內部協作內容。 + +**下一步**: +- `P2-136`:必須等 P2-135 正式部署與 production smoke 完成後,才可承接 release authorization readback gate 後續關卡;仍不得直接開啟 result capture writer、learning writer、PlayBook trust writer、reviewer queue write、Gateway queue write、Telegram send、Bot API call 或 production write。 + ## 2026-06-14|Post-CD reboot recovery readback 無回歸 **背景**:`gitea/main` 從 `2b22c9d6 docs(ops): record 110 fwupd cleanup [skip ci]` 前進到 deploy marker `18b867c3 chore(cd): deploy e0a6d33 [skip ci]` 後,需確認 P2-134 相關 CD 沒有讓主機重啟 / cold-start SOP 狀態倒退。 @@ -15,6 +41,7 @@ - 可以宣稱 post-CD 沒有造成 reboot recovery regression。 - 不能宣稱 full cold-start green、ArgoCD Healthy 或 DR complete;下一個真正完成 gate 仍是下一次官方 03:00 `km-vectorize` 成功更新 `lastSuccessfulTime`,以及 5 個 credential escrow non-secret evidence marker。 + ## 2026-06-14|110 fwupd failed-unit 清理與 cold-start WARN 收斂 **背景**:03:00 官方 `km-vectorize-29689620` 失敗後,08:23 live refresh 顯示 AWOOOI core service、backup、offsite、public routes、120/121 K3s 與 API/Web workload 仍可用;但 cold-start scorecard 仍有兩個 WARN:`km-vectorize` failed Job 與 110 `fwupd-refresh.service` / `fwupd.service` failed units。 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 86ce2882..9de0d79f 100644 --- a/docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md +++ b/docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md @@ -12,25 +12,25 @@ | 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 到 P2-134 已完成只讀證據面、runtime / report / result-capture gates、no-write readback、promotion review、writer implementation review、writer dry-run fixture、writer dry-run readback、owner promotion execution gate、owner-approved execution rehearsal、owner acceptance / maintenance window gate、owner acceptance readback / preflight hold、owner-approved preflight release package、owner-approved release readiness readback、owner release approval gate、post-release verifier / rollback gate、final release candidate readback 與 release authorization hold;P2-134 已正式驗證,固定 5 個 release authorization hold、5 個 rollback authorization hold、5 個 release window hold、5 個 live-apply authorization hold、6 個 blocked authorization transition 與 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、live report delivery、reviewer queue write、Gateway queue write、AI analysis runtime、中低風險 auto worker、KM / LOGBOOK / audit DB / timeline / PlayBook trust 寫入、SDK / 付費服務仍未開 gate | `ai_agent_result_capture_release_authorization_hold_v1`、`GET /api/v1/agents/agent-result-capture-release-authorization-hold`、P2-134 本地 pytest `14 passed`、Web typecheck / build / guard 通過、正式站 deploy marker `18b867c3`、正式 API readback、正式站 `/zh-TW/governance?tab=automation-inventory&_v=18b867c3-p2-134-prod-desktop` desktop / mobile smoke、禁用內部協作片語 `0`、水平溢位 `0`、危險控制 `0`、console error `0`、`ai_agent_result_capture_final_release_candidate_readback_v1`、`GET /api/v1/agents/agent-result-capture-final-release-candidate-readback`、正式站 deploy marker `8be5ddab`、`ai_agent_result_capture_post_release_verifier_rollback_gate_v1`、`GET /api/v1/agents/agent-result-capture-post-release-verifier-rollback-gate`、正式站 deploy marker `934af770`、正式站 `/zh-TW/governance?tab=automation-inventory` desktop / mobile smoke、`ai_agent_result_capture_owner_release_approval_gate_v1`、`GET /api/v1/agents/agent-result-capture-owner-release-approval-gate`、正式站 deploy marker `03617db7`、`ai_agent_result_capture_owner_approved_release_readiness_readback_v1`、`GET /api/v1/agents/agent-result-capture-owner-approved-release-readiness-readback`、正式站 deploy marker `6fcf7241`、`ai_agent_result_capture_owner_approved_preflight_release_package_v1`、`GET /api/v1/agents/agent-result-capture-owner-approved-preflight-release-package`、`ai_agent_result_capture_owner_acceptance_readback_preflight_hold_v1`、`GET /api/v1/agents/agent-result-capture-owner-acceptance-readback-preflight-hold`、`ai_agent_result_capture_owner_acceptance_maintenance_gate_v1`、`GET /api/v1/agents/agent-result-capture-owner-acceptance-maintenance-gate`、`ai_agent_result_capture_owner_approved_execution_rehearsal_v1`、`GET /api/v1/agents/agent-result-capture-owner-approved-execution-rehearsal`、`ai_agent_result_capture_owner_promotion_review_v1`、`ai_agent_result_capture_writer_dry_run_readback_v1`、`ai_agent_result_capture_writer_dry_run_fixture_v1`、`ai_agent_result_capture_writer_implementation_review_v1`、`ai_agent_result_capture_write_gate_review_v1`、`ai_agent_interaction_learning_proof_v1`、MASTER §3.2.1b / §3.2.1d / §3.4.3 | +| OpenClaw / Hermes / NemoTron 主動溝通、學習與成長證據 | 100% | P2-401A 到 P2-135 已完成只讀證據面、runtime / report / result-capture gates、no-write readback、promotion review、writer implementation review、writer dry-run fixture、writer dry-run readback、owner promotion execution gate、owner-approved execution rehearsal、owner acceptance / maintenance window gate、owner acceptance readback / preflight hold、owner-approved preflight release package、owner-approved release readiness readback、owner release approval gate、post-release verifier / rollback gate、final release candidate readback、release authorization hold 與 release authorization readback gate;P2-135 已本地完成,固定 5 個 release authorization readback、5 個 rollback release readback、5 個 maintenance window readback hold、5 個 live-apply release readback hold、6 個 blocked release readback transition 與 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、live report delivery、reviewer queue write、Gateway queue write、AI analysis runtime、中低風險 auto worker、KM / LOGBOOK / audit DB / timeline / PlayBook trust 寫入、SDK / 付費服務仍未開 gate | `ai_agent_result_capture_release_authorization_readback_gate_v1`、`GET /api/v1/agents/agent-result-capture-release-authorization-readback-gate`、P2-135 + P2-134 本地 pytest `14 passed`、JSON parse、Python compile、Web typecheck 通過、正式部署與 production smoke 待推進、`ai_agent_result_capture_release_authorization_hold_v1`、`GET /api/v1/agents/agent-result-capture-release-authorization-hold`、正式站 deploy marker `18b867c3`、正式 API readback、正式站 `/zh-TW/governance?tab=automation-inventory&_v=18b867c3-p2-134-prod-desktop` desktop / mobile smoke、禁用內部協作片語 `0`、水平溢位 `0`、危險控制 `0`、console error `0`、`ai_agent_result_capture_final_release_candidate_readback_v1`、`GET /api/v1/agents/agent-result-capture-final-release-candidate-readback`、正式站 deploy marker `8be5ddab`、`ai_agent_result_capture_post_release_verifier_rollback_gate_v1`、`GET /api/v1/agents/agent-result-capture-post-release-verifier-rollback-gate`、正式站 deploy marker `934af770`、正式站 `/zh-TW/governance?tab=automation-inventory` desktop / mobile smoke、`ai_agent_result_capture_owner_release_approval_gate_v1`、`GET /api/v1/agents/agent-result-capture-owner-release-approval-gate`、正式站 deploy marker `03617db7`、`ai_agent_result_capture_owner_approved_release_readiness_readback_v1`、`GET /api/v1/agents/agent-result-capture-owner-approved-release-readiness-readback`、正式站 deploy marker `6fcf7241`、`ai_agent_result_capture_owner_approved_preflight_release_package_v1`、`GET /api/v1/agents/agent-result-capture-owner-approved-preflight-release-package`、`ai_agent_result_capture_owner_acceptance_readback_preflight_hold_v1`、`GET /api/v1/agents/agent-result-capture-owner-acceptance-readback-preflight-hold`、`ai_agent_result_capture_owner_acceptance_maintenance_gate_v1`、`GET /api/v1/agents/agent-result-capture-owner-acceptance-maintenance-gate`、`ai_agent_result_capture_owner_approved_execution_rehearsal_v1`、`GET /api/v1/agents/agent-result-capture-owner-approved-execution-rehearsal`、`ai_agent_result_capture_owner_promotion_review_v1`、`ai_agent_result_capture_writer_dry_run_readback_v1`、`ai_agent_result_capture_writer_dry_run_fixture_v1`、`ai_agent_result_capture_writer_implementation_review_v1`、`ai_agent_result_capture_write_gate_review_v1`、`ai_agent_interaction_learning_proof_v1`、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 文件 | -### 2026-06-14 08:36 狀態同步 +### 2026-06-14 08:44 狀態同步 -- `P2-134` release authorization hold 已完成並正式驗證:新增 `ai_agent_result_capture_release_authorization_hold_v1`、`GET /api/v1/agents/agent-result-capture-release-authorization-hold`、治理頁 P2-134 區塊與繁中 UI 文案。 -- 本地證據:P2-134 + P2-133 API/service regression `14 passed`、JSON parse、Python compile、Web typecheck、`NEXT_PUBLIC_API_URL=https://awoooi.wooo.work pnpm --filter @awoooi/web build` 均通過;governance First Load JS `435 kB`。 -- P2-134 固定 5 個 release authorization hold、5 個 rollback authorization hold、5 個 release window hold、5 個 live-apply authorization hold、6 個 blocked authorization transition、5 個 operator action、需批准 `8`、阻擋 `9`、正式寫入 / 發送 `0`。 -- 邊界仍維持:owner release authorized、maintenance window approved、rollback owner confirmed、release authorization granted / passed、live apply release passed、writer apply、execution apply、receipt write、result capture write、learning write、PlayBook trust write、reviewer queue write、Gateway queue write、Telegram send、Bot API、production write、secret read、destructive operation 全部 `0 / false`。 -- 正式部署與 readback:feature commit `e0a6d339`、deploy marker `18b867c3`;正式 API 回 current `P2-134`、next `P2-135`、completion `100`、runtime authority `result_capture_release_authorization_hold_only_no_live_write`;desktop / mobile Browser smoke 均確認 P2-134 區塊可見、必要文案全命中、禁用內部協作片語 `0`、水平溢位 `0`、危險控制 `0`、console error `0`。下一步可交給 `P2-135`。 +- `P2-135` release authorization readback gate 已本地完成:新增 `ai_agent_result_capture_release_authorization_readback_gate_v1`、`GET /api/v1/agents/agent-result-capture-release-authorization-readback-gate`、治理頁 P2-135 區塊與繁中 UI 文案。 +- 本地證據:P2-135 + P2-134 API/service regression `14 passed`、JSON parse、Python compile、Web typecheck 均通過;Web production build、正式部署與 production smoke 待推進。 +- P2-135 固定 5 個 release authorization readback、5 個 rollback release readback、5 個 maintenance window readback hold、5 個 live-apply release readback hold、6 個 blocked release readback transition、5 個 operator action、需批准 `8`、阻擋 `9`、正式寫入 / 發送 `0`。 +- 邊界仍維持:owner release authorized、maintenance window approved、rollback owner confirmed、release authorization granted / passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、result capture write、learning write、PlayBook trust write、reviewer queue write、Gateway queue write、Telegram send、Bot API、production write、secret read、destructive operation 全部 `0 / false`。 +- P2-134 正式部署與 readback 已完成:feature commit `e0a6d339`、deploy marker `18b867c3`;正式 API 回 current `P2-134`、next `P2-135`、completion `100`、runtime authority `result_capture_release_authorization_hold_only_no_live_write`;desktop / mobile Browser smoke 均確認 P2-134 區塊可見。P2-135 正式驗證後才可交給 `P2-136`。 AI Agent 自動化工作包目前完成度:**99.8%**。本工作清單文件本身完成度:**100%**。 三 Agent 佈建布局目前完成度:**45%**。第一波已完成只讀 schema / snapshot / API / 測試 / 報告,第二波已接入治理頁自動化盤點 UI;正式 runtime 佈署、Telegram E2E 發送與 AgentSession 工作流仍需逐項 gate。 -三 Agent 主動溝通、學習與成長證據目前完成度:**100%**。P2-403A 到 P2-134 已把互動證據、報表治理、runtime readback、reviewer / result capture / writer gates、no-write readback、promotion review、writer implementation review、writer dry-run fixture、writer dry-run readback、owner promotion execution gate、owner-approved execution rehearsal、owner acceptance / maintenance window gate、owner acceptance readback / preflight hold、owner-approved preflight release package、owner-approved release readiness readback、owner release approval gate、post-release verifier / rollback gate、final release candidate readback 與 release authorization hold 全部固定成可驗證證據。P2-134 已正式驗證,deploy marker `18b867c3`;正式 API 回 `schema_version=ai_agent_result_capture_release_authorization_hold_v1`、current `P2-134`、next `P2-135`、completion `100`、runtime authority `result_capture_release_authorization_hold_only_no_live_write`;desktop / mobile smoke 均確認 P2-134 區塊可見、必要文案全命中、禁用內部協作片語 `0`、水平溢位 `0`、危險控制 `0`、console error `0`。目前 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、live report delivery、AI analysis runtime、中低風險 auto worker、Telegram 實發、shadow worker live、delivery receipt E2E、KM / LOGBOOK / audit DB / timeline / PlayBook trust runtime 寫入仍全部為 `0`。真正下一步是 `P2-135`。 +三 Agent 主動溝通、學習與成長證據目前完成度:**100%**。P2-403A 到 P2-135 已把互動證據、報表治理、runtime readback、reviewer / result capture / writer gates、no-write readback、promotion review、writer implementation review、writer dry-run fixture、writer dry-run readback、owner promotion execution gate、owner-approved execution rehearsal、owner acceptance / maintenance window gate、owner acceptance readback / preflight hold、owner-approved preflight release package、owner-approved release readiness readback、owner release approval gate、post-release verifier / rollback gate、final release candidate readback、release authorization hold 與 release authorization readback gate 全部固定成可驗證證據。P2-135 已本地完成;本地 API 回 `schema_version=ai_agent_result_capture_release_authorization_readback_gate_v1`、current `P2-135`、next `P2-136`、completion `100`、runtime authority `result_capture_release_authorization_readback_gate_only_no_live_write`;正式部署與 production smoke 待推進。P2-134 已正式驗證,deploy marker `18b867c3`;desktop / mobile smoke 均確認 P2-134 區塊可見。目前 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、live report delivery、AI analysis runtime、中低風險 auto worker、Telegram 實發、shadow worker live、delivery receipt E2E、KM / LOGBOOK / audit DB / timeline / PlayBook trust runtime 寫入仍全部為 `0`。真正下一步是 P2-135 正式驗證後的 `P2-136`。 -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-134` 已補互動、學習證據面、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 / readback、result capture writer dry-run fixture、writer dry-run readback、owner promotion execution gate、owner-approved execution rehearsal、owner acceptance / maintenance window gate、owner acceptance readback / preflight hold、owner-approved preflight release package、owner-approved release readiness readback、owner release approval gate、post-release verifier / rollback gate、final release candidate readback 與 release authorization hold。下一步是 `P2-135`;外部 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-135` 已補互動、學習證據面、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 / readback、result capture writer dry-run fixture、writer dry-run readback、owner promotion execution gate、owner-approved execution rehearsal、owner acceptance / maintenance window gate、owner acceptance readback / preflight hold、owner-approved preflight release package、owner-approved release readiness readback、owner release approval gate、post-release verifier / rollback gate、final release candidate readback、release authorization hold 與 release authorization readback gate。下一步是 P2-135 正式驗證後的 `P2-136`;外部 registry / package source / host probe / SSH / kubectl / 工具安裝 / CI 變更 / 實際 PR creation / Telegram 實發與 learning write 仍需 gate。 完成度計算模型: @@ -1015,7 +1015,8 @@ UI: | P2-132 | 完成 | 100 | OpenClaw + Hermes + NemoTron | post-release verifier / rollback gate | `ai_agent_result_capture_post_release_verifier_rollback_gate_v1` / schema / snapshot / 只讀 API / governance UI;正式站 deploy marker `934af770` 已驗證;5 個 post-release verifier gate、5 個 rollback release gate、5 個 release verification hold、5 個 live-apply post-release gate、6 個 blocked post-release transition、5 個 operator action;runtime authority 固定 `result_capture_post_release_verifier_rollback_gate_only_no_live_write`;post-release verifier ready / rollback release passed / release verification passed / live apply release passed / writer apply / execution apply / receipt write / result capture / learning / PlayBook trust / reviewer queue / Gateway / Telegram / Bot API / report receipt / production write 全為 `0` | 已由 P2-133 承接;不把 verifier gate 視為 release 通過、不釋放 live apply、不套用 writer、不寫 receipt、不寫 result capture、不寫 learning、不送 Telegram、不寫 production | | P2-133 | 完成 | 100 | OpenClaw + Hermes + NemoTron | final release candidate readback | `ai_agent_result_capture_final_release_candidate_readback_v1` / schema / snapshot / 只讀 API / governance UI;正式站 deploy marker `8be5ddab` 已驗證;5 個 final release candidate readback、5 個 rollback candidate readback、5 個 candidate acceptance hold、5 個 live-apply candidate hold、6 個 blocked final candidate transition、5 個 operator action;runtime authority 固定 `result_capture_final_release_candidate_readback_only_no_live_write`;owner release approved / maintenance window approved / rollback owner confirmed / final candidate passed / live apply release passed / writer apply / execution apply / receipt write / result capture / learning / PlayBook trust / reviewer queue / Gateway / Telegram / Bot API / report receipt / production write 全為 `0`;desktop / mobile smoke 禁用內部協作片語 `0`、水平溢位 `0`、P2-133 高風險控制 `0`、console error `0` | 已由 P2-134 承接;不把 candidate readback 視為 owner release approved、不釋放 live apply、不套用 writer、不寫 receipt、不寫 result capture、不寫 learning、不送 Telegram、不寫 production | | P2-134 | 完成 | 100 | OpenClaw + Hermes + NemoTron | release authorization hold | `ai_agent_result_capture_release_authorization_hold_v1` / schema / snapshot / 只讀 API / governance UI;正式站 deploy marker `18b867c3` 已驗證;5 個 release authorization hold、5 個 rollback authorization hold、5 個 release window hold、5 個 live-apply authorization hold、6 個 blocked authorization transition、5 個 operator action;runtime authority 固定 `result_capture_release_authorization_hold_only_no_live_write`;owner release authorized / maintenance window approved / rollback owner confirmed / release authorization granted / release authorization passed / live apply release passed / writer apply / execution apply / receipt write / result capture / learning / PlayBook trust / reviewer queue / Gateway / Telegram / Bot API / report receipt / production write / secret read / destructive operation 全為 `0`;desktop / mobile smoke 禁用內部協作片語 `0`、水平溢位 `0`、P2-134 區塊危險操作入口 `0`、console error `0`、critical network issue `0` | 已由 P2-135 承接;不把 authorization hold 視為正式授權、不釋放 live apply、不套用 writer、不寫 receipt、不寫 result capture、不寫 learning、不送 Telegram、不寫 production | -| P2-135 | 待辦 | 0 | OpenClaw + Hermes + NemoTron | release authorization readback / no-write release gate | 待建立 P2-134 release authorization hold 的 readback、rollback hold readback、release window readback、live-apply hold readback 與 blocked release transition 證據;必須維持只讀 API / governance UI / redaction | 不讀 canonical runtime target、不做 live query、不寫 reviewer queue、不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 receipt、不寫 result capture、不寫 learning、不更新 PlayBook trust、不寫 production | +| P2-135 | 進行中 | 100 | OpenClaw + Hermes + NemoTron | release authorization readback gate | `ai_agent_result_capture_release_authorization_readback_gate_v1` / schema / snapshot / 只讀 API / governance UI;本地 pytest `14 passed`、JSON parse、Python compile、Web typecheck 通過;5 個 release authorization readback、5 個 rollback release readback、5 個 maintenance window readback hold、5 個 live-apply release readback hold、6 個 blocked release readback transition、5 個 operator action;runtime authority 固定 `result_capture_release_authorization_readback_gate_only_no_live_write`;owner release authorized、release authorization granted / passed、rollback release、live apply release、writer apply、execution apply、receipt write、result capture、learning、PlayBook trust、Gateway、Telegram、production write 全為 `0` | 正式部署與 production smoke 待推進;完成後才可由 P2-136 承接,不核發 release authorization、不釋放 live apply、不套用 writer | + ### P3 - 候選 Agent 擴展 diff --git a/docs/evaluations/ai_agent_result_capture_release_authorization_readback_gate_2026-06-14.json b/docs/evaluations/ai_agent_result_capture_release_authorization_readback_gate_2026-06-14.json new file mode 100644 index 00000000..d72c68dd --- /dev/null +++ b/docs/evaluations/ai_agent_result_capture_release_authorization_readback_gate_2026-06-14.json @@ -0,0 +1,507 @@ +{ + "schema_version": "ai_agent_result_capture_release_authorization_readback_gate_v1", + "generated_at": "2026-06-14T08:44:07+08:00", + "program_status": { + "overall_completion_percent": 100, + "current_priority": "P2", + "current_task_id": "P2-135", + "next_task_id": "P2-136", + "read_only_mode": true, + "runtime_authority": "result_capture_release_authorization_readback_gate_only_no_live_write", + "status_note": "P2-135 只把 P2-134 release authorization hold 讀回為 release authorization readback gate;不得視為 owner release authorized,不得核發 release authorization,不得通過 rollback release 或 live apply,不得套用 writer、寫 receipt、寫 result capture、寫 learning、寫 queue、送 Telegram 或寫入 production。" + }, + "source_refs": [ + "docs/evaluations/ai_agent_result_capture_release_authorization_hold_2026-06-14.json", + "docs/evaluations/ai_agent_result_capture_final_release_candidate_readback_2026-06-14.json", + "docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md#55-建立-release-authorization-hold" + ], + "prior_release_authorization_hold": { + "schema_version": "ai_agent_result_capture_release_authorization_hold_v1", + "release_authorization_hold_count": 5, + "rollback_authorization_hold_count": 5, + "release_window_hold_count": 5, + "live_apply_authorization_hold_count": 5, + "blocked_authorization_transition_count": 6, + "operator_action_count": 5, + "approval_required_total": 8, + "blocked_total": 9, + "owner_release_authorized_count": 0, + "owner_release_approved_count": 0, + "maintenance_window_approved_count": 0, + "rollback_owner_confirmed_count": 0, + "post_release_verifier_ready_count": 0, + "final_release_candidate_approved_count": 0, + "final_release_candidate_pass_count": 0, + "release_authorization_granted_count": 0, + "release_authorization_pass_count": 0, + "rollback_release_pass_count": 0, + "live_apply_release_pass_count": 0, + "writer_apply_count": 0, + "execution_apply_count": 0, + "receipt_write_count": 0, + "result_capture_write_count": 0, + "learning_write_count": 0, + "playbook_trust_write_count": 0, + "reviewer_queue_write_count": 0, + "gateway_queue_write_count": 0, + "telegram_send_count": 0, + "bot_api_call_count": 0, + "report_receipt_write_count": 0, + "readiness_note": "P2-134 已把 release authorization hold、rollback authorization hold、release window hold、live-apply authorization hold 與 blocked authorization transition 固定為只讀保留;P2-135 只讀回 gate,不核發 release authorization。" + }, + "release_authorization_readback_truth": { + "p2_134_release_authorization_hold_loaded": true, + "release_authorization_readback_ready": true, + "rollback_release_readback_ready": true, + "maintenance_window_readback_hold_active": true, + "live_apply_release_readback_hold_active": true, + "owner_authorization_review_still_required": true, + "release_verifier_review_still_required": true, + "rollback_owner_review_required": true, + "redaction_review_required": true, + "release_authorization_readback_only": true, + "owner_release_authorized": false, + "owner_release_approved": false, + "maintenance_window_approved": false, + "rollback_owner_confirmed": false, + "post_release_verifier_ready": false, + "final_release_candidate_approved": false, + "final_release_candidate_passed": false, + "release_authorization_granted": false, + "release_authorization_passed": false, + "rollback_release_passed": false, + "live_apply_release_passed": false, + "writer_apply_enabled": false, + "execution_apply_enabled": false, + "receipt_write_enabled": false, + "reviewer_queue_write_enabled": false, + "gateway_queue_write_enabled": false, + "telegram_send_enabled": false, + "bot_api_call_enabled": false, + "report_receipt_write_enabled": false, + "result_capture_write_enabled": false, + "learning_write_enabled": false, + "playbook_trust_write_enabled": false, + "production_write_enabled": false, + "secret_read_enabled": false, + "destructive_operation_enabled": false, + "owner_release_authorized_count": 0, + "owner_release_approved_count": 0, + "maintenance_window_approved_count": 0, + "rollback_owner_confirmed_count": 0, + "post_release_verifier_ready_count": 0, + "final_release_candidate_approved_count": 0, + "final_release_candidate_pass_count": 0, + "release_authorization_granted_count": 0, + "release_authorization_pass_count": 0, + "rollback_release_pass_count": 0, + "live_apply_release_pass_count": 0, + "writer_apply_count": 0, + "execution_apply_count": 0, + "receipt_write_count": 0, + "reviewer_queue_write_count": 0, + "gateway_queue_write_count": 0, + "telegram_send_count": 0, + "bot_api_call_count": 0, + "report_receipt_write_count": 0, + "result_capture_write_count": 0, + "learning_write_count": 0, + "playbook_trust_write_count": 0, + "production_write_count": 0, + "secret_read_count": 0, + "destructive_operation_count": 0, + "truth_note": "P2-135 只讀回 release authorization gate;readback 可見不代表 owner release authorized、release authorization granted / passed、rollback release passed 或 live apply release passed。" + }, + "release_authorization_readbacks": [ + { + "readback_id": "release_authorization_readback_result_capture", + "display_name": "Result capture release authorization readback", + "owner_agent": "openclaw", + "source_authorization_hold": "release_authorization_result_capture", + "status": "ready_for_owner_review", + "readback_mode": "release_authorization_readback_gate", + "owner_release_authorized": false, + "release_authorization_granted": false, + "release_authorization_passed": false, + "readback_summary": "讀回 Result capture release authorization hold;仍未取得 owner authorization、maintenance window、rollback owner 與 release authorization pass,不得寫入或發送。", + "evidence_hash": "sha256:8111111111111111111111111111111111111111111111111111111111111111" + }, + { + "readback_id": "release_authorization_readback_learning", + "display_name": "Learning release authorization readback", + "owner_agent": "hermes", + "source_authorization_hold": "release_authorization_learning", + "status": "approval_required", + "readback_mode": "release_authorization_readback_gate", + "owner_release_authorized": false, + "release_authorization_granted": false, + "release_authorization_passed": false, + "readback_summary": "讀回 Learning release authorization hold;仍未取得 owner authorization、maintenance window、rollback owner 與 release authorization pass,不得寫入或發送。", + "evidence_hash": "sha256:8122222222222222222222222222222222222222222222222222222222222222" + }, + { + "readback_id": "release_authorization_readback_playbook_trust", + "display_name": "PlayBook trust release authorization readback", + "owner_agent": "nemotron", + "source_authorization_hold": "release_authorization_playbook_trust", + "status": "blocked_by_policy", + "readback_mode": "release_authorization_readback_gate", + "owner_release_authorized": false, + "release_authorization_granted": false, + "release_authorization_passed": false, + "readback_summary": "讀回 PlayBook trust release authorization hold;仍未取得 owner authorization、maintenance window、rollback owner 與 release authorization pass,不得寫入或發送。", + "evidence_hash": "sha256:8133333333333333333333333333333333333333333333333333333333333333" + }, + { + "readback_id": "release_authorization_readback_reviewer_queue", + "display_name": "Reviewer queue release authorization readback", + "owner_agent": "openclaw", + "source_authorization_hold": "release_authorization_reviewer_queue", + "status": "approval_required", + "readback_mode": "release_authorization_readback_gate", + "owner_release_authorized": false, + "release_authorization_granted": false, + "release_authorization_passed": false, + "readback_summary": "讀回 Reviewer queue release authorization hold;仍未取得 owner authorization、maintenance window、rollback owner 與 release authorization pass,不得寫入或發送。", + "evidence_hash": "sha256:8144444444444444444444444444444444444444444444444444444444444444" + }, + { + "readback_id": "release_authorization_readback_gateway_queue", + "display_name": "Gateway queue release authorization readback", + "owner_agent": "nemotron", + "source_authorization_hold": "release_authorization_gateway_queue", + "status": "ready_for_owner_review", + "readback_mode": "release_authorization_readback_gate", + "owner_release_authorized": false, + "release_authorization_granted": false, + "release_authorization_passed": false, + "readback_summary": "讀回 Gateway queue release authorization hold;仍未取得 owner authorization、maintenance window、rollback owner 與 release authorization pass,不得寫入或發送。", + "evidence_hash": "sha256:8155555555555555555555555555555555555555555555555555555555555555" + } + ], + "rollback_release_readbacks": [ + { + "readback_id": "rollback_release_readback_result_capture", + "display_name": "Result capture rollback release readback", + "owner_agent": "openclaw", + "status": "ready_for_owner_review", + "readback_mode": "rollback_release_readback_gate", + "rollback_owner_required": true, + "rollback_owner_confirmed": false, + "rollback_release_passed": false, + "rollback_release_enabled": false, + "readback_summary": "讀回 Result capture rollback release gate;rollback owner 未 confirmed 前不得通過 rollback release。" + }, + { + "readback_id": "rollback_release_readback_learning", + "display_name": "Learning rollback release readback", + "owner_agent": "hermes", + "status": "approval_required", + "readback_mode": "rollback_release_readback_gate", + "rollback_owner_required": true, + "rollback_owner_confirmed": false, + "rollback_release_passed": false, + "rollback_release_enabled": false, + "readback_summary": "讀回 Learning rollback release gate;rollback owner 未 confirmed 前不得通過 rollback release。" + }, + { + "readback_id": "rollback_release_readback_playbook_trust", + "display_name": "PlayBook trust rollback release readback", + "owner_agent": "nemotron", + "status": "blocked_by_policy", + "readback_mode": "rollback_release_readback_gate", + "rollback_owner_required": true, + "rollback_owner_confirmed": false, + "rollback_release_passed": false, + "rollback_release_enabled": false, + "readback_summary": "讀回 PlayBook trust rollback release gate;rollback owner 未 confirmed 前不得通過 rollback release。" + }, + { + "readback_id": "rollback_release_readback_reviewer_queue", + "display_name": "Reviewer queue rollback release readback", + "owner_agent": "openclaw", + "status": "approval_required", + "readback_mode": "rollback_release_readback_gate", + "rollback_owner_required": true, + "rollback_owner_confirmed": false, + "rollback_release_passed": false, + "rollback_release_enabled": false, + "readback_summary": "讀回 Reviewer queue rollback release gate;rollback owner 未 confirmed 前不得通過 rollback release。" + }, + { + "readback_id": "rollback_release_readback_gateway_queue", + "display_name": "Gateway queue rollback release readback", + "owner_agent": "nemotron", + "status": "ready_for_owner_review", + "readback_mode": "rollback_release_readback_gate", + "rollback_owner_required": true, + "rollback_owner_confirmed": false, + "rollback_release_passed": false, + "rollback_release_enabled": false, + "readback_summary": "讀回 Gateway queue rollback release gate;rollback owner 未 confirmed 前不得通過 rollback release。" + } + ], + "maintenance_window_readback_holds": [ + { + "hold_id": "maintenance_window_readback_result_capture", + "display_name": "Result capture maintenance window readback hold", + "owner_agent": "openclaw", + "status": "ready_for_owner_review", + "hold_mode": "maintenance_window_readback_hold", + "owner_release_authorized": false, + "maintenance_window_approved": false, + "final_release_candidate_passed": false, + "hold_reason": "Result capture maintenance window 只讀回 gate;仍需 owner authorization、maintenance approval 與 final verifier pass。" + }, + { + "hold_id": "maintenance_window_readback_learning", + "display_name": "Learning maintenance window readback hold", + "owner_agent": "hermes", + "status": "approval_required", + "hold_mode": "maintenance_window_readback_hold", + "owner_release_authorized": false, + "maintenance_window_approved": false, + "final_release_candidate_passed": false, + "hold_reason": "Learning maintenance window 只讀回 gate;仍需 owner authorization、maintenance approval 與 final verifier pass。" + }, + { + "hold_id": "maintenance_window_readback_playbook_trust", + "display_name": "PlayBook trust maintenance window readback hold", + "owner_agent": "nemotron", + "status": "blocked_by_policy", + "hold_mode": "maintenance_window_readback_hold", + "owner_release_authorized": false, + "maintenance_window_approved": false, + "final_release_candidate_passed": false, + "hold_reason": "PlayBook trust maintenance window 只讀回 gate;仍需 owner authorization、maintenance approval 與 final verifier pass。" + }, + { + "hold_id": "maintenance_window_readback_reviewer_queue", + "display_name": "Reviewer queue maintenance window readback hold", + "owner_agent": "openclaw", + "status": "approval_required", + "hold_mode": "maintenance_window_readback_hold", + "owner_release_authorized": false, + "maintenance_window_approved": false, + "final_release_candidate_passed": false, + "hold_reason": "Reviewer queue maintenance window 只讀回 gate;仍需 owner authorization、maintenance approval 與 final verifier pass。" + }, + { + "hold_id": "maintenance_window_readback_gateway_queue", + "display_name": "Gateway queue maintenance window readback hold", + "owner_agent": "nemotron", + "status": "ready_for_owner_review", + "hold_mode": "maintenance_window_readback_hold", + "owner_release_authorized": false, + "maintenance_window_approved": false, + "final_release_candidate_passed": false, + "hold_reason": "Gateway queue maintenance window 只讀回 gate;仍需 owner authorization、maintenance approval 與 final verifier pass。" + } + ], + "live_apply_release_readback_holds": [ + { + "hold_id": "live_apply_release_readback_result_capture", + "display_name": "Result capture live apply release readback hold", + "owner_agent": "openclaw", + "status": "ready_for_owner_review", + "hold_mode": "live_apply_release_readback_hold", + "release_authorization_granted": false, + "release_authorization_passed": false, + "live_apply_release_passed": false, + "live_apply_release_enabled": false, + "release_condition": "P2-135 只讀回 release authorization gate;不得直接 writer apply、live apply 或 Telegram 實發。" + }, + { + "hold_id": "live_apply_release_readback_learning", + "display_name": "Learning live apply release readback hold", + "owner_agent": "hermes", + "status": "approval_required", + "hold_mode": "live_apply_release_readback_hold", + "release_authorization_granted": false, + "release_authorization_passed": false, + "live_apply_release_passed": false, + "live_apply_release_enabled": false, + "release_condition": "P2-135 只讀回 release authorization gate;不得直接 writer apply、live apply 或 Telegram 實發。" + }, + { + "hold_id": "live_apply_release_readback_playbook_trust", + "display_name": "PlayBook trust live apply release readback hold", + "owner_agent": "nemotron", + "status": "blocked_by_policy", + "hold_mode": "live_apply_release_readback_hold", + "release_authorization_granted": false, + "release_authorization_passed": false, + "live_apply_release_passed": false, + "live_apply_release_enabled": false, + "release_condition": "P2-135 只讀回 release authorization gate;不得直接 writer apply、live apply 或 Telegram 實發。" + }, + { + "hold_id": "live_apply_release_readback_reviewer_queue", + "display_name": "Reviewer queue live apply release readback hold", + "owner_agent": "openclaw", + "status": "approval_required", + "hold_mode": "live_apply_release_readback_hold", + "release_authorization_granted": false, + "release_authorization_passed": false, + "live_apply_release_passed": false, + "live_apply_release_enabled": false, + "release_condition": "P2-135 只讀回 release authorization gate;不得直接 writer apply、live apply 或 Telegram 實發。" + }, + { + "hold_id": "live_apply_release_readback_gateway_queue", + "display_name": "Gateway queue live apply release readback hold", + "owner_agent": "nemotron", + "status": "ready_for_owner_review", + "hold_mode": "live_apply_release_readback_hold", + "release_authorization_granted": false, + "release_authorization_passed": false, + "live_apply_release_passed": false, + "live_apply_release_enabled": false, + "release_condition": "P2-135 只讀回 release authorization gate;不得直接 writer apply、live apply 或 Telegram 實發。" + } + ], + "blocked_release_readback_transitions": [ + { + "blocker_id": "blocked_writer_apply_release_readback", + "display_name": "Writer apply release readback blocked", + "severity": "critical", + "status": "blocked_by_policy", + "blocked_action": "writer_apply_after_release_authorization_readback", + "blocked_until": "owner authorization + maintenance window + release authorization pass + rollback owner confirmed", + "evidence_hash": "sha256:9122222222222222222222222222222222222222222222222222222222222222" + }, + { + "blocker_id": "blocked_execution_apply_release_readback", + "display_name": "Execution apply release readback blocked", + "severity": "critical", + "status": "blocked_by_policy", + "blocked_action": "execution_apply_after_release_authorization_readback", + "blocked_until": "release authorization passed + rollback release passed + post-release verifier ready", + "evidence_hash": "sha256:9233333333333333333333333333333333333333333333333333333333333333" + }, + { + "blocker_id": "blocked_receipt_write_release_readback", + "display_name": "Receipt write release readback blocked", + "severity": "critical", + "status": "approval_required", + "blocked_action": "receipt_write_after_release_authorization_readback", + "blocked_until": "release authorization granted + release verification passed", + "evidence_hash": "sha256:9344444444444444444444444444444444444444444444444444444444444444" + }, + { + "blocker_id": "blocked_result_capture_write_release_readback", + "display_name": "Result capture write release readback blocked", + "severity": "critical", + "status": "blocked_by_policy", + "blocked_action": "result_capture_write_after_release_authorization_readback", + "blocked_until": "owner authorization + release authorization pass + rollback owner confirmed", + "evidence_hash": "sha256:9455555555555555555555555555555555555555555555555555555555555555" + }, + { + "blocker_id": "blocked_gateway_queue_write_release_readback", + "display_name": "Gateway queue write release readback blocked", + "severity": "critical", + "status": "approval_required", + "blocked_action": "gateway_queue_write_after_release_authorization_readback", + "blocked_until": "SRE route lock + Telegram receipt owner approved + release authorization pass", + "evidence_hash": "sha256:9566666666666666666666666666666666666666666666666666666666666666" + }, + { + "blocker_id": "blocked_telegram_send_release_readback", + "display_name": "Telegram send release readback blocked", + "severity": "high", + "status": "approval_required", + "blocked_action": "telegram_send_after_release_authorization_readback", + "blocked_until": "Gateway queue release approved + Telegram receipt E2E approved + rollback release gate passed", + "evidence_hash": "sha256:9677777777777777777777777777777777777777777777777777777777777777" + } + ], + "operator_actions": [ + { + "action_id": "review_release_authorization_readbacks", + "owner_agent": "openclaw", + "status": "ready_for_operator_review", + "operator_instruction": "審核 5 個 release authorization readback 是否仍符合 P2-134 hold 邊界;不要把 readback 視為正式授權。", + "runtime_write_allowed": false + }, + { + "action_id": "verify_rollback_release_readback", + "owner_agent": "hermes", + "status": "ready_for_operator_review", + "operator_instruction": "確認 rollback release readback 仍全部未 passed,且 rollback_release_enabled 仍為 false。", + "runtime_write_allowed": false + }, + { + "action_id": "verify_maintenance_window_readback_hold", + "owner_agent": "nemotron", + "status": "ready_for_operator_review", + "operator_instruction": "確認 maintenance window readback 仍為 hold;不可批准 maintenance window 或套用 writer。", + "runtime_write_allowed": false + }, + { + "action_id": "verify_live_apply_release_readback_hold", + "owner_agent": "openclaw", + "status": "approval_required", + "operator_instruction": "確認 live apply release readback 仍未 enabled,且 release_authorization_passed 仍為 false。", + "runtime_write_allowed": false + }, + { + "action_id": "prepare_p2_136_release_authorization_review_packet", + "owner_agent": "hermes", + "status": "ready_for_operator_review", + "operator_instruction": "下一關只可建立 P2-136 release authorization review packet,不可放行 writer 或正式寫入。", + "runtime_write_allowed": false + } + ], + "display_redaction_contract": { + "redaction_required": true, + "raw_prompt_display_allowed": false, + "private_reasoning_display_allowed": false, + "secret_value_display_allowed": false, + "raw_runtime_payload_display_allowed": false, + "internal_collaboration_content_display_allowed": false, + "frontend_display_policy": "前端只能顯示 release authorization readback 摘要、狀態、數量、redacted hash 與 0 / false 邊界;不得顯示內部協作環境對話、原始提示詞、私有推理、secret、授權標頭或原始 runtime payload。" + }, + "rollups": { + "release_authorization_readback_count": 5, + "rollback_release_readback_count": 5, + "maintenance_window_readback_hold_count": 5, + "live_apply_release_readback_hold_count": 5, + "blocked_release_readback_transition_count": 6, + "operator_action_count": 5, + "approval_required_authorization_readback_count": 2, + "blocked_authorization_readback_count": 1, + "approval_required_rollback_readback_count": 2, + "blocked_rollback_readback_count": 1, + "approval_required_maintenance_window_count": 2, + "blocked_maintenance_window_count": 1, + "approval_required_live_apply_readback_count": 2, + "blocked_live_apply_readback_count": 1, + "critical_blocker_count": 5, + "owner_release_authorized_count": 0, + "owner_release_approved_count": 0, + "maintenance_window_approved_count": 0, + "rollback_owner_confirmed_count": 0, + "post_release_verifier_ready_count": 0, + "final_release_candidate_approved_count": 0, + "final_release_candidate_pass_count": 0, + "release_authorization_granted_count": 0, + "release_authorization_pass_count": 0, + "rollback_release_pass_count": 0, + "live_apply_release_pass_count": 0, + "writer_apply_count": 0, + "execution_apply_count": 0, + "receipt_write_count": 0, + "reviewer_queue_write_count": 0, + "gateway_queue_write_count": 0, + "telegram_send_count": 0, + "bot_api_call_count": 0, + "report_receipt_write_count": 0, + "result_capture_write_count": 0, + "learning_write_count": 0, + "playbook_trust_write_count": 0, + "production_write_count": 0, + "secret_read_count": 0, + "destructive_operation_count": 0 + } +} diff --git a/docs/schemas/ai_agent_result_capture_release_authorization_readback_gate_v1.schema.json b/docs/schemas/ai_agent_result_capture_release_authorization_readback_gate_v1.schema.json new file mode 100644 index 00000000..d0260820 --- /dev/null +++ b/docs/schemas/ai_agent_result_capture_release_authorization_readback_gate_v1.schema.json @@ -0,0 +1,100 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://awoooi.wooo.work/schemas/ai_agent_result_capture_release_authorization_readback_gate_v1.schema.json", + "title": "AI Agent result capture release authorization readback gate v1", + "type": "object", + "required": [ + "schema_version", + "generated_at", + "program_status", + "source_refs", + "prior_release_authorization_hold", + "release_authorization_readback_truth", + "release_authorization_readbacks", + "rollback_release_readbacks", + "maintenance_window_readback_holds", + "live_apply_release_readback_holds", + "blocked_release_readback_transitions", + "operator_actions", + "display_redaction_contract", + "rollups" + ], + "properties": { + "schema_version": { + "const": "ai_agent_result_capture_release_authorization_readback_gate_v1" + }, + "generated_at": { + "type": "string" + }, + "program_status": { + "type": "object" + }, + "source_refs": { + "type": "array", + "items": { + "type": "string" + } + }, + "prior_release_authorization_hold": { + "type": "object" + }, + "release_authorization_readback_truth": { + "type": "object" + }, + "release_authorization_readbacks": { + "type": "array", + "minItems": 5, + "maxItems": 5, + "items": { + "type": "object" + } + }, + "rollback_release_readbacks": { + "type": "array", + "minItems": 5, + "maxItems": 5, + "items": { + "type": "object" + } + }, + "maintenance_window_readback_holds": { + "type": "array", + "minItems": 5, + "maxItems": 5, + "items": { + "type": "object" + } + }, + "live_apply_release_readback_holds": { + "type": "array", + "minItems": 5, + "maxItems": 5, + "items": { + "type": "object" + } + }, + "blocked_release_readback_transitions": { + "type": "array", + "minItems": 6, + "maxItems": 6, + "items": { + "type": "object" + } + }, + "operator_actions": { + "type": "array", + "minItems": 5, + "maxItems": 5, + "items": { + "type": "object" + } + }, + "display_redaction_contract": { + "type": "object" + }, + "rollups": { + "type": "object" + } + }, + "additionalProperties": false +} 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 dd1af11e..fdfa6afc 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 @@ -672,6 +672,7 @@ Alert / Sentry / SigNoz / Gitea / Market Watch / Operator | `docs/evaluations/ai_agent_result_capture_post_release_verifier_rollback_gate_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-post-release-verifier-rollback-gate` | P2-132 post-release verifier / rollback gate;承接 P2-131 owner release approval gate,建立 5 個 post-release verifier gate、5 個 rollback release gate、5 個 release verification hold、5 個 live-apply post-release gate、6 個 blocked post-release transition 與 5 個 operator action;runtime authority 固定 `result_capture_post_release_verifier_rollback_gate_only_no_live_write`;owner release approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、release verification passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、canonical runtime target read、live query、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive action 全部 `0 / false`;deploy marker `934af770` 已正式驗證,下一步 P2-133 | | `docs/evaluations/ai_agent_result_capture_final_release_candidate_readback_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-final-release-candidate-readback` | P2-133 final release candidate readback;承接 P2-132 post-release verifier / rollback gate,建立 5 個 final release candidate readback、5 個 rollback candidate readback、5 個 candidate acceptance hold、5 個 live-apply candidate hold、6 個 blocked final candidate transition 與 5 個 operator action;runtime authority 固定 `result_capture_final_release_candidate_readback_only_no_live_write`;owner release approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、final release candidate approved、final release candidate passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、canonical runtime target read、live query、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive action 全部 `0 / false`;deploy marker `8be5ddab` 已正式驗證,下一步 P2-134 | | `docs/evaluations/ai_agent_result_capture_release_authorization_hold_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-release-authorization-hold` | P2-134 release authorization hold;承接 P2-133 final release candidate readback,建立 5 個 release authorization hold、5 個 rollback authorization hold、5 個 release window hold、5 個 live-apply authorization hold、6 個 blocked authorization transition 與 5 個 operator action;runtime authority 固定 `result_capture_release_authorization_hold_only_no_live_write`;owner release authorized、owner release approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、final release candidate approved、final release candidate passed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、canonical runtime target read、live query、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive action 全部 `0 / false`;deploy marker `18b867c3` 已正式驗證,下一步 P2-135 | +| `docs/evaluations/ai_agent_result_capture_release_authorization_readback_gate_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-release-authorization-readback-gate` | P2-135 release authorization readback gate;承接 P2-134 release authorization hold,建立 5 個 release authorization readback、5 個 rollback release readback、5 個 maintenance window readback hold、5 個 live-apply release readback hold、6 個 blocked release readback transition 與 5 個 operator action;runtime authority 固定 `result_capture_release_authorization_readback_gate_only_no_live_write`;owner release authorized、owner release approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、final release candidate approved、final release candidate passed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、canonical runtime target read、live query、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive action 全部 `0 / false`;本地 API / typecheck 已通過,正式部署與 Browser smoke 待推進 | | `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 主動營運委派與版本生命週期契約 @@ -795,6 +796,7 @@ Repo / registry / release notes / K8s / host / observability / backup evidence 53. 建立 post-release verifier / rollback gate。✅ P2-132 已完成並正式驗證;post-release verifier gate `5`、rollback release gate `5`、release verification hold `5`、live-apply post-release gate `5`、blocked post-release transition `6`、operator action `5`,approval-required verifier / rollback / verification / live apply `2 / 2 / 2 / 2`、blocked verifier / rollback / verification / live apply `1 / 1 / 1 / 1`、critical blocker `5`;owner release approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、release verification passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write 仍為 `0 / false`;deploy marker `934af770`、正式 API readback 與 desktop / mobile smoke 已完成。已由 P2-133 承接。 54. 建立 final release candidate readback。✅ P2-133 已完成並正式驗證;final release candidate readback `5`、rollback candidate readback `5`、candidate acceptance hold `5`、live-apply candidate hold `5`、blocked final candidate transition `6`、operator action `5`,approval-required candidate / rollback / acceptance / live apply `2 / 2 / 2 / 2`、blocked candidate / rollback / acceptance / live apply `1 / 1 / 1 / 1`、critical blocker `5`;owner release approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、final release candidate approved、final release candidate passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write 仍為 `0 / false`;deploy marker `8be5ddab`、正式 API readback 與 desktop / mobile smoke 已完成。已由 P2-134 正式承接。 55. 建立 release authorization hold。✅ P2-134 已完成並正式驗證;release authorization hold `5`、rollback authorization hold `5`、release window hold `5`、live-apply authorization hold `5`、blocked authorization transition `6`、operator action `5`,approval-required authorization / rollback / release window / live apply `2 / 2 / 2 / 2`、blocked authorization / rollback / release window / live apply `1 / 1 / 1 / 1`、critical blocker `5`;owner release authorized、owner release approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、final release candidate approved、final release candidate passed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write 仍為 `0 / false`;deploy marker `18b867c3`、正式 API readback 與 desktop / mobile smoke 已完成。下一步 P2-135。 +56. 建立 release authorization readback gate。🟡 P2-135 本地完成,正式部署與 production smoke 待推進;release authorization readback `5`、rollback release readback `5`、maintenance window readback hold `5`、live-apply release readback hold `5`、blocked release readback transition `6`、operator action `5`,approval-required readback / rollback / maintenance / live apply `2 / 2 / 2 / 2`、blocked readback / rollback / maintenance / live apply `1 / 1 / 1 / 1`、critical blocker `5`;owner release authorized、owner release approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、final release candidate approved、final release candidate passed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write 仍為 `0 / false`;本地 API/service regression `14 passed`、Web typecheck 通過。正式驗證後才可由 P2-136 承接。 #### 3.2.1d 2026-06-11 Agent 互動、學習與成長證據面 @@ -1890,6 +1892,13 @@ Phase 6 完成後 - 本地 0 / false 邊界:owner release authorized、owner release approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、final release candidate approved、final release candidate passed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive operation 均為 `0 / false`。 - 本波仍不讀 canonical runtime target、不做 live query、不寫 reviewer queue、不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 report receipt、不寫 result capture、不寫 learning、不更新 PlayBook trust、不寫 production target、不讀 secret、不執行 destructive action、不回傳內部協作內容;正式推版與 production smoke 通過後才可由 P2-135 承接。 +### 2026-06-14 08:44 (台北) — §3.2 / §5 — 新增 P2-135 release authorization readback gate — 本地完成釋出授權讀回只讀關卡 + +- 新增 `ai_agent_result_capture_release_authorization_readback_gate_v1` schema、snapshot、loader、API route、governance UI 與繁中訊息;承接 P2-134 release authorization hold,但不核發 release authorization。 +- 本地 rollup:release authorization readback `5`、rollback release readback `5`、maintenance window readback hold `5`、live-apply release readback hold `5`、blocked release readback transition `6`、operator action `5`、正式寫入 / 發送 `0`。 +- 本地驗證:JSON parse、Python compile、P2-135 + P2-134 API/service regression `14 passed`、Web typecheck 通過;正式部署與 production smoke 待推進。 +- 本波仍不讀 canonical runtime target、不做 live query、不寫 reviewer queue、不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 report receipt、不寫 result capture、不寫 learning、不更新 PlayBook trust、不寫 production target、不讀 secret、不執行 destructive action、不回傳內部協作內容;正式驗證後才可由 P2-136 承接。 + ### 2026-06-14 08:36 (台北) — §3.2 / §5 — 正式驗證 P2-134 release authorization hold — 完成釋出授權保留只讀關卡 - Feature commit `e0a6d339` 已由 deploy marker `18b867c3 chore(cd): deploy e0a6d33 [skip ci]` 部署;正式 API health 回 `healthy`、`environment=prod`、`mock_mode=false`。