From 755553e64f45045896f6dde5366a72fb43fbdf0d Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 14 Jun 2026 04:20:22 +0800 Subject: [PATCH] =?UTF-8?q?feat(governance):=20=E6=96=B0=E5=A2=9E=20releas?= =?UTF-8?q?e=20readiness=20readback?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/api/src/api/v1/agents.py | 34 ++ ...ner_approved_release_readiness_readback.py | 420 ++++++++++++++++ ...ner_approved_release_readiness_readback.py | 108 ++++ ...approved_release_readiness_readback_api.py | 46 ++ apps/web/messages/en.json | 32 ++ apps/web/messages/zh-TW.json | 32 ++ .../tabs/automation-inventory-tab.tsx | 183 ++++++- apps/web/src/lib/api-client.ts | 205 ++++++++ docs/LOGBOOK.md | 24 + ...AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md | 9 +- ...release_readiness_readback_2026-06-14.json | 460 ++++++++++++++++++ ..._release_readiness_readback_v1.schema.json | 100 ++++ ...-04-15-MASTER-ai-autonomous-flywheel-v2.md | 18 +- 13 files changed, 1663 insertions(+), 8 deletions(-) create mode 100644 apps/api/src/services/ai_agent_result_capture_owner_approved_release_readiness_readback.py create mode 100644 apps/api/tests/test_ai_agent_result_capture_owner_approved_release_readiness_readback.py create mode 100644 apps/api/tests/test_ai_agent_result_capture_owner_approved_release_readiness_readback_api.py create mode 100644 docs/evaluations/ai_agent_result_capture_owner_approved_release_readiness_readback_2026-06-14.json create mode 100644 docs/schemas/ai_agent_result_capture_owner_approved_release_readiness_readback_v1.schema.json diff --git a/apps/api/src/api/v1/agents.py b/apps/api/src/api/v1/agents.py index 69b32728..4d5a1362 100644 --- a/apps/api/src/api/v1/agents.py +++ b/apps/api/src/api/v1/agents.py @@ -136,6 +136,9 @@ from src.services.ai_agent_result_capture_owner_acceptance_readback_preflight_ho from src.services.ai_agent_result_capture_owner_approved_preflight_release_package import ( load_latest_ai_agent_result_capture_owner_approved_preflight_release_package, ) +from src.services.ai_agent_result_capture_owner_approved_release_readiness_readback import ( + load_latest_ai_agent_result_capture_owner_approved_release_readiness_readback, +) from src.services.ai_agent_result_capture_promotion_approval_gate import ( load_latest_ai_agent_result_capture_promotion_approval_gate, ) @@ -1983,6 +1986,37 @@ async def get_agent_result_capture_owner_approved_preflight_release_package() -> ) from exc +@router.get( + "/agent-result-capture-owner-approved-release-readiness-readback", + response_model=dict[str, Any], + summary="取得 AI Agent result capture owner-approved release readiness readback", + description=( + "讀取最新已提交的 P2-130 owner-approved release readiness readback;" + "此端點只回傳 release readiness readback、owner release readiness check、" + "live apply readiness gate、rollback readiness check、blocked readiness transition 與 operator handoff," + "不批准 owner release、不批准 maintenance window、不釋放 live apply、不套用 writer、不寫 receipt、" + "不寫 result capture、learning、PlayBook trust、reviewer queue、Gateway queue,不送 Telegram、" + "不呼叫 Bot API、不讀 secret。" + ), +) +async def get_agent_result_capture_owner_approved_release_readiness_readback() -> dict[str, Any]: + """Return the latest read-only owner-approved release readiness readback.""" + try: + payload = await asyncio.to_thread(load_latest_ai_agent_result_capture_owner_approved_release_readiness_readback) + 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_approved_release_readiness_readback_invalid", error=str(exc)) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="AI Agent result capture owner-approved release readiness readback 無效", + ) 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_approved_release_readiness_readback.py b/apps/api/src/services/ai_agent_result_capture_owner_approved_release_readiness_readback.py new file mode 100644 index 00000000..82a87222 --- /dev/null +++ b/apps/api/src/services/ai_agent_result_capture_owner_approved_release_readiness_readback.py @@ -0,0 +1,420 @@ +""" +AI Agent result capture owner-approved release readiness readback snapshot. + +Loads the latest committed P2-130 owner-approved release readiness readback. +This module validates committed evidence only; it never approves owner release, +approves maintenance windows, releases live apply, applies writers, writes +receipts, writes result captures, writes learning records, updates PlayBook +trust, writes reviewer / Gateway queues, sends Telegram messages, reads +secrets, or performs destructive operations. +""" + +from __future__ import annotations + +import json +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_approved_release_readiness_readback_*.json" +_SCHEMA_VERSION = "ai_agent_result_capture_owner_approved_release_readiness_readback_v1" +_RUNTIME_AUTHORITY = "result_capture_owner_approved_release_readiness_readback_only_no_live_write" + + +def load_latest_ai_agent_result_capture_owner_approved_release_readiness_readback( + evaluations_dir: Path | None = None, +) -> dict[str, Any]: + """Load the newest committed owner-approved release readiness readback.""" + 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-approved release readiness readback 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_release_readbacks(payload, label) + _require_owner_release_checks(payload, label) + _require_live_apply_readiness_gates(payload, label) + _require_rollback_readiness(payload, label) + _require_blocked_transitions(payload, label) + _require_actions(payload, label) + _require_display_redaction(payload, label) + _require_no_forbidden_display_terms(payload, label) + _require_rollup_consistency(payload, label) + return payload + + +def _require_schema(payload: dict[str, Any], label: str) -> None: + if payload.get("schema_version") != _SCHEMA_VERSION: + raise ValueError(f"{label}: expected schema_version={_SCHEMA_VERSION}") + status = payload.get("program_status") or {} + expected = { + "current_priority": "P2", + "current_task_id": "P2-130", + "next_task_id": "P2-131", + "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_preflight_release_package") or {} + expected = { + "schema_version": "ai_agent_result_capture_owner_approved_preflight_release_package_v1", + "owner_approved_release_package_count": 5, + "release_preflight_check_count": 5, + "live_apply_release_gate_count": 5, + "rollback_release_check_count": 5, + "blocked_release_transition_count": 6, + "operator_action_count": 5, + "approval_required_total": 8, + "blocked_total": 9, + "owner_release_approved_count": 0, + "maintenance_window_approved_count": 0, + "rollback_owner_confirmed_count": 0, + "post_release_verifier_ready_count": 0, + "live_apply_release_pass_count": 0, + "writer_apply_count": 0, + "execution_apply_count": 0, + "receipt_write_count": 0, + "result_capture_write_count": 0, + "learning_write_count": 0, + "playbook_trust_write_count": 0, + "reviewer_queue_write_count": 0, + "gateway_queue_write_count": 0, + "telegram_send_count": 0, + "bot_api_call_count": 0, + "report_receipt_write_count": 0, + } + mismatches = _mismatches(prior, expected) + if mismatches: + raise ValueError(f"{label}: prior_owner_approved_preflight_release_package mismatch: {mismatches}") + if not prior.get("readiness_note"): + raise ValueError(f"{label}: prior_owner_approved_preflight_release_package.readiness_note is required") + + +def _require_truth(payload: dict[str, Any], label: str) -> None: + truth = payload.get("release_readiness_truth") or {} + required_true = { + "p2_129_release_package_loaded", + "release_readiness_readback_ready", + "owner_release_review_required", + "maintenance_window_review_required", + "live_apply_readiness_hold_active", + "rollback_readiness_required", + "post_release_verifier_required", + "redaction_review_required", + "release_readiness_readback_only", + } + missing = sorted(field for field in required_true if truth.get(field) is not True) + if missing: + raise ValueError(f"{label}: release readiness readback flags must remain true: {missing}") + + required_false = { + "owner_release_approved", + "maintenance_window_approved", + "rollback_owner_confirmed", + "post_release_verifier_ready", + "release_readiness_passed", + "live_apply_release_passed", + "writer_apply_enabled", + "execution_apply_enabled", + "receipt_write_enabled", + "reviewer_queue_write_enabled", + "gateway_queue_write_enabled", + "telegram_send_enabled", + "bot_api_call_enabled", + "report_receipt_write_enabled", + "result_capture_write_enabled", + "learning_write_enabled", + "playbook_trust_write_enabled", + "production_write_enabled", + "secret_read_enabled", + "destructive_operation_enabled", + } + unsafe = sorted(field for field in required_false if truth.get(field) is not False) + if unsafe: + raise ValueError(f"{label}: live readiness/send/write flags must remain false: {unsafe}") + + zero_counts = { + "owner_release_approved_count", + "maintenance_window_approved_count", + "rollback_owner_confirmed_count", + "post_release_verifier_ready_count", + "release_readiness_pass_count", + "live_apply_release_pass_count", + "writer_apply_count", + "execution_apply_count", + "receipt_write_count", + "reviewer_queue_write_count", + "gateway_queue_write_count", + "telegram_send_count", + "bot_api_call_count", + "report_receipt_write_count", + "result_capture_write_count", + "learning_write_count", + "playbook_trust_write_count", + "production_write_count", + "secret_read_count", + "destructive_operation_count", + } + non_zero = sorted(field for field in zero_counts if truth.get(field) != 0) + if non_zero: + raise ValueError(f"{label}: release readiness live counters must remain zero: {non_zero}") + if not truth.get("truth_note"): + raise ValueError(f"{label}: release_readiness_truth.truth_note is required") + + +def _require_release_readbacks(payload: dict[str, Any], label: str) -> None: + items = payload.get("release_readiness_readbacks") or [] + required = { + "readback_release_readiness_result_capture_writer", + "readback_release_readiness_learning_writer", + "readback_release_readiness_playbook_trust_writer", + "readback_release_readiness_reviewer_queue_writer", + "readback_release_readiness_gateway_queue_writer", + } + ids = {item.get("readback_id") for item in items} + if ids != required: + raise ValueError(f"{label}: release readiness readbacks must match {sorted(required)}") + for item in items: + item_id = item.get("readback_id") + if item.get("readback_mode") != "owner_approved_release_readiness_readback": + raise ValueError(f"{label}: release readiness readback {item_id} mode is invalid") + if item.get("release_readiness_passed") is not False or item.get("owner_release_approved") is not False: + raise ValueError(f"{label}: release readiness readback {item_id} must stay unpassed and unapproved") + if item.get("status") not in {"ready_for_owner_readback", "approval_required", "blocked_by_policy"}: + raise ValueError(f"{label}: release readiness readback {item_id} status is invalid") + if not item.get("readiness_summary") or not _is_redacted_sha256(item.get("evidence_hash")): + raise ValueError(f"{label}: release readiness readback {item_id} must include summary and redacted evidence_hash") + + +def _require_owner_release_checks(payload: dict[str, Any], label: str) -> None: + items = payload.get("owner_release_readiness_checks") or [] + required = { + "owner_release_readiness_result_capture_writer", + "owner_release_readiness_learning_writer", + "owner_release_readiness_playbook_trust_writer", + "owner_release_readiness_reviewer_queue_writer", + "owner_release_readiness_gateway_queue_writer", + } + ids = {item.get("check_id") for item in items} + if ids != required: + raise ValueError(f"{label}: owner release readiness checks must match {sorted(required)}") + for item in items: + item_id = item.get("check_id") + if item.get("check_mode") != "owner_release_readiness_check": + raise ValueError(f"{label}: owner release readiness check {item_id} mode is invalid") + if item.get("owner_release_review_required") is not True or item.get("owner_release_approved") is not False: + raise ValueError(f"{label}: owner release readiness check {item_id} must remain required and unapproved") + if item.get("status") not in {"ready_for_owner_readback", "approval_required", "blocked_by_policy"}: + raise ValueError(f"{label}: owner release readiness check {item_id} status is invalid") + if not item.get("required_before_live_apply"): + raise ValueError(f"{label}: owner release readiness check {item_id} required_before_live_apply is required") + + +def _require_live_apply_readiness_gates(payload: dict[str, Any], label: str) -> None: + items = payload.get("live_apply_readiness_gates") or [] + required = { + "live_apply_readiness_result_capture", + "live_apply_readiness_learning", + "live_apply_readiness_playbook_trust", + "live_apply_readiness_reviewer_queue", + "live_apply_readiness_gateway_queue", + } + ids = {item.get("gate_id") for item in items} + if ids != required: + raise ValueError(f"{label}: live apply readiness gates must match {sorted(required)}") + for item in items: + item_id = item.get("gate_id") + if item.get("gate_mode") != "live_apply_readiness_gate": + raise ValueError(f"{label}: live apply readiness gate {item_id} mode is invalid") + if item.get("release_readiness_passed") is not False or item.get("live_apply_release_enabled") is not False: + raise ValueError(f"{label}: live apply readiness gate {item_id} must stay held and disabled") + if item.get("status") not in {"ready_for_owner_readback", "approval_required", "blocked_by_policy"}: + raise ValueError(f"{label}: live apply readiness gate {item_id} status is invalid") + if not item.get("hold_reason") or not item.get("release_condition"): + raise ValueError(f"{label}: live apply readiness gate {item_id} hold_reason and release_condition are required") + + +def _require_rollback_readiness(payload: dict[str, Any], label: str) -> None: + items = payload.get("rollback_readiness_checks") or [] + required = { + "rollback_readiness_result_capture", + "rollback_readiness_learning", + "rollback_readiness_playbook_trust", + "rollback_readiness_reviewer_queue", + "rollback_readiness_gateway_queue", + } + ids = {item.get("check_id") for item in items} + if ids != required: + raise ValueError(f"{label}: rollback readiness 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_readiness_passed") is not False: + raise ValueError(f"{label}: rollback readiness {item_id} must stay required and unpassed") + if item.get("status") not in {"ready_for_owner_readback", "approval_required", "blocked_by_policy"}: + raise ValueError(f"{label}: rollback readiness {item_id} status is invalid") + if not item.get("rollback_scope") or not item.get("hold_reason"): + raise ValueError(f"{label}: rollback readiness {item_id} scope and hold_reason are required") + + +def _require_blocked_transitions(payload: dict[str, Any], label: str) -> None: + items = payload.get("blocked_readiness_transitions") or [] + required = { + "blocked_writer_apply_readiness", + "blocked_execution_apply_readiness", + "blocked_receipt_write_readiness", + "blocked_result_capture_write_readiness", + "blocked_gateway_queue_write_readiness", + "blocked_telegram_send_readiness", + } + ids = {item.get("blocker_id") for item in items} + if ids != required: + raise ValueError(f"{label}: blocked readiness transitions 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_release_readiness_readbacks", + "verify_owner_release_readiness_checks", + "verify_live_apply_readiness_hold", + "verify_rollback_readiness", + "prepare_p2_131_owner_release_approval_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 {} + readbacks = payload.get("release_readiness_readbacks") or [] + checks = payload.get("owner_release_readiness_checks") or [] + gates = payload.get("live_apply_readiness_gates") or [] + rollbacks = payload.get("rollback_readiness_checks") or [] + blockers = payload.get("blocked_readiness_transitions") or [] + actions = payload.get("operator_actions") or [] + expected = { + "release_readiness_readback_count": len(readbacks), + "owner_release_readiness_check_count": len(checks), + "live_apply_readiness_gate_count": len(gates), + "rollback_readiness_check_count": len(rollbacks), + "blocked_readiness_transition_count": len(blockers), + "operator_action_count": len(actions), + "approval_required_readback_count": sum(1 for item in readbacks if item.get("status") == "approval_required"), + "blocked_readback_count": sum(1 for item in readbacks if item.get("status") == "blocked_by_policy"), + "approval_required_owner_release_check_count": sum(1 for item in checks if item.get("status") == "approval_required"), + "blocked_owner_release_check_count": sum(1 for item in checks if item.get("status") == "blocked_by_policy"), + "approval_required_readiness_gate_count": sum(1 for item in gates if item.get("status") == "approval_required"), + "blocked_readiness_gate_count": sum(1 for item in gates 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"), + "critical_blocker_count": sum(1 for item in blockers if item.get("severity") == "critical"), + "owner_release_approved_count": 0, + "maintenance_window_approved_count": 0, + "rollback_owner_confirmed_count": 0, + "post_release_verifier_ready_count": 0, + "release_readiness_pass_count": 0, + "live_apply_release_pass_count": 0, + "writer_apply_count": 0, + "execution_apply_count": 0, + "receipt_write_count": 0, + "reviewer_queue_write_count": 0, + "gateway_queue_write_count": 0, + "telegram_send_count": 0, + "bot_api_call_count": 0, + "report_receipt_write_count": 0, + "result_capture_write_count": 0, + "learning_write_count": 0, + "playbook_trust_write_count": 0, + "production_write_count": 0, + "secret_read_count": 0, + "destructive_operation_count": 0, + } + mismatches = _mismatches(rollups, expected) + if mismatches: + raise ValueError(f"{label}: 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_approved_release_readiness_readback.py b/apps/api/tests/test_ai_agent_result_capture_owner_approved_release_readiness_readback.py new file mode 100644 index 00000000..79274adc --- /dev/null +++ b/apps/api/tests/test_ai_agent_result_capture_owner_approved_release_readiness_readback.py @@ -0,0 +1,108 @@ +from __future__ import annotations + +import json +from pathlib import Path + +import pytest + +from src.services.ai_agent_result_capture_owner_approved_release_readiness_readback import ( + load_latest_ai_agent_result_capture_owner_approved_release_readiness_readback, +) + +REPO_ROOT = Path(__file__).resolve().parents[3] +FIXTURE = REPO_ROOT / "docs/evaluations/ai_agent_result_capture_owner_approved_release_readiness_readback_2026-06-14.json" + + +def test_load_latest_ai_agent_result_capture_owner_approved_release_readiness_readback_snapshot() -> None: + data = load_latest_ai_agent_result_capture_owner_approved_release_readiness_readback() + + assert data["schema_version"] == "ai_agent_result_capture_owner_approved_release_readiness_readback_v1" + assert data["program_status"]["current_task_id"] == "P2-130" + assert data["program_status"]["next_task_id"] == "P2-131" + assert data["program_status"]["runtime_authority"] == "result_capture_owner_approved_release_readiness_readback_only_no_live_write" + + rollups = data["rollups"] + assert rollups["release_readiness_readback_count"] == 5 + assert rollups["owner_release_readiness_check_count"] == 5 + assert rollups["live_apply_readiness_gate_count"] == 5 + assert rollups["rollback_readiness_check_count"] == 5 + assert rollups["blocked_readiness_transition_count"] == 6 + assert rollups["operator_action_count"] == 5 + assert rollups["critical_blocker_count"] == 5 + assert rollups["owner_release_approved_count"] == 0 + assert rollups["maintenance_window_approved_count"] == 0 + assert rollups["rollback_owner_confirmed_count"] == 0 + assert rollups["post_release_verifier_ready_count"] == 0 + assert rollups["release_readiness_pass_count"] == 0 + assert rollups["live_apply_release_pass_count"] == 0 + assert rollups["writer_apply_count"] == 0 + assert rollups["execution_apply_count"] == 0 + assert rollups["receipt_write_count"] == 0 + assert rollups["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["release_readiness_passed"] for item in data["release_readiness_readbacks"]} == {False} + assert {item["owner_release_approved"] for item in data["owner_release_readiness_checks"]} == {False} + assert {item["live_apply_release_enabled"] for item in data["live_apply_readiness_gates"]} == {False} + assert {item["rollback_readiness_passed"] for item in data["rollback_readiness_checks"]} == {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_approved_release_readiness_readback_2026-06-14.json" + target.write_text(json.dumps(source, ensure_ascii=False), encoding="utf-8") + return source + + +def test_result_capture_owner_approved_release_readiness_readback_rejects_readiness_passed(tmp_path: Path) -> None: + source = _copy_fixture(tmp_path) + source["release_readiness_readbacks"][0]["release_readiness_passed"] = True + target = tmp_path / "ai_agent_result_capture_owner_approved_release_readiness_readback_2026-06-14.json" + target.write_text(json.dumps(source, ensure_ascii=False), encoding="utf-8") + + with pytest.raises(ValueError, match="must stay unpassed and unapproved"): + load_latest_ai_agent_result_capture_owner_approved_release_readiness_readback(tmp_path) + + +def test_result_capture_owner_approved_release_readiness_readback_rejects_owner_release_approved(tmp_path: Path) -> None: + source = _copy_fixture(tmp_path) + source["owner_release_readiness_checks"][0]["owner_release_approved"] = True + target = tmp_path / "ai_agent_result_capture_owner_approved_release_readiness_readback_2026-06-14.json" + target.write_text(json.dumps(source, ensure_ascii=False), encoding="utf-8") + + with pytest.raises(ValueError, match="must remain required and unapproved"): + load_latest_ai_agent_result_capture_owner_approved_release_readiness_readback(tmp_path) + + +def test_result_capture_owner_approved_release_readiness_readback_rejects_live_apply_enabled(tmp_path: Path) -> None: + source = _copy_fixture(tmp_path) + source["live_apply_readiness_gates"][0]["live_apply_release_enabled"] = True + target = tmp_path / "ai_agent_result_capture_owner_approved_release_readiness_readback_2026-06-14.json" + target.write_text(json.dumps(source, ensure_ascii=False), encoding="utf-8") + + with pytest.raises(ValueError, match="must stay held and disabled"): + load_latest_ai_agent_result_capture_owner_approved_release_readiness_readback(tmp_path) + + +def test_result_capture_owner_approved_release_readiness_readback_rejects_rollup_drift(tmp_path: Path) -> None: + source = _copy_fixture(tmp_path) + source["rollups"]["release_readiness_readback_count"] = 4 + target = tmp_path / "ai_agent_result_capture_owner_approved_release_readiness_readback_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_approved_release_readiness_readback(tmp_path) + + +def test_result_capture_owner_approved_release_readiness_readback_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_approved_release_readiness_readback_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_approved_release_readiness_readback(tmp_path) diff --git a/apps/api/tests/test_ai_agent_result_capture_owner_approved_release_readiness_readback_api.py b/apps/api/tests/test_ai_agent_result_capture_owner_approved_release_readiness_readback_api.py new file mode 100644 index 00000000..5e44d4c7 --- /dev/null +++ b/apps/api/tests/test_ai_agent_result_capture_owner_approved_release_readiness_readback_api.py @@ -0,0 +1,46 @@ +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_approved_release_readiness_readback_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-approved-release-readiness-readback") + + assert response.status_code == 200 + data = response.json() + assert data["schema_version"] == "ai_agent_result_capture_owner_approved_release_readiness_readback_v1" + assert data["program_status"]["current_task_id"] == "P2-130" + assert data["program_status"]["next_task_id"] == "P2-131" + + rollups = data["rollups"] + assert rollups["release_readiness_readback_count"] == 5 + assert rollups["owner_release_readiness_check_count"] == 5 + assert rollups["live_apply_readiness_gate_count"] == 5 + assert rollups["rollback_readiness_check_count"] == 5 + assert rollups["blocked_readiness_transition_count"] == 6 + assert rollups["operator_action_count"] == 5 + assert rollups["owner_release_approved_count"] == 0 + assert rollups["maintenance_window_approved_count"] == 0 + assert rollups["rollback_owner_confirmed_count"] == 0 + assert rollups["post_release_verifier_ready_count"] == 0 + assert rollups["release_readiness_pass_count"] == 0 + assert rollups["live_apply_release_pass_count"] == 0 + assert rollups["writer_apply_count"] == 0 + assert rollups["execution_apply_count"] == 0 + assert rollups["receipt_write_count"] == 0 + assert rollups["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["release_readiness_passed"] for item in data["release_readiness_readbacks"]} == {False} + assert {item["owner_release_approved"] for item in data["owner_release_readiness_checks"]} == {False} + assert {item["live_apply_release_enabled"] for item in data["live_apply_readiness_gates"]} == {False} diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index 0b80e618..d567abb6 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -5944,6 +5944,38 @@ "rollbackPassed": "rollback release passed={value}" } }, + "resultCaptureOwnerApprovedReleaseReadinessReadback": { + "title": "P2-130 owner-approved release readiness readback", + "source": "產生 {generated};目前 {current};下一步 {next}", + "priorTitle": "前一關 release package", + "truthTitle": "release readiness 真相", + "metrics": { + "overall": "完成度", + "readbacks": "Readiness readbacks", + "ownerChecks": "Owner checks", + "readinessGates": "Live-apply readiness gates", + "rollbackChecks": "Rollback readiness checks", + "blockers": "已阻擋 readiness", + "actions": "操作選項", + "approvalRequired": "需批准", + "blocked": "阻擋", + "liveWrites": "正式寫入 / 發送" + }, + "flags": { + "p2Loaded": "已載入 P2-129={value}", + "ownerReleaseReviewRequired": "owner release review required={value}", + "liveApplyReadinessHoldActive": "live apply readiness hold active={value}" + }, + "labels": { + "ownerReleaseApproved": "owner release approved={value}", + "releaseReadinessPassed": "release readiness passed={value}", + "gatewayWrites": "Gateway 寫入={value}", + "readinessPassed": "readiness passed={value}", + "liveApplyReleaseEnabled": "live apply release enabled={value}", + "rollbackRequired": "需要 rollback owner={value}", + "rollbackPassed": "rollback readiness passed={value}" + } + }, "resultCaptureOwnerAcceptanceReadbackPreflightHold": { "title": "P2-128 owner acceptance readback / live-apply preflight hold", "source": "產生 {generated};目前 {current};下一步 {next}", diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index 0b80e618..d567abb6 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -5944,6 +5944,38 @@ "rollbackPassed": "rollback release passed={value}" } }, + "resultCaptureOwnerApprovedReleaseReadinessReadback": { + "title": "P2-130 owner-approved release readiness readback", + "source": "產生 {generated};目前 {current};下一步 {next}", + "priorTitle": "前一關 release package", + "truthTitle": "release readiness 真相", + "metrics": { + "overall": "完成度", + "readbacks": "Readiness readbacks", + "ownerChecks": "Owner checks", + "readinessGates": "Live-apply readiness gates", + "rollbackChecks": "Rollback readiness checks", + "blockers": "已阻擋 readiness", + "actions": "操作選項", + "approvalRequired": "需批准", + "blocked": "阻擋", + "liveWrites": "正式寫入 / 發送" + }, + "flags": { + "p2Loaded": "已載入 P2-129={value}", + "ownerReleaseReviewRequired": "owner release review required={value}", + "liveApplyReadinessHoldActive": "live apply readiness hold active={value}" + }, + "labels": { + "ownerReleaseApproved": "owner release approved={value}", + "releaseReadinessPassed": "release readiness passed={value}", + "gatewayWrites": "Gateway 寫入={value}", + "readinessPassed": "readiness passed={value}", + "liveApplyReleaseEnabled": "live apply release enabled={value}", + "rollbackRequired": "需要 rollback owner={value}", + "rollbackPassed": "rollback readiness passed={value}" + } + }, "resultCaptureOwnerAcceptanceReadbackPreflightHold": { "title": "P2-128 owner acceptance readback / live-apply preflight hold", "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 f71e9718..d1797f9d 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 @@ -77,6 +77,7 @@ import { type AiAgentResultCaptureOwnerAcceptanceMaintenanceGateSnapshot, type AiAgentResultCaptureOwnerAcceptanceReadbackPreflightHoldSnapshot, type AiAgentResultCaptureOwnerApprovedPreflightReleasePackageSnapshot, + type AiAgentResultCaptureOwnerApprovedReleaseReadinessReadbackSnapshot, type AiAgentResultCaptureWriterImplementationReviewSnapshot, type AiAgentOwnerApprovedFixturePromotionGateSnapshot, type AiAgentRuntimeWorkerShadowGateSnapshot, @@ -477,6 +478,7 @@ export function AutomationInventoryTab() { const [resultCaptureOwnerAcceptanceMaintenanceGate, setResultCaptureOwnerAcceptanceMaintenanceGate] = useState(null) const [resultCaptureOwnerAcceptanceReadbackPreflightHold, setResultCaptureOwnerAcceptanceReadbackPreflightHold] = useState(null) const [resultCaptureOwnerApprovedPreflightReleasePackage, setResultCaptureOwnerApprovedPreflightReleasePackage] = useState(null) + const [resultCaptureOwnerApprovedReleaseReadinessReadback, setResultCaptureOwnerApprovedReleaseReadinessReadback] = useState(null) const [reportTruthActionabilityReview, setReportTruthActionabilityReview] = useState(null) const [ownerDryRunPackage, setOwnerDryRunPackage] = useState(null) const [hostStatefulInventory, setHostStatefulInventory] = useState(null) @@ -543,6 +545,7 @@ export function AutomationInventoryTab() { apiClient.getAiAgentResultCaptureOwnerAcceptanceMaintenanceGate(), apiClient.getAiAgentResultCaptureOwnerAcceptanceReadbackPreflightHold(), apiClient.getAiAgentResultCaptureOwnerApprovedPreflightReleasePackage(), + apiClient.getAiAgentResultCaptureOwnerApprovedReleaseReadinessReadback(), apiClient.getAiAgentReportTruthActionabilityReview(), apiClient.getAiAgentOwnerApprovedFixtureDryRun(), apiClient.getAiAgentHostStatefulVersionInventory(), @@ -608,6 +611,7 @@ export function AutomationInventoryTab() { resultCaptureOwnerAcceptanceMaintenanceGateResult, resultCaptureOwnerAcceptanceReadbackPreflightHoldResult, resultCaptureOwnerApprovedPreflightReleasePackageResult, + resultCaptureOwnerApprovedReleaseReadinessReadbackResult, reportTruthActionabilityReviewResult, ownerDryRunPackageResult, hostStatefulInventoryResult, @@ -670,6 +674,7 @@ export function AutomationInventoryTab() { setResultCaptureOwnerAcceptanceMaintenanceGate(resultCaptureOwnerAcceptanceMaintenanceGateResult.status === 'fulfilled' ? resultCaptureOwnerAcceptanceMaintenanceGateResult.value : null) setResultCaptureOwnerAcceptanceReadbackPreflightHold(resultCaptureOwnerAcceptanceReadbackPreflightHoldResult.status === 'fulfilled' ? resultCaptureOwnerAcceptanceReadbackPreflightHoldResult.value : null) setResultCaptureOwnerApprovedPreflightReleasePackage(resultCaptureOwnerApprovedPreflightReleasePackageResult.status === 'fulfilled' ? resultCaptureOwnerApprovedPreflightReleasePackageResult.value : null) + setResultCaptureOwnerApprovedReleaseReadinessReadback(resultCaptureOwnerApprovedReleaseReadinessReadbackResult.status === 'fulfilled' ? resultCaptureOwnerApprovedReleaseReadinessReadbackResult.value : null) setReportTruthActionabilityReview(reportTruthActionabilityReviewResult.status === 'fulfilled' ? reportTruthActionabilityReviewResult.value : null) setOwnerDryRunPackage(ownerDryRunPackageResult.status === 'fulfilled' ? ownerDryRunPackageResult.value : null) setHostStatefulInventory(hostStatefulInventoryResult.status === 'fulfilled' ? hostStatefulInventoryResult.value : null) @@ -730,6 +735,7 @@ export function AutomationInventoryTab() { resultCaptureOwnerAcceptanceMaintenanceGateResult, resultCaptureOwnerAcceptanceReadbackPreflightHoldResult, resultCaptureOwnerApprovedPreflightReleasePackageResult, + resultCaptureOwnerApprovedReleaseReadinessReadbackResult, reportTruthActionabilityReviewResult, ownerDryRunPackageResult, hostStatefulInventoryResult, @@ -1972,7 +1978,7 @@ export function AutomationInventoryTab() { ) } - if (error || !snapshot || !backlog || !backupTargets || !backupReadiness || !backupPolicy || !offsiteEscrow || !giteaHealth || !observabilityMatrix || !providerRouteMatrix || !deploymentLayout || !proactiveOperations || !interactionLearningProof || !liveReadModelGate || !redisDryRunGate || !learningWritebackPackage || !telegramReceiptPackage || !ownerApprovedLearningDryRun || !runtimeWriteGateReview || !postWriteVerifierPackage || !runtimeVerifierEvidenceReview || !reportAutomationReview || !reportStatusBoard || !reportRuntimeReadiness || !reportRuntimeDryRun || !reportRuntimeFixtureReadback || !runtimeWorkerShadowGate || !operationPermissionModel || !candidateOperationDryRunEvidence || !taskResultAuditTrail || !matchedPlaybookLearningGap || !criticReviewerResultCapture || !ownerApprovedResultCaptureDryRun || !ownerApprovedResultCaptureReadback || !runtimeReadbackApprovalPackage || !runtimeReadbackImplementationReview || !reportLiveDeliveryApprovalPackage || !runtimeReadbackFixtureApproval || !runtimeReadbackPromotionGate || !ownerApprovedFixturePromotionGate || !canonicalRuntimeReadbackOwnerAcceptance || !failureReceiptNoSendReplay || !reviewerQueueNoWriteReadback || !resultCaptureNoWriteReadback || !resultCapturePromotionApprovalGate || !ownerApprovedResultCapturePromotionDryRun || !resultCaptureWriteGateReview || !resultCaptureWriterImplementationReview || !resultCaptureWriterDryRunFixture || !resultCaptureWriterDryRunReadback || !resultCaptureOwnerPromotionReview || !resultCaptureOwnerApprovedExecutionRehearsal || !resultCaptureOwnerAcceptanceMaintenanceGate || !resultCaptureOwnerAcceptanceReadbackPreflightHold || !resultCaptureOwnerApprovedPreflightReleasePackage || !reportTruthActionabilityReview || !ownerDryRunPackage || !hostStatefulInventory || !serviceHealthGapMatrix || !serviceHealthNotificationPolicy) { + if (error || !snapshot || !backlog || !backupTargets || !backupReadiness || !backupPolicy || !offsiteEscrow || !giteaHealth || !observabilityMatrix || !providerRouteMatrix || !deploymentLayout || !proactiveOperations || !interactionLearningProof || !liveReadModelGate || !redisDryRunGate || !learningWritebackPackage || !telegramReceiptPackage || !ownerApprovedLearningDryRun || !runtimeWriteGateReview || !postWriteVerifierPackage || !runtimeVerifierEvidenceReview || !reportAutomationReview || !reportStatusBoard || !reportRuntimeReadiness || !reportRuntimeDryRun || !reportRuntimeFixtureReadback || !runtimeWorkerShadowGate || !operationPermissionModel || !candidateOperationDryRunEvidence || !taskResultAuditTrail || !matchedPlaybookLearningGap || !criticReviewerResultCapture || !ownerApprovedResultCaptureDryRun || !ownerApprovedResultCaptureReadback || !runtimeReadbackApprovalPackage || !runtimeReadbackImplementationReview || !reportLiveDeliveryApprovalPackage || !runtimeReadbackFixtureApproval || !runtimeReadbackPromotionGate || !ownerApprovedFixturePromotionGate || !canonicalRuntimeReadbackOwnerAcceptance || !failureReceiptNoSendReplay || !reviewerQueueNoWriteReadback || !resultCaptureNoWriteReadback || !resultCapturePromotionApprovalGate || !ownerApprovedResultCapturePromotionDryRun || !resultCaptureWriteGateReview || !resultCaptureWriterImplementationReview || !resultCaptureWriterDryRunFixture || !resultCaptureWriterDryRunReadback || !resultCaptureOwnerPromotionReview || !resultCaptureOwnerApprovedExecutionRehearsal || !resultCaptureOwnerAcceptanceMaintenanceGate || !resultCaptureOwnerAcceptanceReadbackPreflightHold || !resultCaptureOwnerApprovedPreflightReleasePackage || !resultCaptureOwnerApprovedReleaseReadinessReadback || !reportTruthActionabilityReview || !ownerDryRunPackage || !hostStatefulInventory || !serviceHealthGapMatrix || !serviceHealthNotificationPolicy) { return (
@@ -2982,6 +2988,40 @@ export function AutomationInventoryTab() { + resultCaptureOwnerApprovedPreflightReleasePackage.rollups.playbook_trust_write_count + resultCaptureOwnerApprovedPreflightReleasePackage.rollups.production_write_count ) + const resultCaptureReleaseReadinessOverall = resultCaptureOwnerApprovedReleaseReadinessReadback.program_status.overall_completion_percent + const resultCaptureReleaseReadinessReadbacks = resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.release_readiness_readback_count + const resultCaptureReleaseReadinessOwnerChecks = resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.owner_release_readiness_check_count + const resultCaptureReleaseReadinessGates = resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.live_apply_readiness_gate_count + const resultCaptureReleaseReadinessRollbacks = resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.rollback_readiness_check_count + const resultCaptureReleaseReadinessBlockedTransitions = resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.blocked_readiness_transition_count + const resultCaptureReleaseReadinessActions = resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.operator_action_count + const resultCaptureReleaseReadinessApprovalRequired = ( + resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.approval_required_readback_count + + resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.approval_required_owner_release_check_count + + resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.approval_required_readiness_gate_count + + resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.approval_required_rollback_count + ) + const resultCaptureReleaseReadinessBlocked = ( + resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.blocked_readback_count + + resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.blocked_owner_release_check_count + + resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.blocked_readiness_gate_count + + resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.blocked_rollback_count + + resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.critical_blocker_count + ) + const resultCaptureReleaseReadinessLiveWrites = ( + resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.writer_apply_count + + resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.execution_apply_count + + resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.receipt_write_count + + resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.reviewer_queue_write_count + + resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.gateway_queue_write_count + + resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.telegram_send_count + + resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.bot_api_call_count + + resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.report_receipt_write_count + + resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.result_capture_write_count + + resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.learning_write_count + + resultCaptureOwnerApprovedReleaseReadinessReadback.rollups.playbook_trust_write_count + + resultCaptureOwnerApprovedReleaseReadinessReadback.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 @@ -7531,6 +7571,147 @@ export function AutomationInventoryTab() {
+
+
+
+ + + {t('resultCaptureOwnerApprovedReleaseReadinessReadback.title')} + +
+ +
+ +
+ } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> +
+ +
+
+ {t('resultCaptureOwnerApprovedReleaseReadinessReadback.priorTitle')} + + {resultCaptureOwnerApprovedReleaseReadinessReadback.prior_owner_approved_preflight_release_package.readiness_note} + +
+ + + +
+
+ +
+ {t('resultCaptureOwnerApprovedReleaseReadinessReadback.truthTitle')} + + {resultCaptureOwnerApprovedReleaseReadinessReadback.release_readiness_truth.truth_note} + +
+ + + + + + +
+
+
+ +
+ {resultCaptureOwnerApprovedReleaseReadinessReadback.release_readiness_readbacks.slice(0, 5).map(readback => ( +
+
+ + {readback.display_name} + + +
+ + {readback.source_release_package} → {readback.readiness_summary} + +
+ + + +
+
+ ))} +
+ +
+ {resultCaptureOwnerApprovedReleaseReadinessReadback.owner_release_readiness_checks.slice(0, 5).map(check => ( +
+
+ + {check.display_name} + + +
+ + {check.required_before_live_apply} + +
+ + + +
+
+ ))} +
+ +
+ {resultCaptureOwnerApprovedReleaseReadinessReadback.live_apply_readiness_gates.slice(0, 5).map(gate => ( +
+
+ + {gate.display_name} + + +
+ + {gate.hold_reason} {gate.release_condition} + + +
+ ))} +
+ +
+ {resultCaptureOwnerApprovedReleaseReadinessReadback.rollback_readiness_checks.slice(0, 5).map(rollback => ( +
+
+ + {rollback.display_name} + + +
+ + {rollback.rollback_scope} {rollback.hold_reason} + +
+ + + +
+
+ ))} +
+
+
diff --git a/apps/web/src/lib/api-client.ts b/apps/web/src/lib/api-client.ts index 20e93c3f..9166e65e 100644 --- a/apps/web/src/lib/api-client.ts +++ b/apps/web/src/lib/api-client.ts @@ -545,6 +545,11 @@ export const apiClient = { return handleResponse(res) }, + async getAiAgentResultCaptureOwnerApprovedReleaseReadinessReadback() { + const res = await fetch(`${API_BASE_URL}/agents/agent-result-capture-owner-approved-release-readiness-readback`) + return handleResponse(res) + }, + async getAiAgentOwnerApprovedFixtureDryRun() { const res = await fetch(`${API_BASE_URL}/agents/agent-owner-approved-fixture-dry-run`) return handleResponse(res) @@ -7335,6 +7340,206 @@ export interface AiAgentResultCaptureOwnerApprovedPreflightReleasePackageSnapsho } } +export interface AiAgentResultCaptureOwnerApprovedReleaseReadinessReadbackSnapshot { + schema_version: 'ai_agent_result_capture_owner_approved_release_readiness_readback_v1' + generated_at: string + program_status: { + overall_completion_percent: number + current_priority: 'P0' | 'P1' | 'P2' | 'P3' + current_task_id: 'P2-130' + next_task_id: 'P2-131' + read_only_mode: true + runtime_authority: 'result_capture_owner_approved_release_readiness_readback_only_no_live_write' + status_note: string + } + source_refs: string[] + prior_owner_approved_preflight_release_package: { + schema_version: string + owner_approved_release_package_count: number + release_preflight_check_count: number + live_apply_release_gate_count: number + rollback_release_check_count: number + blocked_release_transition_count: number + operator_action_count: number + approval_required_total: number + blocked_total: number + owner_release_approved_count: number + maintenance_window_approved_count: number + rollback_owner_confirmed_count: number + post_release_verifier_ready_count: number + live_apply_release_pass_count: number + writer_apply_count: number + execution_apply_count: number + receipt_write_count: number + result_capture_write_count: number + learning_write_count: number + playbook_trust_write_count: number + reviewer_queue_write_count: number + gateway_queue_write_count: number + telegram_send_count: number + bot_api_call_count: number + report_receipt_write_count: number + readiness_note: string + } + release_readiness_truth: { + p2_129_release_package_loaded: boolean + release_readiness_readback_ready: boolean + owner_release_review_required: boolean + maintenance_window_review_required: boolean + live_apply_readiness_hold_active: boolean + rollback_readiness_required: boolean + post_release_verifier_required: boolean + redaction_review_required: boolean + release_readiness_readback_only: boolean + owner_release_approved: boolean + maintenance_window_approved: boolean + rollback_owner_confirmed: boolean + post_release_verifier_ready: boolean + release_readiness_passed: boolean + live_apply_release_passed: boolean + writer_apply_enabled: boolean + execution_apply_enabled: boolean + receipt_write_enabled: boolean + reviewer_queue_write_enabled: boolean + gateway_queue_write_enabled: boolean + telegram_send_enabled: boolean + bot_api_call_enabled: boolean + report_receipt_write_enabled: boolean + result_capture_write_enabled: boolean + learning_write_enabled: boolean + playbook_trust_write_enabled: boolean + production_write_enabled: boolean + secret_read_enabled: boolean + destructive_operation_enabled: boolean + owner_release_approved_count: number + maintenance_window_approved_count: number + rollback_owner_confirmed_count: number + post_release_verifier_ready_count: number + release_readiness_pass_count: number + live_apply_release_pass_count: number + writer_apply_count: number + execution_apply_count: number + receipt_write_count: number + reviewer_queue_write_count: number + gateway_queue_write_count: number + telegram_send_count: number + bot_api_call_count: number + report_receipt_write_count: number + result_capture_write_count: number + learning_write_count: number + playbook_trust_write_count: number + production_write_count: number + secret_read_count: number + destructive_operation_count: number + truth_note: string + } + release_readiness_readbacks: Array<{ + readback_id: string + display_name: string + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + source_release_package: string + status: 'ready_for_owner_readback' | 'approval_required' | 'blocked_by_policy' + readback_mode: 'owner_approved_release_readiness_readback' + release_readiness_passed: false + owner_release_approved: false + readiness_summary: string + evidence_hash: string + }> + owner_release_readiness_checks: Array<{ + check_id: string + display_name: string + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + status: 'ready_for_owner_readback' | 'approval_required' | 'blocked_by_policy' + check_mode: 'owner_release_readiness_check' + owner_release_review_required: true + owner_release_approved: false + required_before_live_apply: string + }> + live_apply_readiness_gates: Array<{ + gate_id: string + display_name: string + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + status: 'ready_for_owner_readback' | 'approval_required' | 'blocked_by_policy' + gate_mode: 'live_apply_readiness_gate' + release_readiness_passed: false + live_apply_release_enabled: false + hold_reason: string + release_condition: string + }> + rollback_readiness_checks: Array<{ + check_id: string + display_name: string + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + status: 'ready_for_owner_readback' | 'approval_required' | 'blocked_by_policy' + rollback_owner_required: true + rollback_readiness_passed: false + rollback_scope: string + hold_reason: string + }> + blocked_readiness_transitions: 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 + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + status: 'ready_for_operator_review' | 'approval_required' + operator_instruction: string + runtime_write_allowed: false + }> + display_redaction_contract: { + redaction_required: true + raw_prompt_display_allowed: false + private_reasoning_display_allowed: false + secret_value_display_allowed: false + raw_runtime_payload_display_allowed: false + internal_collaboration_content_display_allowed: false + frontend_display_policy: string + } + rollups: { + release_readiness_readback_count: number + owner_release_readiness_check_count: number + live_apply_readiness_gate_count: number + rollback_readiness_check_count: number + blocked_readiness_transition_count: number + operator_action_count: number + approval_required_readback_count: number + blocked_readback_count: number + approval_required_owner_release_check_count: number + blocked_owner_release_check_count: number + approval_required_readiness_gate_count: number + blocked_readiness_gate_count: number + approval_required_rollback_count: number + blocked_rollback_count: number + critical_blocker_count: number + owner_release_approved_count: number + maintenance_window_approved_count: number + rollback_owner_confirmed_count: number + post_release_verifier_ready_count: number + release_readiness_pass_count: number + live_apply_release_pass_count: number + writer_apply_count: number + execution_apply_count: number + receipt_write_count: number + reviewer_queue_write_count: number + gateway_queue_write_count: number + telegram_send_count: number + bot_api_call_count: number + report_receipt_write_count: number + result_capture_write_count: number + learning_write_count: number + playbook_trust_write_count: number + production_write_count: number + secret_read_count: number + destructive_operation_count: number + } +} + export interface AiAgentOwnerApprovedFixtureDryRunSnapshot { schema_version: 'ai_agent_owner_approved_fixture_dry_run_v1' generated_at: string diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index fc0a00aa..fea9fb86 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -1,3 +1,27 @@ +## 2026-06-14|P2-130 Owner-approved release readiness readback 本地完成 + +**背景**:P2-129 已把 owner-approved release package、release preflight check、live-apply release gate、rollback release check 與 blocked release transition 正式驗證完成;但 release package 仍不得被誤讀成 owner release approved、maintenance window approved 或 live apply passed。P2-130 因此只建立 owner-approved release readiness readback,把 package 讀回成 readiness 狀態與 hold 證據,不批准 owner release、不開維護窗口、不釋放 live apply、不套用 writer、不寫 receipt、不寫 result capture / learning / PlayBook trust / reviewer queue / Gateway queue,也不送 Telegram 或呼叫 Bot API。 + +**完成內容**: +- 新增 `ai_agent_result_capture_owner_approved_release_readiness_readback_v1` schema、committed snapshot、loader 與 API endpoint `GET /api/v1/agents/agent-result-capture-owner-approved-release-readiness-readback`。 +- P2-130 snapshot 固定 5 個 release readiness readback、5 個 owner release readiness check、5 個 live-apply readiness gate、5 個 rollback readiness check、6 個 blocked readiness transition 與 5 個 operator action。 +- Governance automation inventory 頁新增 P2-130 區塊,顯示 P2-130 進度 `100%`、readiness readback `5`、owner check `5`、live-apply readiness gate `5`、rollback readiness check `5`、blocked readiness `6`、operator action `5`、需批准 `8`、阻擋 `9`、正式寫入 / 發送 `0`。 +- Release readiness truth 固定為 `result_capture_owner_approved_release_readiness_readback_only_no_live_write`;owner release approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、release readiness passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API、report receipt、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive operation 仍全部維持 `0 / false`。 + +**本地驗證**: +- JSON parse:P2-130 schema / snapshot、`zh-TW.json`、`en.json` 通過。 +- Python 編譯:P2-130 loader 與 `agents.py` 通過。 +- API/service pytest:P2-130 + P2-129 regression `14 passed`。 +- Web typecheck:`pnpm --filter @awoooi/web typecheck` 通過。 +- Web production build:`NEXT_PUBLIC_API_URL=https://awoooi.wooo.work pnpm --filter @awoooi/web build` 通過;僅既有 Sentry setup / deprecation warning,governance First Load JS `433 kB`。 +- 本段仍是本地完成;正式 API readback、正式站 desktop / mobile Browser smoke 與 deploy marker 需在推送 Gitea main 並完成 CD 後補齊。 + +**安全邊界**: +- P2-130 仍是 owner-approved release readiness readback;不接受口頭批准、不把 readiness 解讀成 owner release approved、不批准維護窗口、不確認 rollback owner、不啟用 post-release verifier live read、不釋放 live apply、不套用 writer、不執行正式寫入、不寫 receipt、不寫 result capture、不寫 learning、不更新 PlayBook trust、不寫 reviewer queue、不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 report receipt、不讀 canonical runtime target、不做 live query、不寫 production target、不讀 secret、不執行 destructive action。 + +**下一步**: +- `P2-131`:owner release approval gate;只有 P2-130 正式驗證後才可把 release readiness readback、owner release readiness check、live-apply readiness gate、rollback readiness check 與 blocked readiness transition 轉成 owner release approval gate,仍不得直接開啟 result capture writer、learning writer、PlayBook trust writer、reviewer queue write、Gateway queue write、Telegram send、Bot API call 或 production write。 + ## 2026-06-14|P2-129 Owner-approved preflight release package 完成與正式驗證 **背景**:P2-128 已把 owner acceptance readback、preflight hold、live-apply hold gate、rollback preflight 與 blocked apply transition 固定成正式驗證完成的只讀 hold;但真正往 live apply release 前進前,仍需要把這些 hold 整理成 owner-approved preflight release package,讓下一關可以讀回 release readiness,而不是直接放行 writer。P2-129 因此只建立 release package,不接受 owner 口頭批准、不釋放 live apply、不套用 writer、不寫 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 fe6b4540..00de19a8 100644 --- a/docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md +++ b/docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md @@ -12,7 +12,7 @@ | Nemotron 實際整合應用 | 30% | 完整回放前仍被關卡擋下 | `blocked_needs_evidence`,下一關是 `refresh_source_evidence_then_5_record_smoke_only` | | 工具 / 服務 / 套件 AI 自動化 | 92% | P0 已完成;P1 服務 / runtime / 監控 / provider / service health / 備份 / DR / 套件與供應鏈只讀基線已完成;P1-007 失敗限定通知合約與前端 redaction 合約已完成;下一主線是 P2-004 依賴 / 供應鏈漂移監控 | 狀態分類、盤點 schema、權限矩陣、靜態盤點種子、只讀 API、UI 骨架、驗證、自動化待辦 schema / 快照 / API / 分組 UI、Backup / DR 目標盤點、準備度矩陣、備份通知政策、Backup / DR 證據 UI、復原演練批准包模板、異地 / escrow 準備度狀態、任務批准邊界、確定性進度彙總、Python 套件 / 供應鏈只讀基線、JS pnpm/npm 只讀基線、Docker build surface 只讀基線、CVE / license / drift 嚴重度政策、定期依賴漂移與外部資料來源檢查設計、依賴升級批准包模板、runtime_surface_inventory_v1 schema / snapshot / API / UI、gitea_workflow_runner_health_v1 schema / snapshot / API / UI、observability_contract_matrix_v1 schema / snapshot / API / UI、ai_provider_route_matrix_v1 schema / snapshot / API / UI、service_health_gap_matrix_v1 schema / snapshot / API / UI、service health evidence cards UI、service_health_failure_notification_policy_v1 schema / snapshot / API / UI 已完成 | | OpenClaw / Hermes / NemoTron 佈建布局 | 45% | P1-401 / P1-402 已完成;仍是只讀 layout 與治理頁顯示,不是 runtime deploy | `ai_agent_deployment_layout_v1` schema、`ai_agent_deployment_layout_2026-06-11.json`、`GET /api/v1/agents/agent-deployment-layout`、治理頁自動化盤點 UI、`AI_AGENT_DEPLOYMENT_LAYOUT_2026-06-11.md` | -| OpenClaw / Hermes / NemoTron 主動溝通、學習與成長證據 | 100% | P2-401A 到 P2-129 已完成只讀證據面、runtime / report / result-capture gates、no-write readback、promotion review、writer implementation review、writer dry-run fixture、writer dry-run readback、owner promotion execution gate、owner-approved execution rehearsal、owner acceptance / maintenance window gate、owner acceptance readback / preflight hold 與 owner-approved preflight release package;P2-129 已完成正式驗證,deploy marker `7e5b4793`,固定 5 個 owner-approved release package、5 個 release preflight check、5 個 live-apply release gate、5 個 rollback release check、6 個 blocked release transition 與 5 個 operator action,desktop / mobile smoke 確認禁用內部協作片語 `0`、水平溢位 `0`、高風險控制 `0`。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_approved_preflight_release_package_v1`、`GET /api/v1/agents/agent-result-capture-owner-approved-preflight-release-package`、`ai_agent_result_capture_owner_acceptance_readback_preflight_hold_v1`、`GET /api/v1/agents/agent-result-capture-owner-acceptance-readback-preflight-hold`、正式站 `/zh-TW/governance?tab=automation-inventory` desktop / mobile smoke、`ai_agent_result_capture_owner_acceptance_maintenance_gate_v1`、`GET /api/v1/agents/agent-result-capture-owner-acceptance-maintenance-gate`、`ai_agent_result_capture_owner_approved_execution_rehearsal_v1`、`GET /api/v1/agents/agent-result-capture-owner-approved-execution-rehearsal`、`ai_agent_result_capture_owner_promotion_review_v1`、`ai_agent_result_capture_writer_dry_run_readback_v1`、`ai_agent_result_capture_writer_dry_run_fixture_v1`、`ai_agent_result_capture_writer_implementation_review_v1`、`ai_agent_result_capture_write_gate_review_v1`、`ai_agent_interaction_learning_proof_v1`、MASTER §3.2.1b / §3.2.1d / §3.4.3 | +| OpenClaw / Hermes / NemoTron 主動溝通、學習與成長證據 | 100% | P2-401A 到 P2-130 已完成只讀證據面、runtime / report / result-capture gates、no-write readback、promotion review、writer implementation review、writer dry-run fixture、writer dry-run readback、owner promotion execution gate、owner-approved execution rehearsal、owner acceptance / maintenance window gate、owner acceptance readback / preflight hold、owner-approved preflight release package 與 owner-approved release readiness readback;P2-130 本地完成,固定 5 個 release readiness readback、5 個 owner release readiness check、5 個 live-apply readiness gate、5 個 rollback readiness check、6 個 blocked readiness transition 與 5 個 operator action,正式站待驗證。runtime worker、DB migration、production Redis consumer group、canonical runtime readback、live query、runtime score、result capture write、Telegram 實發、delivery receipt E2E、live report delivery、reviewer queue write、Gateway queue write、AI analysis runtime、中低風險 auto worker、KM / LOGBOOK / audit DB / timeline / PlayBook trust 寫入、SDK / 付費服務仍未開 gate | `ai_agent_result_capture_owner_approved_release_readiness_readback_v1`、`GET /api/v1/agents/agent-result-capture-owner-approved-release-readiness-readback`、`ai_agent_result_capture_owner_approved_preflight_release_package_v1`、`GET /api/v1/agents/agent-result-capture-owner-approved-preflight-release-package`、`ai_agent_result_capture_owner_acceptance_readback_preflight_hold_v1`、`GET /api/v1/agents/agent-result-capture-owner-acceptance-readback-preflight-hold`、正式站 `/zh-TW/governance?tab=automation-inventory` desktop / mobile smoke、`ai_agent_result_capture_owner_acceptance_maintenance_gate_v1`、`GET /api/v1/agents/agent-result-capture-owner-acceptance-maintenance-gate`、`ai_agent_result_capture_owner_approved_execution_rehearsal_v1`、`GET /api/v1/agents/agent-result-capture-owner-approved-execution-rehearsal`、`ai_agent_result_capture_owner_promotion_review_v1`、`ai_agent_result_capture_writer_dry_run_readback_v1`、`ai_agent_result_capture_writer_dry_run_fixture_v1`、`ai_agent_result_capture_writer_implementation_review_v1`、`ai_agent_result_capture_write_gate_review_v1`、`ai_agent_interaction_learning_proof_v1`、MASTER §3.2.1b / §3.2.1d / §3.4.3 | | AI Agent 主動營運委派與版本生命週期 | 100% | P2-402A / P2-402B / P2-402C / P2-402D / P2-402E / P2-402F / P2-402G 已完成;已建立 repo-only 版本新鮮度快照、工具採用批准包、Telegram action-required digest policy、Gitea PR 草案 lane、host / K3s / stateful 版本只讀盤點、API 與 governance UI。定期排程、外部版本查詢、工具安裝、CI 變更、套件升級、主機更新、container pull、實際 PR creation、auto merge、Telegram 實發、SSH、kubectl、重啟仍未開 gate | `ai_agent_proactive_operations_contract_v1`、`ai_agent_version_freshness_snapshot_v1`、`ai_agent_tool_adoption_approval_package_v1`、`ai_agent_telegram_action_required_digest_policy_v1`、`ai_agent_gitea_pr_draft_lane_v1`、`ai_agent_host_stateful_version_inventory_v1`、`GET /api/v1/agents/agent-proactive-operations-contract`、`GET /api/v1/agents/agent-version-freshness-snapshot`、`GET /api/v1/agents/agent-tool-adoption-approval-package`、`GET /api/v1/agents/agent-telegram-action-required-digest-policy`、`GET /api/v1/agents/agent-gitea-pr-draft-lane`、`GET /api/v1/agents/agent-host-stateful-version-inventory`、`/zh-TW/governance?tab=automation-inventory`、MASTER §3.2.1c | | 本工作清單與分析報告 | 100% | 已完成 | 本 MD 文件 | @@ -20,9 +20,9 @@ AI Agent 自動化工作包目前完成度:**99.3%**。本工作清單文件 三 Agent 佈建布局目前完成度:**45%**。第一波已完成只讀 schema / snapshot / API / 測試 / 報告,第二波已接入治理頁自動化盤點 UI;正式 runtime 佈署、Telegram E2E 發送與 AgentSession 工作流仍需逐項 gate。 -三 Agent 主動溝通、學習與成長證據目前完成度:**100%**。P2-403A 到 P2-129 已把互動證據、報表治理、runtime readback、reviewer / result capture / writer gates、no-write readback、promotion review、writer implementation review、writer dry-run fixture、writer dry-run readback、owner promotion execution gate、owner-approved execution rehearsal、owner acceptance / maintenance window gate、owner acceptance readback / preflight hold 與 owner-approved preflight release package 全部固定成可驗證證據。P2-129 已正式驗證,deploy marker `7e5b4793`,固定 5 個 owner-approved release package、5 個 release preflight check、5 個 live-apply release gate、5 個 rollback release check、6 個 blocked release transition 與 5 個 operator action;正式 API readback 與 desktop / mobile smoke 已完成。目前 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-130`。 +三 Agent 主動溝通、學習與成長證據目前完成度:**100%**。P2-403A 到 P2-130 已把互動證據、報表治理、runtime readback、reviewer / result capture / writer gates、no-write readback、promotion review、writer implementation review、writer dry-run fixture、writer dry-run readback、owner promotion execution gate、owner-approved execution rehearsal、owner acceptance / maintenance window gate、owner acceptance readback / preflight hold、owner-approved preflight release package 與 owner-approved release readiness readback 全部固定成可驗證證據。P2-130 已本地驗證,固定 5 個 release readiness readback、5 個 owner release readiness check、5 個 live-apply readiness gate、5 個 rollback readiness check、6 個 blocked readiness transition 與 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-131`。 -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-129` 已補互動、學習證據面、live read model gate、Redis dry-run gate、learning writeback approval package、Telegram receipt approval package、owner-approved learning dry-run preview、runtime write gate review、post-write verifier package、runtime verifier evidence review、報表真相、TG 戰情室收斂、日週月報、Agent 工作量、圖表化報告、風險自動化政策、報表 runtime 啟動前閘門、no-write dry-run 證據包、fixture/readback/verifier dry-run 證據包、shadow/no-write execution gate、操作類別權限模型、13 類候選操作 dry-run 證據、任務結果稽核軌跡、matched PlayBook 學習缺口、critic / reviewer result capture、owner-approved result capture dry-run / readback、result capture writer dry-run fixture、writer dry-run readback、owner promotion execution gate、owner-approved execution rehearsal、owner acceptance / maintenance window gate、owner acceptance readback / preflight hold 與 owner-approved preflight release package。下一步是 `P2-130`;外部 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-130` 已補互動、學習證據面、live read model gate、Redis dry-run gate、learning writeback approval package、Telegram receipt approval package、owner-approved learning dry-run preview、runtime write gate review、post-write verifier package、runtime verifier evidence review、報表真相、TG 戰情室收斂、日週月報、Agent 工作量、圖表化報告、風險自動化政策、報表 runtime 啟動前閘門、no-write dry-run 證據包、fixture/readback/verifier dry-run 證據包、shadow/no-write execution gate、操作類別權限模型、13 類候選操作 dry-run 證據、任務結果稽核軌跡、matched PlayBook 學習缺口、critic / reviewer result capture、owner-approved result capture dry-run / readback、result capture writer dry-run fixture、writer dry-run readback、owner promotion execution gate、owner-approved execution rehearsal、owner acceptance / maintenance window gate、owner acceptance readback / preflight hold、owner-approved preflight release package 與 owner-approved release readiness readback。下一步是 `P2-131`;外部 registry / package source / host probe / SSH / kubectl / 工具安裝 / CI 變更 / 實際 PR creation / Telegram 實發與 learning write 仍需 gate。 完成度計算模型: @@ -1001,7 +1001,8 @@ UI: | 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;正式站 deploy marker `7b034b58` 已驗證;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`;desktop / mobile smoke 禁用內部協作片語 `0`、水平溢位 `0`、P2-127 區塊危險入口 `0` | 已由 P2-128 承接;不接受口頭批准、不開維護窗口、不套用 writer、不寫 receipt、不寫 result capture、不寫 learning、不更新 PlayBook trust、不送 Telegram、不寫 production | | P2-128 | 完成 | 100 | OpenClaw + Hermes + NemoTron | owner acceptance readback / live-apply preflight hold | `ai_agent_result_capture_owner_acceptance_readback_preflight_hold_v1` / schema / snapshot / 只讀 API / governance UI;正式站 deploy marker `0a3f1533` 已驗證;5 個 owner acceptance readback、5 個 preflight hold check、5 個 live-apply hold gate、5 個 rollback preflight check、6 個 blocked apply transition、5 個 operator action;runtime authority 固定 `result_capture_owner_acceptance_readback_preflight_hold_only_no_live_write`;owner acceptance received / maintenance window approved / rollback owner confirmed / post-apply verifier ready / live apply preflight passed / writer apply / execution apply / receipt write / result capture / learning / PlayBook trust / reviewer queue / Gateway / Telegram / Bot API / report receipt / production write 全為 `0`;desktop / mobile smoke 禁用內部協作片語 `0`、水平溢位 `0`、P2-128 區塊危險入口 `0` | 已由 P2-129 承接;不釋放 live apply、不套用 writer、不寫 receipt、不寫 result capture、不寫 learning、不更新 PlayBook trust、不送 Telegram、不寫 production | -| P2-129 | 完成 | 100 | OpenClaw + Hermes + NemoTron | owner-approved preflight release package | `ai_agent_result_capture_owner_approved_preflight_release_package_v1` / schema / snapshot / 只讀 API / governance UI;正式站 deploy marker `7e5b4793` 已驗證;5 個 owner-approved release package、5 個 release preflight check、5 個 live-apply release gate、5 個 rollback release check、6 個 blocked release transition、5 個 operator action;runtime authority 固定 `result_capture_owner_approved_preflight_release_package_only_no_live_write`;owner release approved / maintenance window approved / rollback owner confirmed / post-release verifier ready / live apply release passed / writer apply / execution apply / receipt write / result capture / learning / PlayBook trust / reviewer queue / Gateway / Telegram / Bot API / report receipt / production write 全為 `0`;desktop / mobile smoke 禁用內部協作片語 `0`、水平溢位 `0`、P2-129 區塊危險入口 `0` | 下一步 P2-130;不把 release package 視為正式批准、不釋放 live apply、不套用 writer、不寫 receipt、不寫 result capture、不寫 learning、不更新 PlayBook trust、不送 Telegram、不寫 production | +| P2-129 | 完成 | 100 | OpenClaw + Hermes + NemoTron | owner-approved preflight release package | `ai_agent_result_capture_owner_approved_preflight_release_package_v1` / schema / snapshot / 只讀 API / governance UI;正式站 deploy marker `7e5b4793` 已驗證;5 個 owner-approved release package、5 個 release preflight check、5 個 live-apply release gate、5 個 rollback release check、6 個 blocked release transition、5 個 operator action;runtime authority 固定 `result_capture_owner_approved_preflight_release_package_only_no_live_write`;owner release approved / maintenance window approved / rollback owner confirmed / post-release verifier ready / live apply release passed / writer apply / execution apply / receipt write / result capture / learning / PlayBook trust / reviewer queue / Gateway / Telegram / Bot API / report receipt / production write 全為 `0`;desktop / mobile smoke 禁用內部協作片語 `0`、水平溢位 `0`、P2-129 區塊危險入口 `0` | 已由 P2-130 承接;不把 release package 視為正式批准、不釋放 live apply、不套用 writer、不寫 receipt、不寫 result capture、不寫 learning、不更新 PlayBook trust、不送 Telegram、不寫 production | +| P2-130 | 本地完成,正式站待驗證 | 100 | OpenClaw + Hermes + NemoTron | owner-approved release readiness readback | `ai_agent_result_capture_owner_approved_release_readiness_readback_v1` / schema / snapshot / 只讀 API / governance UI;5 個 release readiness readback、5 個 owner release readiness check、5 個 live-apply readiness gate、5 個 rollback readiness check、6 個 blocked readiness transition、5 個 operator action;runtime authority 固定 `result_capture_owner_approved_release_readiness_readback_only_no_live_write`;owner release approved / maintenance window approved / rollback owner confirmed / post-release verifier ready / release readiness passed / live apply release passed / writer apply / execution apply / receipt write / result capture / learning / PlayBook trust / reviewer queue / Gateway / Telegram / Bot API / report receipt / production write 全為 `0` | 下一步 P2-131;不把 readiness 視為正式批准、不釋放 live apply、不套用 writer、不寫 receipt、不寫 result capture、不寫 learning、不更新 PlayBook trust、不送 Telegram、不寫 production | ### P3 - 候選 Agent 擴展 diff --git a/docs/evaluations/ai_agent_result_capture_owner_approved_release_readiness_readback_2026-06-14.json b/docs/evaluations/ai_agent_result_capture_owner_approved_release_readiness_readback_2026-06-14.json new file mode 100644 index 00000000..7a74b340 --- /dev/null +++ b/docs/evaluations/ai_agent_result_capture_owner_approved_release_readiness_readback_2026-06-14.json @@ -0,0 +1,460 @@ +{ + "schema_version": "ai_agent_result_capture_owner_approved_release_readiness_readback_v1", + "generated_at": "2026-06-14T06:18:00+08:00", + "program_status": { + "overall_completion_percent": 100, + "current_priority": "P2", + "current_task_id": "P2-130", + "next_task_id": "P2-131", + "read_only_mode": true, + "runtime_authority": "result_capture_owner_approved_release_readiness_readback_only_no_live_write", + "status_note": "P2-130 只把 P2-129 owner-approved preflight release package 轉成 release readiness readback;不得視為 owner release approved,不得批准 maintenance window,不得釋放 live apply、套用 writer、寫 receipt、寫 result capture、寫 learning、寫 queue、送 Telegram 或寫入 production。" + }, + "source_refs": [ + "docs/evaluations/ai_agent_result_capture_owner_approved_preflight_release_package_2026-06-14.json", + "docs/evaluations/ai_agent_result_capture_owner_acceptance_readback_preflight_hold_2026-06-14.json", + "docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md#50-建立-owner-approved-preflight-release-package" + ], + "prior_owner_approved_preflight_release_package": { + "schema_version": "ai_agent_result_capture_owner_approved_preflight_release_package_v1", + "owner_approved_release_package_count": 5, + "release_preflight_check_count": 5, + "live_apply_release_gate_count": 5, + "rollback_release_check_count": 5, + "blocked_release_transition_count": 6, + "operator_action_count": 5, + "approval_required_total": 8, + "blocked_total": 9, + "owner_release_approved_count": 0, + "maintenance_window_approved_count": 0, + "rollback_owner_confirmed_count": 0, + "post_release_verifier_ready_count": 0, + "live_apply_release_pass_count": 0, + "writer_apply_count": 0, + "execution_apply_count": 0, + "receipt_write_count": 0, + "result_capture_write_count": 0, + "learning_write_count": 0, + "playbook_trust_write_count": 0, + "reviewer_queue_write_count": 0, + "gateway_queue_write_count": 0, + "telegram_send_count": 0, + "bot_api_call_count": 0, + "report_receipt_write_count": 0, + "readiness_note": "P2-129 已把 owner-approved release package、release preflight check、live-apply release gate、rollback release check 與 blocked release transition 固定為只讀 release package;P2-130 只讀回 readiness,不放行 live apply。" + }, + "release_readiness_truth": { + "p2_129_release_package_loaded": true, + "release_readiness_readback_ready": true, + "owner_release_review_required": true, + "maintenance_window_review_required": true, + "live_apply_readiness_hold_active": true, + "rollback_readiness_required": true, + "post_release_verifier_required": true, + "redaction_review_required": true, + "release_readiness_readback_only": true, + "owner_release_approved": false, + "maintenance_window_approved": false, + "rollback_owner_confirmed": false, + "post_release_verifier_ready": false, + "release_readiness_passed": false, + "live_apply_release_passed": false, + "writer_apply_enabled": false, + "execution_apply_enabled": false, + "receipt_write_enabled": false, + "reviewer_queue_write_enabled": false, + "gateway_queue_write_enabled": false, + "telegram_send_enabled": false, + "bot_api_call_enabled": false, + "report_receipt_write_enabled": false, + "result_capture_write_enabled": false, + "learning_write_enabled": false, + "playbook_trust_write_enabled": false, + "production_write_enabled": false, + "secret_read_enabled": false, + "destructive_operation_enabled": false, + "owner_release_approved_count": 0, + "maintenance_window_approved_count": 0, + "rollback_owner_confirmed_count": 0, + "post_release_verifier_ready_count": 0, + "release_readiness_pass_count": 0, + "live_apply_release_pass_count": 0, + "writer_apply_count": 0, + "execution_apply_count": 0, + "receipt_write_count": 0, + "reviewer_queue_write_count": 0, + "gateway_queue_write_count": 0, + "telegram_send_count": 0, + "bot_api_call_count": 0, + "report_receipt_write_count": 0, + "result_capture_write_count": 0, + "learning_write_count": 0, + "playbook_trust_write_count": 0, + "production_write_count": 0, + "secret_read_count": 0, + "destructive_operation_count": 0, + "truth_note": "P2-130 只建立 release readiness readback;readiness 可見不代表 owner release approved、maintenance window approved、post-release verifier ready 或 live apply 可執行。" + }, + "release_readiness_readbacks": [ + { + "readback_id": "readback_release_readiness_result_capture_writer", + "display_name": "Result capture release readiness readback", + "owner_agent": "openclaw", + "source_release_package": "release_package_result_capture_writer", + "status": "ready_for_owner_readback", + "readback_mode": "owner_approved_release_readiness_readback", + "release_readiness_passed": false, + "owner_release_approved": false, + "readiness_summary": "讀回 result capture writer release package、rollback owner 與 post-release verifier requirement;不產生 live apply readiness pass。", + "evidence_hash": "sha256:1111111111111111111111111111111111111111111111111111111111111111" + }, + { + "readback_id": "readback_release_readiness_learning_writer", + "display_name": "Learning release readiness readback", + "owner_agent": "hermes", + "source_release_package": "release_package_learning_writer", + "status": "approval_required", + "readback_mode": "owner_approved_release_readiness_readback", + "release_readiness_passed": false, + "owner_release_approved": false, + "readiness_summary": "讀回 KM owner、learning write scope、stale guard 與 rollback owner;不寫 KM 或 learning metadata。", + "evidence_hash": "sha256:2222222222222222222222222222222222222222222222222222222222222222" + }, + { + "readback_id": "readback_release_readiness_playbook_trust_writer", + "display_name": "PlayBook trust release readiness readback", + "owner_agent": "nemotron", + "source_release_package": "release_package_playbook_trust_writer", + "status": "blocked_by_policy", + "readback_mode": "owner_approved_release_readiness_readback", + "release_readiness_passed": false, + "owner_release_approved": false, + "readiness_summary": "讀回 trust delta、負向強化 reviewer 與 OpenClaw 仲裁 requirement;未完成仲裁前不得 release。", + "evidence_hash": "sha256:3333333333333333333333333333333333333333333333333333333333333333" + }, + { + "readback_id": "readback_release_readiness_reviewer_queue_writer", + "display_name": "Reviewer queue release readiness readback", + "owner_agent": "openclaw", + "source_release_package": "release_package_reviewer_queue_writer", + "status": "approval_required", + "readback_mode": "owner_approved_release_readiness_readback", + "release_readiness_passed": false, + "owner_release_approved": false, + "readiness_summary": "讀回 reviewer queue owner、SLA owner、dedupe key owner 與 rollback owner;不寫 reviewer queue。", + "evidence_hash": "sha256:4444444444444444444444444444444444444444444444444444444444444444" + }, + { + "readback_id": "readback_release_readiness_gateway_queue_writer", + "display_name": "Gateway queue release readiness readback", + "owner_agent": "nemotron", + "source_release_package": "release_package_gateway_queue_writer", + "status": "ready_for_owner_readback", + "readback_mode": "owner_approved_release_readiness_readback", + "release_readiness_passed": false, + "owner_release_approved": false, + "readiness_summary": "讀回 SRE route lock、Telegram receipt owner、redaction owner 與 Gateway rollback owner;不寫 Gateway queue、不送 Telegram。", + "evidence_hash": "sha256:5555555555555555555555555555555555555555555555555555555555555555" + } + ], + "owner_release_readiness_checks": [ + { + "check_id": "owner_release_readiness_result_capture_writer", + "display_name": "Result capture owner release readiness check", + "owner_agent": "openclaw", + "status": "ready_for_owner_readback", + "check_mode": "owner_release_readiness_check", + "owner_release_review_required": true, + "owner_release_approved": false, + "required_before_live_apply": "owner release approval、maintenance window、rollback owner、post-release verifier readiness。" + }, + { + "check_id": "owner_release_readiness_learning_writer", + "display_name": "Learning owner release readiness check", + "owner_agent": "hermes", + "status": "approval_required", + "check_mode": "owner_release_readiness_check", + "owner_release_review_required": true, + "owner_release_approved": false, + "required_before_live_apply": "KM owner release approval、stale guard pass、rollback owner、post-release verifier readiness。" + }, + { + "check_id": "owner_release_readiness_playbook_trust_writer", + "display_name": "PlayBook trust owner release readiness check", + "owner_agent": "nemotron", + "status": "blocked_by_policy", + "check_mode": "owner_release_readiness_check", + "owner_release_review_required": true, + "owner_release_approved": false, + "required_before_live_apply": "OpenClaw 仲裁、負向強化審查、trust delta reviewer 與 owner release approval。" + }, + { + "check_id": "owner_release_readiness_reviewer_queue_writer", + "display_name": "Reviewer queue owner release readiness check", + "owner_agent": "openclaw", + "status": "approval_required", + "check_mode": "owner_release_readiness_check", + "owner_release_review_required": true, + "owner_release_approved": false, + "required_before_live_apply": "reviewer SLA owner、dedupe key owner、queue rollback owner 與 post-release verifier readiness。" + }, + { + "check_id": "owner_release_readiness_gateway_queue_writer", + "display_name": "Gateway queue owner release readiness check", + "owner_agent": "nemotron", + "status": "ready_for_owner_readback", + "check_mode": "owner_release_readiness_check", + "owner_release_review_required": true, + "owner_release_approved": false, + "required_before_live_apply": "SRE route lock、Telegram receipt owner、redaction owner 與 Gateway rollback owner。" + } + ], + "live_apply_readiness_gates": [ + { + "gate_id": "live_apply_readiness_result_capture", + "display_name": "Result capture live apply readiness gate", + "owner_agent": "openclaw", + "status": "ready_for_owner_readback", + "gate_mode": "live_apply_readiness_gate", + "release_readiness_passed": false, + "live_apply_release_enabled": false, + "hold_reason": "release readiness 已讀回,但 owner release approval 與 post-release verifier 仍未 ready。", + "release_condition": "P2-131 之後另行建立 owner release approval gate。" + }, + { + "gate_id": "live_apply_readiness_learning", + "display_name": "Learning live apply readiness gate", + "owner_agent": "hermes", + "status": "approval_required", + "gate_mode": "live_apply_readiness_gate", + "release_readiness_passed": false, + "live_apply_release_enabled": false, + "hold_reason": "learning write 仍缺 KM owner release approval 與 stale guard rollback。", + "release_condition": "需 owner release approval gate 與 post-release verifier readiness。" + }, + { + "gate_id": "live_apply_readiness_playbook_trust", + "display_name": "PlayBook trust live apply readiness gate", + "owner_agent": "nemotron", + "status": "blocked_by_policy", + "gate_mode": "live_apply_readiness_gate", + "release_readiness_passed": false, + "live_apply_release_enabled": false, + "hold_reason": "trust delta 與負向強化審查仍未完成。", + "release_condition": "需 OpenClaw 仲裁與 owner release approval gate。" + }, + { + "gate_id": "live_apply_readiness_reviewer_queue", + "display_name": "Reviewer queue live apply readiness gate", + "owner_agent": "openclaw", + "status": "approval_required", + "gate_mode": "live_apply_readiness_gate", + "release_readiness_passed": false, + "live_apply_release_enabled": false, + "hold_reason": "reviewer queue 寫入仍缺 SLA owner 與 rollback owner release approval。", + "release_condition": "需 reviewer queue owner release approval gate。" + }, + { + "gate_id": "live_apply_readiness_gateway_queue", + "display_name": "Gateway queue live apply readiness gate", + "owner_agent": "nemotron", + "status": "ready_for_owner_readback", + "gate_mode": "live_apply_readiness_gate", + "release_readiness_passed": false, + "live_apply_release_enabled": false, + "hold_reason": "Gateway queue 與 Telegram send 仍缺 SRE route lock 與 receipt owner release approval。", + "release_condition": "需 Gateway queue / Telegram receipt owner release approval gate。" + } + ], + "rollback_readiness_checks": [ + { + "check_id": "rollback_readiness_result_capture", + "display_name": "Result capture rollback readiness check", + "owner_agent": "openclaw", + "status": "ready_for_owner_readback", + "rollback_owner_required": true, + "rollback_readiness_passed": false, + "rollback_scope": "撤回 result capture release readiness、receipt hash 與 audit trail append。", + "hold_reason": "rollback owner 尚未 confirmed,不得 release live apply。" + }, + { + "check_id": "rollback_readiness_learning", + "display_name": "Learning rollback readiness check", + "owner_agent": "hermes", + "status": "approval_required", + "rollback_owner_required": true, + "rollback_readiness_passed": false, + "rollback_scope": "撤回 learning release readiness、KM write preview 與 stale guard marker。", + "hold_reason": "KM rollback owner 尚未 confirmed。" + }, + { + "check_id": "rollback_readiness_playbook_trust", + "display_name": "PlayBook trust rollback readiness check", + "owner_agent": "nemotron", + "status": "blocked_by_policy", + "rollback_owner_required": true, + "rollback_readiness_passed": false, + "rollback_scope": "撤回 trust delta release readiness 與 negative reinforcement draft。", + "hold_reason": "trust rollback owner 與負向強化 reviewer 尚未 ready。" + }, + { + "check_id": "rollback_readiness_reviewer_queue", + "display_name": "Reviewer queue rollback readiness check", + "owner_agent": "openclaw", + "status": "approval_required", + "rollback_owner_required": true, + "rollback_readiness_passed": false, + "rollback_scope": "撤回 reviewer queue release readiness、dedupe key 與 SLA route handoff。", + "hold_reason": "reviewer queue rollback owner 尚未 confirmed。" + }, + { + "check_id": "rollback_readiness_gateway_queue", + "display_name": "Gateway queue rollback readiness check", + "owner_agent": "nemotron", + "status": "ready_for_owner_readback", + "rollback_owner_required": true, + "rollback_readiness_passed": false, + "rollback_scope": "撤回 Gateway queue release readiness、route lock 與 Telegram receipt draft。", + "hold_reason": "Gateway rollback owner 尚未 confirmed,不得送 Telegram。" + } + ], + "blocked_readiness_transitions": [ + { + "blocker_id": "blocked_writer_apply_readiness", + "display_name": "Writer apply readiness blocked", + "severity": "critical", + "status": "blocked_by_policy", + "blocked_action": "writer_apply_after_release_readiness", + "blocked_until": "owner release approved + release readiness passed", + "evidence_hash": "sha256:a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1" + }, + { + "blocker_id": "blocked_execution_apply_readiness", + "display_name": "Execution apply readiness blocked", + "severity": "critical", + "status": "blocked_by_policy", + "blocked_action": "execution_apply_after_release_readiness", + "blocked_until": "maintenance window approved + post-release verifier ready", + "evidence_hash": "sha256:a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2" + }, + { + "blocker_id": "blocked_receipt_write_readiness", + "display_name": "Receipt write readiness blocked", + "severity": "critical", + "status": "approval_required", + "blocked_action": "receipt_write_after_release_readiness", + "blocked_until": "post-release verifier ready + rollback owner confirmed", + "evidence_hash": "sha256:a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3" + }, + { + "blocker_id": "blocked_result_capture_write_readiness", + "display_name": "Result capture write readiness blocked", + "severity": "critical", + "status": "blocked_by_policy", + "blocked_action": "result_capture_write_after_release_readiness", + "blocked_until": "owner release approved + result capture verifier ready", + "evidence_hash": "sha256:a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4" + }, + { + "blocker_id": "blocked_gateway_queue_write_readiness", + "display_name": "Gateway queue write readiness blocked", + "severity": "critical", + "status": "approval_required", + "blocked_action": "gateway_queue_write_after_release_readiness", + "blocked_until": "SRE route lock + Telegram receipt owner approved", + "evidence_hash": "sha256:a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5" + }, + { + "blocker_id": "blocked_telegram_send_readiness", + "display_name": "Telegram send readiness blocked", + "severity": "high", + "status": "approval_required", + "blocked_action": "telegram_send_after_release_readiness", + "blocked_until": "Gateway queue release approved + Telegram receipt E2E approved", + "evidence_hash": "sha256:a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6" + } + ], + "operator_actions": [ + { + "action_id": "review_release_readiness_readbacks", + "owner_agent": "openclaw", + "status": "ready_for_operator_review", + "operator_instruction": "審核 5 個 release readiness readback 是否仍符合 P2-129 release package 邊界;不要把 readiness 視為正式批准。", + "runtime_write_allowed": false + }, + { + "action_id": "verify_owner_release_readiness_checks", + "owner_agent": "hermes", + "status": "ready_for_operator_review", + "operator_instruction": "確認 owner release readiness check 仍全部未 approved,且所有 live apply readiness gate 仍為 false。", + "runtime_write_allowed": false + }, + { + "action_id": "verify_live_apply_readiness_hold", + "owner_agent": "nemotron", + "status": "ready_for_operator_review", + "operator_instruction": "確認 live apply readiness 已讀回但仍 hold;不可套用 writer 或執行正式寫入。", + "runtime_write_allowed": false + }, + { + "action_id": "verify_rollback_readiness", + "owner_agent": "openclaw", + "status": "approval_required", + "operator_instruction": "確認 rollback readiness scope、owner 與 hold reason 已整理,但 rollback_readiness_passed 仍為 false。", + "runtime_write_allowed": false + }, + { + "action_id": "prepare_p2_131_owner_release_approval_gate", + "owner_agent": "hermes", + "status": "ready_for_operator_review", + "operator_instruction": "下一關只可建立 P2-131 owner release approval gate,不可放行 writer 或正式寫入。", + "runtime_write_allowed": false + } + ], + "display_redaction_contract": { + "redaction_required": true, + "raw_prompt_display_allowed": false, + "private_reasoning_display_allowed": false, + "secret_value_display_allowed": false, + "raw_runtime_payload_display_allowed": false, + "internal_collaboration_content_display_allowed": false, + "frontend_display_policy": "前端只能顯示 release readiness readback 摘要、狀態、數量、紅acted hash 與 0 / false 邊界;不得顯示工作視窗對話、原始提示詞、私有推理、secret、authorization header 或原始 runtime payload。" + }, + "rollups": { + "release_readiness_readback_count": 5, + "owner_release_readiness_check_count": 5, + "live_apply_readiness_gate_count": 5, + "rollback_readiness_check_count": 5, + "blocked_readiness_transition_count": 6, + "operator_action_count": 5, + "approval_required_readback_count": 2, + "blocked_readback_count": 1, + "approval_required_owner_release_check_count": 2, + "blocked_owner_release_check_count": 1, + "approval_required_readiness_gate_count": 2, + "blocked_readiness_gate_count": 1, + "approval_required_rollback_count": 2, + "blocked_rollback_count": 1, + "critical_blocker_count": 5, + "owner_release_approved_count": 0, + "maintenance_window_approved_count": 0, + "rollback_owner_confirmed_count": 0, + "post_release_verifier_ready_count": 0, + "release_readiness_pass_count": 0, + "live_apply_release_pass_count": 0, + "writer_apply_count": 0, + "execution_apply_count": 0, + "receipt_write_count": 0, + "reviewer_queue_write_count": 0, + "gateway_queue_write_count": 0, + "telegram_send_count": 0, + "bot_api_call_count": 0, + "report_receipt_write_count": 0, + "result_capture_write_count": 0, + "learning_write_count": 0, + "playbook_trust_write_count": 0, + "production_write_count": 0, + "secret_read_count": 0, + "destructive_operation_count": 0 + } +} diff --git a/docs/schemas/ai_agent_result_capture_owner_approved_release_readiness_readback_v1.schema.json b/docs/schemas/ai_agent_result_capture_owner_approved_release_readiness_readback_v1.schema.json new file mode 100644 index 00000000..d18151af --- /dev/null +++ b/docs/schemas/ai_agent_result_capture_owner_approved_release_readiness_readback_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_approved_release_readiness_readback_v1.schema.json", + "title": "AI Agent result capture owner approved release readiness readback v1", + "type": "object", + "required": [ + "schema_version", + "generated_at", + "program_status", + "source_refs", + "prior_owner_approved_preflight_release_package", + "release_readiness_truth", + "release_readiness_readbacks", + "owner_release_readiness_checks", + "live_apply_readiness_gates", + "rollback_readiness_checks", + "blocked_readiness_transitions", + "operator_actions", + "display_redaction_contract", + "rollups" + ], + "properties": { + "schema_version": { + "const": "ai_agent_result_capture_owner_approved_release_readiness_readback_v1" + }, + "generated_at": { + "type": "string" + }, + "program_status": { + "type": "object" + }, + "source_refs": { + "type": "array", + "items": { + "type": "string" + } + }, + "prior_owner_approved_preflight_release_package": { + "type": "object" + }, + "release_readiness_truth": { + "type": "object" + }, + "release_readiness_readbacks": { + "type": "array", + "minItems": 5, + "maxItems": 5, + "items": { + "type": "object" + } + }, + "owner_release_readiness_checks": { + "type": "array", + "minItems": 5, + "maxItems": 5, + "items": { + "type": "object" + } + }, + "live_apply_readiness_gates": { + "type": "array", + "minItems": 5, + "maxItems": 5, + "items": { + "type": "object" + } + }, + "rollback_readiness_checks": { + "type": "array", + "minItems": 5, + "maxItems": 5, + "items": { + "type": "object" + } + }, + "blocked_readiness_transitions": { + "type": "array", + "minItems": 6, + "maxItems": 6, + "items": { + "type": "object" + } + }, + "operator_actions": { + "type": "array", + "minItems": 5, + "maxItems": 5, + "items": { + "type": "object" + } + }, + "display_redaction_contract": { + "type": "object" + }, + "rollups": { + "type": "object" + } + }, + "additionalProperties": false +} diff --git a/docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md b/docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md index 1649aad6..e378c0d3 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 @@ -666,7 +666,8 @@ Alert / Sentry / SigNoz / Gitea / Market Watch / Operator | `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_result_capture_owner_acceptance_readback_preflight_hold_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-owner-acceptance-readback-preflight-hold` | P2-128 owner acceptance readback / live-apply preflight hold;承接 P2-127 owner acceptance / maintenance window gate,建立 5 個 owner acceptance readback、5 個 preflight hold check、5 個 live-apply hold gate、5 個 rollback preflight check、6 個 blocked apply transition 與 5 個 operator action;runtime authority 固定 `result_capture_owner_acceptance_readback_preflight_hold_only_no_live_write`;owner acceptance received、maintenance window approved、rollback owner confirmed、post-apply verifier ready、live apply preflight passed、writer apply、execution apply、receipt write、canonical runtime target read、live query、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive action 全部 `0 / false`;deploy marker `0a3f1533` 已正式驗證,已由 P2-129 承接 | -| `docs/evaluations/ai_agent_result_capture_owner_approved_preflight_release_package_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-owner-approved-preflight-release-package` | P2-129 owner-approved preflight release package;承接 P2-128 owner acceptance readback / live-apply preflight hold,建立 5 個 owner-approved release package、5 個 release preflight check、5 個 live-apply release gate、5 個 rollback release check、6 個 blocked release transition 與 5 個 operator action;runtime authority 固定 `result_capture_owner_approved_preflight_release_package_only_no_live_write`;owner release approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、live apply release passed、writer apply、execution apply、receipt write、canonical runtime target read、live query、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive action 全部 `0 / false`;deploy marker `7e5b4793` 已正式驗證,下一步 P2-130 | +| `docs/evaluations/ai_agent_result_capture_owner_approved_preflight_release_package_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-owner-approved-preflight-release-package` | P2-129 owner-approved preflight release package;承接 P2-128 owner acceptance readback / live-apply preflight hold,建立 5 個 owner-approved release package、5 個 release preflight check、5 個 live-apply release gate、5 個 rollback release check、6 個 blocked release transition 與 5 個 operator action;runtime authority 固定 `result_capture_owner_approved_preflight_release_package_only_no_live_write`;owner release approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、live apply release passed、writer apply、execution apply、receipt write、canonical runtime target read、live query、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive action 全部 `0 / false`;deploy marker `7e5b4793` 已正式驗證,已由 P2-130 承接 | +| `docs/evaluations/ai_agent_result_capture_owner_approved_release_readiness_readback_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-owner-approved-release-readiness-readback` | P2-130 owner-approved release readiness readback;承接 P2-129 owner-approved preflight release package,建立 5 個 release readiness readback、5 個 owner release readiness check、5 個 live-apply readiness gate、5 個 rollback readiness check、6 個 blocked readiness transition 與 5 個 operator action;runtime authority 固定 `result_capture_owner_approved_release_readiness_readback_only_no_live_write`;owner release approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、release readiness passed、live apply release passed、writer apply、execution apply、receipt write、canonical runtime target read、live query、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive action 全部 `0 / false`,下一步 P2-131 | | `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 主動營運委派與版本生命週期契約 @@ -784,7 +785,8 @@ Repo / registry / release notes / K8s / host / observability / backup evidence 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`;deploy marker `7b034b58`、正式 API readback 與 desktop / mobile smoke 已完成。已由 P2-128 承接。 49. 建立 owner acceptance readback / live-apply preflight hold。✅ P2-128 已完成並正式驗證;owner acceptance readback `5`、preflight hold check `5`、live-apply hold gate `5`、rollback preflight check `5`、blocked apply transition `6`、operator action `5`,approval-required readback / preflight / hold / rollback `2 / 2 / 2 / 2`、blocked readback / preflight / hold / rollback `1 / 1 / 1 / 1`、critical blocker `5`;owner acceptance received、maintenance window approved、rollback owner confirmed、post-apply verifier ready、live apply preflight passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write 仍為 `0 / false`;deploy marker `0a3f1533`、正式 API readback 與 desktop / mobile smoke 已完成。已由 P2-129 承接。 -50. 建立 owner-approved preflight release package。✅ P2-129 已完成並正式驗證;owner-approved release package `5`、release preflight check `5`、live-apply release gate `5`、rollback release check `5`、blocked release transition `6`、operator action `5`,approval-required package / preflight / release gate / rollback `2 / 2 / 2 / 2`、blocked package / preflight / release gate / rollback `1 / 1 / 1 / 1`、critical blocker `5`;owner release approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write 仍為 `0 / false`;deploy marker `7e5b4793`、正式 API readback 與 desktop / mobile smoke 已完成。下一步 P2-130。 +50. 建立 owner-approved preflight release package。✅ P2-129 已完成並正式驗證;owner-approved release package `5`、release preflight check `5`、live-apply release gate `5`、rollback release check `5`、blocked release transition `6`、operator action `5`,approval-required package / preflight / release gate / rollback `2 / 2 / 2 / 2`、blocked package / preflight / release gate / rollback `1 / 1 / 1 / 1`、critical blocker `5`;owner release approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write 仍為 `0 / false`;deploy marker `7e5b4793`、正式 API readback 與 desktop / mobile smoke 已完成。已由 P2-130 承接。 +51. 建立 owner-approved release readiness readback。✅ P2-130 已本地完成,正式站待驗證;release readiness readback `5`、owner release readiness check `5`、live-apply readiness gate `5`、rollback readiness check `5`、blocked readiness transition `6`、operator action `5`,approval-required readback / owner check / readiness gate / rollback `2 / 2 / 2 / 2`、blocked readback / owner check / readiness gate / rollback `1 / 1 / 1 / 1`、critical blocker `5`;owner release approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、release readiness passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write 仍為 `0 / false`。下一步 P2-131。 #### 3.2.1d 2026-06-11 Agent 互動、學習與成長證據面 @@ -2105,6 +2107,16 @@ Phase 6 完成後 - 政策裁決: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 06:18 (台北) — §3.2 / §5 — 本地完成 P2-130 owner-approved release readiness readback — 把 release package 讀回成 readiness hold + +- 新增 `ai_agent_result_capture_owner_approved_release_readiness_readback_v1` schema / committed snapshot / loader / API / 測試,承接 P2-129 owner-approved preflight release package,定義 5 個 release readiness readback、5 個 owner release readiness check、5 個 live-apply readiness gate、5 個 rollback readiness check、6 個 blocked readiness transition 與 5 個 operator action。 +- Governance automation inventory 新增 P2-130 區塊,將 release readiness readback、owner release readiness check、live-apply readiness gate、rollback readiness、blocked readiness transition 與 operator action 全部以只讀方式呈現。 +- 本地 API/service regression:P2-130 + P2-129 `14 passed`;JSON parse、Python 3.11 py_compile、`pnpm --filter @awoooi/web typecheck` 與 production build 通過。 +- 本地 snapshot 固定 `schema_version=ai_agent_result_capture_owner_approved_release_readiness_readback_v1`、current `P2-130`、next `P2-131`、completion `100`;release readiness readback `5`、owner release readiness check `5`、live-apply readiness gate `5`、rollback readiness check `5`、blocked readiness transition `6`、operator action `5`、approval-required readback / owner check / readiness gate / rollback `2 / 2 / 2 / 2`、blocked readback / owner check / readiness gate / rollback `1 / 1 / 1 / 1`、critical blocker `5`。 +- 本地 0 / false 邊界:owner release approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、release readiness passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive operation 均為 `0 / false`。 +- 政策裁決:P2-130 只允許 owner-approved release readiness readback 可視化;不得把 readiness 解讀成 owner release approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、live apply release passed、writer apply、execution apply、receipt write、result capture write、learning write、PlayBook trust write、reviewer queue write、Gateway queue write、Telegram 實發、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-131。 + ### 2026-06-14 05:12 (台北) — §3.2 / §5 — 正式驗證 P2-129 owner-approved preflight release package — 把 preflight hold 整理成 release package - 新增 `ai_agent_result_capture_owner_approved_preflight_release_package_v1` schema / committed snapshot / loader / API / 測試,承接 P2-128 owner acceptance readback / live-apply preflight hold,定義 5 個 owner-approved release package、5 個 release preflight check、5 個 live-apply release gate、5 個 rollback release check、6 個 blocked release transition 與 5 個 operator action。 @@ -2117,7 +2129,7 @@ Phase 6 完成後 - 正式 desktop / mobile smoke:P2-129 區塊與必要數字可見,禁用內部協作片語命中 `0`、水平溢位 `0`、P2-129 高風險控制 `0`、console error `0`、API bad response `0`。 - ArgoCD 已同步到 `7e5b4793`,web / api rollout 完成;health 仍因既有 `km-vectorize` CronJob 債務呈現 Degraded,非 P2-129 新增債務。 - 政策裁決:P2-129 只允許 owner-approved preflight release package 可視化;不得把 package 解讀成 owner release approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、live apply release passed、writer apply、execution apply、receipt write、result capture write、learning write、PlayBook trust write、reviewer queue write、Gateway queue write、Telegram 實發、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-130。 +- 本波仍不讀 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-130 承接。 ### 2026-06-14 04:18 (台北) — §3.2 / §5 — 正式驗證 P2-128 owner acceptance readback / live-apply preflight hold — 把 acceptance gate 讀回成 preflight hold