diff --git a/apps/api/src/api/v1/agents.py b/apps/api/src/api/v1/agents.py index 693cc7b94..939555609 100644 --- a/apps/api/src/api/v1/agents.py +++ b/apps/api/src/api/v1/agents.py @@ -91,6 +91,9 @@ from src.services.ai_agent_report_automation_review import ( from src.services.ai_agent_report_runtime_dry_run import ( load_latest_ai_agent_report_runtime_dry_run, ) +from src.services.ai_agent_report_runtime_fixture_readback import ( + load_latest_ai_agent_report_runtime_fixture_readback, +) from src.services.ai_agent_report_runtime_readiness import ( load_latest_ai_agent_report_runtime_readiness, ) @@ -973,6 +976,34 @@ async def get_agent_report_runtime_dry_run() -> dict[str, Any]: ) from exc +@router.get( + "/agent-report-runtime-fixture-readback", + response_model=dict[str, Any], + summary="取得 AI Agent 報表 runtime fixture readback 證據包", + description=( + "讀取最新已提交的 P2-403N fixture smoke、Telegram Gateway queue preview readback " + "與 verifier dry-run 證據包;此端點不排程實發、不送 Telegram、不呼叫 Bot API、" + "不寫 Gateway queue、不寫讀報回執、不啟動 AI runtime worker、不啟動中低風險 auto worker、" + "不執行 verifier live readback、不寫 production target、不讀 secret、不回傳內部對話內容。" + ), +) +async def get_agent_report_runtime_fixture_readback() -> dict[str, Any]: + """Return the latest read-only AI Agent fixture readback package.""" + try: + return await asyncio.to_thread(load_latest_ai_agent_report_runtime_fixture_readback) + 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_report_runtime_fixture_readback_invalid", error=str(exc)) + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="AI Agent 報表 runtime fixture readback 證據包無效", + ) from exc + + @router.get( "/agent-owner-approved-fixture-dry-run", response_model=dict[str, Any], diff --git a/apps/api/src/services/ai_agent_report_runtime_fixture_readback.py b/apps/api/src/services/ai_agent_report_runtime_fixture_readback.py new file mode 100644 index 000000000..64718f3eb --- /dev/null +++ b/apps/api/src/services/ai_agent_report_runtime_fixture_readback.py @@ -0,0 +1,269 @@ +""" +AI Agent report runtime fixture readback snapshot. + +Loads the latest committed P2-403N fixture smoke / queue preview readback / +verifier dry-run contract. This module only validates repo-committed evidence +and never writes Telegram Gateway queues, sends Telegram messages, starts AI +workers, runs live verifiers, or reads secrets. +""" + +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_report_runtime_fixture_readback_*.json" +_SCHEMA_VERSION = "ai_agent_report_runtime_fixture_readback_v1" +_RUNTIME_AUTHORITY = "fixture_smoke_queue_preview_readback_verifier_dry_run_only_no_live_send_or_write" + + +def load_latest_ai_agent_report_runtime_fixture_readback( + evaluations_dir: Path | None = None, +) -> dict[str, Any]: + """Load the newest committed AI Agent fixture readback snapshot.""" + directory = evaluations_dir or _DEFAULT_EVALUATIONS_DIR + candidates = sorted(directory.glob(_SNAPSHOT_PATTERN)) + if not candidates: + raise FileNotFoundError(f"no AI Agent report runtime fixture readback snapshots found in {directory}") + + latest = candidates[-1] + with latest.open(encoding="utf-8") as handle: + payload = json.load(handle) + + if not isinstance(payload, dict): + raise ValueError(f"{latest}: expected JSON object") + _require_schema(payload, str(latest)) + _require_no_write_boundaries(payload, str(latest)) + _require_fixture_contract(payload, str(latest)) + _require_queue_readback_contract(payload, str(latest)) + _require_verifier_contract(payload, str(latest)) + _require_agent_roles(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-403N": + raise ValueError(f"{label}: current_task_id must be P2-403N") + if status.get("next_task_id") != "P2-404": + raise ValueError(f"{label}: next_task_id must be P2-404") + + +def _require_no_write_boundaries(payload: dict[str, Any], label: str) -> None: + truth = payload.get("fixture_readback_truth") or {} + required_true = { + "fixture_smoke_package_ready", + "report_snapshot_hash_ready", + "telegram_queue_preview_readback_ready", + "readback_verifier_dry_run_ready", + "redaction_assertions_ready", + "operator_review_packet_ready", + } + missing = sorted(field for field in required_true if truth.get(field) is not True) + if missing: + raise ValueError(f"{label}: fixture readiness flags must remain true: {missing}") + + required_false = { + "production_delivery_enabled", + "telegram_gateway_queue_write_enabled", + "telegram_send_enabled", + "telegram_bot_api_call_enabled", + "delivery_receipt_write_enabled", + "ai_runtime_worker_enabled", + "medium_low_auto_worker_enabled", + "post_action_verifier_live_readback_enabled", + "production_write_enabled", + "secret_value_read_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/runtime flags must remain false: {unsafe}") + + zero_counts = { + "live_report_delivery_count_24h", + "telegram_gateway_queue_write_count_24h", + "telegram_send_count_24h", + "telegram_bot_api_call_count_24h", + "delivery_receipt_write_count_24h", + "ai_runtime_worker_run_count_24h", + "medium_low_auto_execution_count_24h", + "post_action_verifier_live_readback_count_24h", + "production_write_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/runtime counts must remain zero: {non_zero}") + + +def _require_fixture_contract(payload: dict[str, Any], label: str) -> None: + fixtures = payload.get("fixture_smoke_results") or [] + fixture_ids = {fixture.get("fixture_id") for fixture in fixtures} + required = { + "report_run_snapshot_fixture", + "telegram_digest_payload_fixture", + "queue_preview_redaction_fixture", + "receipt_redaction_fixture", + "medium_low_noop_fixture", + } + if fixture_ids != required: + raise ValueError(f"{label}: fixture smoke results must match {sorted(required)}") + + for fixture in fixtures: + fixture_id = fixture.get("fixture_id") + if not _is_redacted_sha256(fixture.get("output_hash")): + raise ValueError(f"{label}: fixture {fixture_id} must expose a redacted sha256 output_hash") + if fixture.get("writes_production") is not False: + raise ValueError(f"{label}: fixture {fixture_id} must not write production") + if fixture.get("sends_telegram") is not False: + raise ValueError(f"{label}: fixture {fixture_id} must not send Telegram") + if fixture.get("reads_secret_value") is not False: + raise ValueError(f"{label}: fixture {fixture_id} must not read secret value") + if fixture.get("live_execution_count_24h") != 0: + raise ValueError(f"{label}: fixture {fixture_id} live_execution_count_24h must remain zero") + + +def _require_queue_readback_contract(payload: dict[str, Any], label: str) -> None: + readbacks = payload.get("queue_preview_readbacks") or [] + readback_ids = {readback.get("readback_id") for readback in readbacks} + if readback_ids != { + "daily_report_digest_readback", + "weekly_report_digest_readback", + "monthly_report_digest_readback", + }: + raise ValueError(f"{label}: queue preview readbacks must cover daily, weekly, monthly") + + for readback in readbacks: + readback_id = readback.get("readback_id") + if readback.get("recipient_room") != "AwoooI SRE 戰情室": + raise ValueError(f"{label}: readback {readback_id} must target AwoooI SRE 戰情室") + if readback.get("secret_ref") != "SRE_GROUP_CHAT_ID": + raise ValueError(f"{label}: readback {readback_id} must only reference SRE_GROUP_CHAT_ID") + if not _is_redacted_sha256(readback.get("preview_hash")): + raise ValueError(f"{label}: readback {readback_id} must expose a redacted sha256 preview_hash") + if readback.get("payload_redacted") is not True: + raise ValueError(f"{label}: readback {readback_id} payload must remain redacted") + if readback.get("gateway_queue_write_enabled") is not False: + raise ValueError(f"{label}: readback {readback_id} must not write Gateway queue") + if readback.get("telegram_send_enabled") is not False: + raise ValueError(f"{label}: readback {readback_id} must not send Telegram") + if readback.get("direct_bot_api_allowed") is not False: + raise ValueError(f"{label}: readback {readback_id} must not allow direct Bot API") + if readback.get("queue_write_count_24h") != 0: + raise ValueError(f"{label}: readback {readback_id} queue_write_count_24h must remain zero") + + +def _require_verifier_contract(payload: dict[str, Any], label: str) -> None: + cases = payload.get("verifier_dry_run_cases") or [] + case_ids = {case.get("case_id") for case in cases} + required = { + "report_snapshot_verifier_dry_run", + "gateway_preview_verifier_dry_run", + "receipt_redaction_verifier_dry_run", + "medium_low_noop_verifier_dry_run", + } + if case_ids != required: + raise ValueError(f"{label}: verifier dry-run cases must match {sorted(required)}") + + for case in cases: + case_id = case.get("case_id") + if not _is_redacted_sha256(case.get("evidence_hash")): + raise ValueError(f"{label}: verifier case {case_id} must expose a redacted sha256 evidence_hash") + if case.get("live_readback_enabled") is not False: + raise ValueError(f"{label}: verifier case {case_id} must not run live readback") + if case.get("writes_result") is not False: + raise ValueError(f"{label}: verifier case {case_id} must not write result") + if case.get("requires_secret_value") is not False: + raise ValueError(f"{label}: verifier case {case_id} must not require secret value") + + +def _require_agent_roles(payload: dict[str, Any], label: str) -> None: + roles = payload.get("agent_fixture_roles") or [] + agents = {role.get("agent_id") for role in roles} + if agents != {"openclaw", "hermes", "nemotron"}: + raise ValueError(f"{label}: fixture roles must include OpenClaw, Hermes, and NemoTron") + for role in roles: + if role.get("live_action_count_24h") != 0: + raise ValueError(f"{label}: agent {role.get('agent_id')} live_action_count_24h must remain zero") + + +def _require_redaction_contract(payload: dict[str, Any], label: str) -> None: + contract = payload.get("display_redaction_contract") or {} + required_false = { + "raw_report_payload_display_allowed", + "raw_telegram_payload_display_allowed", + "private_reasoning_display_allowed", + "secret_value_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("fixture_readback_truth") or {} + fixtures = payload.get("fixture_smoke_results") or [] + readbacks = payload.get("queue_preview_readbacks") or [] + cases = payload.get("verifier_dry_run_cases") or [] + roles = payload.get("agent_fixture_roles") or [] + checkpoints = payload.get("operator_checkpoints") or [] + + expected = { + "fixture_smoke_count": len(fixtures), + "passed_fixture_smoke_count": sum( + 1 + for fixture in fixtures + if fixture.get("smoke_status") in {"passed_no_write", "passed_redaction"} + ), + "queue_preview_readback_count": len(readbacks), + "verifier_dry_run_case_count": len(cases), + "agent_role_count": len(roles), + "operator_checkpoint_count": len(checkpoints), + "live_report_delivery_count": truth.get("live_report_delivery_count_24h"), + "telegram_gateway_queue_write_count": truth.get("telegram_gateway_queue_write_count_24h"), + "telegram_send_count": truth.get("telegram_send_count_24h"), + "telegram_bot_api_call_count": truth.get("telegram_bot_api_call_count_24h"), + "delivery_receipt_write_count": truth.get("delivery_receipt_write_count_24h"), + "ai_runtime_worker_run_count": truth.get("ai_runtime_worker_run_count_24h"), + "medium_low_auto_execution_count": truth.get("medium_low_auto_execution_count_24h"), + "post_action_verifier_live_readback_count": truth.get("post_action_verifier_live_readback_count_24h"), + "production_write_count": truth.get("production_write_count_24h"), + } + mismatched = { + key: {"expected": value, "actual": rollups.get(key)} + for key, value in expected.items() + if rollups.get(key) != value + } + if mismatched: + raise ValueError(f"{label}: rollup counts must match payload sections: {mismatched}") + + approval_required = sorted( + checkpoint.get("checkpoint_id") + for checkpoint in checkpoints + if checkpoint.get("approval_required") is True + ) + if sorted(rollups.get("approval_required_checkpoint_ids") or []) != approval_required: + raise ValueError(f"{label}: approval_required_checkpoint_ids mismatch") + + +def _is_redacted_sha256(value: Any) -> bool: + if not isinstance(value, str) or not value.startswith("sha256:"): + return False + digest = value.removeprefix("sha256:") + return len(digest) == 64 and all(char in "0123456789abcdef" for char in digest) diff --git a/apps/api/tests/test_ai_agent_report_runtime_fixture_readback.py b/apps/api/tests/test_ai_agent_report_runtime_fixture_readback.py new file mode 100644 index 000000000..47f37eebd --- /dev/null +++ b/apps/api/tests/test_ai_agent_report_runtime_fixture_readback.py @@ -0,0 +1,116 @@ +import copy +import json + +import pytest + +from src.services.ai_agent_report_runtime_fixture_readback import ( + load_latest_ai_agent_report_runtime_fixture_readback, +) + + +def _write_snapshot(tmp_path, payload): + path = tmp_path / "ai_agent_report_runtime_fixture_readback_2026-06-12.json" + path.write_text(json.dumps(payload), encoding="utf-8") + return path + + +def test_load_latest_ai_agent_report_runtime_fixture_readback(): + data = load_latest_ai_agent_report_runtime_fixture_readback() + + assert data["schema_version"] == "ai_agent_report_runtime_fixture_readback_v1" + assert data["program_status"]["current_task_id"] == "P2-403N" + assert data["program_status"]["next_task_id"] == "P2-404" + assert data["program_status"]["overall_completion_percent"] == 94 + assert data["fixture_readback_truth"]["fixture_smoke_package_ready"] is True + assert data["fixture_readback_truth"]["telegram_queue_preview_readback_ready"] is True + assert data["fixture_readback_truth"]["readback_verifier_dry_run_ready"] is True + assert data["fixture_readback_truth"]["production_delivery_enabled"] is False + assert data["fixture_readback_truth"]["telegram_gateway_queue_write_enabled"] is False + assert data["fixture_readback_truth"]["telegram_send_enabled"] is False + assert data["fixture_readback_truth"]["telegram_bot_api_call_enabled"] is False + assert data["fixture_readback_truth"]["ai_runtime_worker_enabled"] is False + assert data["fixture_readback_truth"]["medium_low_auto_worker_enabled"] is False + assert data["fixture_readback_truth"]["post_action_verifier_live_readback_enabled"] is False + assert data["rollups"]["fixture_smoke_count"] == 5 + assert data["rollups"]["passed_fixture_smoke_count"] == 3 + assert data["rollups"]["queue_preview_readback_count"] == 3 + assert data["rollups"]["verifier_dry_run_case_count"] == 4 + assert data["rollups"]["agent_role_count"] == 3 + assert data["rollups"]["operator_checkpoint_count"] == 5 + assert len(data["rollups"]["approval_required_checkpoint_ids"]) == 4 + assert data["rollups"]["live_report_delivery_count"] == 0 + assert data["rollups"]["telegram_gateway_queue_write_count"] == 0 + assert data["rollups"]["telegram_send_count"] == 0 + assert data["rollups"]["telegram_bot_api_call_count"] == 0 + assert data["rollups"]["production_write_count"] == 0 + + +def test_rejects_telegram_send_enabled(tmp_path): + data = load_latest_ai_agent_report_runtime_fixture_readback() + bad = copy.deepcopy(data) + bad["fixture_readback_truth"]["telegram_send_enabled"] = True + _write_snapshot(tmp_path, bad) + + with pytest.raises(ValueError, match="live write/send/runtime flags"): + load_latest_ai_agent_report_runtime_fixture_readback(tmp_path) + + +def test_rejects_gateway_queue_write_count(tmp_path): + data = load_latest_ai_agent_report_runtime_fixture_readback() + bad = copy.deepcopy(data) + bad["fixture_readback_truth"]["telegram_gateway_queue_write_count_24h"] = 1 + bad["rollups"]["telegram_gateway_queue_write_count"] = 1 + _write_snapshot(tmp_path, bad) + + with pytest.raises(ValueError, match="live write/send/runtime counts"): + load_latest_ai_agent_report_runtime_fixture_readback(tmp_path) + + +def test_rejects_fixture_secret_read(tmp_path): + data = load_latest_ai_agent_report_runtime_fixture_readback() + bad = copy.deepcopy(data) + bad["fixture_smoke_results"][0]["reads_secret_value"] = True + _write_snapshot(tmp_path, bad) + + with pytest.raises(ValueError, match="secret value"): + load_latest_ai_agent_report_runtime_fixture_readback(tmp_path) + + +def test_rejects_queue_direct_bot_api(tmp_path): + data = load_latest_ai_agent_report_runtime_fixture_readback() + bad = copy.deepcopy(data) + bad["queue_preview_readbacks"][0]["direct_bot_api_allowed"] = True + _write_snapshot(tmp_path, bad) + + with pytest.raises(ValueError, match="direct Bot API"): + load_latest_ai_agent_report_runtime_fixture_readback(tmp_path) + + +def test_rejects_verifier_live_readback(tmp_path): + data = load_latest_ai_agent_report_runtime_fixture_readback() + bad = copy.deepcopy(data) + bad["verifier_dry_run_cases"][0]["live_readback_enabled"] = True + _write_snapshot(tmp_path, bad) + + with pytest.raises(ValueError, match="live readback"): + load_latest_ai_agent_report_runtime_fixture_readback(tmp_path) + + +def test_rejects_work_window_transcript_display(tmp_path): + data = load_latest_ai_agent_report_runtime_fixture_readback() + bad = copy.deepcopy(data) + bad["display_redaction_contract"]["work_window_transcript_display_allowed"] = True + _write_snapshot(tmp_path, bad) + + with pytest.raises(ValueError, match="display redaction"): + load_latest_ai_agent_report_runtime_fixture_readback(tmp_path) + + +def test_rejects_rollup_mismatch(tmp_path): + data = load_latest_ai_agent_report_runtime_fixture_readback() + bad = copy.deepcopy(data) + bad["rollups"]["fixture_smoke_count"] = 999 + _write_snapshot(tmp_path, bad) + + with pytest.raises(ValueError, match="rollup counts"): + load_latest_ai_agent_report_runtime_fixture_readback(tmp_path) diff --git a/apps/api/tests/test_ai_agent_report_runtime_fixture_readback_api.py b/apps/api/tests/test_ai_agent_report_runtime_fixture_readback_api.py new file mode 100644 index 000000000..63978103b --- /dev/null +++ b/apps/api/tests/test_ai_agent_report_runtime_fixture_readback_api.py @@ -0,0 +1,33 @@ +from fastapi.testclient import TestClient + +from src.main import app + + +def test_get_ai_agent_report_runtime_fixture_readback_api(): + client = TestClient(app) + response = client.get("/api/v1/agents/agent-report-runtime-fixture-readback") + + assert response.status_code == 200 + data = response.json() + assert data["schema_version"] == "ai_agent_report_runtime_fixture_readback_v1" + assert data["program_status"]["current_task_id"] == "P2-403N" + assert data["program_status"]["next_task_id"] == "P2-404" + assert data["program_status"]["overall_completion_percent"] == 94 + assert data["fixture_readback_truth"]["fixture_smoke_package_ready"] is True + assert data["fixture_readback_truth"]["production_delivery_enabled"] is False + assert data["fixture_readback_truth"]["telegram_gateway_queue_write_enabled"] is False + assert data["fixture_readback_truth"]["telegram_send_enabled"] is False + assert data["fixture_readback_truth"]["telegram_bot_api_call_enabled"] is False + assert data["fixture_readback_truth"]["ai_runtime_worker_enabled"] is False + assert data["fixture_readback_truth"]["medium_low_auto_worker_enabled"] is False + assert data["rollups"]["fixture_smoke_count"] == 5 + assert data["rollups"]["passed_fixture_smoke_count"] == 3 + assert data["rollups"]["queue_preview_readback_count"] == 3 + assert data["rollups"]["verifier_dry_run_case_count"] == 4 + assert data["rollups"]["agent_role_count"] == 3 + assert data["rollups"]["operator_checkpoint_count"] == 5 + assert data["rollups"]["live_report_delivery_count"] == 0 + assert data["rollups"]["telegram_gateway_queue_write_count"] == 0 + assert data["rollups"]["telegram_send_count"] == 0 + assert data["rollups"]["telegram_bot_api_call_count"] == 0 + assert data["rollups"]["production_write_count"] == 0 diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index a15fab0d1..d7f6151bd 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -4266,6 +4266,60 @@ "high": "高風險", "critical": "關鍵阻擋" } + }, + "reportRuntimeFixtureReadback": { + "title": "P2-403N fixture smoke / queue preview readback / verifier dry-run", + "source": "{generated} · {current} → {next}", + "truthTitle": "fixture readback 真相", + "queueTitle": "queue preview readback", + "queueSummary": "readback 收件目標是 {room};Secret 只能引用 {secret};目前 queue write {queue}、Bot API {bot}、Telegram send {send}。", + "metrics": { + "overall": "P2-403N 進度", + "smoke": "fixture smoke", + "passed": "已通過", + "queueReadbacks": "queue readbacks", + "verifierCases": "verifier dry-run", + "approvals": "需批准", + "queueWrites": "queue writes", + "sends": "Telegram sends", + "botCalls": "Bot API", + "workerRuns": "worker runs", + "verifierLive": "live verifier" + }, + "flags": { + "fixtureReady": "fixture ready: {value}", + "queueReadback": "queue readback: {value}", + "redaction": "redaction: {value}", + "operatorReview": "operator packet: {value}", + "queueWrite": "queue write: {value}", + "send": "send: {value}", + "directApi": "direct API: {value}", + "secret": "secret value: {value}", + "verifier": "verifier live: {value}", + "resultWrite": "result write: {value}" + }, + "labels": { + "sourceArtifact": "source: {value}", + "outputHash": "hash: {value}", + "previewHash": "preview hash: {value}", + "evidenceHash": "evidence: {value}", + "approvalRequired": "需審核: {value}", + "liveCount": "live {count}" + }, + "statuses": { + "passed_no_write": "no-write 通過", + "passed_redaction": "redaction 通過", + "ready_for_owner_review": "可審查", + "blocked_by_runtime_gate": "runtime 阻擋", + "verified_redacted_preview": "redacted preview 已驗證", + "passed_fixture": "fixture 通過" + }, + "riskTiers": { + "low": "低風險", + "medium": "中風險", + "high": "高風險", + "critical": "關鍵阻擋" + } } } }, diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index a15fab0d1..d7f6151bd 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -4266,6 +4266,60 @@ "high": "高風險", "critical": "關鍵阻擋" } + }, + "reportRuntimeFixtureReadback": { + "title": "P2-403N fixture smoke / queue preview readback / verifier dry-run", + "source": "{generated} · {current} → {next}", + "truthTitle": "fixture readback 真相", + "queueTitle": "queue preview readback", + "queueSummary": "readback 收件目標是 {room};Secret 只能引用 {secret};目前 queue write {queue}、Bot API {bot}、Telegram send {send}。", + "metrics": { + "overall": "P2-403N 進度", + "smoke": "fixture smoke", + "passed": "已通過", + "queueReadbacks": "queue readbacks", + "verifierCases": "verifier dry-run", + "approvals": "需批准", + "queueWrites": "queue writes", + "sends": "Telegram sends", + "botCalls": "Bot API", + "workerRuns": "worker runs", + "verifierLive": "live verifier" + }, + "flags": { + "fixtureReady": "fixture ready: {value}", + "queueReadback": "queue readback: {value}", + "redaction": "redaction: {value}", + "operatorReview": "operator packet: {value}", + "queueWrite": "queue write: {value}", + "send": "send: {value}", + "directApi": "direct API: {value}", + "secret": "secret value: {value}", + "verifier": "verifier live: {value}", + "resultWrite": "result write: {value}" + }, + "labels": { + "sourceArtifact": "source: {value}", + "outputHash": "hash: {value}", + "previewHash": "preview hash: {value}", + "evidenceHash": "evidence: {value}", + "approvalRequired": "需審核: {value}", + "liveCount": "live {count}" + }, + "statuses": { + "passed_no_write": "no-write 通過", + "passed_redaction": "redaction 通過", + "ready_for_owner_review": "可審查", + "blocked_by_runtime_gate": "runtime 阻擋", + "verified_redacted_preview": "redacted preview 已驗證", + "passed_fixture": "fixture 通過" + }, + "riskTiers": { + "low": "低風險", + "medium": "中風險", + "high": "高風險", + "critical": "關鍵阻擋" + } } } }, 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 a62e6898b..d72e646c5 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 @@ -47,6 +47,7 @@ import { type AiAgentRedisDryRunGateSnapshot, type AiAgentReportAutomationReviewSnapshot, type AiAgentReportRuntimeDryRunSnapshot, + type AiAgentReportRuntimeFixtureReadbackSnapshot, type AiAgentReportRuntimeReadinessSnapshot, type AiAgentReportTruthActionabilityReviewSnapshot, type AiAgentRuntimeVerifierEvidenceReviewSnapshot, @@ -342,6 +343,7 @@ export function AutomationInventoryTab() { const [reportAutomationReview, setReportAutomationReview] = useState(null) const [reportRuntimeReadiness, setReportRuntimeReadiness] = useState(null) const [reportRuntimeDryRun, setReportRuntimeDryRun] = useState(null) + const [reportRuntimeFixtureReadback, setReportRuntimeFixtureReadback] = useState(null) const [reportTruthActionabilityReview, setReportTruthActionabilityReview] = useState(null) const [ownerDryRunPackage, setOwnerDryRunPackage] = useState(null) const [hostStatefulInventory, setHostStatefulInventory] = useState(null) @@ -377,6 +379,7 @@ export function AutomationInventoryTab() { apiClient.getAiAgentReportAutomationReview(), apiClient.getAiAgentReportRuntimeReadiness(), apiClient.getAiAgentReportRuntimeDryRun(), + apiClient.getAiAgentReportRuntimeFixtureReadback(), apiClient.getAiAgentReportTruthActionabilityReview(), apiClient.getAiAgentOwnerApprovedFixtureDryRun(), apiClient.getAiAgentHostStatefulVersionInventory(), @@ -411,6 +414,7 @@ export function AutomationInventoryTab() { reportAutomationReviewResult, reportRuntimeReadinessResult, reportRuntimeDryRunResult, + reportRuntimeFixtureReadbackResult, reportTruthActionabilityReviewResult, ownerDryRunPackageResult, hostStatefulInventoryResult, @@ -442,6 +446,7 @@ export function AutomationInventoryTab() { setReportAutomationReview(reportAutomationReviewResult.status === 'fulfilled' ? reportAutomationReviewResult.value : null) setReportRuntimeReadiness(reportRuntimeReadinessResult.status === 'fulfilled' ? reportRuntimeReadinessResult.value : null) setReportRuntimeDryRun(reportRuntimeDryRunResult.status === 'fulfilled' ? reportRuntimeDryRunResult.value : null) + setReportRuntimeFixtureReadback(reportRuntimeFixtureReadbackResult.status === 'fulfilled' ? reportRuntimeFixtureReadbackResult.value : null) setReportTruthActionabilityReview(reportTruthActionabilityReviewResult.status === 'fulfilled' ? reportTruthActionabilityReviewResult.value : null) setOwnerDryRunPackage(ownerDryRunPackageResult.status === 'fulfilled' ? ownerDryRunPackageResult.value : null) setHostStatefulInventory(hostStatefulInventoryResult.status === 'fulfilled' ? hostStatefulInventoryResult.value : null) @@ -471,6 +476,7 @@ export function AutomationInventoryTab() { reportAutomationReviewResult, reportRuntimeReadinessResult, reportRuntimeDryRunResult, + reportRuntimeFixtureReadbackResult, reportTruthActionabilityReviewResult, ownerDryRunPackageResult, hostStatefulInventoryResult, @@ -946,6 +952,53 @@ export function AutomationInventoryTab() { .slice(0, 6) }, [reportRuntimeDryRun]) + const visibleReportRuntimeFixtureResults = useMemo(() => { + if (!reportRuntimeFixtureReadback) return [] + const statusPriority = { blocked_by_runtime_gate: 0, ready_for_owner_review: 1, passed_no_write: 2, passed_redaction: 3 } as Record + return [...reportRuntimeFixtureReadback.fixture_smoke_results] + .sort((a, b) => { + const left = statusPriority[a.smoke_status] ?? 4 + const right = statusPriority[b.smoke_status] ?? 4 + if (left !== right) return left - right + return a.fixture_id.localeCompare(b.fixture_id) + }) + .slice(0, 5) + }, [reportRuntimeFixtureReadback]) + + const visibleReportRuntimeQueueReadbacks = useMemo(() => { + if (!reportRuntimeFixtureReadback) return [] + return [...reportRuntimeFixtureReadback.queue_preview_readbacks] + }, [reportRuntimeFixtureReadback]) + + const visibleReportRuntimeVerifierDryRuns = useMemo(() => { + if (!reportRuntimeFixtureReadback) return [] + const statusPriority = { blocked_by_runtime_gate: 0, ready_for_owner_review: 1, passed_fixture: 2 } as Record + return [...reportRuntimeFixtureReadback.verifier_dry_run_cases] + .sort((a, b) => { + const left = statusPriority[a.dry_run_status] ?? 3 + const right = statusPriority[b.dry_run_status] ?? 3 + if (left !== right) return left - right + return a.case_id.localeCompare(b.case_id) + }) + }, [reportRuntimeFixtureReadback]) + + const visibleReportRuntimeFixtureCheckpoints = useMemo(() => { + if (!reportRuntimeFixtureReadback) return [] + const statusPriority = { blocked_by_runtime_gate: 0, ready_for_owner_review: 1, passed_no_write: 2 } as Record + const riskPriority = { critical: 0, high: 1, medium: 2, low: 3 } as Record + return [...reportRuntimeFixtureReadback.operator_checkpoints] + .sort((a, b) => { + const left = statusPriority[a.status] ?? 3 + const right = statusPriority[b.status] ?? 3 + if (left !== right) return left - right + const leftRisk = riskPriority[a.risk_tier] ?? 4 + const rightRisk = riskPriority[b.risk_tier] ?? 4 + if (leftRisk !== rightRisk) return leftRisk - rightRisk + return a.checkpoint_id.localeCompare(b.checkpoint_id) + }) + .slice(0, 5) + }, [reportRuntimeFixtureReadback]) + const visibleReportTruthFindings = useMemo(() => { if (!reportTruthActionabilityReview) return [] const priority = { critical: 0, high: 1, medium: 2, low: 3 } as Record @@ -1165,7 +1218,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 || !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 || !reportTruthActionabilityReview || !ownerDryRunPackage || !hostStatefulInventory || !serviceHealthGapMatrix || !serviceHealthNotificationPolicy) { return (
@@ -1335,6 +1388,18 @@ export function AutomationInventoryTab() { const reportDryRunAiRuns = reportRuntimeDryRun.rollups.ai_runtime_worker_run_count const reportDryRunVerifierLive = reportRuntimeDryRun.rollups.post_action_verifier_live_readback_count const reportDryRunPrimaryDraft = visibleReportRuntimeQueueDrafts[0] + const reportFixtureOverall = reportRuntimeFixtureReadback.program_status.overall_completion_percent + const reportFixtureSmokeCount = reportRuntimeFixtureReadback.rollups.fixture_smoke_count + const reportFixturePassedCount = reportRuntimeFixtureReadback.rollups.passed_fixture_smoke_count + const reportFixtureQueueReadbacks = reportRuntimeFixtureReadback.rollups.queue_preview_readback_count + const reportFixtureVerifierCases = reportRuntimeFixtureReadback.rollups.verifier_dry_run_case_count + const reportFixtureApprovals = reportRuntimeFixtureReadback.rollups.approval_required_checkpoint_ids.length + const reportFixtureQueueWrites = reportRuntimeFixtureReadback.rollups.telegram_gateway_queue_write_count + const reportFixtureSends = reportRuntimeFixtureReadback.rollups.telegram_send_count + const reportFixtureBotCalls = reportRuntimeFixtureReadback.rollups.telegram_bot_api_call_count + const reportFixtureWorkerRuns = reportRuntimeFixtureReadback.rollups.ai_runtime_worker_run_count + const reportFixtureVerifierLive = reportRuntimeFixtureReadback.rollups.post_action_verifier_live_readback_count + const reportFixturePrimaryReadback = visibleReportRuntimeQueueReadbacks[0] const reportTruthOverall = reportTruthActionabilityReview.program_status.overall_completion_percent const reportTruthFindings = reportTruthActionabilityReview.rollups.zero_signal_finding_count const reportTruthCritical = reportTruthActionabilityReview.rollups.critical_finding_count @@ -2404,6 +2469,185 @@ export function AutomationInventoryTab() {
+
+
+
+ + + {t('reportRuntimeFixtureReadback.title')} + +
+ +
+ +
+ } /> + } /> + } /> + } /> + } /> + 0 ? 'danger' : 'ok'} icon={} /> + } /> + } /> + } /> + } /> + } /> +
+ +
+
+ {t('reportRuntimeFixtureReadback.truthTitle')} + + {reportRuntimeFixtureReadback.fixture_readback_truth.truth_note} + +
+ + + + +
+
+ +
+ {t('reportRuntimeFixtureReadback.queueTitle')} + + {t('reportRuntimeFixtureReadback.queueSummary', { + room: reportFixturePrimaryReadback?.recipient_room ?? '--', + secret: reportFixturePrimaryReadback?.secret_ref ?? '--', + queue: reportFixtureQueueWrites, + bot: reportFixtureBotCalls, + send: reportFixtureSends, + })} + +
+ + + + +
+
+
+ +
+ {visibleReportRuntimeFixtureResults.map(fixture => ( +
+
+ + {fixture.display_name} + + +
+
+ + + +
+ + {fixture.evidence_ref} + + +
+ ))} +
+ +
+ {visibleReportRuntimeQueueReadbacks.map(readback => ( +
+
+ + {readback.display_name} + + +
+
+ + + + + + +
+ +
+ ))} +
+ +
+ {reportRuntimeFixtureReadback.agent_fixture_roles.map(role => ( +
+
+ + {role.display_name} + + +
+ + {role.fixture_responsibility} + +
+ {role.observed_work.slice(0, 2).map(item => ( + + ))} + {role.blocked_now.slice(0, 2).map(item => ( + + ))} +
+
+ ))} +
+ +
+ {visibleReportRuntimeVerifierDryRuns.map(verifierCase => ( +
+
+ + {verifierCase.display_name} + + +
+
+ + + + +
+ + {verifierCase.observed_signal} + + +
+ ))} +
+ +
+ {visibleReportRuntimeFixtureCheckpoints.map(checkpoint => ( +
+
+ + {checkpoint.display_name} + + +
+
+ + + +
+ + {checkpoint.next_safe_step} + +
+ ))} +
+
+
diff --git a/apps/web/src/lib/api-client.ts b/apps/web/src/lib/api-client.ts index 2d5cec6b1..971450a35 100644 --- a/apps/web/src/lib/api-client.ts +++ b/apps/web/src/lib/api-client.ts @@ -337,6 +337,11 @@ export const apiClient = { return handleResponse(res) }, + async getAiAgentReportRuntimeFixtureReadback() { + const res = await fetch(`${API_BASE_URL}/agents/agent-report-runtime-fixture-readback`) + return handleResponse(res) + }, + async getAiAgentOwnerApprovedFixtureDryRun() { const res = await fetch(`${API_BASE_URL}/agents/agent-owner-approved-fixture-dry-run`) return handleResponse(res) @@ -2326,6 +2331,136 @@ export interface AiAgentReportRuntimeDryRunSnapshot { } } +export interface AiAgentReportRuntimeFixtureReadbackSnapshot { + schema_version: 'ai_agent_report_runtime_fixture_readback_v1' + generated_at: string + program_status: { + overall_completion_percent: number + current_priority: 'P0' | 'P1' | 'P2' | 'P3' + current_task_id: 'P2-403N' + next_task_id: 'P2-404' + read_only_mode: true + runtime_authority: 'fixture_smoke_queue_preview_readback_verifier_dry_run_only_no_live_send_or_write' + status_note: string + } + source_refs: string[] + fixture_readback_truth: { + fixture_smoke_package_ready: true + report_snapshot_hash_ready: true + telegram_queue_preview_readback_ready: true + readback_verifier_dry_run_ready: true + redaction_assertions_ready: true + operator_review_packet_ready: true + production_delivery_enabled: false + telegram_gateway_queue_write_enabled: false + telegram_send_enabled: false + telegram_bot_api_call_enabled: false + delivery_receipt_write_enabled: false + ai_runtime_worker_enabled: false + medium_low_auto_worker_enabled: false + post_action_verifier_live_readback_enabled: false + production_write_enabled: false + secret_value_read_enabled: false + work_window_transcript_display_allowed: false + live_report_delivery_count_24h: number + telegram_gateway_queue_write_count_24h: number + telegram_send_count_24h: number + telegram_bot_api_call_count_24h: number + delivery_receipt_write_count_24h: number + ai_runtime_worker_run_count_24h: number + medium_low_auto_execution_count_24h: number + post_action_verifier_live_readback_count_24h: number + production_write_count_24h: number + truth_note: string + } + fixture_smoke_results: Array<{ + fixture_id: string + display_name: string + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + source_artifact_id: string + smoke_status: 'passed_no_write' | 'passed_redaction' | 'ready_for_owner_review' | 'blocked_by_runtime_gate' + evidence_ref: string + input_hash_strategy: string + output_hash: string + writes_production: false + sends_telegram: false + reads_secret_value: false + live_execution_count_24h: number + }> + queue_preview_readbacks: Array<{ + readback_id: 'daily_report_digest_readback' | 'weekly_report_digest_readback' | 'monthly_report_digest_readback' + display_name: string + cadence: 'daily' | 'weekly' | 'monthly' + owner_agent: 'hermes' + recipient_room: 'AwoooI SRE 戰情室' + secret_ref: 'SRE_GROUP_CHAT_ID' + preview_hash: string + payload_redacted: true + gateway_queue_write_enabled: false + telegram_send_enabled: false + direct_bot_api_allowed: false + queue_write_count_24h: number + readback_status: 'verified_redacted_preview' + }> + verifier_dry_run_cases: Array<{ + case_id: string + display_name: string + owner_agent: 'hermes' | 'nemotron' + dry_run_status: 'passed_fixture' | 'ready_for_owner_review' | 'blocked_by_runtime_gate' + expected_signal: string + observed_signal: string + evidence_hash: string + live_readback_enabled: false + writes_result: false + requires_secret_value: false + }> + agent_fixture_roles: Array<{ + agent_id: 'openclaw' | 'hermes' | 'nemotron' + display_name: string + fixture_responsibility: string + observed_work: string[] + blocked_now: string[] + live_action_count_24h: number + }> + operator_checkpoints: Array<{ + checkpoint_id: string + display_name: string + owner_agent: 'openclaw' | 'hermes' | 'nemotron' + risk_tier: 'low' | 'medium' | 'high' | 'critical' + approval_required: boolean + status: 'passed_no_write' | 'ready_for_owner_review' | 'blocked_by_runtime_gate' + next_safe_step: string + }> + display_redaction_contract: { + redaction_required: true + raw_report_payload_display_allowed: false + raw_telegram_payload_display_allowed: false + private_reasoning_display_allowed: false + secret_value_display_allowed: false + work_window_transcript_display_allowed: false + allowed_display_fields: string[] + blocked_display_fields: string[] + } + rollups: { + fixture_smoke_count: number + passed_fixture_smoke_count: number + queue_preview_readback_count: number + verifier_dry_run_case_count: number + agent_role_count: number + operator_checkpoint_count: number + approval_required_checkpoint_ids: string[] + live_report_delivery_count: number + telegram_gateway_queue_write_count: number + telegram_send_count: number + telegram_bot_api_call_count: number + delivery_receipt_write_count: number + ai_runtime_worker_run_count: number + medium_low_auto_execution_count: number + post_action_verifier_live_readback_count: number + production_write_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 73a839ed9..2b1b5ab73 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -1,3 +1,30 @@ +## 2026-06-12|P2-403N fixture smoke / queue preview readback / verifier dry-run + +**背景**:P2-403M 已建立報表 runtime no-write dry-run、SRE 戰情室 Gateway queue 草案與 readback verifier 草案;本段依序推進 P2-403N,把 committed dry-run 證據轉成 fixture smoke、queue preview readback 與 verifier dry-run 的可審查證據。 + +**完成**: + +- 新增 `ai_agent_report_runtime_fixture_readback_v1` schema、committed snapshot 與 backend loader,強制 production delivery、Gateway queue write、Telegram send、Bot API、delivery receipt write、AI runtime worker、中低風險 auto worker、verifier live readback、production write、secret value read 與內部對話顯示全部維持 `false / 0`。 +- 新增 `GET /api/v1/agents/agent-report-runtime-fixture-readback` 只讀 API 與測試;API 只回傳 fixture/readback/verifier dry-run evidence,不送 Telegram、不寫 queue、不讀 secret、不啟動 worker。 +- 治理頁 `/zh-TW/governance?tab=automation-inventory` 新增 P2-403N 區塊,顯示 5 個 fixture smoke、3 個 SRE 戰情室 queue preview readback、4 個 verifier dry-run case、OpenClaw / Hermes / NemoTron fixture 分工與 5 個 operator checkpoint。 +- 更新 `AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md`、`AI_AGENT_INTERACTION_LEARNING_PROOF_2026-06-11.md` 與 MASTER §3.2 / §5,將 P2-403N 標記為完成,下一步改為 `P2-404` runtime worker shadow / no-write execution evidence gate。 + +**驗證(本地)**: + +- `python3 -m json.tool` 檢查 P2-403N snapshot / schema / `zh-TW.json` / `en.json` 通過。 +- `python3 -m py_compile apps/api/src/services/ai_agent_report_runtime_fixture_readback.py apps/api/src/api/v1/agents.py` 通過。 +- `DATABASE_URL='postgresql+asyncpg://test:test@localhost/test' PYTHONPATH=apps/api pytest -q apps/api/tests/test_ai_agent_report_runtime_fixture_readback.py apps/api/tests/test_ai_agent_report_runtime_fixture_readback_api.py`:`9 passed`。 +- `cmp -s apps/web/messages/zh-TW.json apps/web/messages/en.json` 通過,兩份訊息檔維持繁體中文鏡像。 +- `pnpm --filter @awoooi/web typecheck` 通過;本 worktree 先用 `pnpm install --frozen-lockfile` 建立臨時 `node_modules`,未改 lockfile。 + +**完成度同步**: + +- P2-403N:本地完成度 `94%`;fixture smoke `5`、已通過 fixture `3`、queue preview readback `3`、verifier dry-run case `4`、operator checkpoint `5`。 +- live report delivery、Gateway queue write、Telegram send、Telegram Bot API、delivery receipt write、AI runtime worker、中低風險 auto worker、verifier live readback、production write:全部仍為 `0`。 +- P2-404:下一步只能做 runtime worker shadow / no-write execution evidence gate;仍不得直接啟動 live queue write、Telegram send、production write 或 verifier live readback。 + +**邊界**:本段不送 Telegram、不寫 Gateway queue、不呼叫 Bot API、不寫 delivery receipt、不啟動 AI runtime worker、不啟動中低風險 auto worker、不跑 verifier live readback、不讀 secret、不顯示內部對話內容、不提供前端批准 / 執行 / 發送按鈕;不得把 fixture/readback dry-run 解讀成 runtime loop 已運作。 + ## 2026-06-12|P2-403M 報表 runtime no-write dry-run 證據包 **背景**:P2-403L 已把日報 / 週報 / 月報派送、Telegram Gateway queue、讀報回執、AI 讀報後分析、中低風險自動處理與高風險審核拆成啟動前閘門;本段依序推進到 P2-403M,把真正啟動前的 no-write dry-run、SRE 戰情室 queue 草案與 readback verifier 草案固定成可審核證據。 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 675d2579a..63ba434f2 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,固定雙重批准、dry-run hash、post-write verifier 與 redaction 欄位;P2-403H 已完成 post-write verifier implementation package、rollback lane、failure lane 與人工操作選項;P2-403I 已完成 runtime verifier evidence implementation review;P2-403J 已完成報表真相、告警有效性、日報、週報、月報、每個 Agent 工作量、圖表化報告、AI 分析建議與高 / 中 / 低風險自動化政策審查;P2-403K 已完成本地程式層 SRE 戰情室路由收斂;P2-403L 已完成報表派送、Telegram Gateway queue、讀報回執、AI 讀報後分析、中低風險自動處理與高風險審核的啟動前閘門;P2-403M 已完成報表 runtime no-write dry-run 證據包、SRE 戰情室 Gateway queue 草案與 readback verifier 草案。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_live_read_model_gate_v1`、`ai_agent_redis_dry_run_gate_v1`、`ai_agent_learning_writeback_approval_package_v1`、`ai_agent_telegram_receipt_approval_package_v1`、`ai_agent_owner_approved_learning_dry_run_v1`、`ai_agent_owner_approved_fixture_dry_run_v1`、`GET /api/v1/agents/agent-communication-learning-contract`、`GET /api/v1/agents/agent-interaction-learning-proof`、`GET /api/v1/agents/agent-live-read-model-gate`、`GET /api/v1/agents/agent-redis-dry-run-gate`、`GET /api/v1/agents/agent-learning-writeback-approval-package`、`GET /api/v1/agents/agent-telegram-receipt-approval-package`、`GET /api/v1/agents/agent-owner-approved-learning-dry-run`、`GET /api/v1/agents/agent-owner-approved-fixture-dry-run`、`ai_agent_runtime_write_gate_review_v1`、`GET /api/v1/agents/agent-runtime-write-gate-review`、`ai_agent_post_write_verifier_package_v1`、`GET /api/v1/agents/agent-post-write-verifier-package`、`ai_agent_runtime_verifier_evidence_review_v1`、`GET /api/v1/agents/agent-runtime-verifier-evidence-review`、`ai_agent_report_truth_actionability_review_v1`、`GET /api/v1/agents/agent-report-truth-actionability-review`、`ai_agent_report_automation_review_v1`、`GET /api/v1/agents/agent-report-automation-review`、`ai_agent_report_runtime_readiness_v1`、`GET /api/v1/agents/agent-report-runtime-readiness`、`ai_agent_report_runtime_dry_run_v1`、`GET /api/v1/agents/agent-report-runtime-dry-run`、`/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,固定雙重批准、dry-run hash、post-write verifier 與 redaction 欄位;P2-403H 已完成 post-write verifier implementation package、rollback lane、failure lane 與人工操作選項;P2-403I 已完成 runtime verifier evidence implementation review;P2-403J 已完成報表真相、告警有效性、日報、週報、月報、每個 Agent 工作量、圖表化報告、AI 分析建議與高 / 中 / 低風險自動化政策審查;P2-403K 已完成本地程式層 SRE 戰情室路由收斂;P2-403L 已完成報表派送、Telegram Gateway queue、讀報回執、AI 讀報後分析、中低風險自動處理與高風險審核的啟動前閘門;P2-403M 已完成報表 runtime no-write dry-run 證據包、SRE 戰情室 Gateway queue 草案與 readback verifier 草案;P2-403N 已完成 fixture smoke、queue preview readback 與 verifier 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_live_read_model_gate_v1`、`ai_agent_redis_dry_run_gate_v1`、`ai_agent_learning_writeback_approval_package_v1`、`ai_agent_telegram_receipt_approval_package_v1`、`ai_agent_owner_approved_learning_dry_run_v1`、`ai_agent_owner_approved_fixture_dry_run_v1`、`GET /api/v1/agents/agent-communication-learning-contract`、`GET /api/v1/agents/agent-interaction-learning-proof`、`GET /api/v1/agents/agent-live-read-model-gate`、`GET /api/v1/agents/agent-redis-dry-run-gate`、`GET /api/v1/agents/agent-learning-writeback-approval-package`、`GET /api/v1/agents/agent-telegram-receipt-approval-package`、`GET /api/v1/agents/agent-owner-approved-learning-dry-run`、`GET /api/v1/agents/agent-owner-approved-fixture-dry-run`、`ai_agent_runtime_write_gate_review_v1`、`GET /api/v1/agents/agent-runtime-write-gate-review`、`ai_agent_post_write_verifier_package_v1`、`GET /api/v1/agents/agent-post-write-verifier-package`、`ai_agent_runtime_verifier_evidence_review_v1`、`GET /api/v1/agents/agent-runtime-verifier-evidence-review`、`ai_agent_report_truth_actionability_review_v1`、`GET /api/v1/agents/agent-report-truth-actionability-review`、`ai_agent_report_automation_review_v1`、`GET /api/v1/agents/agent-report-automation-review`、`ai_agent_report_runtime_readiness_v1`、`GET /api/v1/agents/agent-report-runtime-readiness`、`ai_agent_report_runtime_dry_run_v1`、`GET /api/v1/agents/agent-report-runtime-dry-run`、`ai_agent_report_runtime_fixture_readback_v1`、`GET /api/v1/agents/agent-report-runtime-fixture-readback`、`/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、人工操作選項與 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 SRE 戰情室路由程式收斂、P2-403L 報表派送 / Telegram queue / 讀報回執 / AI 讀報分析 / 中低風險自動處理 / 高風險審核啟動前閘門,以及 P2-403M no-write dry-run / SRE 戰情室 Gateway queue 草案 / readback verifier;目前 live AgentSession、Agent message、handoff、learning write、Telegram receipt、Gateway queue write、runtime verifier execution、report delivery、AI analysis runtime、中低風險 auto worker、Telegram 實發與 delivery receipt E2E 仍全部為 `0`,下一步依優先順序推 `P2-403N` fixture smoke / queue preview readback / verifier dry-run,但在批准前仍不得啟動 runtime loop。 +三 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、人工操作選項與 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 SRE 戰情室路由程式收斂、P2-403L 報表派送 / Telegram queue / 讀報回執 / AI 讀報分析 / 中低風險自動處理 / 高風險審核啟動前閘門、P2-403M no-write dry-run / SRE 戰情室 Gateway queue 草案 / readback verifier,以及 P2-403N fixture smoke / queue preview readback / verifier 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 實發與 delivery receipt E2E 仍全部為 `0`,下一步依優先順序推 `P2-404` runtime worker shadow / no-write execution evidence gate,但在批准前仍不得啟動 runtime loop。 -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-403M` 已先補互動、學習證據面、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 證據包。下一步是 `P2-403N` fixture smoke / queue preview readback / verifier dry-run,外部 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-403N` 已先補互動、學習證據面、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 證據包。下一步是 `P2-404` runtime worker shadow / no-write execution evidence gate,外部 registry / package source / host probe / SSH / kubectl / 工具安裝 / CI 變更 / 實際 PR creation / Telegram 實發與 learning write 仍需 gate。 完成度計算模型: @@ -971,7 +971,8 @@ UI: | P2-403K | 本地完成,正式站待驗證 | 100 | OpenClaw | AwoooI SRE 戰情室路由程式收斂;移除 Gitea / API / ops script 舊群組與 private mirror fallback | Gitea workflow 使用 `SRE_GROUP_CHAT_ID`;CD 舊相容欄位取自 SRE group;Telegram Gateway / notification matrix / jobs / ops scripts SRE-only;CI guard 擋舊 `TELEGRAM_ALERT_CHAT_ID` / `TELEGRAM_CHAT_ID` 與非 SRE direct fallback | 未讀 secret value、未發 Telegram live 測試、未改 Prometheus / Alertmanager route、未開 Gateway queue write / receipt worker / runtime gate | | P2-403L | 完成 | 86 | OpenClaw + Hermes + NemoTron | 報表派送、Telegram Gateway queue、讀報回執、AI 讀報後分析、中低風險自動處理、高風險審核與 post-action verifier 啟動前閘門 | `ai_agent_report_runtime_readiness_v1` / snapshot / 只讀 API / governance UI;7 個 runtime lane、3 個報表週期 gate、4 個風險政策、7 個 operator decision、SRE 戰情室路由 contract;live delivery / queue write / AI runtime / 中低風險執行全部 `0` | 不排程實發、不寫 Gateway queue、不呼叫 Bot API、不啟動 AI runtime worker、不啟動中低風險 auto worker、不執行生產優化、不讀 secret、不顯示內部對話內容 | | P2-403M | 完成 | 91 | OpenClaw + Hermes + NemoTron | 報表 runtime no-write dry-run、SRE 戰情室 Gateway queue 草案、readback verifier 草案 | `ai_agent_report_runtime_dry_run_v1` / snapshot / 只讀 API / governance UI;5 個 dry-run artifact、3 個 queue digest 草案、4 個 readback verifier case、3 個 Agent dry-run role、6 個 operator checkpoint;live delivery / queue write / Bot API / receipt write / AI runtime / 中低風險 auto worker / verifier live readback 全部 `0` | 不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 delivery receipt、不啟動 AI runtime worker、不啟動中低風險 auto worker、不執行 verifier live readback、不讀 secret、不顯示內部對話內容 | -| P2-403N | 待辦 | 0 | Hermes + NemoTron + OpenClaw | fixture smoke / queue preview readback / verifier dry-run | 以 P2-403M committed snapshot 產生 redacted hash 與 no-write readback evidence | 仍不得 live send / live write;中低風險自動處理與高風險審核需另行批准 | +| 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 | 待辦 | 0 | OpenClaw + Hermes + NemoTron | runtime worker shadow / no-write execution evidence gate | 以 P2-403N fixture/readback/verifier dry-run promotion 建立 shadow worker evidence | 不寫 Gateway queue、不送 Telegram、不 production write;所有 shadow result 需 redacted evidence 與 verifier dry-run | | P2-101 | 待辦 | 0 | OpenClaw | 定義操作類別權限模型 | 操作政策 schema | HITL 關卡 | | P2-102 | 待辦 | 0 | OpenClaw | 所有候選操作都要有 dry-run 證據 | dry-run 合約 | 不直接 apply | | P2-103 | 待辦 | 0 | Hermes | 把任務結果接回 KM / LOGBOOK / 稽核軌跡 | 證據寫入器 | 不洩漏 secret | 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 b7e7c8826..26ec7f349 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 證據包、API 與治理頁 UI。 -> 事實邊界:本波只建立可見證據面、read model gate、報表治理 review、runtime readiness gate 與 no-write dry-run 證據包,不啟動 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、API 與治理頁 UI。 +> 事實邊界:本波只建立可見證據面、read model gate、報表治理 review、runtime readiness gate、no-write dry-run 與 fixture/readback/verifier dry-run 證據包,不啟動 runtime worker、不建立 DB migration、不開 Redis consumer group、不發 Telegram、不寫 Gateway queue、不寫 delivery receipt、不排程實發報告、不啟動中低風險 auto worker、不執行 verifier live readback、不執行生產優化、不顯示工作視窗對話內容。 ## 0. P2-403J 補記:報表真相、日週月報與風險自動化 Review @@ -22,9 +22,15 @@ 本段把 P2-403L 的啟動前閘門往前推到可審查 dry-run 證據:5 個 dry-run artifact、3 個 SRE 戰情室 Telegram digest queue 草案、4 個 readback verifier case、3 個 Agent dry-run role 與 6 個 operator checkpoint。OpenClaw 負責 no-write 風險裁決與中低風險 no-op plan;Hermes 負責 report snapshot preview、redacted Telegram digest 草案與 readback checklist;NemoTron 負責 fixture-only replay scoring、readback failure mode tagging 與 sanitized regression summary。本段仍不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 delivery receipt、不啟動 AI runtime worker、不啟動中低風險 auto worker、不跑 verifier live readback、不讀 secret,所有 live count 仍為 `0`。 +## 0.3 P2-403N 補記:fixture smoke / queue preview readback / verifier dry-run + +2026-06-12 已新增 P2-403N:`ai_agent_report_runtime_fixture_readback_v1`、`docs/evaluations/ai_agent_report_runtime_fixture_readback_2026-06-12.json`、`GET /api/v1/agents/agent-report-runtime-fixture-readback` 與治理頁區塊。 + +本段把 P2-403M committed dry-run 證據轉成可審查 fixture/readback/verifier 證據:5 個 fixture smoke、3 個 SRE 戰情室 queue preview readback、4 個 verifier dry-run case、3 個 Agent fixture role 與 5 個 operator checkpoint。Hermes 負責 report snapshot / Telegram digest / queue preview / receipt redaction 的 readback hash;NemoTron 負責 verifier dry-run 與 no-op replay failure mode;OpenClaw 負責判斷哪些 promotion 必須保持 no-write 或等待高風險審核。本段仍不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 delivery receipt、不啟動 AI runtime worker、不啟動中低風險 auto worker、不跑 verifier live readback、不讀 secret,所有 live count 仍為 `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:讓統帥能在治理頁看到 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 證據包下一步要通過哪些 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:讓統帥能在治理頁看到 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 證據包下一步要通過哪些 gate。 目前真相: @@ -45,6 +51,7 @@ | Report delivery / AI analysis / auto optimization | 未啟用,數量 `0` | | Telegram Gateway queue / 中低風險 auto worker | 未啟用,數量 `0` | | P2-403M no-write dry-run package | 已完成,正式寫入 / 發送 / worker / verifier live readback 全為 `0` | +| P2-403N fixture readback package | 已完成,queue write / Telegram send / Bot API / worker / verifier live readback 全為 `0` | 這代表使用者現在可以看見「哪裡已準備好、哪裡仍未運作、被哪個 gate 阻擋、下一步要如何驗證」。但還不能宣稱三個 Agent 已經在 production runtime 主動互傳訊息或自主學習。 @@ -100,18 +107,20 @@ | `docs/schemas/ai_agent_report_runtime_dry_run_v1.schema.json` | P2-403M 報表 runtime no-write dry-run schema;強制 Gateway queue write、Telegram send、Bot API、delivery receipt、AI runtime worker、中低風險 auto worker、verifier live readback 與 production write 全部維持未授權 | | `docs/evaluations/ai_agent_report_runtime_dry_run_2026-06-12.json` | P2-403M committed snapshot,完成度 `91%`,5 個 dry-run artifact、3 個 queue digest 草案、4 個 readback verifier case、3 個 Agent role、6 個 operator checkpoint;所有 live counts 全為 `0` | | `GET /api/v1/agents/agent-report-runtime-dry-run` | 只讀 API;不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 delivery receipt、不啟動 worker、不讀 secret | +| `docs/schemas/ai_agent_report_runtime_fixture_readback_v1.schema.json` | P2-403N fixture smoke / queue preview readback / verifier dry-run schema;強制 queue write、Telegram send、Bot API、receipt write、worker、verifier live readback、production write 與 secret read 維持未授權 | +| `docs/evaluations/ai_agent_report_runtime_fixture_readback_2026-06-12.json` | P2-403N committed snapshot,完成度 `94%`,5 個 fixture smoke、3 個 queue preview readback、4 個 verifier dry-run case、3 個 Agent fixture role、5 個 operator checkpoint;所有 live counts 全為 `0` | +| `GET /api/v1/agents/agent-report-runtime-fixture-readback` | 只讀 API;不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 delivery receipt、不啟動 worker、不讀 secret | | `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、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、Agent lane、可觀測訊號、runtime gates、前端 redaction | ## 5. 後續優先順序 | 優先 | ID | 工作 | gate | |---:|---|---|---| -| 1 | P2-403N | fixture smoke / queue preview readback / verifier dry-run | 仍不得 live send / live write | -| 2 | P2-404 | runtime worker shadow / no-write execution evidence gate | runtime shadow evidence | +| 1 | P2-404 | runtime worker shadow / no-write execution evidence gate | runtime shadow evidence | ## 6. 紅線 diff --git a/docs/evaluations/ai_agent_report_runtime_fixture_readback_2026-06-12.json b/docs/evaluations/ai_agent_report_runtime_fixture_readback_2026-06-12.json new file mode 100644 index 000000000..6d52d662a --- /dev/null +++ b/docs/evaluations/ai_agent_report_runtime_fixture_readback_2026-06-12.json @@ -0,0 +1,363 @@ +{ + "schema_version": "ai_agent_report_runtime_fixture_readback_v1", + "generated_at": "2026-06-12T13:40:00+08:00", + "program_status": { + "overall_completion_percent": 94, + "current_priority": "P2", + "current_task_id": "P2-403N", + "next_task_id": "P2-404", + "read_only_mode": true, + "runtime_authority": "fixture_smoke_queue_preview_readback_verifier_dry_run_only_no_live_send_or_write", + "status_note": "P2-403N 已把 P2-403M no-write dry-run 往前推到 fixture smoke、queue preview readback 與 verifier dry-run 證據包;目前仍不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫讀報回執、不啟動 AI runtime worker 或中低風險 auto worker。" + }, + "source_refs": [ + "docs/evaluations/ai_agent_report_runtime_dry_run_2026-06-12.json", + "docs/evaluations/ai_agent_report_runtime_readiness_2026-06-12.json", + "docs/evaluations/ai_agent_report_automation_review_2026-06-12.json", + "docs/evaluations/ai_agent_runtime_verifier_evidence_review_2026-06-12.json", + "docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md" + ], + "fixture_readback_truth": { + "fixture_smoke_package_ready": true, + "report_snapshot_hash_ready": true, + "telegram_queue_preview_readback_ready": true, + "readback_verifier_dry_run_ready": true, + "redaction_assertions_ready": true, + "operator_review_packet_ready": true, + "production_delivery_enabled": false, + "telegram_gateway_queue_write_enabled": false, + "telegram_send_enabled": false, + "telegram_bot_api_call_enabled": false, + "delivery_receipt_write_enabled": false, + "ai_runtime_worker_enabled": false, + "medium_low_auto_worker_enabled": false, + "post_action_verifier_live_readback_enabled": false, + "production_write_enabled": false, + "secret_value_read_enabled": false, + "work_window_transcript_display_allowed": false, + "live_report_delivery_count_24h": 0, + "telegram_gateway_queue_write_count_24h": 0, + "telegram_send_count_24h": 0, + "telegram_bot_api_call_count_24h": 0, + "delivery_receipt_write_count_24h": 0, + "ai_runtime_worker_run_count_24h": 0, + "medium_low_auto_execution_count_24h": 0, + "post_action_verifier_live_readback_count_24h": 0, + "production_write_count_24h": 0, + "truth_note": "本段已產出 fixture smoke 與 readback hash 證據,但所有正式 queue write、Telegram send、Bot API、receipt write、runtime worker、auto worker、verifier live readback 與 production write 仍保持 0。" + }, + "fixture_smoke_results": [ + { + "fixture_id": "report_run_snapshot_fixture", + "display_name": "report_run snapshot fixture smoke", + "owner_agent": "hermes", + "source_artifact_id": "report_run_snapshot_preview", + "smoke_status": "passed_no_write", + "evidence_ref": "docs/evaluations/ai_agent_report_runtime_dry_run_2026-06-12.json", + "input_hash_strategy": "P2-403M committed snapshot normalized JSON hash", + "output_hash": "sha256:64b01c50a98958f19a79e0891120bc2a618892c81d65ed0a0eea8e25d213c328", + "writes_production": false, + "sends_telegram": false, + "reads_secret_value": false, + "live_execution_count_24h": 0 + }, + { + "fixture_id": "telegram_digest_payload_fixture", + "display_name": "Telegram digest payload fixture smoke", + "owner_agent": "hermes", + "source_artifact_id": "telegram_digest_payload_preview", + "smoke_status": "passed_redaction", + "evidence_ref": "docs/evaluations/ai_agent_telegram_receipt_approval_package_2026-06-11.json", + "input_hash_strategy": "redacted digest metadata hash", + "output_hash": "sha256:e3a36721167bdc4c39b8f497a7048523d7a558fc2967a0eb4ee85b21b8d37d5b", + "writes_production": false, + "sends_telegram": false, + "reads_secret_value": false, + "live_execution_count_24h": 0 + }, + { + "fixture_id": "queue_preview_redaction_fixture", + "display_name": "Gateway queue preview redaction fixture", + "owner_agent": "hermes", + "source_artifact_id": "gateway_queue_preview_readback", + "smoke_status": "passed_redaction", + "evidence_ref": "docs/evaluations/ai_agent_report_runtime_dry_run_2026-06-12.json", + "input_hash_strategy": "queue draft metadata only hash", + "output_hash": "sha256:65b63639094efccedef00278dad35d92bcbffbabbfab6681026e0f03640d9d68", + "writes_production": false, + "sends_telegram": false, + "reads_secret_value": false, + "live_execution_count_24h": 0 + }, + { + "fixture_id": "receipt_redaction_fixture", + "display_name": "讀報回執 redaction fixture", + "owner_agent": "hermes", + "source_artifact_id": "receipt_redaction_readback", + "smoke_status": "ready_for_owner_review", + "evidence_ref": "docs/evaluations/ai_agent_telegram_receipt_approval_package_2026-06-11.json", + "input_hash_strategy": "receipt schema field allow-list hash", + "output_hash": "sha256:c0ef6e536d10cf97de6dd500409274d4708b329bee9c7eeedc9c8091ae184655", + "writes_production": false, + "sends_telegram": false, + "reads_secret_value": false, + "live_execution_count_24h": 0 + }, + { + "fixture_id": "medium_low_noop_fixture", + "display_name": "中低風險 no-op verifier fixture", + "owner_agent": "nemotron", + "source_artifact_id": "medium_low_noop_readback", + "smoke_status": "blocked_by_runtime_gate", + "evidence_ref": "docs/evaluations/ai_agent_runtime_verifier_evidence_review_2026-06-12.json", + "input_hash_strategy": "fixture-only no-op plan hash", + "output_hash": "sha256:cc0b177f0f55e05442f7c1df9d5ba86b5e85972e2a9706fd092d3e742db48b0d", + "writes_production": false, + "sends_telegram": false, + "reads_secret_value": false, + "live_execution_count_24h": 0 + } + ], + "queue_preview_readbacks": [ + { + "readback_id": "daily_report_digest_readback", + "display_name": "AI Agent 日報 queue preview readback", + "cadence": "daily", + "owner_agent": "hermes", + "recipient_room": "AwoooI SRE 戰情室", + "secret_ref": "SRE_GROUP_CHAT_ID", + "preview_hash": "sha256:5cbc0ccc80ab44d25cfda8694408725e1de02ed4eaff6da499e80abfbcfa6d09", + "payload_redacted": true, + "gateway_queue_write_enabled": false, + "telegram_send_enabled": false, + "direct_bot_api_allowed": false, + "queue_write_count_24h": 0, + "readback_status": "verified_redacted_preview" + }, + { + "readback_id": "weekly_report_digest_readback", + "display_name": "AI Agent 週報 queue preview readback", + "cadence": "weekly", + "owner_agent": "hermes", + "recipient_room": "AwoooI SRE 戰情室", + "secret_ref": "SRE_GROUP_CHAT_ID", + "preview_hash": "sha256:1514a8c06bd4197da659cb1259b74824c0544a74efcae6b91ecdee3bd0383361", + "payload_redacted": true, + "gateway_queue_write_enabled": false, + "telegram_send_enabled": false, + "direct_bot_api_allowed": false, + "queue_write_count_24h": 0, + "readback_status": "verified_redacted_preview" + }, + { + "readback_id": "monthly_report_digest_readback", + "display_name": "AI Agent 月報 queue preview readback", + "cadence": "monthly", + "owner_agent": "hermes", + "recipient_room": "AwoooI SRE 戰情室", + "secret_ref": "SRE_GROUP_CHAT_ID", + "preview_hash": "sha256:764aa686c5813c01a5cc239e3242a3d28557f4f2b1babb310ba45daae3faa0e5", + "payload_redacted": true, + "gateway_queue_write_enabled": false, + "telegram_send_enabled": false, + "direct_bot_api_allowed": false, + "queue_write_count_24h": 0, + "readback_status": "verified_redacted_preview" + } + ], + "verifier_dry_run_cases": [ + { + "case_id": "report_snapshot_verifier_dry_run", + "display_name": "報表 snapshot verifier dry-run", + "owner_agent": "hermes", + "dry_run_status": "passed_fixture", + "expected_signal": "schema、generated_at、workload、risk counts 與 live zero counts 可讀", + "observed_signal": "fixture hash matched committed P2-403M report dry-run snapshot", + "evidence_hash": "sha256:c32b9baa11968da5c122b9e3aca28bc3aba3a0a8ac6f541ea95407a455f9262e", + "live_readback_enabled": false, + "writes_result": false, + "requires_secret_value": false + }, + { + "case_id": "gateway_preview_verifier_dry_run", + "display_name": "Gateway queue preview verifier dry-run", + "owner_agent": "hermes", + "dry_run_status": "passed_fixture", + "expected_signal": "recipient room、secret ref、noise budget 與 redacted preview hash 可讀", + "observed_signal": "三種 cadence queue preview 全部只含 redacted metadata", + "evidence_hash": "sha256:50f5e59e72d4807b07a66b184c25e8f0ebb3036f813fa68ae2cddd11aeb255a8", + "live_readback_enabled": false, + "writes_result": false, + "requires_secret_value": false + }, + { + "case_id": "receipt_redaction_verifier_dry_run", + "display_name": "讀報回執 redaction verifier dry-run", + "owner_agent": "hermes", + "dry_run_status": "ready_for_owner_review", + "expected_signal": "不顯示 chat_id、message_id、raw payload、token 或 authorization header", + "observed_signal": "只保留 redacted message ref 與 receipt contract 欄位", + "evidence_hash": "sha256:122f7412baf69e395d109d7f29c0c4fd021d421bd0aea49e015d067a64ad2189", + "live_readback_enabled": false, + "writes_result": false, + "requires_secret_value": false + }, + { + "case_id": "medium_low_noop_verifier_dry_run", + "display_name": "中低風險 no-op verifier dry-run", + "owner_agent": "nemotron", + "dry_run_status": "blocked_by_runtime_gate", + "expected_signal": "能比較預期 action、no-op 結果與 rollback/readback 訊號,不碰 production target", + "observed_signal": "缺 canonical target inventory promotion,保持 blocked_by_runtime_gate", + "evidence_hash": "sha256:5b07c66a82c9d2d75baa74f51ad869e422679ff83079a6e45712075113a28ee1", + "live_readback_enabled": false, + "writes_result": false, + "requires_secret_value": false + } + ], + "agent_fixture_roles": [ + { + "agent_id": "openclaw", + "display_name": "OpenClaw", + "fixture_responsibility": "審核 fixture smoke 結果是否能升級成中低風險 no-write 執行提案,並阻擋高風險或未通過 guard 的自動化。", + "observed_work": [ + "確認高風險仍需要統帥審核", + "把中低風險維持在 no-op / no-write", + "拒收未附 verifier dry-run 的 promotion" + ], + "blocked_now": [ + "production write", + "high risk execution", + "provider route change" + ], + "live_action_count_24h": 0 + }, + { + "agent_id": "hermes", + "display_name": "Hermes", + "fixture_responsibility": "維護 report snapshot、Telegram digest preview、queue preview readback 與 receipt redaction 的可讀證據。", + "observed_work": [ + "完成三種 cadence queue preview readback", + "提供 redacted digest hash", + "固定不顯示 raw Telegram payload" + ], + "blocked_now": [ + "Gateway queue write", + "Telegram send", + "delivery receipt write" + ], + "live_action_count_24h": 0 + }, + { + "agent_id": "nemotron", + "display_name": "NemoTron", + "fixture_responsibility": "針對 verifier dry-run、failure mode 與 no-op replay 做 fixture-only regression 標籤。", + "observed_work": [ + "標記 no-op verifier blocked_by_runtime_gate", + "整理 fixture-only readback failure mode", + "確認 live verifier execution 仍為 0" + ], + "blocked_now": [ + "live verifier execution", + "production route", + "paid API call" + ], + "live_action_count_24h": 0 + } + ], + "operator_checkpoints": [ + { + "checkpoint_id": "fixture_hash_review", + "display_name": "fixture hash review", + "owner_agent": "hermes", + "risk_tier": "low", + "approval_required": false, + "status": "passed_no_write", + "next_safe_step": "保留 committed fixture hash,下一步只允許在 shadow worker 中重放,不寫 DB。" + }, + { + "checkpoint_id": "queue_preview_hash_review", + "display_name": "Gateway queue preview hash review", + "owner_agent": "hermes", + "risk_tier": "medium", + "approval_required": true, + "status": "ready_for_owner_review", + "next_safe_step": "統帥批准後仍只能進入 queue writer shadow,不得直接 XADD 或送 Telegram。" + }, + { + "checkpoint_id": "receipt_redaction_review", + "display_name": "receipt redaction review", + "owner_agent": "hermes", + "risk_tier": "medium", + "approval_required": true, + "status": "ready_for_owner_review", + "next_safe_step": "確認 receipt 欄位只保留 redacted ref;chat_id / message_id 原值仍不得顯示。" + }, + { + "checkpoint_id": "verifier_case_promotion_review", + "display_name": "verifier case promotion review", + "owner_agent": "nemotron", + "risk_tier": "high", + "approval_required": true, + "status": "blocked_by_runtime_gate", + "next_safe_step": "補 canonical target inventory 與 rollback/readback gate 後,才能申請 live verifier shadow。" + }, + { + "checkpoint_id": "medium_low_noop_guard_review", + "display_name": "中低風險 no-op guard review", + "owner_agent": "openclaw", + "risk_tier": "high", + "approval_required": true, + "status": "blocked_by_runtime_gate", + "next_safe_step": "建立 allow-list、idempotency key、rollback evidence 與 failure-only Telegram 草案後再評估。" + } + ], + "display_redaction_contract": { + "redaction_required": true, + "raw_report_payload_display_allowed": false, + "raw_telegram_payload_display_allowed": false, + "private_reasoning_display_allowed": false, + "secret_value_display_allowed": false, + "work_window_transcript_display_allowed": false, + "allowed_display_fields": [ + "fixture smoke status", + "redacted preview hash", + "queue preview readback metadata", + "verifier dry-run status", + "Agent responsibility", + "operator checkpoint status", + "live zero counts" + ], + "blocked_display_fields": [ + "工作視窗對話內容", + "chain of thought", + "raw Telegram payload", + "chat_id / message_id raw value", + "authorization header", + "secret value" + ] + }, + "rollups": { + "fixture_smoke_count": 5, + "passed_fixture_smoke_count": 3, + "queue_preview_readback_count": 3, + "verifier_dry_run_case_count": 4, + "agent_role_count": 3, + "operator_checkpoint_count": 5, + "approval_required_checkpoint_ids": [ + "medium_low_noop_guard_review", + "queue_preview_hash_review", + "receipt_redaction_review", + "verifier_case_promotion_review" + ], + "live_report_delivery_count": 0, + "telegram_gateway_queue_write_count": 0, + "telegram_send_count": 0, + "telegram_bot_api_call_count": 0, + "delivery_receipt_write_count": 0, + "ai_runtime_worker_run_count": 0, + "medium_low_auto_execution_count": 0, + "post_action_verifier_live_readback_count": 0, + "production_write_count": 0 + } +} diff --git a/docs/schemas/ai_agent_report_runtime_fixture_readback_v1.schema.json b/docs/schemas/ai_agent_report_runtime_fixture_readback_v1.schema.json new file mode 100644 index 000000000..c0caf3585 --- /dev/null +++ b/docs/schemas/ai_agent_report_runtime_fixture_readback_v1.schema.json @@ -0,0 +1,366 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://awoooi.wooo.work/schemas/ai_agent_report_runtime_fixture_readback_v1.schema.json", + "title": "AI Agent Report Runtime Fixture Readback v1", + "type": "object", + "required": [ + "schema_version", + "generated_at", + "program_status", + "source_refs", + "fixture_readback_truth", + "fixture_smoke_results", + "queue_preview_readbacks", + "verifier_dry_run_cases", + "agent_fixture_roles", + "operator_checkpoints", + "display_redaction_contract", + "rollups" + ], + "properties": { + "schema_version": { "const": "ai_agent_report_runtime_fixture_readback_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-403N" }, + "next_task_id": { "const": "P2-404" }, + "read_only_mode": { "const": true }, + "runtime_authority": { "const": "fixture_smoke_queue_preview_readback_verifier_dry_run_only_no_live_send_or_write" }, + "status_note": { "type": "string" } + }, + "additionalProperties": false + }, + "source_refs": { "type": "array", "items": { "type": "string" }, "minItems": 1 }, + "fixture_readback_truth": { + "type": "object", + "required": [ + "fixture_smoke_package_ready", + "report_snapshot_hash_ready", + "telegram_queue_preview_readback_ready", + "readback_verifier_dry_run_ready", + "redaction_assertions_ready", + "operator_review_packet_ready", + "production_delivery_enabled", + "telegram_gateway_queue_write_enabled", + "telegram_send_enabled", + "telegram_bot_api_call_enabled", + "delivery_receipt_write_enabled", + "ai_runtime_worker_enabled", + "medium_low_auto_worker_enabled", + "post_action_verifier_live_readback_enabled", + "production_write_enabled", + "secret_value_read_enabled", + "work_window_transcript_display_allowed", + "live_report_delivery_count_24h", + "telegram_gateway_queue_write_count_24h", + "telegram_send_count_24h", + "telegram_bot_api_call_count_24h", + "delivery_receipt_write_count_24h", + "ai_runtime_worker_run_count_24h", + "medium_low_auto_execution_count_24h", + "post_action_verifier_live_readback_count_24h", + "production_write_count_24h", + "truth_note" + ], + "properties": { + "fixture_smoke_package_ready": { "const": true }, + "report_snapshot_hash_ready": { "const": true }, + "telegram_queue_preview_readback_ready": { "const": true }, + "readback_verifier_dry_run_ready": { "const": true }, + "redaction_assertions_ready": { "const": true }, + "operator_review_packet_ready": { "const": true }, + "production_delivery_enabled": { "const": false }, + "telegram_gateway_queue_write_enabled": { "const": false }, + "telegram_send_enabled": { "const": false }, + "telegram_bot_api_call_enabled": { "const": false }, + "delivery_receipt_write_enabled": { "const": false }, + "ai_runtime_worker_enabled": { "const": false }, + "medium_low_auto_worker_enabled": { "const": false }, + "post_action_verifier_live_readback_enabled": { "const": false }, + "production_write_enabled": { "const": false }, + "secret_value_read_enabled": { "const": false }, + "work_window_transcript_display_allowed": { "const": false }, + "live_report_delivery_count_24h": { "const": 0 }, + "telegram_gateway_queue_write_count_24h": { "const": 0 }, + "telegram_send_count_24h": { "const": 0 }, + "telegram_bot_api_call_count_24h": { "const": 0 }, + "delivery_receipt_write_count_24h": { "const": 0 }, + "ai_runtime_worker_run_count_24h": { "const": 0 }, + "medium_low_auto_execution_count_24h": { "const": 0 }, + "post_action_verifier_live_readback_count_24h": { "const": 0 }, + "production_write_count_24h": { "const": 0 }, + "truth_note": { "type": "string" } + }, + "additionalProperties": false + }, + "fixture_smoke_results": { + "type": "array", + "minItems": 5, + "items": { + "type": "object", + "required": [ + "fixture_id", + "display_name", + "owner_agent", + "source_artifact_id", + "smoke_status", + "evidence_ref", + "input_hash_strategy", + "output_hash", + "writes_production", + "sends_telegram", + "reads_secret_value", + "live_execution_count_24h" + ], + "properties": { + "fixture_id": { + "enum": [ + "report_run_snapshot_fixture", + "telegram_digest_payload_fixture", + "queue_preview_redaction_fixture", + "receipt_redaction_fixture", + "medium_low_noop_fixture" + ] + }, + "display_name": { "type": "string" }, + "owner_agent": { "enum": ["openclaw", "hermes", "nemotron"] }, + "source_artifact_id": { "type": "string" }, + "smoke_status": { + "enum": [ + "passed_no_write", + "passed_redaction", + "ready_for_owner_review", + "blocked_by_runtime_gate" + ] + }, + "evidence_ref": { "type": "string" }, + "input_hash_strategy": { "type": "string" }, + "output_hash": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" }, + "writes_production": { "const": false }, + "sends_telegram": { "const": false }, + "reads_secret_value": { "const": false }, + "live_execution_count_24h": { "const": 0 } + }, + "additionalProperties": false + } + }, + "queue_preview_readbacks": { + "type": "array", + "minItems": 3, + "items": { + "type": "object", + "required": [ + "readback_id", + "display_name", + "cadence", + "owner_agent", + "recipient_room", + "secret_ref", + "preview_hash", + "payload_redacted", + "gateway_queue_write_enabled", + "telegram_send_enabled", + "direct_bot_api_allowed", + "queue_write_count_24h", + "readback_status" + ], + "properties": { + "readback_id": { + "enum": [ + "daily_report_digest_readback", + "weekly_report_digest_readback", + "monthly_report_digest_readback" + ] + }, + "display_name": { "type": "string" }, + "cadence": { "enum": ["daily", "weekly", "monthly"] }, + "owner_agent": { "const": "hermes" }, + "recipient_room": { "const": "AwoooI SRE 戰情室" }, + "secret_ref": { "const": "SRE_GROUP_CHAT_ID" }, + "preview_hash": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" }, + "payload_redacted": { "const": true }, + "gateway_queue_write_enabled": { "const": false }, + "telegram_send_enabled": { "const": false }, + "direct_bot_api_allowed": { "const": false }, + "queue_write_count_24h": { "const": 0 }, + "readback_status": { "const": "verified_redacted_preview" } + }, + "additionalProperties": false + } + }, + "verifier_dry_run_cases": { + "type": "array", + "minItems": 4, + "items": { + "type": "object", + "required": [ + "case_id", + "display_name", + "owner_agent", + "dry_run_status", + "expected_signal", + "observed_signal", + "evidence_hash", + "live_readback_enabled", + "writes_result", + "requires_secret_value" + ], + "properties": { + "case_id": { + "enum": [ + "report_snapshot_verifier_dry_run", + "gateway_preview_verifier_dry_run", + "receipt_redaction_verifier_dry_run", + "medium_low_noop_verifier_dry_run" + ] + }, + "display_name": { "type": "string" }, + "owner_agent": { "enum": ["hermes", "nemotron"] }, + "dry_run_status": { + "enum": ["passed_fixture", "ready_for_owner_review", "blocked_by_runtime_gate"] + }, + "expected_signal": { "type": "string" }, + "observed_signal": { "type": "string" }, + "evidence_hash": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" }, + "live_readback_enabled": { "const": false }, + "writes_result": { "const": false }, + "requires_secret_value": { "const": false } + }, + "additionalProperties": false + } + }, + "agent_fixture_roles": { + "type": "array", + "minItems": 3, + "items": { + "type": "object", + "required": [ + "agent_id", + "display_name", + "fixture_responsibility", + "observed_work", + "blocked_now", + "live_action_count_24h" + ], + "properties": { + "agent_id": { "enum": ["openclaw", "hermes", "nemotron"] }, + "display_name": { "type": "string" }, + "fixture_responsibility": { "type": "string" }, + "observed_work": { "type": "array", "items": { "type": "string" }, "minItems": 1 }, + "blocked_now": { "type": "array", "items": { "type": "string" }, "minItems": 1 }, + "live_action_count_24h": { "const": 0 } + }, + "additionalProperties": false + } + }, + "operator_checkpoints": { + "type": "array", + "minItems": 5, + "items": { + "type": "object", + "required": [ + "checkpoint_id", + "display_name", + "owner_agent", + "risk_tier", + "approval_required", + "status", + "next_safe_step" + ], + "properties": { + "checkpoint_id": { "type": "string" }, + "display_name": { "type": "string" }, + "owner_agent": { "enum": ["openclaw", "hermes", "nemotron"] }, + "risk_tier": { "enum": ["low", "medium", "high", "critical"] }, + "approval_required": { "type": "boolean" }, + "status": { + "enum": [ + "passed_no_write", + "ready_for_owner_review", + "blocked_by_runtime_gate" + ] + }, + "next_safe_step": { "type": "string" } + }, + "additionalProperties": false + } + }, + "display_redaction_contract": { + "type": "object", + "required": [ + "redaction_required", + "raw_report_payload_display_allowed", + "raw_telegram_payload_display_allowed", + "private_reasoning_display_allowed", + "secret_value_display_allowed", + "work_window_transcript_display_allowed", + "allowed_display_fields", + "blocked_display_fields" + ], + "properties": { + "redaction_required": { "const": true }, + "raw_report_payload_display_allowed": { "const": false }, + "raw_telegram_payload_display_allowed": { "const": false }, + "private_reasoning_display_allowed": { "const": false }, + "secret_value_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": [ + "fixture_smoke_count", + "passed_fixture_smoke_count", + "queue_preview_readback_count", + "verifier_dry_run_case_count", + "agent_role_count", + "operator_checkpoint_count", + "approval_required_checkpoint_ids", + "live_report_delivery_count", + "telegram_gateway_queue_write_count", + "telegram_send_count", + "telegram_bot_api_call_count", + "delivery_receipt_write_count", + "ai_runtime_worker_run_count", + "medium_low_auto_execution_count", + "post_action_verifier_live_readback_count", + "production_write_count" + ], + "properties": { + "fixture_smoke_count": { "type": "integer" }, + "passed_fixture_smoke_count": { "type": "integer" }, + "queue_preview_readback_count": { "type": "integer" }, + "verifier_dry_run_case_count": { "type": "integer" }, + "agent_role_count": { "type": "integer" }, + "operator_checkpoint_count": { "type": "integer" }, + "approval_required_checkpoint_ids": { "type": "array", "items": { "type": "string" } }, + "live_report_delivery_count": { "const": 0 }, + "telegram_gateway_queue_write_count": { "const": 0 }, + "telegram_send_count": { "const": 0 }, + "telegram_bot_api_call_count": { "const": 0 }, + "delivery_receipt_write_count": { "const": 0 }, + "ai_runtime_worker_run_count": { "const": 0 }, + "medium_low_auto_execution_count": { "const": 0 }, + "post_action_verifier_live_readback_count": { "const": 0 }, + "production_write_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 ae16adbe7..921f1161a 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,8 +634,9 @@ 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 互動、接手、學習、成長、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 證據面;目前 live session、message、handoff、learning write、Gateway queue、Telegram send、report delivery、auto optimization、verifier execution 全部 `0`,由 P2-403M dry-run package 承接下一步 | -| `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 | +| `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 互動、接手、學習、成長、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 證據面;目前 live session、message、handoff、learning write、Gateway queue、Telegram send、report delivery、auto optimization、verifier execution 全部 `0`,由 P2-404 runtime worker shadow gate 承接下一步 | +| `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_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 主動營運委派與版本生命週期契約 @@ -722,7 +723,8 @@ Repo / registry / release notes / K8s / host / observability / backup evidence 16. 建立 runtime verifier evidence implementation review,固定 implementation 前的 evidence checks、redaction review、rollback template、failure receipt template、NemoTron replay fixture 與人工操作選項。✅ P2-403I 已完成;verifier implementation、canonical readback、rollback work item、Telegram failure receipt、learning writeback 與 verifier execution 仍為 `0 / false`。 17. 建立報表真相、日報、週報、月報、Agent 工作量、圖表化報告、AI 分析建議與高 / 中 / 低風險自動化 policy review。✅ P2-403J 已完成;report delivery、Telegram queue、AI analysis runtime、中低風險 auto worker、生產優化與 route change 仍為 `0 / false`。 18. 建立報表派送、Telegram Gateway queue、讀報回執、AI 讀報後分析、中低風險自動處理、高風險審核與 post-action verifier 啟動前閘門。✅ P2-403L 已完成;live delivery、Gateway queue write、AI runtime worker、中低風險 auto worker、高風險自動執行與 production optimization 仍為 `0 / false`。 -19. 建立報表 runtime no-write dry-run、SRE 戰情室 Gateway queue 草案與 readback verifier 草案。✅ P2-403M 已完成;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-403N fixture smoke / queue preview readback / verifier dry-run。 +19. 建立報表 runtime no-write dry-run、SRE 戰情室 Gateway queue 草案與 readback verifier 草案。✅ P2-403M 已完成;Gateway queue write、Telegram send、Bot API、delivery receipt、AI runtime worker、中低風險 auto worker、verifier live readback、production write 與 secret value read 仍為 `0 / false`。 +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`。下一步 P2-404 runtime worker shadow / no-write execution evidence gate。 #### 3.2.1d 2026-06-11 Agent 互動、學習與成長證據面 @@ -750,6 +752,7 @@ Repo / registry / release notes / K8s / host / observability / backup evidence | `docs/evaluations/ai_agent_report_automation_review_2026-06-12.json` + `GET /api/v1/agents/agent-report-automation-review` | P2-403J 日報 / 週報 / 月報、每個 Agent 工作量、圖表化報告、AI 分析建議與高 / 中 / 低風險自動化 policy review;高風險需人工審核,中低風險目前只定義 policy,不啟動 runtime auto worker | | `docs/evaluations/ai_agent_report_runtime_readiness_2026-06-12.json` + `GET /api/v1/agents/agent-report-runtime-readiness` | P2-403L 報表派送、Telegram Gateway queue、讀報回執、AI 讀報後分析、中低風險自動處理、高風險審核與 post-action verifier 啟動前閘門;不排程實發、不寫 Gateway queue、不啟動 runtime worker、不執行生產優化 | | `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 個 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 | +| `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 個 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 | | `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 仍需批准 | @@ -1889,6 +1892,13 @@ Phase 6 完成後 - 政策裁決:低 / 中風險可在 guard、dry-run、post-action verifier、rollback/no-op evidence 與 failure-only Telegram 草案都通過後自動處理;高 / 關鍵風險仍必須統帥或 owner 審核。 - 本波仍不排程實發報告、不寫 Telegram Gateway queue、不呼叫 Bot API、不啟動 AI runtime worker、不啟動中低風險 auto worker、不執行生產優化、不讀 secret、不回傳工作視窗對話內容;下一步 P2-403M 才進 no-write dry-run / SRE 戰情室 Gateway queue 草案 / readback verifier。 +### 2026-06-12 13:40 (台北) — §3.2 / §5 — 完成 P2-403N fixture readback 證據包 — 把 dry-run 草案轉成可審查 hash / readback / verifier dry-run + +- 新增 `ai_agent_report_runtime_fixture_readback_v1` schema / committed snapshot / loader / API / 測試,定義 report_run snapshot fixture、Telegram digest payload fixture、queue preview redaction fixture、receipt redaction fixture、中低風險 no-op verifier fixture。 +- `apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx` 接入 `GET /api/v1/agents/agent-report-runtime-fixture-readback`,治理頁顯示 5 個 fixture smoke、3 個 SRE 戰情室 queue preview readback、4 個 verifier dry-run case、OpenClaw / Hermes / NemoTron fixture 分工與 5 個 operator checkpoint。 +- 政策裁決:P2-403N 只允許 redacted hash、queue preview readback 與 verifier dry-run;任何 Gateway queue write、Telegram send、Bot API、delivery receipt、AI runtime worker、中低風險 auto worker、verifier live readback、production write 或 secret value read 都仍為 `0 / false`。 +- 本波仍不送 Telegram、不寫 Gateway queue、不呼叫 Bot API、不寫 delivery receipt、不啟動 runtime worker、不跑 verifier live readback、不讀 secret、不回傳工作視窗對話內容;下一步 P2-404 才進 runtime worker shadow / no-write execution evidence gate。 + ### 2026-06-12 11:55 (台北) — §3.2 / §5 — 完成 P2-403M 報表 runtime no-write dry-run 證據包 — 把 queue / verifier 草案固定成可審核證據 - 新增 `ai_agent_report_runtime_dry_run_v1` schema / committed snapshot / loader / API / 測試,定義 report_run snapshot preview、Telegram digest payload preview、AI post-report analysis packet、中低風險 no-op plan、post-action verifier readback plan。