Files
awoooi/scripts/dev/awoooi-status-cleanup-dashboard.py
Your Name 78105a64ca
Some checks failed
CD Pipeline / tests (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
Code Review / ai-code-review (push) Has been cancelled
Ansible / Reboot Recovery Contract / validate (push) Successful in 1m15s
fix(delivery): controlled status cleanup readiness
2026-06-28 09:53:47 +08:00

640 lines
30 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""產生 AWOOOI Status Cleanup dashboard。
本工具整合 status cleanup snapshots提供未來 AWOOOI Workspace / Delivery
頁面單一資料來源。低中高風險 release/status cleanup owner gates 已改為
AI controlled package readinesscritical / 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 readbackrelease 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())