#!/usr/bin/env python3
"""Clean-room verifier for the CAIN-42 Evolution 15 spatial + physical intelligence proof bundle.

IMPORTS NO CAIN-42 CODE. Standard library plus `cryptography` (Ed25519). From the published JSON alone it re-derives:
file hashes (MANIFEST), canonical serialization, spatial-state / trajectory / world-history digests (test vectors),
every published component-state digest, the world-state digest and its hash-chained history (links, monotonic time,
head == live digest), sensor registration digests and every accepted observation's sensor signature (and that the
spoofed one does NOT verify), observation provenance into world components, the cross-modal consistency digests,
the world-model output binding signature, the entity-operation chain, the trajectory digest + the fabric-signed
approval bound to it, the prediction graph root, blast radius and counterfactual digests, the nine-binding
authorization step (signature, TTL, bindings == commit), the physical commit digest, the E8 canonical action hash and
its embedded physical bindings, the E8 token (signature, action hash, TTL), the execution permit (signature, command
digest, action hash, TTL), the actuator result digest, the physical and E8 evidence chains, replay refusal, drift ->
revocation, the autonomy history (hash chain AND legal transitions), the feedback chain, human-act signature and
audit chain, simulation evidence (signature, bindings, never-reality flags), scenario lineage, sim-to-real gap class,
the digital-twin delta, the convergence rows, the P1-P36 matrix, the >=50-scenario bench, both proof signatures and
the signing-key disclosure.

It proves the bundle is intact and self-consistent. It does NOT prove physical safety, that a sensor told the truth,
that a world model is accurate, or that anything outside the enforcement boundary is controlled.

Usage:  python3 verify_e15.py <bundle-directory>
"""
from __future__ import annotations

import base64
import hashlib
import json
import math
import sys
from pathlib import Path

from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.primitives.asymmetric import ed25519

D = {"state": "CAIN42/E15-SPATIAL-TEMPORAL-STATE/v1", "obs": "CAIN42/E15-SPATIAL-OBSERVATION/v1",
     "sensor_reg": "CAIN42/E15-SENSOR-REGISTRATION/v1", "consistency": "CAIN42/E15-CROSS-MODAL-CONSISTENCY/v1",
     "entity_op": "CAIN42/E15-SPATIAL-ENTITY-OPERATION/v1", "world": "CAIN42/E15-GOVERNED-WORLD-STATE/v1",
     "history": "CAIN42/E15-WORLD-STATE-HISTORY/v1", "map": "CAIN42/E15-MAP/v1",
     "prov": "CAIN42/E15-WORLD-STATE-PROVENANCE/v1", "drift": "CAIN42/E15-SPATIAL-REALITY-DRIFT/v1",
     "wm_out": "CAIN42/E15-WORLD-MODEL-OUTPUT/v1", "wm_bind": "CAIN42/E15-WORLD-MODEL-BINDING/v1",
     "traj": "CAIN42/E15-GOVERNED-TRAJECTORY/v1", "approval": "CAIN42/E15-TRAJECTORY-APPROVAL/v1",
     "traj_decision": "CAIN42/E15-TRAJECTORY-DECISION/v1", "graph": "CAIN42/E15-TRAJECTORY-PREDICTION-GRAPH/v1",
     "blast": "CAIN42/E15-PHYSICAL-BLAST-RADIUS/v1", "cf": "CAIN42/E15-PHYSICAL-COUNTERFACTUAL/v1",
     "step": "CAIN42/E15-CONTINUOUS-PHYSICAL-AUTHORIZATION/v1", "binding": "CAIN42/E15-PHYSICAL-BINDING-COMPONENT/v1",
     "actuator": "CAIN42/E15-ACTUATOR-COMMAND/v1", "permit": "CAIN42/E15-ACTUATOR-EXECUTION-PERMIT/v1",
     "result": "CAIN42/E15-ACTUATOR-RESULT/v1", "commit": "CAIN42/E15-PHYSICAL-ACTION-COMMIT/v1",
     "sim": "CAIN42/E15-SIMULATION-EVIDENCE/v1", "twin": "CAIN42/E15-DIGITAL-TWIN/v1",
     "gap": "CAIN42/E15-SIM-REALITY-GAP/v1", "scenario": "CAIN42/E15-PHYSICAL-SCENARIO/v1",
     "adversarial": "CAIN42/E15-PHYSICAL-ADVERSARIAL/v1", "feedback": "CAIN42/E15-REALITY-FEEDBACK/v1",
     "human": "CAIN42/E15-PHYSICAL-HUMAN-AUTHORITY/v1", "human_act": "CAIN42/E15-PHYSICAL-HUMAN-ACT/v1",
     "autonomy": "CAIN42/E15-EMBODIED-AUTONOMY/v1", "evidence": "CAIN42/E15-PHYSICAL-EVIDENCE/v1",
     "convergence": "CAIN42/E15-CONVERGENCE/v1", "gat": "CAIN42/E8-GOVERNANCE-AUTHORIZATION-TOKEN/v1",
     "action": "CAIN42/E8-CANONICAL-ACTION/v1", "kernel_ev": "CAIN42/E8-KERNEL-EVIDENCE/v1",
     "proof": "CAIN42/E15-PROOF/v1", "master": "CAIN42/E15-MASTER/v1"}
BINDING_FIELDS = ("world_state_digest", "trajectory_digest", "decision_digest", "capability_digest",
                  "authority_digest", "policy_digest", "risk_digest", "consequence_digest", "authorization_digest")
MAX_STEP_TTL, MAX_PERMIT_TTL, MAX_GAT_TTL = 5.0, 2.0, 30.0
REQUIRED_FILES = ("MANIFEST.json", "SCHEMAS.json", "CAIN42_EVOLUTION15_PROOF.json",
                  "CAIN42_EVOLUTION15_MASTER_PROOF.json", "WORLD_STATE_EXAMPLES.json",
                  "SPATIAL_OBSERVATION_EXAMPLES.json", "TRAJECTORY_EXAMPLES.json", "PHYSICAL_ACTION_EXAMPLES.json",
                  "SIMULATION_EXAMPLES.json", "DIGITAL_TWIN_EXAMPLES.json", "END_TO_END_DEMO.json",
                  "ATTACK_MANIFEST.json", "TEST_VECTORS.json", "PERFORMANCE.json", "LIMITATIONS.json",
                  "LIMITATIONS.md", "verify_e15.py.txt", "REPRODUCE.txt", "index.html")
REQUIRED_SCHEMAS = ("EmbodiedSystem", "SpatialTemporalState", "SpatialObservation", "GovernedTrajectory",
                    "TrajectoryApproval", "PhysicalAuthorizationStep", "PhysicalActionCommit", "ExecutionPermit",
                    "ActuatorCommand", "PhysicalConsequenceVector", "SpatialCapabilityBoundary", "GovernedWorldModel")
REAL_LAYERS = {"OBSERVED", "INFERRED"}
FORBIDDEN = ("private_key", "private key", "-----begin", "secret_key", "password")


def canon(o) -> bytes:
    return json.dumps(o, sort_keys=True, separators=(",", ":"), ensure_ascii=True).encode()


def h(o) -> str:
    return hashlib.sha256(canon(o)).hexdigest()


def digest(domain: str, fields: dict) -> str:
    return h({"domain": domain, **fields})


def sig_ok(pub_b64: str, sig_b64: str, domain: str, fields: dict) -> bool:
    try:
        ed25519.Ed25519PublicKey.from_public_bytes(base64.b64decode(pub_b64)).verify(
            base64.b64decode(sig_b64), digest(domain, fields).encode())
        return True
    except (InvalidSignature, ValueError, TypeError):
        return False


def strip(d: dict, *keys: str) -> dict:
    return {k: v for k, v in d.items() if k not in keys}


def chain_ok(entries: list, domain: str, *, digest_key: str = "entry_digest") -> bool:
    prev = "0" * 64
    for e in entries:
        b = strip(e, digest_key)
        if b.get("prev") != prev or digest(domain, b) != e.get(digest_key):
            return False
        prev = e[digest_key]
    return True


def dist(a: dict, b: dict) -> float:
    return math.dist((a["x"], a["y"], a["z"]), (b["x"], b["y"], b["z"]))


class Checker:
    def __init__(self) -> None:
        self.checks: list = []
        self.problems: list = []

    def check(self, name: str, ok, detail: str = "") -> None:
        self.checks.append({"check": name, "ok": bool(ok)})
        if not ok:
            self.problems.append(f"{name}: {detail}" if detail else name)


def main() -> int:
    if len(sys.argv) < 2:
        print("usage: python3 verify_e15.py <bundle-directory>")
        return 2
    d = Path(sys.argv[1])
    C = Checker()
    load = lambda n: json.loads((d / n).read_text())

    # --- 1-2 evidence manifest ---------------------------------------------------------------------------------
    manifest = load("MANIFEST.json")
    bad = [n for n, want in manifest["files"].items() if not (d / n).exists()
           or hashlib.sha256((d / n).read_bytes()).hexdigest() != want]
    C.check("manifest_file_hashes", not bad, ",".join(bad))
    presentation = set(manifest.get("unhashed_presentation", []))
    C.check("required_files_present", all((d / f).exists() for f in REQUIRED_FILES) and
            presentation <= {"index.html"} and
            all(f in manifest["files"] for f in REQUIRED_FILES if f not in ("MANIFEST.json", "index.html")))
    proof, master = load("CAIN42_EVOLUTION15_PROOF.json"), load("CAIN42_EVOLUTION15_MASTER_PROOF.json")
    world, obs = load("WORLD_STATE_EXAMPLES.json"), load("SPATIAL_OBSERVATION_EXAMPLES.json")
    traj_ex, phys = load("TRAJECTORY_EXAMPLES.json"), load("PHYSICAL_ACTION_EXAMPLES.json")
    sim, twin, vectors = load("SIMULATION_EXAMPLES.json"), load("DIGITAL_TWIN_EXAMPLES.json"), load("TEST_VECTORS.json")

    # --- 3 schemas ----------------------------------------------------------------------------------------------
    sch = load("SCHEMAS.json")
    C.check("world_state_schemas_published", set(REQUIRED_SCHEMAS) <= set(sch) and
            sch["_enums"]["spatial_layers"] == ["OBSERVED", "INFERRED", "PREDICTED", "SIMULATED", "UNKNOWN"] and
            sch["_enums"]["binding_fields"] == list(BINDING_FIELDS))

    # --- 4-7 test vectors (independent re-derivation) -------------------------------------------------------------
    tv = vectors["canonical"]
    C.check("canonical_serialization_vector", canon(tv["input"]).decode() == tv["canonical_json"]
            and h(tv["input"]) == tv["sha256"])
    C.check("spatial_state_vector", digest(D["state"], vectors["spatial_state"]["body"]) ==
            vectors["spatial_state"]["digest"])
    tr = vectors["trajectory"]
    pts = [tr["body"]["origin"], *tr["body"]["path"], tr["body"]["destination"]]
    ts = tr["body"]["timing"]
    speeds = [dist(pts[i], pts[i + 1]) / (ts[i + 1] - ts[i]) for i in range(len(pts) - 1)]
    C.check("trajectory_vector", digest(D["traj"], tr["body"]) == tr["digest"] and
            all(abs(a - b) < 1e-9 for a, b in zip(speeds, tr["implied_speeds"])))
    C.check("world_history_vector", digest(D["history"], vectors["world_history_entry"]["body"]) ==
            vectors["world_history_entry"]["digest"] and
            digest(D["binding"], {"component": vectors["binding_component"]["name"],
                                  "value": vectors["binding_component"]["value"]}) ==
            vectors["binding_component"]["digest"] and
            digest(D["map"], vectors["map"]["map"]) == vectors["map"]["digest"])

    # --- 8-10 world state -----------------------------------------------------------------------------------------
    w = world["world"]
    comps = world["component_states"]
    C.check("world_component_digests", all(digest(D["state"], strip(s, "digest")) == s["digest"] ==
                                           w["components"][e] for e, s in comps.items())
            and set(comps) == set(w["components"]) and all(s["evidence_class"] in REAL_LAYERS
                                                           for s in comps.values()))
    body = {k: w[k] for k in ("world_state_id", "tenant", "version", "components", "relationships", "environment",
                              "map_digest", "consistency", "invalidated", "invalidation_reason", "observation_root")}
    root = "0" * 64                                  # running hash over every ingested observation, in log order
    for e in world["log"]:
        if e["op"].startswith("INGEST"):
            root = h([root, e["observation"]["observation_id"], e["observation"]["digest"]])
    C.check("world_state_digest", digest(D["world"], body) == w["digest"] and root == w["observation_root"])
    hist = world["history"]
    times = [x["at"] for x in hist]
    C.check("world_history_chain", chain_ok(hist, D["history"]) and times == sorted(times) and
            hist[-1]["state_digest"] == w["digest"] and hist[-1]["entry_digest"] == w["history_head"] and
            [x["version"] for x in hist] == list(range(1, len(hist) + 1)))

    # --- 11-14 observations: sensor identity, signatures, provenance, E12 --------------------------------------
    sensors = {s["sensor_id"]: s for s in obs["sensors"]}
    C.check("sensor_registration_digests", all(digest(D["sensor_reg"], {
        "sensor_id": s["sensor_id"], "source_identity": s["source_identity"], "sensor_type": s["sensor_type"],
        "public_key_b64": s["public_key_b64"], "system_id": s["system_id"], "tenant": s["tenant"],
        "registered_at": 1000.0}) == s["digest"] for s in obs["sensors"]))
    accepted = [e["observation"] for e in world["log"] if e["op"].startswith("INGEST")]
    sig_all = all(o["sensor_id"] in sensors and o["sensor_type"] == sensors[o["sensor_id"]]["sensor_type"] and
                  o["source_identity"] == sensors[o["sensor_id"]]["source_identity"] and
                  sig_ok(sensors[o["sensor_id"]]["public_key_b64"], o["signature_b64"], D["obs"],
                         strip(o, "digest", "signature_b64")) and
                  digest(D["obs"], strip(o, "digest", "signature_b64")) == o["digest"] for o in accepted)
    C.check("observation_sensor_signatures", sig_all and len(accepted) >= 6)
    spoof = next(r for r in obs["refused"] if r["case"] == "spoofed signature")
    so = spoof["observation"]
    C.check("spoofed_observation_does_not_verify", not sig_ok(sensors[so["sensor_id"]]["public_key_b64"],
                                                              so["signature_b64"], D["obs"],
                                                              strip(so, "digest", "signature_b64"))
            and spoof["accepted"] is False and "SENSOR_SIGNATURE_INVALID" in spoof["reasons"])
    by_digest = {o["digest"]: o for o in accepted}
    C.check("observation_provenance_preserved", all(s["provenance"] and s["provenance"][0] in by_digest and
                                                    by_digest[s["provenance"][0]]["entity_id"] == e
                                                    for e, s in comps.items()))
    refused_ok = {r["case"]: r for r in obs["refused"]}
    C.check("timestamps_and_replay_refused", refused_ok["future timestamp"]["reasons"] == ["TIMESTAMP_MANIPULATION"]
            and "STALE_OBSERVATION" in refused_ok["stale"]["reasons"]
            and refused_ok["unregistered sensor"]["reasons"] == ["SENSOR_UNREGISTERED"]
            and "OBSERVATION_REPLAY" in refused_ok["replayed observation"]["reasons"])
    adm = obs["admission"]
    C.check("e12_admission_attested_not_truth", adm["accepted"] and adm["epistemic_status"] == "ATTESTED" and
            adm["is_truth"] is False and adm["e12_envelope"]["source_type"] == "sensor" and
            adm["authority"] == "NONE")

    # --- 15 consistency ------------------------------------------------------------------------------------------
    cons_ok = True
    for name, want in (("consistent", "CONSISTENT"), ("inconsistent", "INCONSISTENT"), ("sensor_dropout", "DEGRADED")):
        r = obs["consistency"][name]
        b = {k: r[k] for k in ("state", "critical", "can_authorize", "conflicts", "reasons", "evaluated_at")}
        cons_ok &= digest(D["consistency"], b) == r["digest"] and r["state"] == want and \
            r["can_authorize"] == (want == "CONSISTENT")
    C.check("cross_modal_consistency", cons_ok)

    # --- 16 world model output ------------------------------------------------------------------------------------
    wm = obs["world_model_output"]
    wb = {k: wm[k] for k in ("output_id", "model_id", "model_version", "model_digest", "config_digest",
                             "world_state_digest", "scenario_digest", "timestamp", "predictions", "uncertainty",
                             "claims_digest", "evidence_class")}
    C.check("world_model_output_bound_and_not_authority", digest(D["wm_out"], wb) == wm["digest"] and
            sig_ok(wm["registry_public_key_b64"], wm["binding_signature_b64"], D["wm_bind"], wb) and
            wm["evidence_class"] == "PREDICTED" and wm["authority"] == "NONE" and
            wm["model_version"] == wm["model"]["model_version"] and wm["model_digest"] == wm["model"]["model_digest"]
            and all(digest(D["state"], strip(s, "digest")) == wm["predictions"][e] and s["evidence_class"] ==
                    "PREDICTED" for e, s in wm["prediction_states"].items())
            and wm["as_evidence"]["is_reality"] is False)

    # --- 17 spatial identity --------------------------------------------------------------------------------------
    ops = phys["entity_operations"]
    C.check("spatial_identity_operations_chain", chain_ok(ops, D["entity_op"], digest_key="op_digest") and
            any(o["op"] == "REGISTER" for o in ops))

    # --- 18-21 trajectory ------------------------------------------------------------------------------------------
    t = traj_ex["trajectory"]
    fabric = traj_ex["fabric_public_key_b64"]
    tbody = strip(t, "digest", "authorization_state", "authority")
    C.check("trajectory_digest", digest(D["traj"], tbody) == t["digest"])
    ap = traj_ex["approval"]
    abody = {k: ap[k] for k in ("approval_id", "trajectory_id", "trajectory_digest", "system_id",
                                "world_state_digest", "inputs_digest", "issued_at", "expires_at")}
    C.check("trajectory_approval_binding", sig_ok(fabric, ap["signature_b64"], D["approval"], abody) and
            ap["issuer"] == fabric and digest(D["approval"], abody) == ap["digest"] and
            ap["trajectory_digest"] == t["digest"] and 0 < ap["expires_at"] - ap["issued_at"] <= MAX_STEP_TTL)
    decs = traj_ex["trajectory_decisions"]
    dec_ok = all(digest(D["traj_decision"], {k: x[k] for k in ("decision", "trajectory_id", "trajectory_digest",
                                                               "reasons", "evaluated_at", "approval_digest",
                                                               "modified_trajectory_digest")}) == x["digest"]
                 for x in decs if "digest" in x)
    C.check("trajectory_decisions_recorded", dec_ok and any(x.get("decision") == "APPROVE" and
                                                            x["approval_digest"] == ap["digest"] for x in decs)
            and traj_ex["obstructed_decision"]["decision"] == "DENY")
    g = traj_ex["prediction_graph"]
    C.check("prediction_graph_root", digest(D["graph"], {"root_state_digest": g["root_state_digest"],
                                                         "futures": [h(f) for f in g["futures"]]}) == g["root"]
            and all(f["evidence_class"] == "PREDICTED" and f["probability"] < 1 and f["uncertainty"] > 0
                    for f in g["futures"]) and g["certain"] is False)
    br, cf = traj_ex["blast_radius"], traj_ex["counterfactual"]
    C.check("blast_radius_and_counterfactual", digest(D["blast"], strip(br, "schema", "digest", "authority")) ==
            br["digest"] and br["measurable"] is True and
            digest(D["cf"], {k: cf[k] for k in ("proposed", "current_state_digest", "alternatives",
                                                "lowest_predicted_risk", "evidence_class", "is_fact",
                                                "evaluated_at")}) == cf["digest"]
            and cf["evidence_class"] == "SIMULATED" and cf["is_fact"] is False and cf["authority"] == "NONE")

    # --- 22-27 physical action boundary -------------------------------------------------------------------------
    step, commit, act, gat = phys["step"], phys["commit"], phys["action"], phys["gat"]
    sbody = {k: step[k] for k in ("step_id", "system_id", "trajectory_id", "world_state_id", "world_version",
                                  "bindings", "scope", "issued_at", "expires_at", "nonce")}
    C.check("authorization_step_signed_bounded", sig_ok(fabric, step["signature_b64"], D["step"], sbody) and
            digest(D["step"], sbody) == step["digest"] and 0 < step["expires_at"] - step["issued_at"] <= MAX_STEP_TTL
            and set(step["bindings"]) == set(BINDING_FIELDS) and all(step["bindings"].values()))
    cbody = strip(commit, "digest", "authority")
    C.check("physical_commit_nine_bindings", digest(D["commit"], cbody) == commit["digest"] and
            {f: commit[f] for f in BINDING_FIELDS} == step["bindings"] and
            step["bindings"]["authorization_digest"] == ap["digest"] and
            step["bindings"]["trajectory_digest"] == t["digest"])
    act_body = strip(act, "action_hash", "authorization_id", "authorization_expiry", "nonce", "authority")
    C.check("e8_canonical_action_binds_physical", digest(D["action"], act_body) == act["action_hash"] and
            act["parameters"]["physical_bindings"] == {f: commit[f] for f in BINDING_FIELDS} and
            act["world_state_root"] == commit["world_state_digest"] and
            act["trajectory_hash"] == commit["trajectory_digest"] and act["policy_root"] == commit["policy_digest"]
            and act["parameters_digest"] == h(act["parameters"]))
    gat_body = strip(gat, "issuer", "signature_b64")
    C.check("e8_token", sig_ok(gat["issuer"], gat["signature_b64"], D["gat"], gat_body) and gat["issuer"] == fabric
            and gat["action_hash"] == act["action_hash"] and 0 < gat["expires_at"] - gat["issued_at"] <= MAX_GAT_TTL
            and gat["expires_at"] <= step["expires_at"] and gat["decision_digest"] == commit["decision_digest"]
            and gat["world_state_root"] == commit["world_state_digest"])
    cmd, pm = phys["command"], phys["permit"]
    pbody = {k: pm[k] for k in ("permit_id", "command_digest", "actuator_id", "system_id", "action_hash", "step_id",
                                "authorization_id", "issued_at", "expires_at", "nonce")}
    C.check("execution_permit", sig_ok(fabric, pm["signature_b64"], D["permit"], pbody) and pm["issuer"] == fabric
            and digest(D["actuator"], strip(cmd, "digest", "authority")) == cmd["digest"] == pm["command_digest"]
            and pm["action_hash"] == act["action_hash"] == cmd["action_hash"] and pm["step_id"] == step["step_id"]
            and pm["authorization_id"] == gat["authorization_id"]
            and 0 < pm["expires_at"] - pm["issued_at"] <= MAX_PERMIT_TTL)
    res = phys["actuator_result"]
    C.check("actuator_result_evidence", res["executed"] is True and res["permit_digest"] == digest(D["permit"], pbody)
            and digest(D["result"], {k: res[k] for k in ("command_digest", "permit_digest", "feedback", "at")}) ==
            res["result_digest"] and res["command_digest"] == cmd["digest"])
    ev = phys["boundary_evidence"]
    committed = [e for e in ev if e["decision"] == "COMMITTED"]
    C.check("physical_evidence_chain", chain_ok(ev, D["evidence"]) and committed and
            committed[0]["permit"] == digest(D["permit"], pbody) and committed[0]["step"] == step["digest"])
    kev = phys["e8_evidence"]
    prev, kok = "0" * 64, True
    for e in kev:
        b = strip(e, "entry_hash")
        kok &= b.get("prev") == prev and digest(D["kernel_ev"], b) == e["entry_hash"]
        prev = e["entry_hash"]
    C.check("e8_evidence_chain", kok)

    # --- 28-30 replay, drift, revocation, autonomy ---------------------------------------------------------------
    C.check("replay_resistance", phys["replayed_commit"]["committed"] is False and
            "STEP_REPLAYED" in phys["replayed_commit"]["reasons"])
    md = phys["material_drift"]
    C.check("drift_invalidates_and_revokes", md["drift"]["material"] is True and md["invalidated"] is True and
            md["revalidation"]["decision"] == "STOP" and md["safe_state"]["applied"] is True and
            digest(D["drift"], {k: md["drift"][k] for k in ("drift", "material", "findings", "affected_entities",
                                                            "action", "evaluated_at", "expected_digest",
                                                            "observed_digest")}) == md["drift"]["digest"]
            and phys["revoked_steps"] and phys["observation_after_step"]["revalidation"]["decision"] in (
                "CONTINUE", "REAUTHORIZE"))
    trans = load("SCHEMAS.json")["_embodied_transitions"]
    ah = phys["autonomy_history"]
    legal = all(ah[i]["state"] in trans[ah[i - 1]["state"]] for i in range(1, len(ah)))
    C.check("autonomy_state_machine", chain_ok(ah, D["autonomy"]) and legal and
            all(e["evidence"] for e in ah if e["state"] == "AUTHORIZED") and
            all(ah[i - 1]["state"] in ("GOVERNANCE_EVALUATION", "REVALIDATING") for i in range(1, len(ah))
                if ah[i]["state"] == "AUTHORIZED"))
    C.check("reality_feedback_chain", chain_ok(phys["feedback"], D["feedback"]) and
            {"PREDICTION", "REAL_WORLD_OBSERVATION", "OUTCOME", "ERROR", "EVIDENCE"} <=
            {e["stage"] for e in phys["feedback"]})
    C.check("mutations_refused", all(m["refused_with_no_actuator_effect"] for m in phys["mutation_refusals"]) and
            len(phys["mutation_refusals"]) >= 6 and all(any("CHANGED" in r for r in m["reasons"])
                                                        for m in phys["mutation_refusals"]))

    # --- 31 humans --------------------------------------------------------------------------------------------------
    humans = {x["human_id"]: x for x in phys["humans"]}
    ha = phys["human_act"]
    hb = {k: ha[k] for k in ("act", "human_id", "subject", "operation", "resource", "reason", "at", "nonce")}
    C.check("human_authority_audited", sig_ok(humans[ha["human_id"]]["public_key_b64"], ha["signature_b64"],
                                              D["human_act"], hb) and chain_ok(phys["human_audit"], D["human"])
            and any(e["op"] == "EMERGENCY_STOP" for e in phys["human_audit"]))

    # --- 32-34 simulation / twin / convergence ------------------------------------------------------------------
    se = sim["simulation_evidence"]
    sbody2 = strip(se, "digest", "issuer", "signature_b64", "authority")
    lineage = sim["scenario_lineage"]
    C.check("simulation_evidence_provenance", sig_ok(sim["simulation_public_key_b64"], se["signature_b64"],
                                                     D["sim"], sbody2) and digest(D["sim"], sbody2) == se["digest"]
            and se["evidence_class"] == "SIMULATED" and se["proves_real_world_safety"] is False and
            se["scenario_digest"] == lineage[0]["digest"] and se["trajectory_digest"] == sim["trajectory_digest"]
            and se["simulator_digest"] == sim["simulator"]["digest"])
    lin_ok = all(digest(D["scenario"], strip(s, "digest", "evidence_class", "authority")) == s["digest"]
                 for s in lineage) and all(lineage[i]["parent_digest"] == lineage[i - 1]["digest"]
                                           for i in range(1, len(lineage)))
    advs = sim["adversarial_scenarios"]
    C.check("scenario_lineage_and_red_team_honesty", lin_ok and len(lineage) >= 5 and
            all(a["real_world_validation"] == "NOT_PERFORMED" and
                digest(D["adversarial"], strip(a, "digest", "authority")) == a["digest"] for a in advs))
    gp, gu = sim["sim_reality_gap"], sim["sim_reality_gap_unknown"]
    worst = max(gp["position_errors_m"].values())
    C.check("sim_to_real_gap_explicit", digest(D["gap"], strip(gp, "digest", "proves_real_world_safety",
                                                               "authority")) == gp["digest"] and
            gp["gap"] == ("HIGH" if worst >= 2.0 else ("MODERATE" if worst >= 0.5 or gp["assumption_mismatches"]
                                                         else "LOW"))
            and gu["gap"] == "UNKNOWN" and gp["proves_real_world_safety"] is False)
    tw = twin["twin"]
    C.check("digital_twin_delta", digest(D["twin"], {k: tw[k] for k in ("system_id", "delta_m", "layers")}) ==
            tw["digest"] and tw["is_reality"] is False and "UNKNOWN" not in [tw["delta_m"].get("amr-1")])
    conv = twin["convergence"]
    rows_ok = all(digest(D["convergence"], {k: r[k] for k in ("system_id", "system_domain", "path", "complete")})
                  == r["digest"] and r["complete"] for r in conv["rows"].values())
    C.check("architecture_convergence", rows_ok and set(conv["rows"]) == {"DIGITAL", "PHYSICAL", "HYBRID"} and
            [p["status"] for p in conv["rows"]["DIGITAL"]["path"]].count("NOT_APPLICABLE") == 2 and
            conv["digital_out_of_scope_refused"] is True)

    # --- 35-37 invariants, bench, end-to-end --------------------------------------------------------------------
    inv = proof["invariants"]
    C.check("invariants_p1_p36", {x["id"] for x in inv["checks"]} == {f"P{i}" for i in range(1, 37)}
            and all(x["holds"] for x in inv["checks"]) and inv["all_hold"] is True)
    bench = load("ATTACK_MANIFEST.json")
    C.check("adversarial_bench", bench["total"] >= 50 and bench["contained"] == bench["total"] and
            len(bench["attacks"]) == bench["total"] and all(a["contained"] for a in bench["attacks"].values())
            and bench["real_world_attack_validation"] == "NOT_PERFORMED" and
            (bench["contained"], bench["total"]) == (proof["attack_bench"]["contained"], proof["attack_bench"]["total"]))
    e2e = load("END_TO_END_DEMO.json")
    C.check("end_to_end_demo", [s["step"] for s in e2e["steps"]] == list(range(1, 20)) and
            all(s["ok"] for s in e2e["steps"]) and all(m["governed"] for m in e2e["mutations"]) and
            len(e2e["mutations"]) >= 7 and h(strip(e2e, "digest", "authority")) == e2e["digest"] and
            e2e["real_world_integration"] == "NOT_IMPLEMENTED")

    # --- 38-42 signatures, module digests, disclosure, secrets --------------------------------------------------
    pbody2 = strip(proof, "signature_b64", "signer_public_key_b64")
    C.check("proof_signature", sig_ok(proof["signer_public_key_b64"], proof["signature_b64"], D["proof"], pbody2))
    mbody = strip(master, "signature_b64", "signer_public_key_b64")
    C.check("master_signature", sig_ok(master["signer_public_key_b64"], master["signature_b64"], D["master"], mbody)
            and master["signer_public_key_b64"] == proof["signer_public_key_b64"])
    C.check("master_matches_proof", master["modules"] == {k: v["sha256"] for k, v in proof["modules"].items()}
            and master["tests_failed"] == 0 and master["tests_passed"] == proof["test_run"]["passed"] > 0
            and master["attacks_contained"] == bench["contained"] and master["end_to_end_steps_ok"] is True)
    C.check("signing_key_disclosed_ephemeral", proof["signing_key"]["class"] == "EPHEMERAL"
            and "not a production trust root" in proof["signing_key"]["note"]
            and proof["signing_key"]["production_key"] == "NOT USED")
    st = proof["status"]
    C.check("honest_status", st["HARDWARE_ATTESTATION"] == "UNKNOWN" and st["REAL_WORLD_INTEGRATION"] ==
            "NOT_IMPLEMENTED" and st["HOSTED_SERVICE"] == "NOT_IMPLEMENTED" and st["MULTI_HOST_SCALE"] == "UNVERIFIED"
            and st["REAL_WORLD_ATTACK_VALIDATION"] == "NOT_PERFORMED" and
            set(st["capability_status"].values()) <= {"IMPLEMENTED", "TESTED", "VERIFIED", "REPRODUCIBLE",
                                                      "SIMULATED", "UNVERIFIED", "UNKNOWN", "NOT_IMPLEMENTED",
                                                      "UNCONTROLLED"})
    blob = "".join((d / n).read_text().lower() for n in manifest["files"] if n.endswith(".json"))
    C.check("no_key_material", not any(f in blob for f in FORBIDDEN))

    print(json.dumps({"bundle": str(d), "checks": len(C.checks), "passed": sum(c["ok"] for c in C.checks),
                      "problems": C.problems, "result": "INTACT" if not C.problems else "FAILED",
                      "detail": C.checks}, indent=2))
    return 0 if not C.problems else 1


if __name__ == "__main__":
    raise SystemExit(main())
