import json

SUPPORTED = "checkpoint.v1"

def gate(observation):
    if observation.get("schema") != SUPPORTED:
        return {"status":"REFUSE", "reason":"UNKNOWN_SCHEMA"}
    try:
        tree = int(observation["tree_size"])
        sealed = int(observation["sealed_entries_total"])
    except (KeyError, TypeError, ValueError):
        return {"status":"REFUSE", "reason":"MALFORMED_CAPTURE"}
    if tree > sealed:
        return {"status":"INCONSISTENT", "reason":"TREE_AHEAD_OF_SEALED", "tree_size":tree, "sealed_entries_total":sealed}
    if observation.get("witnessed_against") != observation.get("capture_id"):
        return {"status":"UNWITNESSED_JOIN", "reason":"CROSS_CAPTURE_WITHOUT_LINKED_WITNESS"}
    return {"status":"SETTLED", "reason":"SAME_CAPTURE_AND_COUNTER_NONDECREASING", "tree_size":tree, "sealed_entries_total":sealed}

fixtures = [
 {"name":"valid_same_capture", "input":{"schema":SUPPORTED,"capture_id":"c1","witnessed_against":"c1","tree_size":8,"sealed_entries_total":8}, "expect":"SETTLED"},
 {"name":"tree_ahead_negative_control", "input":{"schema":SUPPORTED,"capture_id":"c2","witnessed_against":"c2","tree_size":9,"sealed_entries_total":8}, "expect":"INCONSISTENT"},
 {"name":"cross_capture_without_link", "input":{"schema":SUPPORTED,"capture_id":"c3","witnessed_against":"c2","tree_size":8,"sealed_entries_total":9}, "expect":"UNWITNESSED_JOIN"},
 {"name":"unknown_schema", "input":{"schema":"checkpoint.v0","capture_id":"c4","witnessed_against":"c4","tree_size":8,"sealed_entries_total":8}, "expect":"REFUSE"},
 {"name":"malformed", "input":{"schema":SUPPORTED,"capture_id":"c5","witnessed_against":"c5","tree_size":"x","sealed_entries_total":8}, "expect":"REFUSE"},
]

results=[]
for f in fixtures:
    got=gate(f["input"])
    results.append({"name":f["name"],"got":got["status"],"expect":f["expect"],"pass":got["status"]==f["expect"]})
print(json.dumps({"supported_schema":SUPPORTED,"cases":results,"passed":sum(r["pass"] for r in results),"total":len(results)}, sort_keys=True))
assert all(r["pass"] for r in results)
