From 2fe31c911113969334020818d49e2c6715c01d3b Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 14 Jun 2026 12:24:54 +0800 Subject: [PATCH] =?UTF-8?q?feat(governance):=20=E6=96=B0=E5=A2=9E=20releas?= =?UTF-8?q?e=20decision=20next=20handoff?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/api/src/api/v1/agents.py | 33 ++ ...t_capture_release_decision_next_handoff.py | 354 ++++++++++++++++++ ...t_capture_release_decision_next_handoff.py | 98 +++++ ...pture_release_decision_next_handoff_api.py | 32 ++ apps/web/messages/en.json | 36 ++ apps/web/messages/zh-TW.json | 36 ++ .../tabs/automation-inventory-tab.tsx | 165 +++++++- apps/web/src/lib/api-client.ts | 152 ++++++++ docs/LOGBOOK.md | 26 ++ ...AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md | 18 +- ...ease_decision_next_handoff_2026-06-14.json | 353 +++++++++++++++++ ...lease_decision_next_handoff_v1.schema.json | 82 ++++ ...-04-15-MASTER-ai-autonomous-flywheel-v2.md | 9 + 13 files changed, 1389 insertions(+), 5 deletions(-) create mode 100644 apps/api/src/services/ai_agent_result_capture_release_decision_next_handoff.py create mode 100644 apps/api/tests/test_ai_agent_result_capture_release_decision_next_handoff.py create mode 100644 apps/api/tests/test_ai_agent_result_capture_release_decision_next_handoff_api.py create mode 100644 docs/evaluations/ai_agent_result_capture_release_decision_next_handoff_2026-06-14.json create mode 100644 docs/schemas/ai_agent_result_capture_release_decision_next_handoff_v1.schema.json diff --git a/apps/api/src/api/v1/agents.py b/apps/api/src/api/v1/agents.py index 3e87109a1..b60c9e379 100644 --- a/apps/api/src/api/v1/agents.py +++ b/apps/api/src/api/v1/agents.py @@ -127,6 +127,9 @@ from src.services.ai_agent_result_capture_release_decision_hold import ( from src.services.ai_agent_result_capture_release_decision_readback import ( load_latest_ai_agent_result_capture_release_decision_readback, ) +from src.services.ai_agent_result_capture_release_decision_next_handoff import ( + load_latest_ai_agent_result_capture_release_decision_next_handoff, +) from src.services.ai_agent_result_capture_owner_promotion_review import ( load_latest_ai_agent_result_capture_owner_promotion_review, ) @@ -2325,6 +2328,36 @@ async def get_agent_result_capture_release_decision_readback() -> dict[str, Any] ) from exc +@router.get( + "/agent-result-capture-release-decision-next-handoff", + response_model=dict[str, Any], + summary="取得 AI Agent result capture release decision next handoff", + description=( + "讀取最新已提交的 P2-140 release decision next handoff;" + "此端點只回讀 P2-139 release decision readback 的下一關交接,隔離 P2-139 自我迴圈提示," + "不把 handoff 視為 owner approval、不核發 release authorization、" + "不寫 reviewer queue、Gateway queue、receipt、result capture、learning 或 PlayBook trust," + "不送 Telegram、不呼叫 Bot API、不讀 secret、不執行 production 寫入。" + ), +) +async def get_agent_result_capture_release_decision_next_handoff() -> dict[str, Any]: + """Return the latest read-only release decision next-handoff readback.""" + try: + payload = await asyncio.to_thread(load_latest_ai_agent_result_capture_release_decision_next_handoff) + return redact_public_lan_topology(payload) + except FileNotFoundError as exc: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=str(exc), + ) from exc + except (json.JSONDecodeError, ValueError) as exc: + logger.error("ai_agent_result_capture_release_decision_next_handoff_invalid", error=str(exc)) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="AI Agent result capture release decision next handoff 無效", + ) from exc + + @router.get( "/agent-owner-approved-fixture-dry-run", response_model=dict[str, Any], diff --git a/apps/api/src/services/ai_agent_result_capture_release_decision_next_handoff.py b/apps/api/src/services/ai_agent_result_capture_release_decision_next_handoff.py new file mode 100644 index 000000000..04893c1f6 --- /dev/null +++ b/apps/api/src/services/ai_agent_result_capture_release_decision_next_handoff.py @@ -0,0 +1,354 @@ +""" +AI Agent result capture release decision next handoff snapshot. + +Loads the latest committed P2-140 next-handoff readback. This module only +reads committed evidence from P2-139 release decision readback; it never treats +handoff visibility as owner approval, grants release authorization, writes +reviewer / Gateway queues, sends Telegram messages, writes result capture, +writes learning records, updates PlayBook trust, reads secrets, writes +production targets, or performs destructive operations. +""" + +from __future__ import annotations + +import json +import re +from pathlib import Path +from typing import Any + +from src.services.snapshot_paths import default_evaluations_dir + +_DEFAULT_EVALUATIONS_DIR = default_evaluations_dir(Path(__file__)) +_SNAPSHOT_PATTERN = "ai_agent_result_capture_release_decision_next_handoff_*.json" +_SCHEMA_VERSION = "ai_agent_result_capture_release_decision_next_handoff_v1" +_RUNTIME_AUTHORITY = "result_capture_release_decision_next_handoff_only_no_live_write" + + +def load_latest_ai_agent_result_capture_release_decision_next_handoff( + evaluations_dir: Path | None = None, +) -> dict[str, Any]: + """Load the newest committed release decision next-handoff 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 release decision next handoff 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_next_gate_handoffs(payload, label) + _require_stale_containment(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-140", + "next_task_id": "P2-141", + "read_only_mode": True, + "runtime_authority": _RUNTIME_AUTHORITY, + "overall_completion_percent": 100, + } + mismatches = _mismatches(status, expected) + if mismatches: + raise ValueError(f"{label}: program_status mismatch: {mismatches}") + if not status.get("status_note"): + raise ValueError(f"{label}: program_status.status_note is required") + + +def _require_prior(payload: dict[str, Any], label: str) -> None: + prior = payload.get("prior_release_decision_readback") or {} + expected = { + "schema_version": "ai_agent_result_capture_release_decision_readback_v1", + "current_task_id": "P2-139", + "next_task_id": "P2-140", + "release_decision_readback_count": 5, + "owner_decision_readback_count": 5, + "verifier_decision_readback_count": 5, + "rollback_decision_readback_count": 5, + "maintenance_window_decision_readback_count": 5, + "live_apply_decision_readback_count": 5, + "blocked_readback_transition_count": 6, + "operator_action_count": 5, + "approval_required_total": 12, + "blocked_total": 12, + "stale_self_loop_action_count": 1, + } + expected.update(_zero_count_expectations()) + mismatches = _mismatches(prior, expected) + if mismatches: + raise ValueError(f"{label}: prior_release_decision_readback mismatch: {mismatches}") + if not prior.get("readiness_note"): + raise ValueError(f"{label}: prior_release_decision_readback.readiness_note is required") + + +def _require_truth(payload: dict[str, Any], label: str) -> None: + truth = payload.get("next_handoff_truth") or {} + required_true = { + "p2_139_release_decision_readback_loaded", + "next_task_id_alignment_checked", + "stale_self_loop_detected", + "stale_self_loop_contained", + "p2_140_next_handoff_only", + "operator_instruction_requires_p2_141", + "owner_decision_still_required", + "verifier_decision_still_required", + "rollback_decision_still_required", + "maintenance_window_decision_still_required", + "live_apply_decision_still_required", + "redaction_review_still_required", + } + missing = sorted(field for field in required_true if truth.get(field) is not True) + if missing: + raise ValueError(f"{label}: next handoff flags must remain true: {missing}") + + required_false = { + "owner_release_authorized", + "owner_release_approved", + "owner_review_approved", + "owner_decision_approved", + "verifier_decision_approved", + "maintenance_window_approved", + "rollback_owner_confirmed", + "post_release_verifier_ready", + "final_release_candidate_approved", + "final_release_candidate_passed", + "release_decision_passed", + "release_authorization_granted", + "release_authorization_passed", + "rollback_release_passed", + "live_apply_release_passed", + "writer_apply_enabled", + "execution_apply_enabled", + "receipt_write_enabled", + "reviewer_queue_write_enabled", + "gateway_queue_write_enabled", + "telegram_send_enabled", + "bot_api_call_enabled", + "report_receipt_write_enabled", + "result_capture_write_enabled", + "learning_write_enabled", + "playbook_trust_write_enabled", + "production_write_enabled", + "secret_read_enabled", + "destructive_operation_enabled", + } + unsafe = sorted(field for field in required_false if truth.get(field) is not False) + if unsafe: + raise ValueError(f"{label}: next handoff live/send/write flags must remain false: {unsafe}") + + non_zero = sorted(field for field in _zero_count_expectations() if truth.get(field) != 0) + if non_zero: + raise ValueError(f"{label}: next handoff live counters must remain zero: {non_zero}") + if not truth.get("truth_note"): + raise ValueError(f"{label}: next_handoff_truth.truth_note is required") + + +def _require_next_gate_handoffs(payload: dict[str, Any], label: str) -> None: + items = payload.get("next_gate_handoffs") or [] + _require_ids( + items, + "handoff_id", + {f"next_gate_handoff_{name}" for name in ["result_capture", "learning", "playbook_trust", "reviewer_queue", "gateway_queue"]}, + label, + "next gate handoffs", + ) + for item in items: + item_id = item.get("handoff_id") + expected = { + "source_task_id": "P2-139", + "current_task_id": "P2-140", + "target_next_task_id": "P2-141", + "handoff_mode": "next_gate_readback", + "runtime_write_allowed": False, + "telegram_send_allowed": False, + } + mismatches = _mismatches(item, expected) + if mismatches: + raise ValueError(f"{label}: next gate handoff {item_id} mismatch: {mismatches}") + if item.get("handoff_status") not in {"ready_for_operator_review", "approval_required"}: + raise ValueError(f"{label}: next gate handoff {item_id} status is invalid") + if not item.get("handoff_summary"): + raise ValueError(f"{label}: next gate handoff {item_id}.handoff_summary is required") + if not _is_redacted_sha256(item.get("evidence_hash")): + raise ValueError(f"{label}: next gate handoff {item_id}.evidence_hash must be redacted sha256") + + +def _require_stale_containment(payload: dict[str, Any], label: str) -> None: + items = payload.get("stale_operator_action_containments") or [] + _require_count(items, 1, label, "stale operator action containments") + item = items[0] + expected = { + "source_action_id": "prepare_p2_139_release_decision_readback", + "source_task_id": "P2-139", + "expected_current_task_id": "P2-140", + "expected_next_task_id": "P2-141", + "containment_status": "contained_read_only", + "runtime_write_allowed": False, + "telegram_send_allowed": False, + } + mismatches = _mismatches(item, expected) + if mismatches: + raise ValueError(f"{label}: stale operator action containment mismatch: {mismatches}") + if not item.get("containment_summary"): + raise ValueError(f"{label}: stale operator action containment summary is required") + + +def _require_blocked_transitions(payload: dict[str, Any], label: str) -> None: + items = payload.get("blocked_handoff_transitions") or [] + _require_count(items, 6, label, "blocked handoff transitions") + for item in items: + item_id = item.get("transition_id") + if item.get("runtime_write_allowed") is not False: + raise ValueError(f"{label}: blocked handoff transition {item_id} must keep runtime_write_allowed=false") + if item.get("status") not in {"blocked_by_policy", "approval_required"}: + raise ValueError(f"{label}: blocked handoff transition {item_id} status is invalid") + if not item.get("reason"): + raise ValueError(f"{label}: blocked handoff transition {item_id}.reason is required") + + +def _require_actions(payload: dict[str, Any], label: str) -> None: + items = payload.get("operator_actions") or [] + _require_count(items, 5, label, "operator actions") + for item in items: + item_id = item.get("action_id") + if "prepare_p2_139" in str(item_id): + raise ValueError(f"{label}: operator action {item_id} must not point back to P2-139") + if item.get("runtime_write_allowed") is not False: + raise ValueError(f"{label}: operator action {item_id} must keep runtime_write_allowed=false") + if item.get("status") not in {"ready_for_operator_review", "approval_required"}: + raise ValueError(f"{label}: operator action {item_id} status is invalid") + if not item.get("operator_instruction"): + raise ValueError(f"{label}: operator action {item_id}.operator_instruction is required") + + +def _require_display_redaction(payload: dict[str, Any], label: str) -> None: + contract = payload.get("display_redaction_contract") or {} + expected = { + "redaction_required": True, + "raw_prompt_display_allowed": False, + "private_reasoning_display_allowed": False, + "secret_value_display_allowed": False, + "raw_runtime_payload_display_allowed": False, + "internal_collaboration_content_display_allowed": False, + } + mismatches = _mismatches(contract, expected) + if mismatches: + raise ValueError(f"{label}: display_redaction_contract mismatch: {mismatches}") + if not contract.get("frontend_display_policy"): + raise ValueError(f"{label}: display_redaction_contract.frontend_display_policy is required") + + +def _require_rollup_consistency(payload: dict[str, Any], label: str) -> None: + rollups = payload.get("rollups") or {} + expected = { + "next_gate_handoff_count": len(payload.get("next_gate_handoffs") or []), + "stale_operator_action_count": len(payload.get("stale_operator_action_containments") or []), + "blocked_handoff_transition_count": len(payload.get("blocked_handoff_transitions") or []), + "operator_action_count": len(payload.get("operator_actions") or []), + "approval_required_subtotal": 12, + "blocked_and_critical_subtotal": 12, + } + expected.update(_zero_count_expectations()) + mismatches = _mismatches(rollups, expected) + if mismatches: + raise ValueError(f"{label}: rollups mismatch: {mismatches}") + + +def _require_no_forbidden_display_terms(payload: Any, label: str) -> None: + forbidden = { + "work_window_transcript", + "internal_collaboration_transcript", + "raw_prompt", + "private_reasoning", + "chain_of_thought", + "authorization_header", + "secret_value", + } + found = sorted(term for term in forbidden if _contains_term(payload, term)) + if found: + raise ValueError(f"{label}: forbidden display terms leaked: {found}") + + +def _contains_term(value: Any, term: str) -> bool: + if isinstance(value, str): + return term.lower() in value.lower() + if isinstance(value, dict): + return any(_contains_term(child, term) for child in value.values()) + if isinstance(value, list): + return any(_contains_term(child, term) for child in value) + return False + + +def _zero_count_expectations() -> dict[str, int]: + return { + "owner_release_authorized_count": 0, + "owner_release_approved_count": 0, + "owner_review_approved_count": 0, + "owner_decision_approved_count": 0, + "verifier_decision_approved_count": 0, + "maintenance_window_approved_count": 0, + "rollback_owner_confirmed_count": 0, + "post_release_verifier_ready_count": 0, + "final_release_candidate_approved_count": 0, + "final_release_candidate_pass_count": 0, + "release_decision_pass_count": 0, + "release_authorization_granted_count": 0, + "release_authorization_pass_count": 0, + "rollback_release_pass_count": 0, + "live_apply_release_pass_count": 0, + "writer_apply_count": 0, + "execution_apply_count": 0, + "receipt_write_count": 0, + "reviewer_queue_write_count": 0, + "gateway_queue_write_count": 0, + "telegram_send_count": 0, + "bot_api_call_count": 0, + "report_receipt_write_count": 0, + "result_capture_write_count": 0, + "learning_write_count": 0, + "playbook_trust_write_count": 0, + "production_write_count": 0, + "secret_read_count": 0, + "destructive_operation_count": 0, + } + + +def _require_ids(items: list[dict[str, Any]], field: str, expected_ids: set[str], label: str, group_name: str) -> None: + actual_ids = {str(item.get(field)) for item in items} + if actual_ids != expected_ids: + raise ValueError(f"{label}: {group_name} ids mismatch: expected={sorted(expected_ids)} actual={sorted(actual_ids)}") + + +def _require_count(items: list[Any], expected: int, label: str, group_name: str) -> None: + if len(items) != expected: + raise ValueError(f"{label}: expected {expected} {group_name}, got {len(items)}") + + +def _is_redacted_sha256(value: Any) -> bool: + return isinstance(value, str) and re.fullmatch(r"sha256:[0-9a-f]{64}", value) is not None + + +def _mismatches(payload: dict[str, Any], expected: dict[str, Any]) -> dict[str, dict[str, Any]]: + return { + key: {"expected": expected_value, "actual": payload.get(key)} + for key, expected_value in expected.items() + if payload.get(key) != expected_value + } diff --git a/apps/api/tests/test_ai_agent_result_capture_release_decision_next_handoff.py b/apps/api/tests/test_ai_agent_result_capture_release_decision_next_handoff.py new file mode 100644 index 000000000..7fe2ac9af --- /dev/null +++ b/apps/api/tests/test_ai_agent_result_capture_release_decision_next_handoff.py @@ -0,0 +1,98 @@ +from __future__ import annotations + +import copy +import json +from pathlib import Path + +import pytest + +from src.services.ai_agent_result_capture_release_decision_next_handoff import ( + load_latest_ai_agent_result_capture_release_decision_next_handoff, +) + + +def test_load_latest_release_decision_next_handoff_snapshot() -> None: + snapshot = load_latest_ai_agent_result_capture_release_decision_next_handoff() + + assert snapshot["schema_version"] == "ai_agent_result_capture_release_decision_next_handoff_v1" + assert snapshot["program_status"]["current_task_id"] == "P2-140" + assert snapshot["program_status"]["next_task_id"] == "P2-141" + assert snapshot["program_status"]["overall_completion_percent"] == 100 + assert snapshot["program_status"]["runtime_authority"] == "result_capture_release_decision_next_handoff_only_no_live_write" + + rollups = snapshot["rollups"] + assert rollups["next_gate_handoff_count"] == 5 + assert rollups["stale_operator_action_count"] == 1 + assert rollups["blocked_handoff_transition_count"] == 6 + assert rollups["operator_action_count"] == 5 + assert rollups["approval_required_subtotal"] == 12 + assert rollups["blocked_and_critical_subtotal"] == 12 + assert rollups["reviewer_queue_write_count"] == 0 + assert rollups["gateway_queue_write_count"] == 0 + assert rollups["telegram_send_count"] == 0 + assert rollups["bot_api_call_count"] == 0 + assert rollups["result_capture_write_count"] == 0 + assert rollups["learning_write_count"] == 0 + assert rollups["playbook_trust_write_count"] == 0 + assert rollups["production_write_count"] == 0 + + +def test_next_handoff_truth_contains_stale_self_loop_without_writes() -> None: + snapshot = load_latest_ai_agent_result_capture_release_decision_next_handoff() + truth = snapshot["next_handoff_truth"] + + assert truth["p2_139_release_decision_readback_loaded"] is True + assert truth["next_task_id_alignment_checked"] is True + assert truth["stale_self_loop_detected"] is True + assert truth["stale_self_loop_contained"] is True + assert truth["p2_140_next_handoff_only"] is True + assert truth["operator_instruction_requires_p2_141"] is True + assert truth["release_authorization_granted"] is False + assert truth["reviewer_queue_write_enabled"] is False + assert truth["gateway_queue_write_enabled"] is False + assert truth["telegram_send_enabled"] is False + assert truth["production_write_enabled"] is False + assert truth["secret_read_enabled"] is False + assert truth["destructive_operation_enabled"] is False + + +def test_rejects_missing_stale_self_loop_containment(tmp_path: Path) -> None: + snapshot = copy.deepcopy(load_latest_ai_agent_result_capture_release_decision_next_handoff()) + snapshot["stale_operator_action_containments"] = [] + snapshot["rollups"]["stale_operator_action_count"] = 0 + _write_snapshot(tmp_path, snapshot) + + with pytest.raises(ValueError, match="expected 1 stale operator action containments"): + load_latest_ai_agent_result_capture_release_decision_next_handoff(tmp_path) + + +def test_rejects_operator_action_that_points_back_to_p2_139(tmp_path: Path) -> None: + snapshot = copy.deepcopy(load_latest_ai_agent_result_capture_release_decision_next_handoff()) + snapshot["operator_actions"][0]["action_id"] = "prepare_p2_139_release_decision_readback" + _write_snapshot(tmp_path, snapshot) + + with pytest.raises(ValueError, match="must not point back to P2-139"): + load_latest_ai_agent_result_capture_release_decision_next_handoff(tmp_path) + + +def test_rejects_gateway_write_drift(tmp_path: Path) -> None: + snapshot = copy.deepcopy(load_latest_ai_agent_result_capture_release_decision_next_handoff()) + snapshot["rollups"]["gateway_queue_write_count"] = 1 + _write_snapshot(tmp_path, snapshot) + + with pytest.raises(ValueError, match="rollups mismatch"): + load_latest_ai_agent_result_capture_release_decision_next_handoff(tmp_path) + + +def test_rejects_forbidden_display_terms(tmp_path: Path) -> None: + snapshot = copy.deepcopy(load_latest_ai_agent_result_capture_release_decision_next_handoff()) + snapshot["operator_actions"][0]["operator_instruction"] = "不要顯示 raw_prompt" + _write_snapshot(tmp_path, snapshot) + + with pytest.raises(ValueError, match="forbidden display terms leaked"): + load_latest_ai_agent_result_capture_release_decision_next_handoff(tmp_path) + + +def _write_snapshot(directory: Path, payload: dict) -> None: + path = directory / "ai_agent_result_capture_release_decision_next_handoff_2099-01-01.json" + path.write_text(json.dumps(payload, ensure_ascii=False), encoding="utf-8") diff --git a/apps/api/tests/test_ai_agent_result_capture_release_decision_next_handoff_api.py b/apps/api/tests/test_ai_agent_result_capture_release_decision_next_handoff_api.py new file mode 100644 index 000000000..4d4716b66 --- /dev/null +++ b/apps/api/tests/test_ai_agent_result_capture_release_decision_next_handoff_api.py @@ -0,0 +1,32 @@ +from __future__ import annotations + +from fastapi.testclient import TestClient + +from src.main import app + + +def test_release_decision_next_handoff_endpoint() -> None: + client = TestClient(app) + + response = client.get("/api/v1/agents/agent-result-capture-release-decision-next-handoff") + + assert response.status_code == 200 + payload = response.json() + assert payload["schema_version"] == "ai_agent_result_capture_release_decision_next_handoff_v1" + assert payload["program_status"]["current_task_id"] == "P2-140" + assert payload["program_status"]["next_task_id"] == "P2-141" + assert payload["program_status"]["overall_completion_percent"] == 100 + assert payload["program_status"]["runtime_authority"] == "result_capture_release_decision_next_handoff_only_no_live_write" + assert payload["prior_release_decision_readback"]["schema_version"] == "ai_agent_result_capture_release_decision_readback_v1" + assert payload["prior_release_decision_readback"]["next_task_id"] == "P2-140" + assert payload["rollups"]["next_gate_handoff_count"] == 5 + assert payload["rollups"]["stale_operator_action_count"] == 1 + assert payload["rollups"]["blocked_handoff_transition_count"] == 6 + assert payload["rollups"]["operator_action_count"] == 5 + assert payload["rollups"]["approval_required_subtotal"] == 12 + assert payload["rollups"]["blocked_and_critical_subtotal"] == 12 + assert payload["rollups"]["reviewer_queue_write_count"] == 0 + assert payload["rollups"]["gateway_queue_write_count"] == 0 + assert payload["rollups"]["telegram_send_count"] == 0 + assert payload["rollups"]["bot_api_call_count"] == 0 + assert payload["rollups"]["production_write_count"] == 0 diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index deebe5906..74d20e22c 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -6222,6 +6222,42 @@ "telegramSendAllowed": "Telegram 發送允許={value}" } }, + "resultCaptureReleaseDecisionNextHandoff": { + "title": "P2-140 釋出決策下一關交接讀回", + "source": "產生 {generated};目前 {current};下一步 {next}", + "priorTitle": "P2-139 讀回交接基線", + "truthTitle": "下一關交接真相", + "handoffTitle": "下一關交接卡", + "containmentTitle": "自我迴圈隔離", + "blockerTitle": "阻擋轉換", + "actionTitle": "操作員下一步", + "metrics": { + "overall": "完成度", + "nextHandoffs": "下一關交接", + "staleActions": "舊 action 隔離", + "blockers": "已阻擋轉換", + "actions": "操作選項", + "approvalRequired": "仍需批准", + "blocked": "阻擋總數", + "liveWrites": "正式寫入 / 發送" + }, + "flags": { + "p2Loaded": "已載入 P2-139={value}", + "selfLoopContained": "自我迴圈已隔離={value}", + "requiresP2141": "下一步必須往 P2-141={value}" + }, + "labels": { + "priorCurrent": "上一關目前={value}", + "priorNext": "上一關下一步={value}", + "expectedCurrent": "預期目前={value}", + "expectedNext": "預期下一步={value}", + "gatewayWrites": "Gateway 寫入={value}", + "telegramSends": "Telegram 送出={value}", + "productionWrites": "正式寫入={value}", + "runtimeWriteAllowed": "runtime 寫入允許={value}", + "telegramSendAllowed": "Telegram 發送允許={value}" + } + }, "resultCaptureReleaseVerifierOwnerReviewPacket": { "title": "P2-137 釋出驗證器負責人審查包", "source": "產生 {generated};目前 {current};下一步 {next}", diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index deebe5906..74d20e22c 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -6222,6 +6222,42 @@ "telegramSendAllowed": "Telegram 發送允許={value}" } }, + "resultCaptureReleaseDecisionNextHandoff": { + "title": "P2-140 釋出決策下一關交接讀回", + "source": "產生 {generated};目前 {current};下一步 {next}", + "priorTitle": "P2-139 讀回交接基線", + "truthTitle": "下一關交接真相", + "handoffTitle": "下一關交接卡", + "containmentTitle": "自我迴圈隔離", + "blockerTitle": "阻擋轉換", + "actionTitle": "操作員下一步", + "metrics": { + "overall": "完成度", + "nextHandoffs": "下一關交接", + "staleActions": "舊 action 隔離", + "blockers": "已阻擋轉換", + "actions": "操作選項", + "approvalRequired": "仍需批准", + "blocked": "阻擋總數", + "liveWrites": "正式寫入 / 發送" + }, + "flags": { + "p2Loaded": "已載入 P2-139={value}", + "selfLoopContained": "自我迴圈已隔離={value}", + "requiresP2141": "下一步必須往 P2-141={value}" + }, + "labels": { + "priorCurrent": "上一關目前={value}", + "priorNext": "上一關下一步={value}", + "expectedCurrent": "預期目前={value}", + "expectedNext": "預期下一步={value}", + "gatewayWrites": "Gateway 寫入={value}", + "telegramSends": "Telegram 送出={value}", + "productionWrites": "正式寫入={value}", + "runtimeWriteAllowed": "runtime 寫入允許={value}", + "telegramSendAllowed": "Telegram 發送允許={value}" + } + }, "resultCaptureReleaseVerifierOwnerReviewPacket": { "title": "P2-137 釋出驗證器負責人審查包", "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 56d367097..3be42e7fc 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 @@ -88,6 +88,7 @@ import { type AiAgentResultCaptureReleaseAuthorizationReadbackGateSnapshot, type AiAgentResultCaptureReleaseDecisionHoldSnapshot, type AiAgentResultCaptureReleaseDecisionReadbackSnapshot, + type AiAgentResultCaptureReleaseDecisionNextHandoffSnapshot, type AiAgentResultCaptureReleaseVerifierPreflightGateSnapshot, type AiAgentResultCaptureReleaseVerifierOwnerReviewPacketSnapshot, type AiAgentResultCaptureWriterImplementationReviewSnapshot, @@ -504,6 +505,7 @@ export function AutomationInventoryTab() { const [resultCaptureReleaseVerifierOwnerReviewPacket, setResultCaptureReleaseVerifierOwnerReviewPacket] = useState(null) const [resultCaptureReleaseDecisionHold, setResultCaptureReleaseDecisionHold] = useState(null) const [resultCaptureReleaseDecisionReadback, setResultCaptureReleaseDecisionReadback] = useState(null) + const [resultCaptureReleaseDecisionNextHandoff, setResultCaptureReleaseDecisionNextHandoff] = useState(null) const [reportTruthActionabilityReview, setReportTruthActionabilityReview] = useState(null) const [ownerDryRunPackage, setOwnerDryRunPackage] = useState(null) const [hostStatefulInventory, setHostStatefulInventory] = useState(null) @@ -580,6 +582,7 @@ export function AutomationInventoryTab() { apiClient.getAiAgentResultCaptureReleaseVerifierOwnerReviewPacket(), apiClient.getAiAgentResultCaptureReleaseDecisionHold(), apiClient.getAiAgentResultCaptureReleaseDecisionReadback(), + apiClient.getAiAgentResultCaptureReleaseDecisionNextHandoff(), apiClient.getAiAgentReportTruthActionabilityReview(), apiClient.getAiAgentOwnerApprovedFixtureDryRun(), apiClient.getAiAgentHostStatefulVersionInventory(), @@ -655,6 +658,7 @@ export function AutomationInventoryTab() { resultCaptureReleaseVerifierOwnerReviewPacketResult, resultCaptureReleaseDecisionHoldResult, resultCaptureReleaseDecisionReadbackResult, + resultCaptureReleaseDecisionNextHandoffResult, reportTruthActionabilityReviewResult, ownerDryRunPackageResult, hostStatefulInventoryResult, @@ -727,6 +731,7 @@ export function AutomationInventoryTab() { setResultCaptureReleaseVerifierOwnerReviewPacket(resultCaptureReleaseVerifierOwnerReviewPacketResult.status === 'fulfilled' ? resultCaptureReleaseVerifierOwnerReviewPacketResult.value : null) setResultCaptureReleaseDecisionHold(resultCaptureReleaseDecisionHoldResult.status === 'fulfilled' ? resultCaptureReleaseDecisionHoldResult.value : null) setResultCaptureReleaseDecisionReadback(resultCaptureReleaseDecisionReadbackResult.status === 'fulfilled' ? resultCaptureReleaseDecisionReadbackResult.value : null) + setResultCaptureReleaseDecisionNextHandoff(resultCaptureReleaseDecisionNextHandoffResult.status === 'fulfilled' ? resultCaptureReleaseDecisionNextHandoffResult.value : null) setReportTruthActionabilityReview(reportTruthActionabilityReviewResult.status === 'fulfilled' ? reportTruthActionabilityReviewResult.value : null) setOwnerDryRunPackage(ownerDryRunPackageResult.status === 'fulfilled' ? ownerDryRunPackageResult.value : null) setHostStatefulInventory(hostStatefulInventoryResult.status === 'fulfilled' ? hostStatefulInventoryResult.value : null) @@ -797,6 +802,7 @@ export function AutomationInventoryTab() { resultCaptureReleaseVerifierOwnerReviewPacketResult, resultCaptureReleaseDecisionHoldResult, resultCaptureReleaseDecisionReadbackResult, + resultCaptureReleaseDecisionNextHandoffResult, reportTruthActionabilityReviewResult, ownerDryRunPackageResult, hostStatefulInventoryResult, @@ -2039,7 +2045,7 @@ export function AutomationInventoryTab() { ) } - if (error || !snapshot || !backlog || !backupTargets || !backupReadiness || !backupPolicy || !offsiteEscrow || !giteaHealth || !observabilityMatrix || !providerRouteMatrix || !deploymentLayout || !proactiveOperations || !interactionLearningProof || !liveReadModelGate || !redisDryRunGate || !learningWritebackPackage || !telegramReceiptPackage || !ownerApprovedLearningDryRun || !runtimeWriteGateReview || !postWriteVerifierPackage || !runtimeVerifierEvidenceReview || !reportAutomationReview || !reportStatusBoard || !reportRuntimeReadiness || !reportRuntimeDryRun || !reportRuntimeFixtureReadback || !runtimeWorkerShadowGate || !operationPermissionModel || !candidateOperationDryRunEvidence || !taskResultAuditTrail || !matchedPlaybookLearningGap || !criticReviewerResultCapture || !ownerApprovedResultCaptureDryRun || !ownerApprovedResultCaptureReadback || !runtimeReadbackApprovalPackage || !runtimeReadbackImplementationReview || !reportLiveDeliveryApprovalPackage || !runtimeReadbackFixtureApproval || !runtimeReadbackPromotionGate || !ownerApprovedFixturePromotionGate || !canonicalRuntimeReadbackOwnerAcceptance || !failureReceiptNoSendReplay || !reviewerQueueNoWriteReadback || !resultCaptureNoWriteReadback || !resultCapturePromotionApprovalGate || !ownerApprovedResultCapturePromotionDryRun || !resultCaptureWriteGateReview || !resultCaptureWriterImplementationReview || !resultCaptureWriterDryRunFixture || !resultCaptureWriterDryRunReadback || !resultCaptureOwnerPromotionReview || !resultCaptureOwnerApprovedExecutionRehearsal || !resultCaptureOwnerAcceptanceMaintenanceGate || !resultCaptureOwnerAcceptanceReadbackPreflightHold || !resultCaptureOwnerApprovedPreflightReleasePackage || !resultCaptureOwnerApprovedReleaseReadinessReadback || !resultCaptureOwnerReleaseApprovalGate || !resultCapturePostReleaseVerifierRollbackGate || !resultCaptureFinalReleaseCandidateReadback || !resultCaptureReleaseAuthorizationHold || !resultCaptureReleaseAuthorizationReadbackGate || !resultCaptureReleaseVerifierPreflightGate || !resultCaptureReleaseVerifierOwnerReviewPacket || !resultCaptureReleaseDecisionHold || !resultCaptureReleaseDecisionReadback || !reportTruthActionabilityReview || !ownerDryRunPackage || !hostStatefulInventory || !serviceHealthGapMatrix || !serviceHealthNotificationPolicy) { + if (error || !snapshot || !backlog || !backupTargets || !backupReadiness || !backupPolicy || !offsiteEscrow || !giteaHealth || !observabilityMatrix || !providerRouteMatrix || !deploymentLayout || !proactiveOperations || !interactionLearningProof || !liveReadModelGate || !redisDryRunGate || !learningWritebackPackage || !telegramReceiptPackage || !ownerApprovedLearningDryRun || !runtimeWriteGateReview || !postWriteVerifierPackage || !runtimeVerifierEvidenceReview || !reportAutomationReview || !reportStatusBoard || !reportRuntimeReadiness || !reportRuntimeDryRun || !reportRuntimeFixtureReadback || !runtimeWorkerShadowGate || !operationPermissionModel || !candidateOperationDryRunEvidence || !taskResultAuditTrail || !matchedPlaybookLearningGap || !criticReviewerResultCapture || !ownerApprovedResultCaptureDryRun || !ownerApprovedResultCaptureReadback || !runtimeReadbackApprovalPackage || !runtimeReadbackImplementationReview || !reportLiveDeliveryApprovalPackage || !runtimeReadbackFixtureApproval || !runtimeReadbackPromotionGate || !ownerApprovedFixturePromotionGate || !canonicalRuntimeReadbackOwnerAcceptance || !failureReceiptNoSendReplay || !reviewerQueueNoWriteReadback || !resultCaptureNoWriteReadback || !resultCapturePromotionApprovalGate || !ownerApprovedResultCapturePromotionDryRun || !resultCaptureWriteGateReview || !resultCaptureWriterImplementationReview || !resultCaptureWriterDryRunFixture || !resultCaptureWriterDryRunReadback || !resultCaptureOwnerPromotionReview || !resultCaptureOwnerApprovedExecutionRehearsal || !resultCaptureOwnerAcceptanceMaintenanceGate || !resultCaptureOwnerAcceptanceReadbackPreflightHold || !resultCaptureOwnerApprovedPreflightReleasePackage || !resultCaptureOwnerApprovedReleaseReadinessReadback || !resultCaptureOwnerReleaseApprovalGate || !resultCapturePostReleaseVerifierRollbackGate || !resultCaptureFinalReleaseCandidateReadback || !resultCaptureReleaseAuthorizationHold || !resultCaptureReleaseAuthorizationReadbackGate || !resultCaptureReleaseVerifierPreflightGate || !resultCaptureReleaseVerifierOwnerReviewPacket || !resultCaptureReleaseDecisionHold || !resultCaptureReleaseDecisionReadback || !resultCaptureReleaseDecisionNextHandoff || !reportTruthActionabilityReview || !ownerDryRunPackage || !hostStatefulInventory || !serviceHealthGapMatrix || !serviceHealthNotificationPolicy) { return (
@@ -3404,6 +3410,27 @@ export function AutomationInventoryTab() { + resultCaptureReleaseDecisionReadback.rollups.playbook_trust_write_count + resultCaptureReleaseDecisionReadback.rollups.production_write_count ) + const resultCaptureReleaseDecisionNextHandoffOverall = resultCaptureReleaseDecisionNextHandoff.program_status.overall_completion_percent + const resultCaptureReleaseDecisionNextGateHandoffs = resultCaptureReleaseDecisionNextHandoff.rollups.next_gate_handoff_count + const resultCaptureReleaseDecisionStaleActions = resultCaptureReleaseDecisionNextHandoff.rollups.stale_operator_action_count + const resultCaptureReleaseDecisionNextBlockedTransitions = resultCaptureReleaseDecisionNextHandoff.rollups.blocked_handoff_transition_count + const resultCaptureReleaseDecisionNextActions = resultCaptureReleaseDecisionNextHandoff.rollups.operator_action_count + const resultCaptureReleaseDecisionNextApprovalRequired = resultCaptureReleaseDecisionNextHandoff.rollups.approval_required_subtotal + const resultCaptureReleaseDecisionNextBlocked = resultCaptureReleaseDecisionNextHandoff.rollups.blocked_and_critical_subtotal + const resultCaptureReleaseDecisionNextLiveWrites = ( + resultCaptureReleaseDecisionNextHandoff.rollups.writer_apply_count + + resultCaptureReleaseDecisionNextHandoff.rollups.execution_apply_count + + resultCaptureReleaseDecisionNextHandoff.rollups.receipt_write_count + + resultCaptureReleaseDecisionNextHandoff.rollups.reviewer_queue_write_count + + resultCaptureReleaseDecisionNextHandoff.rollups.gateway_queue_write_count + + resultCaptureReleaseDecisionNextHandoff.rollups.telegram_send_count + + resultCaptureReleaseDecisionNextHandoff.rollups.bot_api_call_count + + resultCaptureReleaseDecisionNextHandoff.rollups.report_receipt_write_count + + resultCaptureReleaseDecisionNextHandoff.rollups.result_capture_write_count + + resultCaptureReleaseDecisionNextHandoff.rollups.learning_write_count + + resultCaptureReleaseDecisionNextHandoff.rollups.playbook_trust_write_count + + resultCaptureReleaseDecisionNextHandoff.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 @@ -8138,6 +8165,142 @@ export function AutomationInventoryTab() {
+
+
+
+ + + {t('resultCaptureReleaseDecisionNextHandoff.title')} + +
+ +
+ +
+ } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> +
+ +
+
+ {t('resultCaptureReleaseDecisionNextHandoff.priorTitle')} +

+ {resultCaptureReleaseDecisionNextHandoff.prior_release_decision_readback.readiness_note} +

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

+ {resultCaptureReleaseDecisionNextHandoff.next_handoff_truth.truth_note} +

+
+ + + + + + +
+
+
+ + {t('resultCaptureReleaseDecisionNextHandoff.handoffTitle')} +
+ {resultCaptureReleaseDecisionNextHandoff.next_gate_handoffs.slice(0, 5).map(handoff => ( +
+
+ + {handoff.display_name} + + +
+ + {handoff.handoff_summary} + +
+ + + + +
+
+ ))} +
+ +
+ {resultCaptureReleaseDecisionNextHandoff.stale_operator_action_containments.map(containment => ( +
+ {t('resultCaptureReleaseDecisionNextHandoff.containmentTitle')} + + {containment.source_action_id} + + + {containment.containment_summary} + +
+ + + +
+
+ ))} + + {resultCaptureReleaseDecisionNextHandoff.blocked_handoff_transitions.slice(0, 6).map(transition => ( +
+ {t('resultCaptureReleaseDecisionNextHandoff.blockerTitle')} + + {transition.transition_id} + + + {transition.reason} + + +
+ ))} +
+ + {t('resultCaptureReleaseDecisionNextHandoff.actionTitle')} +
+ {resultCaptureReleaseDecisionNextHandoff.operator_actions.slice(0, 5).map(action => ( +
+
+ + {action.action_id} + + +
+ + {action.operator_instruction} + +
+ + +
+
+ ))} +
+
+
diff --git a/apps/web/src/lib/api-client.ts b/apps/web/src/lib/api-client.ts index b0e7ecb6f..7ffd767e7 100644 --- a/apps/web/src/lib/api-client.ts +++ b/apps/web/src/lib/api-client.ts @@ -595,6 +595,11 @@ export const apiClient = { return handleResponse(res) }, + async getAiAgentResultCaptureReleaseDecisionNextHandoff() { + const res = await fetch(`${API_BASE_URL}/agents/agent-result-capture-release-decision-next-handoff`) + return handleResponse(res) + }, + async getAiAgentOwnerApprovedFixtureDryRun() { const res = await fetch(`${API_BASE_URL}/agents/agent-owner-approved-fixture-dry-run`) return handleResponse(res) @@ -9533,6 +9538,153 @@ export interface AiAgentResultCaptureReleaseDecisionReadbackSnapshot { } } +interface AiAgentReleaseDecisionNextHandoffZeroCounts { + owner_release_authorized_count: number + owner_release_approved_count: number + owner_review_approved_count: number + owner_decision_approved_count: number + verifier_decision_approved_count: number + maintenance_window_approved_count: number + rollback_owner_confirmed_count: number + post_release_verifier_ready_count: number + final_release_candidate_approved_count: number + final_release_candidate_pass_count: number + release_decision_pass_count: number + release_authorization_granted_count: number + release_authorization_pass_count: number + rollback_release_pass_count: number + live_apply_release_pass_count: number + writer_apply_count: number + execution_apply_count: number + receipt_write_count: number + reviewer_queue_write_count: number + gateway_queue_write_count: number + telegram_send_count: number + bot_api_call_count: number + report_receipt_write_count: number + result_capture_write_count: number + learning_write_count: number + playbook_trust_write_count: number + production_write_count: number + secret_read_count: number + destructive_operation_count: number +} + +interface AiAgentReleaseDecisionNextHandoffItem { + handoff_id: string + display_name: string + owner_agent: string + source_readback_id: string + source_task_id: string + current_task_id: string + target_next_task_id: string + handoff_status: string + handoff_mode: string + handoff_summary: string + stale_self_loop_contained: boolean + runtime_write_allowed: boolean + telegram_send_allowed: boolean + evidence_hash?: string +} + +export interface AiAgentResultCaptureReleaseDecisionNextHandoffSnapshot { + schema_version: 'ai_agent_result_capture_release_decision_next_handoff_v1' + generated_at: string + program_status: { + overall_completion_percent: number + current_priority: 'P0' | 'P1' | 'P2' | 'P3' + current_task_id: 'P2-140' + next_task_id: 'P2-141' + read_only_mode: true + runtime_authority: 'result_capture_release_decision_next_handoff_only_no_live_write' + status_note: string + } + source_refs: string[] + prior_release_decision_readback: AiAgentReleaseDecisionNextHandoffZeroCounts & { + schema_version: string + current_task_id: string + next_task_id: string + release_decision_readback_count: number + owner_decision_readback_count: number + verifier_decision_readback_count: number + rollback_decision_readback_count: number + maintenance_window_decision_readback_count: number + live_apply_decision_readback_count: number + blocked_readback_transition_count: number + operator_action_count: number + approval_required_total: number + blocked_total: number + stale_self_loop_action_count: number + readiness_note: string + } + next_handoff_truth: AiAgentReleaseDecisionNextHandoffZeroCounts & { + p2_139_release_decision_readback_loaded: boolean + next_task_id_alignment_checked: boolean + stale_self_loop_detected: boolean + stale_self_loop_contained: boolean + p2_140_next_handoff_only: boolean + operator_instruction_requires_p2_141: boolean + owner_decision_still_required: boolean + verifier_decision_still_required: boolean + rollback_decision_still_required: boolean + maintenance_window_decision_still_required: boolean + live_apply_decision_still_required: boolean + redaction_review_still_required: boolean + truth_note: string + owner_release_authorized: boolean + release_decision_passed: boolean + release_authorization_granted: boolean + gateway_queue_write_enabled: boolean + telegram_send_enabled: boolean + result_capture_write_enabled: boolean + learning_write_enabled: boolean + playbook_trust_write_enabled: boolean + production_write_enabled: boolean + } + next_gate_handoffs: AiAgentReleaseDecisionNextHandoffItem[] + stale_operator_action_containments: { + containment_id: string + source_action_id: string + source_task_id: string + expected_current_task_id: string + expected_next_task_id: string + containment_status: string + containment_summary: string + runtime_write_allowed: boolean + telegram_send_allowed: boolean + }[] + blocked_handoff_transitions: { + transition_id: string + status: string + reason: string + runtime_write_allowed: boolean + }[] + operator_actions: { + action_id: string + owner_agent: string + status: string + operator_instruction: string + runtime_write_allowed: boolean + }[] + display_redaction_contract: { + redaction_required: boolean + raw_prompt_display_allowed: boolean + private_reasoning_display_allowed: boolean + secret_value_display_allowed: boolean + raw_runtime_payload_display_allowed: boolean + internal_collaboration_content_display_allowed: boolean + frontend_display_policy: string + } + rollups: AiAgentReleaseDecisionNextHandoffZeroCounts & { + next_gate_handoff_count: number + stale_operator_action_count: number + blocked_handoff_transition_count: number + operator_action_count: number + approval_required_subtotal: number + blocked_and_critical_subtotal: 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 5172bf297..63303b37c 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -1,3 +1,29 @@ +## 2026-06-14|P2-140 釋出決策下一關交接讀回本地完成 + +**背景**:P2-139 release decision readback 已正式驗證,`program_status.next_task_id=P2-140`;但 P2-139 的 operator action 仍含 `prepare_p2_139_release_decision_readback` 自我迴圈語意。P2-140 因此不開新執行,只把下一關交接讀回固定清楚,避免操作員或 UI 把已完成 P2-139 再次當作下一步。 + +**完成內容**: +- 新增 `ai_agent_result_capture_release_decision_next_handoff_v1` schema、committed snapshot、loader 與 API endpoint `GET /api/v1/agents/agent-result-capture-release-decision-next-handoff`。 +- P2-140 snapshot 固定 5 個 next-gate handoff、1 個 stale operator action containment、6 個 blocked handoff transition 與 5 個 operator action。 +- Governance automation inventory 頁新增 P2-140 區塊,顯示 P2-140 進度 `100%`、下一關交接 `5`、舊 action 隔離 `1`、已阻擋轉換 `6`、operator action `5`、仍需批准 `12`、阻擋總數 `12`、正式寫入 / 發送 `0`。 +- P2-140 truth 固定為 `result_capture_release_decision_next_handoff_only_no_live_write`;owner release authorized、owner review approved、owner decision approved、verifier decision approved、maintenance window approved、release decision passed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API、report receipt、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive operation 仍全部維持 `0 / false`。 +- P2-140 明確把舊 `prepare_p2_139_release_decision_readback` 標記為 `contained_read_only`,真正下一步改為 `P2-141` 的 owner / verifier decision input 準備;不得回頭重跑 P2-139。 + +**本地驗證**: +- JSON parse:P2-140 schema / snapshot、`zh-TW.json`、`en.json` 通過。 +- Python 編譯:P2-140 loader 與 `agents.py` 通過。 +- API/service pytest:P2-140 與 P2-139 regression `14 passed`。 +- i18n key mirror:`11837` keys,`zh-TW.json` / `en.json` 鏡像差異 `0`,placeholder 差異 `0`。 +- Guard:`SOURCE_CONTROL_OWNER_RESPONSE_GUARD_OK`、`SECURITY_MIRROR_PROGRESS_GUARD_OK`、`DOC_SECRET_SANITY_OK scanned_files=800`、`git diff --check` 通過。 +- Web typecheck:本臨時 worktree 無 `node_modules`,`pnpm --filter @awoooi/web typecheck` 停在 `tsc: command not found`;未安裝依賴,避免增加主機負載,等待 Gitea CD 在乾淨環境跑完整前端驗證。 + +**安全邊界**: +- P2-140 仍是只讀 next handoff readback;不接受口頭批准、不把 handoff 可見解讀成 owner release authorized、不核發 release authorization、不寫 reviewer queue、不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 result capture、不寫 learning、不更新 PlayBook trust、不寫 production target、不讀 secret、不執行 destructive action、不回傳內部工作內容。 +- 本段尚未正式部署;需要 feature commit、deploy marker、production API readback 與 desktop / mobile Browser smoke 後,才可記錄正式驗證完成。 + +**下一步**: +- 推送 P2-140 feature commit,等待 Gitea CD / code-review;正式驗證通過後,才可由 `P2-141` 承接。 + ## 2026-06-14|P2-139 釋出決策讀回關卡正式驗證完成 **背景**:P2-139 release decision readback 已由 feature commit `d41b1a38` 推進,CD deploy marker `df867bd6 chore(cd): deploy d41b1a3 [skip ci]` 生效;正式站需要確認 API 與 governance UI 都讀到同一份只讀 readback,且仍沒有 reviewer queue / Gateway / Telegram / Bot API / result capture / learning / production write。 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 dcb229ff7..46b39c82d 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-139 已完成只讀證據面、runtime / report / result-capture gates、no-write readback、promotion review、writer implementation review、writer dry-run fixture、writer dry-run readback、owner promotion execution gate、owner-approved execution rehearsal、owner acceptance / maintenance window gate、owner acceptance readback / preflight hold、owner-approved preflight release package、owner-approved release readiness readback、owner release approval gate、post-release verifier / rollback gate、final release candidate readback、release authorization hold / readback gate、release verifier preflight / owner review packet、release decision hold 與 release decision readback;P2-139 已正式驗證,固定 5 個 release decision readback、5 個 owner decision readback、5 個 verifier decision readback、5 個 rollback decision readback、5 個 maintenance window decision readback、5 個 live-apply decision readback、6 個 blocked readback transition 與 5 個 operator action。runtime worker、DB migration、production Redis consumer group、canonical runtime readback、live query、runtime score、result capture write、Telegram 實發、delivery receipt E2E、live report delivery、reviewer queue write、Gateway queue write、AI analysis runtime、中低風險 auto worker、KM / LOGBOOK / audit DB / timeline / PlayBook trust 寫入、SDK / 付費服務仍未開 gate | `ai_agent_result_capture_release_decision_readback_v1`、`GET /api/v1/agents/agent-result-capture-release-decision-readback`、feature commit `d41b1a38`、deploy marker `df867bd6`、P2-139 正式 API readback、desktop / mobile smoke、P2-139 API/service pytest `7 passed`、JSON parse、Python compile、i18n key mirror `11809`、治理頁 P2-139 區塊、禁用內部協作片語 `0`、水平溢位 `0`、危險控制 `0`、console error `0`、HTTP 4xx/5xx `0`;`ai_agent_result_capture_release_decision_hold_v1`、`GET /api/v1/agents/agent-result-capture-release-decision-hold`、deploy marker `bfd26e76`、正式 API readback、desktop / mobile smoke、MASTER §3.2.1b / §3.2.1d / §3.4.3 | +| OpenClaw / Hermes / NemoTron 主動溝通、學習與成長證據 | 100% | P2-401A 到 P2-140 已完成只讀證據面、runtime / report / result-capture gates、no-write readback、promotion review、writer implementation review、writer dry-run fixture、writer dry-run readback、owner promotion execution gate、owner-approved execution rehearsal、owner acceptance / maintenance window gate、owner acceptance readback / preflight hold、owner-approved preflight release package、owner-approved release readiness readback、owner release approval gate、post-release verifier / rollback gate、final release candidate readback、release authorization hold / readback gate、release verifier preflight / owner review packet、release decision hold / readback 與 release decision next handoff;P2-140 已本地完成,固定 5 個 next-gate handoff、1 個 stale operator action containment、6 個 blocked handoff transition 與 5 個 operator action,並隔離 P2-139 自我迴圈。runtime worker、DB migration、production Redis consumer group、canonical runtime readback、live query、runtime score、result capture write、Telegram 實發、delivery receipt E2E、live report delivery、reviewer queue write、Gateway queue write、AI analysis runtime、中低風險 auto worker、KM / LOGBOOK / audit DB / timeline / PlayBook trust 寫入、SDK / 付費服務仍未開 gate | `ai_agent_result_capture_release_decision_next_handoff_v1`、`GET /api/v1/agents/agent-result-capture-release-decision-next-handoff`、P2-140 本地 schema / snapshot / loader / API / governance UI;P2-139 正式 API readback、desktop / mobile smoke、feature commit `d41b1a38`、deploy marker `df867bd6`;P2-140 仍需 feature commit、Gitea CD、production API readback 與 desktop / mobile smoke;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 文件 | @@ -103,13 +103,22 @@ - Browser smoke 已完成:desktop `1440x1000` 與 mobile `390x844` 均確認 P2-139 區塊、`P2-140`、所有 readback count、`Gateway 寫入=0`、`Telegram 送出=0`、正式寫入 / 發送 `0` 可見;水平溢位 `0`、overflowing element `0`、P2-139 卡片危險控制 `0`、console error `0`、HTTP 4xx/5xx `0`、禁用內部協作片語與敏感欄位命中 `0`。 - P2-139 已可由 `P2-140` 承接;仍不得直接開啟 result capture writer、learning writer、PlayBook trust writer、reviewer queue write、Gateway queue write、Telegram send、Bot API call 或 production write。 +### 2026-06-14 12:17 狀態同步 + +- `P2-140` release decision next handoff 已本地完成:新增 `ai_agent_result_capture_release_decision_next_handoff_v1`、`GET /api/v1/agents/agent-result-capture-release-decision-next-handoff`、治理頁 P2-140 區塊與繁中 UI 文案。 +- P2-140 只讀回 P2-139 的 next handoff,將舊 `prepare_p2_139_release_decision_readback` 自我迴圈標為 `contained_read_only`,並把真正下一步固定為 `P2-141`。 +- P2-140 固定 5 個 next-gate handoff、1 個 stale operator action containment、6 個 blocked handoff transition、5 個 operator action、仍需批准 `12`、阻擋總數 `12`、正式寫入 / 發送 `0`。 +- 本地證據:P2-140 + P2-139 API/service regression `14 passed`、JSON parse、Python compile、i18n key mirror `11837`、guard 與 doc secret sanity 通過;本臨時 worktree 無 `node_modules`,Web typecheck 需由 Gitea CD 乾淨環境驗證。 +- 邊界仍維持:owner release authorized、owner review approved、owner decision approved、verifier decision approved、maintenance window approved、release decision passed、release authorization granted / passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API、report receipt、result capture write、learning write、PlayBook trust write、production write、secret read、destructive operation 全部 `0 / false`。 +- P2-140 推送與正式驗證後才可交給 `P2-141`;仍不得直接開啟 runtime writer、Gateway queue、Telegram send、Bot API call 或 production write。 + AI Agent 自動化工作包目前完成度:**99.8%**。本工作清單文件本身完成度:**100%**。 三 Agent 佈建布局目前完成度:**45%**。第一波已完成只讀 schema / snapshot / API / 測試 / 報告,第二波已接入治理頁自動化盤點 UI;正式 runtime 佈署、Telegram E2E 發送與 AgentSession 工作流仍需逐項 gate。 -三 Agent 主動溝通、學習與成長證據目前完成度:**100%**。P2-403A 到 P2-139 已把互動證據、報表治理、runtime readback、reviewer / result capture / writer gates、no-write readback、promotion review、writer implementation review、writer dry-run fixture、writer dry-run readback、owner promotion execution gate、owner-approved execution rehearsal、owner acceptance / maintenance window gate、owner acceptance readback / preflight hold、owner-approved preflight release package、owner-approved release readiness readback、owner release approval gate、post-release verifier / rollback gate、final release candidate readback、release authorization hold、release authorization readback gate、release verifier preflight gate、release verifier owner review packet、release decision hold 與 release decision readback 固定成可驗證證據。P2-139 已由 feature commit `d41b1a38` 與 deploy marker `df867bd6` 正式驗證;P2-138 最新寫入邊界補強也已正式驗證,deploy marker `923fb117`。目前 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-140`,仍只能接續只讀關卡,不得開啟 runtime writer、Gateway queue、Telegram send、Bot API 或 production write。 +三 Agent 主動溝通、學習與成長證據目前完成度:**100%**。P2-403A 到 P2-140 已把互動證據、報表治理、runtime readback、reviewer / result capture / writer gates、no-write readback、promotion review、writer implementation review、writer dry-run fixture、writer dry-run readback、owner promotion execution gate、owner-approved execution rehearsal、owner acceptance / maintenance window gate、owner acceptance readback / preflight hold、owner-approved preflight release package、owner-approved release readiness readback、owner release approval gate、post-release verifier / rollback gate、final release candidate readback、release authorization hold、release authorization readback gate、release verifier preflight gate、release verifier owner review packet、release decision hold、release decision readback 與 release decision next handoff 固定成可驗證證據。P2-139 已由 feature commit `d41b1a38` 與 deploy marker `df867bd6` 正式驗證;P2-140 已本地完成,正在等待 feature commit / Gitea CD / production smoke。P2-138 最新寫入邊界補強也已正式驗證,deploy marker `923fb117`。目前 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-141`,仍只能接續只讀關卡,不得開啟 runtime writer、Gateway queue、Telegram send、Bot API 或 production write。 -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-139` 已補互動、學習證據面、live read model gate、Redis dry-run gate、learning writeback approval package、Telegram receipt approval package、owner-approved learning dry-run preview、runtime write gate review、post-write verifier package、runtime verifier evidence review、報表真相、TG 戰情室收斂、日週月報、Agent 工作量、圖表化報告、風險自動化政策、報表 runtime 啟動前閘門、no-write dry-run 證據包、fixture/readback/verifier dry-run 證據包、shadow/no-write execution gate、操作類別權限模型、13 類候選操作 dry-run 證據、任務結果稽核軌跡、matched PlayBook 學習缺口、critic / reviewer result capture、owner-approved result capture dry-run / readback、result capture writer dry-run fixture、writer dry-run readback、owner promotion execution gate、owner-approved execution rehearsal、owner acceptance / maintenance window gate、owner acceptance readback / preflight hold、owner-approved preflight release package、owner-approved release readiness readback、owner release approval gate、post-release verifier / rollback gate、final release candidate readback、release authorization hold、release authorization readback gate、release verifier preflight gate、release verifier owner review packet、release decision hold 與 release decision readback。下一步是 P2-140;外部 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-140` 已補互動、學習證據面、live read model gate、Redis dry-run gate、learning writeback approval package、Telegram receipt approval package、owner-approved learning dry-run preview、runtime write gate review、post-write verifier package、runtime verifier evidence review、報表真相、TG 戰情室收斂、日週月報、Agent 工作量、圖表化報告、風險自動化政策、報表 runtime 啟動前閘門、no-write dry-run 證據包、fixture/readback/verifier dry-run 證據包、shadow/no-write execution gate、操作類別權限模型、13 類候選操作 dry-run 證據、任務結果稽核軌跡、matched PlayBook 學習缺口、critic / reviewer result capture、owner-approved result capture dry-run / readback、result capture writer dry-run fixture、writer dry-run readback、owner promotion execution gate、owner-approved execution rehearsal、owner acceptance / maintenance window gate、owner acceptance readback / preflight hold、owner-approved preflight release package、owner-approved release readiness readback、owner release approval gate、post-release verifier / rollback gate、final release candidate readback、release authorization hold、release authorization readback gate、release verifier preflight gate、release verifier owner review packet、release decision hold、release decision readback 與 next handoff readback。下一步是 P2-141;外部 registry / package source / host probe / SSH / kubectl / 工具安裝 / CI 變更 / 實際 PR creation / Telegram 實發與 learning write 仍需 gate。 完成度計算模型: @@ -1098,7 +1107,8 @@ UI: | P2-136 | 完成 | 100 | OpenClaw + Hermes + NemoTron | release verifier preflight gate | `ai_agent_result_capture_release_verifier_preflight_gate_v1` / schema / snapshot / 只讀 API / governance UI;feature commit `913d7f68`、deploy marker `f2fa8454` 已正式驗證;5 個 release verifier preflight、5 個 rollback verifier preflight、5 個 maintenance window verifier hold、5 個 live-apply verifier hold、6 個 blocked verifier preflight transition、5 個 operator action;需批准 `8`、blocked status subtotal `4`、critical blocker `5`、前端顯示阻擋總數 `9`;runtime authority 固定 `result_capture_release_verifier_preflight_gate_only_no_live_write`;post-release verifier ready、release authorization granted / passed、rollback release、live apply release、writer apply、execution apply、receipt write、result capture、learning、PlayBook trust、Gateway、Telegram、production write、secret read、destructive operation 全為 `0` | production API readback、desktop / mobile smoke、禁用內部協作片語 `0`、水平溢位 `0`、危險控制 `0`、console error `0`;已由 P2-137 承接,不把 verifier preflight 視為 post-release verifier ready、不核發 release authorization、不釋放 live apply、不套用 writer | | P2-137 | 完成 | 100 | OpenClaw + Hermes + NemoTron | release verifier owner review packet | `ai_agent_result_capture_release_verifier_owner_review_packet_v1` / schema / snapshot / 只讀 API / governance UI;feature commit `f737f278`、deploy marker `d023f5d7` 已正式驗證;5 個 owner review packet、5 個 verifier review packet、5 個 rollback owner review packet、5 個 maintenance window review hold、5 個 live-apply owner review hold、6 個 blocked owner review transition、5 個 operator action;需批准 `10`、阻擋 `10`;runtime authority 固定 `result_capture_release_verifier_owner_review_packet_only_no_live_write`;owner release authorized / owner review approved / maintenance window approved / rollback owner confirmed / post-release verifier ready / release authorization granted / release authorization passed / rollback release / live apply release / writer apply / execution apply / receipt write / result capture / learning / PlayBook trust / reviewer queue / Gateway / Telegram / Bot API / production write / secret read / destructive operation 全為 `0` | 本地 pytest `7 passed`、JSON parse、Python compile、Web typecheck 通過;production API readback、desktop / mobile smoke、水平溢位 `0`、P2-137 卡片危險控制 `0`、console error `0`、HTTP 4xx/5xx `0`;已由 P2-138 承接 | | P2-138 | 完成 | 100 | OpenClaw + Hermes + NemoTron | release decision hold | `ai_agent_result_capture_release_decision_hold_v1` / schema / snapshot / 只讀 API / governance UI;feature commit `655df33d` 與 maintenance window 補強 commit `1ae67f1f` 已由 deploy marker `bfd26e76` 正式驗證;承接 P2-137,只建立 5 個 release decision hold、5 個 owner decision hold、5 個 verifier decision hold、5 個 rollback decision hold、5 個 maintenance window decision hold、5 個 live-apply decision hold、6 個 blocked decision transition、5 個 operator action;需批准 `12`、阻擋 `12`;runtime authority 固定 `result_capture_release_decision_hold_only_no_live_write`;owner release authorized / owner review approved / owner decision approved / verifier decision approved / maintenance window approved / release decision passed / release authorization granted / passed / rollback release / live apply release / writer apply / execution apply / receipt write / reviewer queue / Gateway / Telegram / Bot API / result capture / learning / PlayBook trust / production write / secret read / destructive operation 全為 `0` | 本地 P2-138 + P2-137 pytest `15 passed`、JSON parse、Python compile、i18n key mirror `11777`、Web typecheck 與 Web production build 通過;production API readback、desktop / mobile smoke、水平溢位 `0`、P2-138 卡片危險控制 `0`、console / page error `0`、HTTP 4xx/5xx `0`;不得把 P2-138 當 runtime gate,已由 P2-139 承接 | -| P2-139 | 本地完成 | 100 | OpenClaw + Hermes + NemoTron | release decision readback | `ai_agent_result_capture_release_decision_readback_v1` / schema / snapshot / 只讀 API / governance UI;承接 P2-138,只讀回 5 個 release decision readback、5 個 owner decision readback、5 個 verifier decision readback、5 個 rollback decision readback、5 個 maintenance window decision readback、5 個 live-apply decision readback、6 個 blocked readback transition、5 個 operator action;需批准 `12`、阻擋 `12`;runtime authority 固定 `result_capture_release_decision_readback_only_no_live_write`;owner release authorized / owner review approved / owner decision approved / verifier decision approved / maintenance window approved / release decision passed / release authorization granted / passed / rollback release / live apply release / writer apply / execution apply / receipt write / reviewer queue / Gateway / Telegram / Bot API / result capture / learning / PlayBook trust / production write / secret read / destructive operation 全為 `0` | 本地 P2-139 API/service pytest `7 passed`、JSON parse、Python compile、i18n key mirror `11809` 通過;本臨時 worktree 無 `node_modules`,Web typecheck 等 Gitea CD 驗證;不得把 P2-139 當 runtime gate,正式部署驗證後才可由 P2-140 承接 | +| P2-139 | 完成 | 100 | OpenClaw + Hermes + NemoTron | release decision readback | `ai_agent_result_capture_release_decision_readback_v1` / schema / snapshot / 只讀 API / governance UI;feature commit `d41b1a38`、deploy marker `df867bd6` 已正式驗證;承接 P2-138,只讀回 5 個 release decision readback、5 個 owner decision readback、5 個 verifier decision readback、5 個 rollback decision readback、5 個 maintenance window decision readback、5 個 live-apply decision readback、6 個 blocked readback transition、5 個 operator action;需批准 `12`、阻擋 `12`;runtime authority 固定 `result_capture_release_decision_readback_only_no_live_write`;owner release authorized / owner review approved / owner decision approved / verifier decision approved / maintenance window approved / release decision passed / release authorization granted / passed / rollback release / live apply release / writer apply / execution apply / receipt write / reviewer queue / Gateway / Telegram / Bot API / result capture / learning / PlayBook trust / production write / secret read / destructive operation 全為 `0` | 本地 P2-139 API/service pytest `7 passed`、JSON parse、Python compile、i18n key mirror `11809` 通過;production API readback、desktop / mobile smoke、水平溢位 `0`、P2-139 卡片危險控制 `0`、console error `0`、HTTP 4xx/5xx `0`;不得把 P2-139 當 runtime gate,已可由 P2-140 承接 | +| P2-140 | 本地完成 | 100 | OpenClaw + Hermes + NemoTron | release decision next handoff readback | `ai_agent_result_capture_release_decision_next_handoff_v1` / schema / snapshot / 只讀 API / governance UI;承接 P2-139,只讀回下一關交接並隔離 P2-139 自我迴圈;固定 5 個 next-gate handoff、1 個 stale operator action containment、6 個 blocked handoff transition、5 個 operator action;需批准 `12`、阻擋 `12`;runtime authority 固定 `result_capture_release_decision_next_handoff_only_no_live_write`;owner release authorized / owner review approved / owner decision approved / verifier decision approved / maintenance window approved / release decision passed / release authorization granted / passed / rollback release / live apply release / writer apply / execution apply / receipt write / reviewer queue / Gateway / Telegram / Bot API / result capture / learning / PlayBook trust / production write / secret read / destructive operation 全為 `0` | 本地 P2-140 + P2-139 API/service regression `14 passed`、JSON parse、Python compile、i18n key mirror `11837`、guard 與 doc secret sanity 通過;本臨時 worktree 無 `node_modules`,Web typecheck 交由 Gitea CD;正式站仍需 Gitea code-review / CD、production API readback、desktop / mobile smoke;不得把 P2-140 當 runtime gate,正式驗證後才可由 P2-141 承接 | ### P3 - 候選 Agent 擴展 diff --git a/docs/evaluations/ai_agent_result_capture_release_decision_next_handoff_2026-06-14.json b/docs/evaluations/ai_agent_result_capture_release_decision_next_handoff_2026-06-14.json new file mode 100644 index 000000000..4af56d87c --- /dev/null +++ b/docs/evaluations/ai_agent_result_capture_release_decision_next_handoff_2026-06-14.json @@ -0,0 +1,353 @@ +{ + "schema_version": "ai_agent_result_capture_release_decision_next_handoff_v1", + "generated_at": "2026-06-14T12:08:00+08:00", + "program_status": { + "overall_completion_percent": 100, + "current_priority": "P2", + "current_task_id": "P2-140", + "next_task_id": "P2-141", + "read_only_mode": true, + "runtime_authority": "result_capture_release_decision_next_handoff_only_no_live_write", + "status_note": "P2-140 只讀回 P2-139 release decision readback 的下一關交接;隔離 prepare_p2_139 自我迴圈,確認操作員只能往 P2-141 準備,不得寫 reviewer / Gateway queue、送 Telegram、呼叫 Bot API、寫 result capture、learning、PlayBook trust 或 production target。" + }, + "source_refs": [ + "docs/evaluations/ai_agent_result_capture_release_decision_readback_2026-06-14.json", + "docs/evaluations/ai_agent_result_capture_release_decision_hold_2026-06-14.json", + "docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md#60-建立-release-decision-readback" + ], + "prior_release_decision_readback": { + "schema_version": "ai_agent_result_capture_release_decision_readback_v1", + "current_task_id": "P2-139", + "next_task_id": "P2-140", + "release_decision_readback_count": 5, + "owner_decision_readback_count": 5, + "verifier_decision_readback_count": 5, + "rollback_decision_readback_count": 5, + "maintenance_window_decision_readback_count": 5, + "live_apply_decision_readback_count": 5, + "blocked_readback_transition_count": 6, + "operator_action_count": 5, + "approval_required_total": 12, + "blocked_total": 12, + "stale_self_loop_action_count": 1, + "readiness_note": "P2-139 readback 已正式驗證且 next_task_id=P2-140;但 operator action 仍有 prepare_p2_139 自我迴圈,P2-140 僅隔離與讀回此 handoff 缺口,不放行任何 runtime 寫入。", + "owner_release_authorized_count": 0, + "owner_release_approved_count": 0, + "owner_review_approved_count": 0, + "owner_decision_approved_count": 0, + "verifier_decision_approved_count": 0, + "maintenance_window_approved_count": 0, + "rollback_owner_confirmed_count": 0, + "post_release_verifier_ready_count": 0, + "final_release_candidate_approved_count": 0, + "final_release_candidate_pass_count": 0, + "release_decision_pass_count": 0, + "release_authorization_granted_count": 0, + "release_authorization_pass_count": 0, + "rollback_release_pass_count": 0, + "live_apply_release_pass_count": 0, + "writer_apply_count": 0, + "execution_apply_count": 0, + "receipt_write_count": 0, + "reviewer_queue_write_count": 0, + "gateway_queue_write_count": 0, + "telegram_send_count": 0, + "bot_api_call_count": 0, + "report_receipt_write_count": 0, + "result_capture_write_count": 0, + "learning_write_count": 0, + "playbook_trust_write_count": 0, + "production_write_count": 0, + "secret_read_count": 0, + "destructive_operation_count": 0 + }, + "next_handoff_truth": { + "p2_139_release_decision_readback_loaded": true, + "next_task_id_alignment_checked": true, + "stale_self_loop_detected": true, + "stale_self_loop_contained": true, + "p2_140_next_handoff_only": true, + "operator_instruction_requires_p2_141": true, + "owner_decision_still_required": true, + "verifier_decision_still_required": true, + "rollback_decision_still_required": true, + "maintenance_window_decision_still_required": true, + "live_apply_decision_still_required": true, + "redaction_review_still_required": true, + "truth_note": "P2-140 只把 P2-139 的 next handoff 固定清楚:已完成的 P2-139 不可再作為下一步;P2-141 仍只能準備 owner/verifier 決策資料,不可直接寫 queue、送 Telegram 或套用 production。", + "owner_release_authorized": false, + "owner_release_approved": false, + "owner_review_approved": false, + "owner_decision_approved": false, + "verifier_decision_approved": false, + "maintenance_window_approved": false, + "rollback_owner_confirmed": false, + "post_release_verifier_ready": false, + "final_release_candidate_approved": false, + "final_release_candidate_passed": false, + "release_decision_passed": false, + "release_authorization_granted": false, + "release_authorization_passed": false, + "rollback_release_passed": false, + "live_apply_release_passed": false, + "writer_apply_enabled": false, + "execution_apply_enabled": false, + "receipt_write_enabled": false, + "reviewer_queue_write_enabled": false, + "gateway_queue_write_enabled": false, + "telegram_send_enabled": false, + "bot_api_call_enabled": false, + "report_receipt_write_enabled": false, + "result_capture_write_enabled": false, + "learning_write_enabled": false, + "playbook_trust_write_enabled": false, + "production_write_enabled": false, + "secret_read_enabled": false, + "destructive_operation_enabled": false, + "owner_release_authorized_count": 0, + "owner_release_approved_count": 0, + "owner_review_approved_count": 0, + "owner_decision_approved_count": 0, + "verifier_decision_approved_count": 0, + "maintenance_window_approved_count": 0, + "rollback_owner_confirmed_count": 0, + "post_release_verifier_ready_count": 0, + "final_release_candidate_approved_count": 0, + "final_release_candidate_pass_count": 0, + "release_decision_pass_count": 0, + "release_authorization_granted_count": 0, + "release_authorization_pass_count": 0, + "rollback_release_pass_count": 0, + "live_apply_release_pass_count": 0, + "writer_apply_count": 0, + "execution_apply_count": 0, + "receipt_write_count": 0, + "reviewer_queue_write_count": 0, + "gateway_queue_write_count": 0, + "telegram_send_count": 0, + "bot_api_call_count": 0, + "report_receipt_write_count": 0, + "result_capture_write_count": 0, + "learning_write_count": 0, + "playbook_trust_write_count": 0, + "production_write_count": 0, + "secret_read_count": 0, + "destructive_operation_count": 0 + }, + "next_gate_handoffs": [ + { + "handoff_id": "next_gate_handoff_result_capture", + "display_name": "Result capture 下一關交接", + "owner_agent": "openclaw", + "source_readback_id": "release_decision_readback_result_capture", + "source_task_id": "P2-139", + "current_task_id": "P2-140", + "target_next_task_id": "P2-141", + "handoff_status": "ready_for_operator_review", + "handoff_mode": "next_gate_readback", + "handoff_summary": "Result capture 只能把 P2-139 readback 交接到 P2-141 準備資料,不得回到 P2-139 或直接開寫入。", + "stale_self_loop_contained": true, + "runtime_write_allowed": false, + "telegram_send_allowed": false, + "evidence_hash": "sha256:d16d187690fc0f91eaaf56c2f5923b8cd4c1d61d16cecb4ec7e049f2237ca64a" + }, + { + "handoff_id": "next_gate_handoff_learning", + "display_name": "Learning 下一關交接", + "owner_agent": "hermes", + "source_readback_id": "release_decision_readback_learning", + "source_task_id": "P2-139", + "current_task_id": "P2-140", + "target_next_task_id": "P2-141", + "handoff_status": "ready_for_operator_review", + "handoff_mode": "next_gate_readback", + "handoff_summary": "Learning 只能把 P2-139 readback 交接到 P2-141 準備資料,不得回到 P2-139 或直接開寫入。", + "stale_self_loop_contained": false, + "runtime_write_allowed": false, + "telegram_send_allowed": false, + "evidence_hash": "sha256:7c9f4c2d49be51cf6b386e4a40c0b7c2c6d464d235e89637b84c87322e3cc520" + }, + { + "handoff_id": "next_gate_handoff_playbook_trust", + "display_name": "PlayBook trust 下一關交接", + "owner_agent": "hermes", + "source_readback_id": "release_decision_readback_playbook_trust", + "source_task_id": "P2-139", + "current_task_id": "P2-140", + "target_next_task_id": "P2-141", + "handoff_status": "ready_for_operator_review", + "handoff_mode": "next_gate_readback", + "handoff_summary": "PlayBook trust 只能把 P2-139 readback 交接到 P2-141 準備資料,不得回到 P2-139 或直接開寫入。", + "stale_self_loop_contained": false, + "runtime_write_allowed": false, + "telegram_send_allowed": false, + "evidence_hash": "sha256:9191716bc4435146247acb4d9db21b2e3f5d5c0298aff4f349ea73e3db65b7bc" + }, + { + "handoff_id": "next_gate_handoff_reviewer_queue", + "display_name": "Reviewer queue 下一關交接", + "owner_agent": "openclaw", + "source_readback_id": "release_decision_readback_reviewer_queue", + "source_task_id": "P2-139", + "current_task_id": "P2-140", + "target_next_task_id": "P2-141", + "handoff_status": "ready_for_operator_review", + "handoff_mode": "next_gate_readback", + "handoff_summary": "Reviewer queue 只能把 P2-139 readback 交接到 P2-141 準備資料,不得回到 P2-139 或直接開寫入。", + "stale_self_loop_contained": false, + "runtime_write_allowed": false, + "telegram_send_allowed": false, + "evidence_hash": "sha256:390d52b679a40fa3b52ce1ab5a71b0cad8a4aca81565fb26571c4719fe540ec8" + }, + { + "handoff_id": "next_gate_handoff_gateway_queue", + "display_name": "Gateway queue 下一關交接", + "owner_agent": "openclaw", + "source_readback_id": "release_decision_readback_gateway_queue", + "source_task_id": "P2-139", + "current_task_id": "P2-140", + "target_next_task_id": "P2-141", + "handoff_status": "ready_for_operator_review", + "handoff_mode": "next_gate_readback", + "handoff_summary": "Gateway queue 只能把 P2-139 readback 交接到 P2-141 準備資料,不得回到 P2-139 或直接開寫入。", + "stale_self_loop_contained": false, + "runtime_write_allowed": false, + "telegram_send_allowed": false, + "evidence_hash": "sha256:6c4129546c6fc9466a78dbb2a6689708eff260d3c6bc003b3191d9540504dafb" + } + ], + "stale_operator_action_containments": [ + { + "containment_id": "contain_prepare_p2_139_release_decision_readback_self_loop", + "source_action_id": "prepare_p2_139_release_decision_readback", + "source_task_id": "P2-139", + "expected_current_task_id": "P2-140", + "expected_next_task_id": "P2-141", + "containment_status": "contained_read_only", + "containment_summary": "P2-139 operator action 仍指向 prepare_p2_139;P2-140 將它標示為已隔離自我迴圈,避免操作員重跑已完成關卡。", + "runtime_write_allowed": false, + "telegram_send_allowed": false + } + ], + "blocked_handoff_transitions": [ + { + "transition_id": "blocked_return_to_p2_139", + "status": "blocked_by_policy", + "reason": "P2-139 已完成正式驗證,下一步不得回到 release decision readback 自我迴圈。", + "runtime_write_allowed": false + }, + { + "transition_id": "blocked_release_authorization_without_owner_decision", + "status": "approval_required", + "reason": "owner / verifier / maintenance / rollback / live apply decision 仍未通過,不得核發 release authorization。", + "runtime_write_allowed": false + }, + { + "transition_id": "blocked_reviewer_queue_write_from_handoff", + "status": "blocked_by_policy", + "reason": "handoff readback 不是 reviewer queue write approval。", + "runtime_write_allowed": false + }, + { + "transition_id": "blocked_gateway_queue_write_from_handoff", + "status": "blocked_by_policy", + "reason": "handoff readback 不是 Gateway queue write approval。", + "runtime_write_allowed": false + }, + { + "transition_id": "blocked_telegram_send_from_handoff", + "status": "blocked_by_policy", + "reason": "Telegram send 未授權,不得發送 handoff 或 release decision 通知。", + "runtime_write_allowed": false + }, + { + "transition_id": "blocked_result_capture_write_from_handoff", + "status": "blocked_by_policy", + "reason": "result capture write 未授權,handoff 只能留在只讀證據層。", + "runtime_write_allowed": false + } + ], + "operator_actions": [ + { + "action_id": "review_next_handoff_alignment", + "owner_agent": "openclaw", + "status": "ready_for_operator_review", + "operator_instruction": "確認 P2-139 next_task_id=P2-140,並使用本 P2-140 handoff 取代舊的自我迴圈提示。", + "runtime_write_allowed": false + }, + { + "action_id": "contain_stale_p2_139_self_loop", + "owner_agent": "openclaw", + "status": "ready_for_operator_review", + "operator_instruction": "將 prepare_p2_139_release_decision_readback 視為已隔離,不再當作下一步操作。", + "runtime_write_allowed": false + }, + { + "action_id": "prepare_p2_141_owner_decision_inputs", + "owner_agent": "hermes", + "status": "approval_required", + "operator_instruction": "下一關只能準備 P2-141 owner / verifier / maintenance / rollback 決策輸入,不得核發 release authorization。", + "runtime_write_allowed": false + }, + { + "action_id": "verify_queue_send_write_closed", + "owner_agent": "openclaw", + "status": "ready_for_operator_review", + "operator_instruction": "確認 reviewer queue、Gateway queue、Telegram、Bot API、result capture、learning 與 production write 仍全部為 0。", + "runtime_write_allowed": false + }, + { + "action_id": "document_next_handoff_boundary", + "owner_agent": "hermes", + "status": "ready_for_operator_review", + "operator_instruction": "同步治理文件的 P2-140 下一關交接邊界;不得送 Telegram 或寫入 production。", + "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": "前端只能顯示 P2-140 handoff 摘要、狀態、數量、redacted hash 與 0 / false 邊界;不得顯示內部協作對話、原始提示詞、私有推理、secret、authorization header 或原始 runtime payload。" + }, + "rollups": { + "next_gate_handoff_count": 5, + "stale_operator_action_count": 1, + "blocked_handoff_transition_count": 6, + "operator_action_count": 5, + "approval_required_subtotal": 12, + "blocked_and_critical_subtotal": 12, + "owner_release_authorized_count": 0, + "owner_release_approved_count": 0, + "owner_review_approved_count": 0, + "owner_decision_approved_count": 0, + "verifier_decision_approved_count": 0, + "maintenance_window_approved_count": 0, + "rollback_owner_confirmed_count": 0, + "post_release_verifier_ready_count": 0, + "final_release_candidate_approved_count": 0, + "final_release_candidate_pass_count": 0, + "release_decision_pass_count": 0, + "release_authorization_granted_count": 0, + "release_authorization_pass_count": 0, + "rollback_release_pass_count": 0, + "live_apply_release_pass_count": 0, + "writer_apply_count": 0, + "execution_apply_count": 0, + "receipt_write_count": 0, + "reviewer_queue_write_count": 0, + "gateway_queue_write_count": 0, + "telegram_send_count": 0, + "bot_api_call_count": 0, + "report_receipt_write_count": 0, + "result_capture_write_count": 0, + "learning_write_count": 0, + "playbook_trust_write_count": 0, + "production_write_count": 0, + "secret_read_count": 0, + "destructive_operation_count": 0 + } +} diff --git a/docs/schemas/ai_agent_result_capture_release_decision_next_handoff_v1.schema.json b/docs/schemas/ai_agent_result_capture_release_decision_next_handoff_v1.schema.json new file mode 100644 index 000000000..9caa6c590 --- /dev/null +++ b/docs/schemas/ai_agent_result_capture_release_decision_next_handoff_v1.schema.json @@ -0,0 +1,82 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://awoooi.wooo.work/schemas/ai_agent_result_capture_release_decision_next_handoff_v1.schema.json", + "title": "AI Agent result capture release decision next handoff v1", + "type": "object", + "required": [ + "schema_version", + "generated_at", + "program_status", + "source_refs", + "prior_release_decision_readback", + "next_handoff_truth", + "next_gate_handoffs", + "stale_operator_action_containments", + "blocked_handoff_transitions", + "operator_actions", + "display_redaction_contract", + "rollups" + ], + "properties": { + "schema_version": { + "const": "ai_agent_result_capture_release_decision_next_handoff_v1" + }, + "generated_at": { + "type": "string" + }, + "program_status": { + "type": "object" + }, + "source_refs": { + "type": "array", + "items": { + "type": "string" + } + }, + "prior_release_decision_readback": { + "type": "object" + }, + "next_handoff_truth": { + "type": "object" + }, + "next_gate_handoffs": { + "type": "array", + "minItems": 5, + "maxItems": 5, + "items": { + "type": "object" + } + }, + "stale_operator_action_containments": { + "type": "array", + "minItems": 1, + "maxItems": 1, + "items": { + "type": "object" + } + }, + "blocked_handoff_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 c824df354..f5d5dbcde 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 @@ -677,6 +677,7 @@ Alert / Sentry / SigNoz / Gitea / Market Watch / Operator | `docs/evaluations/ai_agent_result_capture_release_verifier_owner_review_packet_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-release-verifier-owner-review-packet` | P2-137 release verifier owner review packet;承接 P2-136 release verifier preflight gate,建立 5 個 owner review packet、5 個 verifier review packet、5 個 rollback owner review packet、5 個 maintenance window review hold、5 個 live-apply owner review hold、6 個 blocked owner review transition 與 5 個 operator action;runtime authority 固定 `result_capture_release_verifier_owner_review_packet_only_no_live_write`;owner release authorized、owner review approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、canonical runtime target read、live query、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive action 全部 `0 / false`;deploy marker `d023f5d7` 已正式驗證,正式 API readback 與 desktop / mobile smoke 已完成,下一步 P2-138 release decision hold | | `docs/evaluations/ai_agent_result_capture_release_decision_hold_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-release-decision-hold` | P2-138 release decision hold;承接 P2-137 release verifier owner review packet,建立 5 個 release decision hold、5 個 owner decision hold、5 個 verifier decision hold、5 個 rollback decision hold、5 個 maintenance window decision hold、5 個 live-apply decision hold、6 個 blocked decision transition 與 5 個 operator action;runtime authority 固定 `result_capture_release_decision_hold_only_no_live_write`;owner release authorized、owner review approved、owner decision approved、verifier decision approved、maintenance window approved、release decision passed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、canonical runtime target read、live query、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive action 全部 `0 / false`;feature commit `655df33d` 與 maintenance window 補強 commit `1ae67f1f` 已由 deploy marker `bfd26e76` 正式驗證,正式 API readback 與 desktop / mobile smoke 已完成,下一步 P2-139 release decision readback | | `docs/evaluations/ai_agent_result_capture_release_decision_readback_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-release-decision-readback` | P2-139 release decision readback;承接 P2-138 release decision hold,建立 5 個 release decision readback、5 個 owner decision readback、5 個 verifier decision readback、5 個 rollback decision readback、5 個 maintenance window decision readback、5 個 live-apply decision readback、6 個 blocked readback transition 與 5 個 operator action;runtime authority 固定 `result_capture_release_decision_readback_only_no_live_write`;owner release authorized、owner review approved、owner decision approved、verifier decision approved、maintenance window approved、release decision passed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、canonical runtime target read、live query、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive action 全部 `0 / false`;feature commit `d41b1a38`、deploy marker `df867bd6`、正式 API readback、desktop / mobile smoke、禁用內部協作片語 `0`、水平溢位 `0`、危險控制 `0`、console error `0`、HTTP 4xx/5xx `0` 已完成,下一步 P2-140 | +| `docs/evaluations/ai_agent_result_capture_release_decision_next_handoff_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-release-decision-next-handoff` | P2-140 release decision next handoff readback;承接 P2-139 release decision readback,建立 5 個 next-gate handoff、1 個 stale operator action containment、6 個 blocked handoff transition 與 5 個 operator action;runtime authority 固定 `result_capture_release_decision_next_handoff_only_no_live_write`;P2-139 的 `prepare_p2_139_release_decision_readback` 自我迴圈已標示為 `contained_read_only`,真正下一步為 P2-141;owner release authorized、owner review approved、owner decision approved、verifier decision approved、maintenance window approved、release decision passed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、canonical runtime target read、live query、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive action 全部 `0 / false`;本地 schema / snapshot / loader / API / governance UI 已完成,正式部署與 production smoke 待 feature commit 後驗證,下一步 P2-141 | | `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 主動營運委派與版本生命週期契約 @@ -805,6 +806,7 @@ Repo / registry / release notes / K8s / host / observability / backup evidence 58. 建立 owner / verifier review packet。✅ P2-137 已完成並正式驗證;owner review packet `5`、verifier review packet `5`、rollback owner review packet `5`、maintenance window review hold `5`、live-apply owner review hold `5`、blocked owner review transition `6`、operator action `5`,approval-required owner / verifier / rollback / maintenance / live apply `2 / 2 / 2 / 2 / 2`、blocked owner / verifier / rollback / maintenance / live apply `1 / 1 / 1 / 1 / 1`、critical blocker `5`;owner release authorized、owner review approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read、destructive operation 仍為 `0 / false`;本地 API/service pytest `7 passed`、JSON parse、Python compile、Web typecheck 通過;deploy marker `d023f5d7`、正式 API readback 與 desktop / mobile smoke 已完成。已由 P2-138 承接。 59. 建立 release decision hold。✅ P2-138 最新合約已完成並正式驗證;release decision hold `5`、owner decision hold `5`、verifier decision hold `5`、rollback decision hold `5`、maintenance window decision hold `5`、live-apply decision hold `5`、blocked decision transition `6`、operator action `5`,approval-required release / owner / verifier / rollback / maintenance / live apply `2 / 2 / 2 / 2 / 2 / 2`、blocked release / owner / verifier / rollback / maintenance / live apply `1 / 1 / 1 / 1 / 1 / 1`、critical blocker `6`;owner release authorized、owner review approved、owner decision approved、verifier decision approved、maintenance window approved、release decision passed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read、destructive operation 仍為 `0 / false`;本地 P2-138 + P2-137 regression `15 passed`、JSON parse、Python compile、i18n key mirror、Web typecheck 與 Web production build 通過;deploy marker `bfd26e76`、正式 API readback 與 desktop / mobile smoke 已完成。已由 P2-139 承接。 60. 建立 release decision readback。✅ P2-139 已完成並正式驗證;release decision readback `5`、owner decision readback `5`、verifier decision readback `5`、rollback decision readback `5`、maintenance window decision readback `5`、live-apply decision readback `5`、blocked readback transition `6`、operator action `5`,approval-required release / owner / verifier / rollback / maintenance / live apply `2 / 2 / 2 / 2 / 2 / 2`、blocked release / owner / verifier / rollback / maintenance / live apply `1 / 1 / 1 / 1 / 1 / 1`、critical blocker `6`;owner release authorized、owner review approved、owner decision approved、verifier decision approved、maintenance window approved、release decision passed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read、destructive operation 仍為 `0 / false`;本地 API/service pytest `7 passed`、JSON parse、Python compile、i18n key mirror 通過;deploy marker `df867bd6`、正式 API readback 與 desktop / mobile smoke 已完成。已可由 P2-140 承接。 +61. 建立 release decision next handoff readback。✅ P2-140 已本地完成;next-gate handoff `5`、stale operator action containment `1`、blocked handoff transition `6`、operator action `5`、approval required subtotal `12`、blocked + critical subtotal `12`;P2-139 的 `prepare_p2_139_release_decision_readback` 自我迴圈已標示為 `contained_read_only`,真正下一步固定為 P2-141;owner release authorized、owner review approved、owner decision approved、verifier decision approved、maintenance window approved、release decision passed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read、destructive operation 仍為 `0 / false`;P2-140 + P2-139 regression `14 passed`、JSON parse、Python compile、i18n key mirror、guard 與 doc secret sanity 通過;正式部署與 production smoke 待 feature commit 後驗證。 #### 3.2.1d 2026-06-11 Agent 互動、學習與成長證據面 @@ -1985,6 +1987,13 @@ Phase 6 完成後 - Desktop `1440x1000` 與 mobile `390x844` smoke 均確認 P2-139 區塊、`P2-140`、所有 readback count、`Gateway 寫入=0`、`Telegram 送出=0`、正式寫入 / 發送 `0` 可見;水平溢位 `0`、overflowing element `0`、P2-139 卡片危險控制 `0`、console error `0`、HTTP 4xx/5xx `0`、禁用內部協作片語與敏感欄位命中 `0`。 - 本波仍不讀 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-140 承接,但 P2-140 仍只能推進只讀關卡。 +### 2026-06-14 12:17 (台北) — §3.2 / §5 — 新增 P2-140 release decision next handoff — 本地完成下一關交接讀回 + +- 新增 `ai_agent_result_capture_release_decision_next_handoff_v1` schema、snapshot、service loader、FastAPI endpoint `GET /api/v1/agents/agent-result-capture-release-decision-next-handoff`、governance automation inventory UI 與 i18n 文案。 +- P2-140 承接 P2-139 release decision readback,只讀回 5 個 next-gate handoff、1 個 stale operator action containment、6 個 blocked handoff transition 與 5 個 operator action。 +- P2-140 將 P2-139 的 `prepare_p2_139_release_decision_readback` 自我迴圈標示為 `contained_read_only`,避免操作員重跑已完成關卡;真正下一步固定為 P2-141。 +- 本波仍不讀 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-141 承接。 + ### 2026-06-14 08:36 (台北) — §3.2 / §5 — 正式驗證 P2-134 release authorization hold — 完成釋出授權保留只讀關卡 - Feature commit `e0a6d339` 已由 deploy marker `18b867c3 chore(cd): deploy e0a6d33 [skip ci]` 部署;正式 API health 回 `healthy`、`environment=prod`、`mock_mode=false`。