#!/usr/bin/env python3
"""Dependency-free continuity resume gate.

Usage: python3 continuity_gate.py packet.json
Exit 0 only when an expected->launch->terminal chain is complete and bound.
"""
import hashlib, json, sys

OUTCOMES = {"DONE", "BLOCKED", "FAILED", "PARKED"}

def digest(obj):
    raw = json.dumps(obj, sort_keys=True, separators=(",", ":"), ensure_ascii=False).encode()
    return hashlib.sha256(raw).hexdigest()

def refuse(reason):
    print(json.dumps({"status": "REFUSE", "reason": reason}, sort_keys=True))
    return 1

def check(p):
    if not isinstance(p, dict): return refuse("packet_not_object")
    for k in ("expected", "launch", "terminal"):
        if not isinstance(p.get(k), dict): return refuse(f"missing_{k}")
    e, l, t = p["expected"], p["launch"], p["terminal"]
    ids = [e.get("case_id"), l.get("case_id"), t.get("case_id")]
    if not ids[0] or ids.count(ids[0]) != 3: return refuse("case_identity_mismatch")
    if e.get("kind") != "RESUME_EXPECTED": return refuse("bad_expected_kind")
    if l.get("kind") != "RESUME_LAUNCHED": return refuse("bad_launch_kind")
    if t.get("kind") != "RESUME_TERMINAL": return refuse("bad_terminal_kind")
    if l.get("expected_hash") != digest(e): return refuse("expected_hash_mismatch")
    if t.get("launch_hash") != digest(l): return refuse("launch_hash_mismatch")
    if t.get("outcome") not in OUTCOMES: return refuse("invalid_outcome")
    if not e.get("next_step"): return refuse("missing_next_step")
    if not e.get("owner"): return refuse("missing_owner")
    print(json.dumps({"status":"PASS", "case_id":ids[0], "owner":e["owner"], "next_step":e["next_step"], "outcome":t["outcome"]}, sort_keys=True))
    return 0

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("usage: continuity_gate.py packet.json", file=sys.stderr); raise SystemExit(2)
    with open(sys.argv[1], encoding="utf-8") as f: packet = json.load(f)
    raise SystemExit(check(packet))
