karpal-verify
External prover bridge for the Karpal ecosystem.
karpal-verify is Karpal's external verification foundation crate. It introduces:
- a backend-agnostic proof obligation IR
- reusable algebraic signatures for trait-level law generation
- grouped obligation bundles for Semigroup / Monoid / Group / Semiring / Ring / Lattice laws
- exporters for SMT-LIB2, Lean 4, and generated Kani harnesses
- structured Lean module/theorem metadata for a richer Lean bridge
- Lean import/prelude bridging for module imports and symbol aliases
- Lean project/package scaffolding for generated modules
- project-aware Lean execution planning via
lake env leanorlake build - Kani invocation planning via
cargo kani --harness <name> - artifact writers and dry-run invocation plans for external tools
- runner abstractions, backend-specific verification policies, and basic SMT result parsing
- reporting types that attach execution outcomes and certificates back to obligations
- session/orchestration helpers for build → run → report flows
- report serialization helpers for CI-friendly JSON / Markdown summaries
#[export_obligations]macro re-export backed by thekarpal-verify-derivecompanion crate- GPU compute obligation builders for Metal/MSL-style kernel contracts
- optional amari-flynn integration for statistical contracts, Monte Carlo law-bound checks, and probabilistic contract macros
- an explicit external trust boundary for importing certificates back into Rust
What's inside
Proof obligations
Obligation captures a law to be discharged by an external backend:
use ;
let assoc = associativity;
Algebraic signatures
AlgebraicSignature lets exporters and higher-level integrations refer to
semantic roles like combine, identity, inverse, add, mul, meet,
and join instead of duplicating raw symbol strings:
use ;
let sig = group;
let obligation = left_inverse_in;
assert_eq!;
Obligation bundles
ObligationBundle packages related laws together so callers can generate and
export whole verification batches from one semantic signature:
use ;
let sig = monoid;
let bundle = monoid;
assert_eq!;
SMT-LIB2 export
use ;
let obligation = commutativity;
let smt = export_smt_obligation;
assert!;
Lean 4 export
use ;
let obligation = associativity;
let lean = export_lean_module;
assert!;
let structured = export;
assert_eq!;
You can also drive the Lean prelude explicitly when a module needs imports or raw IR symbols need stable Lean-facing aliases:
use ;
let obligation = associativity;
let module = export_module_with_prelude;
assert!;
assert!;
Batch export APIs
use ;
let sig = group;
let bundle = group;
let smt_scripts = export_smt_bundle;
let lean_module = export_lean_bundle;
let lean_export = export_lean_bundle_structured;
assert_eq!;
assert!;
assert_eq!;
Artifact writing and dry runs
With the std feature, karpal-verify can write export artifacts to disk and
prepare dry-run command plans for solver / Lean invocation. Lean plans can also
run in project-aware mode through lake env lean or whole-package lake build
from the generated artifact root:
use ;
let sig = monoid;
let bundle = monoid;
let layout = new;
let batch = dry_run_bundle_artifacts;
assert_eq!;
assert!;
assert!;
Use LeanDriver::LakeEnv when you want lake env lean lean/<Module>.lean, or
LeanDriver::LakeBuild when you want package-aware target builds through
lake build <Module>. Kani harness plans are generated beside SMT and Lean
artifacts under the artifact layout's kani/ directory.
Trait-to-obligation macro
karpal-verify re-exports the Rust-idiomatic companion proc-macro crate
karpal-verify-derive, so callers can write explicit obligation metadata next
to a Rust item:
use export_obligations;
;
let bundle = karpal_obligation_bundle;
assert_eq!;
Supported families currently include semigroup, monoid, group,
semiring, ring, and lattice.
GPU compute obligations
GPU-oriented consumers can build ordinary ObligationBundle values for
Metal/MSL-style contracts and export them through the same SMT, Lean, and Kani
paths:
use ;
let bundle = metal_kernel
.with_buffer_alignment
.with_workgroup_divisibility
.with_dispatch_limit
.with_kernel_determinism
.into_bundle;
assert_eq!;
Execution model
VerifierRunner abstracts over dry-run and local process execution:
use ;
let plan = InvocationPlan ;
let result = DryRunner.run;
assert_eq!;
For SMT backends, parse_smt_status() recognizes sat, unsat, and unknown,
while parse_smt_output() also extracts simple model / :reason-unknown
information. Lean runs now also support parse_lean_output(stdout, stderr),
which captures structured diagnostics and theorem-name hits from Lean / lake
messages. Reporting then maps those diagnostics back onto exported Lean theorem
metadata instead of relying only on raw obligation names. Successful results can
be turned into lightweight certificates.
Reporting layer
VerificationReport attaches artifact paths, execution results, and generated
certificates back to each obligation in a bundle:
use ;
let sig = semigroup;
let bundle = semigroup;
let artifacts = dry_run_bundle_artifacts;
let report = dry_run_report;
assert_eq!;
assert!;
assert!;
Verification session orchestration
For a higher-level build → run → report flow, use VerificationSession or the
one-shot verify_bundle(...) helper:
use ;
let sig = semigroup;
let bundle = semigroup;
let report = verify_bundle
.expect;
assert_eq!;
VerificationSession::verify_with_ci_outputs(...) also writes JSON / Markdown
summaries directly beside generated artifacts. When a Lean module report is
present it also writes a *.lean-diagnostics.json sidecar containing module-
level diagnostics, theorem failure refs, and per-obligation Lean diagnostic
groupings. The main JSON / Markdown summaries now cross-link both that sidecar
and the generated Lean manifest path, and the Lean manifest now links back to
those CI-oriented report files as well. The serialized report JSON, Lean
manifest JSON, and Lean diagnostics sidecar all now include explicit
schema_version markers. Lean artifact batches now also carry structured
theorem metadata, prelude/import metadata, generated package metadata, and
write a small typed Lean manifest model alongside the module source plus
lakefile.lean / lean-toolchain scaffolding at the artifact root.
amari-flynn statistical integration
Enable the optional amari feature when you want to layer statistical
verification on top of the obligation IR:
= { = "0.5.0", = ["amari"] }
This exposes:
verify_rare_event(...)for Monte Carlo checking of law-violation predicatesStatisticalBound/StatisticalVerificationfor probability bounds, event classification, and Karpal tier mappingprecondition_obligation_for(...),postcondition_obligation_for(...),concentration_obligation_for(...), andexpected_value_obligation_for(...)for bridging Karpal obligations into amari-flynn SMT proof obligations- re-exported
#[prob_requires(...)],#[prob_ensures(...)], and#[ensures_expected(...)]macros for probabilistic contract helpers
use ;
let obligation = commutativity;
let verification = verify_rare_event;
assert_eq!;
This gives karpal-verify a concrete bridge for the roadmap's three-tier
story:
- Impossible → type-level / zero-probability exclusion
- Rare → amari-flynn statistical bounds over violating events
- Emergent → behavior that remains possible and therefore observable
For bundle-level summaries, three_tier_report(...) combines declared
obligation tiers, amari statistical evidence, and successful external
verification results into a single aggregate report with JSON / Markdown
rendering helpers.
Schema compatibility
Current serialized verification artifacts use schema version 1.
Version 1 guarantees:
- a top-level string
schema_version - stable existing field names within the
1.xline - additive evolution via new optional fields only
- nested
report_filesobjects also include their ownschema_version
Consumers should accept schema_version == "1", ignore unknown optional
fields, and treat a future schema bump as a breaking parser boundary. See
docs/dev/verification-schema-versioning.md for the fuller compatibility
policy.
Imported trust markers
External evidence does not silently become a Karpal proof witness.
Certificates can also carry provenance like backend version, obligation digest,
and artifact path. Crossing the boundary into Proven<P, T> remains explicit
and unsafe:
use ;
use ;
let cert = new;
let externally_checked =
unsafe ;
let _: = unsafe ;
Current scope
This crate now provides the external-verification foundation for Karpal:
- obligation modeling
- SMT-LIB2 export
- structured Lean 4 export, project scaffolding, and project-aware execution
- CI/report artifact generation with schema-versioned JSON / Markdown outputs
- explicit trust-model types
- optional amari-flynn statistical integration for rare-event bounds and probabilistic contract helpers
The core roadmap work for karpal-verify is now implemented: obligation IR,
SMT/Lean export, artifact/report/session orchestration, optional amari-flynn
integration, and CI-oriented three-tier summaries. Future work can deepen that
coverage across more derive and trait workflows, but the external verification
foundation is now in place.
License
AGPL-3.0-or-later