Pure evidence substrate for proof-carrying coherence promotion. No
promotion, no vault import, no status transition, no teaching-path
change; ADR-0218 stays Proposed.
- generate/proof_chain/certificate.py: frozen PromotionCertificate
(version/claim_form/premise ids+forms+statuses/entailment_trace/
engine_pin/decision/reason, canonical_json with sort_keys+compact
separators); build_certificate runs evaluate_entailment_with_trace
over entry_id-sorted premises; verify_certificate rebuilds from the
embedded forms and accepts iff byte-identical — tampered forms/claim/
trace/decision/reason/ordering/version all fail replay, structural
breakage fails closed as malformed_certificate.
- promotion_positive is necessary-not-sufficient: entailed over a
non-empty all-coherent recorded premise set; REFUTED/UNKNOWN/REFUSED
verify as themselves but are never positive; zero-premise tautology
certificates fail-closed non-positive in v1.
- engine_pin is recorded provenance; pin tampering is caught only via
caller-supplied expected_engine_pin (P3 must pass the lane SHA) —
limit pinned by dedicated tests.
- entail.py: docstring-only fix removing the incorrect ADR-0206
attribution (numbering collision); now cites ADR-0218. Zero behavior
change. generate_claims.py:74 still carries the label (serving-frozen
surface, flagged for follow-up).
- No xfail markers retire: every PR-A obligation binds to the P3
promoter, which must not exist before ratification. The certificate-
shaped halves of O1/O7 are proven for real in
tests/test_proof_chain_certificate.py (27 tests). ADR phasing bullet
and obligations docstring record the reconciliation.
Validation: certificate 27 passed; obligations 3 passed + 6 xfailed;
architectural invariants 61 passed (INV-21/INV-29 green, allowlists
unchanged); entail/builder/rules 61 passed; smoke files 95 passed.