Skip to content

feat(core): Add CoreSMT verification pipeline with incremental solver and diagnosis#475

Open
MikaelMayer wants to merge 195 commits intomainfrom
migrate-b3-smt-pipeline-core-to-core
Open

feat(core): Add CoreSMT verification pipeline with incremental solver and diagnosis#475
MikaelMayer wants to merge 195 commits intomainfrom
migrate-b3-smt-pipeline-core-to-core

Conversation

@MikaelMayer
Copy link
Contributor

@MikaelMayer MikaelMayer commented Feb 23, 2026

Problem

Strata Core's existing verifier generates all VCs upfront via symbolic execution, encoding each to a separate SMT file. This prevents incremental verification where solver state is maintained across statements.

Additionally, Core.ExpressionMetadata was Unit, discarding source location information and making it impossible to report accurate positions in verification failures.

Solution

Core Expression Metadata: Unit → SourceRange

Core.ExpressionMetadata is changed from Unit to Strata.SourceRange so that:

  • Source locations are preserved through the B3→Core→CoreSMT pipeline
  • Diagnosed failures can be converted back to B3 with accurate source positions

All code constructing Core expressions with () now uses SourceRange.none or a proper range. The SyntaxMono macro (eb[...]) gains a defaultMetadata field on MkLExprParams (defaults to Unit.unit for generic params, overridden to SourceRange.none for Core). TermType.toSMTString is extracted as a pure function to avoid duplication.

CoreSMT Verification Pipeline

An SMTSolverInterface with push/pop support enables incremental verification. A diagnosis engine splits failing conjunctions and checks each conjunct individually to identify which assertions cannot be proved or which covers are refuted.

B3 Verifier Migration

The B3 verifier now uses the CoreSMT pipeline: B3 expressions are converted to Core (preserving source locations), verified via CoreSMT, and diagnosed failures are converted back to B3 for display.

Changes

  • Core.ExpressionMetadata: UnitStrata.SourceRange
  • SyntaxMono macro: defaultMetadata field for type-appropriate metadata
  • TermType.toSMTString: extracted pure function to TermType.lean
  • isCoreSMT predicate, SMTSolverInterface, diagnosis engine, VCResult.diagnosis
  • B3 verifier migrated to CoreSMT pipeline
  • C_Simp/Verify.lean: csimpMetaToCore conversion (Unit → SourceRange)

Testing

All existing tests pass with the new pipeline.

MikaelMayer and others added 30 commits January 27, 2026 11:14
…or Func

- Added ToFormat for generic Func with proper constraints
- Added [ToFormat T.IDMeta] to Factory.lean section variables
- Removed unnecessary ToFormat instances from test files and Program.lean
- Removed custom Env.format function (now uses default ToFormat)
- Function bodies now display properly instead of showing <body>
- Resolved conflict in Factory.lean (Factory_wf moved to FactoryWF.lean in main)
- Applied rotate_left fix to FactoryWF.lean
- Modified testFuncDeclSymbolic to show functions capture variables by reference
- Function declared with n=10, then n mutated to 20, function uses n=20 at call time
- Proof obligation correctly shows result should be 25 (5+20), not 15 (5+10)
- Reverted Env.lean to main (custom scope formatting not needed)
…claration time

- Functions now capture variable values at declaration time, not by reference
- Free variables in function body are substituted with their current values from environment
- Test demonstrates: n=10 at declaration, n=20 after mutation, function uses n=10
- Proof obligation correctly shows result is 15 (5+10), not 25 (5+20)
…duplication

- Move generic Func structure to Strata/DL/Util/Func.lean
- Add PureFunc to Imperative, removing Lambda->Imperative dependency
- Fix funcDecl type checking to add function to type context
- Remove duplicate renameLhs/substFvar from ProcedureInlining
- Extract captureFreevars helper in StatementEval
- Refine getVars to exclude formal parameters for funcDecl
- Add type checking test for funcDecl
- Add WFfuncDeclProp structure in WF.lean checking input parameter uniqueness
- Add LFunc.type_inputs_nodup theorem in Factory.lean
- Add Function.typeCheck_inputs_nodup theorem in FunctionType.lean
- Add listMap_keys_map_snd helper lemma in StatementWF.lean
- Replace sorry in funcDecl case with complete proof
Copy link
Contributor Author

@MikaelMayer MikaelMayer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solid PR. The CoreSMT pipeline is well-structured with clean separation of concerns across State, IsCoreSMT, ExprTranslator, Diagnosis, StmtVerifier, and Verifier. The B3→Core→CoreSMT roundtrip with source location preservation is a meaningful improvement. A few issues to address before merging.

- Remove duplicate imports in StrataMain.lean
- Fix indentation of Value.const in StatementSemantics.lean
- Extract DiagnosedFailure types to CoreSMT.DiagnosisTypes to decouple
  Core.Verifier from CoreSMT.Diagnosis
- Remove unused TermType.toSMTString
- Remove unused mkCvc5Solver/mkSolverFromPath/mkSolverFromEnv helpers
- Simplify ProcedureReport.results from List (VerificationReport × Option Unit)
  to List VerificationReport
- Delete orphaned expected_incremental/ directory
Rename CoreSMT/DiagnosisTypes.lean → Core/DiagnosisTypes.lean and
move types to Strata.Core namespace, since they are general diagnosis
types not specific to the CoreSMT pipeline.
- Restore eraseTypes to preserve metadata (regression fix)
- Use normalizeExpr (erase types + metadata) in ProcedureInlining alpha-equiv
- Use LExpr.metadata in FromCore.exprFromCore instead of manual match
- Replace if-else op chains in FromCore with HashMap lookups
- Remove stale comment in B3/Verifier.lean
- Add sr abbrev in SMTEncoderDatatypeTest to reduce SourceRange.none noise
- Remove stale visibility comment in ProcedureInlining.lean
- Rename expected_interactive/ to expected_incremental/
- Make incremental a flag in run_py_analyze.sh; remove redundant skip
- Extract verifyIncremental/verifyBatch helpers in StrataMain.lean
- Replace _ with m in FromCore.exprFromCore pattern matches to clarify
  we're using the correct metadata (same as outer sr)
- Move VerificationReport/ProcedureReport from B3/Verifier to Core.Verifier
  since they're used in StrataVerify.lean (not B3-specific)
- Remove sr variable in FromCore.exprFromCore, use m from pattern directly
- Fix HashMap efficiency: map to functions taking SourceRange as argument
- Make --incremental a proper flag in run_py_analyze.sh (independent of laurel)
The --incremental flag now applies to whichever command is selected
(pyAnalyze or pyAnalyzeLaurel), rather than forcing pyAnalyzeLaurel.
The --incremental flag only works with pyAnalyzeLaurel, not pyAnalyze.
Updated script to error if --incremental is used without laurel.
Updated CI to call: ./run_py_analyze.sh --incremental laurel
- SMTEncoder.lean: genRecursiveAxioms metadata parameter
- LaurelToCoreTranslator.lean: all LExpr constructors
- SMTEncoderDatatypeTest.lean: all LExpr constructors, move sr abbrev before section
- SMT.lean: remove non-module imports (SolverInterface, State)
- Translate.lean: LExpr.fvar/op metadata from DDM annotations
Main changed tryReadPythonSource to return (String × String) instead of
(String × Lean.FileMap). Updated verifyIncremental/verifyBatch signatures
and use Lean.FileMap.ofString at call sites.
@MikaelMayer MikaelMayer marked this pull request as ready for review March 6, 2026 20:39
Extract SourceRange from expr.md (Laurel metadata) for literal constants
instead of using SourceRange.none.
@MikaelMayer MikaelMayer enabled auto-merge March 6, 2026 20:46
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.

2 participants