From 26b67d11f7b7de4f9c9d95c01bb1dacf4000e887 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 14 Jun 2026 02:43:45 +0800 Subject: [PATCH] =?UTF-8?q?feat(governance):=20=E6=96=B0=E5=A2=9E=20owner?= =?UTF-8?q?=20acceptance=20maintenance=20gate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/api/src/api/v1/agents.py | 33 ++ ...pture_owner_acceptance_maintenance_gate.py | 410 ++++++++++++++++ ...pture_owner_acceptance_maintenance_gate.py | 106 ++++ ...e_owner_acceptance_maintenance_gate_api.py | 40 ++ apps/web/messages/en.json | 33 ++ apps/web/messages/zh-TW.json | 33 ++ .../tabs/automation-inventory-tab.tsx | 163 ++++++- apps/web/src/lib/api-client.ts | 197 ++++++++ docs/LOGBOOK.md | 59 +++ ...AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md | 12 +- ...cceptance_maintenance_gate_2026-06-14.json | 452 ++++++++++++++++++ ...acceptance_maintenance_gate_v1.schema.json | 100 ++++ ...-04-15-MASTER-ai-autonomous-flywheel-v2.md | 28 +- 13 files changed, 1658 insertions(+), 8 deletions(-) create mode 100644 apps/api/src/services/ai_agent_result_capture_owner_acceptance_maintenance_gate.py create mode 100644 apps/api/tests/test_ai_agent_result_capture_owner_acceptance_maintenance_gate.py create mode 100644 apps/api/tests/test_ai_agent_result_capture_owner_acceptance_maintenance_gate_api.py create mode 100644 docs/evaluations/ai_agent_result_capture_owner_acceptance_maintenance_gate_2026-06-14.json create mode 100644 docs/schemas/ai_agent_result_capture_owner_acceptance_maintenance_gate_v1.schema.json diff --git a/apps/api/src/api/v1/agents.py b/apps/api/src/api/v1/agents.py index 3825a0b1d..d49cb4dd3 100644 --- a/apps/api/src/api/v1/agents.py +++ b/apps/api/src/api/v1/agents.py @@ -127,6 +127,9 @@ from src.services.ai_agent_result_capture_owner_promotion_review import ( from src.services.ai_agent_result_capture_owner_approved_execution_rehearsal import ( load_latest_ai_agent_result_capture_owner_approved_execution_rehearsal, ) +from src.services.ai_agent_result_capture_owner_acceptance_maintenance_gate import ( + load_latest_ai_agent_result_capture_owner_acceptance_maintenance_gate, +) from src.services.ai_agent_result_capture_promotion_approval_gate import ( load_latest_ai_agent_result_capture_promotion_approval_gate, ) @@ -1884,6 +1887,36 @@ async def get_agent_result_capture_owner_approved_execution_rehearsal() -> dict[ ) from exc +@router.get( + "/agent-result-capture-owner-acceptance-maintenance-gate", + response_model=dict[str, Any], + summary="取得 AI Agent result capture owner acceptance maintenance gate", + description=( + "讀取最新已提交的 P2-127 owner acceptance / maintenance gate;" + "此端點只回傳 owner acceptance packet、maintenance window、rollback owner、" + "post-apply verifier gate、blocked live write 與 operator handoff,不套用 writer、" + "不執行 live apply、不寫 receipt、不寫 result capture、learning、PlayBook trust、" + "reviewer queue、Gateway queue,不送 Telegram、不呼叫 Bot API、不讀 secret。" + ), +) +async def get_agent_result_capture_owner_acceptance_maintenance_gate() -> dict[str, Any]: + """Return the latest read-only owner acceptance / maintenance gate package.""" + try: + payload = await asyncio.to_thread(load_latest_ai_agent_result_capture_owner_acceptance_maintenance_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_owner_acceptance_maintenance_gate_invalid", error=str(exc)) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="AI Agent result capture owner acceptance maintenance 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_owner_acceptance_maintenance_gate.py b/apps/api/src/services/ai_agent_result_capture_owner_acceptance_maintenance_gate.py new file mode 100644 index 000000000..2a02f33c3 --- /dev/null +++ b/apps/api/src/services/ai_agent_result_capture_owner_acceptance_maintenance_gate.py @@ -0,0 +1,410 @@ +""" +AI Agent result capture owner acceptance maintenance gate snapshot. + +Loads the latest committed P2-127 owner acceptance / maintenance gate package. +This module validates committed evidence only; it never applies writers, executes +live applies, writes receipts, writes result captures, writes learning records, +updates PlayBook trust, writes reviewer / Gateway queues, sends Telegram +messages, reads canonical runtime targets, reads secrets, or performs +destructive operations. +""" + +from __future__ import annotations + +import json +from pathlib import Path +from typing import Any + +from src.services.snapshot_paths import default_evaluations_dir + +_DEFAULT_EVALUATIONS_DIR = default_evaluations_dir(Path(__file__)) +_SNAPSHOT_PATTERN = "ai_agent_result_capture_owner_acceptance_maintenance_gate_*.json" +_SCHEMA_VERSION = "ai_agent_result_capture_owner_acceptance_maintenance_gate_v1" +_RUNTIME_AUTHORITY = "result_capture_owner_acceptance_maintenance_gate_only_no_live_write" + + +def load_latest_ai_agent_result_capture_owner_acceptance_maintenance_gate( + evaluations_dir: Path | None = None, +) -> dict[str, Any]: + """Load the newest committed owner acceptance / maintenance gate package.""" + directory = evaluations_dir or _DEFAULT_EVALUATIONS_DIR + candidates = sorted(directory.glob(_SNAPSHOT_PATTERN)) + if not candidates: + raise FileNotFoundError(f"no AI Agent result capture owner acceptance maintenance 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_acceptance_packets(payload, label) + _require_maintenance_windows(payload, label) + _require_rollback_owner_checks(payload, label) + _require_post_apply_verifier_gates(payload, label) + _require_blocked_live_writes(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-127", + "next_task_id": "P2-128", + "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_owner_approved_execution_rehearsal") or {} + expected = { + "schema_version": "ai_agent_result_capture_owner_approved_execution_rehearsal_v1", + "execution_rehearsal_count": 5, + "no_write_apply_check_count": 5, + "post_write_verifier_rehearsal_count": 5, + "rollback_drill_count": 5, + "blocked_live_apply_count": 6, + "operator_action_count": 5, + "approval_required_total": 8, + "blocked_total": 9, + "owner_approval_record_received_count": 0, + "no_write_apply_execution_count": 0, + "post_write_verifier_pass_count": 0, + "rollback_drill_confirmed_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_owner_approved_execution_rehearsal mismatch: {mismatches}") + if not prior.get("readiness_note"): + raise ValueError(f"{label}: prior_owner_approved_execution_rehearsal.readiness_note is required") + + +def _require_truth(payload: dict[str, Any], label: str) -> None: + truth = payload.get("owner_acceptance_truth") or {} + required_true = { + "p2_126_execution_rehearsal_loaded", + "owner_acceptance_packet_ready", + "maintenance_window_required", + "rollback_owner_required", + "post_apply_verifier_required", + "redaction_review_required", + "live_apply_gate_closed", + "acceptance_gate_only", + } + missing = sorted(field for field in required_true if truth.get(field) is not True) + if missing: + raise ValueError(f"{label}: owner acceptance ready flags must remain true: {missing}") + required_false = { + "owner_acceptance_received", + "maintenance_window_approved", + "rollback_owner_confirmed", + "post_apply_verifier_ready", + "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}: live execution/send/write flags must remain false: {unsafe}") + zero_counts = { + "owner_acceptance_received_count", + "maintenance_window_approved_count", + "rollback_owner_confirmed_count", + "post_apply_verifier_ready_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}: owner acceptance live counters must remain zero: {non_zero}") + if not truth.get("truth_note"): + raise ValueError(f"{label}: owner_acceptance_truth.truth_note is required") + + +def _require_acceptance_packets(payload: dict[str, Any], label: str) -> None: + items = payload.get("owner_acceptance_packets") or [] + required = { + "acceptance_result_capture_writer", + "acceptance_learning_writer", + "acceptance_playbook_trust_writer", + "acceptance_reviewer_queue_writer", + "acceptance_gateway_queue_writer", + } + ids = {item.get("packet_id") for item in items} + if ids != required: + raise ValueError(f"{label}: owner acceptance packets must match {sorted(required)}") + for item in items: + item_id = item.get("packet_id") + if item.get("packet_mode") != "owner_acceptance_required": + raise ValueError(f"{label}: packet {item_id} must remain owner acceptance required") + if item.get("owner_acceptance_required") is not True or item.get("owner_accepted") is not False: + raise ValueError(f"{label}: packet {item_id} must not mark owner accepted") + if item.get("status") not in {"ready_for_owner_review", "approval_required", "blocked_by_policy"}: + raise ValueError(f"{label}: packet {item_id} status is invalid") + if not item.get("required_evidence") or not _is_redacted_sha256(item.get("evidence_hash")): + raise ValueError(f"{label}: packet {item_id} must include required evidence and redacted hash") + + +def _require_maintenance_windows(payload: dict[str, Any], label: str) -> None: + items = payload.get("maintenance_windows") or [] + required = { + "window_result_capture_writer", + "window_learning_writer", + "window_playbook_trust_writer", + "window_reviewer_queue_writer", + "window_gateway_queue_writer", + } + ids = {item.get("window_id") for item in items} + if ids != required: + raise ValueError(f"{label}: maintenance windows must match {sorted(required)}") + for item in items: + item_id = item.get("window_id") + if item.get("window_mode") != "maintenance_window_draft": + raise ValueError(f"{label}: window {item_id} must remain maintenance window draft") + if item.get("maintenance_window_required") is not True or item.get("window_approved") is not False: + raise ValueError(f"{label}: window {item_id} must not be approved") + if item.get("status") not in {"ready_for_owner_review", "approval_required", "blocked_by_policy"}: + raise ValueError(f"{label}: window {item_id} status is invalid") + if not item.get("blackout_policy") or not item.get("validation_plan"): + raise ValueError(f"{label}: window {item_id} blackout_policy and validation_plan are required") + + +def _require_rollback_owner_checks(payload: dict[str, Any], label: str) -> None: + items = payload.get("rollback_owner_checks") or [] + required = { + "rollback_owner_result_capture", + "rollback_owner_learning", + "rollback_owner_playbook_trust", + "rollback_owner_reviewer_queue", + "rollback_owner_gateway_queue", + } + ids = {item.get("check_id") for item in items} + if ids != required: + raise ValueError(f"{label}: rollback owner checks must match {sorted(required)}") + for item in items: + item_id = item.get("check_id") + if item.get("rollback_owner_required") is not True or item.get("rollback_owner_confirmed") is not False: + raise ValueError(f"{label}: rollback owner check {item_id} must remain unconfirmed") + if item.get("status") not in {"ready_for_owner_review", "approval_required", "blocked_by_policy"}: + raise ValueError(f"{label}: rollback owner check {item_id} status is invalid") + if not item.get("rollback_scope") or not item.get("failure_if_missing"): + raise ValueError(f"{label}: rollback owner check {item_id} scope and failure_if_missing are required") + + +def _require_post_apply_verifier_gates(payload: dict[str, Any], label: str) -> None: + items = payload.get("post_apply_verifier_gates") or [] + required = { + "verifier_gate_result_capture", + "verifier_gate_learning", + "verifier_gate_playbook_trust", + "verifier_gate_reviewer_queue", + "verifier_gate_gateway_queue", + } + ids = {item.get("gate_id") for item in items} + if ids != required: + raise ValueError(f"{label}: post-apply verifier gates must match {sorted(required)}") + for item in items: + item_id = item.get("gate_id") + if item.get("gate_mode") != "post_apply_verifier_gate": + raise ValueError(f"{label}: verifier gate {item_id} must remain post-apply verifier gate") + if item.get("verifier_ready") is not False or item.get("live_read_enabled") is not False: + raise ValueError(f"{label}: verifier gate {item_id} must not enable live read") + if item.get("status") not in {"ready_for_owner_review", "approval_required", "blocked_by_policy"}: + raise ValueError(f"{label}: verifier gate {item_id} status is invalid") + if not item.get("expected_signal"): + raise ValueError(f"{label}: verifier gate {item_id} expected_signal is required") + + +def _require_blocked_live_writes(payload: dict[str, Any], label: str) -> None: + items = payload.get("blocked_live_writes") or [] + required = { + "blocked_writer_apply", + "blocked_execution_apply", + "blocked_receipt_write", + "blocked_result_capture_write", + "blocked_gateway_queue_write", + "blocked_telegram_send", + } + ids = {item.get("blocker_id") for item in items} + if ids != required: + raise ValueError(f"{label}: blocked live writes must match {sorted(required)}") + for item in items: + item_id = item.get("blocker_id") + if item.get("status") not in {"approval_required", "blocked_by_policy"}: + raise ValueError(f"{label}: blocker {item_id} status is invalid") + if item.get("severity") not in {"high", "critical"}: + raise ValueError(f"{label}: blocker {item_id} severity is invalid") + if not item.get("blocked_action") or not item.get("blocked_until"): + raise ValueError(f"{label}: blocker {item_id} must include blocked_action and blocked_until") + if not _is_redacted_sha256(item.get("evidence_hash")): + raise ValueError(f"{label}: blocker {item_id} must expose redacted evidence_hash") + + +def _require_actions(payload: dict[str, Any], label: str) -> None: + actions = payload.get("operator_actions") or [] + required = { + "review_owner_acceptance_packets", + "confirm_maintenance_windows", + "confirm_rollback_owners", + "verify_post_apply_gates", + "hold_live_apply_gate", + } + ids = {action.get("action_id") for action in actions} + if ids != required: + raise ValueError(f"{label}: operator actions must match {sorted(required)}") + for action in actions: + action_id = action.get("action_id") + if action.get("runtime_write_allowed") is not False: + raise ValueError(f"{label}: action {action_id} must not allow runtime write") + if not action.get("operator_instruction"): + raise ValueError(f"{label}: action {action_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_rollup_consistency(payload: dict[str, Any], label: str) -> None: + rollups = payload.get("rollups") or {} + packets = payload.get("owner_acceptance_packets") or [] + windows = payload.get("maintenance_windows") or [] + rollbacks = payload.get("rollback_owner_checks") or [] + verifiers = payload.get("post_apply_verifier_gates") or [] + blockers = payload.get("blocked_live_writes") or [] + actions = payload.get("operator_actions") or [] + expected = { + "owner_acceptance_packet_count": len(packets), + "maintenance_window_count": len(windows), + "rollback_owner_check_count": len(rollbacks), + "post_apply_verifier_gate_count": len(verifiers), + "blocked_live_write_count": len(blockers), + "operator_action_count": len(actions), + "approval_required_packet_count": sum(1 for item in packets if item.get("status") == "approval_required"), + "blocked_packet_count": sum(1 for item in packets if item.get("status") == "blocked_by_policy"), + "approval_required_window_count": sum(1 for item in windows if item.get("status") == "approval_required"), + "blocked_window_count": sum(1 for item in windows if item.get("status") == "blocked_by_policy"), + "approval_required_rollback_count": sum(1 for item in rollbacks if item.get("status") == "approval_required"), + "blocked_rollback_count": sum(1 for item in rollbacks if item.get("status") == "blocked_by_policy"), + "approval_required_verifier_count": sum(1 for item in verifiers if item.get("status") == "approval_required"), + "blocked_verifier_count": sum(1 for item in verifiers if item.get("status") == "blocked_by_policy"), + "critical_blocker_count": sum(1 for item in blockers if item.get("severity") == "critical"), + "owner_acceptance_received_count": 0, + "maintenance_window_approved_count": 0, + "rollback_owner_confirmed_count": 0, + "post_apply_verifier_ready_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}: rollup counts mismatch: {mismatches}") + + +def _require_no_forbidden_display_terms(payload: dict[str, Any], label: str) -> None: + serialized = json.dumps(payload, ensure_ascii=False) + forbidden = { + "work_window_transcript", + "session_id", + "browser_context", + "authorization_header", + "raw Telegram payload", + "private reasoning", + "raw prompt", + "chain-of-thought", + } + hits = sorted(term for term in forbidden if term in serialized) + if hits: + raise ValueError(f"{label}: forbidden display terms present: {hits}") + + +def _is_redacted_sha256(value: Any) -> bool: + if not isinstance(value, str) or not value.startswith("sha256:"): + return False + digest = value.removeprefix("sha256:") + return len(digest) == 64 and all(char in "0123456789abcdef" for char in digest) + + +def _mismatches(payload: dict[str, Any], expected: dict[str, Any]) -> dict[str, dict[str, Any]]: + return { + key: {"expected": value, "actual": payload.get(key)} + for key, value in expected.items() + if payload.get(key) != value + } diff --git a/apps/api/tests/test_ai_agent_result_capture_owner_acceptance_maintenance_gate.py b/apps/api/tests/test_ai_agent_result_capture_owner_acceptance_maintenance_gate.py new file mode 100644 index 000000000..89cbaf037 --- /dev/null +++ b/apps/api/tests/test_ai_agent_result_capture_owner_acceptance_maintenance_gate.py @@ -0,0 +1,106 @@ +from __future__ import annotations + +import json +from pathlib import Path + +import pytest + +from src.services.ai_agent_result_capture_owner_acceptance_maintenance_gate import ( + load_latest_ai_agent_result_capture_owner_acceptance_maintenance_gate, +) + +REPO_ROOT = Path(__file__).resolve().parents[3] +FIXTURE = REPO_ROOT / "docs/evaluations/ai_agent_result_capture_owner_acceptance_maintenance_gate_2026-06-14.json" + + +def test_load_latest_ai_agent_result_capture_owner_acceptance_maintenance_gate_snapshot() -> None: + data = load_latest_ai_agent_result_capture_owner_acceptance_maintenance_gate() + + assert data["schema_version"] == "ai_agent_result_capture_owner_acceptance_maintenance_gate_v1" + assert data["program_status"]["current_task_id"] == "P2-127" + assert data["program_status"]["next_task_id"] == "P2-128" + assert data["program_status"]["runtime_authority"] == "result_capture_owner_acceptance_maintenance_gate_only_no_live_write" + + rollups = data["rollups"] + assert rollups["owner_acceptance_packet_count"] == 5 + assert rollups["maintenance_window_count"] == 5 + assert rollups["rollback_owner_check_count"] == 5 + assert rollups["post_apply_verifier_gate_count"] == 5 + assert rollups["blocked_live_write_count"] == 6 + assert rollups["operator_action_count"] == 5 + assert rollups["critical_blocker_count"] == 5 + assert rollups["owner_acceptance_received_count"] == 0 + assert rollups["maintenance_window_approved_count"] == 0 + assert rollups["rollback_owner_confirmed_count"] == 0 + assert rollups["post_apply_verifier_ready_count"] == 0 + assert rollups["writer_apply_count"] == 0 + assert rollups["execution_apply_count"] == 0 + assert rollups["receipt_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["result_capture_write_count"] == 0 + assert rollups["learning_write_count"] == 0 + assert rollups["playbook_trust_write_count"] == 0 + assert rollups["production_write_count"] == 0 + assert {item["owner_accepted"] for item in data["owner_acceptance_packets"]} == {False} + assert {item["window_approved"] for item in data["maintenance_windows"]} == {False} + assert {item["rollback_owner_confirmed"] for item in data["rollback_owner_checks"]} == {False} + assert {item["live_read_enabled"] for item in data["post_apply_verifier_gates"]} == {False} + + +def _copy_fixture(tmp_path: Path) -> dict: + source = json.loads(FIXTURE.read_text(encoding="utf-8")) + target = tmp_path / "ai_agent_result_capture_owner_acceptance_maintenance_gate_2026-06-14.json" + target.write_text(json.dumps(source, ensure_ascii=False), encoding="utf-8") + return source + + +def test_result_capture_owner_acceptance_maintenance_gate_rejects_owner_accepted(tmp_path: Path) -> None: + source = _copy_fixture(tmp_path) + source["owner_acceptance_packets"][0]["owner_accepted"] = True + target = tmp_path / "ai_agent_result_capture_owner_acceptance_maintenance_gate_2026-06-14.json" + target.write_text(json.dumps(source, ensure_ascii=False), encoding="utf-8") + + with pytest.raises(ValueError, match="must not mark owner accepted"): + load_latest_ai_agent_result_capture_owner_acceptance_maintenance_gate(tmp_path) + + +def test_result_capture_owner_acceptance_maintenance_gate_rejects_window_approved(tmp_path: Path) -> None: + source = _copy_fixture(tmp_path) + source["maintenance_windows"][0]["window_approved"] = True + target = tmp_path / "ai_agent_result_capture_owner_acceptance_maintenance_gate_2026-06-14.json" + target.write_text(json.dumps(source, ensure_ascii=False), encoding="utf-8") + + with pytest.raises(ValueError, match="must not be approved"): + load_latest_ai_agent_result_capture_owner_acceptance_maintenance_gate(tmp_path) + + +def test_result_capture_owner_acceptance_maintenance_gate_rejects_truth_write_flag(tmp_path: Path) -> None: + source = _copy_fixture(tmp_path) + source["owner_acceptance_truth"]["gateway_queue_write_enabled"] = True + target = tmp_path / "ai_agent_result_capture_owner_acceptance_maintenance_gate_2026-06-14.json" + target.write_text(json.dumps(source, ensure_ascii=False), encoding="utf-8") + + with pytest.raises(ValueError, match="live execution/send/write flags"): + load_latest_ai_agent_result_capture_owner_acceptance_maintenance_gate(tmp_path) + + +def test_result_capture_owner_acceptance_maintenance_gate_rejects_rollup_drift(tmp_path: Path) -> None: + source = _copy_fixture(tmp_path) + source["rollups"]["owner_acceptance_packet_count"] = 4 + target = tmp_path / "ai_agent_result_capture_owner_acceptance_maintenance_gate_2026-06-14.json" + target.write_text(json.dumps(source, ensure_ascii=False), encoding="utf-8") + + with pytest.raises(ValueError, match="rollup counts mismatch"): + load_latest_ai_agent_result_capture_owner_acceptance_maintenance_gate(tmp_path) + + +def test_result_capture_owner_acceptance_maintenance_gate_rejects_forbidden_display_terms(tmp_path: Path) -> None: + source = _copy_fixture(tmp_path) + source["operator_actions"][0]["operator_instruction"] = "work_window_transcript must never show" + target = tmp_path / "ai_agent_result_capture_owner_acceptance_maintenance_gate_2026-06-14.json" + target.write_text(json.dumps(source, ensure_ascii=False), encoding="utf-8") + + with pytest.raises(ValueError, match="forbidden display terms"): + load_latest_ai_agent_result_capture_owner_acceptance_maintenance_gate(tmp_path) diff --git a/apps/api/tests/test_ai_agent_result_capture_owner_acceptance_maintenance_gate_api.py b/apps/api/tests/test_ai_agent_result_capture_owner_acceptance_maintenance_gate_api.py new file mode 100644 index 000000000..719f915ab --- /dev/null +++ b/apps/api/tests/test_ai_agent_result_capture_owner_acceptance_maintenance_gate_api.py @@ -0,0 +1,40 @@ +from __future__ import annotations + +import pytest +from httpx import ASGITransport, AsyncClient + +from src.main import app + + +@pytest.mark.asyncio +async def test_get_agent_result_capture_owner_acceptance_maintenance_gate_api() -> None: + transport = ASGITransport(app=app) + async with AsyncClient(transport=transport, base_url="http://testserver") as client: + response = await client.get("/api/v1/agents/agent-result-capture-owner-acceptance-maintenance-gate") + + assert response.status_code == 200 + data = response.json() + assert data["schema_version"] == "ai_agent_result_capture_owner_acceptance_maintenance_gate_v1" + assert data["program_status"]["current_task_id"] == "P2-127" + assert data["program_status"]["next_task_id"] == "P2-128" + + rollups = data["rollups"] + assert rollups["owner_acceptance_packet_count"] == 5 + assert rollups["maintenance_window_count"] == 5 + assert rollups["rollback_owner_check_count"] == 5 + assert rollups["post_apply_verifier_gate_count"] == 5 + assert rollups["blocked_live_write_count"] == 6 + assert rollups["operator_action_count"] == 5 + assert rollups["writer_apply_count"] == 0 + assert rollups["execution_apply_count"] == 0 + assert rollups["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["gateway_queue_write_count"] == 0 + assert rollups["telegram_send_count"] == 0 + assert rollups["bot_api_call_count"] == 0 + assert rollups["production_write_count"] == 0 + assert {item["owner_accepted"] for item in data["owner_acceptance_packets"]} == {False} + assert {item["window_approved"] for item in data["maintenance_windows"]} == {False} + assert {item["rollback_owner_confirmed"] for item in data["rollback_owner_checks"]} == {False} diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index 287cac3c2..4901d83b7 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -5878,6 +5878,39 @@ "rollbackConfirmed": "rollback 已確認={value}" } }, + "resultCaptureOwnerAcceptanceMaintenanceGate": { + "title": "P2-127 owner acceptance / maintenance window gate", + "source": "產生 {generated};目前 {current};下一步 {next}", + "priorTitle": "前一關 execution rehearsal", + "truthTitle": "owner acceptance 真相", + "metrics": { + "overall": "完成度", + "packets": "Owner packets", + "windows": "Maintenance windows", + "rollbacks": "Rollback owners", + "verifiers": "Post-apply verifiers", + "blockers": "已阻擋 live write", + "actions": "操作選項", + "approvalRequired": "需批准", + "blocked": "阻擋", + "liveWrites": "正式寫入 / 發送" + }, + "flags": { + "rehearsalLoaded": "已載入 P2-126={value}", + "windowRequired": "maintenance window required={value}", + "rollbackRequired": "rollback owner required={value}" + }, + "labels": { + "ownerAccepted": "owner accepted={value}", + "windowApproved": "window approved={value}", + "gatewayWrites": "Gateway 寫入={value}", + "acceptanceRequired": "acceptance required={value}", + "ownerAcceptedBool": "owner accepted={value}", + "windowApprovedBool": "window approved={value}", + "rollbackRequired": "需要 rollback owner={value}", + "rollbackConfirmed": "rollback 已確認={value}" + } + }, "resultCaptureWriteGateReview": { "title": "P2-121 result capture write gate review", "source": "產生 {generated};目前 {current};下一步 {next}", diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index 287cac3c2..4901d83b7 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -5878,6 +5878,39 @@ "rollbackConfirmed": "rollback 已確認={value}" } }, + "resultCaptureOwnerAcceptanceMaintenanceGate": { + "title": "P2-127 owner acceptance / maintenance window gate", + "source": "產生 {generated};目前 {current};下一步 {next}", + "priorTitle": "前一關 execution rehearsal", + "truthTitle": "owner acceptance 真相", + "metrics": { + "overall": "完成度", + "packets": "Owner packets", + "windows": "Maintenance windows", + "rollbacks": "Rollback owners", + "verifiers": "Post-apply verifiers", + "blockers": "已阻擋 live write", + "actions": "操作選項", + "approvalRequired": "需批准", + "blocked": "阻擋", + "liveWrites": "正式寫入 / 發送" + }, + "flags": { + "rehearsalLoaded": "已載入 P2-126={value}", + "windowRequired": "maintenance window required={value}", + "rollbackRequired": "rollback owner required={value}" + }, + "labels": { + "ownerAccepted": "owner accepted={value}", + "windowApproved": "window approved={value}", + "gatewayWrites": "Gateway 寫入={value}", + "acceptanceRequired": "acceptance required={value}", + "ownerAcceptedBool": "owner accepted={value}", + "windowApprovedBool": "window approved={value}", + "rollbackRequired": "需要 rollback owner={value}", + "rollbackConfirmed": "rollback 已確認={value}" + } + }, "resultCaptureWriteGateReview": { "title": "P2-121 result capture write gate review", "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 7d48dc049..3b6024978 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 @@ -74,6 +74,7 @@ import { type AiAgentResultCaptureWriterDryRunReadbackSnapshot, type AiAgentResultCaptureOwnerPromotionReviewSnapshot, type AiAgentResultCaptureOwnerApprovedExecutionRehearsalSnapshot, + type AiAgentResultCaptureOwnerAcceptanceMaintenanceGateSnapshot, type AiAgentResultCaptureWriterImplementationReviewSnapshot, type AiAgentOwnerApprovedFixturePromotionGateSnapshot, type AiAgentRuntimeWorkerShadowGateSnapshot, @@ -471,6 +472,7 @@ export function AutomationInventoryTab() { const [resultCaptureWriterDryRunReadback, setResultCaptureWriterDryRunReadback] = useState(null) const [resultCaptureOwnerPromotionReview, setResultCaptureOwnerPromotionReview] = useState(null) const [resultCaptureOwnerApprovedExecutionRehearsal, setResultCaptureOwnerApprovedExecutionRehearsal] = useState(null) + const [resultCaptureOwnerAcceptanceMaintenanceGate, setResultCaptureOwnerAcceptanceMaintenanceGate] = useState(null) const [reportTruthActionabilityReview, setReportTruthActionabilityReview] = useState(null) const [ownerDryRunPackage, setOwnerDryRunPackage] = useState(null) const [hostStatefulInventory, setHostStatefulInventory] = useState(null) @@ -534,6 +536,7 @@ export function AutomationInventoryTab() { apiClient.getAiAgentResultCaptureWriterDryRunReadback(), apiClient.getAiAgentResultCaptureOwnerPromotionReview(), apiClient.getAiAgentResultCaptureOwnerApprovedExecutionRehearsal(), + apiClient.getAiAgentResultCaptureOwnerAcceptanceMaintenanceGate(), apiClient.getAiAgentReportTruthActionabilityReview(), apiClient.getAiAgentOwnerApprovedFixtureDryRun(), apiClient.getAiAgentHostStatefulVersionInventory(), @@ -596,6 +599,7 @@ export function AutomationInventoryTab() { resultCaptureWriterDryRunReadbackResult, resultCaptureOwnerPromotionReviewResult, resultCaptureOwnerApprovedExecutionRehearsalResult, + resultCaptureOwnerAcceptanceMaintenanceGateResult, reportTruthActionabilityReviewResult, ownerDryRunPackageResult, hostStatefulInventoryResult, @@ -655,6 +659,7 @@ export function AutomationInventoryTab() { setResultCaptureWriterDryRunReadback(resultCaptureWriterDryRunReadbackResult.status === 'fulfilled' ? resultCaptureWriterDryRunReadbackResult.value : null) setResultCaptureOwnerPromotionReview(resultCaptureOwnerPromotionReviewResult.status === 'fulfilled' ? resultCaptureOwnerPromotionReviewResult.value : null) setResultCaptureOwnerApprovedExecutionRehearsal(resultCaptureOwnerApprovedExecutionRehearsalResult.status === 'fulfilled' ? resultCaptureOwnerApprovedExecutionRehearsalResult.value : null) + setResultCaptureOwnerAcceptanceMaintenanceGate(resultCaptureOwnerAcceptanceMaintenanceGateResult.status === 'fulfilled' ? resultCaptureOwnerAcceptanceMaintenanceGateResult.value : null) setReportTruthActionabilityReview(reportTruthActionabilityReviewResult.status === 'fulfilled' ? reportTruthActionabilityReviewResult.value : null) setOwnerDryRunPackage(ownerDryRunPackageResult.status === 'fulfilled' ? ownerDryRunPackageResult.value : null) setHostStatefulInventory(hostStatefulInventoryResult.status === 'fulfilled' ? hostStatefulInventoryResult.value : null) @@ -712,6 +717,7 @@ export function AutomationInventoryTab() { resultCaptureWriterDryRunReadbackResult, resultCaptureOwnerPromotionReviewResult, resultCaptureOwnerApprovedExecutionRehearsalResult, + resultCaptureOwnerAcceptanceMaintenanceGateResult, reportTruthActionabilityReviewResult, ownerDryRunPackageResult, hostStatefulInventoryResult, @@ -1954,7 +1960,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 || !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 || !reportTruthActionabilityReview || !ownerDryRunPackage || !hostStatefulInventory || !serviceHealthGapMatrix || !serviceHealthNotificationPolicy) { return (
@@ -2862,6 +2868,40 @@ export function AutomationInventoryTab() { + resultCaptureOwnerApprovedExecutionRehearsal.rollups.playbook_trust_write_count + resultCaptureOwnerApprovedExecutionRehearsal.rollups.production_write_count ) + const resultCaptureOwnerAcceptanceOverall = resultCaptureOwnerAcceptanceMaintenanceGate.program_status.overall_completion_percent + const resultCaptureOwnerAcceptancePackets = resultCaptureOwnerAcceptanceMaintenanceGate.rollups.owner_acceptance_packet_count + const resultCaptureOwnerAcceptanceWindows = resultCaptureOwnerAcceptanceMaintenanceGate.rollups.maintenance_window_count + const resultCaptureOwnerAcceptanceRollbacks = resultCaptureOwnerAcceptanceMaintenanceGate.rollups.rollback_owner_check_count + const resultCaptureOwnerAcceptanceVerifiers = resultCaptureOwnerAcceptanceMaintenanceGate.rollups.post_apply_verifier_gate_count + const resultCaptureOwnerAcceptanceBlockers = resultCaptureOwnerAcceptanceMaintenanceGate.rollups.blocked_live_write_count + const resultCaptureOwnerAcceptanceActions = resultCaptureOwnerAcceptanceMaintenanceGate.rollups.operator_action_count + const resultCaptureOwnerAcceptanceApprovalRequired = ( + resultCaptureOwnerAcceptanceMaintenanceGate.rollups.approval_required_packet_count + + resultCaptureOwnerAcceptanceMaintenanceGate.rollups.approval_required_window_count + + resultCaptureOwnerAcceptanceMaintenanceGate.rollups.approval_required_rollback_count + + resultCaptureOwnerAcceptanceMaintenanceGate.rollups.approval_required_verifier_count + ) + const resultCaptureOwnerAcceptanceBlocked = ( + resultCaptureOwnerAcceptanceMaintenanceGate.rollups.blocked_packet_count + + resultCaptureOwnerAcceptanceMaintenanceGate.rollups.blocked_window_count + + resultCaptureOwnerAcceptanceMaintenanceGate.rollups.blocked_rollback_count + + resultCaptureOwnerAcceptanceMaintenanceGate.rollups.blocked_verifier_count + + resultCaptureOwnerAcceptanceMaintenanceGate.rollups.critical_blocker_count + ) + const resultCaptureOwnerAcceptanceLiveWrites = ( + resultCaptureOwnerAcceptanceMaintenanceGate.rollups.writer_apply_count + + resultCaptureOwnerAcceptanceMaintenanceGate.rollups.execution_apply_count + + resultCaptureOwnerAcceptanceMaintenanceGate.rollups.receipt_write_count + + resultCaptureOwnerAcceptanceMaintenanceGate.rollups.reviewer_queue_write_count + + resultCaptureOwnerAcceptanceMaintenanceGate.rollups.gateway_queue_write_count + + resultCaptureOwnerAcceptanceMaintenanceGate.rollups.telegram_send_count + + resultCaptureOwnerAcceptanceMaintenanceGate.rollups.bot_api_call_count + + resultCaptureOwnerAcceptanceMaintenanceGate.rollups.report_receipt_write_count + + resultCaptureOwnerAcceptanceMaintenanceGate.rollups.result_capture_write_count + + resultCaptureOwnerAcceptanceMaintenanceGate.rollups.learning_write_count + + resultCaptureOwnerAcceptanceMaintenanceGate.rollups.playbook_trust_write_count + + resultCaptureOwnerAcceptanceMaintenanceGate.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 @@ -7411,6 +7451,127 @@ export function AutomationInventoryTab() {
+
+
+
+ + + {t('resultCaptureOwnerAcceptanceMaintenanceGate.title')} + +
+ +
+ +
+ } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> +
+ +
+
+ {t('resultCaptureOwnerAcceptanceMaintenanceGate.priorTitle')} + + {resultCaptureOwnerAcceptanceMaintenanceGate.prior_owner_approved_execution_rehearsal.readiness_note} + +
+ + + +
+
+ +
+ {t('resultCaptureOwnerAcceptanceMaintenanceGate.truthTitle')} + + {resultCaptureOwnerAcceptanceMaintenanceGate.owner_acceptance_truth.truth_note} + +
+ + + + + + +
+
+
+ +
+ {resultCaptureOwnerAcceptanceMaintenanceGate.owner_acceptance_packets.slice(0, 5).map(packet => ( +
+
+ + {packet.display_name} + + +
+ + {packet.source_rehearsal} → {packet.required_evidence} + +
+ + + + +
+
+ ))} +
+ +
+ {resultCaptureOwnerAcceptanceMaintenanceGate.maintenance_windows.slice(0, 5).map(window => ( +
+
+ + {window.display_name} + + +
+ + {window.blackout_policy} {window.validation_plan} + + +
+ ))} +
+ +
+ {resultCaptureOwnerAcceptanceMaintenanceGate.rollback_owner_checks.slice(0, 5).map(check => ( +
+
+ + {check.display_name} + + +
+ + {check.rollback_scope} {check.failure_if_missing} + +
+ + + +
+
+ ))} +
+
+
diff --git a/apps/web/src/lib/api-client.ts b/apps/web/src/lib/api-client.ts index db2f3bb00..b1aff8d4b 100644 --- a/apps/web/src/lib/api-client.ts +++ b/apps/web/src/lib/api-client.ts @@ -530,6 +530,11 @@ export const apiClient = { return handleResponse(res) }, + async getAiAgentResultCaptureOwnerAcceptanceMaintenanceGate() { + const res = await fetch(`${API_BASE_URL}/agents/agent-result-capture-owner-acceptance-maintenance-gate`) + return handleResponse(res) + }, + async getAiAgentOwnerApprovedFixtureDryRun() { const res = await fetch(`${API_BASE_URL}/agents/agent-owner-approved-fixture-dry-run`) return handleResponse(res) @@ -6741,6 +6746,198 @@ export interface AiAgentResultCaptureOwnerApprovedExecutionRehearsalSnapshot { } } +export interface AiAgentResultCaptureOwnerAcceptanceMaintenanceGateSnapshot { + schema_version: 'ai_agent_result_capture_owner_acceptance_maintenance_gate_v1' + generated_at: string + program_status: { + overall_completion_percent: number + current_priority: 'P0' | 'P1' | 'P2' | 'P3' + current_task_id: 'P2-127' + next_task_id: 'P2-128' + read_only_mode: true + runtime_authority: 'result_capture_owner_acceptance_maintenance_gate_only_no_live_write' + status_note: string + } + source_refs: string[] + prior_owner_approved_execution_rehearsal: { + schema_version: string + execution_rehearsal_count: number + no_write_apply_check_count: number + post_write_verifier_rehearsal_count: number + rollback_drill_count: number + blocked_live_apply_count: number + operator_action_count: number + approval_required_total: number + blocked_total: number + owner_approval_record_received_count: number + no_write_apply_execution_count: number + post_write_verifier_pass_count: number + rollback_drill_confirmed_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 + } + owner_acceptance_truth: { + p2_126_execution_rehearsal_loaded: boolean + owner_acceptance_packet_ready: boolean + maintenance_window_required: boolean + rollback_owner_required: boolean + post_apply_verifier_required: boolean + redaction_review_required: boolean + live_apply_gate_closed: boolean + acceptance_gate_only: boolean + owner_acceptance_received: boolean + maintenance_window_approved: boolean + rollback_owner_confirmed: boolean + post_apply_verifier_ready: 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_acceptance_received_count: number + maintenance_window_approved_count: number + rollback_owner_confirmed_count: number + post_apply_verifier_ready_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 + } + owner_acceptance_packets: Array<{ + packet_id: string + display_name: string + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + source_rehearsal: string + status: 'ready_for_owner_review' | 'approval_required' | 'blocked_by_policy' + packet_mode: 'owner_acceptance_required' + owner_acceptance_required: true + owner_accepted: false + required_evidence: string + evidence_hash: string + }> + maintenance_windows: Array<{ + window_id: string + display_name: string + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + status: 'ready_for_owner_review' | 'approval_required' | 'blocked_by_policy' + window_mode: 'maintenance_window_draft' + maintenance_window_required: true + window_approved: false + blackout_policy: string + validation_plan: string + }> + rollback_owner_checks: Array<{ + check_id: string + display_name: string + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + status: 'ready_for_owner_review' | 'approval_required' | 'blocked_by_policy' + rollback_owner_required: true + rollback_owner_confirmed: false + rollback_scope: string + failure_if_missing: string + }> + post_apply_verifier_gates: Array<{ + gate_id: string + display_name: string + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + status: 'ready_for_owner_review' | 'approval_required' | 'blocked_by_policy' + gate_mode: 'post_apply_verifier_gate' + verifier_ready: false + live_read_enabled: false + expected_signal: string + }> + blocked_live_writes: Array<{ + blocker_id: string + display_name: string + severity: 'high' | 'critical' + status: 'approval_required' | 'blocked_by_policy' + blocked_action: string + blocked_until: string + evidence_hash: string + }> + operator_actions: Array<{ + action_id: string + display_name: string + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + 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: { + owner_acceptance_packet_count: number + maintenance_window_count: number + rollback_owner_check_count: number + post_apply_verifier_gate_count: number + blocked_live_write_count: number + operator_action_count: number + approval_required_packet_count: number + blocked_packet_count: number + approval_required_window_count: number + blocked_window_count: number + approval_required_rollback_count: number + blocked_rollback_count: number + approval_required_verifier_count: number + blocked_verifier_count: number + critical_blocker_count: number + owner_acceptance_received_count: number + maintenance_window_approved_count: number + rollback_owner_confirmed_count: number + post_apply_verifier_ready_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 2066ffdfd..9f1903fa0 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -1,3 +1,62 @@ +## 2026-06-14|P2-127 Owner acceptance / maintenance window gate 本地完成 + +**背景**:P2-126 已把 owner-approved execution rehearsal / no-write apply gate 正式驗證完成;但真正接近 writer apply、execution apply、receipt write、result capture、learning、PlayBook trust、reviewer queue、Gateway queue 或 Telegram 前,仍需要把 owner acceptance、maintenance window、rollback owner 與 post-apply verifier gate 固定成可審核、可阻擋、可回滾的封包。P2-127 因此只建立 acceptance / maintenance gate,不套用 writer、不開維護窗口、不確認 rollback owner、不寫 receipt、不寫 result capture / learning / PlayBook trust / reviewer queue / Gateway queue,也不送 Telegram 或呼叫 Bot API。 + +**完成內容**: +- 新增 `ai_agent_result_capture_owner_acceptance_maintenance_gate_v1` schema、committed snapshot、loader 與 API endpoint `GET /api/v1/agents/agent-result-capture-owner-acceptance-maintenance-gate`。 +- P2-127 snapshot 固定 5 個 owner acceptance packet、5 個 maintenance window、5 個 rollback owner check、5 個 post-apply verifier gate、6 個 blocked live write 與 5 個 operator action。 +- Governance automation inventory 頁新增 P2-127 區塊,顯示 P2-127 進度 `100%`、owner packet `5`、maintenance window `5`、rollback owner `5`、post-apply verifier `5`、blocked live write `6`、operator action `5`、需批准 `8`、阻擋 `9`、正式寫入 / 發送 `0`。 +- Owner acceptance truth 固定為 `result_capture_owner_acceptance_maintenance_gate_only_no_live_write`;owner accepted、maintenance window approved、rollback owner confirmed、post-apply verifier ready、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-127 schema / snapshot、`zh-TW.json`、`en.json` 通過。 +- Python 編譯:P2-127 loader 與 `agents.py` 通過。 +- API/service pytest:P2-127 + P2-126 regression `13 passed`。 +- Web typecheck:`pnpm --filter @awoooi/web typecheck` 通過。 +- `git diff --check` 通過。 +- 本段仍是本地完成;正式 API readback、正式站 desktop / mobile Browser smoke 與 deploy marker 需在推送 Gitea main 並完成 CD 後補齊。 + +**安全邊界**: +- P2-127 仍是 owner acceptance / maintenance window gate;不接受口頭批准、不自動把本對話批准轉成 owner acceptance record、不開維護窗口、不確認 rollback owner、不啟用 post-apply verifier live read、不套用 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-128`:owner acceptance readback / live-apply preflight hold;只有 P2-127 正式驗證後才可把 owner acceptance packet、maintenance window、rollback owner 與 post-apply verifier gate 轉成 readback / preflight hold,仍不得直接開啟 result capture writer、learning writer、PlayBook trust writer、reviewer queue write、Gateway queue write、Telegram send、Bot API call 或 production write。 + +## 2026-06-14|P2-126 Owner-approved execution rehearsal / no-write apply gate 本地完成與正式驗證 + +**背景**:P2-125 已把 result capture owner promotion review / execution gate 固定成可審核封包;但真正進入 writer apply、execution apply、receipt write、result capture、learning、PlayBook trust、reviewer queue、Gateway queue 或 Telegram 前,仍需要把 owner-approved execution path 先整理成 no-write rehearsal、apply gate、post-write verifier rehearsal 與 rollback drill。P2-126 因此只建立 execution rehearsal,不套用 writer、不執行 production write、不寫 receipt、不寫 result capture / learning / PlayBook trust / reviewer queue / Gateway queue,也不送 Telegram 或呼叫 Bot API。 + +**完成內容**: +- 新增 `ai_agent_result_capture_owner_approved_execution_rehearsal_v1` schema、committed snapshot、loader 與 API endpoint `GET /api/v1/agents/agent-result-capture-owner-approved-execution-rehearsal`。 +- P2-126 snapshot 固定 5 個 execution rehearsal、5 個 no-write apply check、5 個 post-write verifier rehearsal、5 個 rollback drill、6 個 blocked live apply 與 5 個 operator action。 +- Governance automation inventory 頁新增 P2-126 區塊,顯示 P2-126 進度 `100%`、execution rehearsal `5`、no-write apply check `5`、post-write verifier `5`、rollback drill `5`、blocked live apply `6`、operator action `5`、需批准 `8`、阻擋 `9`、正式寫入 / 發送 `0`。 +- Execution rehearsal truth 固定為 `result_capture_owner_approved_execution_rehearsal_only_no_live_write`;owner approval record received、no-write apply executed、post-write verifier passed、rollback drill confirmed、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`。 + +**本地驗證**: +- JSON parse:P2-126 snapshot 通過。 +- 正式 API readback 前,P2-126 loader / schema / API / UI 已由 feature commit `1ceaa458 feat(governance): 新增 owner-approved execution rehearsal` 納入主線。 +- 本 closeout 只補文件與正式證據,不變更 runtime、不新增按鈕、不啟用 writer、不送 Telegram。 + +**正式部署錨點與 readback**: +- Feature commit:`1ceaa458 feat(governance): 新增 owner-approved execution rehearsal`。 +- Deploy marker:`02ff5763 chore(cd): deploy 1ceaa45 [skip ci]`。 +- 正式 API:`GET /api/v1/health` 回 `healthy / prod / mock_mode=false`;`api/postgresql/redis/openclaw/signoz/ollama_gcp_a/ollama_gcp_b=up`,`ollama_local` 仍是既有 cooldown debt,不影響 P2-126 只讀契約。 +- 正式 API:`GET /api/v1/agents/agent-result-capture-owner-approved-execution-rehearsal` 回 `schema_version=ai_agent_result_capture_owner_approved_execution_rehearsal_v1`、current `P2-126`、next `P2-127`、completion `100`、runtime authority `result_capture_owner_approved_execution_rehearsal_only_no_live_write`。 +- 正式 API rollup:execution rehearsal `5`、no-write apply check `5`、post-write verifier rehearsal `5`、rollback drill `5`、blocked live apply `6`、operator action `5`、approval-required rehearsal / check / verifier / rollback `2 / 2 / 2 / 2`、blocked rehearsal / check / verifier / rollback `1 / 1 / 1 / 1`、critical blocker `5`。 +- 正式 API 0 / false 邊界:owner approval record received、no-write apply executed、post-write verifier passed、rollback drill confirmed、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`。 + +**正式站 Browser smoke**: +- Desktop URL:`https://awoooi.wooo.work/zh-TW/governance?tab=automation-inventory&_v=p2-126-prod-verify-02ff5763`,viewport `1440x1000`。 +- Mobile URL:`https://awoooi.wooo.work/zh-TW/governance?tab=automation-inventory&_v=p2-126-prod-verify-02ff5763`,viewport `390x844`。 +- Mobile / desktop 皆可見:`P2-126`、`owner-approved execution rehearsal`、`P2-127`、`no-write apply`、`post-write verifier`、`rollback drill`、`正式寫入 / 發送`、`writer 套用=0`、`execution 套用=0`、`Gateway 寫入=0`。 +- Mobile / desktop:`horizontalOverflow=0`、overflowing elements `0`、內容危險入口 `0`、禁用內部協作 / raw field 片語命中 `0`。 + +**安全邊界**: +- P2-126 仍是 owner-approved execution rehearsal / no-write apply gate;不套用 writer、不執行 no-write apply、不寫 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-127`:owner acceptance / maintenance window / rollback owner gate;只有 P2-126 已正式驗證後才可整理 owner acceptance、maintenance window、rollback owner、post-apply verifier gate 與 live apply blocked contract,仍不得直接開啟 result capture writer、learning writer、PlayBook trust writer、reviewer queue write、Gateway queue write、Telegram send、Bot API call 或 production write。 + ## 2026-06-14|P2-125 Result capture owner promotion review / execution gate 本地完成與正式驗證 **背景**:P2-124 已把 writer dry-run readback、receipt verifier 與 promotion readiness 固定成只讀 readback;但要往真正 writer apply 前進,還需要把 owner promotion packet、execution gate、rollback owner review、blocked execution write 與 operator action 轉成可審核、可阻擋、可交接的下一關。P2-125 因此只建立 result capture owner promotion review / execution gate,不套用 writer、不執行 production write、不寫 receipt、不寫 result capture / learning / PlayBook trust / reviewer queue / Gateway queue,也不送 Telegram 或呼叫 Bot API。 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 a6910d329..9f406fdab 100644 --- a/docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md +++ b/docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md @@ -12,17 +12,17 @@ | 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-125 已完成只讀證據面、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;P2-125 固定 5 個 owner promotion packet、5 個 execution gate check、5 個 rollback owner review、6 個 blocked execution write 與 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_owner_promotion_review_v1`、`GET /api/v1/agents/agent-result-capture-owner-promotion-review`、`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`、`/zh-TW/governance?tab=automation-inventory`、MASTER §3.2.1b / §3.2.1d / §3.4.3 | +| OpenClaw / Hermes / NemoTron 主動溝通、學習與成長證據 | 100% | P2-401A 到 P2-127 已完成只讀證據面、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;P2-127 固定 5 個 owner acceptance packet、5 個 maintenance window、5 個 rollback owner check、5 個 post-apply verifier gate、6 個 blocked live write 與 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_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`、`/zh-TW/governance?tab=automation-inventory`、MASTER §3.2.1b / §3.2.1d / §3.4.3 | | AI Agent 主動營運委派與版本生命週期 | 100% | P2-402A / P2-402B / P2-402C / P2-402D / P2-402E / P2-402F / P2-402G 已完成;已建立 repo-only 版本新鮮度快照、工具採用批准包、Telegram action-required digest policy、Gitea PR 草案 lane、host / K3s / stateful 版本只讀盤點、API 與 governance UI。定期排程、外部版本查詢、工具安裝、CI 變更、套件升級、主機更新、container pull、實際 PR creation、auto merge、Telegram 實發、SSH、kubectl、重啟仍未開 gate | `ai_agent_proactive_operations_contract_v1`、`ai_agent_version_freshness_snapshot_v1`、`ai_agent_tool_adoption_approval_package_v1`、`ai_agent_telegram_action_required_digest_policy_v1`、`ai_agent_gitea_pr_draft_lane_v1`、`ai_agent_host_stateful_version_inventory_v1`、`GET /api/v1/agents/agent-proactive-operations-contract`、`GET /api/v1/agents/agent-version-freshness-snapshot`、`GET /api/v1/agents/agent-tool-adoption-approval-package`、`GET /api/v1/agents/agent-telegram-action-required-digest-policy`、`GET /api/v1/agents/agent-gitea-pr-draft-lane`、`GET /api/v1/agents/agent-host-stateful-version-inventory`、`/zh-TW/governance?tab=automation-inventory`、MASTER §3.2.1c | | 本工作清單與分析報告 | 100% | 已完成 | 本 MD 文件 | -AI Agent 自動化工作包目前完成度:**99%**。本工作清單文件本身完成度:**100%**。 +AI Agent 自動化工作包目前完成度:**99.1%**。本工作清單文件本身完成度:**100%**。 三 Agent 佈建布局目前完成度:**45%**。第一波已完成只讀 schema / snapshot / API / 測試 / 報告,第二波已接入治理頁自動化盤點 UI;正式 runtime 佈署、Telegram E2E 發送與 AgentSession 工作流仍需逐項 gate。 -三 Agent 主動溝通、學習與成長證據目前完成度:**100%**。P2-403A 到 P2-125 已把互動證據、報表治理、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 全部固定成可驗證證據。P2-125 已正式驗證並固定 5 個 owner promotion packet、5 個 execution gate check、5 個 rollback owner review、6 個 blocked execution write 與 5 個 operator action;目前 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-126`。 +三 Agent 主動溝通、學習與成長證據目前完成度:**100%**。P2-403A 到 P2-127 已把互動證據、報表治理、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 全部固定成可驗證證據。P2-127 已本地驗證並固定 5 個 owner acceptance packet、5 個 maintenance window、5 個 rollback owner check、5 個 post-apply verifier gate、6 個 blocked live write 與 5 個 operator action;目前 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-128`。 -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-125` 已補互動、學習證據面、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。下一步是 `P2-126`;外部 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-127` 已補互動、學習證據面、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。下一步是 `P2-128`;外部 registry / package source / host probe / SSH / kubectl / 工具安裝 / CI 變更 / 實際 PR creation / Telegram 實發與 learning write 仍需 gate。 完成度計算模型: @@ -997,7 +997,9 @@ UI: | P2-122 | 完成 | 100 | OpenClaw + Hermes + NemoTron | result capture writer implementation review | `ai_agent_result_capture_writer_implementation_review_v1` / schema / snapshot / 只讀 API / governance UI;正式站 deploy marker `5a0ee844` 已驗證;5 個 writer implementation review、5 個 implementation gate、5 個 post-implementation verifier plan、6 個 blocked runtime change、5 個 operator action;target implementation gate 固定 `result_capture_writer_implementation_review`;writer apply / result capture / learning / PlayBook trust / reviewer queue / Gateway / Telegram / Bot API / report receipt / production write 全為 `0` | 已由 P2-123 承接;不套用 writer、不寫 result capture、不寫 learning、不更新 PlayBook trust、不送 Telegram、不寫 production | | P2-123 | 完成 | 100 | OpenClaw + Hermes + NemoTron | result capture writer dry-run fixture | `ai_agent_result_capture_writer_dry_run_fixture_v1` / schema / snapshot / 只讀 API / governance UI;正式站 deploy marker `efa6b5ae` 已驗證;5 個 writer dry-run fixture、5 個 receipt preview、5 個 idempotency replay check、5 個 rollback rehearsal、6 個 blocked runtime write、5 個 operator action;target dry-run 固定 `result_capture_writer_dry_run_fixture`;writer apply / dry-run execution / receipt write / result capture / learning / PlayBook trust / reviewer queue / Gateway / Telegram / Bot API / report receipt / production write 全為 `0` | 已由 P2-124 承接;不套用 writer、不執行 dry-run、不寫 receipt、不寫 result capture、不寫 learning、不更新 PlayBook trust、不送 Telegram、不寫 production | | P2-124 | 完成 | 100 | OpenClaw + Hermes + NemoTron | result capture writer dry-run readback | `ai_agent_result_capture_writer_dry_run_readback_v1` / schema / snapshot / 只讀 API / governance UI;正式站 deploy marker `110911c4` 已驗證;5 個 dry-run readback、5 個 receipt verifier、5 個 promotion gate、6 個 blocked promotion write、5 個 operator action;runtime authority 固定 `result_capture_writer_dry_run_readback_only_no_live_write`;writer apply / dry-run execution / receipt write / promotion apply / result capture / learning / PlayBook trust / reviewer queue / Gateway / Telegram / Bot API / report receipt / production write 全為 `0` | 已由 P2-125 承接;不套用 writer、不執行 dry-run、不寫 receipt、不寫 result capture、不寫 learning、不更新 PlayBook trust、不送 Telegram、不寫 production | -| P2-125 | 完成 | 100 | OpenClaw + Hermes + NemoTron | result capture owner promotion review / execution gate | `ai_agent_result_capture_owner_promotion_review_v1` / schema / snapshot / 只讀 API / governance UI;正式站 deploy marker `a86f9cef` 已驗證;5 個 owner promotion packet、5 個 execution gate check、5 個 rollback owner review、6 個 blocked execution write、5 個 operator action;execution truth 固定 `result_capture_owner_promotion_review_only_no_live_write`;owner promotion approved / execution gate pass / rollback confirmed / writer apply / execution apply / receipt write / result capture / learning / PlayBook trust / reviewer queue / Gateway / Telegram / Bot API / report receipt / production write 全為 `0` | 下一步 P2-126;不套用 writer、不執行正式寫入、不寫 receipt、不寫 result capture、不寫 learning、不更新 PlayBook trust、不送 Telegram、不寫 production | +| P2-125 | 完成 | 100 | OpenClaw + Hermes + NemoTron | result capture owner promotion review / execution gate | `ai_agent_result_capture_owner_promotion_review_v1` / schema / snapshot / 只讀 API / governance UI;正式站 deploy marker `a86f9cef` 已驗證;5 個 owner promotion packet、5 個 execution gate check、5 個 rollback owner review、6 個 blocked execution write、5 個 operator action;execution truth 固定 `result_capture_owner_promotion_review_only_no_live_write`;owner promotion approved / execution gate pass / rollback confirmed / writer apply / execution apply / receipt write / result capture / learning / PlayBook trust / reviewer queue / Gateway / Telegram / Bot API / report receipt / production write 全為 `0` | 已由 P2-126 承接;不套用 writer、不執行正式寫入、不寫 receipt、不寫 result capture、不寫 learning、不更新 PlayBook trust、不送 Telegram、不寫 production | +| P2-126 | 完成 | 100 | OpenClaw + Hermes + NemoTron | owner-approved execution rehearsal / no-write apply gate | `ai_agent_result_capture_owner_approved_execution_rehearsal_v1` / schema / snapshot / 只讀 API / governance UI;正式站 deploy marker `02ff5763` 已驗證;5 個 execution rehearsal、5 個 no-write apply check、5 個 post-write verifier rehearsal、5 個 rollback drill、6 個 blocked live apply、5 個 operator action;execution rehearsal truth 固定 `result_capture_owner_approved_execution_rehearsal_only_no_live_write`;owner approval record received / no-write apply executed / post-write verifier passed / rollback confirmed / writer apply / execution apply / receipt write / result capture / learning / PlayBook trust / reviewer queue / Gateway / Telegram / Bot API / report receipt / production write 全為 `0` | 已由 P2-127 承接;不套用 writer、不執行 no-write apply、不寫 receipt、不寫 result capture、不寫 learning、不更新 PlayBook trust、不送 Telegram、不寫 production | +| P2-127 | 本地完成,正式站待驗證 | 100 | OpenClaw + Hermes + NemoTron | owner acceptance / maintenance window gate | `ai_agent_result_capture_owner_acceptance_maintenance_gate_v1` / schema / snapshot / 只讀 API / governance UI;5 個 owner acceptance packet、5 個 maintenance window、5 個 rollback owner check、5 個 post-apply verifier gate、6 個 blocked live write、5 個 operator action;runtime authority 固定 `result_capture_owner_acceptance_maintenance_gate_only_no_live_write`;owner accepted / maintenance window approved / rollback owner confirmed / post-apply verifier ready / writer apply / execution apply / receipt write / result capture / learning / PlayBook trust / reviewer queue / Gateway / Telegram / Bot API / report receipt / production write 全為 `0` | 下一步 P2-128;不接受口頭批准、不開維護窗口、不套用 writer、不寫 receipt、不寫 result capture、不寫 learning、不更新 PlayBook trust、不送 Telegram、不寫 production | ### P3 - 候選 Agent 擴展 diff --git a/docs/evaluations/ai_agent_result_capture_owner_acceptance_maintenance_gate_2026-06-14.json b/docs/evaluations/ai_agent_result_capture_owner_acceptance_maintenance_gate_2026-06-14.json new file mode 100644 index 000000000..45501510b --- /dev/null +++ b/docs/evaluations/ai_agent_result_capture_owner_acceptance_maintenance_gate_2026-06-14.json @@ -0,0 +1,452 @@ +{ + "schema_version": "ai_agent_result_capture_owner_acceptance_maintenance_gate_v1", + "generated_at": "2026-06-14T02:58:00+08:00", + "program_status": { + "overall_completion_percent": 100, + "current_priority": "P2", + "current_task_id": "P2-127", + "next_task_id": "P2-128", + "read_only_mode": true, + "runtime_authority": "result_capture_owner_acceptance_maintenance_gate_only_no_live_write", + "status_note": "P2-127 只建立 owner acceptance、maintenance window、rollback owner 與 post-apply verifier gate;不得套用 writer、寫 receipt、寫 result capture 或寫入 production。" + }, + "source_refs": [ + "docs/evaluations/ai_agent_result_capture_owner_approved_execution_rehearsal_2026-06-14.json", + "docs/evaluations/ai_agent_result_capture_owner_promotion_review_2026-06-14.json", + "docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md#47-建立-owner-approved-execution-rehearsal--no-write-apply-gate" + ], + "prior_owner_approved_execution_rehearsal": { + "schema_version": "ai_agent_result_capture_owner_approved_execution_rehearsal_v1", + "execution_rehearsal_count": 5, + "no_write_apply_check_count": 5, + "post_write_verifier_rehearsal_count": 5, + "rollback_drill_count": 5, + "blocked_live_apply_count": 6, + "operator_action_count": 5, + "approval_required_total": 8, + "blocked_total": 9, + "owner_approval_record_received_count": 0, + "no_write_apply_execution_count": 0, + "post_write_verifier_pass_count": 0, + "rollback_drill_confirmed_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-126 已提供 no-write execution rehearsal;P2-127 只把 acceptance、維護窗口、rollback owner 與 post-apply verifier 固定成 owner 可審查封包。" + }, + "owner_acceptance_truth": { + "p2_126_execution_rehearsal_loaded": true, + "owner_acceptance_packet_ready": true, + "maintenance_window_required": true, + "rollback_owner_required": true, + "post_apply_verifier_required": true, + "redaction_review_required": true, + "live_apply_gate_closed": true, + "acceptance_gate_only": true, + "owner_acceptance_received": false, + "maintenance_window_approved": false, + "rollback_owner_confirmed": false, + "post_apply_verifier_ready": 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_acceptance_received_count": 0, + "maintenance_window_approved_count": 0, + "rollback_owner_confirmed_count": 0, + "post_apply_verifier_ready_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-127 只建立 acceptance gate,不接受 owner 口頭批准、不自動開維護窗口、不寫 queue、不發 Telegram、不寫 production。" + }, + "owner_acceptance_packets": [ + { + "packet_id": "acceptance_result_capture_writer", + "display_name": "Result capture writer owner acceptance", + "owner_agent": "openclaw", + "source_rehearsal": "rehearsal_result_capture_writer", + "status": "ready_for_owner_review", + "packet_mode": "owner_acceptance_required", + "owner_acceptance_required": true, + "owner_accepted": false, + "required_evidence": "owner role、acceptance reason、affected scope、rollback owner 與 post-apply verifier plan。", + "evidence_hash": "sha256:a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1" + }, + { + "packet_id": "acceptance_learning_writer", + "display_name": "Learning writer owner acceptance", + "owner_agent": "hermes", + "source_rehearsal": "rehearsal_learning_writer", + "status": "approval_required", + "packet_mode": "owner_acceptance_required", + "owner_acceptance_required": true, + "owner_accepted": false, + "required_evidence": "KM owner、stale guard owner、rollback note 與 learning write scope。", + "evidence_hash": "sha256:a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2" + }, + { + "packet_id": "acceptance_playbook_trust_writer", + "display_name": "PlayBook trust owner acceptance", + "owner_agent": "nemotron", + "source_rehearsal": "rehearsal_playbook_trust_writer", + "status": "blocked_by_policy", + "packet_mode": "owner_acceptance_required", + "owner_acceptance_required": true, + "owner_accepted": false, + "required_evidence": "trust delta reviewer、negative reinforcement owner 與 rollback scope。", + "evidence_hash": "sha256:a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3" + }, + { + "packet_id": "acceptance_reviewer_queue_writer", + "display_name": "Reviewer queue owner acceptance", + "owner_agent": "openclaw", + "source_rehearsal": "rehearsal_reviewer_queue_writer", + "status": "approval_required", + "packet_mode": "owner_acceptance_required", + "owner_acceptance_required": true, + "owner_accepted": false, + "required_evidence": "reviewer queue owner、SLA owner、dedupe key owner 與 rollback owner。", + "evidence_hash": "sha256:a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4" + }, + { + "packet_id": "acceptance_gateway_queue_writer", + "display_name": "Gateway queue owner acceptance", + "owner_agent": "nemotron", + "source_rehearsal": "rehearsal_gateway_queue_writer", + "status": "ready_for_owner_review", + "packet_mode": "owner_acceptance_required", + "owner_acceptance_required": true, + "owner_accepted": false, + "required_evidence": "AwoooI SRE route owner、Telegram receipt owner、route lock 與 redaction owner。", + "evidence_hash": "sha256:a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5" + } + ], + "maintenance_windows": [ + { + "window_id": "window_result_capture_writer", + "display_name": "Result capture writer maintenance window", + "owner_agent": "openclaw", + "status": "ready_for_owner_review", + "window_mode": "maintenance_window_draft", + "maintenance_window_required": true, + "window_approved": false, + "blackout_policy": "避開 production incident、deploy freeze 與備份窗口。", + "validation_plan": "先跑 no-write apply、再驗 verifier preview、最後確認 rollback owner。" + }, + { + "window_id": "window_learning_writer", + "display_name": "Learning writer maintenance window", + "owner_agent": "hermes", + "status": "approval_required", + "window_mode": "maintenance_window_draft", + "maintenance_window_required": true, + "window_approved": false, + "blackout_policy": "避開 KM migration、embedding rebuild 與人工審核高峰。", + "validation_plan": "確認 KM draft、stale guard、owner scope 與 rollback note。" + }, + { + "window_id": "window_playbook_trust_writer", + "display_name": "PlayBook trust maintenance window", + "owner_agent": "nemotron", + "status": "blocked_by_policy", + "window_mode": "maintenance_window_draft", + "maintenance_window_required": true, + "window_approved": false, + "blackout_policy": "未完成 negative reinforcement review 前不得排維護窗口。", + "validation_plan": "確認 trust delta preview、負向強化規則與 rollback owner。" + }, + { + "window_id": "window_reviewer_queue_writer", + "display_name": "Reviewer queue maintenance window", + "owner_agent": "openclaw", + "status": "approval_required", + "window_mode": "maintenance_window_draft", + "maintenance_window_required": true, + "window_approved": false, + "blackout_policy": "避開 reviewer SLA 尖峰與人工審核隊列清空前。", + "validation_plan": "確認 queue preview、dedupe key、SLA route 與 rollback owner。" + }, + { + "window_id": "window_gateway_queue_writer", + "display_name": "Gateway queue maintenance window", + "owner_agent": "nemotron", + "status": "ready_for_owner_review", + "window_mode": "maintenance_window_draft", + "maintenance_window_required": true, + "window_approved": false, + "blackout_policy": "避開 Telegram route freeze、incident escalation 與告警降噪調整。", + "validation_plan": "確認 Gateway queue preview、route lock、redaction 與 Telegram receipt gate。" + } + ], + "rollback_owner_checks": [ + { + "check_id": "rollback_owner_result_capture", + "display_name": "Result capture rollback owner", + "owner_agent": "openclaw", + "status": "ready_for_owner_review", + "rollback_owner_required": true, + "rollback_owner_confirmed": false, + "rollback_scope": "撤回 result capture preview 與 audit trail append。", + "failure_if_missing": "缺 rollback owner 時不得進 live writer apply。" + }, + { + "check_id": "rollback_owner_learning", + "display_name": "Learning rollback owner", + "owner_agent": "hermes", + "status": "approval_required", + "rollback_owner_required": true, + "rollback_owner_confirmed": false, + "rollback_scope": "撤回 learning draft、KM write preview 與 stale guard。", + "failure_if_missing": "缺 rollback owner 時不得寫 learning。" + }, + { + "check_id": "rollback_owner_playbook_trust", + "display_name": "PlayBook trust rollback owner", + "owner_agent": "nemotron", + "status": "blocked_by_policy", + "rollback_owner_required": true, + "rollback_owner_confirmed": false, + "rollback_scope": "撤回 trust delta preview 與 negative reinforcement draft。", + "failure_if_missing": "缺 rollback owner 時不得更新 PlayBook trust。" + }, + { + "check_id": "rollback_owner_reviewer_queue", + "display_name": "Reviewer queue rollback owner", + "owner_agent": "openclaw", + "status": "approval_required", + "rollback_owner_required": true, + "rollback_owner_confirmed": false, + "rollback_scope": "撤回 reviewer queue preview、dedupe key 與 SLA handoff。", + "failure_if_missing": "缺 rollback owner 時不得寫 reviewer queue。" + }, + { + "check_id": "rollback_owner_gateway_queue", + "display_name": "Gateway queue rollback owner", + "owner_agent": "nemotron", + "status": "ready_for_owner_review", + "rollback_owner_required": true, + "rollback_owner_confirmed": false, + "rollback_scope": "撤回 Gateway queue preview、route lock 與 Telegram receipt draft。", + "failure_if_missing": "缺 rollback owner 時不得寫 Gateway queue 或發 Telegram。" + } + ], + "post_apply_verifier_gates": [ + { + "gate_id": "verifier_gate_result_capture", + "display_name": "Result capture post-apply verifier gate", + "owner_agent": "openclaw", + "status": "ready_for_owner_review", + "gate_mode": "post_apply_verifier_gate", + "verifier_ready": false, + "live_read_enabled": false, + "expected_signal": "result capture write、audit trail append 與 receipt hash 對齊。" + }, + { + "gate_id": "verifier_gate_learning", + "display_name": "Learning post-apply verifier gate", + "owner_agent": "hermes", + "status": "approval_required", + "gate_mode": "post_apply_verifier_gate", + "verifier_ready": false, + "live_read_enabled": false, + "expected_signal": "KM entry、learning metadata 與 stale guard 對齊。" + }, + { + "gate_id": "verifier_gate_playbook_trust", + "display_name": "PlayBook trust post-apply verifier gate", + "owner_agent": "nemotron", + "status": "blocked_by_policy", + "gate_mode": "post_apply_verifier_gate", + "verifier_ready": false, + "live_read_enabled": false, + "expected_signal": "trust score delta、negative reinforcement 與 rollback marker 對齊。" + }, + { + "gate_id": "verifier_gate_reviewer_queue", + "display_name": "Reviewer queue post-apply verifier gate", + "owner_agent": "openclaw", + "status": "approval_required", + "gate_mode": "post_apply_verifier_gate", + "verifier_ready": false, + "live_read_enabled": false, + "expected_signal": "reviewer queue item、dedupe key 與 SLA route 對齊。" + }, + { + "gate_id": "verifier_gate_gateway_queue", + "display_name": "Gateway queue post-apply verifier gate", + "owner_agent": "nemotron", + "status": "ready_for_owner_review", + "gate_mode": "post_apply_verifier_gate", + "verifier_ready": false, + "live_read_enabled": false, + "expected_signal": "Gateway queue item、Telegram route lock 與 receipt verifier 對齊。" + } + ], + "blocked_live_writes": [ + { + "blocker_id": "blocked_writer_apply", + "display_name": "Writer apply blocked", + "severity": "critical", + "status": "blocked_by_policy", + "blocked_action": "writer_apply", + "blocked_until": "P2-128 post-apply verifier package + owner acceptance", + "evidence_hash": "sha256:b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1" + }, + { + "blocker_id": "blocked_execution_apply", + "display_name": "Execution apply blocked", + "severity": "critical", + "status": "blocked_by_policy", + "blocked_action": "execution_apply", + "blocked_until": "maintenance window approved + rollback owner confirmed", + "evidence_hash": "sha256:b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2" + }, + { + "blocker_id": "blocked_receipt_write", + "display_name": "Receipt write blocked", + "severity": "high", + "status": "approval_required", + "blocked_action": "receipt_write", + "blocked_until": "post-apply verifier gate ready", + "evidence_hash": "sha256:b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3" + }, + { + "blocker_id": "blocked_result_capture_write", + "display_name": "Result capture write blocked", + "severity": "critical", + "status": "blocked_by_policy", + "blocked_action": "result_capture_write", + "blocked_until": "dual approval + acceptance evidence", + "evidence_hash": "sha256:b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4" + }, + { + "blocker_id": "blocked_gateway_queue_write", + "display_name": "Gateway queue write blocked", + "severity": "critical", + "status": "blocked_by_policy", + "blocked_action": "gateway_queue_write", + "blocked_until": "AwoooI SRE route owner accepts queue write", + "evidence_hash": "sha256:b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5" + }, + { + "blocker_id": "blocked_telegram_send", + "display_name": "Telegram send blocked", + "severity": "critical", + "status": "blocked_by_policy", + "blocked_action": "telegram_send", + "blocked_until": "Gateway queue E2E receipt + SRE route lock", + "evidence_hash": "sha256:b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6" + } + ], + "operator_actions": [ + { + "action_id": "review_owner_acceptance_packets", + "display_name": "審查 owner acceptance packet", + "owner_agent": "openclaw", + "operator_instruction": "確認每個 packet 都有 owner role、decision reason、affected scope 與 redacted evidence ref。", + "runtime_write_allowed": false + }, + { + "action_id": "confirm_maintenance_windows", + "display_name": "確認 maintenance window", + "owner_agent": "hermes", + "operator_instruction": "確認維護窗口避開 incident、deploy freeze、backup 與 Telegram route freeze。", + "runtime_write_allowed": false + }, + { + "action_id": "confirm_rollback_owners", + "display_name": "確認 rollback owner", + "owner_agent": "openclaw", + "operator_instruction": "確認 rollback owner、撤回範圍、驗證人與責任鏈都已具名。", + "runtime_write_allowed": false + }, + { + "action_id": "verify_post_apply_gates", + "display_name": "檢查 post-apply verifier gate", + "owner_agent": "nemotron", + "operator_instruction": "確認 verifier gate 仍未 live read,且只描述未來正式 apply 後要驗的信號。", + "runtime_write_allowed": false + }, + { + "action_id": "hold_live_apply_gate", + "display_name": "維持 live apply gate 關閉", + "owner_agent": "hermes", + "operator_instruction": "P2-127 完成前不得開 writer apply、queue write、Telegram send 或 production write。", + "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": "只顯示 gate id、owner、status、redacted hash、window / rollback 摘要與 operator instruction;不顯示提示詞、私有推理、secret、原始載荷、chat id 或內部協作內容。" + }, + "rollups": { + "owner_acceptance_packet_count": 5, + "maintenance_window_count": 5, + "rollback_owner_check_count": 5, + "post_apply_verifier_gate_count": 5, + "blocked_live_write_count": 6, + "operator_action_count": 5, + "approval_required_packet_count": 2, + "blocked_packet_count": 1, + "approval_required_window_count": 2, + "blocked_window_count": 1, + "approval_required_rollback_count": 2, + "blocked_rollback_count": 1, + "approval_required_verifier_count": 2, + "blocked_verifier_count": 1, + "critical_blocker_count": 5, + "owner_acceptance_received_count": 0, + "maintenance_window_approved_count": 0, + "rollback_owner_confirmed_count": 0, + "post_apply_verifier_ready_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_owner_acceptance_maintenance_gate_v1.schema.json b/docs/schemas/ai_agent_result_capture_owner_acceptance_maintenance_gate_v1.schema.json new file mode 100644 index 000000000..9db4cb1b0 --- /dev/null +++ b/docs/schemas/ai_agent_result_capture_owner_acceptance_maintenance_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_owner_acceptance_maintenance_gate_v1.schema.json", + "title": "AI Agent result capture owner acceptance maintenance gate v1", + "type": "object", + "required": [ + "schema_version", + "generated_at", + "program_status", + "source_refs", + "prior_owner_approved_execution_rehearsal", + "owner_acceptance_truth", + "owner_acceptance_packets", + "maintenance_windows", + "rollback_owner_checks", + "post_apply_verifier_gates", + "blocked_live_writes", + "operator_actions", + "display_redaction_contract", + "rollups" + ], + "properties": { + "schema_version": { + "const": "ai_agent_result_capture_owner_acceptance_maintenance_gate_v1" + }, + "generated_at": { + "type": "string" + }, + "program_status": { + "type": "object" + }, + "source_refs": { + "type": "array", + "items": { + "type": "string" + } + }, + "prior_owner_approved_execution_rehearsal": { + "type": "object" + }, + "owner_acceptance_truth": { + "type": "object" + }, + "owner_acceptance_packets": { + "type": "array", + "minItems": 5, + "maxItems": 5, + "items": { + "type": "object" + } + }, + "maintenance_windows": { + "type": "array", + "minItems": 5, + "maxItems": 5, + "items": { + "type": "object" + } + }, + "rollback_owner_checks": { + "type": "array", + "minItems": 5, + "maxItems": 5, + "items": { + "type": "object" + } + }, + "post_apply_verifier_gates": { + "type": "array", + "minItems": 5, + "maxItems": 5, + "items": { + "type": "object" + } + }, + "blocked_live_writes": { + "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 2dd850121..8d30ed177 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 @@ -662,7 +662,9 @@ Alert / Sentry / SigNoz / Gitea / Market Watch / Operator | `docs/evaluations/ai_agent_result_capture_writer_implementation_review_2026-06-13.json` + `GET /api/v1/agents/agent-result-capture-writer-implementation-review` | P2-122 result capture writer implementation review;承接 P2-121 write gate review,建立 5 個 writer implementation review、5 個 implementation gate、5 個 post-implementation verifier plan、6 個 blocked runtime change 與 5 個 operator action;target implementation gate 固定 `result_capture_writer_implementation_review`;owner approval、dual approval、dry-run hash、post-write verifier、writer apply、implementation applied、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`,已由 P2-123 承接 | | `docs/evaluations/ai_agent_result_capture_writer_dry_run_fixture_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-writer-dry-run-fixture` | P2-123 result capture writer dry-run fixture;承接 P2-122 writer implementation review,建立 5 個 writer dry-run fixture、5 個 receipt preview、5 個 idempotency replay check、5 個 rollback rehearsal、6 個 blocked runtime write 與 5 個 operator action;target dry-run 固定 `result_capture_writer_dry_run_fixture`;owner approval、dual approval、dry-run hash、writer apply、dry-run execution、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`,已由 P2-124 承接 | | `docs/evaluations/ai_agent_result_capture_writer_dry_run_readback_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-writer-dry-run-readback` | P2-124 result capture writer dry-run readback;承接 P2-123 writer dry-run fixture,建立 5 個 dry-run readback、5 個 receipt verifier、5 個 promotion gate、6 個 blocked promotion write 與 5 個 operator action;runtime authority 固定 `result_capture_writer_dry_run_readback_only_no_live_write`;owner approval、dual approval、dry-run hash、receipt verifier pass、writer apply、dry-run execution、receipt write、promotion apply、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`,已由 P2-125 承接 | -| `docs/evaluations/ai_agent_result_capture_owner_promotion_review_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-owner-promotion-review` | P2-125 result capture owner promotion review / execution gate;承接 P2-124 writer dry-run readback,建立 5 個 owner promotion packet、5 個 execution gate check、5 個 rollback owner review、6 個 blocked execution write 與 5 個 operator action;execution truth 固定 `result_capture_owner_promotion_review_only_no_live_write`;owner promotion approved、execution gate pass、rollback owner confirmed、post-write verifier ready、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`,下一步 P2-126 | +| `docs/evaluations/ai_agent_result_capture_owner_promotion_review_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-owner-promotion-review` | P2-125 result capture owner promotion review / execution gate;承接 P2-124 writer dry-run readback,建立 5 個 owner promotion packet、5 個 execution gate check、5 個 rollback owner review、6 個 blocked execution write 與 5 個 operator action;execution truth 固定 `result_capture_owner_promotion_review_only_no_live_write`;owner promotion approved、execution gate pass、rollback owner confirmed、post-write verifier ready、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`,已由 P2-126 承接 | +| `docs/evaluations/ai_agent_result_capture_owner_approved_execution_rehearsal_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-owner-approved-execution-rehearsal` | P2-126 owner-approved execution rehearsal / no-write apply gate;承接 P2-125 owner promotion review,建立 5 個 execution rehearsal、5 個 no-write apply check、5 個 post-write verifier rehearsal、5 個 rollback drill、6 個 blocked live apply 與 5 個 operator action;execution rehearsal truth 固定 `result_capture_owner_approved_execution_rehearsal_only_no_live_write`;owner approval record received、no-write apply executed、post-write verifier passed、rollback drill confirmed、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`,已由 P2-127 承接 | +| `docs/evaluations/ai_agent_result_capture_owner_acceptance_maintenance_gate_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-owner-acceptance-maintenance-gate` | P2-127 owner acceptance / maintenance window gate;承接 P2-126 owner-approved execution rehearsal,建立 5 個 owner acceptance packet、5 個 maintenance window、5 個 rollback owner check、5 個 post-apply verifier gate、6 個 blocked live write 與 5 個 operator action;runtime authority 固定 `result_capture_owner_acceptance_maintenance_gate_only_no_live_write`;owner accepted、maintenance window approved、rollback owner confirmed、post-apply verifier ready、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`,下一步 P2-128 | | `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 主動營運委派與版本生命週期契約 @@ -776,7 +778,9 @@ Repo / registry / release notes / K8s / host / observability / backup evidence 43. 建立 result capture writer implementation review。✅ P2-122 已完成並正式驗證;writer implementation review `5`、implementation gate `5`、post-implementation verifier plan `5`、blocked runtime change `6`、operator action `5`,approval-required review / gate / verifier `2 / 2 / 2`、blocked review / gate `1 / 1`、critical blocker `3`;owner approval、dual approval、dry-run hash、post-write verifier、writer apply、implementation applied、result capture write、learning write、PlayBook trust write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、canonical runtime target read、live query、production write 仍為 `0 / false`。已由 P2-123 承接。 44. 建立 result capture writer dry-run fixture。✅ P2-123 已完成並正式驗證;writer dry-run fixture `5`、receipt preview `5`、idempotency replay check `5`、rollback rehearsal `5`、blocked runtime write `6`、operator action `5`,approval-required fixture / receipt / replay / rollback `2 / 2 / 2 / 1`、blocked fixture / receipt / replay `1 / 1 / 1`、critical blocker `3`;owner approval、dual approval、dry-run hash、writer apply、dry-run execution、receipt write、result capture write、learning write、PlayBook trust write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、canonical runtime target read、live query、production write 仍為 `0 / false`。已由 P2-124 承接。 45. 建立 result capture writer dry-run readback。✅ P2-124 已完成並正式驗證;dry-run readback `5`、receipt verifier `5`、promotion gate `5`、blocked promotion write `6`、operator action `5`,approval-required readback / verifier / gate `2 / 2 / 2`、blocked readback / verifier / gate `1 / 1 / 1`、critical blocker `4`;owner approval、dual approval、dry-run hash、receipt verifier pass、writer apply、dry-run execution、receipt write、promotion apply、result capture write、learning write、PlayBook trust write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、canonical runtime target read、live query、production write 仍為 `0 / false`。已由 P2-125 承接。 -46. 建立 result capture owner promotion review / execution gate。✅ P2-125 已完成並正式驗證;owner promotion packet `5`、execution gate check `5`、rollback owner review `5`、blocked execution write `6`、operator action `5`,approval-required packet / gate / rollback `2 / 2 / 2`、blocked packet / gate / rollback `1 / 1 / 1`、critical blocker `5`、approval-blocked total `6 / 8`;owner promotion approved、execution gate pass、rollback owner confirmed、post-write verifier ready、writer apply、execution apply、receipt write、result capture write、learning write、PlayBook trust write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、canonical runtime target read、live query、production write 仍為 `0 / false`。下一步 P2-126。 +46. 建立 result capture owner promotion review / execution gate。✅ P2-125 已完成並正式驗證;owner promotion packet `5`、execution gate check `5`、rollback owner review `5`、blocked execution write `6`、operator action `5`,approval-required packet / gate / rollback `2 / 2 / 2`、blocked packet / gate / rollback `1 / 1 / 1`、critical blocker `5`、approval-blocked total `6 / 8`;owner promotion approved、execution gate pass、rollback owner confirmed、post-write verifier ready、writer apply、execution apply、receipt write、result capture write、learning write、PlayBook trust write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、canonical runtime target read、live query、production write 仍為 `0 / false`。已由 P2-126 承接。 +47. 建立 owner-approved execution rehearsal / no-write apply gate。✅ P2-126 已完成並正式驗證;execution rehearsal `5`、no-write apply check `5`、post-write verifier rehearsal `5`、rollback drill `5`、blocked live apply `6`、operator action `5`,approval-required rehearsal / check / verifier / rollback `2 / 2 / 2 / 2`、blocked rehearsal / check / verifier / rollback `1 / 1 / 1 / 1`、critical blocker `5`;owner approval record received、no-write apply executed、post-write verifier passed、rollback drill confirmed、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`。已由 P2-127 承接。 +48. 建立 owner acceptance / maintenance window gate。✅ P2-127 已本地完成,正式站待驗證;owner acceptance packet `5`、maintenance window `5`、rollback owner check `5`、post-apply verifier gate `5`、blocked live write `6`、operator action `5`,approval-required packet / window / rollback / verifier `2 / 2 / 2 / 2`、blocked packet / window / rollback / verifier `1 / 1 / 1 / 1`、critical blocker `5`;owner accepted、maintenance window approved、rollback owner confirmed、post-apply verifier ready、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`。下一步 P2-128。 #### 3.2.1d 2026-06-11 Agent 互動、學習與成長證據面 @@ -2087,6 +2091,26 @@ Phase 6 完成後 - 政策裁決:P2-125 只允許 owner promotion review、execution gate、rollback owner review、blocked execution write 與 operator handoff 可視化;不得把 review 解讀成 owner promotion approved、execution gate pass、writer apply、execution apply、receipt write、result capture write、learning write、PlayBook trust write、reviewer queue write、Gateway queue write、Telegram 實發、Bot API 呼叫、report receipt write 或 live writer 已啟用。 - 本波仍不讀 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-126。 +### 2026-06-14 02:42 (台北) — §3.2 / §5 — 正式驗證 P2-126 owner-approved execution rehearsal / no-write apply gate — 把批准後執行路徑收斂成 no-write rehearsal + +- 新增 `ai_agent_result_capture_owner_approved_execution_rehearsal_v1` schema / committed snapshot / loader / API / 測試,承接 P2-125 result capture owner promotion review / execution gate,定義 5 個 execution rehearsal、5 個 no-write apply check、5 個 post-write verifier rehearsal、5 個 rollback drill、6 個 blocked live apply 與 5 個 operator action。 +- Governance automation inventory 新增 P2-126 區塊,將 execution rehearsal、no-write apply gate、post-write verifier rehearsal、rollback drill、blocked live apply 與 operator action 全部以只讀方式呈現。 +- 正式 API 回 `schema_version=ai_agent_result_capture_owner_approved_execution_rehearsal_v1`、current `P2-126`、next `P2-127`、completion `100`;execution rehearsal `5`、no-write apply check `5`、post-write verifier rehearsal `5`、rollback drill `5`、blocked live apply `6`、operator action `5`、approval-required rehearsal / check / verifier / rollback `2 / 2 / 2 / 2`、blocked rehearsal / check / verifier / rollback `1 / 1 / 1 / 1`、critical blocker `5`。 +- 正式 API 0 / false 邊界:owner approval record received、no-write apply executed、post-write verifier passed、rollback drill confirmed、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`。 +- 正式 desktop / mobile smoke:`/zh-TW/governance?tab=automation-inventory` 可見 P2-126 區塊,`P2-126`、`owner-approved execution rehearsal`、`P2-127`、`no-write apply`、`post-write verifier`、`rollback drill`、`正式寫入 / 發送`、`writer 套用=0`、`execution 套用=0`、`Gateway 寫入=0` 可見,水平溢出 `0`、P2-126 內容危險入口 `0`、禁用內部協作 / raw field 片語命中 `0`。 +- 政策裁決:P2-126 只允許 owner-approved execution rehearsal、no-write apply check、post-write verifier rehearsal、rollback drill、blocked live apply 與 operator handoff 可視化;不得把 rehearsal 解讀成 owner approval record 已收、no-write apply 已執行、writer apply、execution apply、receipt write、result capture write、learning write、PlayBook trust write、reviewer queue write、Gateway queue write、Telegram 實發、Bot API 呼叫、report receipt write 或 live writer 已啟用。 +- 本波仍不讀 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-127 承接。 + +### 2026-06-14 03:20 (台北) — §3.2 / §5 — 本地完成 P2-127 owner acceptance / maintenance window gate — 把 no-write rehearsal 推進成 owner acceptance 可審核封包 + +- 新增 `ai_agent_result_capture_owner_acceptance_maintenance_gate_v1` schema / committed snapshot / loader / API / 測試,承接 P2-126 owner-approved execution rehearsal / no-write apply gate,定義 5 個 owner acceptance packet、5 個 maintenance window、5 個 rollback owner check、5 個 post-apply verifier gate、6 個 blocked live write 與 5 個 operator action。 +- Governance automation inventory 新增 P2-127 區塊,將 owner acceptance、maintenance window、rollback owner、post-apply verifier、blocked live write 與 operator action 全部以只讀方式呈現。 +- 本地 API/service regression:P2-127 + P2-126 `13 passed`;JSON parse、Python 3.11 py_compile、`pnpm --filter @awoooi/web typecheck` 與 `git diff --check` 通過。 +- 本地 snapshot 固定 `schema_version=ai_agent_result_capture_owner_acceptance_maintenance_gate_v1`、current `P2-127`、next `P2-128`、completion `100`;owner acceptance packet `5`、maintenance window `5`、rollback owner check `5`、post-apply verifier gate `5`、blocked live write `6`、operator action `5`、approval-required packet / window / rollback / verifier `2 / 2 / 2 / 2`、blocked packet / window / rollback / verifier `1 / 1 / 1 / 1`、critical blocker `5`。 +- 本地 0 / false 邊界:owner accepted、maintenance window approved、rollback owner confirmed、post-apply verifier ready、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`。 +- 政策裁決:P2-127 只允許 owner acceptance packet、maintenance window draft、rollback owner check、post-apply verifier gate、blocked live write 與 operator handoff 可視化;不得把本對話批准、口頭批准或 local package 解讀成 owner acceptance received、maintenance window approved、rollback owner confirmed、post-apply verifier ready、writer apply、execution apply、receipt write、result capture write、learning write、PlayBook trust write、reviewer queue write、Gateway queue write、Telegram 實發、Bot API 呼叫、report receipt write 或 live writer 已啟用。 +- 本波仍不讀 canonical runtime target、不做 live query、不寫 reviewer queue、不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 report receipt、不寫 result capture、不寫 learning、不更新 PlayBook trust、不寫 production target、不讀 secret、不執行 destructive action、不回傳內部協作內容;推送 Gitea main 後補正式 API / Browser readback,下一步 P2-128。 + ### 2026-06-14 00:56 (台北) — §3.2 / §5 — 正式驗證 P2-124 result capture writer dry-run readback — 把 fixture-only dry-run 讀回成 promotion readiness - 新增 `ai_agent_result_capture_writer_dry_run_readback_v1` schema / committed snapshot / loader / API / 測試,承接 P2-123 result capture writer dry-run fixture,定義 5 個 dry-run readback、5 個 receipt verifier、5 個 promotion gate、6 個 blocked promotion write 與 5 個 operator action。