"""Exact singlet tests for the preceding seed-loop candidate color algebra.

No mass, temperature, coupling or confinement potential is fitted or inserted.
Complex tensor representations are the explicit amplitude bridge being tested.
Invariant tensors are necessary color-closure structure, not a binding dynamics.
"""
import json
from pathlib import Path
from seed_lie_closure import mat,identity,edge,traceless,times_i,kron,add,scale,Span


def transpose(a):
    n,r,s=a
    return mat(n,[r[j*n+i] for i in range(n) for j in range(n)],
               [s[j*n+i] for i in range(n) for j in range(n)])


def generator_on_tensor(g,representations):
    total=None
    for acted in range(len(representations)):
        term=identity(1)
        for slot,representation in enumerate(representations):
            operator=g if representation=='q' else scale(transpose(g),-1)
            term=kron(term,operator if slot==acted else identity(3))
        total=term if total is None else add(total,term)
    return total


def annihilates(a,v):
    n,r,s=a
    return all(sum(r[i*n+j]*v[j] for j in range(n))==0 and
               sum(s[i*n+j]*v[j] for j in range(n))==0 for i in range(n))


def main():
    generators=[times_i(traceless(edge(3,i,j,-1))) for i,j in ((0,1),(1,2),(2,0))]
    rows=[]
    for reps in [('q',),('q','q'),('q','qbar'),('q','q','q')]:
        operators=[generator_on_tensor(g,reps) for g in generators]
        d=3**len(reps)
        span=Span()
        for n,r,s in operators:
            assert n==d and not any(r)
            for i in range(d): span.add(s[i*d:(i+1)*d])
        nullity=d-len(span.rows)
        expected=1 if reps in [('q','qbar'),('q','q','q')] else 0
        assert nullity==expected
        if reps==('q','qbar'):
            invariant=[int(i==j) for i in range(3) for j in range(3)]
            assert all(annihilates(g,invariant) for g in operators)
        if reps==('q','q','q'):
            invariant=[]
            for i in range(3):
                for j in range(3):
                    for k in range(3):
                        if len({i,j,k})<3: invariant.append(0)
                        else:
                            inversions=int(i>j)+int(i>k)+int(j>k)
                            invariant.append((-1)**inversions)
            assert all(annihilates(g,invariant) for g in operators)
        rows.append({'factors':reps,'representation_dimension':d,
                     'exact_constraint_rank':len(span.rows),'color_singlet_dimension':nullity})
    result={'date':'2026-10-23','construction':'Tensor actions of the candidate inversion-loop su(3) generators',
            'results':rows,
            'explicit_invariants':{'q_qbar':'delta_ij','q_q_q':'epsilon_ijk'},
            'interpretation':'Supports distinct splitting into colored excitations and later color-neutral pair/triple closure.',
            'scope':'Representation theory only: no confinement dynamics, hadron spectrum, early-universe transition temperature or derivation of physical amplitudes.'}
    out=Path(__file__).with_name('seed-color-singlets.json')
    out.write_text(json.dumps(result,indent=2)+'\n',encoding='utf8')
    print(json.dumps(result,indent=2))


if __name__=='__main__': main()
