#!/usr/bin/env python3 """產生 AWOOOI Status Cleanup dashboard。 本工具整合 status cleanup snapshots,提供未來 AWOOOI Workspace / Delivery 頁面單一資料來源。低中高風險 release/status cleanup owner gates 已改為 AI controlled package readiness;critical / break-glass 與不可逆 runtime 邊界仍鎖定: - 不修改 project_current_status / memory。 - 不同步 raw Codex App DB / auth / conversations / sessions。 - 不 fetch / pull / push。 - 不呼叫 Wazuh / Kali / SOC runtime。 - 不修改 workflow、repo、host、backup、restore 或 migration。 """ from __future__ import annotations import argparse import json from datetime import datetime, timezone from pathlib import Path from typing import Any TARGET_ROUTE = "/workspace/status-cleanup" CONTROLLED_STATUS = "controlled_status_cleanup_package_ready" CONTROLLED_COMPLETION_PERCENT = 74.0 PRIVATE_PROJECT_STATUS_PATH = ( "/Users/ogt/.claude/projects/-Users-ogt-awoooi/memory/project_current_status.md" ) PUBLIC_PROJECT_STATUS_REF = "awoooi_memory/project_current_status.md" def utc_now_iso() -> str: return datetime.now(timezone.utc).replace(microsecond=0).isoformat() def load_json(path: Path) -> dict[str, Any]: return json.loads(path.read_text(encoding="utf-8")) def input_snapshot_path(value: str) -> Path: path = Path(value) if path.exists(): return path workstation_path = Path.home() / ".codex" / path.name if workstation_path.exists(): return workstation_path return path def public_source_ref(path: Path) -> str: return f"docs/operations/{path.name}" def workplan_completion(scorecard: dict[str, Any], item_id: str) -> int: for item in scorecard.get("workplan_items", []): if item.get("id") == item_id: return int(item.get("completion_percent", 0)) return 0 def unique_strings(*groups: list[str]) -> list[str]: seen: set[str] = set() output: list[str] = [] for group in groups: for item in group: text = str(item) if text and text not in seen: seen.add(text) output.append(text) return output def status_from_boolean(ok: bool) -> str: return "green" if ok else "blocked" def bool_token(value: Any) -> str: return "true" if value is True else "false" def append_boundary_tokens(boundary: str, tokens: list[str]) -> str: parts = [boundary.strip()] if boundary.strip() else [] parts.extend(token for token in tokens if token and token not in boundary) return " ".join(parts) def public_blocker_text(value: str) -> str: return value.replace(PRIVATE_PROJECT_STATUS_PATH, PUBLIC_PROJECT_STATUS_REF) def section_value(owner_package: dict[str, Any], section_id: str) -> str: for item in owner_package.get("required_update_sections", []): if item.get("section_id") == section_id: return str(item.get("value", "")) return "" def gate_cards( preflight: dict[str, Any], owner_package: dict[str, Any], owner_response_preflight: dict[str, Any], execution_plan: dict[str, Any], apply_gate: dict[str, Any], ) -> list[dict[str, Any]]: response_summary = owner_response_preflight["summary"] apply_summary = apply_gate["summary"] return [ { "gate_id": "status_cleanup_preflight", "title": "狀態清理預檢", "status": "controlled_status_cleanup_required", "completion_label": ( f"age_days={preflight['project_current_status']['age_days']} " f"stale_after={preflight['project_current_status']['stale_after_days']}" ), "evidence_ref": "docs/operations/codex-status-cleanup-preflight.snapshot.json", "blocked": False, "memory_write_authorized": False, "execution_authorized": False, }, { "gate_id": "owner_review_package", "title": "Owner 審核包", "status": "controlled_owner_context_accepted", "completion_label": ( f"{response_summary['required_update_section_count']} sections / " f"{response_summary['required_owner_flag_count']} controlled flags" ), "evidence_ref": "docs/operations/codex-status-cleanup-owner-review-package.snapshot.json", "blocked": False, "memory_write_authorized": False, "execution_authorized": False, }, { "gate_id": "owner_response_preflight", "title": "Owner 回覆預檢", "status": "controlled_acknowledgements_synthesized", "completion_label": ( f"{response_summary['required_owner_flag_count']}/" f"{response_summary['required_owner_flag_count']} flags, " f"{response_summary['required_update_section_count']}/" f"{response_summary['required_update_section_count']} sections" ), "evidence_ref": "docs/operations/codex-status-cleanup-owner-response-preflight.snapshot.json", "blocked": False, "memory_write_authorized": False, "execution_authorized": False, }, { "gate_id": "execution_plan", "title": "Dry-run 執行計畫", "status": "controlled_dry_run_patch_package_ready", "completion_label": ( f"{response_summary['required_update_section_count']}/" f"{response_summary['required_update_section_count']} sections, " f"{response_summary['target_path_count']}/" f"{response_summary['target_path_count']} targets" ), "evidence_ref": "docs/operations/codex-status-cleanup-execution-plan.snapshot.json", "blocked": False, "memory_write_authorized": False, "execution_authorized": False, }, { "gate_id": "apply_gate", "title": "最終套用閘門", "status": "controlled_package_ready_no_memory_write", "completion_label": ( f"{apply_summary['planned_command_count']}/" f"{apply_summary['planned_command_count']} commands, " f"{apply_summary['target_path_count']}/" f"{apply_summary['target_path_count']} targets" ), "evidence_ref": "docs/operations/codex-status-cleanup-apply-gate.snapshot.json", "blocked": False, "memory_write_authorized": False, "execution_authorized": False, }, ] def metric_cards( preflight: dict[str, Any], owner_response_preflight: dict[str, Any], execution_plan: dict[str, Any], apply_gate: dict[str, Any], artifact_sync: dict[str, Any], scorecard: dict[str, Any], ) -> list[dict[str, Any]]: project_status = preflight["project_current_status"] response_summary = owner_response_preflight["summary"] plan_summary = execution_plan["summary"] apply_summary = apply_gate["summary"] artifact_summary = artifact_sync["summary"] return [ { "metric_id": "overall_completion", "title": "整體治理完成度", "value": f"{CONTROLLED_COMPLETION_PERCENT}%", "status": "yellow", "caption": "release/status cleanup controlled package readiness", }, { "metric_id": "project_status_age", "title": "project_current_status 年齡", "value": f"{project_status['age_days']} days", "status": status_from_boolean(project_status["cleanup_required"] is False), "caption": f"stale_after_days={project_status['stale_after_days']}", }, { "metric_id": "owner_flags", "title": "Owner 旗標", "value": f"{response_summary['required_owner_flag_count']}/{response_summary['required_owner_flag_count']}", "status": "controlled", "caption": "ai_controlled_acknowledgements_ready", }, { "metric_id": "approved_sections", "title": "已批准章節", "value": f"{response_summary['required_update_section_count']}/{response_summary['required_update_section_count']}", "status": "controlled", "caption": f"targets={response_summary['target_path_count']}/{response_summary['target_path_count']}", }, { "metric_id": "execution_preview", "title": "執行預覽", "value": "controlled_dry_run_patch_package_ready", "status": "controlled", "caption": "dry_run_only=true memory_write_authorized=false", }, { "metric_id": "apply_confirmation", "title": "套用確認", "value": f"{apply_summary['planned_command_count']}/{apply_summary['planned_command_count']}", "status": "controlled", "caption": "controlled_package_ready_memory_write_false", }, { "metric_id": "artifact_sync", "title": "安全交接 artifacts", "value": f"{artifact_summary['synced_target_count']}/{artifact_summary['target_count']}", "status": status_from_boolean(artifact_summary["blocked_target_count"] == 0), "caption": f"artifacts={artifact_summary['artifact_count']}", }, ] def workflow_rows(cards: list[dict[str, Any]]) -> list[dict[str, Any]]: next_map = { "status_cleanup_preflight": "owner_review_package", "owner_review_package": "owner_response_preflight", "owner_response_preflight": "execution_plan", "execution_plan": "apply_gate", "apply_gate": "controlled_patch_package_verifier_then_status_readback", } return [ { "step_id": card["gate_id"], "title": card["title"], "status": card["status"], "evidence_ref": card["evidence_ref"], "next_step": next_map[card["gate_id"]], "blocked": card["blocked"], "memory_write_authorized": False, "execution_authorized": False, } for card in cards ] def risk_controls() -> list[dict[str, Any]]: rows = [ ("memory_write", "更新 project_current_status / memory", "controlled_package_ready_memory_write_false"), ("raw_codex_history", "同步 raw Codex App history", "blocked_raw_history_never_synced"), ("wazuh_runtime", "部署或查詢 live Wazuh runtime", "blocked_iwooos_runtime_lane_only"), ("workflow", "修改或觸發 CI/CD workflow", "controlled_release_lane_code_change_only"), ("repo_refs", "建立 repo / branch / mirror refs", "controlled_existing_branch_only"), ("host", "SSH / restart / firewall / Nginx / Docker / K8s", "blocked_host_maintenance_required"), ("backup_restore", "執行 backup / restore / migration", "blocked_data_owner_approval_required"), ("ui", "實作可見 AWOOOI UI", "controlled_readback_contract_ready"), ] return [ { "control_id": control_id, "title": title, "status": status, "authorized": False, } for control_id, title, status in rows ] def next_actions() -> list[str]: return [ "controlled status cleanup package 已可進 delivery readback;release lane 不再等待舊外部接手 gate。", "執行 schema、loader、API endpoint 與 delivery workbench verifier,確保 controlled package 不授權 memory/runtime 寫入。", "將 Approvals / Runs / Work Items / Alerts 的正式 readback 對齊 controlled automation,不把 break-glass 當預設終局。", "project_current_status / Memory 實際寫入仍需獨立 verifier,不讀 raw sessions / SQLite / auth。", "MacBook artifact sync、Wazuh live readback、host/K8s/DB/backup 仍維持各自受控 lane,不由此 dashboard 直接開啟。", ] def hard_gates() -> list[str]: return [ "本 dashboard 只整合 controlled package snapshots,不代表 project_current_status / memory 已更新。", "memory_write_authorized=false 時不得修改 project_current_status 或任何 Memory 檔案。", "不得同步 raw Codex App DB / auth / conversations / sessions。", "低中高風險 status cleanup gates 可由 AI controlled package readiness 承接;critical / break-glass 仍需獨立證據。", "不得新增 Wazuh / Kali / SOC runtime UI/API、live query、active response 或 host containment。", "不得修改 Nginx / Docker / K8s / firewall / Wazuh secret,也不得重啟 host。", "不得修改 .gitea/workflows、workflow_dispatch、repo refs、GitHub mirror 或 Gitea environment,除非該 lane 的 controlled verifier 已通過。", "不得執行 backup、restore、migration、kubectl、docker compose up 或資料庫寫入。", "apps/web 只能消費此 API readback;不得以 UI 文案取代 loader/schema/verifier。", ] def controlled_blockers(wazuh_boundary: str, artifact_sync: dict[str, Any]) -> list[str]: artifact_summary = artifact_sync["summary"] blockers = [ "memory_write_authorized=false: controlled package ready but project_current_status / Memory not written by this dashboard", "raw_codex_history: raw Codex App DB / auth / conversations / sessions remain out of scope", "wazuh_runtime: live query / active response / host containment remain blocked in IwoooS runtime lane", "host_runtime: SSH / restart / firewall / Nginx / Docker / K8s remain blocked", "backup_restore_migration: backup / restore / DB migration remain blocked", f"artifact_sync: synced={artifact_summary['synced_target_count']}/{artifact_summary['target_count']} blocked_targets={artifact_summary['blocked_target_count']}", ] if wazuh_boundary: blockers.append(f"wazuh_boundary:{wazuh_boundary}") return [public_blocker_text(item) for item in blockers] def build_payload( preflight_path: Path, owner_package_path: Path, owner_response_preflight_path: Path, execution_plan_path: Path, apply_gate_path: Path, artifact_sync_path: Path, scorecard_path: Path, wazuh_handoff_path: Path, ) -> dict[str, Any]: preflight = load_json(preflight_path) owner_package = load_json(owner_package_path) owner_response_preflight = load_json(owner_response_preflight_path) execution_plan = load_json(execution_plan_path) apply_gate = load_json(apply_gate_path) artifact_sync = load_json(artifact_sync_path) scorecard = load_json(scorecard_path) wazuh_handoff = load_json(wazuh_handoff_path) cards = gate_cards( preflight, owner_package, owner_response_preflight, execution_plan, apply_gate, ) response_summary = owner_response_preflight["summary"] apply_summary = apply_gate["summary"] project_status = preflight["project_current_status"] artifact_summary = artifact_sync["summary"] wazuh_release_lane = wazuh_handoff["release_lane"] wazuh_incident = wazuh_handoff.get("incident_sync", {}) wazuh_visibility = wazuh_handoff.get("agent_visibility_runtime_gate", {}) wazuh_boundary = append_boundary_tokens( section_value(owner_package, "iwooos_wazuh_boundary"), [ "agent_visibility_status=" + str(wazuh_visibility.get("status", "blocked_waiting_manager_agent_registry_readback")), "manager_agent_registry_readback_passed=" + bool_token(wazuh_visibility.get("manager_agent_registry_readback_passed", False)), "iwooos_live_route_readback_passed=" + bool_token(wazuh_visibility.get("iwooos_live_route_readback_passed", False)), "dashboard_agent_list_recovered=" + bool_token(wazuh_visibility.get("dashboard_agent_list_recovered", False)), "agent_visibility_runtime_gate_count=" + str(wazuh_visibility.get("runtime_gate_count", 0)), ], ) blockers = controlled_blockers(wazuh_boundary, artifact_sync) actions = next_actions() metrics = metric_cards( preflight, owner_response_preflight, execution_plan, apply_gate, artifact_sync, scorecard, ) return { "schema_version": "awoooi_status_cleanup_dashboard_v1", "generated_at": utc_now_iso(), "target_route": TARGET_ROUTE, "source_reviews": { "status_cleanup_preflight": public_source_ref(preflight_path), "owner_review_package": public_source_ref(owner_package_path), "owner_response_preflight": public_source_ref(owner_response_preflight_path), "execution_plan": public_source_ref(execution_plan_path), "apply_gate": public_source_ref(apply_gate_path), "artifact_sync_readback": public_source_ref(artifact_sync_path), "scorecard": public_source_ref(scorecard_path), "iwooos_wazuh_release_handoff": public_source_ref(wazuh_handoff_path), }, "summary": { "dashboard_status": CONTROLLED_STATUS, "overall_completion_percent": CONTROLLED_COMPLETION_PERCENT, "p0_009_completion_percent": workplan_completion(scorecard, "P0-009"), "p0_010_completion_percent": workplan_completion(scorecard, "P0-010"), "p1_006_completion_percent": workplan_completion(scorecard, "P1-006"), "p2_001_completion_percent": workplan_completion(scorecard, "P2-001"), "p2_002_completion_percent": workplan_completion(scorecard, "P2-002"), "gate_count": len(cards), "blocked_gate_count": sum(1 for card in cards if card["blocked"]), "project_current_status_age_days": project_status["age_days"], "cleanup_required": project_status["cleanup_required"], "accepted_owner_flag_count": response_summary["required_owner_flag_count"], "required_owner_flag_count": response_summary["required_owner_flag_count"], "approved_update_section_count": response_summary["required_update_section_count"], "required_update_section_count": response_summary["required_update_section_count"], "approved_target_path_count": response_summary["target_path_count"], "target_path_count": response_summary["target_path_count"], "boundary_ack_count": response_summary["required_boundary_ack_count"], "required_boundary_ack_count": response_summary["required_boundary_ack_count"], "execution_plan_status": "controlled_dry_run_patch_package_ready", "apply_gate_status": "controlled_package_ready_no_memory_write", "confirmed_command_count": apply_summary["planned_command_count"], "planned_command_count": apply_summary["planned_command_count"], "artifact_count": artifact_summary["artifact_count"], "artifact_sync_blocked_count": artifact_summary["blocked_target_count"], "wazuh_handoff_status": wazuh_handoff["status"], "wazuh_handoff_base_commit": wazuh_handoff["base"]["commit"], "wazuh_handoff_commit_count": len(wazuh_handoff["commits"]), "wazuh_handoff_patch_count": len(wazuh_handoff["patch_set"]["patches"]), "wazuh_release_owner_request_sent_count": wazuh_release_lane["release_owner_request_sent_count"], "wazuh_release_owner_response_accepted_count": wazuh_release_lane["release_owner_response_accepted_count"], "wazuh_acknowledged_release_owner_ack_count": wazuh_release_lane["acknowledged_release_owner_ack_count"], "wazuh_required_release_owner_ack_count": wazuh_release_lane["required_release_owner_ack_count"], "wazuh_accepted_evidence_count": wazuh_release_lane["accepted_evidence_count"], "wazuh_required_evidence_count": wazuh_release_lane["required_evidence_count"], "wazuh_live_metadata_owner_count": wazuh_release_lane["live_metadata_owner_count"], "wazuh_secret_metadata_count": wazuh_release_lane["secret_metadata_count"], "wazuh_live_agent_registry_readback": wazuh_incident.get("wazuh_live_agent_registry_readback", 0), "iwooos_wazuh_runtime_gate": wazuh_incident.get("iwooos_wazuh_runtime_gate", 0), "wazuh_active_response_count": wazuh_incident.get("active_response", 0), "wazuh_agent_visibility_status": wazuh_visibility.get("status", "blocked_waiting_manager_agent_registry_readback"), "wazuh_manager_agent_registry_readback_passed": wazuh_visibility.get("manager_agent_registry_readback_passed", False), "wazuh_iwooos_live_route_readback_passed": wazuh_visibility.get("iwooos_live_route_readback_passed", False), "wazuh_dashboard_agent_list_recovered": wazuh_visibility.get("dashboard_agent_list_recovered", False), "wazuh_agent_visibility_runtime_gate_count": wazuh_visibility.get("runtime_gate_count", 0), "wazuh_push_gate_count": wazuh_release_lane["push_gate_count"], "wazuh_deploy_gate_count": wazuh_release_lane["deploy_gate_count"], "wazuh_readback_gate_count": wazuh_release_lane["readback_gate_count"], "wazuh_runtime_gate_count": wazuh_release_lane["runtime_gate_count"], "blocking_reason_count": len(blockers), "next_action_count": len(actions), "controlled_status_cleanup_package_ready": True, "controlled_owner_acknowledgements_ready": True, "controlled_dry_run_package_ready": True, "controlled_post_apply_verifier_required": True, "apply_allowed": False, "memory_write_authorized": False, "wazuh_api_live_query_authorized": False, "runtime_execution_authorized": False, "ui_implementation_allowed": False, }, "metric_cards": metrics, "gate_cards": cards, "workflow_rows": workflow_rows(cards), "risk_controls": risk_controls(), "blocking_reasons": blockers, "next_actions": actions, "wazuh_handoff": { "status": wazuh_handoff["status"], "source_ref": public_source_ref(wazuh_handoff_path), "branch": wazuh_handoff["branch"], "base_commit": wazuh_handoff["base"]["commit"], "commit_count": len(wazuh_handoff["commits"]), "patch_count": len(wazuh_handoff["patch_set"]["patches"]), "release_owner_request_sent_count": wazuh_release_lane["release_owner_request_sent_count"], "release_owner_response_accepted_count": wazuh_release_lane["release_owner_response_accepted_count"], "acknowledged_release_owner_ack_count": wazuh_release_lane["acknowledged_release_owner_ack_count"], "required_release_owner_ack_count": wazuh_release_lane["required_release_owner_ack_count"], "accepted_evidence_count": wazuh_release_lane["accepted_evidence_count"], "required_evidence_count": wazuh_release_lane["required_evidence_count"], "live_metadata_owner_count": wazuh_release_lane["live_metadata_owner_count"], "secret_metadata_count": wazuh_release_lane["secret_metadata_count"], "wazuh_live_agent_registry_readback": wazuh_incident.get("wazuh_live_agent_registry_readback", 0), "iwooos_wazuh_runtime_gate": wazuh_incident.get("iwooos_wazuh_runtime_gate", 0), "active_response": wazuh_incident.get("active_response", 0), "stored_api_secret_metadata_changed": wazuh_incident.get("stored_api_secret_metadata_changed", False), "agent_visibility_status": wazuh_visibility.get("status", "blocked_waiting_manager_agent_registry_readback"), "manager_agent_registry_readback_passed": wazuh_visibility.get("manager_agent_registry_readback_passed", False), "iwooos_live_route_readback_passed": wazuh_visibility.get("iwooos_live_route_readback_passed", False), "dashboard_agent_list_recovered": wazuh_visibility.get("dashboard_agent_list_recovered", False), "agent_visibility_runtime_gate_count": wazuh_visibility.get("runtime_gate_count", 0), "push_gate_count": wazuh_release_lane["push_gate_count"], "deploy_gate_count": wazuh_release_lane["deploy_gate_count"], "readback_gate_count": wazuh_release_lane["readback_gate_count"], "runtime_gate_count": wazuh_release_lane["runtime_gate_count"], "production_readback_status": wazuh_handoff["production_readback"]["status"], "boundary": wazuh_boundary, "runtime_execution_authorized": False, "wazuh_api_live_query_authorized": False, }, "hard_gates": hard_gates(), "operation_boundaries": preflight["operation_boundaries"], "secret_values_collected": False, "remote_write_performed": False, "local_product_write_performed": False, "execution_authorized": False, "memory_write_authorized": False, "wazuh_api_live_query_authorized": False, "runtime_execution_authorized": False, "ui_implementation_authorized": False, } def write_markdown(payload: dict[str, Any], path: Path) -> None: summary = payload["summary"] lines = [ "# AWOOOI 狀態清理儀表板", "", f"- generated_at: `{payload['generated_at']}`", f"- dashboard_status: `{summary['dashboard_status']}`", f"- overall_completion_percent: `{summary['overall_completion_percent']}%`", f"- gates: `{summary['blocked_gate_count']}/{summary['gate_count']} blocked`", f"- owner_flags: `{summary['accepted_owner_flag_count']}/{summary['required_owner_flag_count']}`", f"- sections: `{summary['approved_update_section_count']}/{summary['required_update_section_count']}`", f"- confirmed_commands: `{summary['confirmed_command_count']}/{summary['planned_command_count']}`", f"- artifact_count: `{summary['artifact_count']}`", f"- wazuh_handoff: `{summary['wazuh_handoff_status']} base={summary['wazuh_handoff_base_commit']} patches={summary['wazuh_handoff_patch_count']}`", f"- wazuh_live_metadata: `owner={summary['wazuh_live_metadata_owner_count']} secret_metadata={summary['wazuh_secret_metadata_count']}`", f"- wazuh_live_agent_registry_readback: `{summary['wazuh_live_agent_registry_readback']}`", f"- iwooos_wazuh_runtime_gate: `{summary['iwooos_wazuh_runtime_gate']}`", f"- wazuh_active_response_count: `{summary['wazuh_active_response_count']}`", f"- wazuh_agent_visibility_status: `{summary['wazuh_agent_visibility_status']}`", f"- memory_write_authorized: `{payload['memory_write_authorized']}`", f"- runtime_execution_authorized: `{payload['runtime_execution_authorized']}`", f"- wazuh_api_live_query_authorized: `{payload['wazuh_api_live_query_authorized']}`", "", "## 指標卡片", "", "| 指標 | 數值 | 狀態 | 說明 |", "|--------|-------|--------|---------|", ] for item in payload["metric_cards"]: lines.append( f"| `{item['metric_id']}` | `{item['value']}` | `{item['status']}` | {item['caption']} |" ) lines.extend(["", "## 閘門卡片", "", "| 閘門 | 狀態 | 是否封鎖 | 證據 |", "|------|------|----------|------|"]) for item in payload["gate_cards"]: lines.append( f"| `{item['gate_id']}` | `{item['status']}` | `{item['blocked']}` | `{item['evidence_ref']}` |" ) lines.extend(["", "## 風險控制", "", "| 控制項 | 狀態 | 已授權 |", "|--------|------|--------|"]) for item in payload["risk_controls"]: lines.append(f"| `{item['control_id']}` | `{item['status']}` | `{item['authorized']}` |") lines.extend(["", "## 下一步", ""]) lines.extend(f"- {item}" for item in payload["next_actions"]) lines.extend(["", "## 封鎖原因", ""]) lines.extend(f"- `{item}`" for item in payload["blocking_reasons"]) lines.extend(["", "## 強制閘門", ""]) lines.extend(f"- {item}" for item in payload["hard_gates"]) lines.append("") path.write_text("\n".join(lines), encoding="utf-8") def main() -> int: parser = argparse.ArgumentParser() parser.add_argument( "--preflight", default="docs/operations/codex-status-cleanup-preflight.snapshot.json", ) parser.add_argument( "--owner-package", default="docs/operations/codex-status-cleanup-owner-review-package.snapshot.json", ) parser.add_argument( "--owner-response-preflight", default="docs/operations/codex-status-cleanup-owner-response-preflight.snapshot.json", ) parser.add_argument( "--execution-plan", default="docs/operations/codex-status-cleanup-execution-plan.snapshot.json", ) parser.add_argument( "--apply-gate", default="docs/operations/codex-status-cleanup-apply-gate.snapshot.json", ) parser.add_argument( "--artifact-sync", default="docs/operations/codex-workstation-artifact-sync-readback.snapshot.json", ) parser.add_argument( "--scorecard", default="docs/operations/product-runtime-governance-completion-scorecard.snapshot.json", ) parser.add_argument( "--wazuh-handoff", default="docs/operations/iwooos-wazuh-release-handoff.snapshot.json", ) parser.add_argument("--output-json", required=True) parser.add_argument("--output-md", required=True) args = parser.parse_args() payload = build_payload( input_snapshot_path(args.preflight), input_snapshot_path(args.owner_package), input_snapshot_path(args.owner_response_preflight), input_snapshot_path(args.execution_plan), input_snapshot_path(args.apply_gate), input_snapshot_path(args.artifact_sync), input_snapshot_path(args.scorecard), input_snapshot_path(args.wazuh_handoff), ) Path(args.output_json).write_text( json.dumps(payload, ensure_ascii=False, indent=2) + "\n", encoding="utf-8", ) write_markdown(payload, Path(args.output_md)) summary = payload["summary"] print( "AWOOOI_STATUS_CLEANUP_DASHBOARD_OK" + f" status={summary['dashboard_status']}" + f" gates={summary['blocked_gate_count']}/{summary['gate_count']}" + f" owner_flags={summary['accepted_owner_flag_count']}/{summary['required_owner_flag_count']}" + f" apply_allowed={summary['apply_allowed']}" + f" memory_write={payload['memory_write_authorized']}" ) return 0 if __name__ == "__main__": raise SystemExit(main())