Jump to content

The Principia Machina/TPC-PY/diff sponsor.py

From The Invariance Itself
Revision as of 15:43, 27 September 2026 by BFP Rauch (talk | contribs) (TPC-PY source diff_sponsor.py (0.1.0), SHA-256 11c9f3822eafe3a8; conformed TPS 0.3.0; PROPOSED, not declared (CO-8))
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
"""diff_sponsor 0.1.0: the cross-residence differential for tpc_sponsor
0.1.0. Random conduct events with facts at and around every window
boundary, random evidence lists (conduct and agent events, ages, weights,
priors, half-lives) and random admission and retirement tables, both
residences on the same inputs, 0 differences the pass.
Usage: python3 diff_sponsor.py [seed] [cases]."""
import json, os, random, subprocess, sys, tempfile
here = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, here)
from tpc_sponsor import run_case
seed = int(sys.argv[1]) if len(sys.argv) > 1 else 1
count = int(sys.argv[2]) if len(sys.argv) > 2 else 20000
random.seed(seed)
KINDS = ["CE-F1", "CE-F2", "CE-A1", "CE-A2", "CE-A3", "CE-A4", "CE-A5"]
STATES = ["GREEN", "YELLOW", "ORANGE", "SUSPENDED", "RED"]
def blk(): return random.choice([None, None, 1, 5, 99, 100, 101, 150, 0, -1, True])
def facts(kind):
    r = random.random()
    if r < 0.05: return {"audit": "OPEN"} if kind != "CE-A1" else {"named": True}
    if kind == "CE-F1":
        pred = random.choice([None, None, {"state": random.choice(STATES), "pending": random.choice([0, 0, 1, 3, -1])}])
        return {"named": random.choice([True, True, False]), "predecessor": pred, "blocks": random.choice([0, 50, 99, 100, 101, 400, -1]), "first_violation_block": blk(), "period_taken": random.choice([False, False, True])}
    if kind == "CE-F2":
        return {"declared": random.choice([True, True, False]), "blocks": random.choice([0, 50, 99, 100, 101, 400]), "first_violation_block": blk(), "first_canary_failure_block": blk()}
    if kind in ("CE-A1", "CE-A2", "CE-A3"):
        return {"audit": random.choice(["OPEN", "CONFIRMED", "DISMISSED", "MAYBE"])}
    if kind == "CE-A4":
        w = random.choice([0, 86400, 2592000])
        e = random.randint(0, 10 ** 8)
        return {"admission": random.choice([e, e + w, e + w + 1, e - w, e - w - 1 if e > w else 0, e + random.randint(0, 2 * w + 1)]), "exit": e, "state": random.choice(STATES), "pending": random.choice([0, 0, 1, 2]), "window": w}
    return {"removed": random.choice([True, True, False]), "cause": random.choice(["CANARY", "TRIP", "OTHER", None, "X"])}
cases = []
for t in range(count):
    fn = random.choice(["resolve", "evidence", "whitewash"])
    if fn == "resolve":
        kind = random.choice(KINDS + ["CE-X"])
        cases.append({"fn": "resolve", "args": {"event": {"kind": kind}, "facts": facts(kind if kind != "CE-X" else "CE-A1")}})
    elif fn == "evidence":
        evs = []; ages = []
        for _ in range(random.randint(0, 12)):
            kind = random.choice(KINDS + ["AGENT", "AGENT"])
            if kind == "AGENT":
                e = {"kind": "AGENT", "resolution": random.choice(["FOR", "AGAINST", "FOR"] if random.random() < 0.98 else ["PENDING"]), "weight": round(random.uniform(0, 3), 4)}
                if random.random() < 0.01: del e["weight"]
            else:
                ok = ["FOR", "NEUTRAL"] if kind.startswith("CE-F") else ["AGAINST", "NEUTRAL"]
                e = {"kind": kind, "resolution": random.choice(ok if random.random() < 0.97 else ["PENDING", "FOR", "AGAINST"])}
                if random.random() < 0.01: e["weight"] = 1
            evs.append(e); ages.append(random.choice([0, 0, 1, 50, 250, 500, 1000, 5000, random.randint(0, 3000)]))
        if random.random() < 0.03 and ages: ages = ages[:-1]
        g = {"CE-F1": random.choice([1, 2, 0.5]), "CE-F2": random.choice([1, 0.25])}
        h = {"CE-A1": 2, "CE-A2": 3, "CE-A3": 3, "CE-A4": random.choice([2, 1.5]), "CE-A5": 3}
        if random.random() < 0.03: del h["CE-A3"]
        cases.append({"fn": "evidence", "args": {"events": evs, "ages": ages, "g": g, "h": h, "a0": random.choice([1, 1, 1, 2, 0.5, 0]), "b0": random.choice([1, 1, 2, 0.5]), "half_life": random.choice([500, 500, 500, 100, 1000, 0])}})
    else:
        agents = ["A", "B", "C", "D", "α", "N|1"]
        st = {a: {"state": random.choice(STATES[:4]), "pending": random.choice([0, 0, 1])} for a in agents}
        if random.random() < 0.05: del st["A"]
        w = random.choice([0, 86400, 2592000])
        adm = [{"agent": random.choice(agents + ["N2", "N3"]), "time": random.randint(0, 10 ** 7)} for _ in range(random.randint(0, 4))]
        ret = [{"agent": random.choice(agents), "time": random.randint(0, 10 ** 7)} for _ in range(random.randint(0, 4))]
        if random.random() < 0.3 and adm and ret: adm[0]["time"] = ret[0]["time"] + random.choice([w, w + 1, -w, 0])
        cases.append({"fn": "whitewash", "args": {"admissions": adm, "retirements": ret, "states": st, "window": w}})
CASES_PATH = os.environ.get("TPC_DIFF_CASES")  # named: kept, for crosspy.py
if not CASES_PATH:
    fd, CASES_PATH = tempfile.mkstemp(prefix="tpc_diff_", suffix=".json")  # outside the tree
    os.close(fd)
with open(CASES_PATH, "w", encoding="utf-8") as f:
    json.dump(cases, f, ensure_ascii=False)
py = [run_case(c["fn"], c["args"]) for c in cases]
php = json.loads(subprocess.run(["php", os.path.join(here, "diff_sponsor.php"), CASES_PATH], capture_output=True, text=True, check=True).stdout)
if not os.environ.get("TPC_DIFF_CASES"):
    os.remove(CASES_PATH)
diffs = sum(1 for a, b in zip(py, php) if a != b)
by = {}
for c, x in zip(cases, py):
    k = c["fn"] + ("/ERROR" if x.startswith("ERROR") else "")
    by[k] = by.get(k, 0) + 1
print("seed", seed, "cases", len(cases), "differences", diffs, json.dumps(by, sort_keys=True))
for c, a, b in zip(cases, py, php):
    if a != b:
        print(json.dumps(c, ensure_ascii=False)[:500]); print(a); print("---"); print(b); break