CAIN-42 BFT clean-room judge (ZERO CAIN imports; stdlib + `cryptography`).

Input: what each replica claims it committed (exported certificates) + the pinned membership.
It re-derives from the PBFT rules alone (Castro & Liskov 1999, restated in BFT_PROTOCOL_SPEC.md):

  R1  digest binding   request_digest == SHA256(canonical {"op","req_id","client"} of the PRE_PREPARE payload)
  R2  primary          PRE_PREPARE sender == sorted(members)[view % n], valid Ed25519 under the PINNED key
  R3  prepared         |{pre_prepare sender} U {PREPARE senders}| >= 2f+1, all distinct pinned members,
                       each PREPARE for the same (view, seq, digest), each signature valid
  R4  committed        >= 2f+1 COMMITs from distinct pinned members for the same (view, seq, digest), valid sigs
  R5  agreement        no two replicas hold committed certificates for one seq with different digests
  R6  integrity        a replica's commit_index prefix 1..k has a valid certificate for every seq (no gaps)

Signature rule (wire spec): Ed25519 over the UTF-8 hex of SHA256(canonical JSON of the signing payload
{msg_type, sender_id, cluster_id, view, sequence, request_digest, payload, epoch, nonce,
timestamp rounded to 4 dp, engine_version}). Canonical JSON = sort_keys, separators (",", ":"),
default=str. A key carried INSIDE a message is never used.

It does not trust the engine's own safety report or any "valid" flag. Same-project and same-author as the
vector harness; written from the spec, not by importing the engine.
