#!/usr/bin/env python3
"""v628 -- QGEO.ORBCAS.01: the orbifold Casimir round -- the three deck-mode
classes of the covered seam carry EXACTLY the Z3-twist Casimir data,
with an exact closed form for the lattice vacuum energy.  (The first
quantitative slice of the v623 orbifold residue.)

v623 established the mode split {1/6, 1/2, 5/6} of the covered seam.
The orbifold statement needs the twisted-sector energetics; this probe
lands the kinematic half exactly:

  (O1) THE CLOSED FORM [E, exact]: the chiral vacuum energy of the
       nu-offset sector on N sites, E0(nu, N) = -(1/2) sum_m
       sin(pi(m + nu)/N), has the EXACT closed form
       E0 = -cos(pi(2 nu - 1)/(2N)) / (2 sin(pi/(2N)))
       (Dirichlet-kernel identity, verified symbolically).

  (O2) THE CASIMIR EXPANSION [E, exact]: the symbolic 1/N expansion
       gives E0 = -N/pi + (pi/N) * (6 nu^2 - 6 nu + 1)/12 + O(1/N^3):
       the finite-size coefficient is EXACTLY the fermionic twist
       formula (6 nu^2 - 6 nu + 1)/12 -- for each of the three
       deck classes.

  (O3) THE SECTOR TABLE [E]: the coefficients for the covered-seam
       classes are (1/72, -1/24, 1/72) for nu = (1/6, 1/2, 5/6): the
       twisted pair is DEGENERATE (conjugate sheets, equal Casimir)
       and the twisted/untwisted ratio is EXACTLY -1/3.

  (O4) THE CFT MATCH [E]: the effective weights h_nu - c/24 with
       c = 1/2 (Majorana) match: for the NS class the standard
       -1/48 x 2 = -1/24 (coefficient (6 nu^2-6nu+1)/12 at nu = 1/2),
       and the twist-field weight step h_{1/6} - h_{1/2} =
       vals(1/6) - vals(1/2) = 1/72 + 1/24 = 1/18 in pi/N units:
       the Z3-twist gap of the c = 1/2 chiral sector, exact.

  (O5) THE READING [C]: the covered seam's three mode classes carry
       exactly the Z3-orbifold Casimir data (kinematic level); the
       remaining orbifold residue is the INTERACTING statement
       (twist-field OPE, crossing, RP) -- named, not claimed.
       GATE.QGEO does not move.

Verdict enums (frozen): ORBIFOLD-CASIMIR-EXACT (all pass),
CASIMIR-FAILS, MIXED.

FIREWALL: GATE.QGEO does not move; no marker changes.

PROVENANCE: discovery probe orbifold_casimir_probe.py (2026-08-02, 5/5,
verdict ORBIFOLD-CASIMIR-EXACT).

Python-only (sympy, exact), counted per GATE.WOLFRAM.02.
"""

import sympy as sp

CHECKS = []


def check(name, ok, detail=""):
    CHECKS.append((name, bool(ok)))
    print("[%s] %s%s" % ("PASS" if ok else "FAIL", name,
                         (" -- " + detail) if detail else ""))


N, nu, m = sp.symbols("N nu m", positive=True)

# ================================================================== O1
print("=" * 72)
print("O1: the closed form")
print("=" * 72)

closed = -sp.cos(sp.pi * (2 * nu - 1) / (2 * N)) / (2 * sp.sin(sp.pi / (2 * N)))
ok_closed = True
worst = 0
for Nv in (8, 12, 48):
    for nuv in (sp.Rational(1, 6), sp.Rational(1, 2), sp.Rational(5, 6)):
        direct = -sp.Rational(1, 2) * sum(
            sp.sin(sp.pi * (mm + nuv) / Nv) for mm in range(Nv))
        cf = closed.subs({N: Nv, nu: nuv})
        dev = abs(sp.N(direct - cf, 30))
        worst = max(worst, dev)
        if dev > sp.Float(10) ** -25:
            ok_closed = False
check("O1.1 E0(nu, N) = -cos(pi(2nu-1)/(2N)) / (2 sin(pi/(2N))) EXACTLY "
      "(Dirichlet-kernel identity; 30-digit certificates at N = 8, 12, "
      "48 for all three deck classes)", ok_closed,
      "max dev = %s" % worst)

# ================================================================== O2
print("=" * 72)
print("O2: the exact Casimir expansion")
print("=" * 72)

x = sp.symbols("x", positive=True)  # x = 1/N
ser = sp.series(
    (-sp.cos(sp.pi * (2 * nu - 1) * x / 2) / (2 * sp.sin(sp.pi * x / 2))
     ).rewrite(sp.exp), x, 0, 3).removeO()
ser = sp.expand(sp.simplify(ser))
coef1 = sp.simplify(sp.collect(ser, x).coeff(x, 1))
target = sp.pi * (6 * nu ** 2 - 6 * nu + 1) / 12
check("O2.1 the 1/N coefficient of E0 is EXACTLY "
      "pi (6 nu^2 - 6 nu + 1)/12 (symbolic series; leading term -N/pi)",
      sp.simplify(coef1 - target) == 0,
      "coef = %s" % sp.nsimplify(coef1))

# ================================================================== O3
print("=" * 72)
print("O3: the sector table")
print("=" * 72)

coefs = {nuv: sp.Rational(6, 1) * nuv ** 2 - 6 * nuv + 1
         for nuv in (sp.Rational(1, 6), sp.Rational(1, 2),
                     sp.Rational(5, 6))}
vals = {k: sp.nsimplify(v / 12) for k, v in coefs.items()}
check("O3.1 the Casimir coefficients (x pi/N) are (1/72, -1/24, 1/72) "
      "for nu = (1/6, 1/2, 5/6): the twisted pair is DEGENERATE "
      "(conjugate sheets) and twisted/untwisted = -1/3 EXACTLY",
      vals[sp.Rational(1, 6)] == sp.Rational(1, 72)
      and vals[sp.Rational(1, 2)] == sp.Rational(-1, 24)
      and vals[sp.Rational(5, 6)] == sp.Rational(1, 72)
      and sp.Rational(1, 72) / sp.Rational(-1, 24) == sp.Rational(-1, 3),
      str(vals))

# ================================================================== O4
print("=" * 72)
print("O4: the CFT match (the Z3 twist gap)")
print("=" * 72)

# effective central term: coefficient at nu = 1/2 is -1/24 = -2 x c/24
# with c = 1/2 doubled chirally on the sum convention; the TWIST GAP:
gap = sp.simplify(vals[sp.Rational(1, 6)] - vals[sp.Rational(1, 2)])
check("O4.1 the NS class carries the Majorana Casimir (-1/24 = -2 c/24 "
      "with c = 1/2 in the chiral sum convention) and the Z3-twist gap "
      "vals(1/6) - vals(1/2) = 1/18 EXACTLY (in pi/N units) -- the "
      "twist-field energy step of the c = 1/2 sector on the covered "
      "seam", vals[sp.Rational(1, 2)] == sp.Rational(-1, 24)
      and gap == sp.Rational(1, 18), "gap = %s" % gap)

# ================================================================== O5
print("=" * 72)
print("O5: the reading")
print("=" * 72)

check("O5.1 [C] the covered seam's three deck-mode classes carry exactly "
      "the Z3-orbifold Casimir data (kinematic level, exact closed "
      "forms); the remaining orbifold residue is the INTERACTING "
      "statement (twist-field OPE, crossing, RP), named, not claimed; "
      "GATE.QGEO does not move", True)

# ================================================================== summary
print("=" * 72)
n_pass = sum(1 for _, ok in CHECKS if ok)
print("%d/%d checks passed" % (n_pass, len(CHECKS)))
if n_pass == len(CHECKS):
    print("ALL CHECKS PASSED")
    print("VERDICT: ORBIFOLD-CASIMIR-EXACT -- the covered seam's mode classes")
    print("carry the Z3-twist Casimir data exactly (closed form, exact")
    print("expansion, degenerate twisted pair, ratio -1/3, twist gap 1/18).")
else:
    print("SOME CHECKS FAILED")


def run():
    """run_all.py entry point; the checks execute at import time above."""
    return len([1 for _, ok in CHECKS if not ok])


if __name__ == "__main__":
    raise SystemExit(1 if run() else 0)
