Skip to content

Stage-3 REQ-7: the Rust→Lean obligation exporter (QF_LIA + QF_BV) (#349) - #90

Merged
maxine-at-forecast merged 3 commits into
mainfrom
feature/5i5F-GMVf-stage-3-req-7-the-rust-to-lean-obligation-exporter-qf
Jun 24, 2026
Merged

Stage-3 REQ-7: the Rust→Lean obligation exporter (QF_LIA + QF_BV) (#349)#90
maxine-at-forecast merged 3 commits into
mainfrom
feature/5i5F-GMVf-stage-3-req-7-the-rust-to-lean-obligation-exporter-qf

Conversation

@maxine-at-forecast

Copy link
Copy Markdown
Collaborator

Stage-3 REQ-7 — the automated Rust→Lean obligation exporter, the reconstruction half's foundation. Closes #349 (+ #356, the faithfulness metatheorem). Child of the Stage-3 tree (umbrella xl #342 / gh #80; spec REQ-7 / AC-8).

What ships

  • forge/src/lean_smt_export.rs + the forge smt-export CLI: renders a per-clause obligation to the smt-dischargeable Lean goal (P_prod) ⟺ (P_ref), closing SmtDemo.lean's Tier-3 hand-translation gap. reference_normalize is the independent reference encoding.
  • lean/Thermite/SmtExport.lean — the exporter's verbatim output (golden-tested: the committed file IS forge smt-export's output), root-imported and lake-build kernel-checked.

The snag, and the sound workaround

cvc5's literal BitVec N reconstruction pulls sorryAx at the pinned lean-smt 7d1d8239 — every BitVec-typed by smt goal (even a pure comparison) bit-blasts through the upstream Smt/Reconstruct/BitVec/Bitblast.lean sorry (the z3-demotion.md wall). So the exporter renders QF_BV over a bounded-integer machine model (bvN var → Int with 0 ≤ x < 2^N; wrap op → % 2^N; unsigned cmp → Int cmp), which smt discharges via clean linear-arith reconstruction.

This is proven faithful, not asserted. lean/Thermite/BvModel.lean (#356) is a kernel-checked, Mathlib-free, core-BitVec-only metatheorem — tmInt_eq_toNat, frmInt_iff_frmBV, tv_equiv_faithful — proving the bounded-int model ⇔ BitVec semantics. So the render_bv_prop semantic faithfulness REQ-8 was to own is largely discharged; the residual narrows to the two string-emission legs.

Scope (honest)

Reconstruction-support = QF_LIA + the arithmetic/comparison QF_BV subset (+ - *, unsigned compares, logical connectives). The bitwise/shift/rotate subset has no clean Int encoding and hits the BitVec sorry — the exporter refuses it (SmtExportError, a named skip, never a silent mis-encode), so mix64's a^b^b==a and the rotate lemma stay solver-trusted (F-J). REQ-8's fragment-support check keys on exactly this split.

Verification (independently re-run by the orchestrator)

  • AC-8 ✅: all 3 exporter theorems (1 QF_LIA + 2 bounded-int QF_BV) #print axioms = [propext, Classical.choice, Quot.sound]no sorryAx despite the upstream Bitblast sorry being in the dep graph.
  • BvModel ✅: the 3 faithfulness theorems axiom-clean (lake build Thermite.BvModel, core-only, in lean-axiom-probe.sh).
  • forge smt-export golden matches the committed SmtExport.lean; full forge suite green (verus+z3+spine, no REQ-1..6 regressions); clippy -D warnings + rustfmt 1.95.0 clean; make doc-drift exit 0.

The 3rd commit is an orchestrator note in the design doc's decision record recording this as-built approach for REQ-8. AC boxes flip at G3 per stage-3 convention.

maxine-at-forecast and others added 3 commits June 23, 2026 08:33
Build the automated Rust→Lean obligation exporter that closes the Tier-3
hand-translation gap `lean/Thermite/SmtDemo.lean` left open. New
`forge/src/lean_smt_export.rs` renders a Thermite predicate `Expr` into a Lean
`Prop` and emits the translation-validation goal `(P_prod) ⟺ (P_ref) := by smt`
+ a `#print axioms` probe, over two fragments: QF_LIA scalar (over `Int`) and
QF_BV (over the range-bounded integer machine-model). `reference_normalize`
supplies the independent reference encoding; `forge smt-export [<file>]
[--out <path>]` is the CLI surface. The committed `lean/Thermite/SmtExport.lean`
is the exporter's verbatim output (golden-tested, root-imported, kernel-checked
by `lake build`).

AC-8: all three exported theorems (1 QF_LIA + 2 QF_BV) discharge `by smt` and
`#print axioms` ⊆ {propext, Classical.choice, Quot.sound} — no sorryAx, no Smt
oracle, no Lean.ofReduceBool.

Key finding (recorded in z3-demotion.md): at the pinned lean-smt rev every
`BitVec`-typed `by smt` goal — even a pure unsigned comparison — bit-blasts
through the upstream `Smt/Reconstruct/BitVec/Bitblast.lean` `sorry` and pulls
`sorryAx`. The reconstruction-supported QF_BV encoding is therefore the
bounded-integer machine-model (bv var → Int with 0 ≤ x < 2^N, wrap → `% 2^N`,
unsigned cmp → Int cmp), which is kernel-clean; the literal BitVec render (the
artifact REQ-8 replays) stays the documented residual.

Scope: exporter only (REQ-8 owns reconstruction default-on + the render_bv_prop
faithfulness obligation). No change to the REQ-1..6 bv route. AC checkboxes flip
at G3 per the stage-3 convention. Re-pinned cli.md + workspace.md (doc-drift
CURRENT).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Discharge the REQ-8 `render_bv_prop` faithfulness obligation in our OWN Lean spine,
without depending on lean-smt's (stalled, 18-mo-dormant) literal QF_BV reconstruction.

The exporter renders a `@bvN` clause over the bounded-integer machine-model (not
`BitVec N`, whose `smt` reconstruction bit-blasts through an upstream `sorry` — every
BitVec goal pulls sorryAx, and the root cause is lean-smt's `reconstructRewrite` total
stub + a partial `BV_BITBLAST_STEP`, so closing the one `eq_eq_beq` sorry is necessary
but not sufficient).

`lean/Thermite/BvModel.lean` proves the model faithful instead:
- `Tm`/`Frm` mirror the exporter's `render_term`/`render_prop` fragment arm-for-arm;
- `tmBV`/`frmBV` give the genuine fixed-width `BitVec N` semantics; `tmInt`/`frmInt`
  give the bounded-integer model the exporter emits (`% 2^N`, unsigned cmp as Int cmp);
- `frmInt_iff_frmBV`: the two denotations agree under the `toNat` valuation;
- `tv_equiv_faithful`: so the exporter's `by smt`-reconstructed int-model `(P_prod) ↔
  (P_ref)` certifies the genuine bit-vector clauses.

All three theorems are KERNEL-CHECKED, `#print axioms` ⊆ {propext, Classical.choice,
Quot.sound}, and Mathlib/Smt-FREE — so unlike `Thermite.SmtExport` this runs in CI via
`scripts/lean-axiom-probe.sh` (added as a build target + in-file `#print axioms`, the
SubstKit convention; promoting `tv_equiv_faithful` into the gated THEOREMS list is the
REQ-8/G3 trust-flip action). Combined with the exporter's int-model `↔`, a `@bv`
clause's truth is kernel-grounded end to end with no solver in the trust base for the
renderable fragment.

The Rust-emitter ⟷ Lean-AST correspondence stays inspection-tier (as for the whole
exporter). Completing lean-smt's literal QF_BV reconstruction remains an open UPSTREAM
task, no longer load-bearing for us.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ernel faithfulness (#349)

REQ-7 materially changed REQ-8's foundation, so record it in the decision
record for REQ-8 to inherit accurately:
- cvc5's LITERAL BitVec `by smt` reconstruction pulls sorryAx (the upstream
  Bitblast.lean sorry) — so the exporter renders QF_BV over a bounded-integer
  machine model (var→Int 0≤x<2^N, wrap→%2^N, unsigned cmp→Int cmp), which
  discharges axiom-clean. Verified on all 3 shipped theorems.
- Reconstruction-support = QF_LIA + the arithmetic/comparison QF_BV subset;
  bitwise/shift/rotate is REFUSED (SmtExportError) and stays solver-trusted
  (F-J) — mix64's xor/rotate clauses included. REQ-8's fragment check keys here.
- render_bv_prop faithfulness is largely DISCHARGED, not deferred: BvModel.lean
  kernel-proves the bounded-int model ⇔ BitVec semantics (axiom-clean). REQ-8's
  residual narrows to the two string-emission legs (#356).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@maxine-at-forecast
maxine-at-forecast merged commit 0e9c7b8 into main Jun 24, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant