From 0e5189b51575c3a143c8fb7f0d1decc568449ba4 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 13 Jun 2026 00:33:37 +0800 Subject: [PATCH] =?UTF-8?q?feat(governance):=20=E6=96=B0=E5=A2=9E=E4=BB=BB?= =?UTF-8?q?=E5=8B=99=E7=B5=90=E6=9E=9C=E7=A8=BD=E6=A0=B8=E8=BB=8C=E8=B7=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/api/src/api/v1/agents.py | 31 ++ .../ai_agent_task_result_audit_trail.py | 304 ++++++++++++ .../test_ai_agent_task_result_audit_trail.py | 131 ++++++ ...st_ai_agent_task_result_audit_trail_api.py | 41 ++ apps/web/messages/en.json | 68 +++ apps/web/messages/zh-TW.json | 68 +++ .../tabs/automation-inventory-tab.tsx | 211 ++++++++- apps/web/src/lib/api-client.ts | 144 ++++++ docs/LOGBOOK.md | 27 ++ ...AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md | 10 +- ...T_INTERACTION_LEARNING_PROOF_2026-06-11.md | 20 +- ...nt_task_result_audit_trail_2026-06-13.json | 434 ++++++++++++++++++ ...ent_task_result_audit_trail_v1.schema.json | 336 ++++++++++++++ ...-04-15-MASTER-ai-autonomous-flywheel-v2.md | 18 +- 14 files changed, 1828 insertions(+), 15 deletions(-) create mode 100644 apps/api/src/services/ai_agent_task_result_audit_trail.py create mode 100644 apps/api/tests/test_ai_agent_task_result_audit_trail.py create mode 100644 apps/api/tests/test_ai_agent_task_result_audit_trail_api.py create mode 100644 docs/evaluations/ai_agent_task_result_audit_trail_2026-06-13.json create mode 100644 docs/schemas/ai_agent_task_result_audit_trail_v1.schema.json diff --git a/apps/api/src/api/v1/agents.py b/apps/api/src/api/v1/agents.py index 7ce7cd37c..a4b403cd3 100644 --- a/apps/api/src/api/v1/agents.py +++ b/apps/api/src/api/v1/agents.py @@ -121,6 +121,9 @@ from src.services.ai_agent_telegram_action_required_digest_policy import ( from src.services.ai_agent_telegram_receipt_approval_package import ( load_latest_ai_agent_telegram_receipt_approval_package, ) +from src.services.ai_agent_task_result_audit_trail import ( + load_latest_ai_agent_task_result_audit_trail, +) from src.services.ai_agent_tool_adoption_approval_package import ( load_latest_ai_agent_tool_adoption_approval_package, ) @@ -1097,6 +1100,34 @@ async def get_agent_candidate_operation_dry_run_evidence() -> dict[str, Any]: ) from exc +@router.get( + "/agent-task-result-audit-trail", + response_model=dict[str, Any], + summary="取得 AI Agent 任務結果稽核軌跡", + description=( + "讀取最新已提交的 P2-103 任務結果稽核軌跡;此端點只回傳 result route、" + "KM / LOGBOOK / audit / timeline writeback contract、operator handoff 與 redaction boundary," + "不寫 KM、不 runtime append LOGBOOK、不寫 audit DB、不寫 timeline、不更新 PlayBook trust、" + "不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 production target、不讀 secret。" + ), +) +async def get_agent_task_result_audit_trail() -> dict[str, Any]: + """Return the latest read-only AI Agent task result audit trail contract.""" + try: + return await asyncio.to_thread(load_latest_ai_agent_task_result_audit_trail) + 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_task_result_audit_trail_invalid", error=str(exc)) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="AI Agent 任務結果稽核軌跡無效", + ) from exc + + @router.get( "/agent-owner-approved-fixture-dry-run", response_model=dict[str, Any], diff --git a/apps/api/src/services/ai_agent_task_result_audit_trail.py b/apps/api/src/services/ai_agent_task_result_audit_trail.py new file mode 100644 index 000000000..2b38705a4 --- /dev/null +++ b/apps/api/src/services/ai_agent_task_result_audit_trail.py @@ -0,0 +1,304 @@ +""" +AI Agent task result audit trail snapshot. + +Loads the latest committed P2-103 task result audit trail contract. This module +validates repo-committed evidence only; it never writes KM, appends LOGBOOK, +writes audit DB rows, writes incident timeline, updates PlayBook trust, writes +Gateway queues, sends Telegram messages, reads secrets, or starts runtime work. +""" + +from __future__ import annotations + +import json +from pathlib import Path +from typing import Any + +from src.services.snapshot_paths import default_evaluations_dir + +_DEFAULT_EVALUATIONS_DIR = default_evaluations_dir(Path(__file__)) +_SNAPSHOT_PATTERN = "ai_agent_task_result_audit_trail_*.json" +_SCHEMA_VERSION = "ai_agent_task_result_audit_trail_v1" +_RUNTIME_AUTHORITY = "task_result_audit_trail_contract_only_no_live_writeback" + + +def load_latest_ai_agent_task_result_audit_trail( + evaluations_dir: Path | None = None, +) -> dict[str, Any]: + """Load the newest committed AI Agent task result audit trail contract.""" + directory = evaluations_dir or _DEFAULT_EVALUATIONS_DIR + candidates = sorted(directory.glob(_SNAPSHOT_PATTERN)) + if not candidates: + raise FileNotFoundError(f"no AI Agent task result audit trail snapshots found in {directory}") + + latest = candidates[-1] + with latest.open(encoding="utf-8") as handle: + payload = json.load(handle) + + if not isinstance(payload, dict): + raise ValueError(f"{latest}: expected JSON object") + _require_schema(payload, str(latest)) + _require_no_live_boundaries(payload, str(latest)) + _require_result_routes(payload, str(latest)) + _require_writeback_contracts(payload, str(latest)) + _require_audit_checkpoints(payload, str(latest)) + _require_operator_handoffs(payload, str(latest)) + _require_redaction_contract(payload, str(latest)) + _require_rollup_consistency(payload, str(latest)) + return payload + + +def _require_schema(payload: dict[str, Any], label: str) -> None: + if payload.get("schema_version") != _SCHEMA_VERSION: + raise ValueError(f"{label}: expected schema_version={_SCHEMA_VERSION}") + status = payload.get("program_status") or {} + if status.get("read_only_mode") is not True: + raise ValueError(f"{label}: program_status.read_only_mode must be true") + if status.get("runtime_authority") != _RUNTIME_AUTHORITY: + raise ValueError(f"{label}: runtime_authority must remain {_RUNTIME_AUTHORITY}") + if status.get("current_task_id") != "P2-103": + raise ValueError(f"{label}: current_task_id must be P2-103") + if status.get("next_task_id") != "P2-104": + raise ValueError(f"{label}: next_task_id must be P2-104") + + +def _require_no_live_boundaries(payload: dict[str, Any], label: str) -> None: + truth = payload.get("result_audit_truth") or {} + required_true = { + "p2_102_candidate_dry_run_loaded", + "task_result_route_matrix_ready", + "km_draft_contract_ready", + "logbook_append_contract_ready", + "audit_trail_contract_ready", + "timeline_handoff_contract_ready", + "operator_next_action_ready", + "all_results_have_owner_and_next_step", + } + missing = sorted(field for field in required_true if truth.get(field) is not True) + if missing: + raise ValueError(f"{label}: result audit readiness flags must remain true: {missing}") + + required_false = { + "runtime_execution_enabled", + "km_write_enabled", + "logbook_runtime_write_enabled", + "audit_db_write_enabled", + "timeline_write_enabled", + "playbook_trust_write_enabled", + "gateway_queue_write_enabled", + "telegram_send_enabled", + "delivery_receipt_write_enabled", + "production_write_enabled", + "secret_value_read_enabled", + "host_or_cluster_command_enabled", + "destructive_operation_enabled", + "work_window_transcript_display_allowed", + } + unsafe = sorted(field for field in required_false if truth.get(field) is not False) + if unsafe: + raise ValueError(f"{label}: live write/send/execution flags must remain false: {unsafe}") + + zero_counts = { + "runtime_execution_count_24h", + "km_write_count_24h", + "logbook_runtime_write_count_24h", + "audit_db_write_count_24h", + "timeline_write_count_24h", + "playbook_trust_write_count_24h", + "gateway_queue_write_count_24h", + "telegram_send_count_24h", + "delivery_receipt_write_count_24h", + "production_write_count_24h", + "secret_value_read_count_24h", + "host_or_cluster_command_count_24h", + "destructive_operation_count_24h", + } + non_zero = sorted(field for field in zero_counts if truth.get(field) != 0) + if non_zero: + raise ValueError(f"{label}: live write/send/execution counts must remain zero: {non_zero}") + + +def _require_result_routes(payload: dict[str, Any], label: str) -> None: + routes = payload.get("result_routes") or [] + route_ids = {route.get("route_id") for route in routes} + required = { + "result_diagnostic_no_action", + "result_repair_candidate_needs_owner", + "result_execution_failed_manual", + "result_verified_no_change", + "result_evidence_missing", + "result_policy_blocked", + "result_provider_unmatched", + "result_report_zero_signal", + } + if route_ids != required: + raise ValueError(f"{label}: result routes must match {sorted(required)}") + + valid_states = { + "diagnostic_only", + "owner_review_required", + "execution_failed", + "verified_no_change", + "blocked_until_evidence", + "blocked_by_policy", + "correlation_gap", + "report_quality_gap", + } + for route in routes: + route_id = route.get("route_id") + if route.get("result_state") not in valid_states: + raise ValueError(f"{label}: route {route_id} result_state is invalid") + if route.get("writes_live_state") is not False: + raise ValueError(f"{label}: route {route_id} writes_live_state must remain false") + if not isinstance(route.get("requires_owner_review"), bool): + raise ValueError(f"{label}: route {route_id} requires_owner_review must be boolean") + if not isinstance(route.get("ready_for_km_draft"), bool): + raise ValueError(f"{label}: route {route_id} ready_for_km_draft must be boolean") + for field in { + "primary_owner", + "km_target", + "logbook_target", + "audit_target", + "timeline_target", + "operator_next_action", + "blocked_reason", + }: + if not route.get(field): + raise ValueError(f"{label}: route {route_id} must list {field}") + if not _is_redacted_sha256(route.get("evidence_hash")): + raise ValueError(f"{label}: route {route_id} must expose evidence_hash") + + +def _require_writeback_contracts(payload: dict[str, Any], label: str) -> None: + contracts = payload.get("writeback_contracts") or [] + contract_ids = {contract.get("contract_id") for contract in contracts} + required = { + "contract_km_review_draft", + "contract_logbook_evidence_append", + "contract_audit_trail_entry", + "contract_incident_timeline_handoff", + "contract_playbook_trust_candidate", + "contract_operator_handoff_packet", + } + if contract_ids != required: + raise ValueError(f"{label}: writeback contracts must match {sorted(required)}") + for contract in contracts: + contract_id = contract.get("contract_id") + if contract.get("write_enabled") is not False: + raise ValueError(f"{label}: contract {contract_id} write_enabled must remain false") + if contract.get("runtime_writer_enabled") is not False: + raise ValueError(f"{label}: contract {contract_id} runtime_writer_enabled must remain false") + if not contract.get("required_fields"): + raise ValueError(f"{label}: contract {contract_id} must list required_fields") + if not contract.get("blocker_summary"): + raise ValueError(f"{label}: contract {contract_id} must list blocker_summary") + if not _is_redacted_sha256(contract.get("evidence_hash")): + raise ValueError(f"{label}: contract {contract_id} must expose evidence_hash") + + +def _require_audit_checkpoints(payload: dict[str, Any], label: str) -> None: + checkpoints = payload.get("audit_checkpoints") or [] + checkpoint_ids = {checkpoint.get("checkpoint_id") for checkpoint in checkpoints} + required = { + "checkpoint_result_classification", + "checkpoint_evidence_hash", + "checkpoint_owner_next_action", + "checkpoint_km_draft_review", + "checkpoint_logbook_evidence", + "checkpoint_timeline_handoff", + "checkpoint_redaction_boundary", + } + if checkpoint_ids != required: + raise ValueError(f"{label}: audit checkpoints must match {sorted(required)}") + for checkpoint in checkpoints: + checkpoint_id = checkpoint.get("checkpoint_id") + if checkpoint.get("creates_runtime_action") is not False: + raise ValueError(f"{label}: checkpoint {checkpoint_id} creates_runtime_action must remain false") + if checkpoint.get("status") not in {"ready", "needs_owner_review", "blocked_by_policy"}: + raise ValueError(f"{label}: checkpoint {checkpoint_id} status is invalid") + if not checkpoint.get("failure_if_missing"): + raise ValueError(f"{label}: checkpoint {checkpoint_id} must list failure_if_missing") + + +def _require_operator_handoffs(payload: dict[str, Any], label: str) -> None: + handoffs = payload.get("operator_handoffs") or [] + handoff_ids = {handoff.get("handoff_id") for handoff in handoffs} + required = { + "handoff_manual_fix_or_rollback", + "handoff_collect_missing_repair_evidence", + "handoff_provider_correlation_review", + "handoff_km_owner_review", + "handoff_report_quality_review", + } + if handoff_ids != required: + raise ValueError(f"{label}: operator handoffs must match {sorted(required)}") + for handoff in handoffs: + handoff_id = handoff.get("handoff_id") + if handoff.get("creates_runtime_action") is not False: + raise ValueError(f"{label}: handoff {handoff_id} creates_runtime_action must remain false") + if handoff.get("requires_human_review") is not True: + raise ValueError(f"{label}: handoff {handoff_id} requires_human_review must remain true") + if not handoff.get("human_instruction"): + raise ValueError(f"{label}: handoff {handoff_id} must list human_instruction") + + +def _require_redaction_contract(payload: dict[str, Any], label: str) -> None: + contract = payload.get("display_redaction_contract") or {} + required_false = { + "raw_prompt_display_allowed", + "private_reasoning_display_allowed", + "secret_value_display_allowed", + "raw_telegram_payload_display_allowed", + "work_window_transcript_display_allowed", + } + if contract.get("redaction_required") is not True: + raise ValueError(f"{label}: display redaction must remain required") + unsafe = sorted(field for field in required_false if contract.get(field) is not False) + if unsafe: + raise ValueError(f"{label}: display redaction fields must remain false: {unsafe}") + + +def _require_rollup_consistency(payload: dict[str, Any], label: str) -> None: + rollups = payload.get("rollups") or {} + truth = payload.get("result_audit_truth") or {} + routes = payload.get("result_routes") or [] + contracts = payload.get("writeback_contracts") or [] + checkpoints = payload.get("audit_checkpoints") or [] + handoffs = payload.get("operator_handoffs") or [] + blocked_states = {"blocked_until_evidence", "blocked_by_policy", "correlation_gap"} + + expected = { + "result_route_count": len(routes), + "owner_next_action_ready_count": sum(1 for route in routes if bool(route.get("operator_next_action"))), + "requires_owner_review_count": sum(1 for route in routes if route.get("requires_owner_review") is True), + "ready_for_km_draft_count": sum(1 for route in routes if route.get("ready_for_km_draft") is True), + "blocked_result_count": sum(1 for route in routes if route.get("result_state") in blocked_states), + "writeback_contract_count": len(contracts), + "audit_checkpoint_count": len(checkpoints), + "operator_handoff_count": len(handoffs), + "runtime_execution_count": truth.get("runtime_execution_count_24h"), + "km_write_count": truth.get("km_write_count_24h"), + "logbook_runtime_write_count": truth.get("logbook_runtime_write_count_24h"), + "audit_db_write_count": truth.get("audit_db_write_count_24h"), + "timeline_write_count": truth.get("timeline_write_count_24h"), + "playbook_trust_write_count": truth.get("playbook_trust_write_count_24h"), + "gateway_queue_write_count": truth.get("gateway_queue_write_count_24h"), + "telegram_send_count": truth.get("telegram_send_count_24h"), + "production_write_count": truth.get("production_write_count_24h"), + "secret_value_read_count": truth.get("secret_value_read_count_24h"), + "destructive_operation_count": truth.get("destructive_operation_count_24h"), + } + mismatches = { + key: {"expected": expected_value, "actual": rollups.get(key)} + for key, expected_value in expected.items() + if rollups.get(key) != expected_value + } + if mismatches: + raise ValueError(f"{label}: rollup counts mismatch: {mismatches}") + + +def _is_redacted_sha256(value: Any) -> bool: + if not isinstance(value, str): + return False + if not value.startswith("sha256:") or len(value) != 71: + return False + return all(char in "0123456789abcdef" for char in value.removeprefix("sha256:")) diff --git a/apps/api/tests/test_ai_agent_task_result_audit_trail.py b/apps/api/tests/test_ai_agent_task_result_audit_trail.py new file mode 100644 index 000000000..5c5e675c4 --- /dev/null +++ b/apps/api/tests/test_ai_agent_task_result_audit_trail.py @@ -0,0 +1,131 @@ +import copy +import json + +import pytest + +from src.services.ai_agent_task_result_audit_trail import ( + load_latest_ai_agent_task_result_audit_trail, +) + + +def _write_snapshot(tmp_path, payload): + path = tmp_path / "ai_agent_task_result_audit_trail_2026-06-13.json" + path.write_text(json.dumps(payload), encoding="utf-8") + return path + + +def test_load_latest_ai_agent_task_result_audit_trail(): + data = load_latest_ai_agent_task_result_audit_trail() + + assert data["schema_version"] == "ai_agent_task_result_audit_trail_v1" + assert data["program_status"]["current_task_id"] == "P2-103" + assert data["program_status"]["next_task_id"] == "P2-104" + assert data["program_status"]["overall_completion_percent"] == 99 + assert data["result_audit_truth"]["task_result_route_matrix_ready"] is True + assert data["result_audit_truth"]["km_draft_contract_ready"] is True + assert data["result_audit_truth"]["logbook_append_contract_ready"] is True + assert data["result_audit_truth"]["audit_trail_contract_ready"] is True + assert data["result_audit_truth"]["runtime_execution_enabled"] is False + assert data["result_audit_truth"]["km_write_enabled"] is False + assert data["result_audit_truth"]["logbook_runtime_write_enabled"] is False + assert data["result_audit_truth"]["audit_db_write_enabled"] is False + assert data["result_audit_truth"]["timeline_write_enabled"] is False + assert data["result_audit_truth"]["gateway_queue_write_enabled"] is False + assert data["result_audit_truth"]["telegram_send_enabled"] is False + assert data["rollups"]["result_route_count"] == 8 + assert data["rollups"]["owner_next_action_ready_count"] == 8 + assert data["rollups"]["requires_owner_review_count"] == 7 + assert data["rollups"]["ready_for_km_draft_count"] == 5 + assert data["rollups"]["blocked_result_count"] == 3 + assert data["rollups"]["writeback_contract_count"] == 6 + assert data["rollups"]["audit_checkpoint_count"] == 7 + assert data["rollups"]["operator_handoff_count"] == 5 + assert data["rollups"]["runtime_execution_count"] == 0 + assert data["rollups"]["km_write_count"] == 0 + assert data["rollups"]["logbook_runtime_write_count"] == 0 + assert data["rollups"]["audit_db_write_count"] == 0 + assert data["rollups"]["timeline_write_count"] == 0 + assert data["rollups"]["gateway_queue_write_count"] == 0 + assert data["rollups"]["telegram_send_count"] == 0 + + +def test_rejects_km_write_enabled(tmp_path): + data = load_latest_ai_agent_task_result_audit_trail() + bad = copy.deepcopy(data) + bad["result_audit_truth"]["km_write_enabled"] = True + _write_snapshot(tmp_path, bad) + + with pytest.raises(ValueError, match="live write/send/execution flags"): + load_latest_ai_agent_task_result_audit_trail(tmp_path) + + +def test_rejects_audit_db_write_count(tmp_path): + data = load_latest_ai_agent_task_result_audit_trail() + bad = copy.deepcopy(data) + bad["result_audit_truth"]["audit_db_write_count_24h"] = 1 + bad["rollups"]["audit_db_write_count"] = 1 + _write_snapshot(tmp_path, bad) + + with pytest.raises(ValueError, match="live write/send/execution counts"): + load_latest_ai_agent_task_result_audit_trail(tmp_path) + + +def test_rejects_result_route_live_write(tmp_path): + data = load_latest_ai_agent_task_result_audit_trail() + bad = copy.deepcopy(data) + bad["result_routes"][0]["writes_live_state"] = True + _write_snapshot(tmp_path, bad) + + with pytest.raises(ValueError, match="writes_live_state"): + load_latest_ai_agent_task_result_audit_trail(tmp_path) + + +def test_rejects_result_route_without_next_action(tmp_path): + data = load_latest_ai_agent_task_result_audit_trail() + bad = copy.deepcopy(data) + bad["result_routes"][0]["operator_next_action"] = "" + bad["rollups"]["owner_next_action_ready_count"] = 7 + _write_snapshot(tmp_path, bad) + + with pytest.raises(ValueError, match="operator_next_action"): + load_latest_ai_agent_task_result_audit_trail(tmp_path) + + +def test_rejects_writeback_contract_runtime_writer(tmp_path): + data = load_latest_ai_agent_task_result_audit_trail() + bad = copy.deepcopy(data) + bad["writeback_contracts"][0]["runtime_writer_enabled"] = True + _write_snapshot(tmp_path, bad) + + with pytest.raises(ValueError, match="runtime_writer_enabled"): + load_latest_ai_agent_task_result_audit_trail(tmp_path) + + +def test_rejects_checkpoint_runtime_action(tmp_path): + data = load_latest_ai_agent_task_result_audit_trail() + bad = copy.deepcopy(data) + bad["audit_checkpoints"][0]["creates_runtime_action"] = True + _write_snapshot(tmp_path, bad) + + with pytest.raises(ValueError, match="creates_runtime_action"): + load_latest_ai_agent_task_result_audit_trail(tmp_path) + + +def test_rejects_handoff_runtime_action(tmp_path): + data = load_latest_ai_agent_task_result_audit_trail() + bad = copy.deepcopy(data) + bad["operator_handoffs"][0]["creates_runtime_action"] = True + _write_snapshot(tmp_path, bad) + + with pytest.raises(ValueError, match="creates_runtime_action"): + load_latest_ai_agent_task_result_audit_trail(tmp_path) + + +def test_rejects_rollup_mismatch(tmp_path): + data = load_latest_ai_agent_task_result_audit_trail() + bad = copy.deepcopy(data) + bad["rollups"]["result_route_count"] = 999 + _write_snapshot(tmp_path, bad) + + with pytest.raises(ValueError, match="rollup counts"): + load_latest_ai_agent_task_result_audit_trail(tmp_path) diff --git a/apps/api/tests/test_ai_agent_task_result_audit_trail_api.py b/apps/api/tests/test_ai_agent_task_result_audit_trail_api.py new file mode 100644 index 000000000..46acac9aa --- /dev/null +++ b/apps/api/tests/test_ai_agent_task_result_audit_trail_api.py @@ -0,0 +1,41 @@ +from fastapi.testclient import TestClient + +from src.main import app + + +def test_get_ai_agent_task_result_audit_trail_api(): + client = TestClient(app) + response = client.get("/api/v1/agents/agent-task-result-audit-trail") + + assert response.status_code == 200 + data = response.json() + assert data["schema_version"] == "ai_agent_task_result_audit_trail_v1" + assert data["program_status"]["current_task_id"] == "P2-103" + assert data["program_status"]["next_task_id"] == "P2-104" + assert data["program_status"]["overall_completion_percent"] == 99 + assert data["result_audit_truth"]["task_result_route_matrix_ready"] is True + assert data["result_audit_truth"]["km_draft_contract_ready"] is True + assert data["result_audit_truth"]["logbook_append_contract_ready"] is True + assert data["result_audit_truth"]["audit_trail_contract_ready"] is True + assert data["result_audit_truth"]["runtime_execution_enabled"] is False + assert data["result_audit_truth"]["km_write_enabled"] is False + assert data["result_audit_truth"]["logbook_runtime_write_enabled"] is False + assert data["result_audit_truth"]["audit_db_write_enabled"] is False + assert data["result_audit_truth"]["timeline_write_enabled"] is False + assert data["result_audit_truth"]["gateway_queue_write_enabled"] is False + assert data["result_audit_truth"]["telegram_send_enabled"] is False + assert data["rollups"]["result_route_count"] == 8 + assert data["rollups"]["owner_next_action_ready_count"] == 8 + assert data["rollups"]["requires_owner_review_count"] == 7 + assert data["rollups"]["ready_for_km_draft_count"] == 5 + assert data["rollups"]["blocked_result_count"] == 3 + assert data["rollups"]["writeback_contract_count"] == 6 + assert data["rollups"]["audit_checkpoint_count"] == 7 + assert data["rollups"]["operator_handoff_count"] == 5 + assert data["rollups"]["runtime_execution_count"] == 0 + assert data["rollups"]["km_write_count"] == 0 + assert data["rollups"]["logbook_runtime_write_count"] == 0 + assert data["rollups"]["audit_db_write_count"] == 0 + assert data["rollups"]["timeline_write_count"] == 0 + assert data["rollups"]["gateway_queue_write_count"] == 0 + assert data["rollups"]["telegram_send_count"] == 0 diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index c15fdcad4..e2a057e2d 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -4494,6 +4494,74 @@ "high": "高風險", "critical": "關鍵阻擋" } + }, + "taskResultAuditTrail": { + "title": "P2-103 任務結果稽核軌跡", + "source": "{generated} · {current} → {next}", + "truthTitle": "結果回接真相", + "boundaryTitle": "寫回邊界", + "boundarySummary": "目前 KM write {km}、LOGBOOK runtime append {logbook}、audit DB write {audit}、timeline write {timeline}、Gateway queue write {queue}、Telegram send {send};本段只定義結果路由與人工交接,不開 runtime 寫入。", + "metrics": { + "overall": "P2-103 進度", + "routes": "結果路由", + "nextActions": "下一步齊備", + "ownerReview": "需 owner", + "kmDrafts": "KM 草稿", + "blocked": "卡點結果", + "writebacks": "寫回契約", + "checkpoints": "稽核點", + "kmWrites": "KM writes", + "logbookWrites": "LOGBOOK writes", + "auditWrites": "audit writes", + "timelineWrites": "timeline writes", + "queueWrites": "queue writes", + "telegramSends": "TG sends" + }, + "flags": { + "p2Loaded": "P2-102 loaded: {value}", + "routeReady": "route matrix: {value}", + "kmReady": "KM draft: {value}", + "auditReady": "audit trail: {value}", + "runtime": "runtime enabled: {value}", + "kmWrite": "KM write: {value}", + "logbookWrite": "LOGBOOK append: {value}", + "auditWrite": "audit write: {value}", + "timelineWrite": "timeline write: {value}", + "send": "send: {value}" + }, + "labels": { + "owner": "owner: {value}", + "ownerReview": "owner review: {value}", + "liveWrite": "live write: {value}", + "blockedReason": "卡點: {value}", + "kmTarget": "KM: {value}", + "auditTarget": "audit: {value}", + "evidenceHash": "evidence: {value}", + "targetSystem": "target: {value}", + "writeEnabled": "write enabled: {value}", + "runtimeWriter": "runtime writer: {value}", + "runtimeAction": "runtime action: {value}" + }, + "resultStates": { + "diagnostic_only": "只完成診斷", + "owner_review_required": "等 owner 審查", + "execution_failed": "執行失敗", + "verified_no_change": "只讀驗證", + "blocked_until_evidence": "等補證", + "blocked_by_policy": "政策阻擋", + "correlation_gap": "來源未匹配", + "report_quality_gap": "報表品質缺口" + }, + "allowedModes": { + "committed_snapshot_only": "只讀快照", + "gated_owner_review": "owner gate", + "manual_append_plan": "人工補記計畫" + }, + "checkpointStatuses": { + "ready": "可審查", + "needs_owner_review": "需 owner", + "blocked_by_policy": "政策阻擋" + } } } }, diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index c15fdcad4..e2a057e2d 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -4494,6 +4494,74 @@ "high": "高風險", "critical": "關鍵阻擋" } + }, + "taskResultAuditTrail": { + "title": "P2-103 任務結果稽核軌跡", + "source": "{generated} · {current} → {next}", + "truthTitle": "結果回接真相", + "boundaryTitle": "寫回邊界", + "boundarySummary": "目前 KM write {km}、LOGBOOK runtime append {logbook}、audit DB write {audit}、timeline write {timeline}、Gateway queue write {queue}、Telegram send {send};本段只定義結果路由與人工交接,不開 runtime 寫入。", + "metrics": { + "overall": "P2-103 進度", + "routes": "結果路由", + "nextActions": "下一步齊備", + "ownerReview": "需 owner", + "kmDrafts": "KM 草稿", + "blocked": "卡點結果", + "writebacks": "寫回契約", + "checkpoints": "稽核點", + "kmWrites": "KM writes", + "logbookWrites": "LOGBOOK writes", + "auditWrites": "audit writes", + "timelineWrites": "timeline writes", + "queueWrites": "queue writes", + "telegramSends": "TG sends" + }, + "flags": { + "p2Loaded": "P2-102 loaded: {value}", + "routeReady": "route matrix: {value}", + "kmReady": "KM draft: {value}", + "auditReady": "audit trail: {value}", + "runtime": "runtime enabled: {value}", + "kmWrite": "KM write: {value}", + "logbookWrite": "LOGBOOK append: {value}", + "auditWrite": "audit write: {value}", + "timelineWrite": "timeline write: {value}", + "send": "send: {value}" + }, + "labels": { + "owner": "owner: {value}", + "ownerReview": "owner review: {value}", + "liveWrite": "live write: {value}", + "blockedReason": "卡點: {value}", + "kmTarget": "KM: {value}", + "auditTarget": "audit: {value}", + "evidenceHash": "evidence: {value}", + "targetSystem": "target: {value}", + "writeEnabled": "write enabled: {value}", + "runtimeWriter": "runtime writer: {value}", + "runtimeAction": "runtime action: {value}" + }, + "resultStates": { + "diagnostic_only": "只完成診斷", + "owner_review_required": "等 owner 審查", + "execution_failed": "執行失敗", + "verified_no_change": "只讀驗證", + "blocked_until_evidence": "等補證", + "blocked_by_policy": "政策阻擋", + "correlation_gap": "來源未匹配", + "report_quality_gap": "報表品質缺口" + }, + "allowedModes": { + "committed_snapshot_only": "只讀快照", + "gated_owner_review": "owner gate", + "manual_append_plan": "人工補記計畫" + }, + "checkpointStatuses": { + "ready": "可審查", + "needs_owner_review": "需 owner", + "blocked_by_policy": "政策阻擋" + } } } }, 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 52076d7d3..2b9884524 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 @@ -55,6 +55,7 @@ import { type AiAgentRuntimeWorkerShadowGateSnapshot, type AiAgentRuntimeVerifierEvidenceReviewSnapshot, type AiAgentRuntimeWriteGateReviewSnapshot, + type AiAgentTaskResultAuditTrailSnapshot, type AiAgentTelegramReceiptApprovalPackageSnapshot, type AiProviderRouteMatrixSnapshot, type AiAgentAutomationBacklogSnapshot, @@ -350,6 +351,7 @@ export function AutomationInventoryTab() { const [runtimeWorkerShadowGate, setRuntimeWorkerShadowGate] = useState(null) const [operationPermissionModel, setOperationPermissionModel] = useState(null) const [candidateOperationDryRunEvidence, setCandidateOperationDryRunEvidence] = useState(null) + const [taskResultAuditTrail, setTaskResultAuditTrail] = useState(null) const [reportTruthActionabilityReview, setReportTruthActionabilityReview] = useState(null) const [ownerDryRunPackage, setOwnerDryRunPackage] = useState(null) const [hostStatefulInventory, setHostStatefulInventory] = useState(null) @@ -389,6 +391,7 @@ export function AutomationInventoryTab() { apiClient.getAiAgentRuntimeWorkerShadowGate(), apiClient.getAiAgentOperationPermissionModel(), apiClient.getAiAgentCandidateOperationDryRunEvidence(), + apiClient.getAiAgentTaskResultAuditTrail(), apiClient.getAiAgentReportTruthActionabilityReview(), apiClient.getAiAgentOwnerApprovedFixtureDryRun(), apiClient.getAiAgentHostStatefulVersionInventory(), @@ -427,6 +430,7 @@ export function AutomationInventoryTab() { runtimeWorkerShadowGateResult, operationPermissionModelResult, candidateOperationDryRunEvidenceResult, + taskResultAuditTrailResult, reportTruthActionabilityReviewResult, ownerDryRunPackageResult, hostStatefulInventoryResult, @@ -462,6 +466,7 @@ export function AutomationInventoryTab() { setRuntimeWorkerShadowGate(runtimeWorkerShadowGateResult.status === 'fulfilled' ? runtimeWorkerShadowGateResult.value : null) setOperationPermissionModel(operationPermissionModelResult.status === 'fulfilled' ? operationPermissionModelResult.value : null) setCandidateOperationDryRunEvidence(candidateOperationDryRunEvidenceResult.status === 'fulfilled' ? candidateOperationDryRunEvidenceResult.value : null) + setTaskResultAuditTrail(taskResultAuditTrailResult.status === 'fulfilled' ? taskResultAuditTrailResult.value : null) setReportTruthActionabilityReview(reportTruthActionabilityReviewResult.status === 'fulfilled' ? reportTruthActionabilityReviewResult.value : null) setOwnerDryRunPackage(ownerDryRunPackageResult.status === 'fulfilled' ? ownerDryRunPackageResult.value : null) setHostStatefulInventory(hostStatefulInventoryResult.status === 'fulfilled' ? hostStatefulInventoryResult.value : null) @@ -495,6 +500,7 @@ export function AutomationInventoryTab() { runtimeWorkerShadowGateResult, operationPermissionModelResult, candidateOperationDryRunEvidenceResult, + taskResultAuditTrailResult, reportTruthActionabilityReviewResult, ownerDryRunPackageResult, hostStatefulInventoryResult, @@ -1131,6 +1137,48 @@ export function AutomationInventoryTab() { .slice(0, 5) }, [candidateOperationDryRunEvidence]) + const visibleTaskResultRoutes = useMemo(() => { + if (!taskResultAuditTrail) return [] + const statePriority = { + execution_failed: 0, + blocked_by_policy: 1, + blocked_until_evidence: 2, + correlation_gap: 3, + report_quality_gap: 4, + owner_review_required: 5, + diagnostic_only: 6, + verified_no_change: 7, + } as Record + return [...taskResultAuditTrail.result_routes] + .sort((a, b) => { + const left = statePriority[a.result_state] ?? 8 + const right = statePriority[b.result_state] ?? 8 + if (left !== right) return left - right + return a.route_id.localeCompare(b.route_id) + }) + .slice(0, 8) + }, [taskResultAuditTrail]) + + const visibleTaskWritebackContracts = useMemo(() => { + if (!taskResultAuditTrail) return [] + return [...taskResultAuditTrail.writeback_contracts] + .sort((a, b) => a.contract_id.localeCompare(b.contract_id)) + .slice(0, 6) + }, [taskResultAuditTrail]) + + const visibleTaskAuditCheckpoints = useMemo(() => { + if (!taskResultAuditTrail) return [] + const statusPriority = { blocked_by_policy: 0, needs_owner_review: 1, ready: 2 } as Record + return [...taskResultAuditTrail.audit_checkpoints] + .sort((a, b) => { + const left = statusPriority[a.status] ?? 3 + const right = statusPriority[b.status] ?? 3 + if (left !== right) return left - right + return a.checkpoint_id.localeCompare(b.checkpoint_id) + }) + .slice(0, 7) + }, [taskResultAuditTrail]) + const visibleReportTruthFindings = useMemo(() => { if (!reportTruthActionabilityReview) return [] const priority = { critical: 0, high: 1, medium: 2, low: 3 } as Record @@ -1350,7 +1398,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 || !reportRuntimeReadiness || !reportRuntimeDryRun || !reportRuntimeFixtureReadback || !runtimeWorkerShadowGate || !operationPermissionModel || !candidateOperationDryRunEvidence || !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 || !reportRuntimeReadiness || !reportRuntimeDryRun || !reportRuntimeFixtureReadback || !runtimeWorkerShadowGate || !operationPermissionModel || !candidateOperationDryRunEvidence || !taskResultAuditTrail || !reportTruthActionabilityReview || !ownerDryRunPackage || !hostStatefulInventory || !serviceHealthGapMatrix || !serviceHealthNotificationPolicy) { return (
@@ -1572,6 +1620,20 @@ export function AutomationInventoryTab() { const candidateDryRunProductionWrites = candidateOperationDryRunEvidence.rollups.production_write_count const candidateDryRunSecretReads = candidateOperationDryRunEvidence.rollups.secret_value_read_count const candidateDryRunDestructive = candidateOperationDryRunEvidence.rollups.destructive_operation_count + const taskResultOverall = taskResultAuditTrail.program_status.overall_completion_percent + const taskResultRoutes = taskResultAuditTrail.rollups.result_route_count + const taskResultNextActions = taskResultAuditTrail.rollups.owner_next_action_ready_count + const taskResultOwnerReview = taskResultAuditTrail.rollups.requires_owner_review_count + const taskResultKmDrafts = taskResultAuditTrail.rollups.ready_for_km_draft_count + const taskResultBlocked = taskResultAuditTrail.rollups.blocked_result_count + const taskResultWritebacks = taskResultAuditTrail.rollups.writeback_contract_count + const taskResultCheckpoints = taskResultAuditTrail.rollups.audit_checkpoint_count + const taskResultKmWrites = taskResultAuditTrail.rollups.km_write_count + const taskResultLogbookWrites = taskResultAuditTrail.rollups.logbook_runtime_write_count + const taskResultAuditWrites = taskResultAuditTrail.rollups.audit_db_write_count + const taskResultTimelineWrites = taskResultAuditTrail.rollups.timeline_write_count + const taskResultQueueWrites = taskResultAuditTrail.rollups.gateway_queue_write_count + const taskResultTelegramSends = taskResultAuditTrail.rollups.telegram_send_count const reportTruthOverall = reportTruthActionabilityReview.program_status.overall_completion_percent const reportTruthFindings = reportTruthActionabilityReview.rollups.zero_signal_finding_count const reportTruthCritical = reportTruthActionabilityReview.rollups.critical_finding_count @@ -3332,6 +3394,153 @@ export function AutomationInventoryTab() {
+
+
+
+ + + {t('taskResultAuditTrail.title')} + +
+ +
+ +
+ } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> +
+ +
+
+ {t('taskResultAuditTrail.truthTitle')} + + {taskResultAuditTrail.result_audit_truth.truth_note} + +
+ + + + +
+
+ +
+ {t('taskResultAuditTrail.boundaryTitle')} + + {t('taskResultAuditTrail.boundarySummary', { + km: taskResultKmWrites, + logbook: taskResultLogbookWrites, + audit: taskResultAuditWrites, + timeline: taskResultTimelineWrites, + queue: taskResultQueueWrites, + send: taskResultTelegramSends, + })} + +
+ + + + + + +
+
+
+ +
+ {visibleTaskResultRoutes.map(route => ( +
+
+ + {route.display_name} + + +
+
+ + + + +
+ + {route.operator_next_action} + + + {t('taskResultAuditTrail.labels.blockedReason', { value: route.blocked_reason })} + +
+ + + +
+
+ ))} +
+ +
+ {visibleTaskWritebackContracts.map(contract => ( +
+
+ + {contract.display_name} + + +
+ + {contract.purpose} + + + {contract.blocker_summary} + +
+ + + +
+
+ ))} +
+ +
+ {visibleTaskAuditCheckpoints.map(checkpoint => ( +
+
+ + {checkpoint.display_name} + + +
+ + {checkpoint.required_for} + + + {checkpoint.failure_if_missing} + + +
+ ))} +
+
+
diff --git a/apps/web/src/lib/api-client.ts b/apps/web/src/lib/api-client.ts index 2bedaf80c..3e8e7944e 100644 --- a/apps/web/src/lib/api-client.ts +++ b/apps/web/src/lib/api-client.ts @@ -357,6 +357,11 @@ export const apiClient = { return handleResponse(res) }, + async getAiAgentTaskResultAuditTrail() { + const res = await fetch(`${API_BASE_URL}/agents/agent-task-result-audit-trail`) + return handleResponse(res) + }, + async getAiAgentOwnerApprovedFixtureDryRun() { const res = await fetch(`${API_BASE_URL}/agents/agent-owner-approved-fixture-dry-run`) return handleResponse(res) @@ -2883,6 +2888,145 @@ export interface AiAgentCandidateOperationDryRunEvidenceSnapshot { } } +export interface AiAgentTaskResultAuditTrailSnapshot { + schema_version: 'ai_agent_task_result_audit_trail_v1' + generated_at: string + program_status: { + overall_completion_percent: number + current_priority: 'P0' | 'P1' | 'P2' | 'P3' + current_task_id: 'P2-103' + next_task_id: 'P2-104' + read_only_mode: true + runtime_authority: 'task_result_audit_trail_contract_only_no_live_writeback' + status_note: string + } + source_refs: string[] + result_audit_truth: { + p2_102_candidate_dry_run_loaded: true + task_result_route_matrix_ready: true + km_draft_contract_ready: true + logbook_append_contract_ready: true + audit_trail_contract_ready: true + timeline_handoff_contract_ready: true + operator_next_action_ready: true + all_results_have_owner_and_next_step: true + runtime_execution_enabled: false + km_write_enabled: false + logbook_runtime_write_enabled: false + audit_db_write_enabled: false + timeline_write_enabled: false + playbook_trust_write_enabled: false + gateway_queue_write_enabled: false + telegram_send_enabled: false + delivery_receipt_write_enabled: false + production_write_enabled: false + secret_value_read_enabled: false + host_or_cluster_command_enabled: false + destructive_operation_enabled: false + work_window_transcript_display_allowed: false + runtime_execution_count_24h: number + km_write_count_24h: number + logbook_runtime_write_count_24h: number + audit_db_write_count_24h: number + timeline_write_count_24h: number + playbook_trust_write_count_24h: number + gateway_queue_write_count_24h: number + telegram_send_count_24h: number + delivery_receipt_write_count_24h: number + production_write_count_24h: number + secret_value_read_count_24h: number + host_or_cluster_command_count_24h: number + destructive_operation_count_24h: number + truth_note: string + } + result_routes: Array<{ + route_id: string + display_name: string + source_signal: string + result_state: + | 'diagnostic_only' + | 'owner_review_required' + | 'execution_failed' + | 'verified_no_change' + | 'blocked_until_evidence' + | 'blocked_by_policy' + | 'correlation_gap' + | 'report_quality_gap' + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + primary_owner: string + km_target: string + logbook_target: string + audit_target: string + timeline_target: string + operator_next_action: string + blocked_reason: string + writes_live_state: false + requires_owner_review: boolean + ready_for_km_draft: boolean + evidence_hash: string + }> + writeback_contracts: Array<{ + contract_id: string + display_name: string + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + target_system: string + purpose: string + allowed_mode: 'committed_snapshot_only' | 'gated_owner_review' | 'manual_append_plan' + write_enabled: false + runtime_writer_enabled: false + required_fields: string[] + blocker_summary: string + evidence_hash: string + }> + audit_checkpoints: Array<{ + checkpoint_id: string + display_name: string + required_for: string + status: 'ready' | 'needs_owner_review' | 'blocked_by_policy' + failure_if_missing: string + creates_runtime_action: false + }> + operator_handoffs: Array<{ + handoff_id: string + display_name: string + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + human_instruction: string + creates_runtime_action: false + requires_human_review: true + }> + display_redaction_contract: { + redaction_required: true + raw_prompt_display_allowed: false + private_reasoning_display_allowed: false + secret_value_display_allowed: false + raw_telegram_payload_display_allowed: false + work_window_transcript_display_allowed: false + allowed_display_fields: string[] + blocked_display_fields: string[] + } + rollups: { + result_route_count: number + owner_next_action_ready_count: number + requires_owner_review_count: number + ready_for_km_draft_count: number + blocked_result_count: number + writeback_contract_count: number + audit_checkpoint_count: number + operator_handoff_count: number + runtime_execution_count: number + km_write_count: number + logbook_runtime_write_count: number + audit_db_write_count: number + timeline_write_count: number + playbook_trust_write_count: number + gateway_queue_write_count: number + telegram_send_count: number + production_write_count: number + secret_value_read_count: number + destructive_operation_count: number + } +} + export interface AiAgentOwnerApprovedFixtureDryRunSnapshot { schema_version: 'ai_agent_owner_approved_fixture_dry_run_v1' generated_at: string diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index 4e90655b9..1108e8d53 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -1,3 +1,30 @@ +## 2026-06-13|P2-103 任務結果稽核軌跡 + +**背景**:P2-102 已把 13 類候選操作固定成 dry-run evidence、side-effect count、verifier plan 與人工 handoff;統帥持續指出 TG / AwoooP 批准後仍常停在 `learning_recorded`、`manual_review` 或 `no_action`,沒有清楚顯示結果應接到 KM、LOGBOOK、稽核軌跡、timeline 或人工修復下一步。P2-103 補上結果路由契約,讓批准後卡住的狀態能被分類、追蹤與交接。 + +**完成(本地)**: + +- 新增 `ai_agent_task_result_audit_trail_v1` schema、committed snapshot 與 backend loader,強制 KM write、LOGBOOK runtime append、audit DB write、timeline write、PlayBook trust write、Gateway queue write、Telegram send、production write、secret value read、host / cluster command 與 destructive action 全部維持 `false / 0`。 +- 新增 `GET /api/v1/agents/agent-task-result-audit-trail` 只讀 API 與測試;API 只回傳 8 條 result route、6 個 writeback contract、7 個 audit checkpoint 與 5 個 operator handoff,不寫 KM、不 runtime append LOGBOOK、不寫 audit DB、不寫 timeline、不送 Telegram。 +- 治理頁 `/zh-TW/governance?tab=automation-inventory` 新增 P2-103 區塊,顯示任務結果如何接到 KM 草稿、LOGBOOK 證據、audit trail、timeline handoff、PlayBook trust 候選與人工下一步。 +- 更新 `AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md`、`AI_AGENT_INTERACTION_LEARNING_PROOF_2026-06-11.md` 與 MASTER §3.2 / §5,將 P2-103 標記為完成,下一步改為 `P2-104` 修復 `matched_playbook_id` 學習缺口。 + +**驗證(本地)**: + +- `python3 -m json.tool` 檢查 P2-103 snapshot / schema / `zh-TW.json` / `en.json` 通過。 +- `DATABASE_URL='postgresql+asyncpg://test:test@localhost/test' PYTHONPATH=apps/api /Users/ogt/.pyenv/shims/python3.11 -m pytest -q apps/api/tests/test_ai_agent_task_result_audit_trail.py apps/api/tests/test_ai_agent_task_result_audit_trail_api.py`:`10 passed`。 +- `DATABASE_URL='postgresql+asyncpg://test:test@localhost/test' PYTHONPATH=apps/api /Users/ogt/.pyenv/shims/python3.11 -m py_compile apps/api/src/services/ai_agent_task_result_audit_trail.py apps/api/src/api/v1/agents.py` 通過。 +- `cmp -s apps/web/messages/zh-TW.json apps/web/messages/en.json` 通過,兩份訊息檔維持繁體中文鏡像。 +- `pnpm --filter @awoooi/web typecheck` 本地未完成:乾淨 worktree 無 `node_modules`,`tsc` 不存在;磁碟僅約 `3.6GiB` 可用,未在本地重新安裝依賴,改以 Gitea CD runner 的乾淨安裝 / build 作正式 gate。 + +**完成度同步**: + +- P2-103:本地 `99%`;result route `8`、writeback contract `6`、audit checkpoint `7`、operator handoff `5`。 +- KM write、LOGBOOK runtime append、audit DB write、timeline write、PlayBook trust write、Gateway queue write、Telegram send、production write、secret value read、host / cluster command、destructive action:全部仍為 `0`。 +- P2-104:下一步修復 `matched_playbook_id` 學習缺口;完成前不得把 PlayBook trust 更新或 KM 寫入視為已啟用。 + +**邊界**:本段不寫 KM、不 runtime append LOGBOOK、不寫 audit DB、不寫 timeline、不更新 PlayBook trust、不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不啟動 live AI runtime worker、不啟動中低風險 auto worker、不跑 verifier live readback、不讀 secret、不呼叫付費 provider、不執行 host / cluster / destructive action、不提供前端批准 / 執行 / 發送按鈕;不得把 result audit trail 解讀成 runtime loop 已運作。 + ## 2026-06-13|Full-stack live refresh 與 120/121 workload balancing patch **00:13 / 00:24 live refresh:** 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 6854b5baa..05abf108e 100644 --- a/docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md +++ b/docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md @@ -12,7 +12,7 @@ | Nemotron 實際整合應用 | 30% | 完整回放前仍被關卡擋下 | `blocked_needs_evidence`,下一關是 `refresh_source_evidence_then_5_record_smoke_only` | | 工具 / 服務 / 套件 AI 自動化 | 92% | P0 已完成;P1 服務 / runtime / 監控 / provider / service health / 備份 / DR / 套件與供應鏈只讀基線已完成;P1-007 失敗限定通知合約與前端 redaction 合約已完成;下一主線是 P2-004 依賴 / 供應鏈漂移監控 | 狀態分類、盤點 schema、權限矩陣、靜態盤點種子、只讀 API、UI 骨架、驗證、自動化待辦 schema / 快照 / API / 分組 UI、Backup / DR 目標盤點、準備度矩陣、備份通知政策、Backup / DR 證據 UI、復原演練批准包模板、異地 / escrow 準備度狀態、任務批准邊界、確定性進度彙總、Python 套件 / 供應鏈只讀基線、JS pnpm/npm 只讀基線、Docker build surface 只讀基線、CVE / license / drift 嚴重度政策、定期依賴漂移與外部資料來源檢查設計、依賴升級批准包模板、runtime_surface_inventory_v1 schema / snapshot / API / UI、gitea_workflow_runner_health_v1 schema / snapshot / API / UI、observability_contract_matrix_v1 schema / snapshot / API / UI、ai_provider_route_matrix_v1 schema / snapshot / API / UI、service_health_gap_matrix_v1 schema / snapshot / API / UI、service health evidence cards UI、service_health_failure_notification_policy_v1 schema / snapshot / API / UI 已完成 | | OpenClaw / Hermes / NemoTron 佈建布局 | 45% | P1-401 / P1-402 已完成;仍是只讀 layout 與治理頁顯示,不是 runtime deploy | `ai_agent_deployment_layout_v1` schema、`ai_agent_deployment_layout_2026-06-11.json`、`GET /api/v1/agents/agent-deployment-layout`、治理頁自動化盤點 UI、`AI_AGENT_DEPLOYMENT_LAYOUT_2026-06-11.md` | -| OpenClaw / Hermes / NemoTron 主動溝通、學習與成長證據 | 100% | P2-401A 已完成只讀 contract;P2-403A 已完成互動 / 接手 / 學習 / 成長證據面板;P2-403B 已完成 AgentSession / Redis Streams live read model gate;P2-403C 已完成 Redis Streams consumer group dry-run、handoff envelope、ack / dead-letter / replay gate;P2-403D 已完成 learning writeback approval package;P2-403E 已完成 Telegram receipt approval package;P2-403F 已完成 owner-approved learning dry-run preview、人工操作選項與 fixture-only dry-run 總包;P2-403G 已完成 runtime write gate review;P2-403H 已完成 post-write verifier implementation package;P2-403I 已完成 runtime verifier evidence implementation review;P2-403J 已完成報表真相、告警有效性、日週月報、Agent 工作量、圖表化報告、AI 建議與風險自動化政策審查;P2-403K / L / M / N 已把 SRE 戰情室路由、報表派送啟動前閘門、no-write dry-run 與 fixture/readback/verifier dry-run 固定;P2-404 已完成 runtime worker shadow / no-write evidence;P2-101 已完成操作類別權限模型;P2-102 已完成 13 類候選操作 dry-run 證據。runtime worker、DB migration、production Redis consumer group、Telegram 實發、delivery receipt E2E、report delivery、Gateway queue write、AI analysis runtime、中低風險 auto worker、KM / PlayBook trust / timeline / replay score 寫入、SDK / 付費服務仍未開 gate | `ai_agent_communication_learning_contract_v1`、`ai_agent_interaction_learning_proof_v1`、`ai_agent_operation_permission_model_v1`、`ai_agent_candidate_operation_dry_run_evidence_v1`、`GET /api/v1/agents/agent-operation-permission-model`、`GET /api/v1/agents/agent-candidate-operation-dry-run-evidence`、`/zh-TW/governance?tab=automation-inventory`、MASTER §3.2.1b / §3.2.1d / §3.4.3 | +| OpenClaw / Hermes / NemoTron 主動溝通、學習與成長證據 | 100% | P2-401A 已完成只讀 contract;P2-403A 已完成互動 / 接手 / 學習 / 成長證據面板;P2-403B 已完成 AgentSession / Redis Streams live read model gate;P2-403C 已完成 Redis Streams consumer group dry-run、handoff envelope、ack / dead-letter / replay gate;P2-403D 已完成 learning writeback approval package;P2-403E 已完成 Telegram receipt approval package;P2-403F 已完成 owner-approved learning dry-run preview、人工操作選項與 fixture-only dry-run 總包;P2-403G 已完成 runtime write gate review;P2-403H 已完成 post-write verifier implementation package;P2-403I 已完成 runtime verifier evidence implementation review;P2-403J 已完成報表真相、告警有效性、日週月報、Agent 工作量、圖表化報告、AI 建議與風險自動化政策審查;P2-403K / L / M / N 已把 SRE 戰情室路由、報表派送啟動前閘門、no-write dry-run 與 fixture/readback/verifier dry-run 固定;P2-404 已完成 runtime worker shadow / no-write evidence;P2-101 已完成操作類別權限模型;P2-102 已完成 13 類候選操作 dry-run 證據;P2-103 已完成任務結果稽核軌跡。runtime worker、DB migration、production Redis consumer group、Telegram 實發、delivery receipt E2E、report delivery、Gateway queue write、AI analysis runtime、中低風險 auto worker、KM / LOGBOOK / audit DB / timeline / PlayBook trust 寫入、SDK / 付費服務仍未開 gate | `ai_agent_communication_learning_contract_v1`、`ai_agent_interaction_learning_proof_v1`、`ai_agent_operation_permission_model_v1`、`ai_agent_candidate_operation_dry_run_evidence_v1`、`ai_agent_task_result_audit_trail_v1`、`GET /api/v1/agents/agent-operation-permission-model`、`GET /api/v1/agents/agent-candidate-operation-dry-run-evidence`、`GET /api/v1/agents/agent-task-result-audit-trail`、`/zh-TW/governance?tab=automation-inventory`、MASTER §3.2.1b / §3.2.1d / §3.4.3 | | AI Agent 主動營運委派與版本生命週期 | 100% | P2-402A / P2-402B / P2-402C / P2-402D / P2-402E / P2-402F / P2-402G 已完成;已建立 repo-only 版本新鮮度快照、工具採用批准包、Telegram action-required digest policy、Gitea PR 草案 lane、host / K3s / stateful 版本只讀盤點、API 與 governance UI。定期排程、外部版本查詢、工具安裝、CI 變更、套件升級、主機更新、container pull、實際 PR creation、auto merge、Telegram 實發、SSH、kubectl、重啟仍未開 gate | `ai_agent_proactive_operations_contract_v1`、`ai_agent_version_freshness_snapshot_v1`、`ai_agent_tool_adoption_approval_package_v1`、`ai_agent_telegram_action_required_digest_policy_v1`、`ai_agent_gitea_pr_draft_lane_v1`、`ai_agent_host_stateful_version_inventory_v1`、`GET /api/v1/agents/agent-proactive-operations-contract`、`GET /api/v1/agents/agent-version-freshness-snapshot`、`GET /api/v1/agents/agent-tool-adoption-approval-package`、`GET /api/v1/agents/agent-telegram-action-required-digest-policy`、`GET /api/v1/agents/agent-gitea-pr-draft-lane`、`GET /api/v1/agents/agent-host-stateful-version-inventory`、`/zh-TW/governance?tab=automation-inventory`、MASTER §3.2.1c | | 本工作清單與分析報告 | 100% | 已完成 | 本 MD 文件 | @@ -20,9 +20,9 @@ AI Agent 自動化工作包目前完成度:**92%**。本工作清單文件本 三 Agent 佈建布局目前完成度:**45%**。第一波已完成只讀 schema / snapshot / API / 測試 / 報告,第二波已接入治理頁自動化盤點 UI;正式 runtime 佈署、Telegram E2E 發送與 AgentSession 工作流仍需逐項 gate。 -三 Agent 主動溝通、學習與成長證據目前完成度:**100%**。已完成只讀契約、互動 / 接手 / 學習 / 成長證據面板、P2-403B live read model gate、P2-403C Redis dry-run gate、P2-403D learning writeback approval package、P2-403E Telegram receipt approval package、P2-403F owner-approved learning dry-run preview、P2-403G runtime write gate review、P2-403H post-write verifier implementation package、P2-403I runtime verifier evidence implementation review、P2-403J 報表真相 / 告警有效性 / 日週月報 / Agent 工作量 / 圖表化報告 / AI 建議 / 風險自動化政策審查、P2-403K/L/M/N 報表與 SRE 戰情室 dry-run 鏈、P2-404 runtime worker shadow / no-write execution evidence gate、P2-101 操作類別權限模型,以及 P2-102 候選操作 dry-run 證據;目前 live AgentSession、Agent message、handoff、learning write、Telegram receipt、Gateway queue write、runtime verifier execution、report delivery、AI analysis runtime、中低風險 auto worker、Telegram 實發、shadow worker live 與 delivery receipt E2E 仍全部為 `0`,下一步依優先順序推 `P2-103`,把任務結果接回 KM / LOGBOOK / 稽核軌跡。 +三 Agent 主動溝通、學習與成長證據目前完成度:**100%**。已完成只讀契約、互動 / 接手 / 學習 / 成長證據面板、P2-403B live read model gate、P2-403C Redis dry-run gate、P2-403D learning writeback approval package、P2-403E Telegram receipt approval package、P2-403F owner-approved learning dry-run preview、P2-403G runtime write gate review、P2-403H post-write verifier implementation package、P2-403I runtime verifier evidence implementation review、P2-403J 報表真相 / 告警有效性 / 日週月報 / Agent 工作量 / 圖表化報告 / AI 建議 / 風險自動化政策審查、P2-403K/L/M/N 報表與 SRE 戰情室 dry-run 鏈、P2-404 runtime worker shadow / no-write execution evidence gate、P2-101 操作類別權限模型、P2-102 候選操作 dry-run 證據,以及 P2-103 任務結果稽核軌跡;目前 live AgentSession、Agent message、handoff、learning write、Telegram receipt、Gateway queue write、runtime verifier execution、report delivery、AI analysis runtime、中低風險 auto worker、Telegram 實發、shadow worker live、delivery receipt E2E、KM / LOGBOOK / audit DB / timeline / PlayBook trust runtime 寫入仍全部為 `0`,下一步依優先順序推 `P2-104`,修復 `matched_playbook_id` 學習缺口。 -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-102` 已補互動、學習證據面、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 證據。下一步是 `P2-103` 結果寫回治理軌跡;外部 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-103` 已補互動、學習證據面、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 證據與任務結果稽核軌跡。下一步是 `P2-104` 修復 `matched_playbook_id` 學習缺口;外部 registry / package source / host probe / SSH / kubectl / 工具安裝 / CI 變更 / 實際 PR creation / Telegram 實發與 learning write 仍需 gate。 完成度計算模型: @@ -974,8 +974,8 @@ UI: | P2-403N | 完成 | 94 | Hermes + NemoTron + OpenClaw | fixture smoke / queue preview readback / verifier dry-run | `ai_agent_report_runtime_fixture_readback_v1` / snapshot / 只讀 API / governance UI;5 個 fixture smoke、3 個 queue preview readback、4 個 verifier dry-run case、3 個 Agent fixture role、5 個 operator checkpoint;live delivery / queue write / Telegram send / Bot API / receipt write / AI runtime / 中低風險 auto worker / verifier live readback 全部 `0` | 仍不得 live send / live write;中低風險自動處理與高風險審核需另行批准 | | P2-404 | 完成 | 96 | OpenClaw + Hermes + NemoTron | runtime worker shadow / no-write execution evidence gate | `ai_agent_runtime_worker_shadow_gate_v1` / snapshot / 只讀 API / governance UI;5 個 shadow candidate、4 個 no-write replay、4 個 verifier shadow case、3 個 Agent shadow role、6 個 operator checkpoint;shadow live / Gateway queue write / Telegram send / Bot API / receipt write / AI runtime / 中低風險 auto worker / verifier live readback / production write 全部 `0` | 下一步 P2-101 操作類別權限模型;未完成前不得 live worker、queue write、Telegram send 或 production write | | P2-101 | 完成 | 97 | OpenClaw + Hermes + NemoTron | 定義操作類別權限模型 | `ai_agent_operation_permission_model_v1` / snapshot / 只讀 API / governance UI;5 條 permission lane、13 類操作、3 個 Agent permission role、8 個 gate transition、5 個人工操作模板;runtime execution / Gateway queue write / Telegram send / Bot API / receipt write / AI runtime worker / 中低風險 auto worker / verifier live readback / production write / secret read / paid provider / host command / destructive action 全部 `0` | 已由 P2-102 承接;不得把權限模型解讀成 runtime 授權 | -| P2-102 | 完成 | 98 | OpenClaw + Hermes + NemoTron | 所有候選操作都要有 dry-run 證據 | `ai_agent_candidate_operation_dry_run_evidence_v1` / snapshot / 只讀 API / governance UI;13 類候選操作、13 組 dry-run evidence、6 個 verifier plan、7 個 gate evidence requirement、5 個 operator handoff;side-effect / runtime / queue / Telegram / production write / secret / destructive 全部 `0` | 下一步 P2-103 把任務結果接回 KM / LOGBOOK / 稽核軌跡;不直接 apply、不送 Telegram、不寫 Gateway queue | -| P2-103 | 待辦 | 0 | Hermes | 把任務結果接回 KM / LOGBOOK / 稽核軌跡 | 證據寫入器 | 不洩漏 secret | +| P2-102 | 完成 | 98 | OpenClaw + Hermes + NemoTron | 所有候選操作都要有 dry-run 證據 | `ai_agent_candidate_operation_dry_run_evidence_v1` / snapshot / 只讀 API / governance UI;13 類候選操作、13 組 dry-run evidence、6 個 verifier plan、7 個 gate evidence requirement、5 個 operator handoff;side-effect / runtime / queue / Telegram / production write / secret / destructive 全部 `0` | 已由 P2-103 承接;不直接 apply、不送 Telegram、不寫 Gateway queue | +| P2-103 | 完成 | 99 | Hermes + OpenClaw | 把任務結果接回 KM / LOGBOOK / 稽核軌跡 | `ai_agent_task_result_audit_trail_v1` / snapshot / 只讀 API / governance UI;8 條 result route、6 個 writeback contract、7 個 audit checkpoint、5 個 operator handoff;KM / LOGBOOK / audit DB / timeline / PlayBook trust / queue / Telegram 寫入全為 `0` | 已由 P2-104 承接;不寫 KM、不 runtime append LOGBOOK、不寫 audit DB、不送 Telegram | | P2-104 | 待辦 | 0 | OpenClaw | 修復 `matched_playbook_id` 學習缺口 | playbook trust 更新 | 測試 + live 證據 | | P2-105 | 待辦 | 0 | OpenClaw | 批准前加入 critic / reviewer 評分 | 多 Agent 評分 | 不自動批准 | diff --git a/docs/ai/AI_AGENT_INTERACTION_LEARNING_PROOF_2026-06-11.md b/docs/ai/AI_AGENT_INTERACTION_LEARNING_PROOF_2026-06-11.md index 999758d40..f57c5a233 100644 --- a/docs/ai/AI_AGENT_INTERACTION_LEARNING_PROOF_2026-06-11.md +++ b/docs/ai/AI_AGENT_INTERACTION_LEARNING_PROOF_2026-06-11.md @@ -1,8 +1,8 @@ # AI Agent 互動、溝通、學習與成長證據報告 > 日期:2026-06-11(台北時間) -> 文件定位:P2-403A 證據面 + P2-403B AgentSession / Redis Streams live read model gate + P2-403C Redis dry-run gate + P2-403D learning writeback approval package + P2-403E Telegram receipt approval package + P2-403F owner-approved learning dry-run / fixture dry-run、P2-403G runtime write gate review、P2-403H post-write verifier package、P2-403I runtime verifier evidence implementation review、P2-403J 報表真相 / 日週月報 / Agent 工作量 / 風險自動化 review、P2-403L 報表派送與自動處理啟動前閘門、P2-403M 報表 runtime no-write dry-run 證據包、P2-403N fixture smoke / queue preview readback / verifier dry-run、P2-404 runtime worker shadow / no-write execution evidence gate、P2-101 操作類別權限模型、P2-102 候選操作 dry-run 證據、API 與治理頁 UI。 -> 事實邊界:本波只建立可見證據面、read model gate、報表治理 review、runtime readiness gate、no-write dry-run、fixture/readback/verifier dry-run、shadow/no-write execution 證據包、operation permission lane 與 candidate dry-run evidence,不啟動 runtime worker、不建立 DB migration、不開 Redis consumer group、不發 Telegram、不寫 Gateway queue、不寫 delivery receipt、不排程實發報告、不啟動中低風險 auto worker、不執行 verifier live readback、不執行生產優化、不顯示內部協作內容。 +> 文件定位:P2-403A 證據面 + P2-403B AgentSession / Redis Streams live read model gate + P2-403C Redis dry-run gate + P2-403D learning writeback approval package + P2-403E Telegram receipt approval package + P2-403F owner-approved learning dry-run / fixture dry-run、P2-403G runtime write gate review、P2-403H post-write verifier package、P2-403I runtime verifier evidence implementation review、P2-403J 報表真相 / 日週月報 / Agent 工作量 / 風險自動化 review、P2-403L 報表派送與自動處理啟動前閘門、P2-403M 報表 runtime no-write dry-run 證據包、P2-403N fixture smoke / queue preview readback / verifier dry-run、P2-404 runtime worker shadow / no-write execution evidence gate、P2-101 操作類別權限模型、P2-102 候選操作 dry-run 證據、P2-103 任務結果稽核軌跡、API 與治理頁 UI。 +> 事實邊界:本波只建立可見證據面、read model gate、報表治理 review、runtime readiness gate、no-write dry-run、fixture/readback/verifier dry-run、shadow/no-write execution 證據包、operation permission lane、candidate dry-run evidence 與 result audit trail,不啟動 runtime worker、不建立 DB migration、不開 Redis consumer group、不發 Telegram、不寫 Gateway queue、不寫 delivery receipt、不排程實發報告、不啟動中低風險 auto worker、不執行 verifier live readback、不寫 KM、不 runtime append LOGBOOK、不寫 audit DB、不寫 timeline、不執行生產優化、不顯示內部協作內容。 ## 0. P2-403J 補記:報表真相、日週月報與風險自動化 Review @@ -46,9 +46,15 @@ 本段把 P2-101 的 13 類操作轉成候選操作 dry-run 證據:13 類 candidate operation、13 組 input / output evidence hash、6 個 verifier plan、7 個 gate evidence requirement 與 5 個 operator handoff。OpenClaw 負責修復候選、風險阻擋與 destructive gate;Hermes 負責報表 / SRE 戰情室 queue preview 與補證 handoff;NemoTron 負責 no-write replay、verifier allow-list、redaction / cost / secret boundary。所有 side-effect、runtime execution、Gateway queue write、Telegram send、production write、secret value read、paid provider call、host / cluster command 與 destructive action 仍為 `0`。 +## 0.7 P2-103 補記:任務結果稽核軌跡 + +2026-06-13 已新增 P2-103:`ai_agent_task_result_audit_trail_v1`、`docs/evaluations/ai_agent_task_result_audit_trail_2026-06-13.json`、`GET /api/v1/agents/agent-task-result-audit-trail` 與治理頁區塊。 + +本段把 P2-102 的候選操作結果轉成可追蹤結果路由:8 條 result route、6 個 writeback contract、7 個 audit checkpoint 與 5 個 operator handoff。OpenClaw 負責 execution failed、repair candidate、provider correlation gap 與 policy block 的結果分類;Hermes 負責 KM owner-review 草稿、LOGBOOK evidence append 計畫、報表品質缺口與人工交接;NemoTron 負責 PlayBook trust 候選與 redaction / policy boundary。所有 KM write、LOGBOOK runtime append、audit DB write、timeline write、PlayBook trust write、Gateway queue write、Telegram send、production write、secret value read 與 destructive action 仍為 `0`。 + ## 1. 結論 -已完成 P2-403A、P2-403B、P2-403C、P2-403D、P2-403E、P2-403F、P2-403G、P2-403H、P2-403I、P2-403J、P2-403L、P2-403M、P2-403N、P2-404、P2-101 與 P2-102:讓統帥能在治理頁看到 OpenClaw / Hermes / NemoTron 的互動、接手、學習與成長是否真的有證據,並看到 live read model、Redis dry-run、handoff envelope、ack / dead-letter / replay、learning writeback approval、Telegram receipt approval、fixture dry-run、runtime write gate review、post-write verifier package、runtime verifier evidence review、報表真相、日週月報、Agent 工作量、圖表化報告、風險自動化政策、報表 runtime 啟動前閘門、no-write dry-run 證據包、fixture/readback/verifier dry-run 證據包、shadow/no-write execution evidence gate、操作類別權限模型與候選操作 dry-run 證據下一步要通過哪些 gate。 +已完成 P2-403A、P2-403B、P2-403C、P2-403D、P2-403E、P2-403F、P2-403G、P2-403H、P2-403I、P2-403J、P2-403L、P2-403M、P2-403N、P2-404、P2-101、P2-102 與 P2-103:讓統帥能在治理頁看到 OpenClaw / Hermes / NemoTron 的互動、接手、學習與成長是否真的有證據,並看到 live read model、Redis dry-run、handoff envelope、ack / dead-letter / replay、learning writeback approval、Telegram receipt approval、fixture dry-run、runtime write gate review、post-write verifier package、runtime verifier evidence review、報表真相、日週月報、Agent 工作量、圖表化報告、風險自動化政策、報表 runtime 啟動前閘門、no-write dry-run 證據包、fixture/readback/verifier dry-run 證據包、shadow/no-write execution evidence gate、操作類別權限模型、候選操作 dry-run 證據與任務結果稽核軌跡下一步要通過哪些 gate。 目前真相: @@ -73,6 +79,7 @@ | P2-404 runtime worker shadow gate | 已完成,shadow worker live / queue write / Telegram send / production write 全為 `0` | | P2-101 operation permission model | 已完成,13 類操作已歸入只讀 / no-write replay / 提案 / 人工批准 / 明確阻擋,runtime execution / queue write / Telegram send / production write 全為 `0` | | P2-102 candidate dry-run evidence | 已完成,13 類候選操作已有 dry-run evidence、verifier plan 與 operator handoff,所有 side-effect / runtime / queue / send / write 全為 `0` | +| P2-103 task result audit trail | 已完成,8 條結果路由已接到 KM 草稿、LOGBOOK 證據、audit trail、timeline 與人工交接契約,所有 KM / LOGBOOK / audit / timeline / queue / send 寫入全為 `0` | 這代表使用者現在可以看見「哪裡已準備好、哪裡仍未運作、被哪個 gate 阻擋、下一步要如何驗證」。但還不能宣稱三個 Agent 已經在 production runtime 主動互傳訊息或自主學習。 @@ -140,17 +147,20 @@ | `docs/schemas/ai_agent_candidate_operation_dry_run_evidence_v1.schema.json` | P2-102 候選操作 dry-run 證據 schema;強制 side-effect、runtime execution、queue write、Telegram send、production write、secret / paid provider 與 destructive action 維持 `0 / false` | | `docs/evaluations/ai_agent_candidate_operation_dry_run_evidence_2026-06-12.json` | P2-102 committed snapshot,完成度 `98%`,13 類候選操作、13 組 dry-run evidence、6 個 verifier plan、7 個 gate evidence requirement、5 個 operator handoff;所有 live counts 全為 `0` | | `GET /api/v1/agents/agent-candidate-operation-dry-run-evidence` | 只讀 API;不啟動 runtime worker、不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 production target、不讀 secret、不執行 destructive action | +| `docs/schemas/ai_agent_task_result_audit_trail_v1.schema.json` | P2-103 任務結果稽核軌跡 schema;強制 KM write、LOGBOOK runtime append、audit DB write、timeline write、PlayBook trust write、Gateway queue write、Telegram send、production write 與 secret read 維持未授權 | +| `docs/evaluations/ai_agent_task_result_audit_trail_2026-06-13.json` | P2-103 committed snapshot,完成度 `99%`,8 條 result route、6 個 writeback contract、7 個 audit checkpoint、5 個 operator handoff;所有 live write / send counts 全為 `0` | +| `GET /api/v1/agents/agent-task-result-audit-trail` | 只讀 API;不寫 KM、不 runtime append LOGBOOK、不寫 audit DB、不寫 timeline、不更新 PlayBook trust、不寫 Gateway queue、不送 Telegram | | `apps/api/src/services/ai_agent_interaction_learning_proof.py` | 只讀 loader 與安全驗證 | | `apps/api/src/services/ai_agent_live_read_model_gate.py` | P2-403B 只讀 loader;拒絕 live DB query、Redis consumer、unsafe fields、Telegram 與 writeback | | `GET /api/v1/agents/agent-interaction-learning-proof` | 只讀 API,不啟動 worker、不碰 Redis / DB runtime、不發 Telegram | | `GET /api/v1/agents/agent-live-read-model-gate` | 只讀 API,不連 DB、不讀寫 Redis、不發 Telegram | -| governance UI | 新增證據階梯、目前真相、P2-403B live read gate、P2-403C Redis dry-run gate、P2-403D learning writeback approval package、P2-403E Telegram receipt approval package、P2-403F owner-approved learning dry-run / fixture dry-run、P2-403G runtime write gate review、P2-403H post-write verifier package、P2-403I runtime verifier evidence review、P2-403J 報表真相 / 日週月報 / Agent 工作量 / 圖表 / AI 建議、P2-403L 報表 runtime readiness、P2-403M no-write dry-run、P2-403N fixture readback、P2-404 shadow gate、P2-101 operation permission model、P2-102 candidate dry-run evidence、Agent lane、可觀測訊號、runtime gates、前端 redaction | +| governance UI | 新增證據階梯、目前真相、P2-403B live read gate、P2-403C Redis dry-run gate、P2-403D learning writeback approval package、P2-403E Telegram receipt approval package、P2-403F owner-approved learning dry-run / fixture dry-run、P2-403G runtime write gate review、P2-403H post-write verifier package、P2-403I runtime verifier evidence review、P2-403J 報表真相 / 日週月報 / Agent 工作量 / 圖表 / AI 建議、P2-403L 報表 runtime readiness、P2-403M no-write dry-run、P2-403N fixture readback、P2-404 shadow gate、P2-101 operation permission model、P2-102 candidate dry-run evidence、P2-103 task result audit trail、Agent lane、可觀測訊號、runtime gates、前端 redaction | ## 5. 後續優先順序 | 優先 | ID | 工作 | gate | |---:|---|---|---| -| 1 | P2-103 | 把任務結果接回 KM / LOGBOOK / 稽核軌跡 | 證據寫入器 | +| 1 | P2-104 | 修復 `matched_playbook_id` 學習缺口 | PlayBook trust 候選與結果回寫 gate | ## 6. 紅線 diff --git a/docs/evaluations/ai_agent_task_result_audit_trail_2026-06-13.json b/docs/evaluations/ai_agent_task_result_audit_trail_2026-06-13.json new file mode 100644 index 000000000..e447d8af4 --- /dev/null +++ b/docs/evaluations/ai_agent_task_result_audit_trail_2026-06-13.json @@ -0,0 +1,434 @@ +{ + "schema_version": "ai_agent_task_result_audit_trail_v1", + "generated_at": "2026-06-13T10:20:00+08:00", + "program_status": { + "overall_completion_percent": 99, + "current_priority": "P2", + "current_task_id": "P2-103", + "next_task_id": "P2-104", + "read_only_mode": true, + "runtime_authority": "task_result_audit_trail_contract_only_no_live_writeback", + "status_note": "P2-103 承接 P2-102 候選操作 dry-run 證據,把任務結果固定成 KM 草稿、LOGBOOK 證據、稽核軌跡、timeline 與人工交接的結果路由契約;目前仍不寫 KM、不 runtime append LOGBOOK、不寫 audit DB、不寫 timeline、不更新 PlayBook trust、不寫 Gateway queue、不送 Telegram。" + }, + "source_refs": [ + "docs/evaluations/ai_agent_candidate_operation_dry_run_evidence_2026-06-12.json", + "docs/evaluations/ai_agent_operation_permission_model_2026-06-12.json", + "docs/evaluations/ai_agent_report_runtime_fixture_readback_2026-06-12.json", + "docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md", + "docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md" + ], + "result_audit_truth": { + "p2_102_candidate_dry_run_loaded": true, + "task_result_route_matrix_ready": true, + "km_draft_contract_ready": true, + "logbook_append_contract_ready": true, + "audit_trail_contract_ready": true, + "timeline_handoff_contract_ready": true, + "operator_next_action_ready": true, + "all_results_have_owner_and_next_step": true, + "runtime_execution_enabled": false, + "km_write_enabled": false, + "logbook_runtime_write_enabled": false, + "audit_db_write_enabled": false, + "timeline_write_enabled": false, + "playbook_trust_write_enabled": false, + "gateway_queue_write_enabled": false, + "telegram_send_enabled": false, + "delivery_receipt_write_enabled": false, + "production_write_enabled": false, + "secret_value_read_enabled": false, + "host_or_cluster_command_enabled": false, + "destructive_operation_enabled": false, + "work_window_transcript_display_allowed": false, + "runtime_execution_count_24h": 0, + "km_write_count_24h": 0, + "logbook_runtime_write_count_24h": 0, + "audit_db_write_count_24h": 0, + "timeline_write_count_24h": 0, + "playbook_trust_write_count_24h": 0, + "gateway_queue_write_count_24h": 0, + "telegram_send_count_24h": 0, + "delivery_receipt_write_count_24h": 0, + "production_write_count_24h": 0, + "secret_value_read_count_24h": 0, + "host_or_cluster_command_count_24h": 0, + "destructive_operation_count_24h": 0, + "truth_note": "本段只把任務結果的去向與卡點固定成 committed evidence contract;所有 KM / LOGBOOK / audit / timeline / PlayBook trust / Gateway / Telegram / production write 仍是 0 / false。" + }, + "result_routes": [ + { + "route_id": "result_diagnostic_no_action", + "display_name": "診斷完成但無修復動作", + "source_signal": "diagnostic_only_manual_review", + "result_state": "diagnostic_only", + "owner_agent": "openclaw", + "primary_owner": "SRE operator", + "km_target": "KM 草稿:記錄診斷條件、無修復原因與下次補證欄位", + "logbook_target": "LOGBOOK 證據:只記錄 committed snapshot 與 decision reason", + "audit_target": "audit trail:result=diagnostic_only_no_action", + "timeline_target": "timeline handoff:manual_review_no_action", + "operator_next_action": "人工確認是否接受無修復結論;若不接受,改走補證或修復候選 review。", + "blocked_reason": "未產生 verified repair result,不能標記自動修復成功。", + "writes_live_state": false, + "requires_owner_review": true, + "ready_for_km_draft": true, + "evidence_hash": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "route_id": "result_repair_candidate_needs_owner", + "display_name": "修復候選等待 owner 審查", + "source_signal": "repair_candidate_draft", + "result_state": "owner_review_required", + "owner_agent": "openclaw", + "primary_owner": "service owner", + "km_target": "KM 草稿:保留 MCP evidence、PlayBook trust 與 rollback/no-op plan", + "logbook_target": "LOGBOOK 證據:記錄候選、風險、owner gate 與 verifier plan", + "audit_target": "audit trail:result=repair_candidate_waiting_owner", + "timeline_target": "timeline handoff:owner_review_playbook_trust_gate", + "operator_next_action": "owner 檢查 evidence hash、PlayBook trust、rollback owner 與 maintenance window;缺一項就退回補證。", + "blocked_reason": "owner response、rollback owner 或 verifier plan 尚未接受。", + "writes_live_state": false, + "requires_owner_review": true, + "ready_for_km_draft": true, + "evidence_hash": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "route_id": "result_execution_failed_manual", + "display_name": "執行失敗需人工修復或回滾", + "source_signal": "execution_failed_manual_required", + "result_state": "execution_failed", + "owner_agent": "openclaw", + "primary_owner": "SRE incident commander", + "km_target": "KM 草稿:保留失敗類型、失敗命令遮蔽摘要、人工修復缺口與 verifier mismatch", + "logbook_target": "LOGBOOK 證據:只記錄結果分類、失敗 lane、下一步與 production smoke 狀態", + "audit_target": "audit trail:result=execution_failed_manual_fix_or_rollback", + "timeline_target": "timeline handoff:manual_fix_or_rollback", + "operator_next_action": "SRE 決定人工修復、回滾或補證;AI 只能提供 no-write SOP,不自動再執行。", + "blocked_reason": "verifier degraded 或 execution failed,不能自動宣告 resolved。", + "writes_live_state": false, + "requires_owner_review": true, + "ready_for_km_draft": true, + "evidence_hash": "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "route_id": "result_verified_no_change", + "display_name": "只讀驗證通過但未變更", + "source_signal": "verified_no_write", + "result_state": "verified_no_change", + "owner_agent": "hermes", + "primary_owner": "governance reviewer", + "km_target": "KM 草稿:標記只讀驗證方法與適用限制", + "logbook_target": "LOGBOOK 證據:記錄 API / UI / smoke readback 與 no-write 邊界", + "audit_target": "audit trail:result=verified_no_change", + "timeline_target": "timeline handoff:read_only_verified", + "operator_next_action": "治理 reviewer 決定是否把 read-only 方法納入 Runbook;不需 runtime 修復。", + "blocked_reason": "沒有 live write,不能當成修復已執行。", + "writes_live_state": false, + "requires_owner_review": false, + "ready_for_km_draft": true, + "evidence_hash": "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + }, + { + "route_id": "result_evidence_missing", + "display_name": "證據缺口等待補齊", + "source_signal": "repair_candidate_missing_evidence", + "result_state": "blocked_until_evidence", + "owner_agent": "hermes", + "primary_owner": "evidence owner", + "km_target": "KM 草稿:只列缺口欄位,不固化未驗證結論", + "logbook_target": "LOGBOOK 證據:記錄缺口清單與補證 deadline", + "audit_target": "audit trail:result=blocked_until_evidence", + "timeline_target": "timeline handoff:collect_repair_evidence", + "operator_next_action": "補 MCP / Sentry / SigNoz / host log / PlayBook trust evidence;補完後重新跑 dry-run review。", + "blocked_reason": "MCP / provider / verifier evidence 不足。", + "writes_live_state": false, + "requires_owner_review": true, + "ready_for_km_draft": false, + "evidence_hash": "sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + }, + { + "route_id": "result_policy_blocked", + "display_name": "政策阻擋或明確禁止", + "source_signal": "blocked_by_policy", + "result_state": "blocked_by_policy", + "owner_agent": "nemotron", + "primary_owner": "security reviewer", + "km_target": "KM 草稿:只記錄 policy reason 與替代 no-op 方案", + "logbook_target": "LOGBOOK 證據:記錄阻擋規則、紅線與禁止操作", + "audit_target": "audit trail:result=blocked_by_policy", + "timeline_target": "timeline handoff:security_policy_block", + "operator_next_action": "安全 reviewer 決定是否建立新批准包;未批准前保持 blocked。", + "blocked_reason": "觸及 secret / paid provider / destructive / production write 紅線。", + "writes_live_state": false, + "requires_owner_review": true, + "ready_for_km_draft": false, + "evidence_hash": "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + }, + { + "route_id": "result_provider_unmatched", + "display_name": "供應者新鮮但未匹配 Incident", + "source_signal": "provider_fresh_but_unmatched", + "result_state": "correlation_gap", + "owner_agent": "openclaw", + "primary_owner": "observability owner", + "km_target": "KM 草稿:記錄 source correlation 規則缺口,避免寫成服務已修復", + "logbook_target": "LOGBOOK 證據:記錄 provider refs、candidate count 與未匹配原因", + "audit_target": "audit trail:result=provider_correlation_gap", + "timeline_target": "timeline handoff:review_provider_source_match", + "operator_next_action": "檢查 Sentry / SigNoz / Alertmanager / K8s source id 對應;需要時建立 source correlation review。", + "blocked_reason": "provider 有心跳但事件尚未關聯到 Incident。", + "writes_live_state": false, + "requires_owner_review": true, + "ready_for_km_draft": false, + "evidence_hash": "sha256:1111111111111111111111111111111111111111111111111111111111111111" + }, + { + "route_id": "result_report_zero_signal", + "display_name": "日週月報全 0 或低可信", + "source_signal": "report_zero_signal_low_confidence", + "result_state": "report_quality_gap", + "owner_agent": "hermes", + "primary_owner": "report owner", + "km_target": "KM 草稿:記錄報表資料鏈路缺口與可信度判定", + "logbook_target": "LOGBOOK 證據:記錄日報 / 週報 / 月報資料來源、缺口與 actionability", + "audit_target": "audit trail:result=report_quality_gap", + "timeline_target": "timeline handoff:report_source_quality_review", + "operator_next_action": "檢查告警、AI 提案、部署、成本、token、K3s 指標資料源;全 0 不可當健康。", + "blocked_reason": "報表缺少有效資料來源或 ingestion readback。", + "writes_live_state": false, + "requires_owner_review": true, + "ready_for_km_draft": true, + "evidence_hash": "sha256:2222222222222222222222222222222222222222222222222222222222222222" + } + ], + "writeback_contracts": [ + { + "contract_id": "contract_km_review_draft", + "display_name": "KM owner-review 草稿", + "owner_agent": "hermes", + "target_system": "knowledge_base", + "purpose": "把已驗證或需補證的結果轉成 owner review 草稿,避免 AI 直接固化錯知識。", + "allowed_mode": "gated_owner_review", + "write_enabled": false, + "runtime_writer_enabled": false, + "required_fields": ["result_route_id", "evidence_hash", "owner", "source_refs", "next_action"], + "blocker_summary": "owner review gate 尚未啟用;不可自動寫入高影響 KM。", + "evidence_hash": "sha256:3333333333333333333333333333333333333333333333333333333333333333" + }, + { + "contract_id": "contract_logbook_evidence_append", + "display_name": "LOGBOOK 證據補記契約", + "owner_agent": "hermes", + "target_system": "docs_logbook", + "purpose": "把已部署、已 smoke 或只讀驗證結果整理成可人工提交的 LOGBOOK entry。", + "allowed_mode": "manual_append_plan", + "write_enabled": false, + "runtime_writer_enabled": false, + "required_fields": ["commit", "deploy_marker", "api_readback", "browser_smoke", "runtime_boundary"], + "blocker_summary": "runtime 不得自動改 repo;LOGBOOK 只能經一般 git review / commit 流程。", + "evidence_hash": "sha256:4444444444444444444444444444444444444444444444444444444444444444" + }, + { + "contract_id": "contract_audit_trail_entry", + "display_name": "稽核軌跡 entry contract", + "owner_agent": "openclaw", + "target_system": "governance_audit", + "purpose": "固定 result_state、decision reason、blocked reason、operator next action 與 redacted evidence refs。", + "allowed_mode": "committed_snapshot_only", + "write_enabled": false, + "runtime_writer_enabled": false, + "required_fields": ["result_state", "decision_reason", "blocked_reason", "operator_next_action", "redacted_evidence_refs"], + "blocker_summary": "audit DB writer 尚未批准;目前只回傳契約與 committed snapshot。", + "evidence_hash": "sha256:5555555555555555555555555555555555555555555555555555555555555555" + }, + { + "contract_id": "contract_incident_timeline_handoff", + "display_name": "Incident timeline handoff", + "owner_agent": "openclaw", + "target_system": "incident_timeline", + "purpose": "讓 Operator 可看見目前階段、誰處理、AI 做了什麼、是否需要人工。", + "allowed_mode": "gated_owner_review", + "write_enabled": false, + "runtime_writer_enabled": false, + "required_fields": ["stage", "owner_agent", "operator_next_action", "manual_required", "blocked_reason"], + "blocker_summary": "timeline writer 尚未批准;不可把 UI 顯示當成 timeline 已寫入。", + "evidence_hash": "sha256:6666666666666666666666666666666666666666666666666666666666666666" + }, + { + "contract_id": "contract_playbook_trust_candidate", + "display_name": "PlayBook trust 候選更新", + "owner_agent": "nemotron", + "target_system": "playbook_trust", + "purpose": "把修復成功 / 失敗 / no-op / policy block 結果轉成 trust score 候選,不直接套用。", + "allowed_mode": "gated_owner_review", + "write_enabled": false, + "runtime_writer_enabled": false, + "required_fields": ["playbook_id", "result_state", "verifier_result", "owner_review", "rollback_context"], + "blocker_summary": "P2-104 才修復 matched_playbook_id 學習缺口;目前只保留候選 contract。", + "evidence_hash": "sha256:7777777777777777777777777777777777777777777777777777777777777777" + }, + { + "contract_id": "contract_operator_handoff_packet", + "display_name": "人工交接封包", + "owner_agent": "hermes", + "target_system": "awooop_operator_console", + "purpose": "把 TG / AwoooP approval 後卡住的項目轉成可理解的人工下一步與補證清單。", + "allowed_mode": "committed_snapshot_only", + "write_enabled": false, + "runtime_writer_enabled": false, + "required_fields": ["incident_id", "route_id", "current_stage", "next_action", "missing_evidence", "owner"], + "blocker_summary": "operator console writeback 尚未批准;目前只展示下一步 contract。", + "evidence_hash": "sha256:8888888888888888888888888888888888888888888888888888888888888888" + } + ], + "audit_checkpoints": [ + { + "checkpoint_id": "checkpoint_result_classification", + "display_name": "結果分類一致性", + "required_for": "所有 result route", + "status": "ready", + "failure_if_missing": "TG / AwoooP 只會顯示已批准或執行中,無法知道最後是 no-action、失敗或補證。", + "creates_runtime_action": false + }, + { + "checkpoint_id": "checkpoint_evidence_hash", + "display_name": "redacted evidence hash", + "required_for": "KM / LOGBOOK / audit", + "status": "ready", + "failure_if_missing": "結果無法被追溯,後續 KM 可能固化錯誤。", + "creates_runtime_action": false + }, + { + "checkpoint_id": "checkpoint_owner_next_action", + "display_name": "owner 與下一步", + "required_for": "operator handoff", + "status": "ready", + "failure_if_missing": "人工看不懂該修、該補證、該 rollback 或該關閉。", + "creates_runtime_action": false + }, + { + "checkpoint_id": "checkpoint_km_draft_review", + "display_name": "KM owner review", + "required_for": "knowledge base", + "status": "needs_owner_review", + "failure_if_missing": "AI 可能直接寫入未驗證或過時知識。", + "creates_runtime_action": false + }, + { + "checkpoint_id": "checkpoint_logbook_evidence", + "display_name": "LOGBOOK evidence anchor", + "required_for": "release evidence", + "status": "ready", + "failure_if_missing": "無法連回 commit、deploy marker、API readback 與正式站 smoke。", + "creates_runtime_action": false + }, + { + "checkpoint_id": "checkpoint_timeline_handoff", + "display_name": "timeline handoff", + "required_for": "incident timeline", + "status": "needs_owner_review", + "failure_if_missing": "Incident 頁看不到目前停在哪個階段。", + "creates_runtime_action": false + }, + { + "checkpoint_id": "checkpoint_redaction_boundary", + "display_name": "redaction boundary", + "required_for": "所有前端顯示", + "status": "ready", + "failure_if_missing": "可能外露 secret、prompt、私有推理、raw TG payload 或內部協作內容。", + "creates_runtime_action": false + } + ], + "operator_handoffs": [ + { + "handoff_id": "handoff_manual_fix_or_rollback", + "display_name": "人工修復或回滾", + "owner_agent": "openclaw", + "human_instruction": "若 result_state=execution_failed,SRE 只可依 no-write SOP 決定人工修復 / rollback;AI 不會再次自動執行。", + "creates_runtime_action": false, + "requires_human_review": true + }, + { + "handoff_id": "handoff_collect_missing_repair_evidence", + "display_name": "補齊修復證據", + "owner_agent": "hermes", + "human_instruction": "補 MCP、provider、host log、PlayBook trust 或 verifier evidence;補完後重新回到 dry-run review。", + "creates_runtime_action": false, + "requires_human_review": true + }, + { + "handoff_id": "handoff_provider_correlation_review", + "display_name": "供應者關聯審查", + "owner_agent": "openclaw", + "human_instruction": "檢查 provider refs 與 Incident 的 source id / fingerprint / recurrence 對應,不可把 provider heartbeat 當已關聯。", + "creates_runtime_action": false, + "requires_human_review": true + }, + { + "handoff_id": "handoff_km_owner_review", + "display_name": "KM owner 審查", + "owner_agent": "hermes", + "human_instruction": "owner 確認草稿引用、來源與 stale 風險後才可寫入高影響 KM。", + "creates_runtime_action": false, + "requires_human_review": true + }, + { + "handoff_id": "handoff_report_quality_review", + "display_name": "報表品質審查", + "owner_agent": "hermes", + "human_instruction": "日報 / 週報 / 月報全 0 時先視為資料鏈路異常,需查 ingestion 與 actionability,不得當成健康。", + "creates_runtime_action": false, + "requires_human_review": true + } + ], + "display_redaction_contract": { + "redaction_required": true, + "raw_prompt_display_allowed": false, + "private_reasoning_display_allowed": false, + "secret_value_display_allowed": false, + "raw_telegram_payload_display_allowed": false, + "work_window_transcript_display_allowed": false, + "allowed_display_fields": [ + "route_id", + "display_name", + "result_state", + "owner_agent", + "primary_owner", + "operator_next_action", + "blocked_reason", + "evidence_hash", + "write_enabled", + "runtime_writer_enabled" + ], + "blocked_display_fields": [ + "secret_value", + "token", + "authorization_header", + "raw_prompt", + "private_reasoning", + "raw_telegram_payload", + "internal_collaboration_transcript" + ] + }, + "rollups": { + "result_route_count": 8, + "owner_next_action_ready_count": 8, + "requires_owner_review_count": 7, + "ready_for_km_draft_count": 5, + "blocked_result_count": 3, + "writeback_contract_count": 6, + "audit_checkpoint_count": 7, + "operator_handoff_count": 5, + "runtime_execution_count": 0, + "km_write_count": 0, + "logbook_runtime_write_count": 0, + "audit_db_write_count": 0, + "timeline_write_count": 0, + "playbook_trust_write_count": 0, + "gateway_queue_write_count": 0, + "telegram_send_count": 0, + "production_write_count": 0, + "secret_value_read_count": 0, + "destructive_operation_count": 0 + } +} diff --git a/docs/schemas/ai_agent_task_result_audit_trail_v1.schema.json b/docs/schemas/ai_agent_task_result_audit_trail_v1.schema.json new file mode 100644 index 000000000..f1e31e4c6 --- /dev/null +++ b/docs/schemas/ai_agent_task_result_audit_trail_v1.schema.json @@ -0,0 +1,336 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://awoooi.wooo.work/schemas/ai_agent_task_result_audit_trail_v1.schema.json", + "title": "AI Agent Task Result Audit Trail v1", + "type": "object", + "required": [ + "schema_version", + "generated_at", + "program_status", + "source_refs", + "result_audit_truth", + "result_routes", + "writeback_contracts", + "audit_checkpoints", + "operator_handoffs", + "display_redaction_contract", + "rollups" + ], + "properties": { + "schema_version": { "const": "ai_agent_task_result_audit_trail_v1" }, + "generated_at": { "type": "string" }, + "program_status": { + "type": "object", + "required": [ + "overall_completion_percent", + "current_priority", + "current_task_id", + "next_task_id", + "read_only_mode", + "runtime_authority", + "status_note" + ], + "properties": { + "overall_completion_percent": { "type": "integer", "minimum": 0, "maximum": 100 }, + "current_priority": { "enum": ["P0", "P1", "P2", "P3"] }, + "current_task_id": { "const": "P2-103" }, + "next_task_id": { "const": "P2-104" }, + "read_only_mode": { "const": true }, + "runtime_authority": { "const": "task_result_audit_trail_contract_only_no_live_writeback" }, + "status_note": { "type": "string" } + }, + "additionalProperties": false + }, + "source_refs": { "type": "array", "items": { "type": "string" }, "minItems": 1 }, + "result_audit_truth": { + "type": "object", + "required": [ + "p2_102_candidate_dry_run_loaded", + "task_result_route_matrix_ready", + "km_draft_contract_ready", + "logbook_append_contract_ready", + "audit_trail_contract_ready", + "timeline_handoff_contract_ready", + "operator_next_action_ready", + "all_results_have_owner_and_next_step", + "runtime_execution_enabled", + "km_write_enabled", + "logbook_runtime_write_enabled", + "audit_db_write_enabled", + "timeline_write_enabled", + "playbook_trust_write_enabled", + "gateway_queue_write_enabled", + "telegram_send_enabled", + "delivery_receipt_write_enabled", + "production_write_enabled", + "secret_value_read_enabled", + "host_or_cluster_command_enabled", + "destructive_operation_enabled", + "work_window_transcript_display_allowed", + "runtime_execution_count_24h", + "km_write_count_24h", + "logbook_runtime_write_count_24h", + "audit_db_write_count_24h", + "timeline_write_count_24h", + "playbook_trust_write_count_24h", + "gateway_queue_write_count_24h", + "telegram_send_count_24h", + "delivery_receipt_write_count_24h", + "production_write_count_24h", + "secret_value_read_count_24h", + "host_or_cluster_command_count_24h", + "destructive_operation_count_24h", + "truth_note" + ], + "properties": { + "p2_102_candidate_dry_run_loaded": { "const": true }, + "task_result_route_matrix_ready": { "const": true }, + "km_draft_contract_ready": { "const": true }, + "logbook_append_contract_ready": { "const": true }, + "audit_trail_contract_ready": { "const": true }, + "timeline_handoff_contract_ready": { "const": true }, + "operator_next_action_ready": { "const": true }, + "all_results_have_owner_and_next_step": { "const": true }, + "runtime_execution_enabled": { "const": false }, + "km_write_enabled": { "const": false }, + "logbook_runtime_write_enabled": { "const": false }, + "audit_db_write_enabled": { "const": false }, + "timeline_write_enabled": { "const": false }, + "playbook_trust_write_enabled": { "const": false }, + "gateway_queue_write_enabled": { "const": false }, + "telegram_send_enabled": { "const": false }, + "delivery_receipt_write_enabled": { "const": false }, + "production_write_enabled": { "const": false }, + "secret_value_read_enabled": { "const": false }, + "host_or_cluster_command_enabled": { "const": false }, + "destructive_operation_enabled": { "const": false }, + "work_window_transcript_display_allowed": { "const": false }, + "runtime_execution_count_24h": { "const": 0 }, + "km_write_count_24h": { "const": 0 }, + "logbook_runtime_write_count_24h": { "const": 0 }, + "audit_db_write_count_24h": { "const": 0 }, + "timeline_write_count_24h": { "const": 0 }, + "playbook_trust_write_count_24h": { "const": 0 }, + "gateway_queue_write_count_24h": { "const": 0 }, + "telegram_send_count_24h": { "const": 0 }, + "delivery_receipt_write_count_24h": { "const": 0 }, + "production_write_count_24h": { "const": 0 }, + "secret_value_read_count_24h": { "const": 0 }, + "host_or_cluster_command_count_24h": { "const": 0 }, + "destructive_operation_count_24h": { "const": 0 }, + "truth_note": { "type": "string" } + }, + "additionalProperties": false + }, + "result_routes": { + "type": "array", + "minItems": 8, + "items": { + "type": "object", + "required": [ + "route_id", + "display_name", + "source_signal", + "result_state", + "owner_agent", + "primary_owner", + "km_target", + "logbook_target", + "audit_target", + "timeline_target", + "operator_next_action", + "blocked_reason", + "writes_live_state", + "requires_owner_review", + "ready_for_km_draft", + "evidence_hash" + ], + "properties": { + "route_id": { "type": "string" }, + "display_name": { "type": "string" }, + "source_signal": { "type": "string" }, + "result_state": { + "enum": [ + "diagnostic_only", + "owner_review_required", + "execution_failed", + "verified_no_change", + "blocked_until_evidence", + "blocked_by_policy", + "correlation_gap", + "report_quality_gap" + ] + }, + "owner_agent": { "enum": ["openclaw", "hermes", "nemotron"] }, + "primary_owner": { "type": "string" }, + "km_target": { "type": "string" }, + "logbook_target": { "type": "string" }, + "audit_target": { "type": "string" }, + "timeline_target": { "type": "string" }, + "operator_next_action": { "type": "string" }, + "blocked_reason": { "type": "string" }, + "writes_live_state": { "const": false }, + "requires_owner_review": { "type": "boolean" }, + "ready_for_km_draft": { "type": "boolean" }, + "evidence_hash": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" } + }, + "additionalProperties": false + } + }, + "writeback_contracts": { + "type": "array", + "minItems": 6, + "items": { + "type": "object", + "required": [ + "contract_id", + "display_name", + "owner_agent", + "target_system", + "purpose", + "allowed_mode", + "write_enabled", + "runtime_writer_enabled", + "required_fields", + "blocker_summary", + "evidence_hash" + ], + "properties": { + "contract_id": { "type": "string" }, + "display_name": { "type": "string" }, + "owner_agent": { "enum": ["openclaw", "hermes", "nemotron"] }, + "target_system": { "type": "string" }, + "purpose": { "type": "string" }, + "allowed_mode": { + "enum": ["committed_snapshot_only", "gated_owner_review", "manual_append_plan"] + }, + "write_enabled": { "const": false }, + "runtime_writer_enabled": { "const": false }, + "required_fields": { "type": "array", "items": { "type": "string" }, "minItems": 1 }, + "blocker_summary": { "type": "string" }, + "evidence_hash": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" } + }, + "additionalProperties": false + } + }, + "audit_checkpoints": { + "type": "array", + "minItems": 7, + "items": { + "type": "object", + "required": [ + "checkpoint_id", + "display_name", + "required_for", + "status", + "failure_if_missing", + "creates_runtime_action" + ], + "properties": { + "checkpoint_id": { "type": "string" }, + "display_name": { "type": "string" }, + "required_for": { "type": "string" }, + "status": { "enum": ["ready", "needs_owner_review", "blocked_by_policy"] }, + "failure_if_missing": { "type": "string" }, + "creates_runtime_action": { "const": false } + }, + "additionalProperties": false + } + }, + "operator_handoffs": { + "type": "array", + "minItems": 5, + "items": { + "type": "object", + "required": [ + "handoff_id", + "display_name", + "owner_agent", + "human_instruction", + "creates_runtime_action", + "requires_human_review" + ], + "properties": { + "handoff_id": { "type": "string" }, + "display_name": { "type": "string" }, + "owner_agent": { "enum": ["openclaw", "hermes", "nemotron"] }, + "human_instruction": { "type": "string" }, + "creates_runtime_action": { "const": false }, + "requires_human_review": { "const": true } + }, + "additionalProperties": false + } + }, + "display_redaction_contract": { + "type": "object", + "required": [ + "redaction_required", + "raw_prompt_display_allowed", + "private_reasoning_display_allowed", + "secret_value_display_allowed", + "raw_telegram_payload_display_allowed", + "work_window_transcript_display_allowed", + "allowed_display_fields", + "blocked_display_fields" + ], + "properties": { + "redaction_required": { "const": true }, + "raw_prompt_display_allowed": { "const": false }, + "private_reasoning_display_allowed": { "const": false }, + "secret_value_display_allowed": { "const": false }, + "raw_telegram_payload_display_allowed": { "const": false }, + "work_window_transcript_display_allowed": { "const": false }, + "allowed_display_fields": { "type": "array", "items": { "type": "string" }, "minItems": 1 }, + "blocked_display_fields": { "type": "array", "items": { "type": "string" }, "minItems": 1 } + }, + "additionalProperties": false + }, + "rollups": { + "type": "object", + "required": [ + "result_route_count", + "owner_next_action_ready_count", + "requires_owner_review_count", + "ready_for_km_draft_count", + "blocked_result_count", + "writeback_contract_count", + "audit_checkpoint_count", + "operator_handoff_count", + "runtime_execution_count", + "km_write_count", + "logbook_runtime_write_count", + "audit_db_write_count", + "timeline_write_count", + "playbook_trust_write_count", + "gateway_queue_write_count", + "telegram_send_count", + "production_write_count", + "secret_value_read_count", + "destructive_operation_count" + ], + "properties": { + "result_route_count": { "type": "integer", "minimum": 0 }, + "owner_next_action_ready_count": { "type": "integer", "minimum": 0 }, + "requires_owner_review_count": { "type": "integer", "minimum": 0 }, + "ready_for_km_draft_count": { "type": "integer", "minimum": 0 }, + "blocked_result_count": { "type": "integer", "minimum": 0 }, + "writeback_contract_count": { "type": "integer", "minimum": 0 }, + "audit_checkpoint_count": { "type": "integer", "minimum": 0 }, + "operator_handoff_count": { "type": "integer", "minimum": 0 }, + "runtime_execution_count": { "const": 0 }, + "km_write_count": { "const": 0 }, + "logbook_runtime_write_count": { "const": 0 }, + "audit_db_write_count": { "const": 0 }, + "timeline_write_count": { "const": 0 }, + "playbook_trust_write_count": { "const": 0 }, + "gateway_queue_write_count": { "const": 0 }, + "telegram_send_count": { "const": 0 }, + "production_write_count": { "const": 0 }, + "secret_value_read_count": { "const": 0 }, + "destructive_operation_count": { "const": 0 } + }, + "additionalProperties": false + } + }, + "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 ca54eb67a..2b184d2dc 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 @@ -634,12 +634,13 @@ Alert / Sentry / SigNoz / Gitea / Market Watch / Operator | `docs/evaluations/ai_agent_communication_learning_contract_2026-06-11.json` | 2026-06-11 committed snapshot;完成度 `35%`,runtime worker / DB migration / Telegram direct send 全部 false | | `apps/api/src/services/ai_agent_communication_learning_contract.py` | 只讀 loader;強制驗證 runtime / migration / Telegram / SDK / route 權限都未開 | | `GET /api/v1/agents/agent-communication-learning-contract` | 治理 API;只回傳 committed contract,不啟動 worker、不碰 DB/Redis、不呼叫外部服務 | -| `docs/evaluations/ai_agent_interaction_learning_proof_2026-06-11.json` + `GET /api/v1/agents/agent-interaction-learning-proof` | P2-403A / P2-403B / P2-403C / P2-403D / P2-403E / P2-403F / P2-403G / P2-403H / P2-403I / P2-403J / P2-403L / P2-403M / P2-403N / P2-404 互動、接手、學習、成長、read model gate、Redis dry-run gate、learning writeback approval package、Telegram receipt approval package、owner-approved learning dry-run、fixture dry-run、runtime write gate review、post-write verifier package、runtime verifier evidence review、報表真相、日週月報、Agent 工作量、圖表化報告、風險自動化政策、報表 runtime readiness、no-write dry-run、fixture/readback/verifier dry-run 與 shadow/no-write execution 證據面;目前 live session、message、handoff、learning write、Gateway queue、Telegram send、report delivery、auto optimization、shadow worker、verifier execution 全部 `0`,由 P2-101 / P2-102 權限模型與候選 dry-run 證據承接下一步 | +| `docs/evaluations/ai_agent_interaction_learning_proof_2026-06-11.json` + `GET /api/v1/agents/agent-interaction-learning-proof` | P2-403A / P2-403B / P2-403C / P2-403D / P2-403E / P2-403F / P2-403G / P2-403H / P2-403I / P2-403J / P2-403L / P2-403M / P2-403N / P2-404 互動、接手、學習、成長、read model gate、Redis dry-run gate、learning writeback approval package、Telegram receipt approval package、owner-approved learning dry-run、fixture dry-run、runtime write gate review、post-write verifier package、runtime verifier evidence review、報表真相、日週月報、Agent 工作量、圖表化報告、風險自動化政策、報表 runtime readiness、no-write dry-run、fixture/readback/verifier dry-run 與 shadow/no-write execution 證據面;目前 live session、message、handoff、learning write、Gateway queue、Telegram send、report delivery、auto optimization、shadow worker、verifier execution 全部 `0`,由 P2-101 / P2-102 / P2-103 權限模型、候選 dry-run 證據與結果稽核軌跡承接下一步 | | `docs/evaluations/ai_agent_report_runtime_dry_run_2026-06-12.json` + `GET /api/v1/agents/agent-report-runtime-dry-run` | P2-403M 報表 runtime no-write dry-run 證據包;建立 5 個 dry-run artifact、3 個 SRE 戰情室 queue digest 草案、4 個 readback verifier case、3 個 Agent dry-run role 與 6 個 operator checkpoint;不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 delivery receipt、不啟動 worker、不跑 verifier live readback、不讀 secret,已由 P2-403N fixture readback 承接 | | `docs/evaluations/ai_agent_report_runtime_fixture_readback_2026-06-12.json` + `GET /api/v1/agents/agent-report-runtime-fixture-readback` | P2-403N fixture smoke / queue preview readback / verifier dry-run 證據包;建立 5 個 fixture smoke、3 個 SRE 戰情室 queue preview readback、4 個 verifier dry-run case、3 個 Agent fixture role 與 5 個 operator checkpoint;不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 delivery receipt、不啟動 worker、不跑 verifier live readback、不讀 secret,下一步 P2-404 | | `docs/evaluations/ai_agent_runtime_worker_shadow_gate_2026-06-12.json` + `GET /api/v1/agents/agent-runtime-worker-shadow-gate` | P2-404 runtime worker shadow / no-write execution evidence gate;建立 5 個 shadow candidate、4 個 no-write replay、4 個 verifier shadow case、3 個 Agent shadow role 與 6 個 operator checkpoint;shadow live worker、Gateway queue write、Telegram send、Bot API、delivery receipt、auto worker、verifier live readback、production write 與 secret read 全部 `0 / false`,下一步 P2-101 | | `docs/evaluations/ai_agent_operation_permission_model_2026-06-12.json` + `GET /api/v1/agents/agent-operation-permission-model` | P2-101 操作類別權限模型;建立 5 條 permission lane、13 類 operation category、3 個 Agent permission role、8 個 gate transition 與 5 個 operator decision template;runtime execution、Gateway queue write、Telegram send、Bot API、delivery receipt、auto worker、verifier live readback、production write、secret / paid provider、host command 與 destructive action 全部 `0 / false`,已由 P2-102 承接 | -| `docs/evaluations/ai_agent_candidate_operation_dry_run_evidence_2026-06-12.json` + `GET /api/v1/agents/agent-candidate-operation-dry-run-evidence` | P2-102 候選操作 dry-run 證據;13 類候選操作全部具備 input / output evidence hash、side-effect count、verifier plan、rollback/no-op plan 與人工 handoff;6 個 verifier plan、7 個 gate evidence requirement、5 個 operator handoff;runtime、Gateway queue、Telegram、production write、secret / paid provider 與 destructive action 全部 `0 / false`,下一步 P2-103 | +| `docs/evaluations/ai_agent_candidate_operation_dry_run_evidence_2026-06-12.json` + `GET /api/v1/agents/agent-candidate-operation-dry-run-evidence` | P2-102 候選操作 dry-run 證據;13 類候選操作全部具備 input / output evidence hash、side-effect count、verifier plan、rollback/no-op plan 與人工 handoff;6 個 verifier plan、7 個 gate evidence requirement、5 個 operator handoff;runtime、Gateway queue、Telegram、production write、secret / paid provider 與 destructive action 全部 `0 / false`,已由 P2-103 承接 | +| `docs/evaluations/ai_agent_task_result_audit_trail_2026-06-13.json` + `GET /api/v1/agents/agent-task-result-audit-trail` | P2-103 任務結果稽核軌跡;8 條 result route、6 個 writeback contract、7 個 audit checkpoint、5 個 operator handoff;把 diagnostic-only、repair candidate、execution failed、provider unmatched、report zero-signal 等結果固定到 KM 草稿、LOGBOOK 證據、audit trail、timeline 與人工下一步;KM / LOGBOOK / audit DB / timeline / PlayBook trust / Gateway queue / Telegram 寫入全為 `0 / false`,下一步 P2-104 | | `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 主動營運委派與版本生命週期契約 @@ -730,7 +731,8 @@ Repo / registry / release notes / K8s / host / observability / backup evidence 20. 建立 fixture smoke、queue preview readback 與 verifier dry-run 證據包。✅ P2-403N 已完成;fixture smoke `5`、queue preview readback `3`、verifier dry-run case `4`,Gateway queue write、Telegram send、Bot API、delivery receipt、AI runtime worker、中低風險 auto worker、verifier live readback、production write 與 secret value read 仍為 `0 / false`。 21. 建立 runtime worker shadow / no-write execution evidence gate。✅ P2-404 已完成;shadow candidate `5`、no-write replay `4`、verifier shadow case `4`、Agent shadow role `3`、operator checkpoint `6`,shadow live worker、Gateway queue write、Telegram send、Bot API、delivery receipt、AI runtime worker、中低風險 auto worker、verifier live readback、production write 與 secret value read 仍為 `0 / false`。已由 P2-101 承接。 22. 定義操作類別權限模型。✅ P2-101 已完成;permission lane `5`、operation category `13`、Agent permission role `3`、gate transition `8`、operator decision template `5`,runtime execution、Gateway queue write、Telegram send、Bot API、delivery receipt、AI runtime worker、中低風險 auto worker、verifier live readback、production write、secret / paid provider、host command 與 destructive action 仍為 `0 / false`。已由 P2-102 承接。 -23. 建立候選操作 dry-run 證據。✅ P2-102 已完成;candidate operation `13`、dry-run evidence `13`、verifier plan `6`、gate evidence requirement `7`、operator handoff `5`,side-effect、runtime execution、Gateway queue write、Telegram send、production write、secret value read、paid provider call、host / cluster command 與 destructive action 仍為 `0 / false`。下一步 P2-103 把任務結果接回 KM / LOGBOOK / 稽核軌跡。 +23. 建立候選操作 dry-run 證據。✅ P2-102 已完成;candidate operation `13`、dry-run evidence `13`、verifier plan `6`、gate evidence requirement `7`、operator handoff `5`,side-effect、runtime execution、Gateway queue write、Telegram send、production write、secret value read、paid provider call、host / cluster command 與 destructive action 仍為 `0 / false`。已由 P2-103 承接。 +24. 把任務結果接回 KM / LOGBOOK / 稽核軌跡。✅ P2-103 已完成;result route `8`、writeback contract `6`、audit checkpoint `7`、operator handoff `5`,KM write、LOGBOOK runtime append、audit DB write、timeline write、PlayBook trust write、Gateway queue write、Telegram send 與 production write 仍為 `0 / false`。下一步 P2-104 修復 `matched_playbook_id` 學習缺口。 #### 3.2.1d 2026-06-11 Agent 互動、學習與成長證據面 @@ -762,6 +764,7 @@ Repo / registry / release notes / K8s / host / observability / backup evidence | `docs/evaluations/ai_agent_runtime_worker_shadow_gate_2026-06-12.json` + `GET /api/v1/agents/agent-runtime-worker-shadow-gate` | P2-404 runtime worker shadow / no-write execution evidence gate;5 個 shadow candidate、4 個 no-write replay、4 個 verifier shadow case、3 個 Agent shadow role、6 個 operator checkpoint;不啟動 live worker、不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 production target | | `docs/evaluations/ai_agent_operation_permission_model_2026-06-12.json` + `GET /api/v1/agents/agent-operation-permission-model` | P2-101 操作類別權限模型;5 條 permission lane、13 類 operation category、3 個 Agent permission role、8 個 gate transition、5 個 operator decision template;不啟動 runtime worker、不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 production target、不讀 secret | | `docs/evaluations/ai_agent_candidate_operation_dry_run_evidence_2026-06-12.json` + `GET /api/v1/agents/agent-candidate-operation-dry-run-evidence` | P2-102 候選操作 dry-run 證據;13 類候選操作、13 組 dry-run evidence、6 個 verifier plan、7 個 gate evidence requirement、5 個 operator handoff;不啟動 runtime worker、不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 production target、不讀 secret、不執行 destructive action | +| `docs/evaluations/ai_agent_task_result_audit_trail_2026-06-13.json` + `GET /api/v1/agents/agent-task-result-audit-trail` | P2-103 任務結果稽核軌跡;8 條 result route、6 個 writeback contract、7 個 audit checkpoint、5 個 operator handoff;不寫 KM、不 runtime append LOGBOOK、不寫 audit DB、不寫 timeline、不更新 PlayBook trust、不寫 Gateway queue、不送 Telegram | | `apps/api/src/services/ai_agent_interaction_learning_proof.py` | 只讀 loader;強制 live flags / DB / Redis / Telegram / transcript / 私有推理全部關閉 | | `GET /api/v1/agents/agent-interaction-learning-proof` | 治理 API;只回傳證據面,不啟動 worker、不碰 live DB/Redis、不發 Telegram | | `docs/schemas/ai_agent_live_read_model_gate_v1.schema.json` | P2-403B live read model gate schema;強制 DB / Redis / worker / Telegram / learning writeback 仍需批准 | @@ -1927,7 +1930,14 @@ Phase 6 完成後 - 新增 `ai_agent_candidate_operation_dry_run_evidence_v1` schema / committed snapshot / loader / API / 測試,定義 13 類 candidate operation、13 組 dry-run input / output evidence hash、side-effect count、rollback/no-op plan 與人工 handoff。 - `apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx` 接入 `GET /api/v1/agents/agent-candidate-operation-dry-run-evidence`,治理頁顯示候選操作、dry-run 證據、verifier plan、gate evidence requirement、operator handoff 與不可誤讀合約。 - 政策裁決:P2-102 只允許 no-write dry-run 證據、queue preview、verifier fixture 與人工下一步;任何 runtime execution、Gateway queue write、Telegram send、Bot API、delivery receipt、AI runtime worker、中低風險 auto worker、verifier live readback、production write、secret / paid provider、host command 或 destructive action 都仍為 `0 / false`。 -- 本波仍不送 Telegram、不寫 Gateway queue、不呼叫 Bot API、不寫 delivery receipt、不啟動 live runtime worker、不跑 verifier live readback、不讀 secret、不呼叫付費 provider、不執行主機或叢集命令、不回傳內部協作內容;下一步 P2-103 才把結果接回 KM / LOGBOOK / 稽核軌跡。 +- 本波仍不送 Telegram、不寫 Gateway queue、不呼叫 Bot API、不寫 delivery receipt、不啟動 live runtime worker、不跑 verifier live readback、不讀 secret、不呼叫付費 provider、不執行主機或叢集命令、不回傳內部協作內容;已由 P2-103 把結果接回 KM / LOGBOOK / 稽核軌跡契約。 + +### 2026-06-13 10:20 (台北) — §3.2 / §5 — 完成 P2-103 任務結果稽核軌跡 — 把批准後卡住的結果固定成可追蹤路由 + +- 新增 `ai_agent_task_result_audit_trail_v1` schema / committed snapshot / loader / API / 測試,定義 8 條 result route、6 個 writeback contract、7 個 audit checkpoint 與 5 個 operator handoff。 +- `apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx` 接入 `GET /api/v1/agents/agent-task-result-audit-trail`,治理頁顯示 diagnostic-only、repair candidate、execution failed、provider unmatched、report zero-signal 等結果該進 KM 草稿、LOGBOOK 證據、audit trail、timeline 或人工交接。 +- 政策裁決:P2-103 只允許結果路由、redacted evidence hash、寫回契約、稽核 checkpoint 與人工下一步;任何 KM write、LOGBOOK runtime append、audit DB write、timeline write、PlayBook trust write、Gateway queue write、Telegram send、production write 或 secret value read 都仍為 `0 / false`。 +- 本波仍不寫 KM、不 runtime append LOGBOOK、不寫 audit DB、不寫 timeline、不更新 PlayBook trust、不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不啟動 runtime worker、不讀 secret、不回傳內部協作內容;下一步 P2-104 才修復 `matched_playbook_id` 學習缺口。 ### 2026-06-12 11:55 (台北) — §3.2 / §5 — 完成 P2-403M 報表 runtime no-write dry-run 證據包 — 把 queue / verifier 草案固定成可審核證據