#!/usr/bin/env python3
"""產生 AWOOOI Status Cleanup dashboard。

本工具只整合 status cleanup 的 read-only snapshots，提供未來 AWOOOI
Workspace / Delivery 頁面單一資料來源：
- 不修改 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"
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 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]]:
    preflight_status = preflight["status"]
    owner_summary = owner_package["summary"]
    response_summary = owner_response_preflight["summary"]
    plan_summary = execution_plan["summary"]
    apply_summary = apply_gate["summary"]

    return [
        {
            "gate_id": "status_cleanup_preflight",
            "title": "狀態清理預檢",
            "status": preflight_status,
            "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": preflight_status != "ready_status_current",
            "memory_write_authorized": False,
            "execution_authorized": False,
        },
        {
            "gate_id": "owner_review_package",
            "title": "Owner 審核包",
            "status": owner_summary["review_status"],
            "completion_label": (
                f"{owner_summary['required_update_section_count']} sections / "
                f"{owner_summary['required_owner_flag_count']} owner flags"
            ),
            "evidence_ref": "docs/operations/codex-status-cleanup-owner-review-package.snapshot.json",
            "blocked": owner_summary["ready_for_status_cleanup_apply_gate"] is not True,
            "memory_write_authorized": False,
            "execution_authorized": False,
        },
        {
            "gate_id": "owner_response_preflight",
            "title": "Owner 回覆預檢",
            "status": response_summary["preflight_status"],
            "completion_label": (
                f"{response_summary['accepted_owner_flag_count']}/"
                f"{response_summary['required_owner_flag_count']} flags, "
                f"{response_summary['approved_update_section_count']}/"
                f"{response_summary['required_update_section_count']} sections"
            ),
            "evidence_ref": "docs/operations/codex-status-cleanup-owner-response-preflight.snapshot.json",
            "blocked": response_summary["ready_for_status_cleanup_apply_gate"] is not True,
            "memory_write_authorized": False,
            "execution_authorized": False,
        },
        {
            "gate_id": "execution_plan",
            "title": "Dry-run 執行計畫",
            "status": plan_summary["execution_status"],
            "completion_label": (
                f"{plan_summary['approved_update_section_count']}/"
                f"{plan_summary['required_update_section_count']} sections, "
                f"{plan_summary['approved_target_path_count']}/"
                f"{plan_summary['target_path_count']} targets"
            ),
            "evidence_ref": "docs/operations/codex-status-cleanup-execution-plan.snapshot.json",
            "blocked": plan_summary["execution_status"] != "blocked_final_confirmation_required",
            "memory_write_authorized": False,
            "execution_authorized": False,
        },
        {
            "gate_id": "apply_gate",
            "title": "最終套用閘門",
            "status": apply_summary["apply_gate_status"],
            "completion_label": (
                f"{apply_summary['confirmed_command_count']}/"
                f"{apply_summary['planned_command_count']} commands, "
                f"{apply_summary['confirmed_target_path_count']}/"
                f"{apply_summary['target_path_count']} targets"
            ),
            "evidence_ref": "docs/operations/codex-status-cleanup-apply-gate.snapshot.json",
            "blocked": apply_summary["apply_allowed"] is not True,
            "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"{scorecard['overall_completion_percent']}%",
            "status": scorecard.get("status", "orange"),
            "caption": "產品 Runtime 治理完成度計分卡",
        },
        {
            "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['accepted_owner_flag_count']}/{response_summary['required_owner_flag_count']}",
            "status": status_from_boolean(response_summary["accepted_owner_flag_count"] == response_summary["required_owner_flag_count"]),
            "caption": response_summary["owner_response_status"],
        },
        {
            "metric_id": "approved_sections",
            "title": "已批准章節",
            "value": f"{response_summary['approved_update_section_count']}/{response_summary['required_update_section_count']}",
            "status": status_from_boolean(response_summary["approved_update_section_count"] == response_summary["required_update_section_count"]),
            "caption": f"targets={response_summary['approved_target_path_count']}/{response_summary['target_path_count']}",
        },
        {
            "metric_id": "execution_preview",
            "title": "執行預覽",
            "value": plan_summary["execution_status"],
            "status": status_from_boolean(plan_summary["preflight_ready"]),
            "caption": "dry_run_only=true",
        },
        {
            "metric_id": "apply_confirmation",
            "title": "套用確認",
            "value": f"{apply_summary['confirmed_command_count']}/{apply_summary['planned_command_count']}",
            "status": status_from_boolean(apply_summary["apply_allowed"]),
            "caption": apply_summary["final_confirmation_status"],
        },
        {
            "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": "manual_project_current_status_update_after_explicit_final_confirmation",
    }
    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", "blocked_final_apply_gate_required"),
        ("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", "blocked_workflow_authorization_required"),
        ("repo_refs", "建立 repo / branch / mirror refs", "blocked_source_control_approval_required"),
        ("host", "SSH / restart / firewall / Nginx / Docker / K8s", "blocked_host_maintenance_required"),
        ("backup_restore", "執行 backup / restore / migration", "blocked_data_owner_approval_required"),
        ("ui", "實作可見 AWOOOI UI", "blocked_apps_web_readiness_required"),
    ]
    return [
        {
            "control_id": control_id,
            "title": title,
            "status": status,
            "authorized": False,
        }
        for control_id, title, status in rows
    ]


def next_actions(owner_response_preflight: dict[str, Any], apply_gate: dict[str, Any]) -> list[str]:
    response_summary = owner_response_preflight["summary"]
    apply_summary = apply_gate["summary"]
    return [
        f"收齊 owner 旗標：{response_summary['accepted_owner_flag_count']}/{response_summary['required_owner_flag_count']}。",
        f"收齊已批准章節：{response_summary['approved_update_section_count']}/{response_summary['required_update_section_count']}。",
        f"確認目標路徑：{response_summary['approved_target_path_count']}/{response_summary['target_path_count']}。",
        f"確認邊界 acknowledgement：{response_summary['boundary_ack_count']}/{response_summary['required_boundary_ack_count']}。",
        "owner response preflight ready 後，重新產生 dry-run execution plan。",
        f"apply gate 目前 apply_allowed={apply_summary['apply_allowed']}；未變 true 前不得寫 project_current_status。",
    ]


def hard_gates() -> list[str]:
    return [
        "本 dashboard 只整合 read-only snapshots，不代表 project_current_status / memory 已更新。",
        "memory_write_authorized=false 時不得修改 project_current_status 或任何 Memory 檔案。",
        "不得同步 raw Codex App DB / auth / conversations / sessions。",
        "不得把一般批准繼續視為 owner response 或 final apply confirmation。",
        "不得新增 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。",
        "不得執行 backup、restore、migration、kubectl、docker compose up 或資料庫寫入。",
        "apps/web build/i18n 必要檔案未恢復前，本 dashboard 只可作 page model 資料，不代表 UI 實作授權。",
    ]


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"]
    plan_summary = execution_plan["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 = [
        public_blocker_text(item)
        for item in unique_strings(
            preflight.get("hard_gates", []),
            [
                f"owner_response_preflight:{item}"
                for item in owner_response_preflight.get("blocking_reasons", [])
            ],
            [
                f"execution_plan_blocked_until:{item}"
                for item in execution_plan.get("blocked_until", [])
            ],
            [f"apply_gate:{item}" for item in apply_gate.get("blocking_reasons", [])],
            [f"wazuh_boundary:{wazuh_boundary}"] if wazuh_boundary else [],
        )
    ]
    actions = next_actions(owner_response_preflight, apply_gate)
    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": str(preflight_path),
            "owner_review_package": str(owner_package_path),
            "owner_response_preflight": str(owner_response_preflight_path),
            "execution_plan": str(execution_plan_path),
            "apply_gate": str(apply_gate_path),
            "artifact_sync_readback": str(artifact_sync_path),
            "scorecard": str(scorecard_path),
            "iwooos_wazuh_release_handoff": str(wazuh_handoff_path),
        },
        "summary": {
            "dashboard_status": "blocked_status_cleanup_apply_not_authorized",
            "overall_completion_percent": scorecard["overall_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["accepted_owner_flag_count"],
            "required_owner_flag_count": response_summary["required_owner_flag_count"],
            "approved_update_section_count": response_summary["approved_update_section_count"],
            "required_update_section_count": response_summary["required_update_section_count"],
            "approved_target_path_count": response_summary["approved_target_path_count"],
            "target_path_count": response_summary["target_path_count"],
            "boundary_ack_count": response_summary["boundary_ack_count"],
            "required_boundary_ack_count": response_summary["required_boundary_ack_count"],
            "execution_plan_status": plan_summary["execution_status"],
            "apply_gate_status": apply_summary["apply_gate_status"],
            "confirmed_command_count": apply_summary["confirmed_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),
            "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": str(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(
        Path(args.preflight),
        Path(args.owner_package),
        Path(args.owner_response_preflight),
        Path(args.execution_plan),
        Path(args.apply_gate),
        Path(args.artifact_sync),
        Path(args.scorecard),
        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())
