#!/usr/bin/env python3
"""Reconcile an agent's self ledger against an independently sourced event set.

Input JSON objects:
  ledger: {"events": [{"id": "...", ...}]}
  witness: {"events": [{"id": "...", ...}]}

Exit 0 only when IDs match exactly; exit 1 on missing/extra/duplicate IDs.
The witness is intentionally supplied separately: this tool cannot prove that
its witness is independent, complete, or that quiet no-op runs occurred.
"""
import argparse, json, sys

def ids(doc, label):
    events = doc.get("events")
    if not isinstance(events, list):
        raise ValueError(f"{label}.events must be a list")
    out = []
    for i, event in enumerate(events):
        if not isinstance(event, dict) or not isinstance(event.get("id"), str) or not event["id"]:
            raise ValueError(f"{label}.events[{i}].id must be a non-empty string")
        out.append(event["id"])
    return out

def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("ledger")
    ap.add_argument("witness")
    args = ap.parse_args()
    try:
        with open(args.ledger, encoding="utf-8") as f: ledger = json.load(f)
        with open(args.witness, encoding="utf-8") as f: witness = json.load(f)
        li, wi = ids(ledger, "ledger"), ids(witness, "witness")
    except (OSError, json.JSONDecodeError, ValueError) as e:
        print(json.dumps({"ok": False, "error": str(e)}, sort_keys=True)); return 2
    lset, wset = set(li), set(wi)
    report = {"ok": li == list(dict.fromkeys(li)) and wi == list(dict.fromkeys(wi)) and lset == wset,
              "ledger_count": len(li), "witness_count": len(wi),
              "missing_from_ledger": sorted(wset-lset), "extra_in_ledger": sorted(lset-wset),
              "duplicate_ledger_ids": sorted({x for x in li if li.count(x)>1}),
              "duplicate_witness_ids": sorted({x for x in wi if wi.count(x)>1})}
    print(json.dumps(report, sort_keys=True))
    return 0 if report["ok"] else 1

if __name__ == "__main__": sys.exit(main())
