#!/usr/bin/env python3
"""Summarize external proof intake for the current route-promotion blocker."""
from __future__ import annotations

import argparse
import html
import json
from pathlib import Path
from typing import Any


ROOT = Path(__file__).resolve().parents[1]
OUT = ROOT / "out"
SOURCE = "map1_01a"
TARGET = "map2_02d"
REFRESH_COMMAND = "python3 tools/refresh_savedata_route_proof.py --search-root <file-or-dir-or-zip>"


def load_json(path: Path, fallback: Any) -> Any:
    if not path.exists():
        return fallback
    return json.loads(path.read_text(encoding="utf-8"))


def optional_out_href(name: str) -> str | None:
    return name if (OUT / name).exists() else None


def first_blocker(completion_audit: dict) -> dict:
    for blocker in completion_audit.get("confirmedRouteBlockers") or []:
        if blocker.get("source") == SOURCE and blocker.get("target") == TARGET:
            return blocker
    return {}


def command_chain() -> list[str]:
    return [
        REFRESH_COMMAND,
        "python3 tools/scan_savedata_slots.py --search-root <file-or-dir-or-zip>",
        "python3 tools/summarize_save_selector_real_savedata_evidence_gap.py --search-root <file-or-dir-or-zip>",
        "python3 tools/summarize_route_investigation_queue.py",
        "python3 tools/summarize_route_promotion_gate.py",
        "python3 tools/summarize_strict_source_hotspot_external_review_packet.py",
        "python3 tools/summarize_selected_root_execution_external_proof_packet.py",
        "python3 tools/summarize_current_leaf_wrapper_external_proof_packet.py",
        "python3 tools/summarize_predecessor_fill_external_proof_packet.py",
        "python3 tools/summarize_selector_merge_external_proof_packet.py",
        "python3 tools/summarize_opcode20_gate_base_external_proof_packet.py",
        "python3 tools/summarize_opcode24_runtime_producer_external_proof_packet.py",
        "python3 tools/summarize_completion_audit.py",
        "python3 tools/summarize_route_blocker_evidence_matrix.py",
        "python3 tools/summarize_route_promotion_external_proof_handoff.py",
        "python3 tools/validate_route_promotion_external_proof.py",
        "python3 tools/verify_route_promotion_external_proof_validator.py",
        "python3 tools/summarize_goal_completion_checklist.py",
        "python3 tools/verify_web_assets.py",
    ]


def proof_template(summary: dict) -> dict:
    packages = {row.get("id"): row for row in summary.get("proofPackages") or []}
    external_inputs = {row.get("id"): row for row in summary.get("externalInputChecklist") or []}
    savedata = packages.get("captured-selector-2-0-savedata") or {}
    runtime = packages.get("runtime-trace-or-equivalent-selected-root-proof") or {}
    strict = packages.get("strict-source-hotspot-review") or {}

    return {
        "schemaVersion": 1,
        "templateStatus": "no-external-proof-submitted",
        "route": {"source": SOURCE, "target": TARGET},
        "purpose": (
            "Fill one of these records when external evidence is available. "
            "The template is not proof by itself and must not change route promotion status."
        ),
        "handoffUrl": "route_promotion_external_proof_handoff.html",
        "completionAuditUrl": "completion_audit.html",
        "validationCommand": "python3 tools/validate_route_promotion_external_proof.py <submitted-proof.json>",
        "requireAcceptedValidationCommand": (
            "python3 tools/validate_route_promotion_external_proof.py <submitted-proof.json> --require-accepted"
        ),
        "validationRefreshCommand": (
            "python3 tools/refresh_savedata_route_proof.py --proof-json <submitted-proof.json> --require-accepted-proof"
        ),
        "requiredInputs": [
            {
                "id": "real-selector-2-0-save",
                "proofPackageId": "captured-selector-2-0-savedata",
                "artifactKind": "captured gameplay savedat file or savedat zip",
                "acceptedSignal": (external_inputs.get("real-selector-2-0-save") or {}).get("acceptedSignal"),
                "submitBy": [
                    "Place captured savedatN.dat or savedatN.zip under SAVEDATA/ or SaveData/",
                    "or pass the file, directory, or zip with --search-root",
                ],
                "refreshCommand": REFRESH_COMMAND,
                "requiredChecks": [
                    "size == 1274",
                    "offset 0x0002 == 0x02",
                    "offset 0x0003 == 0x00",
                    "selectedPointerHex == 0x00540714",
                    "routeEvidenceProofFound == true",
                    "syntheticDiagnostic == false",
                ],
                "expectedSelector": savedata.get("expectedSelector"),
                "expectedSelectedPointerHex": savedata.get("expectedSelectedPointerHex"),
                "expectedRouteMaps": savedata.get("expectedRouteMaps") or [],
                "exampleRecord": {
                    "inputId": "real-selector-2-0-save",
                    "path": "SAVEDATA/savedatN.dat",
                    "capturedFromGameplay": True,
                    "selector": "2:0",
                    "selectedPointerHex": "0x00540714",
                    "fieldMaps": ["map1_01a", "map2_02d"],
                    "syntheticDiagnostic": False,
                    "notes": "Replace N/path with the captured save slot.",
                },
            },
            {
                "id": "normal-route-runtime-trace",
                "proofPackageId": "runtime-trace-or-equivalent-selected-root-proof",
                "artifactKind": "runtime trace, watchpoint log, or equivalent selected-root execution proof",
                "acceptedSignal": (external_inputs.get("normal-route-runtime-trace") or {}).get("acceptedSignal"),
                "submitBy": [
                    "Attach a trace/log artifact that records the normal route path, not a constructed diagnostic",
                    "Refresh selected-root and route-promotion reports after adding the artifact summary",
                ],
                "refreshCommands": [
                    "python3 tools/summarize_selected_root_execution_external_proof_packet.py",
                    "python3 tools/summarize_route_promotion_external_proof_handoff.py",
                    "python3 tools/summarize_completion_audit.py",
                    "python3 tools/verify_web_assets.py",
                ],
                "requiredChecks": [
                    "normalRoutePath == true",
                    "diagnosticRun == false",
                    "selectedPointerGlobalVaHex == 0x0059de30",
                    "selectedPointerValueHex == 0x00540714",
                    "selectedRootExecutionRefFound == true or equivalent proof found",
                    "trace reaches one accepted trace point on the route path",
                ],
                "acceptedTracePoints": [
                    {
                        "addressHex": row.get("addressHex"),
                        "name": row.get("name"),
                        "kind": row.get("kind"),
                        "purpose": row.get("purpose"),
                    }
                    for row in runtime.get("tracePoints") or []
                ],
                "exampleRecord": {
                    "inputId": "normal-route-runtime-trace",
                    "traceTool": "external debugger/watchpoint environment",
                    "normalRoutePath": True,
                    "diagnosticRun": False,
                    "selectedPointerGlobalVaHex": "0x0059de30",
                    "selectedPointerValueHex": "0x00540714",
                    "selectedRootHex": "0x00540714",
                    "observedTracePoints": [
                        {"addressHex": "0x0059de30", "event": "selected pointer observed as 0x00540714"},
                        {"addressHex": "0x00542b0c", "event": "frontier reader executed on route path"},
                    ],
                },
            },
            {
                "id": "strict-source-hotspot",
                "proofPackageId": "strict-source-hotspot-review",
                "artifactKind": "strict source coordinate, event row, tile hotspot review, or equivalent trigger proof",
                "acceptedSignal": (external_inputs.get("strict-source-hotspot") or {}).get("acceptedSignal"),
                "submitBy": [
                    "Attach the candidate side/source tile/target spawn and supporting review artifact",
                    "Refresh strict-source hotspot and route-promotion reports after adding the review result",
                ],
                "refreshCommands": [
                    "python3 tools/summarize_strict_source_hotspot_external_review_packet.py",
                    "python3 tools/summarize_route_promotion_gate.py",
                    "python3 tools/summarize_completion_audit.py",
                    "python3 tools/verify_web_assets.py",
                ],
                "requiredChecks": [
                    "sourceMap == map1_01a",
                    "targetMap == map2_02d",
                    "strictSourceHotspotProofFound == true",
                    "tileHotspotConfirmed == true",
                    "selector-only scene-list adjacency is not the only evidence",
                ],
                "candidateSides": strict.get("reviewPacketCandidateSides") or [],
                "exampleRecord": {
                    "inputId": "strict-source-hotspot",
                    "sourceMap": "map1_01a",
                    "targetMap": "map2_02d",
                    "candidateSide": "top|bottom|left|right",
                    "sourceTile": {"x": None, "y": None},
                    "targetSpawn": {"x": None, "y": None},
                    "strictSourceHotspotProofFound": True,
                    "tileHotspotConfirmed": True,
                    "supportingArtifact": "manual-review-or-runtime-trigger-log",
                },
            },
        ],
        "notAcceptedEvidence": summary.get("notAcceptedEvidence") or [],
    }


def normalized_blocker(blocker: str) -> str:
    prefix = "execution probe: "
    text = blocker.strip()
    return text[len(prefix):] if text.startswith(prefix) else text


def dedupe_blockers(*blocker_lists: list[str]) -> list[str]:
    blockers: list[str] = []
    seen: set[str] = set()
    for blocker_list in blocker_lists:
        for blocker in blocker_list:
            text = normalized_blocker(str(blocker))
            if not text or text in seen:
                continue
            seen.add(text)
            blockers.append(text)
    return blockers


def build_summary() -> dict:
    audit = load_json(OUT / "completion_audit.json", {})
    gate = load_json(OUT / "route_promotion_gate.json", {})
    real = load_json(OUT / "save_selector_real_savedata_evidence_gap.json", {})
    runtime_feas = load_json(OUT / "runtime_trace_feasibility.json", {})
    runtime_exec = load_json(OUT / "runtime_trace_execution_probe.json", {})
    strict = load_json(OUT / "map1_01a_strict_source_hotspot_context.json", {})
    strict_packet = load_json(OUT / "strict_source_hotspot_external_review_packet.json", {})
    selected = load_json(OUT / "save_selector_selected_root_execution_gap.json", {})
    selected_packet = load_json(OUT / "selected_root_execution_external_proof_packet.json", {})
    current_leaf_packet = load_json(OUT / "current_leaf_wrapper_external_proof_packet.json", {})
    predecessor_packet = load_json(OUT / "predecessor_fill_external_proof_packet.json", {})
    selector_merge_packet = load_json(OUT / "selector_merge_external_proof_packet.json", {})
    opcode20_packet = load_json(OUT / "opcode20_gate_base_external_proof_packet.json", {})
    opcode24_packet = load_json(OUT / "opcode24_runtime_producer_external_proof_packet.json", {})
    blocker = first_blocker(audit)
    capture = real.get("requiredCaptureChecklist") or {}
    runtime_exec_blockers = runtime_exec.get("blockers") or []
    runtime_feas_blockers = runtime_feas.get("blockers") or []
    runtime_raw_blockers = runtime_feas_blockers + runtime_exec_blockers
    runtime_blockers = dedupe_blockers(runtime_exec_blockers, runtime_feas_blockers)
    trace_points = runtime_feas.get("tracePoints") or []
    relocated_trace_points = (runtime_exec.get("relocationContext") or {}).get("tracePoints") or []

    proof_packages = [
        {
            "id": "captured-selector-2-0-savedata",
            "status": "missing",
            "primaryGate": "realSelector20Savedata",
            "supportsGates": ["selectedRootExecution"],
            "reportUrl": optional_out_href("save_selector_real_savedata_evidence_gap.html"),
            "reportStatus": (
                "available"
                if optional_out_href("save_selector_real_savedata_evidence_gap.html")
                else "parked until external savedata refresh"
            ),
            "slotScanUrl": optional_out_href("savedata_slot_scan.html"),
            "slotScanStatus": (
                "available"
                if optional_out_href("savedata_slot_scan.html")
                else "parked until external savedata refresh"
            ),
            "webScanUrl": real.get("webScanUrl") or "../web/game.html?savedatScan=1",
            "intakeReadmePaths": ["SAVEDATA/README.md", "SaveData/README.md"],
            "gitignoreGuardrails": ["SAVEDATA/*", "!SAVEDATA/README.md", "SaveData/*", "!SaveData/README.md"],
            "refreshCommand": REFRESH_COMMAND,
            "acceptedPaths": capture.get("acceptedPaths") or [],
            "expectedSize": capture.get("expectedSize"),
            "requiredBytes": capture.get("requiredBytes") or [],
            "expectedSelector": capture.get("expectedSelector") or "2:0",
            "expectedSelectedPointerHex": capture.get("expectedSelectedPointerHex") or "0x00540714",
            "expectedRouteMaps": capture.get("expectedRouteMaps") or [SOURCE, TARGET],
            "scanCommands": capture.get("scanCommands") or [],
            "browserChecks": capture.get("browserChecks") or [],
            "currentState": {
                "currentSelectorRealSaveCount": real.get("currentSelectorRealSaveCount"),
                "selectedPointerRealSaveCount": real.get("selectedPointerRealSaveCount"),
                "routePairRealSaveCount": real.get("routePairRealSaveCount"),
                "routeEvidenceProofFound": real.get("routeEvidenceProofFound"),
                "requiredSelectorBytePairRealSaveCount": real.get("requiredSelectorBytePairRealSaveCount"),
                "publicSearchNoteCount": len(real.get("publicSearchNotes") or []),
                "publicSearchSourceRefCount": len(real.get("publicSearchSourceRefs") or []),
                "syntheticDiagnosticExcluded": real.get("syntheticDiagnosticExcluded"),
                "localSlotScanSyntheticDiagnosticCount": (
                    real.get("localSavedataSlotScan") or {}
                ).get("syntheticDiagnosticCount"),
            },
            "diagnosticExclusionPolicy": real.get("diagnosticExclusionPolicy") or {},
            "successSignals": [
                "currentSelectorRealSaveCount > 0",
                "selectedPointerRealSaveCount > 0",
                "routePairRealSaveCount > 0",
                "routeEvidenceProofFound == true",
            ],
            "stillRequiredAfterMatch": capture.get("stillRequiredAfterMatch") or [],
        },
        {
            "id": "runtime-trace-or-equivalent-selected-root-proof",
            "status": "blocked-by-environment",
            "primaryGate": "runtimeTraceOrEquivalent",
            "supportsGates": ["selectedRootExecution", "strictSourceHotspot"],
            "reportUrl": "runtime_trace_feasibility.html",
            "executionProbeUrl": "runtime_trace_execution_probe.json",
            "tracePoints": trace_points,
            "relocatedTracePoints": relocated_trace_points,
            "runtimeTraceCanRunNow": runtime_feas.get("canRunRuntimeTraceNow"),
            "runtimeTraceExecutionCanCaptureNow": runtime_exec.get("canCaptureTraceNow"),
            "blockers": runtime_blockers,
            "rawBlockers": runtime_raw_blockers,
            "rawBlockerCount": len(runtime_raw_blockers),
            "dedupedBlockerCount": len(runtime_blockers),
            "successSignals": [
                "runtime trace captures 0x0059e348 producer or 0x0040c675 read on route path",
                "runtime trace reaches 0x00542b0c frontier reader on a non-diagnostic path",
                "selected pointer 0x0059de30 becomes 0x00540714 on the normal route path",
            ],
        },
        {
            "id": "strict-source-hotspot-review",
            "status": "missing",
            "primaryGate": "strictSourceHotspot",
            "supportsGates": ["tileHotspotConfirmation"],
            "candidateCount": strict.get("candidateCount"),
            "reviewPacketUrl": "strict_source_hotspot_external_review_packet.html",
            "proofFound": strict_packet.get("proofFound"),
            "strictSourceHotspotExternalReviewProofFound": strict_packet.get(
                "strictSourceHotspotExternalReviewProofFound"
            ),
            "reviewPacketBlockedIds": (
                strict_packet.get("failedStrictSourceHotspotReviewGateIds")
                or strict.get("failedStrictHotspotGateIds")
                or []
            ),
            "missingEvidence": strict_packet.get("missingEvidence") or strict.get("missingEvidence") or [],
            "reviewPacketEvidenceRefCount": strict_packet.get("evidenceRefCount"),
            "reviewPacketCandidateCount": strict_packet.get("candidateCount"),
            "reviewPacketCandidateSides": [
                row.get("side") for row in strict_packet.get("candidateRows") or []
            ],
            "strictSourceHotspotProofFound": strict.get("strictSourceHotspotProofFound"),
            "tileHotspotConfirmed": strict.get("tileHotspotConfirmed"),
            "candidateAllBlocked": strict.get("candidateAllBlocked"),
            "candidateBlockReasonCounts": strict.get("candidateBlockReasonCounts") or {},
            "remainingProofs": strict.get("remainingProofs") or [],
            "successSignals": [
                "strictSourceHotspotProofFound == true",
                "tileHotspotConfirmed == true",
                "candidate row links map1_01a source tile to map2_02d target",
            ],
        },
        {
            "id": "selected-root-execution-proof",
            "status": "missing",
            "primaryGate": "selectedRootExecution",
            "supportsGates": ["runtimeTraceOrEquivalent"],
            "proofPacketUrl": "selected_root_execution_external_proof_packet.html",
            "proofFound": selected_packet.get("proofFound"),
            "selectedRootExternalProofFound": selected_packet.get("selectedRootExternalProofFound"),
            "proofPacketBlockedIds": (
                selected_packet.get("failedSelectedRootExternalGateIds")
                or selected.get("failedSelectedRootGateIds")
                or []
            ),
            "missingEvidence": selected_packet.get("missingEvidence") or selected.get("missingEvidence") or [],
            "proofPacketEvidenceRefCount": selected_packet.get("evidenceRefCount"),
            "proofPacketSubgateCount": selected_packet.get("selectedRootSubgateCount"),
            "proofPacketNonPromotingSubgateCount": selected_packet.get(
                "selectedRootNonPromotingSubgateCount"
            ),
            "proofPacketRoutePairEntryIndices": (
                selected_packet.get("routePairSelectionEvidence") or {}
            ).get("routePairEntryIndices") or [],
            "proofPacketNegativeReaderEntryIndices": (
                selected_packet.get("routePairSelectionEvidence") or {}
            ).get("negativeReaderEntryIndices") or [],
            "selectedRootExecutionRefFound": selected.get("selectedRootExecutionRefFound"),
            "subgateStatuses": selected.get("selectedRootSubgateStatuses") or {},
            "remainingProofs": selected.get("remainingProofs") or [],
            "successSignals": [
                "selectedRootExecutionRefFound == true",
                "selected root 0x00540714 is reached by normal execution, not constructed diagnostics",
            ],
        },
        {
            "id": "current-leaf-wrapper-proof",
            "status": "missing",
            "primaryGate": "selectedRootExecution",
            "supportsGates": ["runtimeTraceOrEquivalent"],
            "proofPacketUrl": "current_leaf_wrapper_external_proof_packet.html",
            "proofFound": current_leaf_packet.get("proofFound"),
            "currentLeafWrapperExternalProofFound": current_leaf_packet.get(
                "currentLeafWrapperExternalProofFound"
            ),
            "proofPacketBlockedIds": current_leaf_packet.get("failedCurrentLeafWrapperExternalGateIds") or [],
            "failedCurrentLeafWrapperExternalGateIds": current_leaf_packet.get(
                "failedCurrentLeafWrapperExternalGateIds"
            )
            or [],
            "missingEvidence": current_leaf_packet.get("missingEvidence") or [],
            "currentSelector": current_leaf_packet.get("currentSelector"),
            "currentRootHex": current_leaf_packet.get("currentRootHex"),
            "rootTablePointerHex": current_leaf_packet.get("rootTablePointerHex"),
            "wrapperEntryHex": current_leaf_packet.get("wrapperEntryHex"),
            "wrapperDescriptorHex": current_leaf_packet.get("wrapperDescriptorHex"),
            "wrapperChildPointerHex": current_leaf_packet.get("wrapperChildPointerHex"),
            "frontierLeafHex": current_leaf_packet.get("frontierLeafHex"),
            "frontierReaderHex": current_leaf_packet.get("frontierReaderHex"),
            "routePairEntryIndices": current_leaf_packet.get("routePairEntryIndices") or [],
            "routePairCorrectedTraceEntryIndices": current_leaf_packet.get(
                "routePairCorrectedTraceEntryIndices"
            )
            or [],
            "negativeReaderEntryIndices": current_leaf_packet.get("negativeReaderEntryIndices") or [],
            "correctedTraceReachesReaderCount": current_leaf_packet.get("correctedTraceReachesReaderCount"),
            "correctedTraceAllRoutePairDescriptorsReachReader": current_leaf_packet.get(
                "correctedTraceAllRoutePairDescriptorsReachReader"
            ),
            "frontierReaderSelectableByNonNegativeIndex": current_leaf_packet.get(
                "frontierReaderSelectableByNonNegativeIndex"
            ),
            "frontierReaderReachableByCorrectedNonNegativeIndex": current_leaf_packet.get(
                "frontierReaderReachableByCorrectedNonNegativeIndex"
            ),
            "correctedTraceNormalSelectionGapStatus": current_leaf_packet.get(
                "correctedTraceNormalSelectionGapStatus"
            ),
            "routePairEntryExecutionProven": current_leaf_packet.get("routePairEntryExecutionProven"),
            "routePairIndexSourceProofFound": current_leaf_packet.get("routePairIndexSourceProofFound"),
            "wrapperExecutionProofFound": current_leaf_packet.get("wrapperExecutionProofFound"),
            "currentLeafSelectionProofFound": current_leaf_packet.get("currentLeafSelectionProofFound"),
            "currentSelectorLeafExecutionProofFound": current_leaf_packet.get(
                "currentSelectorLeafExecutionProofFound"
            ),
            "rootTableWindowDirectRefCount": (
                current_leaf_packet.get("rootTableEvidence") or {}
            ).get("rootTableWindowDirectRefCount"),
            "rootTableWindowDirectTextRefCount": (
                current_leaf_packet.get("rootTableEvidence") or {}
            ).get("rootTableWindowDirectTextRefCount"),
            "routePairIndexSourceDirectPointerRefPromotesRoute": (
                current_leaf_packet.get("rootTableEvidence") or {}
            ).get("routePairIndexSourceDirectPointerRefPromotesRoute"),
            "diagnosticWrapperProofStatus": (
                current_leaf_packet.get("diagnosticExclusionEvidence") or {}
            ).get("constructedDiagnosticWrapperProofStatus"),
            "diagnosticLeftStabilityRouteSelectorHitCount": (
                current_leaf_packet.get("diagnosticExclusionEvidence") or {}
            ).get("constructedDiagnosticLeftStabilityRouteSelectorHitCount"),
            "diagnosticLeftStabilityRecheckRouteSelectorHitCount": (
                current_leaf_packet.get("diagnosticExclusionEvidence") or {}
            ).get("constructedDiagnosticLeftStabilityRecheckRouteSelectorHitCount"),
            "proofPacketEvidenceRefCount": current_leaf_packet.get("evidenceRefCount"),
            "successSignals": [
                "normal selected-root execution reaches selector 2:0/current root 0x00540714",
                "route-pair entries 6/8 or wrapper -12 are selected by a higher-level index source",
                "wrapper 0x00542a04 executes into frontier leaf 0x00542ae8 before reader 0x00542b0c",
            ],
        },
        {
            "id": "predecessor-fill-order-proof",
            "status": "missing",
            "primaryGate": "selectedRootExecution",
            "supportsGates": ["runtimeTraceOrEquivalent"],
            "proofPacketUrl": "predecessor_fill_external_proof_packet.html",
            "proofPacketBlockedIds": (
                predecessor_packet.get("failedPredecessorFillExternalGateIds")
                or predecessor_packet.get("proofGateBlockedIds")
                or []
            ),
            "missingEvidence": predecessor_packet.get("missingEvidence") or [],
            "proofPacketGatePassCount": predecessor_packet.get("proofGatePassCount"),
            "proofPacketGateBlockedCount": predecessor_packet.get("proofGateBlockedCount"),
            "proofPacketAllBlocked": predecessor_packet.get("proofGatesAllBlocked"),
            "proofPacketEvidenceRefCount": predecessor_packet.get("evidenceRefCount"),
            "predecessorSelector": predecessor_packet.get("predecessorSelector"),
            "currentSelector": predecessor_packet.get("currentSelector"),
            "fillSites": predecessor_packet.get("fillSites") or [],
            "currentReaderHex": predecessor_packet.get("currentReaderHex"),
            "proofFound": predecessor_packet.get("proofFound"),
            "predecessorFillExternalProofFound": predecessor_packet.get(
                "predecessorFillExternalProofFound"
            ),
            "runtimePredecessorFillObserved": predecessor_packet.get("runtimePredecessorFillObserved"),
            "runtimeObservationSummary": predecessor_packet.get("runtimeObservationSummary") or {},
            "successSignals": [
                "normal runtime observes predecessor fill before current reader",
                "save-selector slice dispatch is proven at the predecessor descriptor boundary",
                "selector merge/order closes on a non-diagnostic path",
            ],
        },
        {
            "id": "selector-merge-proof",
            "status": "missing",
            "primaryGate": "selectedRootExecution",
            "supportsGates": ["runtimeTraceOrEquivalent"],
            "proofPacketUrl": "selector_merge_external_proof_packet.html",
            "proofFound": selector_merge_packet.get("proofFound"),
            "selectorMergeExternalProofFound": selector_merge_packet.get(
                "selectorMergeExternalProofFound"
            ),
            "proofPacketBlockedIds": selector_merge_packet.get("failedSelectorMergeExternalGateIds") or [],
            "failedSelectorMergeExternalGateIds": selector_merge_packet.get(
                "failedSelectorMergeExternalGateIds"
            )
            or [],
            "missingEvidence": selector_merge_packet.get("missingEvidence") or [],
            "currentEqualsPredecessorPlusSource": selector_merge_packet.get(
                "currentEqualsPredecessorPlusSource"
            ),
            "sourcePredecessorUnionCoversCurrent": selector_merge_packet.get(
                "sourcePredecessorUnionCoversCurrent"
            ),
            "sourcePredecessorUnionExtraMaps": selector_merge_packet.get(
                "sourcePredecessorUnionExtraMaps"
            )
            or [],
            "mergeShapeOnly": selector_merge_packet.get("mergeShapeOnly"),
            "selectorMergeGapOpen": selector_merge_packet.get("selectorMergeGapOpen"),
            "routeOrderProven": selector_merge_packet.get("routeOrderProven"),
            "sourceToCurrentBridgeHitCount": (
                selector_merge_packet.get("executionBridgeMatrix") or {}
            ).get("sourceToCurrentBridgeHitCount"),
            "predecessorToCurrentHitCount": (
                selector_merge_packet.get("executionBridgeMatrix") or {}
            ).get("predecessorToCurrentHitCount"),
            "forwardMergeBridgeHitCount": (
                selector_merge_packet.get("executionBridgeMatrix") or {}
            ).get("forwardMergeBridgeHitCount"),
            "currentToPredecessorBeforeFillHitCount": (
                selector_merge_packet.get("executionBridgeMatrix") or {}
            ).get("currentToPredecessorBeforeFillHitCount"),
            "currentPredecessorHitsBeforeFillOnly": (
                selector_merge_packet.get("executionBridgeMatrix") or {}
            ).get("currentPredecessorHitsBeforeFillOnly"),
            "selectorMergeExecutionProofFound": selector_merge_packet.get(
                "selectorMergeExecutionProofFound"
            ),
            "selectorMergeRuntimeProofFound": selector_merge_packet.get(
                "selectorMergeRuntimeProofFound"
            ),
            "selectorMergeClosureProofFound": selector_merge_packet.get(
                "selectorMergeClosureProofFound"
            ),
            "proofPacketEvidenceRefCount": selector_merge_packet.get("evidenceRefCount"),
            "successSignals": [
                "source/current VM control-flow bridge into selector 2:0 is observed",
                "predecessor/current forward bridge or execution-like merge bridge is observed",
                "selector 2:0 selected-root execution is proven on a non-diagnostic path",
            ],
        },
        {
            "id": "opcode20-gate-base-proof",
            "status": "missing",
            "primaryGate": "selectedRootExecution",
            "supportsGates": ["runtimeTraceOrEquivalent"],
            "proofPacketUrl": "opcode20_gate_base_external_proof_packet.html",
            "proofFound": opcode20_packet.get("proofFound"),
            "opcode20GateBaseExternalProofFound": opcode20_packet.get(
                "opcode20GateBaseExternalProofFound"
            ),
            "proofPacketBlockedIds": opcode20_packet.get("failedOpcode20GateBaseExternalGateIds") or [],
            "failedOpcode20GateBaseExternalGateIds": opcode20_packet.get(
                "failedOpcode20GateBaseExternalGateIds"
            )
            or [],
            "missingEvidence": opcode20_packet.get("missingEvidence") or [],
            "currentWriterVaHex": opcode20_packet.get("currentWriterVaHex"),
            "firstGateVaHex": opcode20_packet.get("firstGateVaHex"),
            "secondGateVaHex": opcode20_packet.get("secondGateVaHex"),
            "opcode20CandidateVaHex": opcode20_packet.get("opcode20CandidateVaHex"),
            "opcode20CurrentMode": opcode20_packet.get("opcode20CurrentMode"),
            "gateWindowOnlyOpcode20BaseCandidate": opcode20_packet.get(
                "gateWindowOnlyOpcode20BaseCandidate"
            ),
            "activeOrderProofFound": opcode20_packet.get("activeOrderProofFound"),
            "gateTimeBaseProofFound": opcode20_packet.get("gateTimeBaseProofFound"),
            "activeOrderOnlyProofEliminated": opcode20_packet.get(
                "activeOrderOnlyProofEliminated"
            ),
            "descriptorAllScriptSpecificGateBaseProven": (
                opcode20_packet.get("descriptorEvidence") or {}
            ).get("allScriptSpecificGateBaseProven"),
            "descriptorAllScriptSelectionOpcodeCount": (
                opcode20_packet.get("descriptorEvidence") or {}
            ).get("allScriptSelectionOpcodeCount"),
            "contextF2SpecificRuntimeObjectPointerProven": (
                opcode20_packet.get("contextF2Evidence") or {}
            ).get("specificRuntimeObjectPointerProven"),
            "contextF2RuntimeObjectTableStateRequired": (
                opcode20_packet.get("contextF2Evidence") or {}
            ).get("runtimeObjectTableStateRequired"),
            "diagnosticActiveOrderSampleCount": (
                (opcode20_packet.get("runtimeObservationSummary") or {}).get(
                    "diagnosticActiveOrderEvidence"
                )
                or {}
            ).get("sampleCount"),
            "publicPredecessorActiveOrderSampleCount": (
                (opcode20_packet.get("runtimeObservationSummary") or {}).get(
                    "publicPredecessorActiveOrderEvidence"
                )
                or {}
            ).get("sampleCount"),
            "proofPacketEvidenceRefCount": opcode20_packet.get("evidenceRefCount"),
            "successSignals": [
                "opcode 0x20 route-path runtime descriptor/base is proven before the gate",
                "normal selector 2:0 active order/count or equivalent runtime trace is captured",
                "context+0xa8 base at 0x005428c4/0x005428cc is proven on the route path",
            ],
        },
        {
            "id": "opcode24-runtime-producer-proof",
            "status": "blocked-by-environment",
            "primaryGate": "runtimeTraceOrEquivalent",
            "supportsGates": ["selectedRootExecution", "strictSourceHotspot"],
            "proofPacketUrl": "opcode24_runtime_producer_external_proof_packet.html",
            "mode1SourceHex": opcode24_packet.get("mode1SourceHex"),
            "mode1ReadVaHex": opcode24_packet.get("mode1ReadVaHex"),
            "opcode24BoundaryVaHex": opcode24_packet.get("opcode24BoundaryVaHex"),
            "proofFound": opcode24_packet.get("proofFound"),
            "proofPacketBlockedIds": (
                opcode24_packet.get("failedOpcode24RuntimeProducerGateIds") or []
            ),
            "missingEvidence": opcode24_packet.get("missingEvidence") or [],
            "runtimeClassification": (
                opcode24_packet.get("defaultAndRuntimePollEvidence") or {}
            ).get("runtimeClassification"),
            "mode1SourceNonzeroObserved": (
                opcode24_packet.get("defaultAndRuntimePollEvidence") or {}
            ).get("mode1SourceNonzeroObserved"),
            "canRunRuntimeTraceNow": (
                opcode24_packet.get("traceAvailability") or {}
            ).get("canRunRuntimeTraceNow"),
            "canCaptureTraceNow": (
                opcode24_packet.get("traceAvailability") or {}
            ).get("canCaptureTraceNow"),
            "successSignals": [
                "watchpoint captures a write to 0x0059e348 on the normal route path",
                "breakpoint at 0x0040c675 observes a route-backed mode1 value",
                "runtime flag and selected-root proof line up on the same non-diagnostic path",
            ],
        },
    ]

    verification_checklist = [
        {
            "requirement": "normal route can promote map1_01a -> map2_02d",
            "currentEvidence": "out/route_promotion_gate.json",
            "requiredSignal": "routePromotionAllowed == true",
            "currentStatus": "missing" if gate.get("routePromotionAllowed") is not True else "satisfied",
        },
        {
            "requirement": "completion audit accepts the goal",
            "currentEvidence": "out/completion_audit.json",
            "requiredSignal": "achieved == true",
            "currentStatus": "missing" if audit.get("achieved") is not True else "satisfied",
        },
        {
            "requirement": "captured selector 2:0 savedata is present",
            "currentEvidence": "out/save_selector_real_savedata_evidence_gap.json",
            "requiredSignal": "routeEvidenceProofFound == true",
            "currentStatus": "missing" if real.get("routeEvidenceProofFound") is not True else "satisfied",
        },
        {
            "requirement": "runtime trace or selected-root equivalent proof exists",
            "currentEvidence": "out/runtime_trace_feasibility.json; out/save_selector_selected_root_execution_gap.json",
            "requiredSignal": "runtime trace/equivalent selected-root proof",
            "currentStatus": "missing",
        },
        {
            "requirement": "strict source hotspot and tile hotspot are confirmed",
            "currentEvidence": "out/map1_01a_strict_source_hotspot_context.json",
            "requiredSignal": "strictSourceHotspotProofFound == true and tileHotspotConfirmed == true",
            "currentStatus": "missing",
        },
    ]

    not_accepted_evidence = [
        "out/synthetic_savedat_selector_2_0.dat is constructed diagnostic data, not captured gameplay savedata",
        "out/runtime_patched_public_savedat_selector_2_0*.dat files are generated patched diagnostics, not captured gameplay savedata",
        "public editor/remaster pages are source refs only; they do not contain original selector 2:0 savedata",
        "patched selector/runtime diagnostic polls are non-promoting unless reproduced by real captured state",
    ]
    external_input_checklist = [
        {
            "id": "real-selector-2-0-save",
            "neededInput": "captured gameplay SaveData/savedatN.dat or savedatN.zip",
            "currentState": (
                f"realSelector2:0={real.get('currentSelectorRealSaveCount')}; "
                f"selectedPointer={real.get('selectedPointerRealSaveCount')}; "
                f"routePair={real.get('routePairRealSaveCount')}"
            ),
            "acceptedSignal": (
                "1274-byte save with 0x0002=0x02, 0x0003=0x00, selected pointer 0x00540714, "
                "and routeEvidenceProofFound == true"
            ),
            "refresh": REFRESH_COMMAND,
        },
        {
            "id": "normal-route-runtime-trace",
            "neededInput": "runtime trace or equivalent selected-root proof from a stable debugger/VM",
            "currentState": (
                f"canRunRuntimeTraceNow={runtime_feas.get('canRunRuntimeTraceNow')}; "
                f"canCaptureTraceNow={runtime_exec.get('canCaptureTraceNow')}"
            ),
            "acceptedSignal": (
                "0x0059de30 becomes 0x00540714, or 0x00542b0c / 0x0040c675 is observed on a non-diagnostic route path"
            ),
            "refresh": "python3 tools/summarize_selected_root_execution_external_proof_packet.py",
        },
        {
            "id": "strict-source-hotspot",
            "neededInput": "strict map1_01a source coordinate/event row or manual review tied to map2_02d",
            "currentState": (
                f"candidates={strict_packet.get('candidateCount')}; "
                f"proofFound={strict_packet.get('proofFound')}; "
                f"tileHotspotConfirmed={strict.get('tileHotspotConfirmed')}"
            ),
            "acceptedSignal": (
                "strictSourceHotspotProofFound == true and tileHotspotConfirmed == true for the same map1_01a -> map2_02d candidate"
            ),
            "refresh": "python3 tools/summarize_strict_source_hotspot_external_review_packet.py",
        },
    ]
    next_required_inputs = audit.get("nextRequiredInputs") or [
        "Captured gameplay savedat with selector 2:0 and selected pointer 0x00540714 covering map1_01a -> map2_02d.",
        "Stable selected-root runtime trace or equivalent proof for selected pointer 0x0059de30 executing root 0x00540714.",
        "Strict map1_01a source coordinate or tile-hotspot proof linked to map2_02d.",
    ]

    return {
        "source": SOURCE,
        "target": TARGET,
        "achieved": audit.get("achieved"),
        "reachableCount": audit.get("reachableCount"),
        "routePromotionAllowed": blocker.get("routePromotionAllowed"),
        "failedGateIds": blocker.get("routePromotionFailedGateIds") or gate.get("failedGateIds") or [],
        "missingEvidence": blocker.get("routePromotionMissingEvidence") or gate.get("missingEvidence") or [],
        "hardMissingEvidence": blocker.get("hardMissingEvidence") or [],
        "nextRequiredInputs": next_required_inputs,
        "proofTemplateUrl": "route_promotion_external_proof_template.html",
        "proofTemplateJsonUrl": "route_promotion_external_proof_template.json",
        "proofValidationUrl": "route_promotion_external_proof_validation.html",
        "proofValidationJsonUrl": "route_promotion_external_proof_validation.json",
        "proofValidationCommand": "python3 tools/validate_route_promotion_external_proof.py <submitted-proof.json>",
        "proofValidationRequireAcceptedCommand": (
            "python3 tools/validate_route_promotion_external_proof.py <submitted-proof.json> --require-accepted"
        ),
        "proofValidationRefreshCommand": (
            "python3 tools/refresh_savedata_route_proof.py --proof-json <submitted-proof.json> --require-accepted-proof"
        ),
        "proofPackages": proof_packages,
        "externalInputChecklist": external_input_checklist,
        "notAcceptedEvidence": not_accepted_evidence,
        "regenerateAndVerifyCommands": command_chain(),
        "verificationChecklist": verification_checklist,
        "promotionStatus": "blocked" if audit.get("achieved") is not True else "complete",
        "conclusion": (
            "The route remains blocked until a real selector 2:0 savedata sample, a stable runtime "
            "trace/equivalent selected-root proof, and strict source/tile hotspot proof are available."
        ),
    }


def markdown(summary: dict) -> str:
    def md_report(label: str, href: str | None, status: str | None = None) -> str:
        if href:
            return f"[{label}]({href})"
        return f"{label} ({status or 'not generated'})"

    lines = [
        "# Route Promotion External Proof Handoff",
        "",
        f"- route: {summary['source']} -> {summary['target']}",
        f"- achieved: {summary.get('achieved')}",
        f"- reachable count: {summary.get('reachableCount')}",
        f"- route promotion allowed: {summary.get('routePromotionAllowed')}",
        f"- promotion status: {summary.get('promotionStatus')}",
        f"- failed gates: {', '.join(summary.get('failedGateIds') or [])}",
        f"- missing evidence: {', '.join(summary.get('missingEvidence') or [])}",
        "",
        "## Next Required Inputs",
        "",
    ]
    lines.extend(f"- {item}" for item in summary.get("nextRequiredInputs") or [])
    lines.extend([
        "",
        "## External Proof Template",
        "",
        f"- json: `{summary.get('proofTemplateJsonUrl')}`",
        f"- html: `{summary.get('proofTemplateUrl')}`",
        f"- validation: `{summary.get('proofValidationUrl')}`",
        f"- validation json: `{summary.get('proofValidationJsonUrl')}`",
        f"- validate submitted record: `{summary.get('proofValidationCommand')}`",
        f"- require accepted record: `{summary.get('proofValidationRequireAcceptedCommand')}`",
        f"- validate and refresh: `{summary.get('proofValidationRefreshCommand')}`",
        "- status: template only; not accepted as proof until a filled external record satisfies one accepted signal",
        "",
        "## Proof Packages",
        "",
        "| id | status | primary gate | success signals |",
        "| --- | --- | --- | --- |",
    ])
    for package in summary.get("proofPackages") or []:
        lines.append(
            f"| `{package.get('id')}` | {package.get('status')} | `{package.get('primaryGate')}` | "
            f"{'<br>'.join(package.get('successSignals') or [])} |"
        )
    lines.extend([
        "",
        "## Required External Inputs",
        "",
        "| id | needed input | current state | accepted signal | refresh |",
        "| --- | --- | --- | --- | --- |",
    ])
    for row in summary.get("externalInputChecklist") or []:
        lines.append(
            f"| `{row.get('id')}` | {row.get('neededInput')} | {row.get('currentState')} | "
            f"{row.get('acceptedSignal')} | `{row.get('refresh')}` |"
        )
    lines.extend([
        "",
        "## Captured Savedata Intake",
        "",
    ])
    savedata = (summary.get("proofPackages") or [{}])[0]
    lines.append(
        f"- report: {md_report('real savedata evidence gap', savedata.get('reportUrl'), savedata.get('reportStatus'))}"
    )
    lines.append(
        f"- slot scan: {md_report('SAVEDATA slot scan', savedata.get('slotScanUrl'), savedata.get('slotScanStatus'))}"
    )
    lines.append(f"- browser scan: `{savedata.get('webScanUrl')}`")
    lines.append(f"- intake readmes: {', '.join(f'`{path}`' for path in savedata.get('intakeReadmePaths') or [])}")
    lines.append(f"- gitignore guardrails: {', '.join(f'`{rule}`' for rule in savedata.get('gitignoreGuardrails') or [])}")
    lines.append(f"- one-command refresh: `{savedata.get('refreshCommand')}`")
    lines.append(f"- expected size: {savedata.get('expectedSize')}")
    lines.append(f"- expected selector: `{savedata.get('expectedSelector')}`")
    lines.append(f"- expected selected pointer: `{savedata.get('expectedSelectedPointerHex')}`")
    lines.append(f"- expected route maps: {', '.join(savedata.get('expectedRouteMaps') or [])}")
    policy = savedata.get("diagnosticExclusionPolicy") or {}
    current_state = savedata.get("currentState") or {}
    lines.append(f"- diagnostic exclusion policy: {policy.get('note')}")
    lines.append(f"- diagnostic path markers: {', '.join(f'`{item}`' for item in policy.get('pathMarkers') or [])}")
    lines.append(f"- synthetic diagnostic excluded: {current_state.get('syntheticDiagnosticExcluded')}")
    lines.append(f"- local slot scan synthetic diagnostics: {current_state.get('localSlotScanSyntheticDiagnosticCount')}")
    lines.extend(["", "| offset | required | meaning |", "| --- | --- | --- |"])
    for row in savedata.get("requiredBytes") or []:
        lines.append(f"| `{row.get('offsetHex')}` | `{row.get('requiredHex')}` | {row.get('meaning')} |")
    lines.extend(["", "Accepted paths:"])
    lines.extend(f"- `{path}`" for path in savedata.get("acceptedPaths") or [])
    lines.extend(["", "Scan commands:"])
    lines.extend(f"- `{cmd}`" for cmd in savedata.get("scanCommands") or [])
    lines.extend(["", "## Runtime Trace Points", ""])
    runtime = (summary.get("proofPackages") or [{}, {}])[1]
    lines.append(f"- report: `{runtime.get('reportUrl')}`")
    lines.append(f"- execution probe: `{runtime.get('executionProbeUrl')}`")
    lines.append(f"- blocker count: {runtime.get('dedupedBlockerCount')}")
    lines.append(f"- raw blocker count: {runtime.get('rawBlockerCount')}")
    lines.extend(["", "| name | kind | address | purpose |", "| --- | --- | --- | --- |"])
    for row in runtime.get("tracePoints") or []:
        lines.append(
            f"| {row.get('name')} | {row.get('kind')} | `{row.get('addressHex')}` | {row.get('purpose')} |"
        )
    lines.extend(["", "Runtime trace blockers:"])
    lines.extend(f"- {item}" for item in runtime.get("blockers") or ["none"])
    strict = (summary.get("proofPackages") or [{}, {}, {}])[2]
    lines.extend([
        "",
        "## Strict Hotspot Review Packet",
        "",
        f"- review packet: `{strict.get('reviewPacketUrl')}`",
        f"- proof found: {strict.get('proofFound')}",
        f"- failed strict-source hotspot review gates: `{', '.join(strict.get('reviewPacketBlockedIds') or [])}`",
        f"- missing evidence count: {len(strict.get('missingEvidence') or [])}",
        f"- evidence refs: {strict.get('reviewPacketEvidenceRefCount')}",
        f"- candidate count: {strict.get('reviewPacketCandidateCount')}",
        f"- candidate sides: {', '.join(strict.get('reviewPacketCandidateSides') or [])}",
    ])
    selected = (summary.get("proofPackages") or [{}, {}, {}, {}])[3]
    lines.extend([
        "",
        "## Selected Root Execution Packet",
        "",
        f"- proof packet: `{selected.get('proofPacketUrl')}`",
        f"- proof found: {selected.get('proofFound')}",
        f"- subgates: {selected.get('proofPacketNonPromotingSubgateCount')}/"
        f"{selected.get('proofPacketSubgateCount')} non-promoting",
        f"- failed selected-root external gates: `{', '.join(selected.get('proofPacketBlockedIds') or [])}`",
        f"- missing evidence count: {len(selected.get('missingEvidence') or [])}",
        f"- evidence refs: {selected.get('proofPacketEvidenceRefCount')}",
        f"- route-pair entry indices: {selected.get('proofPacketRoutePairEntryIndices')}",
        f"- negative reader entry indices: {selected.get('proofPacketNegativeReaderEntryIndices')}",
    ])
    current_leaf = next(
        (row for row in summary.get("proofPackages") or [] if row.get("id") == "current-leaf-wrapper-proof"),
        {},
    )
    lines.extend([
        "",
        "## Current Leaf Wrapper Packet",
        "",
        f"- proof packet: `{current_leaf.get('proofPacketUrl')}`",
        f"- proof found: {current_leaf.get('proofFound')}",
        f"- currentLeafWrapperExternalProofFound: {current_leaf.get('currentLeafWrapperExternalProofFound')}",
        f"- blocked gate ids: `{', '.join(current_leaf.get('proofPacketBlockedIds') or [])}`",
        f"- missing evidence count: {len(current_leaf.get('missingEvidence') or [])}",
        f"- evidence refs: {current_leaf.get('proofPacketEvidenceRefCount')}",
        f"- current selector/root/table: `{current_leaf.get('currentSelector')}` / `{current_leaf.get('currentRootHex')}` / `{current_leaf.get('rootTablePointerHex')}`",
        f"- wrapper entry/descriptor/child: `{current_leaf.get('wrapperEntryHex')}` / `{current_leaf.get('wrapperDescriptorHex')}` / `{current_leaf.get('wrapperChildPointerHex')}`",
        f"- frontier leaf/reader: `{current_leaf.get('frontierLeafHex')}` / `{current_leaf.get('frontierReaderHex')}`",
        f"- route-pair entry indices: {current_leaf.get('routePairEntryIndices')}",
        f"- corrected trace entry indices: {current_leaf.get('routePairCorrectedTraceEntryIndices')}",
        f"- negative reader entry indices: {current_leaf.get('negativeReaderEntryIndices')}",
        f"- corrected trace reader count/all: {current_leaf.get('correctedTraceReachesReaderCount')}/"
        f"{current_leaf.get('correctedTraceAllRoutePairDescriptorsReachReader')}",
        f"- nonnegative selectable/corrected reachable: {current_leaf.get('frontierReaderSelectableByNonNegativeIndex')}/"
        f"{current_leaf.get('frontierReaderReachableByCorrectedNonNegativeIndex')}",
        f"- corrected trace normal-selection status: `{current_leaf.get('correctedTraceNormalSelectionGapStatus')}`",
        f"- route/index/wrapper/current-leaf/current-selector-leaf proofs: {current_leaf.get('routePairEntryExecutionProven')}/"
        f"{current_leaf.get('routePairIndexSourceProofFound')}/{current_leaf.get('wrapperExecutionProofFound')}/"
        f"{current_leaf.get('currentLeafSelectionProofFound')}/{current_leaf.get('currentSelectorLeafExecutionProofFound')}",
        f"- rootTableWindowDirectRefCount/text refs: {current_leaf.get('rootTableWindowDirectRefCount')}/"
        f"{current_leaf.get('rootTableWindowDirectTextRefCount')}",
        f"- route-pair direct pointer promotes route: {current_leaf.get('routePairIndexSourceDirectPointerRefPromotesRoute')}",
        f"- diagnostic wrapper proof/status/recheck: `{current_leaf.get('diagnosticWrapperProofStatus')}` / "
        f"{current_leaf.get('diagnosticLeftStabilityRouteSelectorHitCount')}/"
        f"{current_leaf.get('diagnosticLeftStabilityRecheckRouteSelectorHitCount')}",
    ])
    predecessor = next(
        (row for row in summary.get("proofPackages") or [] if row.get("id") == "predecessor-fill-order-proof"),
        {},
    )
    lines.extend([
        "",
        "## Predecessor Fill Packet",
        "",
        f"- proof packet: `{predecessor.get('proofPacketUrl')}`",
        f"- selector path: `{predecessor.get('predecessorSelector')}` -> `{predecessor.get('currentSelector')}`",
        f"- fill sites: {predecessor.get('fillSites')}",
        f"- current reader: `{predecessor.get('currentReaderHex')}`",
        f"- blocked gate ids: `{', '.join(predecessor.get('proofPacketBlockedIds') or [])}`",
        f"- missing evidence count: {len(predecessor.get('missingEvidence') or [])}",
        f"- evidence refs: {predecessor.get('proofPacketEvidenceRefCount')}",
    ])
    predecessor_runtime = predecessor.get("runtimeObservationSummary") or {}
    lines.extend([
        f"- runtime observation classification: `{predecessor_runtime.get('classification')}`",
        f"- runtime poll/sequence/sample: {predecessor_runtime.get('pollCount')}/"
        f"{predecessor_runtime.get('sequenceCount')}/{predecessor_runtime.get('sampleCount')}",
        f"- public/current/route hits: {predecessor_runtime.get('publicPredecessorHitCount')}/"
        f"{predecessor_runtime.get('currentRootHitCount')}/{predecessor_runtime.get('routeSelectorHitCount')}",
        f"- all-zero/fill matches: {predecessor_runtime.get('allZeroCount')}/"
        f"{predecessor_runtime.get('fillMatchCount')}",
        f"- accepted signal present: {predecessor_runtime.get('acceptedSignalPresent')}",
        f"- target observation status: `{predecessor_runtime.get('targetObservationStatus')}`",
    ])
    selector_merge = next(
        (row for row in summary.get("proofPackages") or [] if row.get("id") == "selector-merge-proof"),
        {},
    )
    lines.extend([
        "",
        "## Selector Merge Packet",
        "",
        f"- proof packet: `{selector_merge.get('proofPacketUrl')}`",
        f"- proof found: {selector_merge.get('proofFound')}",
        f"- selectorMergeExternalProofFound: {selector_merge.get('selectorMergeExternalProofFound')}",
        f"- blocked gate ids: `{', '.join(selector_merge.get('proofPacketBlockedIds') or [])}`",
        f"- missing evidence count: {len(selector_merge.get('missingEvidence') or [])}",
        f"- evidence refs: {selector_merge.get('proofPacketEvidenceRefCount')}",
        f"- shape current=predecessor+source / union covers current: {selector_merge.get('currentEqualsPredecessorPlusSource')}/"
        f"{selector_merge.get('sourcePredecessorUnionCoversCurrent')}",
        f"- mergeShapeOnly: {selector_merge.get('mergeShapeOnly')}",
        f"- selectorMergeGapOpen / routeOrderProven: {selector_merge.get('selectorMergeGapOpen')}/"
        f"{selector_merge.get('routeOrderProven')}",
        f"- source/predecessor/forward bridge hits: {selector_merge.get('sourceToCurrentBridgeHitCount')}/"
        f"{selector_merge.get('predecessorToCurrentHitCount')}/{selector_merge.get('forwardMergeBridgeHitCount')}",
        f"- current-to-predecessor before-fill only: {selector_merge.get('currentToPredecessorBeforeFillHitCount')} / "
        f"{selector_merge.get('currentPredecessorHitsBeforeFillOnly')}",
    ])
    opcode20 = next(
        (row for row in summary.get("proofPackages") or [] if row.get("id") == "opcode20-gate-base-proof"),
        {},
    )
    lines.extend([
        "",
        "## Opcode 0x20 Gate Base Packet",
        "",
        f"- proof packet: `{opcode20.get('proofPacketUrl')}`",
        f"- proof found: {opcode20.get('proofFound')}",
        f"- opcode20GateBaseExternalProofFound: {opcode20.get('opcode20GateBaseExternalProofFound')}",
        f"- blocked gate ids: `{', '.join(opcode20.get('proofPacketBlockedIds') or [])}`",
        f"- missing evidence count: {len(opcode20.get('missingEvidence') or [])}",
        f"- evidence refs: {opcode20.get('proofPacketEvidenceRefCount')}",
        f"- writer/gates: `{opcode20.get('currentWriterVaHex')}` -> `{opcode20.get('firstGateVaHex')}`, `{opcode20.get('secondGateVaHex')}`",
        f"- opcode20 candidate/mode: `{opcode20.get('opcode20CandidateVaHex')}` / `{opcode20.get('opcode20CurrentMode')}`",
        f"- only opcode20 base candidate: {opcode20.get('gateWindowOnlyOpcode20BaseCandidate')}",
        f"- active order/gate-time proof: {opcode20.get('activeOrderProofFound')}/"
        f"{opcode20.get('gateTimeBaseProofFound')}",
        f"- activeOrderOnlyProofEliminated: {opcode20.get('activeOrderOnlyProofEliminated')}",
        f"- descriptor all-script rows/specific base: {opcode20.get('descriptorAllScriptSelectionOpcodeCount')}/"
        f"{opcode20.get('descriptorAllScriptSpecificGateBaseProven')}",
        f"- context+0xf2 object pointer proven/required: {opcode20.get('contextF2SpecificRuntimeObjectPointerProven')}/"
        f"{opcode20.get('contextF2RuntimeObjectTableStateRequired')}",
        f"- diagnostic/public predecessor active-order samples: {opcode20.get('diagnosticActiveOrderSampleCount')}/"
        f"{opcode20.get('publicPredecessorActiveOrderSampleCount')}",
    ])
    opcode24 = next(
        (row for row in summary.get("proofPackages") or [] if row.get("id") == "opcode24-runtime-producer-proof"),
        {},
    )
    lines.extend([
        "",
        "## Opcode 0x24 Runtime Producer Packet",
        "",
        f"- proof packet: `{opcode24.get('proofPacketUrl')}`",
        f"- mode1 source/read: `{opcode24.get('mode1SourceHex')}` / `{opcode24.get('mode1ReadVaHex')}`",
        f"- opcode24 boundary: `{opcode24.get('opcode24BoundaryVaHex')}`",
        f"- proof found: {opcode24.get('proofFound')}",
        f"- blocked gate ids: `{', '.join(opcode24.get('proofPacketBlockedIds') or [])}`",
        f"- missing evidence count: {len(opcode24.get('missingEvidence') or [])}",
        f"- runtime classification: `{opcode24.get('runtimeClassification')}`",
        f"- mode1 source nonzero observed: {opcode24.get('mode1SourceNonzeroObserved')}",
    ])
    lines.extend(["", "## Regenerate And Verify", ""])
    lines.extend(f"- `{cmd}`" for cmd in summary.get("regenerateAndVerifyCommands") or [])
    lines.extend(["", "## Verification Checklist", "", "| requirement | evidence | signal | current status |", "| --- | --- | --- | --- |"])
    for row in summary.get("verificationChecklist") or []:
        lines.append(
            f"| {row.get('requirement')} | `{row.get('currentEvidence')}` | {row.get('requiredSignal')} | "
            f"{row.get('currentStatus')} |"
        )
    lines.extend(["", "## Not Accepted Evidence", ""])
    lines.extend(f"- {item}" for item in summary.get("notAcceptedEvidence") or [])
    lines.extend(["", summary.get("conclusion") or "", ""])
    return "\n".join(lines)


def html_page(summary: dict) -> str:
    def esc(value: Any) -> str:
        return html.escape(str(value))

    def html_link_or_status(label: str, href: str | None, status: str | None = None) -> str:
        if href:
            return f'<a href="{esc(href)}">{esc(label)}</a>'
        return f'{esc(label)} <span class="muted">({esc(status or "not generated")})</span>'

    package_rows = []
    for package in summary.get("proofPackages") or []:
        signals = "<br>".join(esc(item) for item in package.get("successSignals") or [])
        package_rows.append(
            "<tr>"
            f"<td><code>{esc(package.get('id'))}</code></td>"
            f"<td>{esc(package.get('status'))}</td>"
            f"<td><code>{esc(package.get('primaryGate'))}</code></td>"
            f"<td>{signals}</td>"
            "</tr>"
        )
    checklist_rows = []
    for row in summary.get("verificationChecklist") or []:
        checklist_rows.append(
            "<tr>"
            f"<td>{esc(row.get('requirement'))}</td>"
            f"<td><code>{esc(row.get('currentEvidence'))}</code></td>"
            f"<td>{esc(row.get('requiredSignal'))}</td>"
            f"<td>{esc(row.get('currentStatus'))}</td>"
            "</tr>"
        )
    external_input_rows = []
    for row in summary.get("externalInputChecklist") or []:
        external_input_rows.append(
            "<tr>"
            f"<td><code>{esc(row.get('id'))}</code></td>"
            f"<td>{esc(row.get('neededInput'))}</td>"
            f"<td>{esc(row.get('currentState'))}</td>"
            f"<td>{esc(row.get('acceptedSignal'))}</td>"
            f"<td><code>{esc(row.get('refresh'))}</code></td>"
            "</tr>"
        )
    packages_by_id = {row.get("id"): row for row in summary.get("proofPackages") or []}
    runtime = packages_by_id.get("runtime-trace-or-equivalent-selected-root-proof") or {}
    savedata = packages_by_id.get("captured-selector-2-0-savedata") or {}
    strict = packages_by_id.get("strict-source-hotspot-review") or {}
    selected = packages_by_id.get("selected-root-execution-proof") or {}
    current_leaf = packages_by_id.get("current-leaf-wrapper-proof") or {}
    predecessor = packages_by_id.get("predecessor-fill-order-proof") or {}
    selector_merge = packages_by_id.get("selector-merge-proof") or {}
    opcode20 = packages_by_id.get("opcode20-gate-base-proof") or {}
    opcode24 = packages_by_id.get("opcode24-runtime-producer-proof") or {}
    predecessor_runtime = predecessor.get("runtimeObservationSummary") or {}
    trace_rows = []
    for row in runtime.get("tracePoints") or []:
        trace_rows.append(
            "<tr>"
            f"<td>{esc(row.get('name'))}</td>"
            f"<td>{esc(row.get('kind'))}</td>"
            f"<td><code>{esc(row.get('addressHex'))}</code></td>"
            f"<td>{esc(row.get('purpose'))}</td>"
            "</tr>"
        )
    runtime_blockers = "".join(f"<li>{esc(item)}</li>" for item in runtime.get("blockers") or ["none"])
    commands = "".join(f"<li><code>{esc(cmd)}</code></li>" for cmd in summary.get("regenerateAndVerifyCommands") or [])
    not_accepted = "".join(f"<li>{esc(item)}</li>" for item in summary.get("notAcceptedEvidence") or [])
    next_required_inputs = "".join(f"<li>{esc(item)}</li>" for item in summary.get("nextRequiredInputs") or [])
    return "\n".join([
        "<!doctype html>",
        '<html lang="en">',
        "<head>",
        '  <meta charset="utf-8">',
        '  <meta name="viewport" content="width=device-width, initial-scale=1">',
        "  <title>Route Promotion External Proof Handoff</title>",
        "  <style>body{margin:24px;background:#101010;color:#eee;font:14px system-ui,sans-serif}table{border-collapse:collapse;width:100%;margin:16px 0 28px}th,td{border:1px solid #333;padding:6px 8px;vertical-align:top}th{background:#1d1d1d}code{color:#f5d76e}.muted{color:#aaa}</style>",
        "</head>",
        "<body>",
        "  <h1>Route Promotion External Proof Handoff</h1>",
        f"  <p>route <code>{esc(summary['source'])}</code> -&gt; <code>{esc(summary['target'])}</code>; "
        f"achieved {esc(summary.get('achieved'))}; route promotion allowed {esc(summary.get('routePromotionAllowed'))}; "
        f"promotion status: {esc(summary.get('promotionStatus'))}.</p>",
        f"  <p>failed gates: <code>{esc(', '.join(summary.get('failedGateIds') or []))}</code>.</p>",
        "  <h2>Next Required Inputs</h2>",
        f"  <ul>{next_required_inputs}</ul>",
        "  <h2>External Proof Template</h2>",
        f"  <p>Template files: <a href=\"{esc(summary.get('proofTemplateUrl'))}\">"
        f"{esc(summary.get('proofTemplateUrl'))}</a>, "
        f"<a href=\"{esc(summary.get('proofTemplateJsonUrl'))}\">"
        f"{esc(summary.get('proofTemplateJsonUrl'))}</a>. "
        f"Validation output: <a href=\"{esc(summary.get('proofValidationUrl'))}\">"
        f"{esc(summary.get('proofValidationUrl'))}</a>, "
        f"<a href=\"{esc(summary.get('proofValidationJsonUrl'))}\">"
        f"{esc(summary.get('proofValidationJsonUrl'))}</a>. "
        f"Validate submitted record with <code>{esc(summary.get('proofValidationCommand'))}</code>; "
        f"use <code>{esc(summary.get('proofValidationRequireAcceptedCommand'))}</code> to fail when no record is accepted. "
        f"Use <code>{esc(summary.get('proofValidationRefreshCommand'))}</code> to validate a submitted record while refreshing the route-proof reports. "
        "This is template only; it is not accepted as proof until a filled external record satisfies one accepted signal.</p>",
        "  <h2>Proof Packages</h2>",
        "  <table><thead><tr><th>id</th><th>status</th><th>primary gate</th><th>success signals</th></tr></thead>",
        f"  <tbody>{''.join(package_rows)}</tbody></table>",
        "  <h2>Required External Inputs</h2>",
        "  <table><thead><tr><th>id</th><th>needed input</th><th>current state</th><th>accepted signal</th><th>refresh</th></tr></thead>",
        f"  <tbody>{''.join(external_input_rows)}</tbody></table>",
        "  <h2>Runtime Trace Points</h2>",
        f"  <p>report <a href=\"{esc(runtime.get('reportUrl'))}\">{esc(runtime.get('reportUrl'))}</a>; "
        f"execution probe <a href=\"{esc(runtime.get('executionProbeUrl'))}\">{esc(runtime.get('executionProbeUrl'))}</a>.</p>",
        f"  <p>deduped blocker count {esc(runtime.get('dedupedBlockerCount'))}; "
        f"raw blocker count {esc(runtime.get('rawBlockerCount'))}.</p>",
        f"  <ul>{runtime_blockers}</ul>",
        "  <table><thead><tr><th>name</th><th>kind</th><th>address</th><th>purpose</th></tr></thead>",
        f"  <tbody>{''.join(trace_rows)}</tbody></table>",
        "  <h2>Captured Savedata Intake</h2>",
        f"  <p>report {html_link_or_status('real savedata evidence gap', savedata.get('reportUrl'), savedata.get('reportStatus'))}; "
        f"slot scan {html_link_or_status('SAVEDATA slot scan', savedata.get('slotScanUrl'), savedata.get('slotScanStatus'))}; "
        f"browser scan <a href=\"{esc(savedata.get('webScanUrl'))}\"><code>{esc(savedata.get('webScanUrl'))}</code></a>; expected selector "
        f"<code>{esc(savedata.get('expectedSelector'))}</code>; expected selected pointer "
        f"<code>{esc(savedata.get('expectedSelectedPointerHex'))}</code>.</p>",
        f"  <p>intake readmes <code>{esc(', '.join(savedata.get('intakeReadmePaths') or []))}</code>; "
        f"gitignore guardrails <code>{esc(', '.join(savedata.get('gitignoreGuardrails') or []))}</code>; "
        f"one-command refresh <code>{esc(savedata.get('refreshCommand'))}</code>.</p>",
        f"  <p>diagnostic exclusion policy: {esc((savedata.get('diagnosticExclusionPolicy') or {}).get('note'))}; "
        f"path markers <code>{esc(', '.join((savedata.get('diagnosticExclusionPolicy') or {}).get('pathMarkers') or []))}</code>; "
        f"synthetic diagnostic excluded {esc((savedata.get('currentState') or {}).get('syntheticDiagnosticExcluded'))}; "
        f"local slot scan synthetic diagnostics {esc((savedata.get('currentState') or {}).get('localSlotScanSyntheticDiagnosticCount'))}.</p>",
        "  <h2>Strict Hotspot Review Packet</h2>",
        f"  <p>review packet <a href=\"{esc(strict.get('reviewPacketUrl'))}\">{esc(strict.get('reviewPacketUrl'))}</a>; "
        f"proof found {esc(strict.get('proofFound'))}; "
        "failed strict-source hotspot review gates "
        f"<code>{esc(', '.join(strict.get('reviewPacketBlockedIds') or []))}</code>; "
        f"missing evidence count {esc(len(strict.get('missingEvidence') or []))}; "
        f"evidence refs {esc(strict.get('reviewPacketEvidenceRefCount'))}; "
        f"candidate count {esc(strict.get('reviewPacketCandidateCount'))}; "
        f"candidate sides <code>{esc(','.join(strict.get('reviewPacketCandidateSides') or []))}</code>.</p>",
        "  <h2>Selected Root Execution Packet</h2>",
        f"  <p>proof packet <a href=\"{esc(selected.get('proofPacketUrl'))}\">{esc(selected.get('proofPacketUrl'))}</a>; "
        f"proof found {esc(selected.get('proofFound'))}; "
        f"subgates {esc(selected.get('proofPacketNonPromotingSubgateCount'))}/"
        f"{esc(selected.get('proofPacketSubgateCount'))} non-promoting; "
        "failed selected-root external gates "
        f"<code>{esc(', '.join(selected.get('proofPacketBlockedIds') or []))}</code>; "
        f"missing evidence count {esc(len(selected.get('missingEvidence') or []))}; "
        f"evidence refs {esc(selected.get('proofPacketEvidenceRefCount'))}; "
        f"route-pair entry indices <code>{esc(selected.get('proofPacketRoutePairEntryIndices'))}</code>; "
        f"negative reader entry indices <code>{esc(selected.get('proofPacketNegativeReaderEntryIndices'))}</code>.</p>",
        "  <h2>Current Leaf Wrapper Packet</h2>",
        f"  <p>proof packet <a href=\"{esc(current_leaf.get('proofPacketUrl'))}\">"
        f"{esc(current_leaf.get('proofPacketUrl'))}</a>; proof found "
        f"{esc(current_leaf.get('proofFound'))}; currentLeafWrapperExternalProofFound "
        f"{esc(current_leaf.get('currentLeafWrapperExternalProofFound'))}; blocked ids "
        f"<code>{esc(', '.join(current_leaf.get('proofPacketBlockedIds') or []))}</code>; "
        f"missing evidence count {esc(len(current_leaf.get('missingEvidence') or []))}; "
        f"evidence refs {esc(current_leaf.get('proofPacketEvidenceRefCount'))}.</p>",
        f"  <p>current selector/root/table <code>{esc(current_leaf.get('currentSelector'))}</code> / "
        f"<code>{esc(current_leaf.get('currentRootHex'))}</code> / "
        f"<code>{esc(current_leaf.get('rootTablePointerHex'))}</code>; wrapper "
        f"<code>{esc(current_leaf.get('wrapperEntryHex'))}</code> / "
        f"<code>{esc(current_leaf.get('wrapperDescriptorHex'))}</code> / "
        f"<code>{esc(current_leaf.get('wrapperChildPointerHex'))}</code>; frontier "
        f"<code>{esc(current_leaf.get('frontierLeafHex'))}</code> / "
        f"<code>{esc(current_leaf.get('frontierReaderHex'))}</code>.</p>",
        f"  <p>route-pair entry indices <code>{esc(current_leaf.get('routePairEntryIndices'))}</code>; "
        f"corrected trace entry indices <code>{esc(current_leaf.get('routePairCorrectedTraceEntryIndices'))}</code>; "
        f"negative reader entry indices <code>{esc(current_leaf.get('negativeReaderEntryIndices'))}</code>; "
        f"corrected trace reader count/all {esc(current_leaf.get('correctedTraceReachesReaderCount'))}/"
        f"{esc(current_leaf.get('correctedTraceAllRoutePairDescriptorsReachReader'))}; "
        f"nonnegative selectable/corrected reachable "
        f"{esc(current_leaf.get('frontierReaderSelectableByNonNegativeIndex'))}/"
        f"{esc(current_leaf.get('frontierReaderReachableByCorrectedNonNegativeIndex'))}; status "
        f"<code>{esc(current_leaf.get('correctedTraceNormalSelectionGapStatus'))}</code>.</p>",
        f"  <p>route/index/wrapper/current-leaf/current-selector-leaf proofs "
        f"{esc(current_leaf.get('routePairEntryExecutionProven'))}/"
        f"{esc(current_leaf.get('routePairIndexSourceProofFound'))}/"
        f"{esc(current_leaf.get('wrapperExecutionProofFound'))}/"
        f"{esc(current_leaf.get('currentLeafSelectionProofFound'))}/"
        f"{esc(current_leaf.get('currentSelectorLeafExecutionProofFound'))}; rootTableWindowDirectRefCount/text "
        f"{esc(current_leaf.get('rootTableWindowDirectRefCount'))}/"
        f"{esc(current_leaf.get('rootTableWindowDirectTextRefCount'))}; direct pointer promotes route "
        f"{esc(current_leaf.get('routePairIndexSourceDirectPointerRefPromotesRoute'))}; diagnostic "
        f"<code>{esc(current_leaf.get('diagnosticWrapperProofStatus'))}</code> "
        f"{esc(current_leaf.get('diagnosticLeftStabilityRouteSelectorHitCount'))}/"
        f"{esc(current_leaf.get('diagnosticLeftStabilityRecheckRouteSelectorHitCount'))}.</p>",
        "  <h2>Predecessor Fill Packet</h2>",
        f"  <p>proof packet <a href=\"{esc(predecessor.get('proofPacketUrl'))}\">{esc(predecessor.get('proofPacketUrl'))}</a>; "
        f"selector path <code>{esc(predecessor.get('predecessorSelector'))}</code> -&gt; "
        f"<code>{esc(predecessor.get('currentSelector'))}</code>; fill sites "
        f"<code>{esc(predecessor.get('fillSites'))}</code>; blocked ids "
        f"<code>{esc(', '.join(predecessor.get('proofPacketBlockedIds') or []))}</code>; "
        f"missing evidence count {esc(len(predecessor.get('missingEvidence') or []))}; "
        f"evidence refs {esc(predecessor.get('proofPacketEvidenceRefCount'))}.</p>",
        f"  <p>runtime observation classification <code>{esc(predecessor_runtime.get('classification'))}</code>; "
        f"poll/sequence/sample {esc(predecessor_runtime.get('pollCount'))}/"
        f"{esc(predecessor_runtime.get('sequenceCount'))}/{esc(predecessor_runtime.get('sampleCount'))}; "
        f"public/current/route hits {esc(predecessor_runtime.get('publicPredecessorHitCount'))}/"
        f"{esc(predecessor_runtime.get('currentRootHitCount'))}/{esc(predecessor_runtime.get('routeSelectorHitCount'))}; "
        f"all-zero/fill matches {esc(predecessor_runtime.get('allZeroCount'))}/"
        f"{esc(predecessor_runtime.get('fillMatchCount'))}; accepted signal present "
        f"{esc(predecessor_runtime.get('acceptedSignalPresent'))}; target observation status "
        f"<code>{esc(predecessor_runtime.get('targetObservationStatus'))}</code>.</p>",
        "  <h2>Selector Merge Packet</h2>",
        f"  <p>proof packet <a href=\"{esc(selector_merge.get('proofPacketUrl'))}\">"
        f"{esc(selector_merge.get('proofPacketUrl'))}</a>; proof found "
        f"{esc(selector_merge.get('proofFound'))}; selectorMergeExternalProofFound "
        f"{esc(selector_merge.get('selectorMergeExternalProofFound'))}; blocked ids "
        f"<code>{esc(', '.join(selector_merge.get('proofPacketBlockedIds') or []))}</code>; "
        f"missing evidence count {esc(len(selector_merge.get('missingEvidence') or []))}; "
        f"evidence refs {esc(selector_merge.get('proofPacketEvidenceRefCount'))}.</p>",
        f"  <p>shape current=predecessor+source {esc(selector_merge.get('currentEqualsPredecessorPlusSource'))}; "
        f"union covers current {esc(selector_merge.get('sourcePredecessorUnionCoversCurrent'))}; "
        f"mergeShapeOnly {esc(selector_merge.get('mergeShapeOnly'))}; selectorMergeGapOpen "
        f"{esc(selector_merge.get('selectorMergeGapOpen'))}; routeOrderProven "
        f"{esc(selector_merge.get('routeOrderProven'))}.</p>",
        f"  <p>source/predecessor/forward bridge hits "
        f"{esc(selector_merge.get('sourceToCurrentBridgeHitCount'))}/"
        f"{esc(selector_merge.get('predecessorToCurrentHitCount'))}/"
        f"{esc(selector_merge.get('forwardMergeBridgeHitCount'))}; current-to-predecessor before-fill only "
        f"{esc(selector_merge.get('currentToPredecessorBeforeFillHitCount'))}/"
        f"{esc(selector_merge.get('currentPredecessorHitsBeforeFillOnly'))}.</p>",
        "  <h2>Opcode 0x20 Gate Base Packet</h2>",
        f"  <p>proof packet <a href=\"{esc(opcode20.get('proofPacketUrl'))}\">"
        f"{esc(opcode20.get('proofPacketUrl'))}</a>; proof found "
        f"{esc(opcode20.get('proofFound'))}; opcode20GateBaseExternalProofFound "
        f"{esc(opcode20.get('opcode20GateBaseExternalProofFound'))}; blocked ids "
        f"<code>{esc(', '.join(opcode20.get('proofPacketBlockedIds') or []))}</code>; "
        f"missing evidence count {esc(len(opcode20.get('missingEvidence') or []))}; "
        f"evidence refs {esc(opcode20.get('proofPacketEvidenceRefCount'))}.</p>",
        f"  <p>writer/gates <code>{esc(opcode20.get('currentWriterVaHex'))}</code> -&gt; "
        f"<code>{esc(opcode20.get('firstGateVaHex'))}</code>, "
        f"<code>{esc(opcode20.get('secondGateVaHex'))}</code>; opcode20 candidate "
        f"<code>{esc(opcode20.get('opcode20CandidateVaHex'))}</code>; mode "
        f"<code>{esc(opcode20.get('opcode20CurrentMode'))}</code>; only opcode20 base candidate "
        f"{esc(opcode20.get('gateWindowOnlyOpcode20BaseCandidate'))}.</p>",
        f"  <p>active order/gate-time proof {esc(opcode20.get('activeOrderProofFound'))}/"
        f"{esc(opcode20.get('gateTimeBaseProofFound'))}; activeOrderOnlyProofEliminated "
        f"{esc(opcode20.get('activeOrderOnlyProofEliminated'))}; descriptor all-script rows/specific base "
        f"{esc(opcode20.get('descriptorAllScriptSelectionOpcodeCount'))}/"
        f"{esc(opcode20.get('descriptorAllScriptSpecificGateBaseProven'))}; context+0xf2 object pointer proven/required "
        f"{esc(opcode20.get('contextF2SpecificRuntimeObjectPointerProven'))}/"
        f"{esc(opcode20.get('contextF2RuntimeObjectTableStateRequired'))}; diagnostic/public predecessor active-order samples "
        f"{esc(opcode20.get('diagnosticActiveOrderSampleCount'))}/"
        f"{esc(opcode20.get('publicPredecessorActiveOrderSampleCount'))}.</p>",
        "  <h2>Opcode 0x24 Runtime Producer Packet</h2>",
        f"  <p>proof packet <a href=\"{esc(opcode24.get('proofPacketUrl'))}\">{esc(opcode24.get('proofPacketUrl'))}</a>; "
        f"mode1 source <code>{esc(opcode24.get('mode1SourceHex'))}</code>; read "
        f"<code>{esc(opcode24.get('mode1ReadVaHex'))}</code>; classification "
        f"<code>{esc(opcode24.get('runtimeClassification'))}</code>; nonzero observed "
        f"{esc(opcode24.get('mode1SourceNonzeroObserved'))}; proof found "
        f"{esc(opcode24.get('proofFound'))}; blocked ids "
        f"<code>{esc(', '.join(opcode24.get('proofPacketBlockedIds') or []))}</code>; "
        f"missing evidence count {esc(len(opcode24.get('missingEvidence') or []))}.</p>",
        "  <h2>Regenerate And Verify</h2>",
        f"  <ul>{commands}</ul>",
        "  <h2>Verification Checklist</h2>",
        "  <table><thead><tr><th>requirement</th><th>evidence</th><th>signal</th><th>current status</th></tr></thead>",
        f"  <tbody>{''.join(checklist_rows)}</tbody></table>",
        "  <h2>Not Accepted Evidence</h2>",
        f"  <ul>{not_accepted}</ul>",
        f"  <p>{esc(summary.get('conclusion'))}</p>",
        "</body>",
        "</html>",
        "",
    ])


def template_markdown(template: dict) -> str:
    lines = [
        "# Route Promotion External Proof Template",
        "",
        f"- schema version: `{template.get('schemaVersion')}`",
        f"- template status: `{template.get('templateStatus')}`",
        f"- route: `{SOURCE}` -> `{TARGET}`",
        f"- handoff: `{template.get('handoffUrl')}`",
        f"- completion audit: `{template.get('completionAuditUrl')}`",
        f"- validation command: `{template.get('validationCommand')}`",
        f"- require accepted command: `{template.get('requireAcceptedValidationCommand')}`",
        f"- validate and refresh command: `{template.get('validationRefreshCommand')}`",
        "",
        template.get("purpose") or "",
        "",
        "## Required Input Records",
        "",
    ]
    for row in template.get("requiredInputs") or []:
        lines.extend([
            f"### {row.get('id')}",
            "",
            f"- package: `{row.get('proofPackageId')}`",
            f"- artifact kind: {row.get('artifactKind')}",
            f"- accepted signal: {row.get('acceptedSignal')}",
            "- submit by:",
        ])
        lines.extend(f"  - {item}" for item in row.get("submitBy") or [])
        if row.get("refreshCommand"):
            lines.append(f"- refresh: `{row.get('refreshCommand')}`")
        if row.get("refreshCommands"):
            lines.append("- refresh commands:")
            lines.extend(f"  - `{item}`" for item in row.get("refreshCommands") or [])
        lines.append("- required checks:")
        lines.extend(f"  - `{item}`" for item in row.get("requiredChecks") or [])
        if row.get("acceptedTracePoints"):
            lines.append("- accepted trace points:")
            lines.extend(
                f"  - `{point.get('addressHex')}` {point.get('name')} ({point.get('kind')})"
                for point in row.get("acceptedTracePoints") or []
            )
        if row.get("candidateSides"):
            lines.append(f"- candidate sides: `{', '.join(row.get('candidateSides') or [])}`")
        lines.extend([
            "- example record:",
            "```json",
            json.dumps(row.get("exampleRecord") or {}, ensure_ascii=False, indent=2),
            "```",
            "",
        ])
    lines.extend([
        "## Not Accepted Evidence",
        "",
    ])
    lines.extend(f"- {item}" for item in template.get("notAcceptedEvidence") or [])
    return "\n".join(lines) + "\n"


def template_html(template: dict) -> str:
    esc = lambda value: html.escape(str(value))
    sections = []
    for row in template.get("requiredInputs") or []:
        submit = "".join(f"<li>{esc(item)}</li>" for item in row.get("submitBy") or [])
        checks = "".join(f"<li><code>{esc(item)}</code></li>" for item in row.get("requiredChecks") or [])
        commands = ""
        if row.get("refreshCommand"):
            commands = f"<p>refresh <code>{esc(row.get('refreshCommand'))}</code></p>"
        if row.get("refreshCommands"):
            commands = "<ul>" + "".join(
                f"<li><code>{esc(item)}</code></li>" for item in row.get("refreshCommands") or []
            ) + "</ul>"
        trace_points = ""
        if row.get("acceptedTracePoints"):
            trace_points = "<p>accepted trace points: " + ", ".join(
                f"<code>{esc(point.get('addressHex'))}</code> {esc(point.get('name'))}"
                for point in row.get("acceptedTracePoints") or []
            ) + "</p>"
        candidate_sides = ""
        if row.get("candidateSides"):
            candidate_sides = f"<p>candidate sides: <code>{esc(', '.join(row.get('candidateSides') or []))}</code></p>"
        sections.append(
            "<section>"
            f"<h2>{esc(row.get('id'))}</h2>"
            f"<p>package <code>{esc(row.get('proofPackageId'))}</code>; "
            f"artifact kind {esc(row.get('artifactKind'))}</p>"
            f"<p>accepted signal: {esc(row.get('acceptedSignal'))}</p>"
            f"<h3>Submit By</h3><ul>{submit}</ul>"
            f"{commands}"
            f"<h3>Required Checks</h3><ul>{checks}</ul>"
            f"{trace_points}{candidate_sides}"
            f"<h3>Example Record</h3><pre>{esc(json.dumps(row.get('exampleRecord') or {}, ensure_ascii=False, indent=2))}</pre>"
            "</section>"
        )
    not_accepted = "".join(f"<li>{esc(item)}</li>" for item in template.get("notAcceptedEvidence") or [])
    return "\n".join([
        "<!doctype html>",
        '<html lang="en">',
        "<head>",
        '  <meta charset="utf-8">',
        '  <meta name="viewport" content="width=device-width, initial-scale=1">',
        "  <title>Route Promotion External Proof Template</title>",
        "  <style>body{margin:24px;background:#101010;color:#eee;font:14px system-ui,sans-serif}section{border-top:1px solid #333;margin-top:20px;padding-top:16px}code{color:#f5d76e}pre{background:#181818;border:1px solid #333;padding:12px;white-space:pre-wrap}</style>",
        "</head>",
        "<body>",
        "  <h1>Route Promotion External Proof Template</h1>",
        f"  <p>schema version <code>{esc(template.get('schemaVersion'))}</code>; "
        f"template status <code>{esc(template.get('templateStatus'))}</code>; "
        f"route <code>{SOURCE}</code> -&gt; <code>{TARGET}</code>.</p>",
        f"  <p>{esc(template.get('purpose'))}</p>",
        f"  <p>handoff <a href=\"{esc(template.get('handoffUrl'))}\">{esc(template.get('handoffUrl'))}</a>; "
        f"completion audit <a href=\"{esc(template.get('completionAuditUrl'))}\">{esc(template.get('completionAuditUrl'))}</a>.</p>",
        f"  <p>validation command <code>{esc(template.get('validationCommand'))}</code>; "
        f"require accepted command <code>{esc(template.get('requireAcceptedValidationCommand'))}</code>; "
        f"validate and refresh command <code>{esc(template.get('validationRefreshCommand'))}</code>.</p>",
        *sections,
        "  <h2>Not Accepted Evidence</h2>",
        f"  <ul>{not_accepted}</ul>",
        "</body>",
        "</html>",
        "",
    ])


def write_outputs(summary: dict, out_dir: Path = OUT) -> None:
    out_dir.mkdir(parents=True, exist_ok=True)
    template = proof_template(summary)
    (out_dir / "route_promotion_external_proof_handoff.json").write_text(
        json.dumps(summary, ensure_ascii=False, indent=2) + "\n",
        encoding="utf-8",
    )
    (out_dir / "route_promotion_external_proof_handoff.html").write_text(html_page(summary), encoding="utf-8")
    (out_dir / "route_promotion_external_proof_template.json").write_text(
        json.dumps(template, ensure_ascii=False, indent=2) + "\n",
        encoding="utf-8",
    )
    (out_dir / "route_promotion_external_proof_template.html").write_text(
        template_html(template),
        encoding="utf-8",
    )


def main() -> None:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.parse_args()
    summary = build_summary()
    write_outputs(summary)
    print(f"wrote external proof handoff -> {OUT / 'route_promotion_external_proof_handoff.html'}")


if __name__ == "__main__":
    main()
