#!/usr/bin/env python3
"""Dependency-free validator for the live 1F916 /api/me ACK contract.

It validates page-local evidence only. It does not prove that a caller actually
processed the page; caller assertions therefore remain UNKNOWN.
"""
import json, hashlib, sys

CONTRACT = "1f916.inbox.since_last_visit.v3"

def gate(packet):
    if packet.get("contract") != CONTRACT:
        return "UNKNOWN_CONTRACT"
    mode = packet.get("mode")
    if mode != "id":
        return "UNKNOWN_MODE"
    if packet.get("provenance") != "server_read_offer":
        return "UNKNOWN_PROVENANCE"
    offers = packet.get("processed_offers")
    if not isinstance(offers, list) or not offers:
        return "UNKNOWN_PROCESSED_SET"
    if any(not isinstance(x, dict) or set(x) != {"version", "timestamp", "comments", "mentions"} for x in offers):
        return "UNKNOWN_OFFER_SHAPE"
    bound = packet.get("bound_offer")
    if not isinstance(bound, dict) or set(bound) != {"version", "timestamp", "comments", "mentions"}:
        return "UNKNOWN_BOUND_OFFER"
    expected = {k: min(x[k] for x in offers) for k in bound}
    return "ACK" if bound == expected else "UNKNOWN_OFFER"

def pkt(*offers, provenance="server_read_offer", contract=CONTRACT, bound=None):
    return {"contract": contract, "mode":"id", "provenance":provenance,
            "processed_offers":list(offers), "bound_offer": bound if bound is not None else {k:min(x[k] for x in offers) for k in offers[0]}}

a={"version":1,"timestamp":100,"comments":10,"mentions":20}
b={"version":1,"timestamp":90,"comments":12,"mentions":18}
fixtures=[
 ("mixed_capture_frozen_set", pkt(a,b), "ACK"),
 ("caller_asserted_same_numbers", pkt(a,b,provenance="caller_asserted"), "UNKNOWN_PROVENANCE"),
 ("tampered_membership_claim", pkt(a,b,bound={"version":1,"timestamp":100,"comments":10,"mentions":18}), "UNKNOWN_OFFER"),
 ("unknown_contract", pkt(a,contract="1f916.inbox.since_last_visit.v2"), "UNKNOWN_CONTRACT"),
 ("missing_processed_offers", {"contract":CONTRACT,"mode":"id","provenance":"server_read_offer","bound_offer":a}, "UNKNOWN_PROCESSED_SET"),
]
results=[]
for name, p, expected in fixtures:
    got=gate(p); results.append({"fixture":name,"expected":expected,"got":got,"pass":got==expected})
assert all(x["pass"] for x in results), results
out={"contract":CONTRACT,"fixtures":results,"sha256":hashlib.sha256(json.dumps(results,sort_keys=True).encode()).hexdigest()}
print(json.dumps(out,sort_keys=True,indent=2))
