core/docs/issues/proof-carrying-coherence-promotion.md
Shay e473f5b55f feat(teaching): ADR-0218 P3 — proof-carrying coherence promotion
The ratified capability, through the existing mutation owner only:

- teaching/proof_promotion.py — pure decider. Fresh-reads every premise AND
  the claim from the store (claim_entry_index; forms never proposer-supplied),
  strict status compares (no parse-defaulting), reading_certified must be the
  boolean True, engine certification via the pinned deductive engine,
  proposer_payload accepted and provably never read (del before use; poisoned-
  mapping test), certificate digest emitted for D4 trace-hash folding. Zero
  mutation; zero vault.store calls; zero status writes (proven with the
  INV-21/INV-29 detectors themselves).
- vault/store.py::apply_certified_promotion — the single transition site.
  Independently re-verifies: byte-for-byte replay under DEDUCTIVE_ENGINE_PIN,
  promotion_positive, live claim form/reading/status cross-checks, live
  premise form/reading/status cross-checks (staleness refuses). Fabricated or
  tampered certificates flip nothing; authority is live store state plus
  recomputation, never the artifact.
- generate/proof_chain/engine_pin.py — DEDUCTIVE_ENGINE_PIN mirrors the
  deductive_logic_v1 lane SHA; sync pinned by AST test against
  scripts/verify_lane_shas.py.
- Consistency fix found in lookback: both promotion sites now stamp
  epistemic_state alongside epistemic_status (the ADR-0148 site left the
  stored state tag stale; recall recomputed it, but the stored key lied).

Obligations: all six strict-xfail markers retired and live (O1/O2
strengthened to prove the transition through the vault owner); the
module-existence pin deleted per its own docstring; the two remaining
honesty pins kept. INV-21 allowlist unchanged; INV-29 allowlist unchanged
({vault/store.py}); INV-29's 29c visibility floor raised 2 -> 3 to cover the
new site.

No runtime turn path calls promotion; the deterministic demo is PR D.

Validation: new suite 49 passed; obligations 8 passed (0 xfail remaining);
invariants 66 passed; certificate 27 passed; 0148 6 passed; epistemic 20
passed; smoke files green; lane SHAs verified.
2026-06-11 17:02:45 -07:00

234 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Issue — Proof-carrying coherence promotion (the logical arm of ADR-0021's v2 gap)
**Status:** Capability landed — [ADR-0218 ratified 2026-06-11](../decisions/ADR-0218-proof-carrying-coherence-promotion.md).
PR A shipped the obligations + INV-29; PR B the pure evidence substrate
(`generate/proof_chain/certificate.py`); PR C (post-ratification) the P3
promoter: `teaching/proof_promotion.py` (pure decider, fresh-read store
state, proposer payload provably unread) +
`VaultStore.apply_certified_promotion` (independent re-verification, the
only transition site — INV-21/INV-29 allowlists unchanged). All strict-xfail
obligations are retired and pass live. No runtime turn path calls promotion
yet; the deterministic demo is PR D.
**Raised:** 2026-06-11
**Surface:** `teaching/epistemic.py`, `teaching/review.py`, the deductive
engine (`deductive_logic_v1`), `vault/store.py`, INV-21 one-mutation-path
**Governing ADR:** [ADR-0021 — Epistemic Grade Policy](../decisions/ADR-0021-epistemic-grade-policy.md)
(this issue specifies one arm of that ADR's *"Named gap (v2 work, explicit)"*)
**Requires before any code:** a ratified ADR (provisional **ADR-0218**, number
to be confirmed against in-flight branches — current max committed is ADR-0217)
---
## TL;DR
The position paper §3.4 and the `EpistemicStatus` docstring both implied a
stronger promotion story than the code delivers. Two things were corrected in
the same change that raised this issue:
1. **Doctrine precision (paper §3.4).** "Promotion requires a *curator-mediated*
coherence judgment" over-states a *necessity*. The doctrine (ADR-0021 §3) only
requires that promotion be a function of **coherence with the reviewed field**.
For the subclass of claims that are *deductively entailed* by an
already-`COHERENT` premise set, the entailment proof **is** that coherence
judgment and can be machine-certified by CORE's sound deductive engine — no
human re-deciding settled logic.
2. **Code honesty (`teaching/epistemic.py`).** The enum docstring claimed
transitions are *"computed from coherence with the existing reviewed field."*
They are not computed; `review_correction` carries the status as a
curator-supplied input. The docstring now says so.
**This issue specifies the missing capability**: a *proof-carrying promotion*
path that lets a `SPECULATIVE` claim become `COHERENT` **iff** it is deductively
entailed by an already-`COHERENT` premise set, with the proof chain as the audit
artifact. It is **designed-but-unwired**. Building it touches the single most
protected boundary in the system (INV-21), so it is ADR-gated.
---
## 1. Context — what is true today
| Claim | Reality in code |
|---|---|
| "Coherence is the only admission signal." | True and load-bearing (ADR-0021 §3). Source/credentials/own-output carry no standing. |
| "Transitions are computed from coherence." | **False today.** `teaching/review.py::review_correction` checks identity-override + emptiness, then sets `outcome`; `epistemic_status` is a **passed-in parameter** (default `SPECULATIVE`). No coherence computation runs. |
| "A sound deductive engine exists." | True. `deductive_logic_v1` is sound + complete for propositional entailment, ROBDD-canonical (ADR-0201/0202), independently oracle-checked, holdout wrong=0, SHA-pinned. |
| "The engine certifies promotions." | **False today.** The deductive engine and the binding-graph proof DAG (ADR-01320135) have **zero consumers** in the teaching/promotion path. |
| "Only one path writes the reviewed field." | True (INV-21). Every vault writer is allowlisted in `tests/test_architectural_invariants.py::TestINV21OneMutationPath`. |
ADR-0021 already anticipated this exact gap. Its *"Named gap (v2 work,
explicit)"* says v1 is "honest about the gap: … the coherence judgment behind a
tag is still curator-mediated, and the architecture commits to closing that gap
on a stated path." Its v2 sketch is **geometric** (`cga_inner(claim, field) ≥
τ`). This issue is the **logical** complement to that sketch.
## 2. Two arms of one goal — do not conflate them
ADR-0021's "structural coherence metric" successor to curator mediation has two
distinct mechanizations, and they catch different failures:
- **Geometric arm (ADR-0021 v2 sketch).** `cga_inner(claim_versor, field) ≥
τ_admit` and no reviewed relation with `cga_inner ≤ τ_reject`. Detects
*contradiction with / proximity to* the reviewed field. Metric, continuous,
threshold-tuned.
- **Logical arm (this issue).** The claim is *deductively entailed* by a
`COHERENT` premise set, certified by the sound engine. Detects
*derivability from* the reviewed field. Combinatorial, exact, no threshold.
These are complementary, **not** substitutes. The field metric does not perform
entailment — logic is combinatorial, not metric. A claim can sit far from any
existing versor (low geometric agreement) yet be a rigorous deductive
consequence of reviewed premises, and vice-versa. The logical arm is the one the
already-built engine can deliver soonest, because the deductive engine already
exists and is wrong=0; it just is not wired to the promotion path.
## 3. Scope — what proof-carrying promotion IS and IS NOT
**IS:**
- A path that promotes `SPECULATIVE → COHERENT` **only** when a sound proof
derives the claim from an exclusively-`COHERENT` premise set.
- Proof-carrying: the promotion artifact embeds the proof chain (binding-graph
DAG / ROBDD witness) so replay can re-verify it deterministically.
- Audit-first: the proof is the justification; no source, credential, or
confidence score appears anywhere in the decision.
**IS NOT:**
- Not promotion of the system's own *asserted* output (a generated surface, a
guess). That remains forbidden — promoting it and re-feeding it is the
fabrication loop ADR-0021 and CLAUDE.md exist to prevent.
- Not a source-trust fast-path. "Came from a trusted place" never promotes
anything. INV-21's prohibition on "a fast-path for known-good sources" stands.
- Not a relaxation of `wrong=0`. It adds a *narrower* admission, gated by a
sound proof, not a *looser* one.
- Not the geometric arm. That is separate ADR-0021 v2 work.
## 4. The crux — the reading hazard, not the deduction
The deduction is mechanical and already wrong=0. **The fallible step is the
reading**, and the design must put the whole defensive burden there:
1. **Translation faithfulness.** Natural-language claim → propositional /
binding-graph form. A sound proof over a *misread* premise is a sound proof of
the wrong thing. This is the live `wrong=0` hazard surface (the self-check is
*soundness*, not *correctness* — there is no gold to compare against).
2. **Premise grounding.** Every premise fed to the engine must *already* be
`COHERENT` in the vault — verified by status, not assumed. A premise that is
`SPECULATIVE`/`CONTESTED` must make the proof inadmissible for promotion.
3. **Premise selection / closure.** The premise set must be explicit and
bounded; the proof must not silently pull in unreviewed claims.
**Design consequence:** proof-carrying promotion does **not** remove human
review — it *relocates* it. The human (or a separately-ratified structural
check) certifies the **reading** (13); the engine certifies the **entailment**.
The autonomy is only ever as safe as the faithfulness of the reading, and the
design must make an unfaithful reading *fail closed* (refuse to promote), never
fall through to admission. This mirrors why today's `idle_tick` continuous-
learning loop is proposal-only → pending-HITL even for *determined* facts.
## 5. Where it touches the architecture
- **INV-21 one-mutation-path (highest risk).** Promotion writes the reviewed
field. Any new promoter must be added to the `TestINV21OneMutationPath`
allowlist *with documented justification*, or — preferably — routed through the
existing reviewed write path so no new mutation site is created. The CI failure
is the prompt, not a thing to route around. A proof-carrying promoter that
bypasses the single path silently re-introduces the backdoor the invariant
forbids.
- **`teaching/review.py`.** Either `review_correction` gains an
entailment-certification branch, or a sibling reviewed-path function is added
that consumes a proof artifact. Must not become a *parallel* learning path
(CLAUDE.md: "Do not create a parallel correction/learning path").
- **`teaching/epistemic.py`.** No enum change needed; `COHERENT` already is the
target. The transition *function* is what gains a sound-proof input.
- **Deductive engine (`deductive_logic_v1`) + binding-graph DAG (ADR-01320135,
ROBDD ADR-0201/0202).** First real consumer of the proof_chain substrate.
proof_chain Phase 2 (binding-graph wiring, acyclicity refusal, modus_ponens)
is a prerequisite — today only `transitive` (ADR-0083) actually executes.
- **`vault/store.py`.** Reads premise `epistemic_status`; the promoter must query
`min_status=COHERENT` for premises and refuse if any premise is not admissible.
- **`core/cognition/trace.py`.** The proof artifact and resulting status fold
into `trace_hash` (ADR-0021 §Schema impact already requires status in the
hash). Replay must re-verify the proof bit-for-bit.
## 6. Trust boundary statement (required by CLAUDE.md)
Proof-carrying promotion consumes (a) a premise set drawn from the vault and (b)
a reading of a candidate claim into propositional form. The **untrusted** input
is the *reading* (it may originate from user text or a model-style proposer). The
boundary rule: **the reading is data, never authority.** The promoter must:
- Refuse promotion unless every premise resolves to a stored `COHERENT` entry.
- Refuse promotion unless the proof is produced by the pinned sound engine and
re-verifies on replay.
- Never let a proposer-supplied "proof", "status", or "confidence" field
influence the decision (echo-and-ignore, as the epistemic-truth-state demo
does for `proposed_state`).
- Fail closed: any unresolved premise, any reading ambiguity, any engine refusal
→ no promotion, claim stays `SPECULATIVE`.
## 7. Falsification / test obligations
Per CLAUDE.md *"Schema-Defined Proof Obligations"* — every claimed guarantee
must have a test that **fails loudly** when the guarantee is violated. A test
that passes under a broken implementation is decoration. Required failing-tests:
1. **Entailed-from-COHERENT promotes.** A claim genuinely entailed by `COHERENT`
premises is promoted, and the proof artifact re-verifies on replay.
2. **Non-entailed does NOT promote.** A claim merely *consistent* with (but not
entailed by) the field stays `SPECULATIVE`. Mutating the proof to a
non-sequitur must flip the test red.
3. **Premise-status gate.** If any premise is `SPECULATIVE`/`CONTESTED`/
`FALSIFIED`, promotion is refused. Silently downgrading the premise check must
make this test fail.
4. **Reading-hazard fail-closed.** A deliberately misread premise (right symbols,
wrong proposition) must NOT promote — the reading certification must catch it.
5. **No proposer authority.** A proposer-supplied proof/status/confidence field
is ignored; promotion decision is byte-identical with and without it.
6. **INV-21 intact.** The one-mutation-path allowlist test still passes; if a new
write site was added, its justification is present and the test references it.
7. **Determinism.** Double-run promotion is byte-identical; `trace_hash` includes
the proof; replay re-verifies.
8. **wrong=0 preserved.** The full serving + deductive holdout lanes stay
wrong=0 after the path is wired.
## 8. Phased plan
- **P0 — Doc + honesty (this change, no feature).** Paper §3.4 corrected; enum
docstring de-claimed; this issue written. ✅
- **P1 — Reading contract (spec).** Define the NL→proposition reading contract
and its certification surface (what makes a reading "faithful enough" to gate
on). This is the hard, hazard-bearing part; it gets its own design pass and may
itself stay curator-mediated initially.
- **P2 — proof_chain Phase 2 prerequisite.** Wire the binding-graph DAG as the
first consumer (acyclicity refusal, modus_ponens) so a proof artifact exists in
a replayable form. (Already a deferred item; this issue is a forcing function.)
- **P3 — Proof-carrying promoter (behind ADR-0218).** Add the
entailment-certification branch to the *single* reviewed write path. Premise
status gate + fail-closed reading gate + proof-in-trace. All §7 tests green.
- **P4 — Geometric arm (separate, ADR-0021 v2).** Out of scope here; tracked so
the two arms are not conflated.
## 9. Proposed ADR-0218 must rule on
- Whether proof-carrying promotion extends the existing reviewed path or is
allowlisted as a new INV-21 write site (strong preference: extend, don't add).
- The reading-certification bar for P1 (curator-certified reading vs. a
structural reading check) and whether P3 ships with reading still
curator-mediated (entailment automated, reading human) as the honest first cut.
- The exact admissibility predicate: premises ⊆ `COHERENT`, proof from pinned
engine, replay re-verifies, fail-closed on any gap.
- Trace-hash composition for the proof artifact.
## 10. Explicit non-goals
- Geometric coherence admission (`cga_inner ≥ τ`) — ADR-0021 v2, separate.
- Promotion of generated/asserted output — permanently forbidden.
- Any source-authority or confidence-weighted promotion — permanently forbidden.
- Relaxing `wrong=0` or the non-hardening invariant — out of question.
## 11. Acceptance criteria for closing this issue
This issue is closed when **either** (a) ADR-0218 is ratified and P3 lands with
all §7 tests green and wrong=0 preserved, **or** (b) the architect rules the
logical arm is not worth wiring and records that decision — in which case paper
§3.4 must be amended again to drop the "specified but not yet wired" forward
reference and state plainly that promotion is curator-mediated by design.