"""RUN-011 - Round 10 (v0.10): the full phase-contact map, the stationary points and the global numerical exclusion.

Round 10 splits the phase circle for Round 08's best candidate (Round 09's decimal curve) into 18 intervals of fixed
active supports - (argmin rotated x, argmin rotated y, argmax diagonal), with labels p0..p3 for the ends and junctions
and L, R for a wing's interior point - lists the 17 switches between them with their one-sided derivatives, 12 smooth
stationary points found by sampling the envelope derivative s'(phi) on 257, 1,025 and 4,097 points per interval, and
a ledger of each interval's minimum. It finds 8 local minima - four cusps at switches, four smooth - and the least at
3pi/2, the 120-degree cusp 1.6383e-9 above it, and leaves an interval certificate of s(phi) >= s(3pi/2) open.

Checks (each returns a list of failures; empty = pass)
  S1 parameters   the curve parameters are Round 08's best and Round 09's decimal constants; the source note states the
                  labels and the envelope formula
  S2 phase map    18 contiguous intervals from 0 to 2pi with 17 boundaries; the active supports at each interval's
                  midpoint are its signature (this run's exact support at 60 digits); each boundary lies within 1e-12
                  of the exact switch; the distinct signatures; the CSV and the summary hold the same intervals
  S3 switches     each switch's scale is the exact scale there, to 2e-13; at a switch between two corners its one-sided
                  derivatives are the exact ones, to 1e-7; at a switch to or from a wing's interior point, where s is
                  continuously differentiable, the two stated derivatives agree (fixed-text failures); a cusp minimum
                  is a switch with D- < 0 < D+; the two special phases likewise
  S4 stationary   each stated stationary point is an exact one, to 1e-11 in phase and 2e-13 in scale, of its kind and
                  signature; the list is complete (fixed-text failure)
  S5 derivative   each interval's sampled derivative extremes lie within its exact derivative's range; its classification
                  and the guards' root counts are the exact derivative's sign changes (fixed-text failures)
  S6 minima       the 8 minimum candidates and the 18 ledger rows: each is the exact minimum of its kind and place, to
                  2e-13 (fixed-text failures); the margins; the global candidate
  S7 resolution   this run's own scans at 32,768 to 262,144 phases give the stated cyclic switch counts, signature
                  counts, sampled local minima and global minimum phase; the stated minimum is s(3pi/2) to 2e-13
  S8 consistency  the README, the report's tables and figures, the interface note and the manifest state the data's
  S9 digits       the report's long figures of s270, s0 and their difference hold to their printed digits

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/run011_round10_phase_map.py [--drill [--log PATH] | --blind S#]
"""
import argparse
import copy
import csv
import io
import json
import math
import pathlib
import re

import mpmath as mp
import numpy as np

from corpus import TREE, sha256, source_bytes
import gate
from run001_corpus_identity import restore_escapes
from run004_round03_symmetric_links import load
from run009_round08_smooth_layer import Wing
import run010_round09_precision_cusp as r10
from run010_round09_precision_cusp import cusp_270, dec, hi, holds, iv, lo, tanh_iv

RID = "round-v0.10"
LOG = TREE / "data" / "gate-logs" / "run011-round10-phase-map.json"
NAMES = ("min_x", "min_y", "max_d")
LABELS = ("p0", "p1", "p2", "p3", "L", "L", "R", "R")


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

def build_world():
    f, f8, f5 = load(RID), load("round-v0.8.3"), load("round-v0.5")
    md = lambda n: restore_escapes(f[n].decode("utf-8"))
    rows = lambda n: list(csv.DictReader(io.StringIO(f[n].decode("utf-8"))))
    return {
        "readme": md("README.md"), "report": md("reports/ROUND_10_REPORT.md"),
        "interface": md("reports/ROUND_10_GLOBAL_CERTIFICATE_INTERFACE.md"),
        "source": f["src/phase_contact_map.py"].decode("utf-8"),
        "manifest": json.loads(f["MANIFEST.json"]),
        "members": sorted(f),
        "summary": json.loads(f["data/round10_summary.json"]),
        "audit": json.loads(f["data/round10_global_exclusion_audit.json"]),
        "intervals_csv": rows("data/phase_contact_intervals.csv"),
        "round08_best": json.loads(f8["data/round08_summary.json"])["best_verified_candidate"],
        "round09": json.loads(load("round-v0.9")["data/round09_summary.json"]),
        "round05": json.loads(f5["data/round05_summary.json"])["event_solution"]["parameters"],
        "legs": ("1", "1"),
    }


def hp(w):
    """the world RUN-010's high-precision tools read: the decimal curves, the triangle"""
    P = w["summary"]["curve_parameters"]
    E = w["round05"]
    return {"summary": {"definitions": {
                "candidate": {k: repr(float(P[k])) for k in ("epsilon", "wing_length", "beta", "delta", "transition_center")},
                "event_control": {"l1": repr(float(E["l1"])), "l2": repr(float(E["l2"])), "beta": repr(float(E["beta_radians"])),
                                  "delta": repr(float(E["delta_radians"]))}}},
            "legs": w["legs"], "cusp_formula": cusp_270}


def cand(w, dps=60):
    return r10.cand(hp(w), dps)


def point(C, label, name, ph):
    """the support point a label names for a functional at a phase; an interior label names the wing point whose
    tangent is perpendicular to the functional, clamped to the wing"""
    if label in C.P:
        return C.P[label]
    a = C.a[name]
    cs, sn = mp.cos(ph), mp.sin(ph)
    n = (a[0] * cs + a[1] * sn, -a[0] * sn + a[1] * cs)
    ang = mp.atan2(n[1], n[0]) if label == "L" else mp.atan2(n[1], -n[0])
    best = None
    for k in (-1, 1):
        t = ang + k * mp.pi / 2
        t -= 2 * mp.pi * mp.floor((t + mp.pi) / (2 * mp.pi))
        f = (t - C.b) / C.d
        if best is None or abs(f - mp.mpf(0.5)) < abs(best - mp.mpf(0.5)):
            best = f
    f = min(max(best, mp.mpf(0)), mp.mpf(1))
    u = mp.mpf(1) if f == 0 else (mp.mpf(0) if f == 1 else C.c - C.eps * mp.atanh(C.T1 + f * (C.T0 - C.T1)))
    px, py = C.pos(u) if u > 0 else (mp.mpf(0), mp.mpf(0))
    return (px, py) if label == "L" else (2 * C.P["p1"][0] + C.l0 - px, py)


def deriv(C, signature, ph):
    """the envelope derivative of s with a signature's supports: sum over the three maxima of n_k'(phi).p_k"""
    with mp.workdps(C.dps):
        cs, sn = mp.cos(ph), mp.sin(ph)
        tot = mp.mpf(0)
        for name, lab in zip(NAMES, signature.split("|")):
            a = C.a[name]
            p = point(C, lab, name, ph)
            tot += (-a[0] * sn + a[1] * cs) * p[0] + (-a[0] * cs - a[1] * sn) * p[1]
        return tot


def sig_at(C, ph):
    T = C.terms(ph)
    return "|".join(",".join(T[k][1]) for k in NAMES)


def exact_switch(w, sw):
    """the exact phase where the changing functional's support leaves the left label, by bisection on the labels"""
    def go():
        C = cand(w)
        L, R = sw["left_signature"].split("|"), sw["right_signature"].split("|")
        k = [i for i in range(3) if L[i] != R[i]][0]
        with mp.workdps(60):
            lo_, hi_ = mp.mpf(sw["phase"]) - mp.mpf("1e-6"), mp.mpf(sw["phase"]) + mp.mpf("1e-6")
            if C.terms(lo_)[NAMES[k]][1] != [L[k]] or C.terms(hi_)[NAMES[k]][1] != [R[k]]:
                return None
            for _ in range(70):
                mid = (lo_ + hi_) / 2
                if C.terms(mid)[NAMES[k]][1] == [L[k]]:
                    lo_ = mid
                else:
                    hi_ = mid
            ph = (lo_ + hi_) / 2
            return {"phase": ph, "scale": C.s(ph), "left": deriv(C, sw["left_signature"], ph),
                    "right": deriv(C, sw["right_signature"], ph), "interior": "L" in L[k] + R[k] or "R" in L[k] + R[k]}
    key = json.dumps([sw["phase"], sw["left_signature"], sw["right_signature"]])
    return r10.memo("switch", hp(w), key)(go)


def exact_stationary(w, i):
    """the exact stationary points of interval i's derivative: a scan of 65 equal steps and 15 geometric steps toward
    each end (to 1e-15 of the width), then bisection on each sign change"""
    def go():
        C = cand(w, 40)
        I = w["summary"]["phase_map"]["intervals"][i]
        with mp.workdps(40):
            a, b = mp.mpf(I["start"]), mp.mpf(I["end"])
            fr = sorted({mp.mpf(k) / 64 for k in range(65)} | {mp.mpf(10) ** -e for e in range(1, 16)} |
                        {1 - mp.mpf(10) ** -e for e in range(1, 16)})
            vals = [(a + f * (b - a), deriv(C, I["signature"], a + f * (b - a))) for f in fr]
            out = []
            for (p0, d0), (p1_, d1) in zip(vals, vals[1:]):
                if (d0 > 0) != (d1 > 0):
                    x, y = p0, p1_
                    for _ in range(110):
                        m = (x + y) / 2
                        if (deriv(C, I["signature"], m) > 0) == (d0 > 0):
                            x = m
                        else:
                            y = m
                    q = (x + y) / 2
                    out.append({"phase": q, "scale": C.s(q), "kind": "smooth_minimum" if d0 < 0 else "smooth_maximum"})
            return {"ends": (vals[0][1], vals[-1][1]), "min": min(v for _, v in vals), "max": max(v for _, v in vals),
                    "stationary": out}
    return r10.memo("stationary", hp(w), i)(go)


# ---------------------------------------------------------------- a double-precision exact scan

def scan(w, n):
    """this run's exact support at n equally spaced phases from 0, in double precision: the scale and the labels"""
    P = w["summary"]["curve_parameters"]
    wing = Wing(P["wing_length"], P["beta"], P["delta"], P["transition_center"], P["epsilon"])
    fa, fb = (float(x) for x in w["legs"])
    A = (3 + 4 * math.sqrt(3)) / 18 / 1.0048 * fa
    B = (4 + math.sqrt(3)) / 6 / 1.0048 * fb
    x1, y1 = wing.P1
    corners = np.array([[0.0, 0.0], [x1, y1], [x1 + wing.l0, y1], [2 * x1 + wing.l0, 0.0]])
    ph = 2 * math.pi * np.arange(n) / n
    c, s = np.cos(ph), np.sin(ph)
    total = np.zeros(n)
    labs = []
    for a0, a1 in ((-1 / A, 0.0), (0.0, -1 / B), (1 / A, 1 / B)):
        n0, n1 = a0 * c + a1 * s, -a0 * s + a1 * c
        vals = [corners[j, 0] * n0 + corners[j, 1] * n1 for j in range(4)]
        for side, ang in (("L", np.arctan2(n1, n0)), ("R", np.arctan2(n1, -n0))):
            for k in (-1, 1):
                t = np.remainder(ang + k * math.pi / 2 + math.pi, 2 * math.pi) - math.pi
                f = (t - wing.b) / wing.d
                ok = (f > 0) & (f < 1)
                v = np.full(n, -np.inf)
                if ok.any():
                    u = wing.c - wing.eps * np.arctanh(wing.T1 + f[ok] * (wing.T0 - wing.T1))
                    p = wing.pos(u)
                    if side == "R":
                        p = np.stack([2 * x1 + wing.l0 - p[:, 0], p[:, 1]], 1)
                    v[ok] = p[:, 0] * n0[ok] + p[:, 1] * n1[ok]
                vals.append(v)
        V = np.stack(vals, 1)
        total += V.max(1)
        labs.append(np.array(LABELS)[V.argmax(1)])
    sig = np.char.add(np.char.add(np.char.add(labs[0], "|"), np.char.add(labs[1], "|")), labs[2])
    return ph, total, sig


def scan_summary(w, n):
    def go():
        ph, s, sig = scan(w, n)
        switches = int((sig != np.roll(sig, 1)).sum())
        mins = np.flatnonzero((s < np.roll(s, 1)) & (s < np.roll(s, -1)))
        j = int(s.argmin())
        return {"switches": switches, "signatures": len(set(sig.tolist())), "minima": len(mins),
                "global_phase": float(ph[j]), "global": float(s[j])}
    return r10.memo("scan", hp(w), n)(go)


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

def s1_parameters(w):
    failures = []
    P = w["summary"]["curve_parameters"]
    B8 = w["round08_best"]
    want = {"epsilon": B8["epsilon"], "wing_length": B8["parameters"][0], "beta": B8["parameters"][1],
            "delta": B8["parameters"][2], "transition_center": B8["parameters"][3]}
    D9 = w["round09"]["definitions"]["candidate"]
    for k, v in want.items():
        if P[k] != v or repr(float(P[k])) != D9[k]:
            failures.append(f"the parameter {k} is not Round 08's and Round 09's")
    src = w["source"]
    for frag in ("p0, p1, p2, p3", "L, R", "(argmin rotated-x, argmin rotated-y, argmax diagonal support)",
                 "s' = n_d'·p_d - (n_x'·p_x)/A - (n_y'·p_y)/B"):
        if frag not in src:
            failures.append(f"the source note lacks {frag}")
    return failures


def s2_phase_map(w):
    failures = []
    M = w["summary"]["phase_map"]
    I = M["intervals"]
    if len(I) != 18 or M["interval_count"] != 18 or M["boundary_count"] != 17:
        failures.append("the map does not have 18 intervals and 17 boundaries")
    if I[0]["start"] != 0 or abs(I[-1]["end"] - 2 * math.pi) > 1e-15 or any(x["end"] != y["start"] for x, y in zip(I, I[1:])):
        failures.append("the intervals do not tile [0, 2pi]")
    if any(abs(x["width"] - (x["end"] - x["start"])) > 1e-15 for x in I):
        failures.append("a width is not its interval's")
    if [(b["phase"], b["left_signature"], b["right_signature"]) for b in M["boundaries"]] != \
            [(x["end"], x["signature"], y["signature"]) for x, y in zip(I, I[1:])]:
        failures.append("the boundaries are not the intervals' ends")
    if sorted(M["distinct_signatures"]) != sorted({x["signature"] for x in I}) or len(M["distinct_signatures"]) != 18:
        failures.append("the distinct signatures are not the intervals'")
    C = cand(w)
    with mp.workdps(60):
        for i, x in enumerate(I):
            if sig_at(C, mp.mpf((x["start"] + x["end"]) / 2)) != x["signature"]:
                failures.append(f"interval {i}: the active supports at its midpoint are not its signature")
    for i, sw in enumerate(w["summary"]["contact_switches"]):
        e = exact_switch(w, sw)
        if e is None or abs(mp.mpf(sw["phase"]) - e["phase"]) > 1e-12:
            failures.append(f"switch {i} is not at the exact switch")
        if sw["phase"] != M["boundaries"][i]["phase"] or sw["left_signature"] != I[i]["signature"] or sw["right_signature"] != I[i + 1]["signature"]:
            failures.append(f"switch {i} is not the map's boundary")
    csvI = w["intervals_csv"]
    DA = w["summary"]["interval_derivative_analysis"]
    for r, x, d in zip(csvI, I, DA):
        same = (int(r["index"]) == d["index"] and r["signature"] == x["signature"] == d["signature"]
                and float(r["start"]) == x["start"] and float(r["end"]) == x["end"] and r["classification"] == d["classification"]
                and float(r["derivative_min"]) == d["sample_derivative_min"] and float(r["derivative_max"]) == d["sample_derivative_max"]
                and int(r["stationary_count"]) == len(d["stationary_points"]))
        if not same:
            failures.append(f"the CSV's row {r['index']} is not the summary's")
    if len(csvI) != 18:
        failures.append("the CSV does not have 18 rows")
    return failures


def s3_switches(w):
    failures = []
    for i, sw in enumerate(w["summary"]["contact_switches"]):
        e = exact_switch(w, sw)
        if e is None:
            failures.append(f"switch {i}: no exact switch")
            continue
        if abs(mp.mpf(sw["scale"]) - e["scale"]) > 2e-13:
            failures.append(f"switch {i}: scale {sw['scale']!r}, exact {mp.nstr(e['scale'], 17)}")
        if e["interior"]:
            # s is continuously differentiable where a wing's interior support leaves or reaches a corner
            if abs(sw["left_derivative"] - sw["right_derivative"]) > 1e-6:
                failures.append(f"switch {i}: the stated one-sided derivatives are not the derivative there")
        elif abs(sw["left_derivative"] - e["left"]) > 1e-7 or abs(sw["right_derivative"] - e["right"]) > 1e-7:
            failures.append(f"switch {i}: one-sided derivatives {sw['left_derivative']!r}, {sw['right_derivative']!r}")
        cusp = e["left"] < 0 < e["right"]
        if (sw["kind"] == "cusp_minimum") != cusp:
            failures.append(f"switch {i}: the kind is not the exact derivatives'")
    C = cand(w)
    for sp in w["summary"]["special_phases"]:
        with mp.workdps(60):
            ph = 2 * mp.pi / 3 if sp["name"] == "120deg" else 3 * mp.pi / 2
            Dm, Dp = C.dsides(ph)
            if abs(mp.mpf(sp["phase"]) - ph) > 1e-15 or abs(mp.mpf(sp["scale"]) - C.s(ph)) > 2e-13 \
                    or abs(sp["left_derivative"] - Dm) > 1e-7 or abs(sp["right_derivative"] - Dp) > 1e-7:
                failures.append(f"{sp['name']}: not the exact cusp")
    return failures


def all_stationary(w):
    return [dict(st, interval=i) for i in range(18) for st in exact_stationary(w, i)["stationary"]]


def s4_stationary(w):
    failures = []
    exact = all_stationary(w)
    for j, st in enumerate(w["summary"]["stationary_points"]):
        near = [e for e in exact if abs(e["phase"] - mp.mpf(st["phase"])) < 1e-11]
        if len(near) != 1:
            failures.append(f"stationary point {j} is not an exact one")
            continue
        e = near[0]
        I = w["summary"]["phase_map"]["intervals"][e["interval"]]
        if abs(mp.mpf(st["scale"]) - e["scale"]) > 2e-13 or st["kind"] != e["kind"] or st["interval_index"] != e["interval"] \
                or st["signature"] != I["signature"]:
            failures.append(f"stationary point {j}: scale, kind or place is not the exact one's")
    if len(exact) != len(w["summary"]["stationary_points"]):
        failures.append("the stationary points are not all the derivative's zeros")
    return failures


CLASS = {"strictly_decreasing_sampled": "down", "strictly_increasing_sampled": "up", "contains_stationary": "stationary"}


def s5_derivative(w):
    failures = []
    for i, d in enumerate(w["summary"]["interval_derivative_analysis"]):
        e = exact_stationary(w, i)
        if d["sample_derivative_min"] < e["min"] - 1e-9 or d["sample_derivative_max"] > e["max"] + 1e-9:
            failures.append(f"interval {i}: the sampled derivative leaves the exact range")
        n = len(e["stationary"])
        want = "stationary" if n else ("down" if e["ends"][0] < 0 else "up")
        if CLASS.get(d["classification"]) != want:
            failures.append(f"interval {i}: the classification is not the derivative's")
        if any(g["root_count"] != n for g in w["audit"]["derivative_root_guards"][i]["grids"].values()):
            failures.append(f"interval {i}: the guards' root counts are not the derivative's")
    return failures


def exact_minima(w):
    """this run's local minima: the cusp minima at switches (D- < 0 < D+) and the smooth minima"""
    out = []
    for sw in w["summary"]["contact_switches"]:
        e = exact_switch(w, sw)
        if e and e["left"] < 0 < e["right"]:
            out.append({"source": "cusp", "phase": e["phase"], "scale": e["scale"]})
    out += [{"source": "smooth", "phase": e["phase"], "scale": e["scale"]} for e in all_stationary(w) if e["kind"] == "smooth_minimum"]
    return sorted(out, key=lambda m: m["scale"])


def s6_minima(w):
    failures = []
    S = w["summary"]
    mine = exact_minima(w)
    cands = S["minimum_candidates"]
    if len(cands) != len(mine):
        failures.append("the minimum candidates are not all the local minima")
    for j, (c, m) in enumerate(zip(cands, mine)):
        src = "smooth" if c["source"] == "smooth_stationary" else "cusp"
        if abs(mp.mpf(c["phase"]) - m["phase"]) > 1e-11 or abs(mp.mpf(c["scale"]) - m["scale"]) > 2e-13 or src != m["source"]:
            failures.append(f"minimum candidate {j} is not the local minimum of its rank")
    if S["global_candidate"] != cands[0]:
        failures.append("the global candidate is not the first")
    ref = S["reference_270_arbitrary_precision"]
    C = cand(w)
    stat = all_stationary(w)
    for row in S["interval_minimum_ledger"]:
        i = row["interval_index"]
        I = S["phase_map"]["intervals"][i]
        with mp.workdps(60):
            pts = [mp.mpf(I["start"]), mp.mpf(I["end"])]
            for sw in S["contact_switches"]:
                e = exact_switch(w, sw)
                if e is not None and sw["phase"] in (I["start"], I["end"]):
                    pts[pts.index(mp.mpf(sw["phase"]))] = e["phase"]
            if i == 8:
                pts[0] = 2 * mp.pi / 3
            cand_vals = [C.s(p) for p in pts] + [e["scale"] for e in stat if e["interval"] == i]
            true_min = min(cand_vals)
            if abs(mp.mpf(row["minimum_scale"]) - true_min) > 2e-13:
                failures.append(f"ledger interval {i}: the minimum is not the interval's")
        if abs(row["margin_above_round9_270"] - (row["minimum_scale"] - ref)) > 1e-18:
            failures.append(f"ledger interval {i}: the margin")
    if w["audit"]["interval_minimum_ledger"] != S["interval_minimum_ledger"]:
        failures.append("the audit's ledger is not the summary's")
    return failures


def s7_resolution(w):
    failures = []
    S = w["summary"]
    rows = S["multi_resolution_audit"]
    if rows != w["audit"]["multi_resolution_contact_map"]:
        failures.append("the audit's resolution table is not the summary's")
    C = cand(w)
    with mp.workdps(60):
        s270 = C.s(3 * mp.pi / 2)
    for r in rows:
        m = scan_summary(w, r["phase_count"])
        if (m["switches"], m["signatures"], m["minima"]) != (r["contact_switch_count_cyclic"], r["distinct_signature_count"],
                                                            r["sampled_local_minimum_count"]):
            failures.append(f"{r['phase_count']} phases: the counts are not this run's scan's")
        if abs(m["global_phase"] - r["sampled_global_phase"]) > 1e-14 or abs(mp.mpf(r["sampled_global_minimum"]) - s270) > 2e-13:
            failures.append(f"{r['phase_count']} phases: the global minimum is not s(3pi/2)")
    if abs(S["double_minus_arbitrary_precision_270"] - (S["global_candidate"]["scale"] - S["reference_270_arbitrary_precision"])) > 1e-18:
        failures.append("the double-minus-arbitrary figure is not the difference")
    if abs(S["reference_270_arbitrary_precision"] - float(w["round09"]["arbitrary_precision"]["candidate_270_scale"])) > 0:
        failures.append("the reference is not Round 09's value")
    return failures


def s8_consistency(w):
    failures = []
    S = w["summary"]
    rp = w["report"].replace("\r\n", "\n")
    rs = gate.squash(rp)
    rd = "\n".join(l.rstrip() for l in w["readme"].replace("\r\n", "\n").split("\n"))
    I = S["phase_map"]["intervals"]
    led = {r["interval_index"]: r for r in S["interval_minimum_ledger"]}
    # section 3: the interval table
    rows = re.findall(r"^\|\s*(\d+)\s*\|\s*([\d.]+)\s*\|\s*([\d.]+)\s*\|\s*`([^`]+)`\s*\|\s*(\w+)\s*\|\s*([\d.]+)\s*\|\s*(-?[\d.e+-]+)\s*\|", rp, re.M)
    if len(rows) != 18:
        failures.append(f"section 3: {len(rows)} rows")
    for k, st, en, sg, cl, mn, mar in rows:
        x, d, L = I[int(k)], S["interval_derivative_analysis"][int(k)], led[int(k)]
        ok = (r10.rounds_to(st, x["start"]) or float(st) == 0) and r10.rounds_to(en, x["end"]) and sg == x["signature"] \
            and cl == d["classification"] and r10.rounds_to(mn, L["minimum_scale"]) and r10.rounds_to(mar, L["margin_above_round9_270"])
        if not ok:
            failures.append(f"section 3 row {k} is not the data's")
    # section 4: the resolution table
    res = {r["phase_count"]: r for r in S["multi_resolution_audit"]}
    rows = re.findall(r"^\|\s*(\d{5,6})\s*\|\s*(\d+)\s*\|\s*(\d+)\s*\|\s*(\d+)\s*\|\s*([\d.]+)\s*\|\s*([\d.]+)\s*\|", rp, re.M)
    if len(rows) != 4:
        failures.append(f"section 4: {len(rows)} rows")
    for n, sw, sg, mi, gm, gp in rows:
        r = res.get(int(n))
        if not r or (int(sw), int(sg), int(mi)) != (r["contact_switch_count_cyclic"], r["distinct_signature_count"], r["sampled_local_minimum_count"]) \
                or not r10.rounds_to(gm, r["sampled_global_minimum"]) or not r10.rounds_to(gp, r["sampled_global_phase"]):
            failures.append(f"section 4 row {n} is not the data's")
    # section 5: the stationary table
    rows = re.findall(r"^\|\s*(\d+)\s*\|\s*([\d.]+)\s*\|\s*([\d.]+)\s*\|\s*(smooth_\w+)\s*\|\s*`([^`]+)`\s*\|", rp, re.M)
    if len(rows) != len(S["stationary_points"]):
        failures.append(f"section 5: {len(rows)} rows")
    for (k, ph, sc, kd, sg), st in zip(rows, S["stationary_points"]):
        if not (r10.rounds_to(ph, st["phase"]) and r10.rounds_to(sc, st["scale"]) and kd == st["kind"] and sg == st["signature"]):
            failures.append(f"section 5 row {k} is not the data's")
    # section 6: the switch table
    rows = re.findall(r"^\|\s*(\d+)\s*\|\s*([\d.]+)\s*\|\s*`([^`]+)`\s*\|\s*`([^`]+)`\s*\|\s*(\w+)\s*\|\s*(-?[\d.]+)\s*\|\s*(-?[\d.]+)\s*\|", rp, re.M)
    if len(rows) != len(S["contact_switches"]):
        failures.append(f"section 6: {len(rows)} rows")
    for (k, ph, ls, rs_, kd, dl, dr), sw in zip(rows, S["contact_switches"]):
        if not (r10.rounds_to(ph, sw["phase"]) and ls == sw["left_signature"] and rs_ == sw["right_signature"] and kd == sw["kind"]
                and r10.rounds_to(dl, sw["left_derivative"]) and r10.rounds_to(dr, sw["right_derivative"])):
            failures.append(f"section 6 row {k} is not the data's")
    m = re.search(r"其中有(\S)個接觸切換形成尖點局部極小", rs)
    ncusp = sum(1 for sw in S["contact_switches"] if sw["kind"] == "cusp_minimum")
    if not m or {"四": 4, "三": 3, "五": 5}.get(m.group(1)) != ncusp:
        failures.append("section 6's count of cusp minima is not the data's")
    # section 7: the ranking
    rows = re.findall(r"^\|\s*(\d)\s*\|\s*(\w+)\s*\|\s*([\d.]+)\s*\|\s*([\d.]+)\s*\|\s*(-?[\d.e+-]+)\s*\|\s*`([^`]+)`\s*\|", rp, re.M)
    if len(rows) != len(S["minimum_candidates"]):
        failures.append(f"section 7: {len(rows)} rows")
    for (k, src, ph, sc, mar, sg), c in zip(rows, S["minimum_candidates"]):
        if not (src == c["source"] and r10.rounds_to(ph, c["phase"]) and r10.rounds_to(sc, c["scale"]) and sg == c["signature"]
                and r10.rounds_to(mar, c["scale"] - S["reference_270_arbitrary_precision"])):
            failures.append(f"section 7 row {k} is not the data's")
    # README and the report's counts
    counts = {"活動身份區間": 18, "不同接觸簽章": len(S["phase_map"]["distinct_signatures"]), "光滑駐點": len(S["stationary_points"]),
              "取樣局部極小": S["multi_resolution_audit"][0]["sampled_local_minimum_count"]}
    for label, v in counts.items():
        m = re.search(label + r"：(\d+)", rd)
        if not m or int(m.group(1)) != v:
            failures.append(f"the README's {label} is not the data's")
    if "接觸切換數保持 18" not in rd or "簽章數保持 18" not in rd or "局部極小數保持 8" not in rd or "257、1025、4097" not in rd:
        failures.append("the README's stability lines are not the data's")
    m = re.search(r"約 \$(\d\.\d+)\\times10\^\{-9\}\$", rd)
    # the 120-degree branch's height above s270, Round 09's: 1.638334069193e-9
    if not m or not r10.rounds_to(m.group(1) + "e-9", 1.638334069193151e-9):
        failures.append("the README's gap is not the 120-degree margin")
    m = re.search(r"s_\{120\}-s_\{270\}\\approx([\d.]+)\\times10\^\{-9\}", rs)
    if not m or not r10.rounds_to(m.group(1) + "e-9", 1.638334069193151e-9):
        failures.append("section 8's gap is not Round 09's")
    # the manifest and the interface note
    M = w["manifest"]
    if M["phase_interval_count"] != 18 or M["contact_switch_count"] != len(S["contact_switches"]) \
            or M["stationary_point_count"] != len(S["stationary_points"]) or M["global_candidate"] != {k: S["global_candidate"][k] for k in ("source", "phase", "scale", "signature")} \
            or M["version"] != "0.10" or sorted(M["files"]) != sorted(set(w["members"]) - {"MANIFEST.json"}):
        failures.append("the manifest is not the package's")
    if "s(\\phi)\\ges(3\\pi/2)" not in gate.squash(w["interface"]) or "本輪尚未聲稱完成此嚴格證書" not in w["interface"]:
        failures.append("the interface note does not state its target as open")
    return failures


def s9_digits(w):
    failures = []
    H = hp(w)
    s = r10.s270(H)
    m = min(r10.event_branches(H))
    with mp.workdps(200):
        d = s - m
    rs = gate.squash(w["report"])
    figs = [("section 7's s270", re.search(r"0\.99891433908463271725296441853670224618019211931483351998479812835127468110999017(?=\\ldots)", rs), s),
            ("section 11's s270", re.search(r"s_\{270\}=(0\.\d{60,})\\ldots", rs), s),
            ("section 11's s0", re.search(r"s_0=(0\.\d{60,})\\ldots", rs), m),
            ("section 11's difference", re.search(r"s_\{270\}-s_0=(0\.\d{40,})\\ldots", rs), d)]
    for label, mt, true in figs:
        txt = (mt.group(1) if mt and mt.groups() else (mt.group(0) if mt else None))
        if txt is None or not holds(txt, true):
            failures.append(f"{label} does not hold to its digits")
    return failures


CHECKS = {"S1": s1_parameters, "S2": s2_phase_map, "S3": s3_switches, "S4": s4_stationary, "S5": s5_derivative,
          "S6": s6_minima, "S7": s7_resolution, "S8": s8_consistency, "S9": s9_digits}
HPK = {"summary", "round05", "legs"}
DEPENDS = {
    "S1": {"summary", "round08_best", "round09", "source"},
    "S2": HPK | {"intervals_csv"},
    "S3": HPK,
    "S4": HPK,
    "S5": HPK | {"audit"},
    "S6": HPK | {"audit"},
    "S7": HPK | {"audit", "round09"},
    "S8": {"readme", "report", "interface", "manifest", "members", "summary"},
    "S9": {"report", "round05", "summary", "legs"},
}


# ---------------------------------------------------------------- the certificate: the least is at 3pi/2

def least_certificate(w, K=262144, target_gap=0.0, eta=0.05):
    """s(phi) >= s(3pi/2) for every phi, in interval arithmetic.
    - s(3pi/2) = y1/A + (x1 + l0)/B (the support identity there: theta in (pi/6, pi/2) makes the curve rise and fall,
      run right throughout, and peak in y/A - x/B at the wing's end p1), enclosed from the trapezoid boxes.
    - beside 3pi/2 and 2pi/3 (within eta): s >= g, the sum of the three functionals on the corners active on that side,
      and g' has one sign there (interval arithmetic over the phase interval), so g moves away from its value at the
      cusp; at 3pi/2 that value is s(3pi/2) itself, at 2pi/3 it exceeds s(3pi/2) (a linear form in x1, y1)
    - elsewhere: for an interval of half-width h about m and the points chosen at m, s(phi) >= G(m) - |G'(m)| h - Lip h^2/2,
      since |G''| <= sum |a_k| |q_k| <= Lip; every interval's bound must exceed the upper bound of s(3pi/2)"""
    H = hp(w)
    iv.dps = 30
    A, B = r10.legs_iv(H)
    funs = [(1 / A, 1 / B), (-1 / A, iv.mpf(0)), (iv.mpf(0), -1 / B)]           # max_d, min_x, min_y
    bx = r10.certificate_boxes(H, K)
    PX, PY = bx["PX"], bx["PY"]
    n_pts = len(PX)
    x1, y1, l0 = bx["x1"], bx["y1"], bx["l0"]
    D = H["summary"]["definitions"]["candidate"]
    beta, delta = iv.mpf(D["beta"]), iv.mpf(D["delta"])
    premise = bool(lo(beta) > hi(iv.pi / 6) and hi(beta + delta) < lo(iv.pi / 2))
    S270 = cusp_270(x1, y1, l0, A, B)
    S_hi = hi(S270)
    # the corners, centred as the boxes are (the same fixed translation)
    K1 = (len(PX) - 2) // 2
    corner = {"p0": (PX[0], PY[0]), "p1": (PX[K1], PY[K1]), "p2": (PX[K1 + 1], PY[K1 + 1]), "p3": (PX[-1], PY[-1])}

    def G(ph, pts, d=0):
        """the sum of the functionals (max_d, min_x, min_y) on fixed points, or its phase derivative"""
        c, s = iv.cos(ph), iv.sin(ph)
        tot = iv.mpf(0)
        for (a0, a1), (px, py) in zip(funs, pts):
            if d == 0:
                tot += (a0 * c + a1 * s) * px + (-a0 * s + a1 * c) * py
            else:
                tot += (-a0 * s + a1 * c) * px + (-a0 * c - a1 * s) * py
        return tot

    def one_sign(pts, a_, b_, sign, pieces=64):
        """G' has the given sign on [a_, b_]: interval arithmetic on `pieces` sub-intervals whose ends run from a_ to
        b_ exactly"""
        xs = [a_] + [a_ + (b_ - a_) * j / pieces for j in range(1, pieces)] + [b_]
        for j in range(pieces):
            Ph = iv.mpf([xs[j], xs[j + 1]])
            g = G(Ph, pts, 1)
            if not ((sign < 0 and hi(g) < 0) or (sign > 0 and lo(g) > 0)):
                return False
        return True
    p = corner
    with mp.workdps(40):
        e270, e120 = mp.mpf(3) * mp.pi / 2, 2 * mp.pi / 3
        # each side's range runs past the cusp's interval enclosure, so it contains the exact cusp 3pi/2 or 2pi/3
        E270, E120 = 3 * iv.pi / 2, 2 * iv.pi / 3
        # and is widened by 1e-12, so it overlaps the float ends of the pieces covered elsewhere
        wide = eta + mp.mpf("1e-12")
        # 3pi/2: left of it (p1, p3, p3) - max_d p1, min_x p3, min_y p3 - and right (p1, p0, p3)
        left270 = one_sign((p["p1"], p["p3"], p["p3"]), lo(E270) - wide, hi(E270), -1)
        right270 = one_sign((p["p1"], p["p0"], p["p3"]), lo(E270), hi(E270) + wide, +1)
        # 2pi/3: left (p3, p2, p1), right (p0, p2, p1); their values at 2pi/3 against s(3pi/2), as linear forms
        left120 = one_sign((p["p3"], p["p2"], p["p1"]), lo(E120) - wide, hi(E120), -1)
        right120 = one_sign((p["p0"], p["p2"], p["p1"]), lo(E120), hi(E120) + wide, +1)
    # g(2pi/3) - s(3pi/2) with the corners in terms of x1, y1 (uncentred), so the boxes enter once each
    ph = 2 * iv.pi / 3
    c, s = iv.cos(ph), iv.sin(ph)
    Q = {"p0": (iv.mpf(0), iv.mpf(0)), "p1": (x1, y1), "p2": (x1 + l0, y1), "p3": (2 * x1 + l0, iv.mpf(0))}

    def lin(md):
        # g at 2pi/3 minus s(3pi/2) = cx x1 + cy y1 + c0, gathered term by term
        nd = (c / A + s / B, -s / A + c / B)
        nx = (-c / A, s / A)
        ny = (-s / B, -c / B)
        cx_ = nx[0] + ny[0] + (2 * nd[0] if md == "p3" else 0) - 1 / B
        cy_ = nx[1] + ny[1] - 1 / A
        c0 = nx[0] * l0 + (nd[0] * l0 if md == "p3" else 0) - l0 / B
        return cx_ * x1 + cy_ * y1 + c0
    gap120 = [lin("p3"), lin("p0")]
    gap_ok = all(lo(g_) > 0 for g_ in gap120)
    # elsewhere: the cover
    cx = np.array([float(v.mid) for v in PX])
    cy = np.array([float(v.mid) for v in PY])
    with mp.workdps(40):
        mxe = max(max(abs(mp.mpf(v._mpi_[0])), abs(mp.mpf(v._mpi_[1]))) for v in PX)
        mye = max(max(abs(mp.mpf(v._mpi_[0])), abs(mp.mpf(v._mpi_[1]))) for v in PY)
    R_up = hi(iv.sqrt(iv.mpf(mxe) ** 2 + iv.mpf(mye) ** 2))
    Lip_up = hi(iv.mpf(R_up) * sum((iv.mpf(hi(iv.sqrt(a0 ** 2 + a1 ** 2))) for a0, a1 in funs), iv.mpf(0)))
    Lip = float(Lip_up) * (1 + 1e-12)
    af = [(float(a0.mid), float(a1.mid)) for a0, a1 in funs]
    neg_tang = -np.unwrap(np.arctan2(np.diff(cy), np.diff(cx)))
    S_f = float(S_hi)

    def best_idx(ph):
        c_, s_ = math.cos(ph), math.sin(ph)
        out = []
        for a0, a1 in af:
            n0, n1 = a0 * c_ + a1 * s_, -a0 * s_ + a1 * c_
            psi = math.atan2(n1, n0)
            ci = [0, n_pts - 1]
            for bnd in (psi - math.pi / 2, psi + math.pi / 2):
                k = int(np.searchsorted(neg_tang, -math.remainder(bnd, 2 * math.pi)))
                ci += [i for i in range(k - 2, k + 3) if 0 <= i < n_pts]
            ci = np.array(ci)
            vals = cx[ci] * n0 + cy[ci] * n1
            i = int(ci[int(np.argmax(vals))])
            out.append((i, float(vals.max()), float(cx[i] * (-a0 * s_ + a1 * c_) + cy[i] * (-a0 * c_ - a1 * s_))))
        return out
    pieces = [(0.0, float(e120) - eta), (float(e120) + eta, float(e270) - eta), (float(e270) + eta, 2 * math.pi + 1e-9)]
    leaves = []
    for a_, b_ in pieces:
        todo = [(a_ + (b_ - a_) * k / 512, a_ + (b_ - a_) * (k + 1) / 512) for k in range(512)][::-1]
        while todo:
            u, v = todo.pop()
            m = (u + v) / 2
            h = (v - u) / 2
            bi = best_idx(m)
            est = sum(x[1] for x in bi) - abs(sum(x[2] for x in bi)) * h - Lip * h * h / 2 - 1e-11
            if est > S_f + target_gap:
                leaves.append((u, v, m, [x[0] for x in bi]))
            elif h < 1e-12:
                raise ValueError(f"cannot cover near {m}")
            else:
                todo += [(m, v), (u, m)]
    LipI = iv.mpf(Lip_up)
    worst = None
    for u, v, m, idx in leaves:
        M = iv.mpf(m)
        h = iv.mpf(max(hi(M - iv.mpf(u)), hi(iv.mpf(v) - M)))
        pts = [(PX[i], PY[i]) for i in idx]
        g0, g1 = G(M, pts), G(M, pts, 1)
        lb = lo(g0 - iv.mpf(max(abs(lo(g1)), abs(hi(g1)))) * h - LipI * h * h / 2)
        if worst is None or lb < worst[0]:
            worst = (lb, m)
    # the pieces and the two neighbourhoods tile the circle: [0, 2pi/3 - eta] [.. + eta, 3pi/2 - eta] [.. + eta, 2pi + 1e-9]
    sl = sorted((u, v) for u, v, _, _ in leaves)
    tiled = all(x[1] == y[0] or (x[1], y[0]) in ((pieces[0][1], pieces[1][0]), (pieces[1][1], pieces[2][0]))
                for x, y in zip(sl, sl[1:])) and sl[0][0] == 0.0 and sl[-1][1] >= 2 * math.pi
    with mp.workdps(40):
        nb_ok = abs(mp.mpf(pieces[0][1]) - (e120 - eta)) < 1e-12 and abs(mp.mpf(pieces[1][0]) - (e120 + eta)) < 1e-12 \
            and abs(mp.mpf(pieces[1][1]) - (e270 - eta)) < 1e-12 and abs(mp.mpf(pieces[2][0]) - (e270 + eta)) < 1e-12
    E_up = r10.event_least_upper(H)
    out = {"wing_steps": K, "interval_digits": 30, "premise_beta_above_pi_6_alpha_below_pi_2": premise,
           "largest_box": [max(float(v.delta) for v in PX), max(float(v.delta) for v in PY)],
           "s270_at_least": dec(lo(S270), 15), "s270_at_most": dec(S_hi, 15, up=True),
           "neighbourhood_half_width": eta,
           "derivative_signs": {"left_of_3pi_2": left270, "right_of_3pi_2": right270, "left_of_2pi_3": left120, "right_of_2pi_3": right120},
           "s_2pi_3_corners_minus_s270_at_least": [dec(lo(g_), 15) for g_ in gap120],
           "radius_at_most": dec(R_up, 8, up=True), "lipschitz_at_most": dec(Lip_up, 8, up=True),
           "phase_intervals": len(leaves), "pieces_tiled": bool(tiled and nb_ok),
           "elsewhere_at_least": dec(worst[0], 15), "elsewhere_worst_midpoint": worst[1],
           "elsewhere_minus_s270_upper_at_least": dec(worst[0] - S_hi, 15),
           "event_least_at_most": dec(E_up, 30, up=True),
           "candidate_least_minus_event_least_at_least": dec(lo(S270) - E_up, 20)}
    out["certified"] = bool(premise and left270 and right270 and left120 and right120 and gap_ok and tiled and nb_ok
                            and worst[0] > S_hi)
    return out


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

def findings(w):
    S = w["summary"]
    out = {}
    sw_rows = []
    for i, sw in enumerate(S["contact_switches"]):
        e = exact_switch(w, sw)
        with mp.workdps(60):
            sw_rows.append({"index": i, "phase_minus_exact": mp.nstr(mp.mpf(sw["phase"]) - e["phase"], 3),
                            "scale_minus_exact": mp.nstr(mp.mpf(sw["scale"]) - e["scale"], 3),
                            "interior": e["interior"], "exact_left": mp.nstr(e["left"], 12), "exact_right": mp.nstr(e["right"], 12),
                            "stated_left_minus_exact": mp.nstr(mp.mpf(sw["left_derivative"]) - e["left"], 3),
                            "stated_right_minus_exact": mp.nstr(mp.mpf(sw["right_derivative"]) - e["right"], 3),
                            "stated_kind": sw["kind"], "exact_cusp_minimum": bool(e["left"] < 0 < e["right"])})
    out["switches"] = sw_rows
    stat = all_stationary(w)
    out["stationary_count"] = len(stat)
    out["stationary"] = [{"interval": e["interval"], "phase": mp.nstr(e["phase"], 20), "scale": mp.nstr(e["scale"], 20),
                          "kind": e["kind"]} for e in stat]
    # interval 9's minimum against the stated cusp
    C = cand(w)
    i9 = [e for e in stat if e["interval"] == 9]
    if i9:
        sw9 = exact_switch(w, S["contact_switches"][9])
        with mp.workdps(60):
            out["interval_9_minimum"] = {"phase": mp.nstr(i9[0]["phase"], 25), "switch_minus_phase": mp.nstr(sw9["phase"] - i9[0]["phase"], 5),
                                         "scale": mp.nstr(i9[0]["scale"], 20),
                                         "stated_cusp_minus_minimum": mp.nstr(mp.mpf(S["contact_switches"][9]["scale"]) - i9[0]["scale"], 5)}
    # the derivative's steepness beside a switch to an interior support (interval 1)
    I1 = S["phase_map"]["intervals"][1]
    with mp.workdps(60):
        a, b = mp.mpf(I1["start"]), mp.mpf(I1["end"])
        out["interval_1_derivative"] = {f: mp.nstr(deriv(C, I1["signature"], a + mp.mpf(f) * (b - a)), 6)
                                        for f in ("0", "1e-9", "1e-6", "1e-3", "0.5", "0.999", "0.999999", "1")}
        th = C.theta
        out["wing_angle_within_of_alpha_at_u_0.3"] = mp.nstr((C.b + C.d) - th(mp.mpf("0.3")), 3)
        out["wing_angle_within_of_beta_at_u_0.85"] = mp.nstr(th(mp.mpf("0.85")) - C.b, 3)
    # the stated stationary points and special phases against this run's, and each tolerance's margin
    st_dev = []
    for st in S["stationary_points"]:
        e = min(stat, key=lambda e: abs(e["phase"] - mp.mpf(st["phase"])))
        st_dev.append((abs(mp.mpf(st["phase"]) - e["phase"]), abs(mp.mpf(st["scale"]) - e["scale"])))
    out["stated_stationary_largest_deviation"] = {"phase": mp.nstr(max(d[0] for d in st_dev), 3), "scale": mp.nstr(max(d[1] for d in st_dev), 3)}
    sp_dev = []
    with mp.workdps(60):
        for sp in S["special_phases"]:
            ph = 2 * mp.pi / 3 if sp["name"] == "120deg" else 3 * mp.pi / 2
            Dm, Dp = C.dsides(ph)
            sp_dev.append({"name": sp["name"], "scale": mp.nstr(mp.mpf(sp["scale"]) - C.s(ph), 3),
                           "left": mp.nstr(sp["left_derivative"] - Dm, 3), "right": mp.nstr(sp["right_derivative"] - Dp, 3)})
    out["special_phases_minus_exact"] = sp_dev
    mins = exact_minima(w)
    cand_dev = max(abs(mp.mpf(c["scale"]) - m["scale"]) for c, m in zip(S["minimum_candidates"], mins) if c["source"] != "contact_switch_cusp" or m["source"] == "cusp")
    sw_scale = max(abs(float(r["scale_minus_exact"])) for r in sw_rows)
    sw_phase = max(abs(float(r["phase_minus_exact"])) for r in sw_rows)
    corner = max(max(abs(float(r["stated_left_minus_exact"])), abs(float(r["stated_right_minus_exact"]))) for r in sw_rows if not r["interior"])
    scan_dev = max(abs(mp.mpf(r["sampled_global_minimum"]) - C.s(3 * mp.pi / 2)) for r in S["multi_resolution_audit"])
    out["check_margins"] = {"S2_switch_phase": 1e-12 / sw_phase, "S3_switch_scale": 2e-13 / sw_scale, "S3_corner_derivative": 1e-7 / corner,
                            "S4_phase": mp.nstr(mp.mpf("1e-11") / max(d[0] for d in st_dev), 3),
                            "S4_scale": mp.nstr(mp.mpf("2e-13") / max(d[1] for d in st_dev), 3),
                            "S6_candidate_scale_where_the_kind_holds": mp.nstr(mp.mpf("2e-13") / cand_dev, 3),
                            "S7_global": mp.nstr(mp.mpf("2e-13") / scan_dev, 3)}
    out["derivative_extremes"] = {i: [mp.nstr(exact_stationary(w, i)["min"], 6), mp.nstr(exact_stationary(w, i)["max"], 6)] for i in range(18)}
    out["scans"] = {n: scan_summary(w, n) for n in (32768, 65536, 131072, 262144)}
    out["certificate"] = least_certificate(w)
    return out


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

def drill_cases(base):
    def edit(key, fn):
        v = copy.deepcopy(base[key])
        fn(v)
        return v
    S = base["summary"]
    b8 = edit("round08_best", lambda b: b["parameters"].__setitem__(3, b["parameters"][3] + 1e-16))
    src = base["source"].replace("argmax diagonal support", "argmax diagonal")
    # a switch moved by 1e-9, with the map's boundary moved alike
    def move(s):
        s["contact_switches"][4]["phase"] += 1e-9
        s["phase_map"]["boundaries"][4]["phase"] = s["contact_switches"][4]["phase"]
    sw_phase = edit("summary", move)
    rep_sw = base["report"].replace("| 4 | 1.570796326795 |", f"| 4 | {sw_phase['contact_switches'][4]['phase']:.12f} |")
    sw_scale = edit("summary", lambda s: s["contact_switches"][10].__setitem__("scale", s["contact_switches"][10]["scale"] + 1e-12))
    sw_der = edit("summary", lambda s: s["contact_switches"][4].__setitem__("right_derivative", s["contact_switches"][4]["right_derivative"] + 2e-7))
    st_scale = edit("summary", lambda s: s["stationary_points"][0].__setitem__("scale", s["stationary_points"][0]["scale"] - 3e-13))
    st_place = edit("summary", lambda s: s["stationary_points"][1].__setitem__("interval_index", 2))
    # the sampled derivative's maximum in interval 2, in the summary and the CSV alike
    da = edit("summary", lambda s: s["interval_derivative_analysis"][2].__setitem__("sample_derivative_max", s["interval_derivative_analysis"][2]["sample_derivative_max"] + 0.01))
    dcsv = edit("intervals_csv", lambda rows: rows[2].__setitem__("derivative_max", repr(da["interval_derivative_analysis"][2]["sample_derivative_max"])))
    guard = edit("audit", lambda a: a["derivative_root_guards"][4]["grids"]["1025"].__setitem__("root_count", 2))
    # a minimum candidate's scale, with the report's section 7 cell alike
    newc = S["minimum_candidates"][4]["scale"] + 3e-13
    mc = edit("summary", lambda s: s["minimum_candidates"][4].__setitem__("scale", newc))
    rep7 = base["report"].replace("| 1.029351988860359 |", f"| {newc:.15f} |")
    # a ledger margin, in the summary and the audit alike
    lm = lambda L: L[17].__setitem__("margin_above_round9_270", L[17]["margin_above_round9_270"] + 1e-9)
    led_s = edit("summary", lambda s: lm(s["interval_minimum_ledger"]))
    led_a = edit("audit", lambda a: lm(a["interval_minimum_ledger"]))
    # a resolution count, in the summary, the audit and the report's section 4 alike
    rc = lambda R: R[1].__setitem__("sampled_local_minimum_count", 9)
    res_s = edit("summary", lambda s: rc(s["multi_resolution_audit"]))
    res_a = edit("audit", lambda a: rc(a["multi_resolution_contact_map"]))
    rep4 = base["report"].replace("| 65536 | 18 | 18 | 8 |", "| 65536 | 18 | 18 | 9 |")
    rep6 = base["report"].replace("其中有四個接觸切換", "其中有三個接觸切換")
    readme = base["readme"].replace("光滑駐點：12", "光滑駐點：13")
    s0 = "0.9989037571325086749551298249005564802172682267121921037894386799512563"
    rep11 = base["report"].replace(s0, s0[:52] + str((int(s0[52]) + 1) % 10) + s0[53:])
    man = edit("manifest", lambda m: m.__setitem__("stationary_point_count", 13))
    csv_st = edit("intervals_csv", lambda rows: rows[7].__setitem__("stationary_count", "2"))
    for x, y in ((src, base["source"]), (rep_sw, base["report"]), (rep7, base["report"]), (rep4, base["report"]), (rep6, base["report"]),
                 (readme, base["readme"]), (rep11, base["report"])):
        assert x != y, "a plant must hit the raw text"
    return [
        ("K0-unmodified", "control", {}, set()),
        ("K1-report-crlf", "control", {"report": base["report"].replace("\n", "\r\n")}, set()),
        ("K2-readme-trailing-spaces", "control", {"readme": "\n".join(l + " " for l in base["readme"].split("\n"))}, set()),
        ("K3-audit-copied", "control", {"audit": copy.deepcopy(base["audit"])}, set()),
        ("M1-triangle-leg", "mutation", {"legs": ("1.0005", "1")}, {"S2", "S3", "S4", "S5", "S6", "S7", "S9"}),
        ("M2-round08-centre", "mutation", {"round08_best": b8}, {"S1"}),
        ("M3-source-note", "mutation", {"source": src}, {"S1"}),
        ("M4-switch-phase", "mutation", {"summary": sw_phase, "report": rep_sw}, {"S2"}),
        ("M5-switch-scale", "mutation", {"summary": sw_scale}, {"S3"}),
        ("M6-corner-derivative", "mutation", {"summary": sw_der}, {"S3"}),
        ("M7-stationary-scale", "mutation", {"summary": st_scale}, {"S4"}),
        ("M8-stationary-place", "mutation", {"summary": st_place}, {"S4"}),
        ("M9-sampled-derivative", "mutation", {"summary": da, "intervals_csv": dcsv}, {"S5"}),
        ("M10-guard-count", "mutation", {"audit": guard}, {"S5"}),
        ("M11-minimum-candidate", "mutation", {"summary": mc, "report": rep7}, {"S6"}),
        ("M12-ledger-margin", "mutation", {"summary": led_s, "audit": led_a}, {"S6"}),
        ("M13-resolution-count", "mutation", {"summary": res_s, "audit": res_a, "report": rep4}, {"S7"}),
        ("M14-cusp-count-word", "mutation", {"report": rep6}, {"S8"}),
        ("M15-readme-count", "mutation", {"readme": readme}, {"S8"}),
        ("M16-section11-digit", "mutation", {"report": rep11}, {"S9"}),
        ("M17-manifest-count", "mutation", {"manifest": man}, {"S8"}),
        ("M18-csv-stationary-count", "mutation", {"intervals_csv": csv_st}, {"S2"}),
    ]


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[:10]:
            print("    ", x)
    log = {"run": "RUN-011",
           "subject": "Round 10 (v0.10): the full phase-contact map, the stationary points and the global numerical exclusion",
           "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, ensure_ascii=False, default=str)[:9000])
    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, default=str) + "\n", encoding="utf-8", newline="\n")


if __name__ == "__main__":
    main()
