"""RUN-063 - BCODR LUC 01: the bidirectional kernel closure of root 6217's shape space (arrival-time field).

BCODR-LUC-01 (2026-09-21) puts BCODR on root 6217. The 200 subroots of Cycle 11 fix a normalized 5-D parameter space
(x3, y3, rho5, x5, y5); the outward field is Paper 09B's critical ray for 0 <= rho <= 0.003, the inward field the five
A_ref-pruned boxes (28, 36, 68, 144, 155). Each of the 195 shape-active boxes gets arrival times T+ (normalized distance to
the ray) and T- (to the prune boxes), a meeting radius max(T+, T-), a balance and a balance entropy H_B, and a scheduling
score. It reports no positive-measure active/prune overlap, 35 boundary-contact pairs, root 131 as the one
zero-radius contact nexus (T+ = T- = 0), and 166, 167, 164, 165, 127, 101, 104 and 103 as the most balanced finite-
radius cells. It ships the ledger (JSON and CSV), a kernel-metric schema, a frontier graph, a verifier, a state record
and VALIDATION. It is evidence, not a canonical document. Here the boxes are put on their exact dyadic grid and every
number is rebuilt from them.

Checks
  A0 anchors      the statements below occur in the document as written
  W1 domain       sec. 1-2: the normalization from the 200 subroots
  W2 arrival      sec. 4-13, 31: T+, T-, the nearest ray point and prune root, the meeting radius, balance, entropy and score
  W3 contacts     sec. 14-16, 25: overlaps and contacts on the exact dyadic grid - among all 200, and active/prune
  W4 frontier     sec. 17-24: the nexus; the ray inside box 131; the finite-radius cells and the most balanced ones; how
                  they depend on where the ray is cut
  W5 ledger       sec. 0, 35: the 195 = 10 + 44 + 141 split (RUN-058), and the part of root 6217's box the 200 boxes cover
  W6 records      the ledger's counts, the CSV, the state, the schema and the graph against each other and the rebuild
  W7 verifier     the verifier, read after this rebuild and never run
  P1 package      the VALIDATION record against the bytes and the archive

Usage: python code/run063_bcodr_luc01.py [--drill] [--blind CID]
"""
import argparse
import collections
import copy
import csv
import hashlib
import inspect
import io
import json
import math
import re

import numpy as np

import gate
import run048_uesfcm_cycles_12_14 as r48
from corpus import SOURCES, TREE, source_bytes, walk_sources

PKG = "main.zip!/BCODR/BCODR_LUC_01_Package_v0.1.zip!/"
DOC = PKG + "BCODR_LUC_01_Root6217_Bidirectional_Kernel_Closure_v0.1.md"
LEDGER = PKG + "BCODR_LUC_01_Arrival_Information_Ledger_v0.1.json"
CSV = PKG + "BCODR_LUC_01_Arrival_Information_Ledger_v0.1.csv"
SCHEMA = PKG + "BCODR_LUC_01_Kernel_Metric_Schema_v0.1.json"
GRAPH = PKG + "BCODR_LUC_01_First_Frontier_Graph_v0.1.dot"
PNG = PKG + "BCODR_LUC_01_First_Frontier_Graph_v0.1.png"
VERIFIER = PKG + "BCODR_LUC_01_Verify_Arrival_Ledger.py"
STATE = PKG + "BCODR_LUC_01_STATE_v0.1.json"
VALIDATION = PKG + "BCODR_LUC_01_VALIDATION.json"
LOG = TREE / "data" / "gate-logs" / "run063-bcodr-luc01.json"
LOG58 = TREE / "data" / "gate-logs" / "run058-lesr-paper08.json"
MANIFEST = TREE / "data" / "SOURCE_MANIFEST.v1.json"
CACHE = TREE / "data" / "cache" / "run063-searches.json"     # data/cache is not committed
X30, S, X5 = -0.01215883209899, 0.00882, 0.019770946347947549
U, V = 5.157126245268359, -0.18922818990664067               # Paper 09B's critical velocity, as the ledger carries it
PRUNE = [28, 36, 68, 144, 155]
RHO_MAX = 0.003


def load_inputs():
    blobs = {n: source_bytes(n) for n in SOURCES}
    want = (DOC, LEDGER, CSV, SCHEMA, GRAPH, PNG, VERIFIER, STATE, VALIDATION)
    got = {leaf.id: d for leaf, d in walk_sources(blobs, keep=lambda l: l.id in want) if d is not None}
    rows = {r[0]: r for r in json.loads(MANIFEST.read_text(encoding="utf-8"))["leaves"] if r[0] in want}
    c11 = r48.load_inputs()
    return {"text": got[DOC].decode("utf-8"), "ledger": json.loads(got[LEDGER]), "csv": got[CSV].decode("utf-8"), "schema": json.loads(got[SCHEMA]),
            "graph": got[GRAPH].decode("utf-8"), "verifier": got[VERIFIER].decode("utf-8"), "state": json.loads(got[STATE]),
            "validation": json.loads(got[VALIDATION]), "bytes": {k: got[k] for k in want}, "manifest_rows": rows,
            "subroots": c11["subroots"], "root": c11["root"], "log58": json.loads(LOG58.read_text(encoding="utf-8"))}


# ---------------------------------------------------------------- the field, rebuilt

def domain(sub):
    C, H = np.array(sub["centers"], dtype=float), np.array(sub["halfwidths"], dtype=float)
    lo, hi = (C - H).min(axis=0), (C + H).max(axis=0)
    return C, H, lo, hi, (lo + hi) / 2, hi - lo


def ray(rho):
    return np.array([X30 + S * math.cos(math.pi - rho * U), S * math.sin(math.pi - rho * U), rho, X5, rho * V])


def to_box(p, c, h):
    return float(np.linalg.norm(np.maximum(0.0, np.abs(p - c) - h)))


def nearest_on_ray(c, h, mid, scale, rho_max=RHO_MAX):
    """the least normalized distance from the box to the ray on [0, rho_max]: a 600-step scan, then golden section in the
    best step's neighbourhood"""
    f = lambda r: to_box((ray(r) - mid) / scale, c, h)
    grid = np.linspace(0, rho_max, 601)
    k = min(range(len(grid)), key=lambda i: f(grid[i]))
    a, b = grid[max(k - 1, 0)], grid[min(k + 1, len(grid) - 1)]
    g = (math.sqrt(5) - 1) / 2
    x1, x2 = b - g * (b - a), a + g * (b - a)
    f1, f2 = f(x1), f(x2)
    for _ in range(100):
        if f1 < f2:
            b, x2, f2 = x2, x1, f1
            x1 = b - g * (b - a)
            f1 = f(x1)
        else:
            a, x1, f1 = x1, x2, f2
            x2 = a + g * (b - a)
            f2 = f(x2)
    cand = [(f(grid[0]), 0.0), (f(grid[-1]), rho_max), ((f1, x1) if f1 < f2 else (f2, x2))]
    return min(cand)


def field(sub):
    """per active box: T+ with the nearest ray rho, T- with the nearest prune root (normalized coordinates)"""
    C, H, lo, hi, mid, scale = domain(sub)
    Cn, Hn = (C - mid) / scale, H / scale
    out = {}
    for i in range(len(C)):
        if i in PRUNE:
            continue
        tp, rr = nearest_on_ray(Cn[i], Hn[i], mid, scale)
        tms = [(float(np.linalg.norm(np.maximum(0.0, np.abs(Cn[i] - Cn[j]) - (Hn[i] + Hn[j])))), j) for j in PRUNE]
        tm = min(t for t, _ in tms)
        out[str(i)] = [tp, rr, tm, [j for t, j in tms if t <= tm + 1e-15]]          # every prune root at the least distance
    return {"low": lo.tolist(), "high": hi.tolist(), "scale": scale.tolist(), "cells": out}


def grid(sub, root):
    """the boxes on the dyadic grid of root 6217's box (2^20 units per side): overlaps among all 200; active/prune
    contacts by the number of zero-thickness dimensions; the boxes touching a prune box"""
    C, H = np.array(sub["centers"], dtype=float), np.array(sub["halfwidths"], dtype=float)
    rc, rh = np.array(root[0]), np.array(root[1])
    K = 2 ** 20
    fl, fh = (C - H - (rc - rh)) / (2 * rh) * K, (C + H - (rc - rh)) / (2 * rh) * K
    lo, hi = np.round(fl), np.round(fh)
    err = float(max(np.abs(fl - lo).max(), np.abs(fh - hi).max()))
    common = lambda i, j: np.minimum(hi[i], hi[j]) - np.maximum(lo[i], lo[j])
    overlaps = sum(1 for i in range(len(C)) for j in range(i + 1, len(C)) if np.all(common(i, j) > 0))
    pairs, dims, touching = 0, collections.Counter(), set()
    for i in range(len(C)):
        if i in PRUNE:
            continue
        for j in PRUNE:
            a = common(i, j)
            if np.all(a >= 0) and not np.all(a > 0):
                pairs += 1
                dims[int(np.sum(a == 0))] += 1
                touching.add(i)
    return {"rounding": err, "overlaps": overlaps, "pairs": pairs, "dims": {str(k): v for k, v in sorted(dims.items())}, "touching": sorted(touching)}


def frontier(sub):
    """the ray's points in boxes; the most balanced finite-radius cells for other cuts of the ray"""
    C, H, lo, hi, mid, scale = domain(sub)
    Cn, Hn = (C - mid) / scale, H / scale
    holders = set()
    for r in np.linspace(0, RHO_MAX, 3001):
        p = (ray(r) - mid) / scale
        holders.add(tuple(i for i in range(len(C)) if np.all(np.abs(p - Cn[i]) <= Hn[i] + 1e-12)))
    act = [i for i in range(len(C)) if i not in PRUNE]
    tm = {i: min(float(np.linalg.norm(np.maximum(0.0, np.abs(Cn[i] - Cn[j]) - (Hn[i] + Hn[j])))) for j in PRUNE) for i in act}
    cuts = {}
    for rmax in (0.001, 0.002, 0.003, 0.004, 0.006):
        tp = {i: nearest_on_ray(Cn[i], Hn[i], mid, scale, rmax)[0] for i in act}
        fin = [i for i in act if tp[i] > 1e-12 and tm[i] > 1e-12]
        ent = {}
        for i in fin:
            q = tm[i] / (tp[i] + tm[i])
            ent[i] = (-q * math.log(q) - (1 - q) * math.log(1 - q)) / math.log(2)
        cuts[str(rmax)] = sorted(fin, key=lambda i: -ent[i])[:8]
    return {"holders": sorted(holders), "cuts": cuts}


def _key(fn, extra=""):
    digest = hashlib.sha256(inspect.getsource(fn).encode())
    for helper in (domain, ray, to_box, nearest_on_ray):
        digest.update(inspect.getsource(helper).encode())
    digest.update(extra.encode())
    return digest.hexdigest()


def searches(inputs):
    cached = json.loads(CACHE.read_text(encoding="utf-8")) if CACHE.exists() else {}
    out = {}
    tag = json.dumps([inputs["subroots"], inputs["root"]], sort_keys=True)
    jobs = (("field", field, lambda: field(inputs["subroots"])), ("grid", grid, lambda: grid(inputs["subroots"], inputs["root"])),
            ("frontier", frontier, lambda: frontier(inputs["subroots"])))
    for name, fn, call in jobs:
        key = _key(fn, tag)
        if cached.get(name, {}).get("key") != key:
            cached[name] = {"key": key, "value": json.loads(json.dumps(call()))}
            CACHE.parent.mkdir(parents=True, exist_ok=True)
            CACHE.write_text(json.dumps(cached, indent=1) + "\n", encoding="utf-8")
        out[name] = cached[name]["value"]
    return out


# ---------------------------------------------------------------- checks

ANCHORS = {"A0": [r"\ell=[-0.024243718609038,0,0,0.012319849090351,-0.012319849090351],", r"u=[-0.012121859304519,0.012121859304519,0.026179938779915,"
                  r"0.024639698180702,0].", r"\text{positive-measureactive/pruneoverlaps}=0.", r"$$\boxed{35}$$個active/pruneboxpairs",
                  r"\boxed{T_+(131)=0}", r"\boxed{T_-(131)=0.}", r"\boxed{166,167,164,165,127,101,104,103.}",
                  r"P_i=\frac{H_B}{1+T_\cap/\operatorname{median}(T_\cap)}.", r"195=10_{\rmlocal}+44_{\rmsplit}+141_{\rmtail}."]}
CLAIMS = {
    "domain_claim": {"text": True, "ledger": [True, True, True]},
    # T+ to 2e-9 (the ledger's ray grid), T- to 3e-16; nine cells sit at equal distance from two prune boxes, where the
    # ledger names one of them; the scores divide by the median over the finite-radius cells, not over all
    "arrival_claim": {"T_plus": 2e-09, "T_minus": 3e-16, "prune_roots": [140, 140], "ties": [1, 6, 31, 51, 64, 74, 96, 127, 168],
                      "formulas_below_1e-12": [True, True, True, True], "score_median": 0.766444, "median_of_all": 0.696945},
    # 64 active/prune contact pairs on the exact grid (40 across a 4-face), not the 35 reported
    "contacts_claim": {"rounding_below": True, "overlaps_all": 0, "pairs": [64, 35], "dims": {"1": 40, "2": 14, "3": 8, "4": 2}, "touching": [55, 55],
                       "positive_overlaps": 0},
    "frontier_claim": {"nexus": [131], "ray_holders": [[131]], "finite": 140, "top8": [166, 167, 164, 165, 127, 101, 104, 103], "text_top8": True,
                       "ledger_top8": [166, 167, 164, 165, 127, 101, 104, 103], "at_end": 178,
                       "cuts": {"0.001": [164, 165, 127, 166, 167, 101, 104, 103], "0.002": [164, 166, 165, 167, 127, 101, 104, 103],
                                "0.003": [166, 167, 164, 165, 127, 101, 104, 103], "0.004": [166, 167, 164, 165, 160, 168, 127, 101],
                                "0.006": [166, 167, 165, 164, 100, 101, 104, 168]}},
    "ledger_claim": {"classes": {"LOCAL_ONLY": 10, "SPLIT_AT_RHO_CUT": 44, "TAIL_ONLY": 141}, "covered": 0.559, "missing_in_branch": 0.146},
    "records_claim": {"state_counts": True, "csv": [195, True, True], "graph_cells": [101, 103, 104, 127, 131, 164, 165, 166, 167], "graph_is_nexus_and_top8": True,
                      "schema_roles": ["ZERO_RADIUS_CONTACT_NEXUS", "OUTWARD_SEED_CONTACT", "INWARD_CERT_BOUNDARY_CONTACT", "FINITE_RADIUS_FIELD_CELL"],
                      "next": "BCODR-LUC-02 — Atomic Cut and Structural Recomposition"},
    "verifier_facts": {"lines": 32, "reads_boxes": False, "asserts_constants": 4, "prints_pairs_unchecked": True},
    "package_claim": {"digests": {"paper_sha256": True, "ledger_sha256": True, "csv_sha256": True, "schema_sha256": True, "graph_sha256": True,
                                  "verifier_sha256": True, "state_sha256": True}, "dot_digested": False, "manifest": True, "utf8": True, "delimiters": ["PASS", []],
                      "replay": ["PASS", "shape-active cells = 195", "boundary contact pairs = 35", "positive-measure active/prune overlap = 0",
                                 "zero-radius nexus ids = [131]", "top finite balanced ids = [166, 167, 164, 165, 127, 101, 104, 103]"]},
}


def sig(x, n=2):
    return float(f"{x:.{n - 1}e}")


def w1_domain(w):
    f, L = w["search"]["field"], w["ledger"]["normalization"]
    printed_lo = [-0.024243718609038, 0, 0, 0.012319849090351, -0.012319849090351]
    printed_hi = [-0.012121859304519, 0.012121859304519, 0.026179938779915, 0.024639698180702, 0]
    got = {"text": max(abs(a - b) for a, b in zip(f["low"] + f["high"], printed_lo + printed_hi)) < 1e-15,
           "ledger": [f["low"] == L["domain_low"], f["high"] == L["domain_high"], max(abs(a - b) for a, b in zip(f["scale"], L["scale"])) == 0.0]}
    w["w1"] = got
    return [] if got == w["domain_claim"] else [f"the domain: {got}"]


def w2_arrival(w):
    """the rebuilt T+ and T- against the ledger's, cell by cell; the ledger's own meeting radius, balance, entropy and score
    against their definitions"""
    f, cells = w["search"]["field"]["cells"], w["ledger"]["cells"]
    dp = max(abs(f[str(c["local_index"])][0] - c["T_plus"]) for c in cells)
    dm = max(abs(f[str(c["local_index"])][2] - c["T_minus"]) for c in cells)
    roots = sum(c["nearest_prune_root"] in f[str(c["local_index"])][3] for c in cells if c["T_minus"] > 1e-12)
    ties = sorted(c["local_index"] for c in cells if len(f[str(c["local_index"])][3]) > 1 and c["T_minus"] > 1e-12)
    # sec. 31 writes median(T_cap); the scores use the median over the 140 finite-radius cells
    med = float(np.median([c["meeting_radius"] for c in cells if c["T_plus"] > 0 and c["T_minus"] > 0]))

    def ent(c):
        s = c["T_plus"] + c["T_minus"]
        if s == 0:
            return 1.0
        q = c["T_minus"] / s
        return 0.0 if q in (0.0, 1.0) else (-q * math.log(q) - (1 - q) * math.log(1 - q)) / math.log(2)
    formula = [max(abs(c["meeting_radius"] - max(c["T_plus"], c["T_minus"])) for c in cells),
               max(abs(c["balance"] - ((c["T_minus"] - c["T_plus"]) / (c["T_plus"] + c["T_minus"]) if c["T_plus"] + c["T_minus"] else 0.0)) for c in cells),
               max(abs(c["balance_entropy"] - ent(c)) for c in cells),
               max(abs(c["priority_score"] - ent(c) / (1 + c["meeting_radius"] / med)) for c in cells)]
    got = {"T_plus": sig(dp, 1), "T_minus": sig(dm, 1), "prune_roots": [roots, sum(1 for c in cells if c["T_minus"] > 1e-12)], "ties": ties,
           "formulas_below_1e-12": [x < 1e-12 for x in formula], "score_median": round(med, 6),
           "median_of_all": round(float(np.median([c["meeting_radius"] for c in cells])), 6)}
    w["w2"] = got
    return [] if got == w["arrival_claim"] else [f"the arrival times: {got}"]


def w3_contacts(w):
    """on the exact grid: no two of the 200 boxes overlap (they are atomic cells); no active box overlaps a prune box; 64
    active/prune pairs touch - not 35 - 40 across a 4-face; 55 active boxes touch a prune box (the state's 54 contact
    cells and the nexus)"""
    g, cnt = w["search"]["grid"], w["ledger"]["counts"]
    got = {"rounding_below": g["rounding"] < 1e-6, "overlaps_all": g["overlaps"], "pairs": [g["pairs"], cnt["active_prune_boundary_contact_pairs"]],
           "dims": g["dims"], "touching": [len(g["touching"]), cnt["inward_boundary_contact_cells"] + cnt["zero_radius_contact_nexus_cells"]],
           "positive_overlaps": cnt["positive_measure_active_prune_overlaps"]}
    w["w3"] = got
    return [] if got == w["contacts_claim"] else [f"the contacts: {got}"]


def w4_frontier(w):
    """the nexus is 131, which holds the whole ray (the barrier sits on its corner rho = 0, y3 = 0); 140 finite-radius
    cells; the most balanced eight are the text's - and for 182 of 195 cells the nearest ray point is its end rho = 0.003,
    so the eight move with the cut"""
    f, fr, L = w["search"]["field"]["cells"], w["search"]["frontier"], w["ledger"]
    nexus = sorted(int(i) for i, v in f.items() if v[0] < 1e-12 and v[2] < 1e-12)
    fin = [i for i, v in f.items() if v[0] > 1e-12 and v[2] > 1e-12]
    got = {"nexus": nexus, "ray_holders": fr["holders"], "finite": len(fin), "top8": fr["cuts"]["0.003"],
           "text_top8": fr["cuts"]["0.003"] == [166, 167, 164, 165, 127, 101, 104, 103], "ledger_top8": [c["local_index"] for c in L["top_balanced_finite_radius_cells"][:8]],
           "at_end": sum(1 for v in f.values() if v[1] >= RHO_MAX - 1e-9), "cuts": fr["cuts"]}
    w["w4"] = got
    return [] if got == w["frontier_claim"] else [f"the frontier: {got}"]


def w5_ledger(w):
    """sec. 0, 35: the ledger's rho classes are Paper 08's 10 / 44 / 141 (RUN-058), and the 200 boxes cover 55.9 % of root
    6217's box - the 14.6 % closed for A3+ only, and in the far branch, has no cell here (RUN-058)"""
    cls = collections.Counter(c["rho_class"] for c in w["ledger"]["cells"])
    s = w["log58"]["w4"]["shares"]
    got = {"classes": dict(sorted(cls.items())), "covered": s["inside"], "missing_in_branch": s["outside_f3"]}
    w["w5"] = got
    return [] if got == w["ledger_claim"] else [f"the ledger's domain: {got}"]


def w6_records(w):
    L, st, sc = w["ledger"], w["state"], w["schema"]
    text = w["csv"]
    bom = text.startswith("﻿")
    rows = list(csv.DictReader(io.StringIO(text.lstrip("﻿"))))
    same = all(abs(float(r[k]) - c[k]) == 0.0 for r, c in zip(rows, L["cells"]) for k in ("T_plus", "T_minus", "meeting_radius", "balance", "balance_entropy", "priority_score"))
    nodes = sorted({int(m) for m in re.findall(r'^"C(\d+)" \[label', w["graph"], re.M)})
    got = {"state_counts": st["counts"] == L["counts"], "csv": [len(rows), same, bom], "graph_cells": nodes,
           "graph_is_nexus_and_top8": nodes == sorted([131] + [c["local_index"] for c in L["top_balanced_finite_radius_cells"][:8]]),
           "schema_roles": sc["cell_roles"], "next": st["next"]}
    w["w6"] = got
    return [] if got == w["records_claim"] else [f"the records: {got}"]


def w7_verifier(w):
    """read after the rebuild and never run: it reads the ledger alone, asserts its counts as constants, and recomputes no
    distance; the 35 it prints is the ledger's"""
    code = w["verifier"]
    got = {"lines": code.count("\n"), "reads_boxes": bool(re.search(r"center|halfwidth|subroot", code)),
           "asserts_constants": len(re.findall(r'assert D\["counts"\]', code)), "prints_pairs_unchecked": "boundary contact pairs" in code and "pairs ==" not in code}
    w["w7"] = got
    return [] if got == w["verifier_facts"] else [f"the verifier: {got}"]


def p1_package(w):
    v, B = w["validation"], w["bytes"]
    sha = lambda b: hashlib.sha256(b).hexdigest()
    keys = {"paper_sha256": DOC, "ledger_sha256": LEDGER, "csv_sha256": CSV, "schema_sha256": SCHEMA, "graph_sha256": PNG, "verifier_sha256": VERIFIER,
            "state_sha256": STATE}
    body = B[DOC].decode("utf-8")
    # "graph_sha256" is the PNG's digest; the DOT the graph is drawn from is not digested
    got = {"digests": {k: v[k] == sha(B[f]) for k, f in keys.items()}, "dot_digested": any(sha(B[GRAPH]) == x for x in v.values()),
           "manifest": all(w["manifest_rows"][k][2] == sha(b) for k, b in B.items()), "utf8": v["utf8"] is True,
           "delimiters": [v["math_delimiters"], sorted(set(re.findall(r"\\\(|\\\)|\\\[|\\\]", body)))],
           "replay": v["fresh_replay_stdout"].split("\n")}
    w["p1"] = got
    return [] if got == w["package_claim"] else [f"the package: {got}"]


def a0_anchors(w):
    text = gate.squash(w["text"])
    return [f"anchor not found: {a[:60]}" for a in ANCHORS["A0"] if a not in text]


CHECKS = {"A0": a0_anchors, "W1": w1_domain, "W2": w2_arrival, "W3": w3_contacts, "W4": w4_frontier, "W5": w5_ledger, "W6": w6_records, "W7": w7_verifier,
          "P1": p1_package}
DEPENDS = {"A0": {"text"}, "W1": {"search", "ledger", "domain_claim"}, "W2": {"search", "ledger", "arrival_claim"}, "W3": {"search", "ledger", "contacts_claim"},
           "W4": {"search", "ledger", "frontier_claim"}, "W5": {"ledger", "log58", "ledger_claim"},
           "W6": {"ledger", "state", "schema", "csv", "graph", "records_claim"}, "W7": {"verifier", "verifier_facts"},
           "P1": {"validation", "bytes", "manifest_rows", "package_claim"}}


def drill_cases(base):
    def edit(obj, fn):
        x = copy.deepcopy(obj)
        fn(x)
        return x

    text, s, L = base["text"], base["search"], base["ledger"]
    row = base["csv"].split("\n")
    return [
        ("K0-unmodified", "control", {}, set()),
        ("K1-crlf", "control", {"text": text.replace("\n", "\r\n")}, set()),
        ("K2-validation-keys-sorted", "control", {"validation": json.loads(json.dumps(base["validation"], sort_keys=True))}, set()),
        ("K3-ledger-keys-sorted", "control", {"ledger": json.loads(json.dumps(L, sort_keys=True))}, set()),
        ("M1-text-pairs", "mutation", {"text": text.replace("個 active/prune box pairs", "個 active-prune box pairs")}, {"A0"}),
        ("M2-domain", "mutation", {"ledger": edit(L, lambda x: x["normalization"]["domain_low"].__setitem__(0, -0.0242))}, {"W1"}),
        ("M3-T-plus", "mutation", {"search": edit(s, lambda x: x["field"]["cells"]["0"].__setitem__(0, x["field"]["cells"]["0"][0] + 1e-6))}, {"W2"}),
        ("M4-tie", "mutation", {"search": edit(s, lambda x: x["field"]["cells"]["6"].__setitem__(3, [36]))}, {"W2"}),
        ("M5-pairs", "mutation", {"search": edit(s, lambda x: x["grid"].update(pairs=35))}, {"W3"}),
        ("M6-contact-cells", "mutation", {"ledger": edit(L, lambda x: x["counts"].update(inward_boundary_contact_cells=53))}, {"W3", "W6"}),
        ("M7-ray-holder", "mutation", {"search": edit(s, lambda x: x["frontier"]["holders"].append([130]))}, {"W4"}),
        ("M8-cut", "mutation", {"search": edit(s, lambda x: x["frontier"]["cuts"].update({"0.004": [166, 167, 164, 165, 127, 101, 104, 103]}))}, {"W4"}),
        ("M9-coverage", "mutation", {"log58": edit(base["log58"], lambda x: x["w4"]["shares"].update(inside=0.6))}, {"W5"}),
        ("M10-rho-class", "mutation", {"ledger": edit(L, lambda x: x["cells"][0].update(rho_class="LOCAL_ONLY"))}, {"W5"}),
        ("M11-graph-node", "mutation", {"graph": base["graph"].replace("}", '"C99" [label="cell 99"];\n}')}, {"W6"}),
        ("M12-csv-value", "mutation", {"csv": "\n".join(row[:1] + [row[1].replace(",0.25,", ",0.26,", 1)] + row[2:])}, {"W6"}),
        ("M13-verifier-boxes", "mutation", {"verifier": base["verifier"] + "\ncenters = D['cells'][0]['center']\n"}, {"W7"}),
        ("M14-validation-digest", "mutation", {"validation": {**base["validation"], "csv_sha256": "0" * 64}}, {"P1"}),
        ("M15-paper-bytes", "mutation", {"bytes": {**base["bytes"], DOC: base["bytes"][DOC] + b" "}}, {"P1"}),
    ]


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--drill", action="store_true")
    ap.add_argument("--blind", metavar="CID")
    args = ap.parse_args()
    inputs = load_inputs()
    base = {**inputs, "search": searches(inputs)}

    def build():
        return {**copy.deepcopy(base), **copy.deepcopy(CLAIMS)}

    if args.blind:
        CHECKS[args.blind] = lambda w: []
        args.drill = True
    w = build()
    results = {}
    for c, fn in CHECKS.items():
        try:
            results[c] = fn(w)
        except KeyError as e:
            results[c] = [f"claim missing: {e}"]
    for c, f in results.items():
        print(f"{c} {'PASS' if not f else 'FAIL'}", *(f"\n     {x}" for x in f[:6]))
    for key in ("w1", "w2", "w3", "w4", "w5", "w6", "w7", "p1"):
        print(key, "=", json.dumps(w.get(key), default=str, ensure_ascii=False))
    if not args.drill:
        return
    cases = drill_cases(base)
    if args.blind:
        cases = [c for c in cases if args.blind in c[3]]
    d = gate.run_drill(build, CHECKS, DEPENDS, cases)
    summary = gate.summarize(d, CHECKS)
    print(gate.report_drill(summary))
    for x in d:
        if not x["ok"]:
            print("   DRILL FAIL", x)
    if args.blind:
        n = sum(1 for x in d if args.blind in x["expected"] and args.blind not in x["tripped"])
        print(f"blind {args.blind}: drill reported it blind in {n} cases (nothing written)")
        return
    log = {"run": "RUN-063", "subject": "BCODR LUC 01: the bidirectional kernel closure of root 6217's shape space", "document": DOC,
           "checks": {c: {"pass": not f, "failures": f} for c, f in results.items()},
           **{k: w.get(k) for k in ("w1", "w2", "w3", "w4", "w5", "w6", "w7", "p1")}, "drill": summary}
    LOG.write_text(json.dumps(log, ensure_ascii=False, indent=1, default=float) + "\n", encoding="utf-8")


if __name__ == "__main__":
    main()
