#!/usr/bin/env python3
"""Build an external proof packet for the current leaf/wrapper execution 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"
CURRENT_LEAF_WRAPPER_EXTERNAL_EVIDENCE_REFS = [
    {
        "path": "out/save_selector_wrapper_execution_gap.json",
        "fields": [
            "proofFound",
            "failedWrapperGateIds",
            "missingEvidence",
            "wrapperExecutionProofFound",
            "currentLeafSelectionProofFound",
            "currentSelectorLeafExecutionProofFound",
            "evidenceRefs",
            "evidenceRefCount",
        ],
    },
    {
        "path": "out/save_selector_route_pair_entry_execution_gap.json",
        "fields": [
            "proofFound",
            "failedRoutePairEntryGateIds",
            "missingEvidence",
            "routePairEntryExecutionProven",
            "selectedRootExecutionRefFound",
            "wrapperExecutionProofFound",
            "routePairEntryIndices",
            "negativeReaderEntryIndices",
            "evidenceRefs",
            "evidenceRefCount",
        ],
    },
    {
        "path": "out/save_selector_route_pair_index_source_gap.json",
        "fields": [
            "proofFound",
            "failedRoutePairIndexSourceGateIds",
            "missingEvidence",
            "routePairEntryIndices",
            "negativeReaderEntryIndices",
            "evidenceRefs",
            "evidenceRefCount",
        ],
    },
    {
        "path": "out/save_selector_selected_root_execution_gap.json",
        "fields": [
            "proofFound",
            "failedSelectedRootGateIds",
            "missingEvidence",
            "selectedRootExecutionRefFound",
            "selectedRootExecutionRejectionClassification",
            "evidenceRefs",
            "evidenceRefCount",
        ],
    },
    {
        "path": "out/save_selector_leaf_table_context.json",
        "fields": [
            "proofFound",
            "failedLeafTableGateIds",
            "missingEvidence",
            "frontierLeafRefIsDirectRootTableEntry",
            "runtimeSelectionProven",
            "evidenceRefs",
            "evidenceRefCount",
        ],
    },
    {
        "path": "out/save_selector_leaf_index_space.json",
        "fields": [
            "proofFound",
            "failedLeafIndexGateIds",
            "missingEvidence",
            "frontierReaderSelectableByNonNegativeIndex",
            "frontierReaderReachableByCorrectedNonNegativeIndex",
            "correctedTraceAllRoutePairDescriptorsReachReader",
            "evidenceRefs",
            "evidenceRefCount",
        ],
    },
    {
        "path": "out/save_selector_leaf_table_global_context.json",
        "fields": [
            "currentSelectorRoutePairIndices",
            "currentFrontierLeafOnlyNegative",
            "selectorTableCount",
            "fieldEntryRowCount",
            "runtimeSelectionProven",
            "evidenceRefs",
            "evidenceRefCount",
        ],
    },
    {
        "path": "out/save_selector_route_pair_descriptor_context.json",
        "fields": [
            "proofFound",
            "missingEvidence",
            "frontierReaderSelectableByNonNegativeIndex",
            "frontierReaderReachableByCorrectedNonNegativeIndex",
            "readerBearingNegativeIndices",
            "runtimeSelectionProven",
            "evidenceRefs",
            "evidenceRefCount",
        ],
    },
    {
        "path": "out/save_selector_opcode2c_route_pair_context.json",
        "fields": [
            "proofFound",
            "failedOpcode2cRoutePairGateIds",
            "missingEvidence",
            "correctedTraceReachesReaderCount",
            "correctedTraceAllRoutePairDescriptorsReachReader",
            "evidenceRefs",
            "evidenceRefCount",
        ],
    },
    {
        "path": "out/save_selector_current_writer_paths.json",
        "fields": [
            "proofFound",
            "failedCurrentWriterPathGateIds",
            "missingEvidence",
            "currentWriterPathProofFound",
            "evidenceRefs",
            "evidenceRefCount",
        ],
    },
    {
        "path": "out/save_selector_current_root_frontier_paths.json",
        "fields": [
            "proofFound",
            "failedCurrentRootFrontierPathGateIds",
            "missingEvidence",
            "runtimeSelectionProven",
            "evidenceRefs",
            "evidenceRefCount",
        ],
    },
]


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


def as_dict(value: Any) -> dict:
    return value if isinstance(value, dict) else {}


def proof_gate_rows(wrapper: dict, route_pair: dict, index_source: dict, leaf_index: dict, selected: dict) -> list[dict]:
    return [
        {
            "id": "selectedRootExecution",
            "pass": selected.get("selectedRootExecutionRefFound") is True,
            "status": "missing" if selected.get("selectedRootExecutionRefFound") is not True else "present",
            "detail": "normal route execution has not reached selector 2:0/current root 0x00540714",
        },
        {
            "id": "routePairCorrectedTraceOnly",
            "pass": False,
            "status": "corrected-trace-only-not-proof",
            "detail": (
                f"entries {route_pair.get('routePairEntryIndices')} corrected traces reach "
                f"{route_pair.get('frontierReaderHex')}, but normal selection remains unproven"
            ),
        },
        {
            "id": "routePairIndexSource",
            "pass": index_source.get("proofFound") is True,
            "status": "missing" if index_source.get("proofFound") is not True else "present",
            "detail": "no direct, encoded, opcode07, or higher-level source selects entries 6/8 or wrapper -12",
        },
        {
            "id": "currentLeafSelection",
            "pass": wrapper.get("currentLeafSelectionProofFound") is True,
            "status": "missing" if wrapper.get("currentLeafSelectionProofFound") is not True else "present",
            "detail": "frontier leaf 0x00542ae8 is table data, not a proven selected current leaf",
        },
        {
            "id": "wrapperExecution",
            "pass": wrapper.get("wrapperExecutionProofFound") is True,
            "status": "missing" if wrapper.get("wrapperExecutionProofFound") is not True else "present",
            "detail": "negative wrapper entry -12 / 0x00542a04 is not proven executed on the normal route path",
        },
        {
            "id": "currentSelectorLeafExecution",
            "pass": wrapper.get("currentSelectorLeafExecutionProofFound") is True,
            "status": "missing" if wrapper.get("currentSelectorLeafExecutionProofFound") is not True else "present",
            "detail": "selected root, leaf selection, wrapper execution, and reader trace are not tied together",
        },
        {
            "id": "strictSourceHotspot",
            "pass": False,
            "status": "missing",
            "detail": "strict map1_01a source coordinate/hotspot linked to map2_02d remains absent",
        },
    ]


def root_table_evidence(wrapper: dict, index_source: dict) -> dict:
    return {
        "rootTableWindowDirectRefCount": wrapper.get("rootTableWindowDirectRefCount"),
        "rootTableWindowDirectTextRefCount": wrapper.get("rootTableWindowDirectTextRefCount"),
        "rootTableRouteEntryAddressTextRefCount": wrapper.get("rootTableRouteEntryAddressTextRefCount"),
        "rootTableRouteLeafValueTextRefCount": wrapper.get("rootTableRouteLeafValueTextRefCount"),
        "rootTableFrontierLeafValueTextRefCount": wrapper.get("rootTableFrontierLeafValueTextRefCount"),
        "rootTableFrontierReaderValueTextRefCount": wrapper.get("rootTableFrontierReaderValueTextRefCount"),
        "currentRootReferencesWrapper": wrapper.get("currentRootReferencesWrapper"),
        "wrapperEntryPromotingRefCount": wrapper.get("wrapperEntryPromotingRefCount"),
        "routePairIndexSourceDirectPointerRefPromotesRoute": index_source.get("directPointerRefPromotesRoute"),
        "routePairIndexSourceEncodedEntryAnchorClassification": index_source.get("encodedEntryAnchorClassification"),
        "routePairIndexSourceEncodedEntryAnchorPromotingCandidateCount": index_source.get(
            "encodedEntryAnchorPromotingCandidateCount"
        ),
    }


def build_summary(out_dir: Path = OUT) -> dict:
    wrapper = load_json(out_dir / "save_selector_wrapper_execution_gap.json", {})
    route_pair = load_json(out_dir / "save_selector_route_pair_entry_execution_gap.json", {})
    index_source = load_json(out_dir / "save_selector_route_pair_index_source_gap.json", {})
    selected = load_json(out_dir / "save_selector_selected_root_execution_gap.json", {})
    leaf_table = load_json(out_dir / "save_selector_leaf_table_context.json", {})
    leaf_index = load_json(out_dir / "save_selector_leaf_index_space.json", {})
    global_leaf = load_json(out_dir / "save_selector_leaf_table_global_context.json", {})
    route_pair_descriptor = load_json(out_dir / "save_selector_route_pair_descriptor_context.json", {})
    opcode2c = load_json(out_dir / "save_selector_opcode2c_route_pair_context.json", {})
    current_writer = as_dict(load_json(out_dir / "save_selector_current_writer_paths.json", {}))
    current_frontier = as_dict(load_json(out_dir / "save_selector_current_root_frontier_paths.json", {}))
    gate_rows = proof_gate_rows(wrapper, route_pair, index_source, leaf_index, selected)
    return {
        "source": SOURCE,
        "target": TARGET,
        "promotionStatus": "blocked",
        "proofFound": wrapper.get("proofFound"),
        "currentLeafWrapperExternalProofFound": wrapper.get("proofFound"),
        "failedCurrentLeafWrapperExternalGateIds": wrapper.get("failedWrapperGateIds") or [],
        "missingEvidence": wrapper.get("missingEvidence") or [],
        "currentSelector": selected.get("currentSelector") or wrapper.get("selector") or "2:0",
        "currentRootHex": selected.get("currentRootHex") or wrapper.get("rootHex") or route_pair.get("rootHex"),
        "rootTablePointerHex": wrapper.get("rootTablePointerHex") or route_pair.get("rootTablePointerHex"),
        "wrapperEntryHex": wrapper.get("wrapperEntryHex"),
        "wrapperDescriptorHex": wrapper.get("wrapperDescriptorHex"),
        "wrapperChildPointerHex": wrapper.get("wrapperChildPointerHex"),
        "frontierLeafHex": wrapper.get("frontierLeafHex"),
        "frontierReaderHex": wrapper.get("frontierReaderHex"),
        "selectedRootExecutionRefFound": selected.get("selectedRootExecutionRefFound"),
        "selectedRootExecutionRejectionClassification": selected.get(
            "selectedRootExecutionRejectionClassification"
        ),
        "routePairEntryIndices": route_pair.get("routePairEntryIndices") or wrapper.get("currentRoutePairDescriptorIndices") or [],
        "routePairCorrectedTraceEntryIndices": route_pair.get("routePairCorrectedTraceEntryIndices")
        or leaf_index.get("routePairCorrectedTraceDescriptorIndices")
        or [],
        "negativeReaderEntryIndices": route_pair.get("negativeReaderEntryIndices") or wrapper.get("readerBearingNegativeIndices") or [],
        "globalCurrentSelectorRoutePairIndices": global_leaf.get("currentSelectorRoutePairIndices") or [],
        "globalCurrentFrontierLeafOnlyNegative": global_leaf.get("currentFrontierLeafOnlyNegative"),
        "frontierReaderSelectableByNonNegativeIndex": leaf_index.get("frontierReaderSelectableByNonNegativeIndex"),
        "frontierReaderReachableByCorrectedNonNegativeIndex": leaf_index.get(
            "frontierReaderReachableByCorrectedNonNegativeIndex"
        ),
        "correctedTraceAllRoutePairDescriptorsReachReader": leaf_index.get(
            "correctedTraceAllRoutePairDescriptorsReachReader"
        ),
        "correctedTraceReachesReaderCount": opcode2c.get("correctedTraceReachesReaderCount")
        or route_pair.get("routePairCorrectedTraceReachesReaderCount"),
        "correctedTraceNormalSelectionGapFound": wrapper.get("correctedTraceNormalSelectionGapFound"),
        "correctedTraceNormalSelectionGapStatus": wrapper.get("correctedTraceNormalSelectionGapStatus"),
        "routePairEntryExecutionProven": route_pair.get("routePairEntryExecutionProven"),
        "routePairIndexSourceProofFound": index_source.get("proofFound"),
        "wrapperExecutionProofFound": wrapper.get("wrapperExecutionProofFound"),
        "currentLeafSelectionProofFound": wrapper.get("currentLeafSelectionProofFound"),
        "currentSelectorLeafExecutionProofFound": wrapper.get("currentSelectorLeafExecutionProofFound"),
        "leafTableRuntimeSelectionProven": leaf_table.get("runtimeSelectionProven"),
        "leafTableFrontierLeafRefIsDirectRootTableEntry": leaf_table.get(
            "frontierLeafRefIsDirectRootTableEntry"
        ),
        "leafIndexRuntimeSelectionProven": leaf_index.get("runtimeSelectionProven"),
        "routePairDescriptorRuntimeSelectionProven": route_pair_descriptor.get("runtimeSelectionProven"),
        "currentWriterPathProofFound": current_writer.get("currentWriterPathProofFound"),
        "currentRootFrontierPathProofFound": current_frontier.get("proofFound"),
        "rootTableEvidence": root_table_evidence(wrapper, index_source),
        "routePairIndexSourceEvidence": {
            "proofFound": index_source.get("proofFound"),
            "failedGateIds": index_source.get("failedRoutePairIndexSourceGateIds") or [],
            "missingEvidence": index_source.get("missingEvidence") or [],
            "directPointerRefPromotesRoute": index_source.get("directPointerRefPromotesRoute"),
            "encodedEntryAnchorClassification": index_source.get("encodedEntryAnchorClassification"),
            "encodedEntryAnchorPromotingCandidateCount": index_source.get(
                "encodedEntryAnchorPromotingCandidateCount"
            ),
            "opcode07DirectEntrySelectionAbsent": index_source.get("opcode07DirectEntrySelectionAbsent"),
            "opcode07SelectedCurrentRootEntrySlotCount": index_source.get(
                "opcode07SelectedCurrentRootEntrySlotCount"
            ),
            "opcode07SelectedNegativeRootEntrySlotCount": index_source.get(
                "opcode07SelectedNegativeRootEntrySlotCount"
            ),
            "opcode07SelectedWrapperEntrySlotCount": index_source.get("opcode07SelectedWrapperEntrySlotCount"),
            "opcode07SelectedLeafTableWindowSlotCount": index_source.get(
                "opcode07SelectedLeafTableWindowSlotCount"
            ),
            "opcode07DirectFrontierTargetCount": index_source.get("opcode07DirectFrontierTargetCount"),
        },
        "sourcePredecessorProducerEvidence": {
            "opcode08SourceOrPredecessorCurrentRootProducerCount": route_pair.get(
                "opcode08SourceOrPredecessorCurrentRootProducerCount"
            ),
            "opcode08SourceOrPredecessorCurrentRangeProducerCount": route_pair.get(
                "opcode08SourceOrPredecessorCurrentRangeProducerCount"
            ),
            "opcode09SourceOrPredecessorCurrentRangeStoreCount": route_pair.get(
                "opcode09SourceOrPredecessorCurrentRangeStoreCount"
            ),
            "opcode08ActivationPromotesRoute": route_pair.get("opcode08ActivationPromotesRoute"),
            "opcode09PointerCollisionPromotesRoute": route_pair.get("opcode09PointerCollisionPromotesRoute"),
        },
        "diagnosticExclusionEvidence": {
            "constructedDiagnosticWrapperProofStatus": wrapper.get("constructedDiagnosticWrapperProofStatus"),
            "constructedDiagnosticExcludedFromWrapperProof": wrapper.get(
                "constructedDiagnosticExcludedFromWrapperProof"
            ),
            "constructedDiagnosticLeftStabilityRouteSelectorHitCount": wrapper.get(
                "constructedDiagnosticLeftStabilityRouteSelectorHitCount"
            ),
            "constructedDiagnosticLeftStabilityRecheckRouteSelectorHitCount": wrapper.get(
                "constructedDiagnosticLeftStabilityRecheckRouteSelectorHitCount"
            ),
            "constructedDiagnosticLeftActiveOrderRecheckRouteSelectorHitCount": wrapper.get(
                "constructedDiagnosticLeftActiveOrderRecheckRouteSelectorHitCount"
            ),
            "constructedDiagnosticLeftActiveOrderRecheckActiveOrderCountValues": wrapper.get(
                "constructedDiagnosticLeftActiveOrderRecheckActiveOrderCountValues"
            ),
        },
        "supportProofRows": [
            {
                "id": "wrapper-execution-gap",
                "proofFound": wrapper.get("proofFound"),
                "failedGateIds": wrapper.get("failedWrapperGateIds") or [],
                "missingEvidence": wrapper.get("missingEvidence") or [],
                "evidenceRefCount": wrapper.get("evidenceRefCount"),
            },
            {
                "id": "route-pair-entry-execution-gap",
                "proofFound": route_pair.get("proofFound"),
                "failedGateIds": route_pair.get("failedRoutePairEntryGateIds") or [],
                "missingEvidence": route_pair.get("missingEvidence") or [],
                "evidenceRefCount": route_pair.get("evidenceRefCount"),
            },
            {
                "id": "route-pair-index-source-gap",
                "proofFound": index_source.get("proofFound"),
                "failedGateIds": index_source.get("failedRoutePairIndexSourceGateIds") or [],
                "missingEvidence": index_source.get("missingEvidence") or [],
                "evidenceRefCount": index_source.get("evidenceRefCount"),
            },
            {
                "id": "opcode2c-corrected-route-pair-context",
                "proofFound": opcode2c.get("proofFound"),
                "failedGateIds": opcode2c.get("failedOpcode2cRoutePairGateIds") or [],
                "missingEvidence": opcode2c.get("missingEvidence") or [],
                "evidenceRefCount": opcode2c.get("evidenceRefCount"),
            },
        ],
        "proofGateCount": len(gate_rows),
        "proofGatePassCount": sum(1 for row in gate_rows if row.get("pass") is True),
        "proofGateBlockedCount": sum(1 for row in gate_rows if row.get("pass") is not True),
        "proofGatesAllBlocked": all(row.get("pass") is not True for row in gate_rows),
        "proofGateRows": gate_rows,
        "acceptedEvidenceChecklist": [
            {
                "requirement": "normal selected-root execution reaches current selector 2:0",
                "currentStatus": "missing",
                "acceptedSignal": "selectedRootExecutionRefFound == true on a non-diagnostic route path",
            },
            {
                "requirement": "higher-level index source selects route-pair entries 6/8 or wrapper -12",
                "currentStatus": "missing",
                "acceptedSignal": "routePairIndexSourceProofFound == true",
            },
            {
                "requirement": "wrapper 0x00542a04 executes into frontier leaf 0x00542ae8",
                "currentStatus": "missing",
                "acceptedSignal": "wrapperExecutionProofFound == true",
            },
            {
                "requirement": "current selector leaf execution ties selected root, leaf selection, wrapper, and reader",
                "currentStatus": "missing",
                "acceptedSignal": "currentSelectorLeafExecutionProofFound == true",
            },
            {
                "requirement": "strict map1_01a source coordinate/hotspot links to map2_02d",
                "currentStatus": "missing",
                "acceptedSignal": "strict source hotspot or equivalent runtime trigger is proven",
            },
        ],
        "notAcceptedEvidence": [
            "corrected opcode 0x2c route-pair traces that reach 0x00542b0c without normal selection proof",
            "negative reader-bearing wrapper entry -12 as table data outside the current root run",
            "root-table direct refs in .data with zero text/control-flow refs",
            "opcode 0x5a mode0 fallthrough words whose low-byte handlers are non-code/default contexts",
            "constructed selector 2:0 diagnostic left-route hits that are not reproduced by recheck",
            "source/predecessor opcode 0x08/0x09 pointer-shaped collisions with zero current root/range producer",
        ],
        "relatedReports": [
            "out/save_selector_wrapper_execution_gap.html",
            "out/save_selector_route_pair_entry_execution_gap.html",
            "out/save_selector_route_pair_index_source_gap.html",
            "out/save_selector_leaf_index_space.html",
            "out/save_selector_opcode2c_route_pair_context.json",
        ],
        "evidenceRefs": CURRENT_LEAF_WRAPPER_EXTERNAL_EVIDENCE_REFS,
        "evidenceRefCount": len(CURRENT_LEAF_WRAPPER_EXTERNAL_EVIDENCE_REFS),
        "regenerateAndVerifyCommands": [
            "python3 tools/summarize_current_leaf_wrapper_external_proof_packet.py",
            "python3 tools/verify_web_assets.py",
        ],
        "remainingProofs": wrapper.get("remainingProofs") or [],
        "conclusion": (
            "Current leaf/wrapper execution remains blocked: route-pair entries 6/8 have "
            "corrected reader traces, but no selected-root execution, index-source, wrapper "
            "execution, current selector leaf execution, or strict hotspot proof selects them "
            "on the normal route path."
        ),
    }


def markdown(summary: dict) -> str:
    lines = [
        "# Current Leaf Wrapper External Proof Packet",
        "",
        f"- route: `{summary['source']} -> {summary['target']}`",
        f"- promotion status: `{summary['promotionStatus']}`",
        f"- proof found: {summary.get('proofFound')}",
        f"- currentLeafWrapperExternalProofFound: {summary.get('currentLeafWrapperExternalProofFound')}",
        f"- current selector/root: `{summary.get('currentSelector')}` / `{summary.get('currentRootHex')}`",
        f"- root table: `{summary.get('rootTablePointerHex')}`",
        f"- wrapper entry/descriptor/child: `{summary.get('wrapperEntryHex')}` / `{summary.get('wrapperDescriptorHex')}` / `{summary.get('wrapperChildPointerHex')}`",
        f"- frontier leaf/reader: `{summary.get('frontierLeafHex')}` / `{summary.get('frontierReaderHex')}`",
        f"- failed current leaf/wrapper external gates: `{', '.join(summary.get('failedCurrentLeafWrapperExternalGateIds') or [])}`",
        f"- missing evidence count: {len(summary.get('missingEvidence') or [])}",
        f"- evidence refs: {summary.get('evidenceRefCount')}",
        "",
        "## Route-Pair And Wrapper Evidence",
        "",
        f"- route-pair entry indices: `{summary.get('routePairEntryIndices')}`",
        f"- corrected trace entry indices: `{summary.get('routePairCorrectedTraceEntryIndices')}`",
        f"- negative reader entry indices: `{summary.get('negativeReaderEntryIndices')}`",
        f"- global route-pair indices: `{summary.get('globalCurrentSelectorRoutePairIndices')}`",
        f"- global current frontier leaf only negative: {summary.get('globalCurrentFrontierLeafOnlyNegative')}",
        f"- corrected trace reaches reader count: {summary.get('correctedTraceReachesReaderCount')}",
        f"- corrected all route-pair descriptors reach reader: {summary.get('correctedTraceAllRoutePairDescriptorsReachReader')}",
        f"- frontier reader selectable by non-negative index: {summary.get('frontierReaderSelectableByNonNegativeIndex')}",
        f"- frontier reader reachable by corrected non-negative index: {summary.get('frontierReaderReachableByCorrectedNonNegativeIndex')}",
        f"- corrected trace normal-selection gap: `{summary.get('correctedTraceNormalSelectionGapStatus')}`",
        f"- route-pair entry execution proven: {summary.get('routePairEntryExecutionProven')}",
        f"- route-pair index source proof found: {summary.get('routePairIndexSourceProofFound')}",
        f"- wrapper execution proof found: {summary.get('wrapperExecutionProofFound')}",
        f"- current leaf selection proof found: {summary.get('currentLeafSelectionProofFound')}",
        f"- current selector leaf execution proof found: {summary.get('currentSelectorLeafExecutionProofFound')}",
        "",
        "## Root Table Evidence",
        "",
    ]
    root = summary.get("rootTableEvidence") or {}
    for key, value in root.items():
        lines.append(f"- {key}: `{value}`")
    lines.extend(["", "## Route-Pair Index Source Evidence", ""])
    index = summary.get("routePairIndexSourceEvidence") or {}
    for key, value in index.items():
        lines.append(f"- {key}: `{value}`")
    lines.extend(["", "## Source/Predecessor Producer Evidence", ""])
    producer = summary.get("sourcePredecessorProducerEvidence") or {}
    for key, value in producer.items():
        lines.append(f"- {key}: `{value}`")
    lines.extend(["", "## Diagnostic Exclusion Evidence", ""])
    diag = summary.get("diagnosticExclusionEvidence") or {}
    for key, value in diag.items():
        lines.append(f"- {key}: `{value}`")
    lines.extend([
        "",
        "## Proof Gates",
        "",
        "| id | pass | status | detail |",
        "| --- | --- | --- | --- |",
    ])
    for row in summary.get("proofGateRows") or []:
        lines.append(
            f"| `{row.get('id')}` | {row.get('pass')} | `{row.get('status')}` | {row.get('detail')} |"
        )
    lines.extend([
        "",
        "## Support Proof Rows",
        "",
        "| id | proof found | failed gate ids | evidence refs |",
        "| --- | --- | --- | --- |",
    ])
    for row in summary.get("supportProofRows") or []:
        lines.append(
            f"| `{row.get('id')}` | {row.get('proofFound')} | `{', '.join(row.get('failedGateIds') or [])}` | "
            f"{row.get('evidenceRefCount')} |"
        )
    lines.extend([
        "",
        "## Accepted Evidence Checklist",
        "",
        "| requirement | current status | accepted signal |",
        "| --- | --- | --- |",
    ])
    for row in summary.get("acceptedEvidenceChecklist") or []:
        lines.append(
            f"| {row.get('requirement')} | `{row.get('currentStatus')}` | {row.get('acceptedSignal')} |"
        )
    lines.extend(["", "## Missing Evidence", ""])
    lines.extend(f"- {item}" for item in summary.get("missingEvidence") or [])
    lines.extend(["", "## Not Accepted Evidence", ""])
    lines.extend(f"- {item}" for item in summary.get("notAcceptedEvidence") or [])
    lines.extend(["", "## Evidence Refs", ""])
    for ref in summary.get("evidenceRefs") or []:
        lines.append(f"- `{ref.get('path')}`: {', '.join(ref.get('fields') or [])}")
    lines.extend(["", "## Regenerate And Verify", ""])
    lines.extend(f"- `{cmd}`" for cmd in summary.get("regenerateAndVerifyCommands") 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))

    gate_rows = []
    for row in summary.get("proofGateRows") or []:
        gate_rows.append(
            "<tr>"
            f"<td><code>{esc(row.get('id'))}</code></td>"
            f"<td>{esc(row.get('pass'))}</td>"
            f"<td><code>{esc(row.get('status'))}</code></td>"
            f"<td>{esc(row.get('detail'))}</td>"
            "</tr>"
        )
    support_rows = []
    for row in summary.get("supportProofRows") or []:
        support_rows.append(
            "<tr>"
            f"<td><code>{esc(row.get('id'))}</code></td>"
            f"<td>{esc(row.get('proofFound'))}</td>"
            f"<td><code>{esc(', '.join(row.get('failedGateIds') or []))}</code></td>"
            f"<td>{esc(row.get('evidenceRefCount'))}</td>"
            "</tr>"
        )
    checklist_rows = []
    for row in summary.get("acceptedEvidenceChecklist") or []:
        checklist_rows.append(
            "<tr>"
            f"<td>{esc(row.get('requirement'))}</td>"
            f"<td><code>{esc(row.get('currentStatus'))}</code></td>"
            f"<td>{esc(row.get('acceptedSignal'))}</td>"
            "</tr>"
        )
    missing = "".join(f"<li>{esc(item)}</li>" for item in summary.get("missingEvidence") or [])
    not_accepted = "".join(f"<li>{esc(item)}</li>" for item in summary.get("notAcceptedEvidence") or [])
    refs = "".join(
        f"<li><code>{esc(ref.get('path'))}</code>: {esc(', '.join(ref.get('fields') or []))}</li>"
        for ref in summary.get("evidenceRefs") or []
    )
    commands = "".join(
        f"<li><code>{esc(cmd)}</code></li>" for cmd in summary.get("regenerateAndVerifyCommands") or []
    )
    root = summary.get("rootTableEvidence") or {}
    index = summary.get("routePairIndexSourceEvidence") or {}
    producer = summary.get("sourcePredecessorProducerEvidence") or {}
    diag = summary.get("diagnosticExclusionEvidence") or {}
    details = []
    for title, mapping in [
        ("Root Table Evidence", root),
        ("Route-Pair Index Source Evidence", index),
        ("Source/Predecessor Producer Evidence", producer),
        ("Diagnostic Exclusion Evidence", diag),
    ]:
        items = "".join(f"<li>{esc(key)}: <code>{esc(value)}</code></li>" for key, value in mapping.items())
        details.append(f"<h2>{esc(title)}</h2><ul>{items}</ul>")
    return "\n".join([
        "<!doctype html>",
        '<html lang="en">',
        "<head>",
        '  <meta charset="utf-8">',
        '  <meta name="viewport" content="width=device-width, initial-scale=1">',
        "  <title>Current Leaf Wrapper External Proof Packet</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}</style>",
        "</head>",
        "<body>",
        "  <h1>Current Leaf Wrapper External Proof Packet</h1>",
        f"  <p>route <code>{esc(summary['source'])}</code> -&gt; <code>{esc(summary['target'])}</code>; "
        f"promotion status <code>{esc(summary.get('promotionStatus'))}</code>; proof found "
        f"{esc(summary.get('proofFound'))}; currentLeafWrapperExternalProofFound "
        f"{esc(summary.get('currentLeafWrapperExternalProofFound'))}.</p>",
        f"  <p>current selector/root <code>{esc(summary.get('currentSelector'))}</code> / "
        f"<code>{esc(summary.get('currentRootHex'))}</code>; root table "
        f"<code>{esc(summary.get('rootTablePointerHex'))}</code>; wrapper "
        f"<code>{esc(summary.get('wrapperEntryHex'))}</code> / "
        f"<code>{esc(summary.get('wrapperDescriptorHex'))}</code> / "
        f"<code>{esc(summary.get('wrapperChildPointerHex'))}</code>; frontier "
        f"<code>{esc(summary.get('frontierLeafHex'))}</code> / "
        f"<code>{esc(summary.get('frontierReaderHex'))}</code>.</p>",
        f"  <p>route-pair entry indices <code>{esc(summary.get('routePairEntryIndices'))}</code>; "
        f"corrected trace entry indices <code>{esc(summary.get('routePairCorrectedTraceEntryIndices'))}</code>; "
        f"negative reader entry indices <code>{esc(summary.get('negativeReaderEntryIndices'))}</code>; "
        f"corrected trace status <code>{esc(summary.get('correctedTraceNormalSelectionGapStatus'))}</code>.</p>",
        f"  <p>failed current leaf/wrapper external gates <code>{esc(', '.join(summary.get('failedCurrentLeafWrapperExternalGateIds') or []))}</code>; "
        f"evidence refs {esc(summary.get('evidenceRefCount'))}.</p>",
        *details,
        "  <h2>Proof Gates</h2>",
        "  <table><thead><tr><th>id</th><th>pass</th><th>status</th><th>detail</th></tr></thead>",
        f"  <tbody>{''.join(gate_rows)}</tbody></table>",
        "  <h2>Support Proof Rows</h2>",
        "  <table><thead><tr><th>id</th><th>proof found</th><th>failed gate ids</th><th>evidence refs</th></tr></thead>",
        f"  <tbody>{''.join(support_rows)}</tbody></table>",
        "  <h2>Accepted Evidence Checklist</h2>",
        "  <table><thead><tr><th>requirement</th><th>current status</th><th>accepted signal</th></tr></thead>",
        f"  <tbody>{''.join(checklist_rows)}</tbody></table>",
        "  <h2>Missing Evidence</h2>",
        f"  <ul>{missing}</ul>",
        "  <h2>Not Accepted Evidence</h2>",
        f"  <ul>{not_accepted}</ul>",
        "  <h2>Evidence Refs</h2>",
        f"  <ul>{refs}</ul>",
        "  <h2>Regenerate And Verify</h2>",
        f"  <ul>{commands}</ul>",
        f"  <p>{esc(summary.get('conclusion'))}</p>",
        "</body>",
        "</html>",
        "",
    ])


def write_outputs(summary: dict, out_dir: Path = OUT, md_out: Path | None = None) -> None:
    out_dir.mkdir(parents=True, exist_ok=True)
    (out_dir / "current_leaf_wrapper_external_proof_packet.json").write_text(
        json.dumps(summary, ensure_ascii=False, indent=2) + "\n",
        encoding="utf-8",
    )
    if md_out is not None:
        md_out.write_text(markdown(summary), encoding="utf-8")
    (out_dir / "current_leaf_wrapper_external_proof_packet.html").write_text(html_page(summary), encoding="utf-8")


def main() -> None:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--out-dir", type=Path, default=OUT)
    parser.add_argument("--md-out", type=Path, help="Optional legacy markdown output path.")
    args = parser.parse_args()
    summary = build_summary(args.out_dir)
    write_outputs(summary, args.out_dir, args.md_out)
    print(f"wrote current leaf/wrapper external proof packet -> {args.out_dir / 'current_leaf_wrapper_external_proof_packet.html'}")


if __name__ == "__main__":
    main()
