"""experiment_floor_plan_bg_to_fp_region_ref_slice — W18D.

Deterministic join of the W18A2 overlay payload + the W18C VLM
readback, producing a `bg_to_fp_region_ref` preview that a downstream
background prompt assembler can consume. No LLM call. No VLM call.
No image API call. No DB / ImageAsset write. No production manifest
mutation. No commit. No push.

Codex W18D contract:
- Per bg in W18A2 `bg_state_overlay_payload_by_bg`:
  - point to the W18B base FP PNG (relative path).
  - carry the W18A2 `target_unit_ids` → resolve each to its base unit
    layout rect from W18C `base_unit_layout`.
  - carry the W18A2 `base_markers_to_reference` → resolve each marker
    to its W18C `read_marker` row (label, cell/rect, confidence,
    visible).
  - carry the W18A2 `transient_markers_to_describe` → resolve each to
    its W18A2 `excluded_transient_elements` entry (label, overlay
    instruction hint).
  - emit a short deterministic `region_prompt_hint` enumerating the
    referenced base markers and transient markers (NO LLM, NO
    natural-language generation).

CLI:
  --derive-region-ref-from <W18C_run_dir>   (required)
  --target-fp-ids fp_l05_01                 (default, wave-1 lock)
  --output-root <path>
  --diag-print-imports
"""
from __future__ import annotations

import argparse
import json
import sys
from datetime import datetime
from pathlib import Path
from typing import Any, Dict, List, Optional, Set, Tuple

_REPO_ROOT = Path(__file__).resolve().parents[2]
_SCRIPTS_DIR = _REPO_ROOT / "backend" / "scripts"
if str(_SCRIPTS_DIR) not in sys.path:
    sys.path.insert(0, str(_SCRIPTS_DIR))

from experiment_background_pipeline_slice import (  # type: ignore
    KST,
    PLAN_VERSION,
    _check_image_imports_present,
    _check_production_diff_empty,
    _maybe_print_imports,
)
from experiment_floor_plan_grid_layout_slice import (  # type: ignore
    W16_ALLOWED_TARGET_FP_IDS,
    _resolve_targets,
)
from experiment_floor_plan_base_layout_vlm_readback_slice import (  # type: ignore
    _resolve_w18a_run_dir_from_w18b,
)

W18D_STAGE = "w18d_floor_plan_bg_to_fp_region_ref_slice"

_DEFAULT_OUTPUT_ROOT = (
    _REPO_ROOT
    / "scripts_output"
    / "floor_plan_bg_to_fp_region_ref_slice_experiment"
)


def _run_id() -> str:
    import secrets

    return datetime.now(KST).strftime("%Y%m%d_%H%M") + "_" + secrets.token_hex(3)


def _parse_args(argv):
    p = argparse.ArgumentParser(
        description=(
            "W18D bg→fp region ref preview — deterministic only. "
            "No LLM/VLM/image API call."
        )
    )
    p.add_argument(
        "--derive-region-ref-from", required=True,
        help="Path to a prior W18C success run dir.",
    )
    p.add_argument(
        "--target-fp-ids", default="fp_l05_01",
        help="Comma-separated fp_id subset. Wave 1 only allows fp_l05_01.",
    )
    p.add_argument("--output-root", default=str(_DEFAULT_OUTPUT_ROOT))
    p.add_argument("--diag-print-imports", action="store_true")
    return p.parse_args(argv)


def _resolve_w18b_run_dir_from_w18c(
    w18c_meta: Dict[str, Any],
) -> Optional[Path]:
    args_dict = (w18c_meta or {}).get("args") or {}
    if isinstance(args_dict, dict):
        raw = args_dict.get("derive_base_vlm_readback_from")
        if isinstance(raw, str) and raw:
            p = Path(raw)
            if not p.is_absolute():
                p = _REPO_ROOT / raw
            if (p / "run_meta.json").exists():
                return p
    derived_from = (w18c_meta or {}).get("derived_from") or ""
    if isinstance(derived_from, str) and derived_from:
        parent = (
            _REPO_ROOT
            / "scripts_output"
            / "floor_plan_base_layout_image_smoke_slice_experiment"
        )
        if (parent / derived_from / "run_meta.json").exists():
            return parent / derived_from
    return None


def _build_region_ref_for_fp(
    *, fp_id: str,
    w18a_fp_entry: Dict[str, Any],
    w18c_readback: Dict[str, Any],
    w18b_png_relative_to_repo: str,
) -> Tuple[Dict[str, Dict[str, Any]], List[Dict[str, Any]]]:
    """Return ({bg_id: bg_payload}, unresolved_diagnostics)."""
    # Index W18A2 included markers by unit_id (for #1..#6 area markers).
    included_legend = w18a_fp_entry.get("included_marker_legend") or []
    unit_id_to_marker: Dict[str, Dict[str, Any]] = {}
    marker_to_legend: Dict[int, Dict[str, Any]] = {}
    for it in included_legend:
        if not isinstance(it, dict):
            continue
        n = it.get("marker_number")
        if isinstance(n, int):
            marker_to_legend[n] = it
            uid = it.get("unit_id") or ""
            if (
                it.get("base_layer_decision") == "base_structural_unit"
                and uid
            ):
                unit_id_to_marker[uid] = it

    # Index W18A2 excluded transient elements by marker_number.
    excluded_by_n: Dict[int, Dict[str, Any]] = {}
    for it in w18a_fp_entry.get("excluded_transient_elements") or []:
        if not isinstance(it, dict):
            continue
        n = it.get("marker_number")
        if isinstance(n, int):
            excluded_by_n[n] = it

    # Index W18C VLM readback by marker_number (read_markers).
    read_by_n: Dict[int, Dict[str, Any]] = {}
    for it in w18c_readback.get("read_markers") or []:
        if isinstance(it, dict) and isinstance(it.get("marker_number"), int):
            read_by_n[int(it["marker_number"])] = it

    # Index W18C base_unit_layout by marker_number (spatial unit rects).
    unit_layout_by_n: Dict[int, Dict[str, Any]] = {}
    for it in w18c_readback.get("base_unit_layout") or []:
        if isinstance(it, dict) and isinstance(it.get("marker_number"), int):
            unit_layout_by_n[int(it["marker_number"])] = it

    overlay = w18a_fp_entry.get("bg_state_overlay_payload_by_bg") or {}
    out: Dict[str, Dict[str, Any]] = {}
    diagnostics: List[Dict[str, Any]] = []

    for bg_id in sorted(overlay.keys()):
        bg_payload = overlay.get(bg_id) or {}
        target_unit_ids: List[str] = list(
            bg_payload.get("target_unit_ids") or []
        )
        base_marker_nums: List[int] = [
            int(n) for n in (bg_payload.get("base_markers_to_reference") or [])
            if isinstance(n, int)
        ]
        transient_marker_nums: List[int] = [
            int(n)
            for n in (bg_payload.get("transient_markers_to_describe") or [])
            if isinstance(n, int)
        ]

        target_unit_refs: List[Dict[str, Any]] = []
        for uid in target_unit_ids:
            legend = unit_id_to_marker.get(uid)
            if legend is None:
                diagnostics.append({
                    "bg_id": bg_id, "kind": "target_unit_no_legend_match",
                    "unit_id": uid,
                })
                continue
            n = legend.get("marker_number")
            layout = unit_layout_by_n.get(n) if isinstance(n, int) else None
            target_unit_refs.append({
                "unit_id": uid,
                "marker_number": n,
                "label": legend.get("label") or "",
                "approximate_10x10_rect": (
                    (layout or {}).get("approximate_10x10_rect")
                ),
                "observed_area_label": (
                    (layout or {}).get("observed_area_label") or ""
                ),
                "adjacency_notes": (
                    (layout or {}).get("adjacency_notes") or ""
                ),
            })
            if layout is None:
                diagnostics.append({
                    "bg_id": bg_id,
                    "kind": "target_unit_no_w18c_unit_layout",
                    "unit_id": uid, "marker_number": n,
                })

        base_marker_refs: List[Dict[str, Any]] = []
        for n in base_marker_nums:
            legend = marker_to_legend.get(n)
            read = read_by_n.get(n)
            base_marker_refs.append({
                "marker_number": n,
                "label": (legend or {}).get("label") or "",
                "base_layer_decision": (legend or {}).get(
                    "base_layer_decision"
                ) or "",
                "visual_encoding": (legend or {}).get("visual_encoding") or "",
                "visible": bool((read or {}).get("visible")),
                "confidence": (read or {}).get("confidence") or "",
                "approximate_10x10_rect": (
                    (read or {}).get("approximate_10x10_rect")
                ),
                "approximate_10x10_cell": (
                    (read or {}).get("approximate_10x10_cell")
                ),
                "observed_label_or_area": (
                    (read or {}).get("observed_label_or_area") or ""
                ),
            })
            if read is None:
                diagnostics.append({
                    "bg_id": bg_id, "kind": "base_marker_no_w18c_read",
                    "marker_number": n,
                })

        transient_overlay_to_describe: List[Dict[str, Any]] = []
        for n in transient_marker_nums:
            excl = excluded_by_n.get(n)
            transient_overlay_to_describe.append({
                "marker_number": n,
                "label": (excl or {}).get("label") or "",
                "unit_id": (excl or {}).get("unit_id") or "",
                "base_layer_decision": (
                    (excl or {}).get("base_layer_decision") or ""
                ),
                "overlay_instruction_hint": (
                    (excl or {}).get("overlay_instruction_hint") or ""
                ),
            })
            if excl is None:
                diagnostics.append({
                    "bg_id": bg_id, "kind": "transient_marker_no_w18a_entry",
                    "marker_number": n,
                })

        # Deterministic region_prompt_hint — short, enumerative only.
        base_marker_label = ", ".join(
            f"#{m['marker_number']}" for m in base_marker_refs
        ) or "(none)"
        transient_label = ", ".join(
            f"#{m['marker_number']}"
            for m in transient_overlay_to_describe
        ) or "(none)"
        target_unit_label = ", ".join(
            f"#{r['marker_number']} ({r['unit_id']})"
            for r in target_unit_refs
            if isinstance(r.get("marker_number"), int)
        ) or "(none)"
        region_prompt_hint = (
            f"Reference base FP units {target_unit_label}; "
            f"use base markers {base_marker_label}; "
            f"overlay transient markers {transient_label}."
        )

        out[bg_id] = {
            "bg_id": bg_id,
            "fp_id": fp_id,
            "base_fp_png_path_relative_to_repo": w18b_png_relative_to_repo,
            "target_unit_refs": target_unit_refs,
            "base_marker_refs": base_marker_refs,
            "transient_overlay_to_describe": transient_overlay_to_describe,
            "region_prompt_hint": region_prompt_hint,
        }

    return out, diagnostics


def _build_w18d_compatibility_report(
    *, region_ref_by_bg: Dict[str, Dict[str, Any]],
    w18a_fp_entry: Dict[str, Any],
    w18c_readback: Dict[str, Any],
    target_fp_ids: Set[str],
    production_diff_empty: bool,
    db_write_count: int,
    image_import_seen: bool,
    image_api_call_count: int,
    vlm_api_call_count: int,
    llm_api_call_count: int,
    missing_inputs: List[str],
    prev_run_id: str,
) -> dict:
    inv: Dict[str, Dict[str, Any]] = {}

    # 1. inputs_present
    inv["inputs_present"] = {
        "pass": (
            not missing_inputs
            and bool(region_ref_by_bg)
            and bool(w18a_fp_entry)
            and bool(w18c_readback)
        ),
        "detail": {
            "missing_inputs": list(missing_inputs),
            "region_ref_bg_count": len(region_ref_by_bg),
            "prev_run_id": prev_run_id,
        },
    }

    # 2. target_fp_only_fp_l05_01
    inv["target_fp_only_fp_l05_01"] = {
        "pass": bool(target_fp_ids) and target_fp_ids.issubset(
            W16_ALLOWED_TARGET_FP_IDS
        ),
        "detail": {
            "received_target_fp_ids": sorted(target_fp_ids or set()),
            "allowed": sorted(W16_ALLOWED_TARGET_FP_IDS),
        },
    }

    # 3. bg_region_refs_cover_w18a2_overlay_bgs
    expected_bgs = set(
        (w18a_fp_entry.get("bg_state_overlay_payload_by_bg") or {}).keys()
    )
    actual_bgs = set(region_ref_by_bg.keys())
    inv["bg_region_refs_cover_w18a2_overlay_bgs"] = {
        "pass": expected_bgs == actual_bgs and bool(expected_bgs),
        "detail": {
            "expected_bgs": sorted(expected_bgs),
            "actual_bgs": sorted(actual_bgs),
            "missing_in_w18d": sorted(expected_bgs - actual_bgs),
            "extra_in_w18d": sorted(actual_bgs - expected_bgs),
        },
    }

    # 4. referenced_base_markers_resolve_in_w18c
    read_by_n: Dict[int, Dict[str, Any]] = {
        int(it["marker_number"]): it
        for it in (w18c_readback.get("read_markers") or [])
        if isinstance(it, dict) and isinstance(it.get("marker_number"), int)
    }
    resolve_failures: List[dict] = []
    for bg_id, payload in region_ref_by_bg.items():
        for ref in payload.get("base_marker_refs") or []:
            n = ref.get("marker_number")
            if not isinstance(n, int):
                resolve_failures.append({
                    "bg_id": bg_id, "reason": "base_marker_not_int",
                    "value": n,
                })
                continue
            read = read_by_n.get(n)
            if read is None:
                resolve_failures.append({
                    "bg_id": bg_id, "marker_number": n,
                    "reason": "base_marker_not_in_w18c_read",
                })
                continue
            if not bool(read.get("visible")):
                resolve_failures.append({
                    "bg_id": bg_id, "marker_number": n,
                    "reason": "base_marker_w18c_visible_false",
                })
    inv["referenced_base_markers_resolve_in_w18c"] = {
        "pass": not resolve_failures,
        "detail": {
            "failures": resolve_failures[:30],
            "failure_count": len(resolve_failures),
        },
    }

    # 5. production / api zero guard
    inv["production_diff_zero_db_write_zero_llm_vlm_image_zero"] = {
        "pass": (
            production_diff_empty
            and db_write_count == 0
            and not image_import_seen
            and image_api_call_count == 0
            and vlm_api_call_count == 0
            and llm_api_call_count == 0
        ),
        "detail": {
            "production_diff_empty": production_diff_empty,
            "db_write_count": db_write_count,
            "image_import_seen": image_import_seen,
            "image_api_call_count": image_api_call_count,
            "vlm_api_call_count": vlm_api_call_count,
            "llm_api_call_count": llm_api_call_count,
        },
    }

    all_pass = all(v["pass"] for v in inv.values())
    return {"invariants": inv, "all_pass": all_pass}


def main(argv=None) -> int:
    args = _parse_args(argv)
    run_id = _run_id()
    out_root = Path(args.output_root)
    run_dir = out_root / run_id
    run_dir.mkdir(parents=True, exist_ok=True)

    prev_run_dir = Path(args.derive_region_ref_from)
    if not prev_run_dir.is_absolute():
        prev_run_dir = Path.cwd() / prev_run_dir

    target_fp_ids, invalid_targets = _resolve_targets(args.target_fp_ids)

    failed_invariants: List[str] = []
    run_status = "succeeded"
    exit_code = 0

    run_meta: Dict[str, Any] = {
        "run_id": run_id,
        "stage": W18D_STAGE,
        "plan_version": PLAN_VERSION,
        "generated_at": datetime.now(KST).isoformat(),
        "args": vars(args),
        "derived_from": prev_run_dir.name,
        "target_fp_ids": sorted(target_fp_ids),
        "invalid_targets": invalid_targets,
        "llm_api_call_count": 0,
        "vlm_api_call_count": 0,
        "image_api_call_count": 0,
        "outputs": [],
        "run_status": run_status,
        "exit_code": exit_code,
        "failed_invariants": failed_invariants,
    }

    def _persist_and_exit(code: int) -> int:
        run_meta["exit_code"] = code
        if code != 0:
            run_meta["run_status"] = "validation_failed"
        run_meta["failed_invariants"] = failed_invariants
        (run_dir / "run_meta.json").write_text(
            json.dumps(run_meta, ensure_ascii=False, indent=2)
        )
        return code

    missing: List[str] = []
    w18c_readback_path = prev_run_dir / "vlm_readback.json"
    w18c_meta_path = prev_run_dir / "run_meta.json"
    if not w18c_readback_path.exists():
        missing.append("vlm_readback.json")
    if not w18c_meta_path.exists():
        missing.append("run_meta.json")
    if missing:
        failed_invariants.append("w18c_inputs_missing")
        run_meta["missing_inputs"] = missing
        return _persist_and_exit(1)
    if invalid_targets:
        failed_invariants.append("invalid_target_fp_ids")
        return _persist_and_exit(1)
    if not target_fp_ids.issubset(W16_ALLOWED_TARGET_FP_IDS):
        failed_invariants.append("target_fp_outside_allowed")
        return _persist_and_exit(1)

    w18c_readback = json.loads(w18c_readback_path.read_text())
    w18c_meta = json.loads(w18c_meta_path.read_text())

    # W18C → W18B → W18A2 chain walk.
    w18b_run_dir = _resolve_w18b_run_dir_from_w18c(w18c_meta)
    w18a_fp_entry: Dict[str, Any] = {}
    w18b_png_relative: str = ""
    fp_id_first = sorted(target_fp_ids)[0]
    if w18b_run_dir is not None:
        try:
            w18b_meta = json.loads(
                (w18b_run_dir / "run_meta.json").read_text()
            )
            w18a_run_dir = _resolve_w18a_run_dir_from_w18b(w18b_meta)
        except Exception:  # noqa: BLE001
            w18a_run_dir = None
        png_path = w18b_run_dir / "png" / f"{fp_id_first}.png"
        if png_path.exists():
            try:
                w18b_png_relative = str(
                    png_path.resolve().relative_to(_REPO_ROOT.resolve())
                )
            except ValueError:
                w18b_png_relative = str(png_path.resolve())
        if w18a_run_dir is not None:
            try:
                base_artifact = json.loads(
                    (w18a_run_dir / "base_layout_prompt.json").read_text()
                )
                by_fp = (base_artifact or {}).get(
                    "base_layout_prompt_by_fp"
                ) or {}
                w18a_fp_entry = by_fp.get(fp_id_first) or {}
            except Exception:  # noqa: BLE001
                w18a_fp_entry = {}

    if not w18a_fp_entry:
        failed_invariants.append("w18a_fp_entry_unresolved")
        run_meta["chain_status"] = "w18a_fp_entry_unresolved"
        return _persist_and_exit(1)

    region_ref_by_bg, diagnostics = _build_region_ref_for_fp(
        fp_id=fp_id_first,
        w18a_fp_entry=w18a_fp_entry,
        w18c_readback=w18c_readback,
        w18b_png_relative_to_repo=w18b_png_relative,
    )

    region_ref_payload = {
        "bg_to_fp_region_ref_by_bg": region_ref_by_bg,
        "fp_id": fp_id_first,
        "policy_note": (
            "Observation payload preview for the background prompt "
            "assembler. W18A2 candidate stays the truth surface; W18C "
            "readback is an observation layer; 10x10 rect/cell values "
            "are coarse relative references, not pixel-precise "
            "coordinates."
        ),
        "join_diagnostics": diagnostics,
    }

    (run_dir / "bg_to_fp_region_ref.json").write_text(
        json.dumps(region_ref_payload, ensure_ascii=False, indent=2)
    )
    run_meta["outputs"].append("bg_to_fp_region_ref.json")

    report = _build_w18d_compatibility_report(
        region_ref_by_bg=region_ref_by_bg,
        w18a_fp_entry=w18a_fp_entry,
        w18c_readback=w18c_readback,
        target_fp_ids=target_fp_ids,
        production_diff_empty=_check_production_diff_empty(),
        db_write_count=0,
        image_import_seen=_check_image_imports_present(),
        image_api_call_count=0,
        vlm_api_call_count=0,
        llm_api_call_count=0,
        missing_inputs=missing,
        prev_run_id=prev_run_dir.name,
    )
    (run_dir / "w18d_compatibility_report.json").write_text(
        json.dumps(report, ensure_ascii=False, indent=2)
    )
    run_meta["outputs"].append("w18d_compatibility_report.json")

    for name, v in report["invariants"].items():
        if not v["pass"] and name not in failed_invariants:
            failed_invariants.append(name)
    if failed_invariants and run_status == "succeeded":
        run_status = "validation_failed"
        exit_code = 1

    run_meta["run_status"] = run_status
    run_meta["exit_code"] = exit_code
    run_meta["failed_invariants"] = failed_invariants

    def esc(x):
        return (
            str(x).replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
        )

    inv_rows = "".join(
        f"<tr><td>{esc(k)}</td>"
        f"<td class=\"{'pass' if v['pass'] else 'fail'}\">"
        f"{'PASS' if v['pass'] else 'FAIL'}</td>"
        f"<td><pre>{esc(json.dumps(v.get('detail'), ensure_ascii=False))[:800]}</pre></td>"
        f"</tr>"
        for k, v in (report.get("invariants") or {}).items()
    )
    bg_sections: List[str] = []
    for bg_id, payload in region_ref_by_bg.items():
        target_rows = "".join(
            f"<tr><td>{esc(r.get('unit_id'))}</td>"
            f"<td>#{esc(r.get('marker_number'))}</td>"
            f"<td>{esc(r.get('label'))}</td>"
            f"<td>{esc(r.get('approximate_10x10_rect'))}</td>"
            f"<td>{esc(r.get('observed_area_label'))}</td>"
            f"<td>{esc(r.get('adjacency_notes'))}</td></tr>"
            for r in payload.get("target_unit_refs") or []
        )
        base_rows = "".join(
            f"<tr><td>#{esc(m.get('marker_number'))}</td>"
            f"<td>{esc(m.get('label'))}</td>"
            f"<td>{esc(m.get('base_layer_decision'))}</td>"
            f"<td>{esc(m.get('visible'))}</td>"
            f"<td>{esc(m.get('confidence'))}</td>"
            f"<td>{esc(m.get('approximate_10x10_rect'))}</td>"
            f"<td>{esc(m.get('approximate_10x10_cell'))}</td>"
            f"<td>{esc(m.get('observed_label_or_area'))}</td></tr>"
            for m in payload.get("base_marker_refs") or []
        )
        transient_rows = "".join(
            f"<tr><td>#{esc(t.get('marker_number'))}</td>"
            f"<td>{esc(t.get('label'))}</td>"
            f"<td>{esc(t.get('unit_id'))}</td>"
            f"<td>{esc(t.get('base_layer_decision'))}</td>"
            f"<td>{esc(t.get('overlay_instruction_hint'))}</td></tr>"
            for t in payload.get("transient_overlay_to_describe") or []
        )
        bg_sections.append(
            f"<section><h2>bg: {esc(bg_id)}</h2>"
            f"<p>base_fp_png_path: <code>{esc(payload.get('base_fp_png_path_relative_to_repo'))}</code></p>"
            f"<p>region_prompt_hint: <pre>{esc(payload.get('region_prompt_hint'))}</pre></p>"
            f"<h3>target_unit_refs (#1..#6 markers)</h3>"
            f"<table><tr><th>unit_id</th><th>#</th><th>label</th>"
            f"<th>10x10 rect</th><th>observed_area</th><th>adjacency_notes</th>"
            f"</tr>{target_rows}</table>"
            f"<h3>base_marker_refs</h3>"
            f"<table><tr><th>#</th><th>label</th><th>decision</th>"
            f"<th>visible</th><th>conf</th><th>rect</th><th>cell</th>"
            f"<th>observed</th></tr>{base_rows}</table>"
            f"<h3>transient_overlay_to_describe</h3>"
            f"<table><tr><th>#</th><th>label</th><th>unit_id</th>"
            f"<th>decision</th><th>overlay_hint</th></tr>{transient_rows}"
            f"</table></section>"
        )

    (run_dir / "index.html").write_text(
        f"""<!doctype html><html><head><meta charset="utf-8">
<title>W18D bg_to_fp_region_ref {esc(run_id)}</title>
<style>body{{font-family:sans-serif;margin:1.5em}}
table{{border-collapse:collapse;margin:0.5em 0}}
td,th{{border:1px solid #ccc;padding:4px 8px;vertical-align:top}}
.pass{{color:#080}} .fail{{color:#b00}}
pre{{white-space:pre-wrap;font-size:0.85em;max-width:84ch}}
section{{margin:1.5em 0}}</style></head><body>
<h1>W18D — bg_to_fp_region_ref {esc(run_id)}</h1>
<p>derived_from(W18C): {esc(prev_run_dir.name)}
| run_status: <b>{esc(run_status)}</b>
| exit_code: {esc(exit_code)}
| llm/vlm/image api calls: <b>0/0/0</b></p>

{''.join(bg_sections)}

<section><h2>invariants</h2>
<table><tr><th>invariant</th><th>status</th><th>detail</th></tr>
{inv_rows}</table></section>

<details><summary>raw run_meta.json</summary>
<pre>{esc(json.dumps(run_meta, ensure_ascii=False, indent=2))}</pre></details>
</body></html>"""
    )
    run_meta["outputs"].append("index.html")

    (run_dir / "run_meta.json").write_text(
        json.dumps(run_meta, ensure_ascii=False, indent=2)
    )
    _maybe_print_imports(args)
    return exit_code


if __name__ == "__main__":
    sys.exit(main())
