"""RUN-015 - Round 12: the checkpoint crystal and the multi-AI audit protocol.

Round 12 stores the distributed proof state itself: a checkpoint holds the root, the
target, a bundle of proof-critical dependency hashes and its fingerprint, the frontier,
an append-only claim ledger and audit ledger, and an aggregate. A claim counts only
while its fingerprint is current (stale safety, Thm 5.1); performance-only changes do
not touch the fingerprint; a rejected claim frees its seeds; a correction supersedes.
Five reference checkpoints walk through these transitions on Round 11's shards. Here
the digests are re-derived, the five verdicts rebuilt by this tree's own validator,
the links to Round 11 checked, and the transitions read against the round's own rules.

Checks
  A0 anchors      the table and formulas below occur in Round 12 as written
  W1 digests      each checkpoint's payload digest and dependency fingerprint re-derived;
                  V2 keeps V1's fingerprint and V3 changes it; the copies of Round 11's files
  W2 validator    sec. 14-15, 18-21, 28: accepted, pending, stale and rejected claims and
                  theorem_ready for V1-V5, by this tree's own rules
  W3 links        sec. 22-23: the claims are Round 11's shards; the audits are its merge rows
  W4 semantics    sec. 12, 14, 19, 32: each file's stored aggregate against its own ledger;
                  certificate bytes that were rejected coming back under a new claim
  W5 stale        Thm 5.1 on random bundles: the fingerprint moves with every proof-critical
                  field and with no performance-only one
  P1 package      the checkpoints against the JSON schema; the audit protocol against the text
  P2 package      the package's self-description of its files matches the archive
  R1 registry     Round 12's judgments reviewed, first-used statuses defined

Usage: python code/run015_round12_checkpoint_crystal.py [--drill] [--blind CID]
"""
import argparse
import copy
import hashlib
import json
import re

import jsonschema
import numpy as np

import gate
import registry
from corpus import SOURCES, TREE, source_bytes, walk_sources
from run014_round11_global_shards import complete

PKG = "main.zip!/AMRAL_LUC_FC_Round_12_Package_v0.1.zip!/"
REF = PKG + "AMRAL_LUC_FC_Round_12_reference_checkpoint/"
DOC = PKG + "AMRAL_Lebesgue_Finite_Closure_Round_12_Checkpoint_Crystal_v0.1.md"
PROTOCOL = PKG + "AMRAL_LUC_FC_Round_12_MULTI_AI_AUDIT_PROTOCOL_v0.1.md"
CRYSTAL = PKG + "AMRAL_LUC_FC_State_Crystal_Round_12_v0.1.md"
VALIDATION = PKG + "AMRAL_LUC_FC_Round_12_VALIDATION.json"
SCHEMA = PKG + "AMRAL_LUC_FC_Round_12_CHECKPOINT_SCHEMA.json"
VALIDATOR = REF + "checkpoint_validator.py"
DEMO = REF + "state_transition_demo.py"
SUMMARY = REF + "state_transition_summary.json"
STATES = {"v1_baseline": "checkpoint_v1.json", "v2_performance_only": "checkpoint_v2_performance_only.json",
          "v3_proof_critical_change": "checkpoint_v3_proof_critical_change.json",
          "v4_rejected_B": "checkpoint_v4_rejected_B.json", "v5_corrected_B": "checkpoint_v5_corrected_B.json"}
R11 = "main.zip!/AMRAL_LUC_FC_Round_11_Package_v0.1.zip!/AMRAL_LUC_FC_Round_11_reference_shards/"
COPIES = ["global_manifest.json", "merge_verification_summary.json", "shards/shard-A.json", "shards/shard-B.json",
          "shards/shard-C.json"]
LOG = TREE / "data" / "gate-logs" / "run015-round12-checkpoint-crystal.json"
MANIFEST = TREE / "data" / "SOURCE_MANIFEST.v1.json"

ANCHORS = {
    "W1": [r"H_{\rmdep}=H(D_{\rmproof}).", r"D_{\rmperf}\text{不進}H_{\rmdep}.", r"e_{\rmfp}=10^{-8}"],
    "W2": [r"|V1|baseline|`true`|", r"|V2|scheduleronly|`true`|", r"|V3|arithmeticproofdependency|`false`|",
           r"|V4|shard-Brejected|`false`|", r"|V5|appendcorrectedBclaim|`true`|", r"H_{\rmdep}^{c}=H_{\rmdep}^{\rmcurrent}"],
    "W3": [r"\{00,01,10,11\}", r"scope=ROUND10-LOCAL-REFERENCE-SHARDS"],
    "W4": [r"100個PASS也不會消除一個有效反例。", r"supersedes=claim-shard-B-v1"],
}
SEC7_STATES = ["EMITTED", "VERIFIED-INDEPENDENT-REPLAY", "REJECTED", "STALE", "SUPERSEDED", "CORRECTED"]
PROTOCOL_STATES = ["REJECTED-PENDING-REVIEW", "STALE-AGGREGATE"]
SEC36 = {                               # the text's publication gate, and the protocol's wording of each item
    "complete global frontier": "current frontier complete + prefix-free",
    "exactly one active claim per terminal seed": "every terminal seed exactly one active claim",
    "active claim dependencies current": "all proof-critical dependency fingerprints current",
    "A1 PASS for every active claim": "every active claim A1 PASS",
    "no active reject or stale": "no stale / rejected active claim",
    "global merge PASS": "full merge verifier PASS", "forest identities": "global forest identity",
    "publication-grade arithmetic": "arithmetic policy有 publication-grade theorem",
    "source and certificate hashes": None,
    "correction ancestry complete": "all correction ledgers append-only and linked"}


# ---------------------------------------------------------------- this tree's validator

def canonical(obj):
    return json.dumps(obj, sort_keys=True, separators=(",", ":"), ensure_ascii=False).encode("utf-8")


def sha(obj):
    return hashlib.sha256(canonical(obj)).hexdigest()


def validate(payload):
    """sec. 14-15: a claim is accepted when it is VERIFIED-INDEPENDENT-REPLAY, its fingerprint
    is the checkpoint's current one, an A1 audit passed it, and no later claim supersedes
    it; a seed with no accepted claim is pending; theorem_ready needs a complete
    prefix-free frontier with every seed covered exactly once"""
    current = sha(payload["dependency_bundle"]["proof_critical"])
    claims, audits = payload["claim_ledger"], payload["audit_ledger"]
    superseded = {c["supersedes"] for c in claims if c.get("supersedes")}
    a1 = {a["claim_id"] for a in audits if a["audit_level"].startswith("A1") and a["result"] == "PASS"}
    accepted, stale, rejected = [], [], []
    for c in claims:
        if c["claim_id"] in superseded:         # an ancestor is history, whatever its status (sec. 8-9)
            continue
        if c["status"] == "REJECTED":
            rejected.append(c["claim_id"])
        elif c["dependency_fingerprint"] != current:
            stale.append(c["claim_id"])
        elif c["status"] == "VERIFIED-INDEPENDENT-REPLAY" and c["claim_id"] in a1:
            accepted.append(c["claim_id"])
    cover = [s for c in claims if c["claim_id"] in accepted for s in c["seed_paths"]]
    seeds = payload["frontier"]["seed_paths"]
    pending = sorted(s for s in seeds if s not in cover)
    duplicate = sorted({s for s in cover if cover.count(s) > 1})
    ready = complete(set(seeds)) and not pending and not duplicate
    return {"fingerprint": current, "theorem_ready": ready, "accepted_claim_ids": sorted(accepted),
            "pending_seed_paths": pending, "duplicate_seed_paths": duplicate, "stale_claim_ids": sorted(stale),
            "rejected_claim_ids": sorted(rejected), "superseded_claim_ids": sorted(superseded)}


# ---------------------------------------------------------------- checks

def w1_digests(w):
    out, fps = [], {}
    for name, cp in w["checkpoints"].items():
        p = cp["payload"]
        if w["digest"](p) != cp["payload_sha256"]:
            out.append(f"{name}: the payload digest does not re-derive")
        fp = w["digest"](p["dependency_bundle"]["proof_critical"])
        if fp != p["dependency_bundle"]["proof_critical_fingerprint"]:
            out.append(f"{name}: the fingerprint is not the digest of the proof-critical bundle")
        fps[name] = fp
    if fps["v2_performance_only"] != fps["v1_baseline"] or fps["v3_proof_critical_change"] == fps["v1_baseline"]:
        out.append("V2 must keep V1's fingerprint and V3 must change it")
    g = w["r11"]["global_manifest.json"]
    root = w["checkpoints"]["v1_baseline"]["payload"]["dependency_bundle"]["proof_critical"]["root_domain_hash"]
    if w["digest"](json.loads(g)["payload"]["root_base_domain"]) != root:
        out.append("root_domain_hash is not the digest of Round 11's root box")
    agg = w["checkpoints"]["v1_baseline"]["payload"]["aggregate"]["source_merge_summary_hash"]
    raw = hashlib.sha256(w["r11"]["merge_verification_summary.json"]).hexdigest()
    if raw != agg:
        out.append("source_merge_summary_hash is not the digest of Round 11's merge summary")
    for f in COPIES:
        if w["r12_copies"][f] != w["r11"][f]:
            out.append(f"{f}: Round 12's copy differs from Round 11's")
    # the arithmetic policy hash commits to a two-field descriptor; the text's pad, then its V3 change
    for name, pad in (("v1_baseline", w["fp_pads"][0]), ("v3_proof_critical_change", w["fp_pads"][1])):
        rec = w["checkpoints"][name]["payload"]["dependency_bundle"]["proof_critical"]["arithmetic_policy_hash"]
        if w["digest"]({"mode": "REFERENCE_DRY_RUN", "fp_pad": pad}) != rec:
            out.append(f"{name}: the arithmetic policy hash is not the digest of its pad {pad}")
    w["w1"] = {"fingerprints": fps, "merge_summary_hash_is_of": "file bytes, not the canonical form",
               "arithmetic_policy_preimage": {"mode": "REFERENCE_DRY_RUN", "fp_pad": list(w["fp_pads"])},
               "other_preimages": "not in the package"}
    return out


def w2_validator(w):
    out, rows = [], {}
    for name, cp in w["checkpoints"].items():
        r = w["validate"](cp["payload"])
        rows[name] = r
        s = w["summary"][name]
        for key in ("theorem_ready", "accepted_claim_ids", "pending_seed_paths", "duplicate_seed_paths",
                    "stale_claim_ids", "rejected_claim_ids"):
            if r[key] != s[key]:
                out.append(f"{name}: {key} {r[key]}, summary {s[key]}")
        if r["theorem_ready"] != w["text_table"][name]:
            out.append(f"{name}: theorem_ready {r['theorem_ready']}, the text's table {w['text_table'][name]}")
    w["w2"] = {k: {"theorem_ready": v["theorem_ready"], "accepted": v["accepted_claim_ids"],
                   "pending": v["pending_seed_paths"]} for k, v in rows.items()}
    return out


def w3_links(w):
    out = []
    g = json.loads(w["r11"]["global_manifest.json"])["payload"]
    merged = {m["shard_id"]: m for m in json.loads(w["r11"]["merge_verification_summary.json"])["per_shard"]}
    listed = {s["shard_id"]: s for s in g["shards"]}
    p = w["checkpoints"]["v1_baseline"]["payload"]
    verifier = p["dependency_bundle"]["proof_critical"]["verifier_semantics_hash"]
    for c in p["claim_ledger"]:
        s = listed[c["shard_id"]]
        if c["certificate_payload_sha256"] != s["payload_sha256"] or c["seed_paths"] != s["seed_paths"] \
                or c["references"]["round11_shard_merkle_root"] != g["shard_merkle_root"]:
            out.append(f"{c['claim_id']}: not Round 11's {c['shard_id']}")
    for a in p["audit_ledger"]:
        shard = next(c["shard_id"] for c in p["claim_ledger"] if c["claim_id"] == a["claim_id"])
        m = merged[shard]
        if (a["nodes"], a["leaves"], a["worst_verified_slack"]) != (m["nodes"], m["leaves"], m["worst_verified_slack"]) \
                or a["verifier_hash"] != verifier:
            out.append(f"{a['audit_id']}: its metrics are not Round 11's merge row for {shard}")
    if p["scope"] != w["scope"] or p["global_lebesgue_claim"] is not False:
        out.append("the reference checkpoint does not mark itself local")
    return out


def w4_semantics(w):
    out, stored_wrong, readmitted, bare_a1 = [], [], [], []
    for name, cp in w["checkpoints"].items():
        p = cp["payload"]
        r = validate(p)
        agg = p["aggregate"]
        if agg["theorem_ready"] != r["theorem_ready"] or agg.get("active_claim_ids") != r["accepted_claim_ids"] \
                or agg["pending_seed_paths"] != r["pending_seed_paths"]:
            stored_wrong.append(name)
        failed = {a["claim_id"] for a in p["audit_ledger"] if a["result"] == "FAIL"}
        rejected_bytes = {c["certificate_payload_sha256"] for c in p["claim_ledger"]
                          if c["status"] == "REJECTED" and c["claim_id"] in failed}
        if any(c["certificate_payload_sha256"] in rejected_bytes for c in p["claim_ledger"]
               if c["claim_id"] in r["accepted_claim_ids"]):
            readmitted.append(name)
        for a in p["audit_ledger"]:
            if a["audit_level"].startswith("A1") and a["result"] == "PASS" and "leaves" not in a:
                bare_a1.append(f"{name}: {a['audit_id']}")
    if sorted(stored_wrong) != sorted(w["stored_aggregate_wrong"]):
        out.append(f"checkpoints whose stored aggregate contradicts their ledger: {stored_wrong}, "
                   f"recorded {w['stored_aggregate_wrong']}")
    if sorted(readmitted) != sorted(w["rejected_bytes_readmitted"]):
        out.append(f"checkpoints accepting bytes a FAIL rejected: {readmitted}, recorded {w['rejected_bytes_readmitted']}")
    w["w4"] = {"stored_aggregate_contradicts_ledger": stored_wrong, "rejected_bytes_readmitted": readmitted,
               "A1_passes_without_replay_metrics": bare_a1}
    return out


def w5_stale(w):
    out, rng = [], np.random.default_rng(115)
    base = copy.deepcopy(w["checkpoints"]["v1_baseline"]["payload"]["dependency_bundle"])
    fp0 = w["digest"](base["proof_critical"])
    for k in base["proof_critical"]:
        b = copy.deepcopy(base)
        b["proof_critical"][k] = (b["proof_critical"][k] + 1e-9) if isinstance(b["proof_critical"][k], float) \
            else hashlib.sha256(str(rng.random()).encode()).hexdigest()
        if w["digest"](b["proof_critical"]) == fp0:
            out.append(f"changing {k} leaves the fingerprint")
    for k in base["performance_only"]:
        b = copy.deepcopy(base)
        b["performance_only"][k] = "changed"
        if w["digest"](b["proof_critical"]) != fp0:
            out.append(f"changing the performance-only {k} moves the fingerprint")
    shuffled = dict(reversed(list(base["proof_critical"].items())))
    if w["digest"](shuffled) != fp0:
        out.append("the fingerprint depends on key order")
    return out


def p1_package(w):
    out, schema = [], w["schema"]
    bad = []
    for name, cp in w["checkpoints"].items():
        try:
            jsonschema.validate(cp["payload"], schema)
        except jsonschema.ValidationError:
            bad.append(name)
    if bad:
        out.append(f"checkpoints failing the schema: {bad}")
    extra = sorted(s for s in PROTOCOL_STATES if s in w["protocol"] and s not in SEC7_STATES)
    if extra != sorted(w["protocol_states_outside_text"]):
        out.append(f"the protocol's states outside sec. 7: {extra}, recorded {w['protocol_states_outside_text']}")
    missing = sorted(k for k, v in SEC36.items() if v is None or v not in w["protocol"])
    if missing != sorted(w["protocol_gate_missing"]):
        out.append(f"the protocol's gate leaves out {missing}, recorded {w['protocol_gate_missing']}")
    w["p1"] = {"schema_failures": bad, "protocol_states_outside_text": extra, "protocol_gate_missing": missing}
    return out


def p2_package(w):
    out, leaves = [], {row[0]: row for row in w["manifest"]["leaves"]}
    v = w["validation"]
    for rec, leaf_id, text in ((v["round12"], DOC, w["text"]), (v["state_crystal"], CRYSTAL, w["crystal"]),
                               (v["audit_protocol"], PROTOCOL, w["protocol"])):
        _, size, digest = leaves[leaf_id]
        if rec["sha256"] != digest or rec["bytes"] != size:
            out.append(f"{rec['file']}: recorded sha256/bytes differ from the archive")
        n = text.count("$$")
        if rec["double_dollar_count"] != n or rec["double_dollar_even"] != (n % 2 == 0):
            out.append(f"{rec['file']}: recorded {rec['double_dollar_count']} $$, document has {n}")
        if rec["contains_unicode_escape_sequence"] != bool(re.search(r"\\u[0-9a-fA-F]{4}", text)):
            out.append(f"{rec['file']}: unicode-escape flag differs")
        if rec["contains_bracket_math_delimiter"] != bool(re.search(r"\\[\[\]()]", text)):
            out.append(f"{rec['file']}: bracket-delimiter flag differs")
    for key, leaf_id in (("checkpoint_schema_sha256", SCHEMA), ("validator_sha256", VALIDATOR),
                         ("transition_demo_sha256", DEMO)):
        if v[key] != leaves[leaf_id][2]:
            out.append(f"{key}: recorded digest differs from the archive")
    if v["baseline_checkpoint"] != w["summary"]["v1_baseline"]:
        out.append("VALIDATION's baseline differs from the transition summary")
    results = {k: w["summary"][k]["theorem_ready"] for k in STATES}
    if v["transition_results"] != results or v["transition_expectations"] != results:
        out.append("VALIDATION's transition results or expectations differ from the summary")
    return out


# ---------------------------------------------------------------- registry (Round 12)

TOKEN = "a claim or aggregate state of sec. 7, 20 or 26, defined there; not a judgment"
R12_DEFINITIONS = {
    "TESTED": ("contextual", "sec. 40: exercised by the reference transitions V1-V5; not proved"),
    "STILL DEFERRED": ("in-line", "sec. 0: the global 0.835 computation is still deferred"),
    "PROVED + TESTED": ("in-line", "sec. 40: proved, and exercised by the reference transitions"),
    "STALE": ("in-line", "sec. 4, 7: a claim whose fingerprint is not the checkpoint's current one; computed, not stored"),
    "VERIFIED-INDEPENDENT-REPLAY": ("in-line", "sec. 7: a claim whose certificate passed the canonical independent verifier"),
    "EMITTED": ("in-line", "sec. 7: certificate bytes exist; nothing verified"),
    "NOT-THEOREM-READY": ("in-line", "sec. 20, 33: the aggregate while any terminal claim is stale, rejected or missing"),
    "SUPERSEDED": ("in-line", "sec. 7, 9: a claim replaced by a newer one that names it in supersedes"),
}
R12_REVIEWS = [
    ("PASS", "Reference checkpoint transition V1–V5", "computation", "PASS",
     "W2: this tree's validator gives the same five verdicts"),
    ("CLOSED", "DISTRIBUTED PROOF CHECKPOINT ABI", "reading", "PARTIAL",
     "the fingerprint and the digests work (W1), but nothing checks a checkpoint's stored aggregate against its "
     "ledger: V3 and V4 store theorem_ready = true, and V4 and V5 list a rejected claim as active (W4)"),
    ("CLOSED", "STALE / CORRECTION SEMANTICS", "analytic", "PARTIAL",
     "staleness and rejection work (W2); a correction may re-admit the very bytes a FAIL rejected on a fresh A1 "
     "PASS from the verifier that had passed them, which sec. 12 forbids (W4)"),
    ("COMPUTE-DEFERRED", "Global $0.8350$ checkpoint", "n/a", "n/a", ""),
    ("STILL DEFERRED", "GLOBAL 0.8350 COMPUTE", "n/a", "n/a", "sec. 0's boxed summary; read from census v3 on (RUN-003)"),
    ("PROVED + TESTED", "Stale-safety semantics", "analytic", "PASS",
     "Thm 5.1 on random bundles (W5) and V1-V5 (W2); read from census v4 on (RUN-003)"),
    ("IMPLEMENTED", "Checkpoint schema", "computation", "PASS",
     "all five checkpoints validate (P1); the schema leaves claims and audits untyped"),
    ("IMPLEMENTED", "Dependency fingerprint", "computation", "PASS", "SHA-256 of the canonical proof-critical bundle (W1)"),
    ("REJECTED", "", "n/a", "n/a", TOKEN),
    ("REJECTED", "26. Transition V4：local shard rejection", "n/a", "n/a", TOKEN),
    ("TESTED", "Performance-only non-invalidation", "computation", "PASS", "V2 keeps V1's fingerprint (W1, W2)"),
    ("TESTED", "Local rejection propagation", "computation", "PASS", "V4 frees seed 01 and keeps A and C (W2)"),
    ("TESTED", "Append-only correction", "computation", "PARTIAL",
     "the ledger stays append-only and V5 is theorem-ready (W2), but its corrected claim is the rejected bytes, "
     "passed again by the same verifier, with the FAIL unanswered (W4)"),
    ("CORRECTED", "", "n/a", "n/a", TOKEN),
    ("SPECIFIED", "Multi-AI audit protocol", "reading", "PASS",
     "consistent with the text, with two extra states and one gate item fewer (P1); its A1 'separate proof path' "
     "holds for the reference verifier only in the hull routine (RUN-013)"),
    ("STALE", "證明", "n/a", "n/a", TOKEN),
    ("STALE", "", "n/a", "n/a", TOKEN),
    ("VERIFIED-INDEPENDENT-REPLAY", "", "n/a", "n/a", TOKEN),
    ("VERIFIED-INDEPENDENT-REPLAY", "", "n/a", "n/a", TOKEN),
    ("EMITTED", "", "n/a", "n/a", TOKEN),
    ("NOT-THEOREM-READY", "20. Proof-critical change propagation", "n/a", "n/a", TOKEN),
    ("SUPERSEDED", "", "n/a", "n/a", TOKEN),
]


def r1_registry(w):
    return registry.completeness(w["registry"], "R12", w["definitions"], w["reviews"])


# ---------------------------------------------------------------- world, checks, drill

CHECKS = {"A0": gate.anchors_check(ANCHORS), "W1": w1_digests, "W2": w2_validator, "W3": w3_links,
          "W4": w4_semantics, "W5": w5_stale, "P1": p1_package, "P2": p2_package, "R1": r1_registry}
DEPENDS = {"A0": {"text"}, "W1": {"checkpoints", "digest", "r11", "r12_copies", "fp_pads"},
           "W2": {"checkpoints", "summary", "validate", "text_table"}, "W3": {"checkpoints", "r11", "scope"},
           "W4": {"checkpoints", "stored_aggregate_wrong", "rejected_bytes_readmitted"}, "W5": {"checkpoints", "digest"},
           "P1": {"checkpoints", "schema", "protocol", "protocol_states_outside_text", "protocol_gate_missing"},
           "P2": {"validation", "text", "crystal", "protocol", "manifest", "summary"},
           "R1": {"registry", "definitions", "reviews"}}

CLAIMS = {
    "digest": sha, "validate": validate, "fp_pads": (1e-8, 2e-8),
    "text_table": {"v1_baseline": True, "v2_performance_only": True, "v3_proof_critical_change": False,
                   "v4_rejected_B": False, "v5_corrected_B": True},
    "scope": "ROUND10-LOCAL-REFERENCE-SHARDS",
    "stored_aggregate_wrong": ["v3_proof_critical_change", "v4_rejected_B", "v5_corrected_B"],
    "rejected_bytes_readmitted": ["v5_corrected_B"],
    "protocol_states_outside_text": ["REJECTED-PENDING-REVIEW", "STALE-AGGREGATE"],
    "protocol_gate_missing": ["source and certificate hashes"],
}


def load_inputs():
    blobs = {n: source_bytes(n) for n in SOURCES}
    want = {DOC, PROTOCOL, CRYSTAL, VALIDATION, SCHEMA, SUMMARY, *(REF + f for f in STATES.values()),
            *(REF + f for f in COPIES), *(R11 + f for f in COPIES)}
    got = {leaf.id: d for leaf, d in walk_sources(blobs, keep=lambda l: l.id in want) if d is not None}
    return {"text": got[DOC].decode("utf-8"), "protocol": got[PROTOCOL].decode("utf-8"),
            "crystal": got[CRYSTAL].decode("utf-8"), "validation": json.loads(got[VALIDATION]),
            "schema": json.loads(got[SCHEMA]), "summary": json.loads(got[SUMMARY]),
            "checkpoints": {k: json.loads(got[REF + f]) for k, f in STATES.items()},
            "r12_copies": {f: got[REF + f] for f in COPIES}, "r11": {f: got[R11 + f] for f in COPIES},
            "manifest": json.loads(MANIFEST.read_text(encoding="utf-8"))}


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--drill", action="store_true")
    ap.add_argument("--blind", metavar="CID")
    args = ap.parse_args()
    inputs = load_inputs()

    def build():
        return {**{k: (copy.deepcopy(v) if k not in ("r11", "r12_copies") else dict(v)) for k, v in inputs.items()},
                "registry": registry.load(), "definitions": dict(R12_DEFINITIONS), "reviews": list(R12_REVIEWS),
                **copy.deepcopy({k: v for k, v in CLAIMS.items() if k not in ("digest", "validate")}),
                "digest": CLAIMS["digest"], "validate": CLAIMS["validate"]}

    if args.blind:
        CHECKS[args.blind] = lambda w: []
        args.drill = True
    w = build()
    results = {c: fn(w) for c, fn in CHECKS.items()}
    for c, f in results.items():
        print(f"{c} {'PASS' if not f else 'FAIL'}", *(f"\n     {x}" for x in f[:6]))
    for key in ("w1", "w2", "w4", "p1"):
        print(key, w.get(key))
    if not args.drill:
        return
    cps, table = inputs["checkpoints"], CLAIMS["text_table"]
    v4 = copy.deepcopy(cps["v4_rejected_B"])
    v4["payload"]["claim_ledger"][1]["status"] = "VERIFIED-INDEPENDENT-REPLAY"
    cases = [
        ("K0-unmodified", "control", {}, set()),
        ("K1-doc-crlf", "control", {"text": inputs["text"].replace("\n", "\r\n")}, set()),
        ("K2-digest-ascii", "control",
         {"digest": lambda o: hashlib.sha256(json.dumps(o, sort_keys=True, separators=(",", ":")).encode()).hexdigest()},
         set()),
        ("K3-digest-of-reversed-keys", "control",
         {"digest": lambda o: sha(dict(reversed(list(o.items()))) if isinstance(o, dict) else o)}, set()),
        ("M1-doc-table", "mutation", {"text": inputs["text"].replace("| V4 | shard-B rejected | `false` |",
                                                                     "| V4 | shard-B rejected | `true` |")}, {"A0"}),
        ("M2-digest-unsorted", "mutation",
         {"digest": lambda o: hashlib.sha256(json.dumps(o, separators=(",", ":")).encode()).hexdigest()}, {"W1", "W5"}),
        ("M2b-pad-misread", "mutation", {"fp_pads": (1e-7, 2e-8)}, {"W1"}),
        ("M3-validator-ignores-staleness", "mutation",
         {"validate": lambda p: {**validate({**p, "dependency_bundle": cps["v1_baseline"]["payload"]["dependency_bundle"]})}},
         {"W2"}),
        ("M4-text-table", "mutation", {"text_table": {**table, "v3_proof_critical_change": True}}, {"W2"}),
        ("M5-scope-global", "mutation", {"scope": "GLOBAL-F3-BASE-ATLAS-T08350"}, {"W3"}),
        ("M6-stored-aggregates-assumed-right", "mutation", {"stored_aggregate_wrong": []}, {"W4"}),
        ("M7-readmission-assumed-absent", "mutation", {"rejected_bytes_readmitted": []}, {"W4"}),
        ("M8-protocol-states-assumed-in-text", "mutation", {"protocol_states_outside_text": []}, {"P1"}),
        ("M9-validation-results", "mutation", {"validation": {**inputs["validation"], "transition_results": {
            **inputs["validation"]["transition_results"], "v4_rejected_B": True}}}, {"P2"}),
        ("M10-review-dropped", "mutation", {"reviews": list(R12_REVIEWS[1:])}, {"R1"}),
    ]
    if args.blind:
        cases = [c for c in cases if args.blind in c[3]]
    d = gate.run_drill(build, CHECKS, DEPENDS, cases)
    summary = gate.summarize(d, CHECKS)
    print(gate.report_drill(summary))
    for x in d:
        if not x["ok"]:
            print("   DRILL FAIL", x)
    if args.blind:
        n = sum(1 for x in d if args.blind in x["expected"] and args.blind not in x["tripped"])
        print(f"blind {args.blind}: drill reported it blind in {n} cases (nothing written)")
        return
    log = {"run": "RUN-015", "subject": "Round 12: the checkpoint crystal and the multi-AI audit protocol",
           "document": DOC, "checks": {c: {"pass": not f, "failures": f} for c, f in results.items()},
           **{k: w.get(k) for k in ("w1", "w2", "w4", "p1")}, "drill": summary}
    LOG.write_text(json.dumps(log, ensure_ascii=False, indent=1, default=float) + "\n", encoding="utf-8")
    if not results["R1"]:
        registry.record("R12", "RUN-015", R12_DEFINITIONS, R12_REVIEWS)
        print(f"registry: {len(R12_DEFINITIONS)} definitions, {len(R12_REVIEWS)} reviews recorded for R12")


if __name__ == "__main__":
    main()
