"""RUN-007 - Round 06 (v0.6.1): chirality escape, the eight-dimensional five-link search and the local stability draft.

Round 06 leaves the mirror-symmetric five-link of Round 05 (RUN-006) for the general five-link near it: four symmetric
parameters (l1, l2, beta, delta) and four antisymmetric ones (d_l1, d_l2, d_alpha, d_beta), lengths (l1 + d_l1,
l2 + d_l2, l3, l2 - d_l2, l1 - d_l1) and directions (alpha + d_alpha, beta + d_beta, 0, -beta + d_beta,
-alpha + d_alpha), scored by the congruent scale s_cong = min{s+, s-}. It scans the four antisymmetric modes one at a
time, searches all eight parameters (best congruent 0.998557207698881, 3.47e-4 below the event root), samples 1,600
curves for a contact-topology census (five signatures in the top twenty), samples 6,300 more in a local escape audit
(none above the root), and samples symmetric parameter boxes for a local stability draft.

Checks (each returns a list of failures; empty = pass)
  A1 reference      the reference is Round 05's event solution; its two handednesses are the event scale, at 3pi/2
                    and pi/2, with nine local minima each and no chirality gap; the logged escape curve is the stated
                    escape parameters in the general family, with l3 = 1 - 2(l1 + l2)
  A2 modes          each of the 404 mode rows: its plus and minus values are the 2,048-phase grid minima of the curve
                    and of its mirror image, its congruent value and gap are theirs; each mode's summary is its rows'
  A3 mirror         in every mode the plus value at t is the minus value at -t, as an antisymmetric mode requires
  A4 escape         the escape curve's two handednesses, their phases and their local-minimum counts on 131,072
                    phases are the stated ones, and the improvement and the distance to 1 are the differences they name
  A5 census         each of the twenty census rows: coarse values are the 2,048-phase grid minima, refined values and
                    phases are this run's, the winning branch and its contact signature are this run's; five distinct
                    signatures
  A6 audit          each of the fifteen logged audit candidates' values reproduce; the gains, the antisymmetric norms,
                    the best non-base gain and the count above the root are theirs; 7 radii x 900 = 6,300
  A7 stability      the base margins are the root's identity margins; the Jacobian figures are Round 05's; every box
                    sample of this run keeps the four signatures, and each stated box minimum lies between the base
                    margin and its first-order lower bound
  A8 consistency    the README, the report, the interpretation note, the audit note and METHOD.md state the data's
                    numbers, tables and method

Drill: each plant names the checks that must trip - trip meaning a failure the unplanted package does not already
have; controls must trip nothing.

Usage:
  python code/run007_round06_chirality_escape.py [--drill [--log PATH] | --blind A#]
"""
import argparse
import copy
import csv
import io
import json
import math
import pathlib
import re

import numpy as np

from corpus import TREE, sha256, source_bytes
import gate
from run001_corpus_identity import restore_escapes
from run003_round02_phase_scan_chirality import exact_min, exact_scale, legs, mirror
from run004_round03_symmetric_links import contacts, grid_values, load, same_B, strict_minima
from run005_round04_branch_equalization import num, table
from run006_round05_contact_events import grad, identity_margins

RID = "round-v0.6.1"
LOG = TREE / "data" / "gate-logs" / "run007-round06-chirality-escape.json"
LABELS = ("B1", "B2", "B3", "B4")
MODES = {"outer_length_antisym": 4, "inner_length_antisym": 5, "outer_angle_antisym": 6, "inner_angle_antisym": 7}
COARSE = 2048
FINE_COUNT = 131072


# ---------------------------------------------------------------- the world

def build_world():
    f, f5 = load(RID), load("round-v0.5")
    md = lambda n: restore_escapes(f[n].decode("utf-8"))
    rows = list(csv.DictReader(io.StringIO(f["data/topology_escape_curve.csv"].decode("utf-8"))))
    return {
        "readme": md("README.md"), "report": md("reports/ROUND_06_REPORT.md"),
        "interpretation": md("reports/ROUND_06_INTERPRETATION.md"), "audit_note": md("reports/ROUND_06_LOCAL_ESCAPE_AUDIT.md"),
        "method": md("src/METHOD.md"),
        "summary": json.loads(f["data/round06_summary.json"]),
        "modes": json.loads(f["data/antisymmetric_mode_profiles.json"]),
        "census": json.loads(f["data/topology_census.json"]),
        "audit": json.loads(f["data/local_escape_audit.json"]),
        "curve": np.array([[float(r["x"]), float(r["y"])] for r in rows]),
        "round05": json.loads(f5["data/round05_summary.json"]),
        "legs": ((3 + 4 * math.sqrt(3)) / 18, (4 + math.sqrt(3)) / 6),
        "cert_scale_divisor": 1.0048,
        "rot_sign": 1,
        "formula_B": same_B,
    }


# ---------------------------------------------------------------- the general five-link

def vertices(st):
    """state (l1, l2, beta, delta, d_l1, d_l2, d_alpha, d_beta), angles in radians; complex-safe"""
    l1, l2, b, d, dl1, dl2, da, db = st
    a = b + d
    l3 = 1 - 2 * (l1 + l2)
    pts = [(0 * l1, 0 * l1)]
    for th, L in zip((a + da, b + db, 0 * b, -b + db, -a + da), (l1 + dl1, l2 + dl2, l3, l2 - dl2, l1 - dl1)):
        x, y = pts[-1]
        pts.append((x + L * np.cos(th), y + L * np.sin(th)))
    return pts


def curve(st):
    return np.array([[complex(x).real, complex(y).real] for x, y in vertices(st)])


FLIP = np.array([1, 1, 1, 1, -1, -1, -1, -1])


def closed8(w, st):
    """the four branch values at their event phases for the general five-link (Round 05's identities): link 1, then
    link 2, parallel to the leg x = 0; the endpoints tied on the hypotenuse; the endpoints tied on the leg x = 0"""
    A, B = legs(w)
    q = vertices(st)
    l1, l2, b, d, dl1, dl2, da, db = st
    c, s = np.cos, np.sin
    X = lambda ph, v: v[0] * c(ph) - v[1] * s(ph)
    Y = lambda ph, v: v[0] * s(ph) + v[1] * c(ph)
    H = lambda ph, v: X(ph, v) / A + Y(ph, v) / B
    th5 = np.arctan(q[5][1] / q[5][0])
    f1, f2, f3, f4 = math.pi / 2 - (b + d + da), math.pi / 2 - (b + db), 2 * math.pi / 3 - th5, 3 * math.pi / 2 - th5
    Bm = w["formula_B"](B)
    return np.array([H(f1, q[3]) - X(f1, q[0]) / A - Y(f1, q[0]) / Bm,
                     H(f2, q[3]) - X(f2, q[1]) / A - Y(f2, q[0]) / Bm,
                     H(f3, q[0]) - X(f3, q[3]) / A - Y(f3, q[2]) / Bm,
                     H(f4, q[2]) - X(f4, q[0]) / A - Y(f4, q[5]) / Bm])


def grad8(w, st, h=1e-30):
    G = np.zeros((4, 8))
    for j in range(8):
        z = np.array(st, dtype=complex)
        z[j] += 1j * h
        G[:, j] = closed8(w, z).imag / h
    return G


def fast_grid(w, p, n):
    """the exact scale on n phases 2 pi k / n, all at once (the same rotation, legs and B term as exact_scale)"""
    A, B = legs(w)
    ph = w["rot_sign"] * 2 * np.pi * np.arange(n) / n
    c, s = np.cos(ph)[:, None], np.sin(ph)[:, None]
    x = p[:, 0][None, :] * c - p[:, 1][None, :] * s
    y = p[:, 0][None, :] * s + p[:, 1][None, :] * c
    return (x / A + y / B).max(axis=1) - x.min(axis=1) / A - y.min(axis=1) / w["formula_B"](B)


def handed(w, st):
    """(s+, phase+), (s-, phase-): the least exact scale over all phases of the curve and of its mirror image"""
    p = curve(st)
    return exact_min(w, p), exact_min(w, mirror(p))


def coarse(w, st):
    p = curve(st)
    return float(fast_grid(w, p, COARSE).min()), float(fast_grid(w, mirror(p), COARSE).min())


def ref_state(w):
    P = w["summary"]["reference"]["parameters"]
    return np.array([P["l1"], P["l2"], math.radians(P["beta_degrees"]), math.radians(P["delta_degrees"]), 0, 0, 0, 0])


def escape_state(w):
    P = w["summary"]["topology_escape"]["parameters"]
    return np.array([P["l1"], P["l2"], math.radians(P["beta_degrees"]), math.radians(P["delta_degrees"]),
                     P["antisym_outer_length"], P["antisym_inner_length"], math.radians(P["antisym_outer_angle_degrees"]),
                     math.radians(P["antisym_inner_angle_degrees"])])


def signature(w, p, phase):
    left, bottom, hyp = contacts(w, p, phase)
    return {"left": left, "bottom": bottom, "hypotenuse": hyp}


# ---------------------------------------------------------------- the checks

def a1_reference(w):
    failures = []
    S = w["summary"]
    R = S["reference"]
    E5 = w["round05"]["event_solution"]
    P, P5 = R["parameters"], E5["parameters"]
    for k in ("l1", "l2", "l3", "beta_degrees", "delta_degrees", "alpha_degrees"):
        if abs(P[k] - P5[k]) > 1e-15:
            failures.append(f"reference {k} {P[k]!r} is not Round 05's {P5[k]!r}")
    if abs(R["event_scale"] - E5["common_scale"]) > 1e-16:
        failures.append("the reference event scale is not Round 05's")
    st = ref_state(w)
    (sp, pp), (sm, pm) = handed(w, st)
    rc = R["refined_congruent"]
    for label, got, want in (("plus", sp, rc["orientation_preserving"]["scale"]), ("minus", sm, rc["reflected"]["scale"]),
                             ("congruent", min(sp, sm), rc["congruent_scale"]), ("event", min(sp, sm), R["event_scale"])):
        if abs(got - want) > 1e-13:
            failures.append(f"reference {label}: this run {got!r}, stated {want!r}")
    # the four events are level at the root, so a least phase is any of them: the stated one must reach the least
    # scale and be a local minimum
    for label, p, s_, rec in (("plus", curve(st), sp, rc["orientation_preserving"]), ("minus", mirror(curve(st)), sm, rc["reflected"])):
        ph = rec["phase"]
        if abs(exact_scale(w, p, ph) - s_) > 1e-13 or not exact_scale(w, p, ph) < min(exact_scale(w, p, ph - 1e-6), exact_scale(w, p, ph + 1e-6)):
            failures.append(f"reference {label}: the stated phase {ph!r} is not a least-scale local minimum")
    if rc["chirality_gap"] > 1e-15:
        failures.append(f"the reference's chirality gap is {rc['chirality_gap']!r}")
    for label, p in (("orientation_preserving", curve(st)), ("reflected", mirror(curve(st)))):
        n = strict_minima(fast_grid(w, p, FINE_COUNT)).size
        if n != rc[label]["local_minimum_count"]:
            failures.append(f"reference {label}: {n} local minima on {FINE_COUNT} phases, stated {rc[label]['local_minimum_count']}")
    E = S["topology_escape"]["parameters"]
    if abs(E["l3"] - (1 - 2 * (E["l1"] + E["l2"]))) > 1e-15 or abs(E["alpha_degrees"] - E["beta_degrees"] - E["delta_degrees"]) > 1e-12:
        failures.append("the escape parameters are not in the family (l3 or alpha)")
    p = w["curve"]
    q = curve(escape_state(w))
    if p.shape != q.shape or np.abs((p - p[0]) - (q - q[0])).max() > 1e-15:
        failures.append("the logged escape curve is not the stated escape parameters")
    return failures


def mode_state(w, name, t):
    st = ref_state(w)
    st[MODES[name]] = t
    return st


def a2_modes(w):
    failures = []
    S = w["summary"]["antisymmetric_modes"]
    for name, rows in w["modes"].items():
        if name not in MODES or len(rows) != 101:
            failures.append(f"mode {name}: {len(rows)} rows")
            continue
        for row in rows:
            cp, cm = coarse(w, mode_state(w, name, row["mode_value"]))
            if abs(cp - row["plus_scale"]) > 1e-14 or abs(cm - row["minus_scale"]) > 1e-14:
                failures.append(f"{name} at {row['mode_value']:+.6f}: grid minima ({cp!r}, {cm!r}), stated "
                                f"({row['plus_scale']!r}, {row['minus_scale']!r})")
            if row["congruent_scale"] != min(row["plus_scale"], row["minus_scale"]) or \
                    abs(row["chirality_gap"] - abs(row["plus_scale"] - row["minus_scale"])) > 1e-18 or not row["valid"]:
                failures.append(f"{name} at {row['mode_value']:+.6f}: congruent value, gap or validity")
        best = max(rows, key=lambda r: r["congruent_scale"])
        centre = min(rows, key=lambda r: abs(r["mode_value"]))
        s = S[name]
        for label, got, want in (("best value", best["mode_value"], s["best_mode_value"]),
                                 ("best scale", best["congruent_scale"], s["best_congruent_scale"]),
                                 ("centre", centre["congruent_scale"], s["center_congruent_scale"]),
                                 ("best minus centre", best["congruent_scale"] - centre["congruent_scale"], s["best_minus_center"]),
                                 ("largest gap", max(r["chirality_gap"] for r in rows), s["maximum_chirality_gap"])):
            if abs(got - want) > 1e-15:
                failures.append(f"{name} {label}: the rows give {got!r}, the summary {want!r}")
    return failures


def a3_mirror(w):
    failures = []
    for name, rows in w["modes"].items():
        by = {round(r["mode_value"], 12): r for r in rows}
        for r in rows:
            m = by.get(round(-r["mode_value"], 12))
            if m is None or abs(r["plus_scale"] - m["minus_scale"]) > 1e-15:
                failures.append(f"{name} at {r['mode_value']:+.6f}: plus is not the minus value at the opposite mode value")
    return failures


def a4_escape(w):
    failures = []
    E = w["summary"]["topology_escape"]
    R = E["refined"]
    st = escape_state(w)
    (sp, pp), (sm, pm) = handed(w, st)
    for label, got, phase, rec in (("orientation_preserving", sp, pp, R["orientation_preserving"]),
                                   ("reflected", sm, pm, R["reflected"])):
        if abs(got - rec["scale"]) > 1e-12 or abs(math.remainder(phase - rec["phase"], 2 * math.pi)) > 1e-8:
            failures.append(f"escape {label}: ({got!r}, {phase!r}), stated ({rec['scale']!r}, {rec['phase']!r})")
        p = curve(st) if label == "orientation_preserving" else mirror(curve(st))
        n = strict_minima(fast_grid(w, p, FINE_COUNT)).size
        if n != rec["local_minimum_count"]:
            failures.append(f"escape {label}: {n} local minima on {FINE_COUNT} phases, stated {rec['local_minimum_count']}")
    cong = min(R["orientation_preserving"]["scale"], R["reflected"]["scale"])
    win = "orientation_preserving" if R["orientation_preserving"]["scale"] <= R["reflected"]["scale"] else "reflected"
    if R["congruent_scale"] != cong or R["winning_branch"] != win or \
            abs(R["chirality_gap"] - abs(R["orientation_preserving"]["scale"] - R["reflected"]["scale"])) > 1e-18:
        failures.append("escape: the congruent value, gap or winning branch is not the handednesses'")
    ref = w["summary"]["reference"]["event_scale"]
    for label, got, want in (("improvement", E["improvement_over_event"], R["congruent_scale"] - ref),
                             ("distance", E["distance_to_one"], 1 - R["congruent_scale"])):
        if abs(got - want) > 1e-18:
            failures.append(f"escape {label}: stated {got!r}, the difference is {want!r}")
    return failures


def a5_census(w):
    failures = []
    C = w["census"]
    if C != w["summary"]["random_topology_census"]["top_refined"]:
        failures.append("the summary's census is not topology_census.json")
    sigs = set()
    for row in C:
        st = np.array(row["state"])
        cp, cm = coarse(w, st)
        if abs(cp - row["plus_scale"]) > 1e-14 or abs(cm - row["minus_scale"]) > 1e-14:
            failures.append(f"census {row['index']}: coarse ({cp!r}, {cm!r}), stated ({row['plus_scale']!r}, {row['minus_scale']!r})")
        if row["congruent_scale"] != min(row["plus_scale"], row["minus_scale"]) or \
                abs(row["chirality_gap"] - abs(row["plus_scale"] - row["minus_scale"])) > 1e-18:
            failures.append(f"census {row['index']}: coarse congruent value or gap")
        (sp, pp), (sm, pm) = handed(w, st)
        R = row["refined"]
        for label, got, phase in (("orientation_preserving", sp, pp), ("reflected", sm, pm)):
            if abs(got - R[label]["scale"]) > 1e-12 or abs(math.remainder(phase - R[label]["phase"], 2 * math.pi)) > 1e-8:
                failures.append(f"census {row['index']} {label}: ({got!r}, {phase!r}), stated ({R[label]['scale']!r}, {R[label]['phase']!r})")
        win = "orientation_preserving" if sp <= sm else "reflected"
        if R["winning_branch"] != win or abs(R["congruent_scale"] - min(sp, sm)) > 1e-12:
            failures.append(f"census {row['index']}: winning branch {R['winning_branch']}, this run {win}")
        p = curve(st) if win == "orientation_preserving" else mirror(curve(st))
        sig = signature(w, p, pp if win == "orientation_preserving" else pm)
        if sig != row["winning_contact_signature"]:
            failures.append(f"census {row['index']}: signature {sig}, recorded {row['winning_contact_signature']}")
        sigs.add(json.dumps(row["winning_contact_signature"], sort_keys=True))
    if len(sigs) != w["summary"]["random_topology_census"]["distinct_top_contact_signatures"]:
        failures.append(f"{len(sigs)} distinct signatures, stated {w['summary']['random_topology_census']['distinct_top_contact_signatures']}")
    return failures


def a6_audit(w):
    failures = []
    L = w["audit"]
    ref = L["reference_scale"]
    if ref != w["summary"]["reference"]["event_scale"]:
        failures.append("the audit's reference is not the event scale")
    if len(L["radii"]) * L["samples_per_radius"] != L["total_valid_samples"]:
        failures.append(f"{len(L['radii'])} radii x {L['samples_per_radius']} is not {L['total_valid_samples']}")
    for c in L["best_refined_candidates"]:
        (sp, _), (sm, _) = handed(w, np.array(c["state"]))
        if abs(sp - c["plus"]) > 1e-12 or abs(sm - c["minus"]) > 1e-12:
            failures.append(f"audit candidate: ({sp!r}, {sm!r}), stated ({c['plus']!r}, {c['minus']!r})")
        if c["refined_congruent"] != min(c["plus"], c["minus"]) or abs(c["gain_over_reference"] - (c["refined_congruent"] - ref)) > 1e-18 \
                or abs(c["antisym_norm"] - float(np.linalg.norm(c["state"][4:]))) > 1e-18:
            failures.append("audit candidate: congruent value, gain or norm is not its own")
    nonbase = [c["gain_over_reference"] for c in L["best_refined_candidates"] if c["antisym_norm"] > 0]
    if max(nonbase) != L["best_nonbase_gain"]:
        failures.append(f"the best non-base gain is {max(nonbase)!r}, stated {L['best_nonbase_gain']!r}")
    above = sum(1 for g in nonbase if g > 0)
    if above != L["number_refined_above_reference"]:
        failures.append(f"{above} logged candidates lie above the root, stated {L['number_refined_above_reference']}")
    return failures


def sym_margin_min(w, q4):
    """the least identity margin over the four events of the symmetric five-link q4 = (l1, l2, beta, delta), and
    whether each event keeps the root's ledger"""
    st = np.concatenate([q4, np.zeros(4)])
    p = curve(st)
    a, b = q4[2] + q4[3], q4[2]
    phases = [math.pi / 2 - a, math.pi / 2 - b, 2 * math.pi / 3, 3 * math.pi / 2]
    m = identity_margins(w, p, phases)
    return min(t["margin"] for e in m for t in e.values()), [list(contacts(w, p, ph)) for ph in phases]


def a7_stability(w):
    failures = []
    D = w["summary"]["local_stability_draft"]
    st = ref_state(w)
    p = curve(st)
    phases = [math.pi / 2 - (st[2] + st[3]), math.pi / 2 - st[2], 2 * math.pi / 3, 3 * math.pi / 2]
    mine = identity_margins(w, p, phases)
    for lab, stated, got in zip(LABELS, D["base_active_margins"], mine):
        for k in ("left", "bottom", "hypotenuse"):
            if abs(stated[k] - got[k]["margin"]) > 1e-15:
                failures.append(f"{lab} {k}: base margin {stated[k]!r}, the root's {got[k]['margin']!r}")
    I5 = w["round05"]["isolation_diagnostics"]
    slopes = [abs(v) for c in w["round05"]["cusp_slopes"] for v in (c["left_derivative"], c["right_derivative"])]
    for label, got, want in (("sigma min", D["jacobian_minimum_singular_value"], I5["singular_values"][-1]),
                             ("condition", D["jacobian_condition_number"], I5["condition_number"]),
                             ("least slope", D["minimum_absolute_one_sided_slope"], min(slopes))):
        if got != want:
            failures.append(f"{label}: stated {got!r}, Round 05's {want!r}")
    base, ledger = sym_margin_min(w, st[:4])
    g = np.zeros(4)
    for j in range(4):
        e = np.zeros(4)
        e[j] = 1e-7
        g[j] = (sym_margin_min(w, st[:4] + e)[0] - sym_margin_min(w, st[:4] - e)[0]) / 2e-7
    rng = np.random.default_rng(7)
    for row in D["box_sampling"]:
        r = row["radius"]
        lower = base - r * np.abs(g).sum() - 10 * r * r
        if not lower <= row["minimum_observed_inactive_margin"] <= base + 1e-15:
            failures.append(f"radius {r:g}: stated minimum margin {row['minimum_observed_inactive_margin']!r} outside "
                            f"[{lower!r}, {base!r}]")
        if row["stable_count"] != row["samples"] or row["stable_fraction"] != row["stable_count"] / row["samples"]:
            failures.append(f"radius {r:g}: {row['stable_count']} of {row['samples']}, fraction {row['stable_fraction']}")
        lost = sum(sym_margin_min(w, st[:4] + rng.uniform(-r, r, 4))[1] != ledger for _ in range(100))
        if lost:
            failures.append(f"radius {r:g}: {lost} of this run's 100 box samples change a contact signature")
    return failures


def a8_consistency(w):
    failures = []
    S = w["summary"]
    E = S["topology_escape"]
    rd, rp = gate.squash(w["readme"]), gate.squash(w["report"])
    au, it = gate.squash(w["audit_note"]), gate.squash(w["interpretation"])
    L = w["audit"]

    def same(label, got, want, tol):
        if got is None or abs(got - want) > tol:
            failures.append(f"{label}: stated {got}, the data {want!r}")
    same("README event", num(r"第5輪事件尺度：(\d+\.\d+)", rd), S["reference"]["event_scale"], 6e-16)
    same("README best", num(r"八維最佳合同尺度：(\d+\.\d+)", rd), E["refined"]["congruent_scale"], 6e-16)
    same("README difference", num(r"差值：(-\d+\.\d+e-?\d+)", rd), E["improvement_over_event"], 6e-17)
    same("README gap", num(r"手性差：(\d+\.\d+e-?\d+)", rd), E["refined"]["chirality_gap"], 6e-18)
    same("README signatures", num(r"前二十候選接觸簽章數：(\d+)", rd), S["random_topology_census"]["distinct_top_contact_signatures"], 0)
    same("README samples", num(r"合法八維局部樣本：(\d+)", rd), L["total_valid_samples"], 0)
    same("README best non-base", num(r"最佳非基準高解析差值：(-\d+\.\d+e-?\d+)", rd), L["best_nonbase_gain"], 6e-17)
    same("README above", num(r"高解析超越事件根候選數：(\d+)", rd), L["number_refined_above_reference"], 0)
    same("report escape", num(r"s_\{\\mathrm\{escape\}\}=(\d+\.\d+)", rp), E["refined"]["congruent_scale"], 6e-16)
    same("report difference", num(r"s_\{\\mathrm\{escape\}\}-s_\{\\mathrm\{event\}\}=(-\d+\.\d+e-?\d+)", rp), E["improvement_over_event"], 6e-17)
    same("report distance", num(r"1-s_\{\\mathrm\{escape\}\}=(\d+\.\d+e-?\d+)", rp), E["distance_to_one"], 6e-16)
    same("report gap", num(r"\\chi_\{\\mathrm\{escape\}\}=(\d+\.\d+e-?\d+)", rp), E["refined"]["chirality_gap"], 6e-18)
    P = E["parameters"]
    same("report d_l1", num(r"d_\{l_1\}=(-?\d+\.\d+e-?\d+)", rp), P["antisym_outer_length"], 6e-15)
    same("report d_l2", num(r"d_\{l_2\}=(-?\d+\.\d+e-?\d+)", rp), P["antisym_inner_length"], 6e-15)
    same("report d_alpha", num(r"d_\\alpha=(-?\d+\.\d+)\^\\circ", rp), P["antisym_outer_angle_degrees"], 6e-10)
    same("report d_beta", num(r"d_\\beta=(-?\d+\.\d+)\^\\circ", rp), P["antisym_inner_angle_degrees"], 6e-10)
    same("report grid", num(r"使用\$(\d+)\$相位點", rp), FINE_COUNT, 0)
    same("report sigma", num(r"\\sigma_\{\\min\}\(J\)=(\d+\.\d+e-?\d+)", rp), S["local_stability_draft"]["jacobian_minimum_singular_value"], 6e-15)
    same("report kappa", num(r"\\kappa\(J\)=(\d+\.\d+)", rp), S["local_stability_draft"]["jacobian_condition_number"], 6e-10)
    same("report slope", num(r"\\min\|D_\\pms\|=(\d+\.\d+e-?\d+)", rp), S["local_stability_draft"]["minimum_absolute_one_sided_slope"], 6e-15)
    same("report census size", num(r"抽樣(\d+)條一般五連桿", rp), S["random_topology_census"]["sample_count"], 0)
    for row in table(w["report"], "掃描內最大手性差"):
        s = S["antisymmetric_modes"][row[0]]
        same(f"report mode {row[0]}", float(row[3]), s["maximum_chirality_gap"], 6e-10 * s["maximum_chirality_gap"])
        if float(row[1]) != s["best_mode_value"] or float(row[2]) != s["best_minus_center"]:
            failures.append(f"report mode {row[0]}: best value or gain")
    for row, c in zip(table(w["report"], "勝出分支接觸簽章"), S["random_topology_census"]["top_refined"]):
        same(f"report census rank {row[0]}", float(row[1]), c["refined"]["congruent_scale"], 6e-13)
        same(f"report census rank {row[0]} gap", float(row[2]), c["refined"]["chirality_gap"], 6e-4 * c["refined"]["chirality_gap"])
        if json.loads(row[3]) != c["winning_contact_signature"]:
            failures.append(f"report census rank {row[0]}: signature")
    for row, b in zip(table(w["report"], "參數盒半徑"), S["local_stability_draft"]["box_sampling"]):
        if float(row[0]) != b["radius"] or row[1] != f"{b['stable_count']}/{b['samples']}" or \
                abs(float(row[3]) - b["minimum_observed_inactive_margin"]) > 6e-7:
            failures.append(f"report box row {row[0]} is not the data's")
    same("audit note s0", num(r"s_0=(\d+\.\d+)", au), L["reference_scale"], 6e-16)
    same("audit note best", num(r"s_\{\\mathrm\{local\}\}=(\d+\.\d+)", au), L["reference_scale"] + L["best_nonbase_gain"], 6e-16)
    same("audit note gain", num(r"s_\{\\mathrm\{local\}\}-s_0=(-\d+\.\d+e-?\d+)", au), L["best_nonbase_gain"], 6e-17)
    same("audit note per radius", num(r"每個半徑\$(\d+)\$個", au), L["samples_per_radius"], 0)
    same("audit note total", num(r"總計(\d+)個", au), L["total_valid_samples"], 0)
    if "按七個尺度半徑抽樣" not in au or len(L["radii"]) != 7:
        failures.append(f"the audit note's seven radii vs the data's {len(L['radii'])}")
    if "最佳候選重新收斂到近鏡像對稱" not in it:
        failures.append("the interpretation note no longer states its reading")
    for phrase in ("s_{\\mathrm{cong}}(\\gamma)=\\min\\{s_+(\\gamma),s_-(\\gamma)\\}",):
        for label, text in (("METHOD.md", gate.squash(w["method"])), ("the report", rp)):
            if phrase not in text:
                failures.append(f"{label} does not state {phrase}")
    return failures


CHECKS = {"A1": a1_reference, "A2": a2_modes, "A3": a3_mirror, "A4": a4_escape, "A5": a5_census, "A6": a6_audit,
          "A7": a7_stability, "A8": a8_consistency}
GEOM = {"legs", "cert_scale_divisor", "rot_sign", "formula_B"}
DEPENDS = {
    "A1": {"summary", "round05", "curve"} | GEOM,
    "A2": {"summary", "modes"} | GEOM,
    "A3": {"modes"},
    "A4": {"summary"} | GEOM,
    "A5": {"summary", "census"} | GEOM,
    "A6": {"summary", "audit"} | GEOM,
    "A7": {"summary", "round05"} | GEOM,
    "A8": {"readme", "report", "interpretation", "audit_note", "method", "summary", "audit"},
}


# ---------------------------------------------------------------- findings

def findings(w):
    S = w["summary"]
    st0 = ref_state(w)
    s0 = S["reference"]["event_scale"]
    G = grad8(w, st0)
    Gp, Gd = G[:, :4], G[:, 4:]
    U, svp, Vt = np.linalg.svd(Gp)
    v = Vt[-1]
    mu = np.array(w["round05"]["event_solution"]["branch_pressures"])
    # the eight-dimensional problem: maximize z subject to m_r(p, d) >= z and m_r(p, -d) >= z (the mirror image of the
    # d-curve is the -d curve). With Gd nonsingular, the multipliers are mu/2 on both, the critical cone is (v, 0),
    # and the curvature along it is the symmetric problem's
    h = 1e-5
    e = np.concatenate([v, np.zeros(4)])
    hess = lambda x: (mu / 2) @ (grad8(w, x) + grad8(w, x * FLIP) * FLIP)
    curv = float(e @ ((hess(st0 + h * e) - hess(st0 - h * e)) / (2 * h)))
    rng = np.random.default_rng(0)
    near = {}
    for size in (1e-5, 1e-4):
        gaps, rises, dists = [], [], []
        for _ in range(40):
            step = size * rng.normal(size=8)
            st = st0 + step
            (sp, _), (sm, _) = handed(w, st)
            model = min(closed8(w, st).min(), closed8(w, st * FLIP).min())
            gaps.append(abs(min(sp, sm) - model))
            rises.append(min(sp, sm) - s0)
            dists.append(float(np.linalg.norm(step)))
        near[str(size)] = {"max_full_minus_model": float(max(gaps)), "max_rise": float(max(rises)),
                           "distance_min_median_max": [min(dists), float(np.median(dists)), max(dists)]}
    # the mode profiles against the true least scales
    profiles = {}
    for name, rows in w["modes"].items():
        true = []
        for row in rows:
            (sp, _), (sm, _) = handed(w, mode_state(w, name, row["mode_value"]))
            true.append((row["mode_value"], sp, sm))
        cong = [min(a, b) for _, a, b in true]
        k = int(np.argmax(cong))
        profiles[name] = {"true_best_mode_value": true[k][0], "true_best_minus_event": cong[k] - s0,
                          "true_largest_gap": float(max(abs(a - b) for _, a, b in true)),
                          "grid_minus_true_max": float(max(max(r["plus_scale"] - a, r["minus_scale"] - b)
                                                           for r, (_, a, b) in zip(rows, true))),
                          "one_sided_slopes_at_zero": [float((cong[51] - cong[50]) / (rows[51]["mode_value"] - rows[50]["mode_value"])),
                                                       float((cong[50] - cong[49]) / (rows[50]["mode_value"] - rows[49]["mode_value"]))]}
    census = [{"index": c["index"], "coarse_minus_refined": c["congruent_scale"] - c["refined"]["congruent_scale"]} for c in w["census"]]
    dev = {"census_value": 0.0, "census_phase": 0.0, "audit_value": 0.0, "mode_rows_grid": 0.0}
    for c in w["census"]:
        (sp, pp), (sm, pm) = handed(w, np.array(c["state"]))
        R = c["refined"]
        dev["census_value"] = max(dev["census_value"], abs(sp - R["orientation_preserving"]["scale"]), abs(sm - R["reflected"]["scale"]))
        dev["census_phase"] = max(dev["census_phase"], abs(math.remainder(pp - R["orientation_preserving"]["phase"], 2 * math.pi)),
                                  abs(math.remainder(pm - R["reflected"]["phase"], 2 * math.pi)))
    for c in w["audit"]["best_refined_candidates"]:
        (sp, _), (sm, _) = handed(w, np.array(c["state"]))
        dev["audit_value"] = max(dev["audit_value"], abs(sp - c["plus"]), abs(sm - c["minus"]))
    for name, rows in w["modes"].items():
        for row in rows:
            cp, cm = coarse(w, mode_state(w, name, row["mode_value"]))
            dev["mode_rows_grid"] = max(dev["mode_rows_grid"], abs(cp - row["plus_scale"]), abs(cm - row["minus_scale"]))
    (esp, epp), (esm, epm) = handed(w, escape_state(w))
    ER = S["topology_escape"]["refined"]
    dev["escape"] = [esp - ER["orientation_preserving"]["scale"], esm - ER["reflected"]["scale"],
                     math.remainder(epp - ER["orientation_preserving"]["phase"], 2 * math.pi),
                     math.remainder(epm - ER["reflected"]["phase"], 2 * math.pi)]
    order = [c["congruent_scale"] for c in w["census"]]
    E = S["topology_escape"]
    # the reference's two handednesses; the base margins against the root's; the mirror image of the d-curve against
    # the -d curve, by least scales, at random points
    (rsp, rpp), (rsm, rpm) = handed(w, st0)
    phases0 = [math.pi / 2 - (st0[2] + st0[3]), math.pi / 2 - st0[2], 2 * math.pi / 3, 3 * math.pi / 2]
    mine = identity_margins(w, curve(st0), phases0)
    base_dev = max(abs(b[k] - m[k]["margin"]) for b, m in zip(S["local_stability_draft"]["base_active_margins"], mine)
                   for k in ("left", "bottom", "hypotenuse"))
    mir = 0.0
    for _ in range(6):
        st = st0 + 1e-2 * rng.normal(size=8)
        mir = max(mir, abs(exact_min(w, mirror(curve(st)))[0] - exact_min(w, curve(st * FLIP))[0]))
    return {
        "reference_handednesses": {"plus": [rsp, rpp], "minus": [rsm, rpm], "minus_event": [rsp - s0, rsm - s0]},
        "base_margins_minus_root": base_dev,
        "mirror_of_d_minus_minus_d": mir,
        "eight_dim_closed_forms": {"at_root_minus_event": (closed8(w, st0) - s0).tolist(),
                                   "symmetric_block_minus_run006_gradients": float(np.abs(Gp - grad(w, st0[:4])).max())},
        "antisymmetric_gradients": {"matrix": Gd.tolist(), "singular_values": np.linalg.svd(Gd, compute_uv=False).tolist()},
        "symmetric_gradients_singular_values": svp.tolist(),
        "eight_dim_curvature_along_critical_line": curv,
        "eight_dim_near_root": near,
        "mode_profiles_true": profiles,
        "reproduction_deviations": dev,
        "census_coarse_minus_refined": census,
        "census_sorted_by_coarse": all(order[i] >= order[i + 1] for i in range(len(order) - 1)),
        "escape_below_root": E["refined"]["congruent_scale"] - S["reference"]["event_scale"],
        "escape_antisymmetric_relative": {"d_l1_over_l1": E["parameters"]["antisym_outer_length"] / E["parameters"]["l1"],
                                          "d_l2_over_l2": E["parameters"]["antisym_inner_length"] / E["parameters"]["l2"]},
    }


# ---------------------------------------------------------------- the drill

def drill_cases(base):
    def edit(key, fn):
        v = copy.deepcopy(base[key])
        fn(v)
        return v
    s_ref = edit("summary", lambda s: s["reference"]["parameters"].__setitem__("l2", s["reference"]["parameters"]["l2"] + 1e-12))
    s_refc = edit("summary", lambda s: s["reference"]["refined_congruent"]["reflected"].__setitem__("scale", s["reference"]["refined_congruent"]["reflected"]["scale"] + 1e-12))
    s_modesum = edit("summary", lambda s: s["antisymmetric_modes"]["inner_angle_antisym"].__setitem__("maximum_chirality_gap", 0.005369528921))
    s_escp = edit("summary", lambda s: s["topology_escape"]["parameters"].__setitem__(
        "antisym_inner_angle_degrees", s["topology_escape"]["parameters"]["antisym_inner_angle_degrees"] + 1e-6))
    s_escs = edit("summary", lambda s: s["topology_escape"]["refined"]["orientation_preserving"].__setitem__("local_minimum_count", 9))
    s_imp = edit("summary", lambda s: s["topology_escape"].__setitem__("improvement_over_event", -3.4654943363e-04))
    s_margin = edit("summary", lambda s: s["local_stability_draft"]["base_active_margins"][1].__setitem__("bottom", 0.0677275329))
    s_box = edit("summary", lambda s: s["local_stability_draft"]["box_sampling"][11].__setitem__("minimum_observed_inactive_margin", 0.00674))
    modes = copy.deepcopy(base["modes"])
    modes["outer_angle_antisym"][30]["plus_scale"] += 1e-9
    modes2 = copy.deepcopy(base["modes"])
    modes2["inner_length_antisym"][70]["minus_scale"] += 1e-12
    census = copy.deepcopy(base["census"])
    census[4]["refined"]["reflected"]["scale"] += 1e-10
    census2 = copy.deepcopy(base["census"])
    census2[7]["winning_contact_signature"]["left"] = [3]
    audit = copy.deepcopy(base["audit"])
    audit["best_refined_candidates"][3]["plus"] += 1e-10
    audit2 = copy.deepcopy(base["audit"])
    audit2["number_refined_above_reference"] = 1
    cv = base["curve"].copy()
    cv[2, 1] += 1e-9
    rep = base["report"].replace("1-s_{\\mathrm{escape}}\n=\n1.442792301119e-03", "1-s_{\\mathrm{escape}}\n=\n1.442792301129e-03")
    readme = base["readme"].replace("前二十候選接觸簽章數：\n  5", "前二十候選接觸簽章數：\n  6")
    note = base["audit_note"].replace("s_{\\mathrm{local}}=0.998790843965457", "s_{\\mathrm{local}}=0.998790843965467")
    method = base["method"].replace("\\min\\{s_+(\\gamma),s_-(\\gamma)\\}", "\\max\\{s_+(\\gamma),s_-(\\gamma)\\}")
    for a, b in ((rep, base["report"]), (readme, base["readme"]), (note, base["audit_note"]), (method, base["method"])):
        assert a != b, "a plant must hit the raw text"
    a, b = base["legs"]
    return [
        ("K0-unmodified", "control", {}, set()),
        ("K1-report-crlf", "control", {"report": base["report"].replace("\n", "\r\n")}, set()),
        ("K2-modes-copied", "control", {"modes": copy.deepcopy(base["modes"])}, set()),
        ("K3-readme-trailing-spaces", "control", {"readme": "\n".join(l + " " for l in base["readme"].split("\n"))}, set()),
        ("M1-triangle-leg", "mutation", {"legs": (a * 1.0005, b)}, {"A1", "A2", "A4", "A5", "A6", "A7"}),
        ("M2-reference-length", "mutation", {"summary": s_ref}, {"A1", "A2", "A7"}),
        ("M3-reference-mirror-scale", "mutation", {"summary": s_refc}, {"A1"}),
        ("M4-mode-row", "mutation", {"modes": modes}, {"A2", "A3"}),
        ("M5-mode-row-mirror", "mutation", {"modes": modes2}, {"A2", "A3"}),
        ("M6-mode-summary", "mutation", {"summary": s_modesum}, {"A2"}),
        ("M7-escape-angle", "mutation", {"summary": s_escp}, {"A1", "A4", "A8"}),
        ("M8-escape-count", "mutation", {"summary": s_escs}, {"A4"}),
        ("M9-escape-improvement", "mutation", {"summary": s_imp}, {"A4", "A8"}),
        ("M10-census-scale", "mutation", {"census": census}, {"A5"}),
        ("M11-census-signature", "mutation", {"census": census2}, {"A5"}),
        ("M12-audit-candidate", "mutation", {"audit": audit}, {"A6"}),
        ("M13-audit-count", "mutation", {"audit": audit2}, {"A6", "A8"}),
        ("M14-base-margin", "mutation", {"summary": s_margin}, {"A7"}),
        ("M15-box-margin", "mutation", {"summary": s_box}, {"A7", "A8"}),
        ("M16-escape-curve", "mutation", {"curve": cv}, {"A1"}),
        ("M17-report-digit", "mutation", {"report": rep}, {"A8"}),
        ("M18-readme-digit", "mutation", {"readme": readme}, {"A8"}),
        ("M19-audit-note-digit", "mutation", {"audit_note": note}, {"A8"}),
        ("M20-method-min", "mutation", {"method": method}, {"A8"}),
        ("M21-formula-term", "mutation", {"formula_B": lambda B: 2 * B}, {"A1", "A2", "A4", "A5", "A6"}),
    ]


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--drill", action="store_true")
    ap.add_argument("--blind", metavar="CID")
    ap.add_argument("--log", default=None)
    args = ap.parse_args()
    if args.blind:
        CHECKS[args.blind] = lambda w: []
        args.drill = True
    w = build_world()
    results = {cid: fn(w) for cid, fn in CHECKS.items()}
    for cid, f in results.items():
        print(f"{cid} {'PASS' if not f else 'FAIL'}  ({len(f)} failures)")
        for x in f[:6]:
            print("    ", x)
    log = {"run": "RUN-007",
           "subject": "Round 06 (v0.6.1): chirality escape, the eight-dimensional five-link search, the local stability draft",
           "package": {"id": RID, "sha256": sha256(source_bytes(RID))},
           "checks": {cid: {"pass": not f, "failures": f} for cid, f in results.items()},
           "findings": None if args.blind else findings(w)}
    if log["findings"]:
        print(json.dumps(log["findings"], indent=1)[:6000])
    if args.drill:
        drill = gate.run_drill(build_world, CHECKS, DEPENDS, drill_cases(build_world()))
        log["drill"] = gate.summarize(drill, CHECKS)
        print(gate.report_drill(log["drill"]))
        for d in drill:
            if not d["ok"]:
                print("   DRILL FAIL", d)
    if args.blind:
        seen = sum(1 for d in log["drill"]["cases"] if args.blind in d["expected"] and args.blind not in d["tripped"])
        print(f"blind {args.blind}: reported blind in {seen} cases (log not written)")
        return
    if args.drill:
        path = pathlib.Path(args.log) if args.log else LOG
        path.parent.mkdir(parents=True, exist_ok=True)
        path.write_text(json.dumps(log, ensure_ascii=False, indent=1) + "\n", encoding="utf-8", newline="\n")


if __name__ == "__main__":
    main()
