"""master/interactions — a ledger file of the master's blocks G, P and Z, interactions: the rows the interactions theme
proves (ledger migration, task LM29, 6 October 2026; the electroweak, strong, projection, exclusion and horizon rows
19 October 2026).

The master's block G is bound by this file (the interactions theme). It binds G11 (one generation, its content), G12
(one generation, its origin) and G16 (flavour, the Koide form), and since 19 October 2026 G1 (electromagnetism), G2
(the weak amplitudes), G4 (the strong structure), G5 (the string tension), G7 (the strong-CP angle, the python check
of its shared key p27043), G18 (the flavour projection), the prediction P4 (the exclusions, block P) and Z5 (the horizon
forcing the simple unification, block Z, the shared key p27021 of 27:C9): the table of keys (generated from
docs/00-ledger.json and docs/predictions.json by ci/make_ledgers.py), the Lean proofs each key conjoins (PROOFS; the
chart clauses of P4 on Mathlib, CHART), and the checks, which call the interactions theme (frc/interactions.py), the
horizon theme's tower (frc/ladder.py) and, for the exclusions' confrontations, the chart modules. The Lean side is
lean/FrcCore/Theme/Interactions.lean, Theme/Unitary.lean and Theme/Fields.lean, the key files lean/FrcCore/Keys/Interactions.lean
(and Keys/Hadrons.lean for the keys whose highest-ranked theorem is the hadrons theme's, G5 and P4) and the certificates
lean/FrcCore/Ledgers/Master/Interactions.lean and lean/FrcMathlib/Ledgers/Master/Interactions.lean (P4's chart clauses).

    python3 -m frc.ledgers.master.interactions        every block, the census; exit 1 if a check fails (≈ 3 s)

Blocks:  E  electromagnetism: charge as winding, the forced photon, the Coulomb table                    EXACT  (00:G1)
         W  the weak amplitudes: the V − A current from the Frobenius branch, G_F = 1/(√2 v²)              EXACT  (00:G2)
         S  the strong sector: the rank tower, SU(3, 2) and its centre, the gluon, the tension's series     EXACT  (00:G4, 00:G5)
         C  the strong-CP angle: real determinants, the Wilson term even under orientation reversal        EXACT  (00:G7)
         H  one generation: the reflection algebra, the fifth direction, the 16 read 3 + 2                 EXACT  (00:G11, 00:G12)
         M  the flavour projection: the 16 through C₃ × Q₄, anchored at the neutral singlet ν^c             EXACT  (00:G18)
         K  the Koide form on the cube-root orbit                                                         EXACT  (00:G16)
         U  the horizon forces structure: the off-block automorphisms, the torsion beyond the horizon       EXACT  (00:Z5)
         X  the exclusions: the closed ladder, the one generation, the proton's lifetime, the running       CHART  (00:P4)

The notebook frc/ledgers/master/interactions.ipynb runs one row per cell, the cell's id its key (gate G13).
"""
import random
import sys
from collections import Counter
from fractions import Fraction
from math import comb, gcd, isqrt

from frc import arith
from frc.registry import Registry
from frc import interactions as I
from frc import ladder as LD
from frc import chart as CH
from frc import chart_dark as CD
from frc import chart_fields as CF
from frc import hadrons as HD
from frc.interactions import bit, cnt, emul, fifth, gen16, col, wk, y6, q6, koide_q, koide_rho2

# ---- generated by ci/make_ledgers.py from docs/00-ledger.json; edit the ledger, not this table ----
BLOCK = "GPZ"
KEYS = {"G1": "p00178", "G2": "p00067", "G3": "p00068", "G4": "p00069", "G5": "p00070", "G6": "p00071", "G7": "p27043", "G8": "p00073", "G9": "p00074", "G10": "p00075", "G11": "p27020", "G12": "p00155", "G13": "p00078", "G14": "p00079", "G15": "p00080", "G16": "p00081", "G17": "p00179", "G18": "p00083", "G19": "p00088", "G20": "p00089", "G21": "p00090", "Z1": "p00186", "Z2": "p00110", "Z3": "p00111", "Z4": "p00112", "Z5": "p27021", "Z6": "p00114", "Z7": "p00115", "Z8": "p00116", "Z9": "p00187", "Z10": "p20043", "Z11": "p00135", "P1": "p00133", "P2": "p00061", "P3": "p00180", "P4": "p00091"}       # every row of the blocks: its label and its accession key
LEAN = {"G1": "core", "G2": "core", "G4": "core", "G5": "core", "G7": "core", "G11": "core", "G12": "core", "G16": "core", "G18": "core", "Z5": "core", "P4": "core, ml"}       # the rows with a Lean declaration: the libraries whose key files prove them
# ---- end of the generated table ----

# The Lean proofs of the rows' keys: the theorems of the themes that each key conjoins (lean/make_keys.py writes the keys
# FRC.Ledger.p<key> from them). The master's block file is the binding's source, as a paper's \lean{} cells are its own.
PROOFS = {
    "G1": ["FRC.Interactions.gauge_flux_invariant", "FRC.Interactions.projector_forced", "FRC.Interactions.admissible_two",
           "FRC.Interactions.green_torus"],                                                 # 19 October 2026: 27:C2's and 27:C3's theorems
    "G2": ["FRC.Interactions.va_cancel", "FRC.Interactions.orientation_flip"],          # 19 October 2026: the V − A current (27:C4, 27:X6); G_F is 27:C6's Mathlib fermi_constant, a chart clause no T row of block G may bind (G08)
    "G4": ["FRC.Interactions.rank_tower", "FRC.Interactions.su3_centre", "FRC.Interactions.gluon_commutator"],   # 19 October 2026: 27:C7's and 27:X7's core theorems; the area law's positivity is their Mathlib area_law_positive
    "G5": ["FRC.Interactions.tetrahedral_group", "FRC.Hadrons.adjoint_channel"],             # 19 October 2026: SU(2, 𝔽₃) = 2T and the SU(3) Haar moments by the Weyl constant term, the data of the tension's closed form and series; the key lives in Keys/Hadrons.lean
    "G7": ["FRC.Unitary.wilson_orientation_even", "FRC.Unitary.hermitian_det_real", "FRC.Unitary.hermitian_det_shell"],        # 16 October 2026 (27-fields' migration): the key p27043 is 27:P9's, shared under LM13; the python check is 27:H3 (frc/ledgers/p27_fields.py)
    "G11": ["FRC.Interactions.one_generation"],
    "G12": ["FRC.Interactions.reflection_algebra", "FRC.Interactions.fifth_direction"],
    "G16": ["FRC.Interactions.koide_parseval", "FRC.Interactions.koide_two_thirds", "FRC.Interactions.koide_extension",
            "FRC.Interactions.koide_half"],
    "G18": ["FRC.Interactions.fifth_direction", "FRC.Interactions.one_generation"],     # 19 October 2026: the quarter-turn as the fifth direction (28:C12) and the generation's content with its one neutral singlet ν^c
    "P4": ["FRC.Ladder.tower_reduces", "FRC.Interactions.one_generation", "FRC.Interactions.unification_counts",
           "FRC.Hadrons.colourless_content"],                                          # 19 October 2026: 27:P1, P2, P6, P7 (the closed ladder, the one generation), 27:P4 (the off-block leptoquarks) and 35:P4 (the proton as the minimal colour-neutral wrap); the key lives in Keys/Hadrons.lean
    "Z5": ["FRC.Interactions.unification_counts", "FRC.Interactions.fifth_direction", "FRC.Interactions.offblock_automorphism",
           "FRC.Interactions.torsion_beyond_horizon"],                                 # 19 October 2026: the shared key p27021 of 27:C9, bound as the paper binds it
}

# The Mathlib theorems of P4's chart clauses (the confrontations of a prediction row, Q23): the one-loop running's near-miss,
# the proton lifetime at the substrate scale, the one-variable law of the dark sector (32:P6).
CHART = {
    "P4": ["FRC.FieldsML.running_near_miss", "FRC.FieldsML.proton_lifetime", "FRC.DarkML.rar_monotone"],
}

LEAN_ONLY = ()                  # the rows with a Lean declaration and no python check in this file (gate G12): none (G7's python check is C1 since 19 October 2026; 27:H3 decides 27:P9 on the same key)

LEDGER = {"E1": "00:G1", "E2": "00:G1", "W1": "00:G2", "W2": "00:G2", "S1": "00:G4", "S2": "00:G5", "C1": "00:G7",
          "H1": "00:G12", "H2": "00:G11", "H3": "00:G11", "M1": "00:G18", "K1": "00:G16", "K2": "00:G16", "K3": "00:G16",
          "U1": "00:Z5", "X1": "00:P4"}
BLOCKS = {"E": "electromagnetism: charge as winding, the forced photon, the Coulomb table",
          "W": "the weak amplitudes: the V − A current from the Frobenius branch, G_F = 1/(√2 v²)",
          "S": "the strong sector: the rank tower, SU(3, 2) and its centre, the gluon, the tension's series",
          "C": "the strong-CP angle: real determinants, the Wilson term even under orientation reversal",
          "H": "one generation: the reflection algebra, the fifth direction, the 16 read 3 + 2",
          "M": "the flavour projection: the 16 through C₃ × Q₄, anchored at the neutral singlet ν^c",
          "K": "the Koide form on the cube-root orbit",
          "U": "the horizon forces structure: the off-block automorphisms, the torsion beyond the horizon",
          "X": "the exclusions: the closed ladder, the one generation, the proton's lifetime, the running"}
PREDICATES = {"00:G1": "E1", "00:G2": "W1", "00:G4": "S1", "00:G5": "S2", "00:G7": "C1", "00:G12": "H1", "00:G11": "H2",
              "00:G18": "M1", "00:G16": "K1", "00:Z5": "U1", "00:P4": "X1"}

R = Registry("00", "interactions", LEDGER, PREDICATES, sources=[__file__])

# the Standard-Model generation by name: (colour rep, weak rep, Y) and its multiplicity
SM = {"nu^c": ("1", "1", Fraction(0)), "u^c": ("3b", "1", Fraction(-2, 3)), "Q": ("3", "2", Fraction(1, 6)),
      "e^c": ("1", "1", Fraction(1)), "L": ("1", "2", Fraction(-1, 2)), "d^c": ("3b", "1", Fraction(1, 3))}
DIM = {"1": 1, "2": 2, "3": 3, "3b": 3}


# ------------------------------------------------------------------------------------------------------------
# block H: one generation (00:G11, 00:G12)
@R.block("H", BLOCKS["H"])
def block_H():
    """Block H — one generation (EXACT): H1–H3."""
    # 00:G12 (p00155)
    basis = range(16)
    def mulvec(x, y):                     # product of algebra elements as dicts index -> coefficient
        out = {}
        for S, a in x.items():
            for T, b in y.items():
                s, U = emul(S, T)
                if s: out[U] = out.get(U, 0) + s * a * b
        return {k: v for k, v in out.items() if v}
    rng = random.Random(12)
    ok = all(mulvec(mulvec({S: 1}, {T: 1}), {U: 1}) == mulvec({S: 1}, mulvec({T: 1}, {U: 1}))
             for S in basis for T in basis for U in basis)
    for _ in range(200):                  # associativity on random elements
        x, y, z = ({S: rng.randrange(-3, 4) for S in basis} for _ in range(3))
        ok &= mulvec(mulvec(x, y), z) == mulvec(x, mulvec(y, z))
    ok &= all(emul(1 << i, 1 << j) == ((0, 0) if i == j else (-emul(1 << j, 1 << i)[0], emul(1 << j, 1 << i)[1]))
              for i in range(4) for j in range(4))
    imgs = [fifth(S) for S in basis]
    ok &= sorted(imgs) == gen16() and len(gen16()) == 16
    ok &= all(emul(S, 16) == (1, S | 16) for S in basis if cnt(S, 0, 4) % 2)
    R.check("H1", "the reflection algebra of four directions: 16 basis elements, the product associative on all 4 096 basis "
            "triples and on 200 random elements, distinct directions anticommuting and squaring to zero; the fifth "
            "direction e_S ↦ e_S, e_S e_4 maps the 16 one-to-one onto the even subsets of five directions", ok,
            f"images {imgs}")
    # 00:G11 (p27020)
    g = gen16()
    content = {}
    # the colour type by triality: the centre ω·1 of SU(3) acts on Λᵏ(ℂ³) as ωᵏ, so k ≡ 0, 1, 2 (mod 3) is the
    # singlet, the 3 and the 3̄ (Λ² ≅ 3̄ by the volume form); the weak type by Λᵏ(ℂ²): k = 1 the doublet, else a singlet
    # (the template Λᵏ(ℂⁿ) for the k-th fundamental is imported)
    TRIALITY = {0: "1", 1: "3", 2: "3b"}
    for S in g:
        c, w = col(S), wk(S)
        rep = (TRIALITY[c % 3], {0: "1", 1: "2", 2: "1"}[w], Fraction(y6(S), 6))
        content[rep] = content.get(rep, 0) + 1
    want = {(c, w, y): DIM[c] * DIM[w] for c, w, y in SM.values()}
    ok = content == want
    ok &= all(comb(3, k) == DIM[TRIALITY[k % 3]] for k in range(4)) and all(comb(2, k) == DIM[{0: "1", 1: "2", 2: "1"}[k]] for k in range(3))
    ok &= sum(y6(S) for S in g) == 0 and sum(y6(S) ** 3 for S in g) == 0
    ok &= sum(y6(S) for S in g if col(S) in (1, 2)) == 0 and sum(y6(S) for S in g if wk(S) == 1) == 0
    ok &= sorted(Fraction(q6(S), 6) for S in g) == sorted([Fraction(0), Fraction(0)] + [Fraction(2, 3)] * 3 + [Fraction(-2, 3)] * 3
                                                            + [Fraction(-1, 3)] * 3 + [Fraction(1, 3)] * 3 + [Fraction(1), Fraction(-1)])
    R.check("H2", "the 16 read 3 + 2, the colour type by triality (k mod 3 on Λᵏ(ℂ³)) and the weak type by Λᵏ(ℂ²), dimensions "
            "binom(3, k) and binom(2, k): the content ν^c + u^c + Q + e^c + L + d^c with their hypercharges, by name against the "
            "Standard-Model table; Σ Y = Σ Y³ = 0, SU(3)²Y = SU(2)²Y = 0; the charges 0, 0, ±2/3 ×3, ±1/3 ×3, ±1", ok,
            f"content {dict((f'{k[0]},{k[1]},{k[2]}', v) for k, v in content.items())}")
    # H3 a second method: the anomaly sums by multiplet, from the table
    s1 = sum(DIM[c] * DIM[w] * y for c, w, y in SM.values())
    s3 = sum(DIM[c] * DIM[w] * y ** 3 for c, w, y in SM.values())
    s33 = sum(DIM[w] * y for c, w, y in SM.values() if c != "1")
    s22 = sum(DIM[c] * y for c, w, y in SM.values() if w == "2")
    R.check("H3", "the anomaly sums from the multiplet table: Σ d Y = 0, Σ d Y³ = 0, SU(3)²Y = 0, SU(2)²Y = 0; four doublets",
            s1 == s3 == s33 == s22 == 0 and sum(DIM[c] for c, w, y in SM.values() if w == "2") == 4,
            f"{s1}, {s3}, {s33}, {s22}")


# ------------------------------------------------------------------------------------------------------------
# block K: the Koide form (00:G16)
@R.block("K", BLOCKS["K"])
def block_K():
    """Block K — the Koide form (EXACT): K1–K3."""
    # 00:G16 (p00081)
    bad = []
    for p in [q for q in range(7, 400) if q % 3 == 1 and arith.is_prime(q)]:
        w = next(x for x in range(2, p) if (x * x + x + 1) % p == 0)
        rng = random.Random(p)
        for _ in range(30):
            a = [rng.randrange(p) for _ in range(3)]
            hat, lhs, rhs = koide_rho2(a, p, w)
            if lhs != rhs: bad.append(p)
            if ((lhs - 2 * hat[0] ** 2) % p == 0) != ((2 * hat[1] * hat[2] - hat[0] ** 2) % p == 0): bad.append(p)
    R.check("K1", "every prime p ≡ 1 (mod 3) below 400 with ω² + ω + 1 = 0, 30 random amplitude vectors each: 3 Σ a² = â₀² + "
            "2 â₁â₂ (Q = 1/3 + 2ρ²/3), and 3 Σ a² = 2 â₀² exactly when 2 â₁â₂ = â₀² (Q = 2/3 ⟺ ρ² = 1/2)", not bad,
            f"exceptions {bad[:3]}")
    # K2 a second method: the cube-root orbit a_k = 1 + ρ(z ω^k + z⁻¹ ω^{−k}) in 𝔽_p has Σ a = 3 and Σ a² = 3 + 6ρ²
    bad = []
    for p in [q for q in range(7, 400) if q % 3 == 1 and arith.is_prime(q)]:
        w = next(x for x in range(2, p) if (x * x + x + 1) % p == 0)
        for z in range(1, p, max(1, p // 7)):
            zi = pow(z, -1, p)
            for rho in range(p):
                a = [(1 + rho * (z * pow(w, k, p) + zi * pow(w, -k % 3, p))) % p for k in range(3)]
                if sum(a) % p != 3 % p or sum(x * x for x in a) % p != (3 + 6 * rho * rho) % p: bad.append(p); break
    R.check("K2", "every prime p ≡ 1 (mod 3) below 400: on the cube-root orbit a_k = 1 + ρ(z ω^k + z⁻¹ ω^{−k}), Σ a = 3 and "
            "Σ a² = 3 + 6ρ² for every ρ and seven z, so Q = (3 + 6ρ²)/9 = 1/3 + 2ρ²/3, and Q = 2/3 at ρ² = 1/2",
            not bad, f"exceptions {bad[:3]}")
    # K3 every shell, the Carriers included: in the extension 𝔽_p[w]/(w² + 3), ω = −h + h w (h = 1/2) is a cube root of
    # unity, â₂ = â̄₁, and 3 Σ a² = â₀² + 2 N(â₁) with N(x + y w) = x² + 3 y² (Interactions.lean: koide_extension, koide_half)
    def emul3(z, u, p): return ((z[0] * u[0] - 3 * z[1] * u[1]) % p, (z[0] * u[1] + z[1] * u[0]) % p)
    bad = []
    for p in [q for q in range(5, 400) if q % 3 == 2 and arith.is_prime(q)] + [233, 30089, 2408561]:
        h = (p + 1) // 2
        om = ((-h) % p, h)
        om2 = emul3(om, om, p)
        if ((om2[0] + om[0] + 1) % p, (om2[1] + om[1]) % p) != (0, 0) or emul3(om2, om, p) != (1, 0): bad.append(p); continue
        rng = random.Random(p)
        for _ in range(30):
            a = [rng.randrange(p) for _ in range(3)]
            hat1 = ((a[0] + a[1] * om[0] + a[2] * om2[0]) % p, (a[1] * om[1] + a[2] * om2[1]) % p)
            hat2 = ((a[0] + a[1] * om2[0] + a[2] * om[0]) % p, (a[1] * om2[1] + a[2] * om[1]) % p)
            nrm = (hat1[0] ** 2 + 3 * hat1[1] ** 2) % p
            if hat2 != (hat1[0], (-hat1[1]) % p) or emul3(hat1, hat2, p) != (nrm, 0): bad.append(p); break
            if (3 * sum(x * x for x in a) - sum(a) ** 2 - 2 * nrm) % p: bad.append(p); break
    R.check("K3", "every prime p ≡ 2 (mod 3) below 400 and the Carriers 233, 30 089, 2 408 561 (no cube root of unity in "
            "𝔽_p): in 𝔽_p[w]/(w² + 3), ω = −1/2 + w/2 has ω² + ω + 1 = 0 and ω³ = 1; for 30 random amplitude vectors "
            "â₂ = â̄₁, â₁â₂ = N(â₁), and 3 Σ a² = â₀² + 2 N(â₁)", not bad, f"exceptions {bad[:3]}")


# ------------------------------------------------------------------------------------------------------------
# block E: electromagnetism (00:G1) — 27:C2's and 27:C3's deciding content on smaller lattices
@R.block("E", BLOCKS["E"])
def block_E():
    """Block E — electromagnetism (EXACT): E1–E2."""
    # 00:G1 (p00178)
    rng = random.Random(178); L = 6; ok_s = ok_a = True
    for M in (12, 156, 420):                                                   # charge = winding: the holonomy is the enclosed flux
        for _ in range(40):
            Ax = {(x, y): rng.randrange(M) for x in range(L) for y in range(L)}
            Ay = {(x, y): rng.randrange(M) for x in range(L) for y in range(L)}
            Fl = {(x, y): (Ax[(x, y)] + Ay[((x + 1) % L, y)] - Ax[(x, (y + 1) % L)] - Ay[(x, y)]) % M for x in range(L) for y in range(L)}
            a, b = rng.randrange(2, L), rng.randrange(2, L)
            ok_s &= I.holonomy(Ax, Ay, 0, 0, a, b, L, M) == sum(Fl[(x, y)] for x in range(a) for y in range(b)) % M
            a2 = rng.randrange(1, L - a + 1)
            ok_a &= (I.holonomy(Ax, Ay, 0, 0, a, b, L, M) + I.holonomy(Ax, Ay, a, 0, a2, b, L, M)) % M == I.holonomy(Ax, Ay, 0, 0, a + a2, b, L, M)
    pars, rows = I.maxwell_constraints(4)                                      # the forced photon: corank 2, the relevant operator the transverse projector
    cM = I.maxwell_form(4)
    adm = I.nullspace(rows, len(pars))
    corank = len(pars) - I.rank_mod(rows, len(pars), (1 << 61) - 1)
    maxwell = all(sum(r.get(a, 0) * cM[a] for a in r) == 0 for r in rows) and any(cM)
    P = I.transverse_projector()
    flat = lambda S0, S2: [x for r in S0 for x in r] + [x for a in S2 for b in a for c in b for x in c]
    vecs = [flat(*I.symbol_taylor(I.kernel_of(v))) for v in adm]
    rk = len(vecs[0]) - len(I.nullspace([{k: v[k] for k in range(len(v)) if v[k]} for v in vecs], len(vecs[0])))
    rel = next(v for v in vecs if any(v)); S2 = rel[9:]; Pf = [x for a in P for b in a for c in b for x in c]
    lam = next(s / p_ for s, p_ in zip(S2, Pf) if p_)
    proj = all(s == lam * p_ for s, p_ in zip(S2, Pf)) and lam != 0 and not any(rel[:9])
    R.check("E1", "charge = winding: the holonomy of a loop is the enclosed flux mod M and is additive over adjacent loops "
            "(M = 12, 156, 420, 40 random fields on L = 6); the photon forced: the range-1 gauge- and hypercubic-invariant "
            "quadratic actions on L = 4 have corank 2, Maxwell's plaquette action among them, and the one relevant O(k²) "
            "operator is exactly the transverse projector |k|²δ − kk (massless, unique up to its coefficient)",
            ok_s and ok_a and corank == 2 == len(adm) and maxwell and rk == 1 and proj,
            f"Stokes {ok_s}, additive {ok_a}; corank {corank}; relevant = {lam} × projector")
    axis = [I.green_exact(4, (k, 0, 0)) for k in range(4)]
    R.check("E2", "the Coulomb table: the L = 4 periodic Green's function is an exact rational, U(separation 1) = 257/7680, "
            "monotone G(0) > G(1) > G(2) on the axis (27:C3)", axis[1] == Fraction(257, 7680) and axis[0] > axis[1] > axis[2],
            "G(n,0,0) = " + ", ".join(str(g) for g in axis))


# ------------------------------------------------------------------------------------------------------------
# block W: the weak amplitudes (00:G2) — 27:C4's and 27:X6's V − A selection, 27:C6's four-fermion identity
@R.block("W", BLOCKS["W"])
def block_W():
    """Block W — the weak amplitudes (EXACT): W1–W2."""
    # 00:G2 (p00067)
    ok = True; det = []
    for q in (3, 5, 7, 13):
        N = q + 1
        ok &= all(q * a % N == (-a) % N for a in range(N))                       # Frobenius z ↦ z^q inverts the boost cycle
        dl = next(x for x in range(1, N) if gcd(x, N) == 1)
        for eps in (1, -1):                                                        # both orientation conventions
            counter = (2 * eps * dl) % N; aligned = I.char_sum(N, 0)
            ok &= aligned[0] == N and not any(aligned[1:]) and counter != 0 and I.cyclo_zero(I.char_sum(N, counter), N)
        det.append(f"C_{N}: δ = {dl}")
    R.check("W1", "the V − A current derived: Frobenius inverts the boost cycle C_{q+1} (q = 3, 5, 7, 13); over one drive "
            "period the drive-aligned branch couples with weight N and the counter-aligned branch exactly 0, for either "
            "orientation convention (the exponents 2δ and 2(N − δ) both sum to zero): maximal parity violation", ok, "; ".join(det))
    names = ("g", "v"); gg, v = (I.Poly.var(names, x) for x in names)
    MW2 = gg * gg * v * v * Fraction(1, 4)
    R.check("W2", "the four-fermion amplitude: G_F/√2 = g²/(8 M_W²) = 1/(2 v²) from M_W² = g² v²/4, so G_F = 1/(√2 v²), as a "
            "polynomial identity in g and v (27:C6)", 8 * MW2 == 2 * v * v * gg * gg, f"8 M_W² = {8 * MW2}")


# ------------------------------------------------------------------------------------------------------------
# block S: the strong sector (00:G4, 00:G5) — 27:C7's and 27:X7's structure, the tension's series
@R.block("S", BLOCKS["S"])
def block_S():
    """Block S — the strong sector (EXACT): S1 the structure, S2 the tension."""
    # 00:G4 (p00069)
    adm = [q for q in range(5, 200) if q % 12 == 5 and arith.is_prime(q)]
    tower = all([gcd(n_, Om + 1) for n_ in (1, 2, 3, 4)] == [1, 2, 3, 2] for Om in adm[:8])   # the ranks 1, 2, 3 and no 4
    F4 = I.Fq2(2, 1, 1); su3 = I.unitary_frames(F4, 3)
    one = tuple(tuple(F4.one if i == j else F4.zero for j in range(3)) for i in range(3))
    mm = lambda X, Y: I.mat_mul(F4, X, Y); dg = lambda X: I.dagger(F4, X)
    scalars = [x for x in F4.elements() if F4.norm(x) == 1 and F4.pow(x, 3) == F4.one]
    cent = [g for g in su3 if all(mm(g, h) == mm(h, g) for h in su3)]
    centre_ok = len(su3) == 216 and len(scalars) == 3 == len(cent) and all(any(g == tuple(tuple(x if i == j else F4.zero for j in range(3)) for i in range(3)) for x in scalars) for g in cent)
    gluon = next((U, V) for U in su3 for V in su3 if mm(U, V) != mm(V, U))      # the gluon self-coupling: a non-trivial commutator plaquette
    U, V = gluon; Up = mm(mm(U, V), mm(dg(U), dg(V)))
    wilson = I.trace(F4, mm(mm(V, Up), dg(V))) == I.trace(F4, Up)                 # the Wilson trace is gauge-invariant
    R.check("S1", "the colour frame forced: on the first eight shells Ω ≡ 5 (mod 12) the cycle Ω + 1 carries the ranks 1, 2, 3 "
            "and not 4 (the minimal triality frame is rank 3, the isospin rank 2); SU(3, 2) over F_4 built exactly, 216 "
            "elements, its centre the three scalars 1, w, w² (Z_3); two elements with a non-trivial commutator plaquette, "
            "the gluon self-coupling, its Wilson trace gauge-invariant; dim Λ^even(C⁵) = 16",
            tower and centre_ok and Up != one and wilson and sum(comb(5, k) for k in (0, 2, 4)) == 16,
            f"shells {adm[:8]}, |SU(3, 2)| = {len(su3)}, centre {len(cent)}")
    # 00:G5 (p00070)
    G, closed, unit, traces = I.tetrahedral_quaternions()
    ok = len(G) == 24 and closed and unit and traces == {2: 1, -2: 1, 0: 6, 1: 8, -1: 8}
    mom = [Fraction(sum(m * t ** k for t, m in traces.items()), 24) for k in range(8)]
    c2T = I.moment_c1_series(mom, 2, 7); cSU2 = I.bessel_ratio_series(1, 7)
    ok &= c2T[0] == 0 and c2T[1] == Fraction(1, 4) and c2T[:5] == cSU2[:5] and c2T[5] != cSU2[5]    # agreement through β⁴
    N_, D_, positive, c1_at_2 = I.area_law_rational(2)                            # 0 < c₁ < 1 for every x = e^{β/2} > 1: σ = −ln c₁ > 0
    ok &= positive and 0 < c1_at_2 < 1
    mom3 = [sum(comb(k, j) * I.su3_moment(j, k - j) for j in range(k + 1)) * Fraction(1, 2 ** k) for k in range(5)]
    c3 = I.moment_c1_series(mom3, 3, 4)
    ok &= c3[:3] == [0, Fraction(1, 18), Fraction(1, 216)]
    R.check("S2", "the string tension in finite units: 2T = SU(2, F_3) has 24 elements with the trace multiset {2:1, −2:1, 0:6, "
            "1:8, −1:8}, its c₁ = β/4 + … agrees with continuum SU(2) through β⁴ and differs at β⁵; c₁ = N(x)/D(x) in x = e^{β/2} "
            "lies in (0, 1) for every x > 1, so σ = −ln c₁ > 0 (c₁(x = 2) exact); colour SU(3): c₁ = β/18 + β²/216 + … from the "
            "Haar moments of the fundamental character (the Weyl constant term)", ok,
            f"c₁^2T {[str(c) for c in c2T[:6]]}; c₁(2) = {c1_at_2}; SU(3) {[str(c) for c in c3[:3]]}")


# ------------------------------------------------------------------------------------------------------------
# block C: the strong-CP angle (00:G7) — 27:H3's and 27:H4's content on the shared key p27043
@R.block("C", BLOCKS["C"])
def block_C():
    """Block C — the strong-CP angle (EXACT): C1."""
    # 00:G7 (p27043)
    ok = True; n_ = 0
    for p in (17, 53, 173):
        K = I.Fq2(p, 0, -3)
        def herm_m(diag, up):
            return ((K.scalar(diag[0]), up[0], up[1]), (K.conj(up[0]), K.scalar(diag[1]), up[2]),
                    (K.conj(up[1]), K.conj(up[2]), K.scalar(diag[2])))
        Hu = herm_m((3, 7, 11), ((1, 1), (2, 3), (4, 1))); Hd = herm_m((2, 5, 13), ((3, 2), (1, 4), (5, 2)))
        du, dd = I.det(K, Hu), I.det(K, Hd)
        checks = [du[1] == 0 and du != K.zero, dd[1] == 0 and dd != K.zero, K.mul(du, dd)[1] == 0,
                  I.mat_mul(K, Hu, Hd) != I.mat_mul(K, Hd, Hu)]
        ok &= all(checks); n_ += len(checks)
    G, _, _, _ = I.tetrahedral_quaternions()
    for g in G:                                                                    # the Wilson term even under U ↦ U⁻¹ = U†
        M, Mi = I.su2_matrix(g), I.su2_matrix(I.qconj(g))
        trM = tuple(a + b for a, b in zip(M[0][0], M[1][1])); trMi = tuple(a + b for a, b in zip(Mi[0][0], Mi[1][1]))
        ok &= trMi == I.gauss_conj(trM) and trM[1] == 0
    F4 = I.Fq2(2, 1, 1); su3 = I.unitary_frames(F4, 3)
    tr = lambda X: I.trace(F4, X); re2 = lambda U: F4.add(tr(U), F4.conj(tr(U)))
    ok &= len(su3) == 216 and all(tr(I.dagger(F4, U)) == F4.conj(tr(U)) and re2(I.dagger(F4, U)) == re2(U) for U in su3)
    R.check("C1", "the strong-CP angle vanishes: Hermitian textured up and down mass matrices over F_{p²}/F_p (p = 17, 53, 173) "
            "have nonzero determinants in F_p and a product determinant in F_p (arg det M_q = 0) while not commuting (the "
            "CP phase in the misalignment); the Wilson term Tr U + conj Tr U is even under orientation reversal on the 24 "
            "elements of 2T and the 216 of SU(3, 2): no orientation-odd term, θ = 0", ok, f"{n_} determinant checks, 24 + 216 elements")


# ------------------------------------------------------------------------------------------------------------
# block M: the flavour projection (00:G18) — the 16 through C₃ × Q₄, anchored at ν^c
@R.block("M", BLOCKS["M"])
def block_M():
    """Block M — the flavour projection (EXACT): M1."""
    # 00:G18 (p00083)
    g = gen16()
    images = sorted(fifth(S) for S in range(16))                                   # the quarter-turn as the fifth direction: 16 → the even subsets, one-to-one
    singlets = [S for S in g if col(S) % 3 == 0 and wk(S) != 1 and y6(S) == 0]
    neutral = [S for S in g if q6(S) == 0]                                         # the two neutral states: ν in the doublet, ν^c the singlet
    classes = {(col(S) % 3, wk(S)) for S in g}                                     # the C₃ (triality) × doublet/singlet types of the projection
    ok = images == g and len(g) == 16 and singlets == [0] and neutral == [0, 15] and wk(15) == 1 and fifth(0) == 0
    ok &= classes == {(0, 0), (2, 0), (1, 1), (0, 2), (0, 1), (2, 2)} and all(y6(S) == -2 * col(S) + 3 * wk(S) for S in g)
    R.check("M1", "the 16 → spectrum projection: the quarter-turn as the fifth direction maps the sixteen e_S one-to-one onto the "
            "even subsets (the chiral 16); the types (triality k mod 3, weak count) read 3 + 2 with the hypercharge "
            "6Y = −2 col + 3 wk; the unique total singlet (triality 0, weak singlet, Y = 0) is e_∅ = ν^c, the one neutral state "
            "outside the lepton doublet (the other, ν, sits in it) and the fixed point of the fifth direction: the anchor of "
            "the projection, the matter twin of the photon",
            ok, f"images {images}; singlet {singlets}, neutral {neutral}; types {sorted(classes)}")


# ------------------------------------------------------------------------------------------------------------
# block U: the horizon forces structure (00:Z5) — 27:C9's content on the shared key p27021
@R.block("U", BLOCKS["U"])
def block_U():
    """Block U — the horizon forces structure (EXACT): U1."""
    # 00:Z5 (p27021)
    su5, sm, off, so10 = 5 ** 2 - 1, (3 ** 2 - 1) + (2 ** 2 - 1) + 1, 2 * (3 * 2), 10 * 9 // 2
    ok = su5 - sm == off == 12 and so10 == 45 and 1 + 5 + 10 == 16
    tr_ = lambda c, w, i: w if i == c else c if i == w else i
    act = lambda c, w, S: sum(1 << tr_(c, w, i) for i in range(5) if bit(S, i))
    for c in (0, 1, 2):
        for w in (3, 4):                                                           # the six colour–isospin transpositions
            ok &= sorted(act(c, w, S) for S in range(32)) == list(range(32))
            for S in range(32):
                for T in range(32):
                    a, b = emul(S, T), emul(act(c, w, S), act(c, w, T))
                    ok &= b[0] * b[0] == a[0] * a[0] and (a[0] == 0 or b[1] == act(c, w, a[1]))   # an automorphism up to the sign of e_{S∪T}
    adm = [q for q in range(7, 3000) if q % 12 == 5 and arith.is_prime(q)]
    horizon = all(3 * s < Om + 1 for Om in adm for s in range(isqrt(Om) + 1))        # the torsion period exceeds every horizon count
    images = sorted(fifth(S) for S in range(16)) == gen16()
    R.check("U1", "the horizon forces the simple unification: the colour–isospin off-block is 24 − 12 = 12 = 2·(3·2), the spinor "
            "1 + 5 + 10 = 16, dim SO(10) = 45; each of the six colour–isospin transpositions is an automorphism of the "
            "reflection algebra of five directions up to the sign of the basis element (all 32 × 32 products) and a "
            "bijection of the subsets, so the off-block reframings are gauge; on every shell Ω ≡ 5 (mod 12) below 3000, "
            "every count s within the coherence horizon (s² ≤ Ω) has 3 s < Ω + 1: the torsion that distinguishes the blocks "
            "lies beyond the horizon; the fifth direction's bijection onto the 16", ok and horizon and images,
            f"{len(adm)} shells, off-block {off}")


# ------------------------------------------------------------------------------------------------------------
# block X: the exclusions (00:P4) — 27:P1–P4, P6, P7, 32:P6 and 35:P4 read together
@R.block("X", BLOCKS["X"])
def block_X():
    """Block X — the exclusions (CHART): X1."""
    # 00:P4 (p00091)
    ok = True; det = []
    for p in (13, 53, 157):                                                        # the closed ladder: the fifth step returns to counting
        g, n = arith.primitive_root(p), p - 1
        ok &= all(LD.tower(g, j, p)[0] == LD.tower(g, j, p)[1] for j in range(n)) and any(pow(g, j, p) >= n for j in range(n))
    g16 = gen16()
    content = Counter((col(S) % 3, wk(S), y6(S)) for S in g16)                      # exactly one generation, nothing beyond
    ok &= len(g16) == 16 and sum(content.values()) == 16 and sum(y6(S) for S in g16) == 0 and sum(y6(S) ** 3 for S in g16) == 0
    ok &= content == Counter({(0, 0, 0): 1, (2, 0, -4): 3, (1, 1, 1): 6, (0, 2, 6): 1, (0, 1, -3): 2, (2, 2, 2): 3})
    ok &= 24 - (8 + 3 + 1) == 12 == 2 * (3 * 2)                                     # the twelve X, Y leptoquarks
    d = CF.DATA["p8"]                                                               # the proton lifetime at the substrate scale
    tau = {M: M ** 4 / (d["alpha_GUT"] ** 2 * d["m_p"] ** 5) * d["hbar_GeV_s"] / d["year_s"] for M in d["M_X"]}
    Ms = sorted(tau)
    ok &= tau[Ms[-1]] >= 10 ** 45 and tau[Ms[0]] > 10 ** 34 and all(tau[b] / tau[a] == (b / a) ** 4 for a, b in zip(Ms, Ms[1:]))
    d1 = CF.DATA["p1"]; b1, b2, b3 = d1["b"]                                        # the running: no TeV supersymmetry, the near-miss
    a1, a2, a3 = Fraction(3, 5) * (1 - d1["sin2"]) * d1["ainv_em"], d1["sin2"] * d1["ainv_em"], 1 / d1["alpha_s"]
    u = (a1 - a2) / (b1 - b2); aG, a3X = a2 - b2 * u, a3 - b3 * u
    miss = abs(a3X - aG) / aG; MX = Fraction(CF.unification_scale())
    ok &= miss < Fraction(1, 5) and 10 ** 12 < MX < 10 ** 14
    mono = CD.monotone_grid()                                                       # no new dark-matter particle: the one-variable law (32:P6)
    F, G = HD.colour_group(); wrap = HD.colourless_content(F, G)                    # the proton the minimal colour-neutral wrap (35:P4)
    ok &= mono and wrap == (1, 0, 0, 1) and len(G) == 216
    R.check("X1", "[chart] the exclusions: the role ladder closes on F_13, F_53, F_157 (the tower's exponent read modulo p − 1 for "
            "every index: no fourth generation, no fifth force); the matter content is exactly the sixteen states of one "
            "generation with Σ Y = Σ Y³ = 0 (the desert, no superpartner, no new dark-matter particle, no beyond-SM (g − 2)_μ); "
            "the twelve off-block leptoquarks; τ_p ∝ M_X⁴ exceeds 10⁴⁵ yr at the Planck scale and 10³⁴ yr at 10¹⁶ GeV; the "
            "one-loop running meets α₁ = α₂ in [10¹², 10¹⁴] GeV with the strong near-miss below 20 %; the dark law is a "
            "strictly increasing function of the one baryonic variable; the colourless content (1, 0, 0, 1) of Λ•(3) makes "
            "the proton the minimal colour-neutral wrap", ok,
            f"τ_p: " + ", ".join(f"{CH.show(M, '.1e')} GeV → {CH.show(tau[M], '.1e')} yr" for M in Ms) + f"; M_X = {CH.show(MX, '.2e')} GeV, near-miss {CH.show(100 * miss, '.0f')} %",
            kind="CHART")


if __name__ == "__main__":
    blocks = [a for a in sys.argv[1:] if a in R.blocks]
    if blocks:
        for b in blocks: R.run_block(b)
        sys.exit(0 if R.summary(write=False) else 1)
    sys.exit(0 if R.verify_all() else 1)
