#!/usr/bin/env python3
"""
IwoooS Backup / Restore / Escrow post-incident readback 只讀計畫產生器。

本工具讀取 Backup / Restore / Escrow owner response acceptance snapshot，
建立事故後回讀計畫：誰觸發或觀察到 backup / restore / offsite / escrow
異常、改前改後 freshness / restore / offsite / retention 狀態、是否有
no-false-green 與 rollback / stop condition。它不執行 backup、不 restore、
不 rclone / restic / Velero、不寫 escrow marker、不 SSH、不 kubectl、不讀
secret value、不保存 raw backup listing、不寫 production。
"""

from __future__ import annotations

import argparse
import json
import subprocess
import sys
from datetime import datetime, timedelta, timezone
from pathlib import Path
from typing import Any


TAIPEI = timezone(timedelta(hours=8))

READBACK_FIELDS = [
    "post_incident_readback_candidate_id",
    "source_acceptance_candidate_id",
    "request_id",
    "surface_id",
    "config_kind",
    "backup_scope",
    "control_tier",
    "write_capable_surface",
    "requires_live_evidence",
    "backup_incident_or_change_ref",
    "actor_attribution_ref",
    "change_or_outage_time_window_ref",
    "change_intent_or_break_glass_ref",
    "before_backup_freshness_state_ref",
    "after_backup_freshness_state_ref",
    "backup_status_readback_ref",
    "restore_drill_readback_ref",
    "restore_target_isolation_readback_ref",
    "offsite_sync_readback_ref",
    "offsite_remote_delete_guard_readback_ref",
    "credential_escrow_non_secret_readback_ref",
    "credential_recovery_drill_readback_ref",
    "retention_runway_readback_ref",
    "retention_or_prune_decision_ref",
    "backup_dependency_map_readback_ref",
    "data_classification_readback_ref",
    "restore_observer_stop_condition_ref",
    "backup_health_no_false_green_readback_ref",
    "alert_textfile_readback_ref",
    "cold_start_dr_scorecard_ref",
    "cross_project_sync_ref",
    "rollback_validation_ref",
    "post_change_monitoring_ref",
    "postcheck_readback_ref",
    "recurrence_guard_ref",
    "maintenance_window",
    "rollback_owner",
    "followup_owner",
    "redacted_evidence_refs",
    "reviewer_outcome",
    "no_secret_value_attestation",
    "no_raw_backup_payload_attestation",
    "no_production_restore_attestation",
    "no_false_green_attestation",
    "not_approval",
]

REQUIRED_READBACK_FIELDS = [
    "backup_incident_or_change_ref",
    "actor_attribution_ref",
    "change_or_outage_time_window_ref",
    "change_intent_or_break_glass_ref",
    "before_backup_freshness_state_ref",
    "after_backup_freshness_state_ref",
    "backup_status_readback_ref",
    "restore_drill_readback_ref",
    "restore_target_isolation_readback_ref",
    "offsite_sync_readback_ref",
    "offsite_remote_delete_guard_readback_ref",
    "credential_escrow_non_secret_readback_ref",
    "credential_recovery_drill_readback_ref",
    "retention_runway_readback_ref",
    "retention_or_prune_decision_ref",
    "backup_dependency_map_readback_ref",
    "data_classification_readback_ref",
    "restore_observer_stop_condition_ref",
    "backup_health_no_false_green_readback_ref",
    "alert_textfile_readback_ref",
    "cold_start_dr_scorecard_ref",
    "cross_project_sync_ref",
    "rollback_validation_ref",
    "post_change_monitoring_ref",
    "postcheck_readback_ref",
    "recurrence_guard_ref",
    "maintenance_window",
    "rollback_owner",
    "followup_owner",
    "redacted_evidence_refs",
    "no_secret_value_attestation",
    "no_raw_backup_payload_attestation",
    "no_production_restore_attestation",
    "no_false_green_attestation",
]

REVIEWER_CHECKS = [
    {"check_id": "source_owner_response_acceptance_current", "instruction": "來源 owner response acceptance snapshot 必須是目前版本。"},
    {"check_id": "incident_or_change_ref_present", "instruction": "必須有 incident、change、outage、ticket 或 maintenance ref，不能只寫備份正常。"},
    {"check_id": "actor_attribution_present", "instruction": "必須標示 actor role / team，不接受匿名 backup、restore、sync、prune 或 escrow marker write。"},
    {"check_id": "change_or_outage_time_window_present", "instruction": "必須有變更 / 異常時間窗，供 freshness、offsite、alert 與 cold-start scorecard 對齊。"},
    {"check_id": "intent_or_break_glass_present", "instruction": "正常變更需有 change intent；緊急變更需有 break-glass reason，但 break-glass 不等於事前批准。"},
    {"check_id": "before_after_freshness_present", "instruction": "必須有 before / after backup freshness state ref，不得只看最新一次成功。"},
    {"check_id": "backup_status_readback_present", "instruction": "backup status 只能收 owner-provided redacted ref，不得讀 raw backup store 或未脫敏 listing。"},
    {"check_id": "restore_drill_readback_present", "instruction": "restore drill 必須是 readback / approval metadata，不得是 production restore 執行要求。"},
    {"check_id": "restore_target_isolation_present", "instruction": "必須有隔離 restore target 或明確 no-production-write 邊界。"},
    {"check_id": "offsite_sync_readback_present", "instruction": "offsite sync 必須有 redacted state ref，不得保存 raw remote path、object listing 或 rclone config。"},
    {"check_id": "remote_delete_guard_present", "instruction": "任何 latest-only、remote delete 或 retention policy 必須有 remote delete guard 與 owner ref。"},
    {"check_id": "credential_escrow_non_secret_present", "instruction": "credential escrow 只能是 non-secret proof / marker ref，不得包含 value、hash、seed、recovery code 或 partial token。"},
    {"check_id": "credential_recovery_drill_metadata_only", "instruction": "credential recovery drill 必須以 metadata / evidence id 呈現，不保存 secret derivative。"},
    {"check_id": "retention_runway_present", "instruction": "retention / prune 必須有可恢復窗口、runway、撤回條件與 owner。"},
    {"check_id": "retention_or_prune_decision_present", "instruction": "retention 或 prune decision 必須獨立列出，不得與 offsite sync 成功混在一起。"},
    {"check_id": "dependency_map_present", "instruction": "必須列出 DB、repo、registry、object storage、K8s、monitoring、credential escrow 與 DR runbook 依賴圖 ref。"},
    {"check_id": "data_classification_present", "instruction": "必須標示備份集資料分級；不得要求 raw customer data、payload 或 unredacted archive listing。"},
    {"check_id": "restore_observer_stop_condition_present", "instruction": "restore / drill 必須有 observer、stop condition、rollback owner 與停損條件。"},
    {"check_id": "backup_health_no_false_green_present", "instruction": "backup health / textfile / alert evidence 必須防止 false green，不能只看單一 healthy、route 200 或 dashboard up。"},
    {"check_id": "alert_textfile_readback_present", "instruction": "若涉及告警或 textfile exporter，必須回讀 stale / partial / missing marker，不得只看 alert quiet。"},
    {"check_id": "cold_start_scorecard_present", "instruction": "若影響冷啟動或 DR，必須有 cold-start / scorecard ref，且不能偽造 credential escrow evidence。"},
    {"check_id": "cross_project_sync_present", "instruction": "若影響 AwoooP、IwoooS、momo、Gitea、Harbor、monitoring 或公開站，需有跨專案同步 ref。"},
    {"check_id": "rollback_validation_present", "instruction": "必須提供 rollback validation ref，包含 rollback owner 與回復方式。"},
    {"check_id": "post_change_monitoring_present", "instruction": "必須有 post-change monitoring window，觀察 freshness、offsite、restore target、alerts 與 scorecard。"},
    {"check_id": "postcheck_independent", "instruction": "post-check 必須獨立於原操作人、單一 backup status 與 UI 顯示。"},
    {"check_id": "recurrence_guard_present", "instruction": "必須提出防再發 guard、owner review、retention freeze、remote-delete block 或 automation block。"},
    {"check_id": "maintenance_window_present", "instruction": "後續任何 backup、restore、offsite sync、prune、escrow marker 或 Velero 動作都需維護窗口。"},
    {"check_id": "redacted_refs_only", "instruction": "evidence 只能是脫敏 ref、hash、ticket、commit 或 artifact pointer。"},
    {"check_id": "secret_value_absent", "instruction": "不得出現 token、private key、rclone config、restic password、seed、kubeconfig、recovery code、credential URL 或 partial secret。"},
    {"check_id": "raw_payload_absent", "instruction": "不得保存 raw backup listing、raw restore payload、raw archive content、raw object path、raw DB dump 或未脫敏 screenshot。"},
    {"check_id": "no_false_green", "instruction": "不得只用 backup success、route 200、dashboard up、alert quiet、textfile present、UI 可見或 CD success 當 DR / backup 驗收。"},
    {"check_id": "runtime_stays_zero", "instruction": "readback plan 不得觸發 backup、restore、offsite sync、remote delete、retention change、prune、Velero、kubectl、SSH 或 production write。"},
]

OUTCOME_LANES = [
    {"lane_id": "waiting_post_incident_readback", "meaning": "尚未收到 Backup / Restore / Escrow 事故回讀包；所有 accepted / runtime count 維持 0。"},
    {"lane_id": "request_actor_or_time_supplement", "meaning": "缺 actor、change / outage time window、intent 或 break-glass reason 時要求補件。"},
    {"lane_id": "request_backup_freshness_supplement", "meaning": "缺 before / after freshness、backup status、alert textfile 或 scorecard 時要求補件。"},
    {"lane_id": "request_restore_isolation_supplement", "meaning": "缺 restore drill、隔離目標、observer、stop condition 或 rollback validation 時要求補件。"},
    {"lane_id": "request_offsite_retention_supplement", "meaning": "缺 offsite sync、remote delete guard、retention runway 或 prune decision 時要求補件。"},
    {"lane_id": "request_escrow_non_secret_supplement", "meaning": "缺 credential escrow non-secret proof 或 recovery drill metadata 時要求補件。"},
    {"lane_id": "quarantine_raw_payload", "meaning": "收到 secret、raw backup listing、raw restore payload、raw DB dump、rclone config 或未脫敏截圖時只能隔離。"},
    {"lane_id": "reject_false_green_claim", "meaning": "把 backup success、route 200、dashboard up、alert quiet、textfile present 或 UI 可見當驗收時拒收。"},
    {"lane_id": "ready_for_backup_restore_post_incident_review", "meaning": "metadata 合格後，只能進 backup / restore reviewer review。"},
    {"lane_id": "recurrence_guard_backfill_required", "meaning": "需補防再發 guard、retention freeze、remote-delete block、owner review 或 automation block。"},
    {"lane_id": "waiting_runtime_gate", "meaning": "即使 readback accepted，runtime gate 仍需獨立人工批准。"},
]

BLOCKED_ACTIONS = [
    "backup_run",
    "restore_run",
    "restore_drill",
    "production_restore",
    "offsite_sync",
    "offsite_remote_delete",
    "credential_escrow_marker_write",
    "credential_recovery_execution",
    "retention_change",
    "retention_prune",
    "restic_prune",
    "rclone_config_read",
    "rclone_config_change",
    "velero_restore",
    "velero_backup",
    "kubectl_action",
    "ssh_read",
    "ssh_write",
    "secret_value_collection",
    "secret_hash_collection",
    "partial_token_collection",
    "restic_password_collection",
    "rclone_token_collection",
    "kubeconfig_collection",
    "host_write",
    "active_scan",
    "production_write",
    "runtime_gate_open",
    "raw_backup_payload_storage",
    "raw_restore_payload_storage",
    "raw_object_listing_storage",
    "raw_db_dump_storage",
    "accept_secret_value_evidence",
    "accept_credential_derivative_evidence",
    "mark_readback_accepted_without_reviewer_record",
    "accept_backup_success_without_freshness_slo",
    "accept_restore_without_isolated_target",
    "accept_offsite_without_remote_delete_guard",
    "accept_retention_without_runway",
    "accept_credential_recovery_without_non_secret_proof",
    "accept_backup_health_false_green",
    "accept_alert_quiet_as_backup_healthy",
    "accept_textfile_present_as_dr_complete",
    "skip_dependency_map_review",
    "skip_data_classification_review",
    "skip_restore_observer_stop_condition",
    "skip_cross_project_sync",
    "skip_rollback_validation",
    "skip_post_change_monitoring",
    "forge_credential_escrow_evidence",
    "add_action_button",
]


def git_short_sha(root: Path) -> str:
    try:
        result = subprocess.run(
            ["git", "rev-parse", "--short", "HEAD"],
            cwd=root,
            check=True,
            capture_output=True,
            text=True,
        )
        return result.stdout.strip()
    except Exception:
        return "unknown"


def load_json(path: Path) -> dict[str, Any]:
    return json.loads(path.read_text(encoding="utf-8"))


def readback_candidate(item: dict[str, Any]) -> dict[str, Any]:
    surface_id = item["surface_id"]
    candidate_id = f"backup_restore_post_incident_readback:{surface_id}"
    return {
        "post_incident_readback_candidate_id": candidate_id,
        "status": "waiting_post_incident_readback",
        "source_acceptance_candidate_id": item["acceptance_candidate_id"],
        "request_id": item["request_id"],
        "surface_id": surface_id,
        "config_kind": item["config_kind"],
        "backup_scope": item["backup_scope"],
        "control_tier": item["control_tier"],
        "write_capable_surface": item["write_capable_surface"],
        "requires_live_evidence": True,
        "backup_incident_or_change_ref": None,
        "actor_attribution_ref": None,
        "change_or_outage_time_window_ref": None,
        "change_intent_or_break_glass_ref": None,
        "before_backup_freshness_state_ref": None,
        "after_backup_freshness_state_ref": None,
        "backup_status_readback_ref": None,
        "restore_drill_readback_ref": None,
        "restore_target_isolation_readback_ref": None,
        "offsite_sync_readback_ref": None,
        "offsite_remote_delete_guard_readback_ref": None,
        "credential_escrow_non_secret_readback_ref": None,
        "credential_recovery_drill_readback_ref": None,
        "retention_runway_readback_ref": None,
        "retention_or_prune_decision_ref": None,
        "backup_dependency_map_readback_ref": None,
        "data_classification_readback_ref": None,
        "restore_observer_stop_condition_ref": None,
        "backup_health_no_false_green_readback_ref": None,
        "alert_textfile_readback_ref": None,
        "cold_start_dr_scorecard_ref": None,
        "cross_project_sync_ref": None,
        "rollback_validation_ref": None,
        "post_change_monitoring_ref": None,
        "postcheck_readback_ref": None,
        "recurrence_guard_ref": None,
        "maintenance_window": "pending_post_incident_readback",
        "rollback_owner": "pending_post_incident_readback",
        "followup_owner": "pending_post_incident_readback",
        "redacted_evidence_refs": [],
        "reviewer_outcome": "waiting_post_incident_readback",
        "readback_fields": READBACK_FIELDS,
        "required_readback_fields": REQUIRED_READBACK_FIELDS,
        "reviewer_checks": [entry["check_id"] for entry in REVIEWER_CHECKS],
        "outcome_lanes": [entry["lane_id"] for entry in OUTCOME_LANES],
        "blocked_actions": BLOCKED_ACTIONS,
        "not_approval": True,
        "post_incident_readback_received": False,
        "post_incident_readback_accepted": False,
        "actor_attribution_accepted": False,
        "before_after_freshness_accepted": False,
        "backup_status_readback_accepted": False,
        "restore_drill_readback_accepted": False,
        "restore_target_isolation_readback_accepted": False,
        "offsite_sync_readback_accepted": False,
        "offsite_remote_delete_guard_accepted": False,
        "credential_escrow_non_secret_readback_accepted": False,
        "credential_recovery_drill_readback_accepted": False,
        "retention_runway_readback_accepted": False,
        "retention_or_prune_decision_accepted": False,
        "backup_dependency_map_readback_accepted": False,
        "data_classification_readback_accepted": False,
        "restore_observer_stop_condition_accepted": False,
        "backup_health_no_false_green_readback_accepted": False,
        "alert_textfile_readback_accepted": False,
        "cold_start_dr_scorecard_accepted": False,
        "cross_project_sync_accepted": False,
        "rollback_validation_accepted": False,
        "post_change_monitoring_accepted": False,
        "postcheck_readback_accepted": False,
        "recurrence_guard_accepted": False,
        "no_false_green_accepted": False,
        "backup_run_authorized": False,
        "restore_run_authorized": False,
        "offsite_sync_authorized": False,
        "offsite_remote_delete_authorized": False,
        "credential_escrow_marker_write_authorized": False,
        "credential_recovery_execution_authorized": False,
        "retention_change_authorized": False,
        "restic_prune_authorized": False,
        "rclone_config_authorized": False,
        "velero_restore_authorized": False,
        "velero_backup_authorized": False,
        "kubectl_action_authorized": False,
        "ssh_read_authorized": False,
        "ssh_write_authorized": False,
        "secret_value_collection_allowed": False,
        "host_write_authorized": False,
        "active_scan_authorized": False,
        "production_write_authorized": False,
        "runtime_gate": False,
        "action_buttons_allowed": False,
    }


def searchable_candidate_text(item: dict[str, Any]) -> str:
    scopes = item.get("backup_scope", [])
    return " ".join(
        [
            str(item.get("surface_id", "")),
            str(item.get("config_kind", "")),
            " ".join(str(scope) for scope in scopes),
        ]
    ).lower()


def candidate_has_any(item: dict[str, Any], keywords: set[str]) -> bool:
    text = searchable_candidate_text(item)
    return any(keyword in text for keyword in keywords)


def build_report(root: Path, source: dict[str, Any], generated_at: str | None) -> dict[str, Any]:
    report_time = generated_at or datetime.now(TAIPEI).isoformat(timespec="seconds")
    source_candidates = source.get("acceptance_candidates", [])
    candidates = [readback_candidate(item) for item in source_candidates]

    def count_true(key: str) -> int:
        return sum(1 for item in candidates if item[key])

    summary = {
        "source_acceptance_candidate_count": source["summary"]["acceptance_candidate_count"],
        "source_write_capable_acceptance_candidate_count": source["summary"]["write_capable_acceptance_candidate_count"],
        "source_live_evidence_required_candidate_count": source["summary"]["live_evidence_required_candidate_count"],
        "source_required_owner_field_count": source["summary"]["required_owner_field_count"],
        "source_reviewer_check_count": source["summary"]["reviewer_check_count"],
        "source_blocked_action_count": source["summary"]["blocked_action_count"],
        "source_owner_response_accepted_count": source["summary"]["owner_response_accepted_count"],
        "source_runtime_gate_count": source["summary"]["runtime_gate_count"],
        "readback_candidate_count": len(candidates),
        "write_capable_readback_candidate_count": count_true("write_capable_surface"),
        "live_evidence_required_readback_candidate_count": count_true("requires_live_evidence"),
        "restore_drill_readback_required_candidate_count": len(candidates),
        "offsite_or_escrow_readback_required_candidate_count": sum(
            1
            for item in candidates
            if candidate_has_any(
                item,
                {
                    "offsite",
                    "escrow",
                    "credential",
                    "rclone",
                    "b2",
                    "velero",
                    "object storage",
                },
            )
        ),
        "retention_or_remote_delete_readback_required_candidate_count": sum(
            1
            for item in candidates
            if candidate_has_any(
                item,
                {
                    "retention",
                    "prune",
                    "remote_delete",
                    "latest-only",
                    "restic",
                    "offsite",
                },
            )
        ),
        "cross_project_sync_required_candidate_count": len(candidates),
        "no_false_green_required_candidate_count": len(candidates),
        "readback_field_count": len(READBACK_FIELDS),
        "required_readback_field_count": len(REQUIRED_READBACK_FIELDS),
        "reviewer_check_count": len(REVIEWER_CHECKS),
        "outcome_lane_count": len(OUTCOME_LANES),
        "blocked_action_count": len(BLOCKED_ACTIONS),
        "post_incident_readback_received_count": 0,
        "post_incident_readback_accepted_count": 0,
        "actor_attribution_accepted_count": 0,
        "before_after_freshness_accepted_count": 0,
        "backup_status_readback_accepted_count": 0,
        "restore_drill_readback_accepted_count": 0,
        "restore_target_isolation_readback_accepted_count": 0,
        "offsite_sync_readback_accepted_count": 0,
        "offsite_remote_delete_guard_accepted_count": 0,
        "credential_escrow_non_secret_readback_accepted_count": 0,
        "credential_recovery_drill_readback_accepted_count": 0,
        "retention_runway_readback_accepted_count": 0,
        "retention_or_prune_decision_accepted_count": 0,
        "backup_dependency_map_readback_accepted_count": 0,
        "data_classification_readback_accepted_count": 0,
        "restore_observer_stop_condition_accepted_count": 0,
        "backup_health_no_false_green_readback_accepted_count": 0,
        "alert_textfile_readback_accepted_count": 0,
        "cold_start_dr_scorecard_accepted_count": 0,
        "cross_project_sync_accepted_count": 0,
        "rollback_validation_accepted_count": 0,
        "post_change_monitoring_accepted_count": 0,
        "postcheck_readback_accepted_count": 0,
        "recurrence_guard_accepted_count": 0,
        "no_false_green_accepted_count": 0,
        "backup_run_authorized_count": 0,
        "restore_run_authorized_count": 0,
        "offsite_sync_authorized_count": 0,
        "offsite_remote_delete_authorized_count": 0,
        "credential_escrow_marker_write_authorized_count": 0,
        "credential_recovery_execution_authorized_count": 0,
        "retention_change_authorized_count": 0,
        "restic_prune_authorized_count": 0,
        "rclone_config_authorized_count": 0,
        "velero_restore_authorized_count": 0,
        "velero_backup_authorized_count": 0,
        "kubectl_action_authorized_count": 0,
        "ssh_read_authorized_count": 0,
        "ssh_write_authorized_count": 0,
        "secret_value_collection_allowed_count": 0,
        "host_write_authorized_count": 0,
        "active_scan_authorized_count": 0,
        "production_write_authorized_count": 0,
        "runtime_gate_count": 0,
        "action_button_count": 0,
        "coverage_percent_after_readback_plan": 66,
    }

    return {
        "schema_version": "backup_restore_post_incident_readback_plan_v1",
        "generated_at": report_time,
        "git_commit": git_short_sha(root),
        "mode": "metadata_only_no_backup_no_restore_no_secret_value",
        "source_schema_version": source["schema_version"],
        "source_status": source["status"],
        "source_paths": [
            "docs/security/BACKUP-RESTORE-ESCROW-INVENTORY.md",
            "docs/security/backup-restore-escrow-inventory.snapshot.json",
            "docs/security/BACKUP-RESTORE-OWNER-RESPONSE-ACCEPTANCE.md",
            "docs/security/backup-restore-owner-response-acceptance.snapshot.json",
        ],
        "status": "post_incident_readback_plan_ready_no_runtime_action",
        "readback_candidates": candidates,
        "readback_fields": READBACK_FIELDS,
        "required_readback_fields": REQUIRED_READBACK_FIELDS,
        "reviewer_checks": REVIEWER_CHECKS,
        "outcome_lanes": OUTCOME_LANES,
        "blocked_actions": BLOCKED_ACTIONS,
        "execution_boundaries": {
            "not_authorization": True,
            "backup_run_authorized": False,
            "restore_run_authorized": False,
            "offsite_sync_authorized": False,
            "offsite_remote_delete_authorized": False,
            "credential_escrow_marker_write_authorized": False,
            "credential_recovery_execution_authorized": False,
            "retention_change_authorized": False,
            "restic_prune_authorized": False,
            "rclone_config_authorized": False,
            "velero_restore_authorized": False,
            "velero_backup_authorized": False,
            "kubectl_action_authorized": False,
            "ssh_read_authorized": False,
            "ssh_write_authorized": False,
            "secret_value_collection_allowed": False,
            "host_write_authorized": False,
            "active_scan_authorized": False,
            "production_write_authorized": False,
            "runtime_gate": False,
            "action_buttons_allowed": False,
            "raw_backup_payload_storage_allowed": False,
        },
        "operator_interpretation": [
            "此計畫只定義 Backup / Restore / Escrow 事故後回讀欄位，不代表 live backup store 已讀取或可讀取。",
            "backup success、route 200、dashboard up、alert quiet、textfile present、UI 可見或 CD success 都不能單獨當成 DR / backup 健康。",
            "未來若要 backup、restore、offsite sync、remote delete、retention / prune、escrow marker、Velero、kubectl、SSH 或 production write，必須另有維護窗口、rollback owner 與人工批准。",
        ],
        "summary": summary,
    }


def write_report(report: dict[str, Any], output: Path | None) -> None:
    text = json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True) + "\n"
    if output:
        output.write_text(text, encoding="utf-8")
    else:
        sys.stdout.write(text)


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("--root", default=".", help="Repository root")
    parser.add_argument("--generated-at", default=None, help="Override generated_at")
    parser.add_argument("--output", default=None, help="Output snapshot path")
    args = parser.parse_args()

    root = Path(args.root).resolve()
    source = load_json(root / "docs/security/backup-restore-owner-response-acceptance.snapshot.json")
    report = build_report(root, source, args.generated_at)
    output = Path(args.output).resolve() if args.output else None
    write_report(report, output)
    summary = report["summary"]
    print(
        "BACKUP_RESTORE_POST_INCIDENT_READBACK_PLAN_OK "
        f"candidates={summary['readback_candidate_count']} "
        f"write_capable={summary['write_capable_readback_candidate_count']} "
        f"checks={summary['reviewer_check_count']} "
        f"lanes={summary['outcome_lane_count']} "
        f"accepted={summary['post_incident_readback_accepted_count']} "
        f"runtime_gate={summary['runtime_gate_count']}"
    )
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
