Commit graph

2 commits

Author SHA1 Message Date
Shay
e1e8426d97 feat(verified): P1-C — split bound_slots_digest into a separate VERIFIED obligation
Proof-object hardening before any serving wiring (review of #663): the "from the
stated quantities" obligation is now THREE separable digests, not folded into
derivation_digest — for replay, audit, and failure localization.

core/epistemic_disclosure/verified_contract.py:
- VerificationProof gains bound_slots_digest (the answer binds to a STATED slot — the
  asked unknown — not a phantom), between derivation_digest and back_substitution_digest.
- VerificationObligation gains requires_bound_slots (VERIFICATION_OBLIGATION strict);
  evaluate_verification adds the REASON_NO_BOUND_SLOTS check.

evals/constraint_oracle/verified_producer.py: populates bound_slots_digest from
unknowns_signature + query_signature + the bound solution, ONLY when the asked unknown
is in the solution (empty for a phantom answer).

A complete derivation does NOT imply the answer bound to a declared slot, so the two are
distinct obligations: test_derivation_digest_alone_is_insufficient_without_bound_slots
proves it (relaxing requires_bound_slots is what admits the gap — load-bearing).

All 7 real r2_gold 'solved' problems still VERIFY (bound_slots populated); wrong=0.
Contract+producer suites 106/0; smoke 90/0. Still off-serving.
2026-06-08 17:04:45 -07:00
Shay
ec7c680cfc feat(epistemic-disclosure): P1-A — the VERIFIED contract + meaningful-fail tests
Defines what it MEANS for a result to earn DisclosureClaim.VERIFIED /
EpistemicState.VERIFIED — the soundness≠correctness gate the whole VERIFIED lane
rests on. Contract ONLY: no producer, no reader, no solver, no serving, no
verify.py, no verified_serving_enabled, no claim emission in any serving path.

core/epistemic_disclosure/verified_contract.py:
- VerificationObligation — the declarative contract (4 load-bearing flags);
  VERIFICATION_OBLIGATION is fully strict.
- VerificationProof — the replayable proof SHAPE P1-B+ will fill (two reads kept
  separate: distinct lineages for independence, matching digests for convergence).
- evaluate_verification(proof, *, limitation, obligation) -> VerificationResult —
  refuse-preferring: VERIFIED only if EVERY obligation survives.
- disclosure_for_verification(result) — the ONLY sanctioned route to
  (EpistemicState.VERIFIED, DisclosureClaim.VERIFIED); anything else -> UNDETERMINED/NONE.

The mechanism that makes the lane safe: VERIFIED requires TWO INDEPENDENT reads
(distinct lineages) that CONVERGE on one canonical structure. A faithful solve of a
WRONG read is caught because the independent read disagrees (back-substitution alone
cannot catch a read error); "same answer twice" is rejected as not independent.
Neither gold-agreement nor no-refusal nor a second solver over one read can verify.

15 tests, all non-vacuous. THE central test rejects a faithful solve of a wrong read;
one proves the wrong-read obligation is load-bearing (relax it -> poison slips the
check); the full chain composes proof -> contract -> (VERIFIED, VERIFIED) -> P0-3
DISCLOSE, and the poison degrades to COMMIT. Off-serving; smoke 90/0.
2026-06-08 16:20:19 -07:00