Skip to content

feat(codegen): Kani harnesses for generated-code AADL contract preservation#224

Merged
avrabe merged 3 commits into
mainfrom
feat/v0.10.x-kani-codegen-contracts
May 16, 2026
Merged

feat(codegen): Kani harnesses for generated-code AADL contract preservation#224
avrabe merged 3 commits into
mainfrom
feat/v0.10.x-kani-codegen-contracts

Conversation

@avrabe
Copy link
Copy Markdown
Contributor

@avrabe avrabe commented May 14, 2026

Summary

This PR adds spar's Logika-equivalent strategy for generated-code correctness: instead of importing a new prover language, three Kani bounded model-checking harnesses give machine-checked proofs that each codegen pass preserves the source AADL contract.

  • prove_thread_period_preserved — for any Period p ∈ (0, 1_000_000_000] ns, the emitted dispatch-metadata string round-trips back to exactly p (no truncation, no off-by-one). Uses kani::any() over the full nanosecond range; kani::assume(period_ns > 0 && period_ns <= MAX_PERIOD_NS).
  • prove_port_direction_preservedOut source maps exclusively to a WIT setter; In sink to a getter; a well-formed Out→In connection always produces a complementary setter+getter pair; same-direction features never produce a complementary pair. Proves the AADL §9 directionality contract over all direction combinations.
  • prove_access_right_preservedAccess_Rights = Read_Only never produces &mut in the generated access shim; Read_Write always does. Proves read-only enforcement at the Rust type level.

Wire-up

  • crates/spar-codegen/tests/kani_contracts.rs — three #[cfg(kani)] #[kani::proof] harnesses
  • crates/spar-codegen/Cargo.tomlkani-harnesses feature flag (no-op at runtime; enables cargo build -p spar-codegen --features kani-harnesses for CI compilation gating)
  • .github/workflows/ci.yml — CI Kani job extended to run each harness by name
  • artifacts/requirements.yamlREQ-KANI-CODEGEN-001 (implemented, tags: codegen/kani/verification/v0100/safety)
  • artifacts/verification.yamlTEST-KANI-CODEGEN (passing, satisfies REQ-KANI-CODEGEN-001)

Design note

Kani cannot symbolically construct SystemInstance values (they embed la_arena::Idx handles requiring a live arena). Following the pattern established in kani_codegen.rs and kani_solver.rs, each harness models the pure functions the codegen calls and asserts the invariant that pass must satisfy. Any divergence between the Kani model and production would be caught by the existing unit + golden tests.

Test plan

  • cargo build -p spar-codegen --features kani-harnesses — compiles clean
  • cargo test -p spar-codegen — 19 unit tests pass, harness files load without error
  • cargo kani --tests -p spar-codegen --harness prove_thread_period_preserved (CI)
  • cargo kani --tests -p spar-codegen --harness prove_port_direction_preserved (CI)
  • cargo kani --tests -p spar-codegen --harness prove_access_right_preserved (CI)
  • rivet validate — no new errors (pre-existing YAML parse issue at verification.yaml:1648 is unrelated)

🤖 Generated with Claude Code

…vation

Add three #[kani::proof] harnesses in crates/spar-codegen/tests/kani_contracts.rs
that prove each codegen pass preserves the AADL source contract (spar's
Logika-equivalent strategy: machine-checked proofs on the generated-code path).

- prove_thread_period_preserved: for any Period p in (0, 1_000_000_000] ns,
  the emitted dispatch-metadata string round-trips back to exactly p (no
  truncation, no off-by-one)
- prove_port_direction_preserved: Out→In connections produce complementary
  WIT setter+getter pairs; same-direction connections never produce a
  complementary pair (AADL §9 directionality contract)
- prove_access_right_preserved: Access_Rights = Read_Only never produces
  &mut in the generated access shim; Read_Write always does (type-level
  read-only enforcement)

Wire-up: add kani-harnesses feature flag to spar-codegen/Cargo.toml; extend
CI Kani job to run each harness explicitly; add REQ-KANI-CODEGEN-001 +
TEST-KANI-CODEGEN to artifacts YAML.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@avrabe avrabe enabled auto-merge (squash) May 14, 2026 17:17
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 15, 2026

Rivet verification gate

14/14 passed

count
Passed 14
Failed 0
Skipped (no steps) 0

Filter: (and (= type "feature") (or (has-tag "v093") (has-tag "v0100")))

Failed artifacts

(none)

Updated automatically by tools/post_verification_comment.py. Source of truth: artifacts/verification.yaml.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 16, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@avrabe avrabe merged commit 5b603ec into main May 16, 2026
17 of 18 checks passed
@avrabe avrabe deleted the feat/v0.10.x-kani-codegen-contracts branch May 16, 2026 09:35
avrabe added a commit that referenced this pull request May 20, 2026
v0.10.0 ships:

**Mermaid emission (M1 + M2 + M3)**
- spar-mermaid foundation crate with `emit_flowchart` (#220)
- `spar emit --format mermaid` CLI subcommand (#222)
- `emit_class_diagram` + `emit_requirement_diagram` + matching CLI
  flags `--format mermaid-class` / `mermaid-req` (#228)

**Soundness deepening**
- Lean 4 sorry-free proofs of end-to-end latency monotonicity and
  ARINC 653 partition isolation, alongside the pre-existing RTA / EDF /
  Network Calculus proofs (#223)
- Kani BMC harnesses on generated-code AADL contract preservation
  (thread Period, port Direction, bus access right) — spar's
  Logika-equivalent strategy for verified codegen (#224)

**Safety analysis**
- EMV2 error-propagation traversal across the AADL connection graph
  (closes the #1 gap vs OSATE/HAMR in safety-case reviews) (#225)

**Verification infrastructure**
- Rivet-driven verification gate that executes every artifact's
  `fields.steps[].run` commands and posts a sticky PR comment with
  pass/fail counts and failed artifact IDs (#221)
- Workflow tuning: gate timeout 30→60 min for future Mathlib-heavy
  workloads; TEST-PROOF-* stay on sorry-grep until lake cache lands
  (#227, #229, #230)

**Chore**
- Pruned stale dev artifacts (.playwright-mcp logs + dashboard-render
  PNGs) and tightened gitignore (#226)

Bumps Cargo.toml + vscode-spar/package.json from 0.9.3 → 0.10.0.
The release workflow's `check-versions` job enforces tag/Cargo/vsix
agreement, so these must move together with the v0.10.0 tag push.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
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