Phase 1 — semantics doc
docs/002. hsmc-semantics-formal.md
Phase 2 — deterministic execution journal
hsmc/src/journal.rs (TraceEvent, JournalSink, ActionKind)
hsmc-macros: __chart_journal! emission at every observable site
(entry/exit/action/transition/timer arm-cancel-fire/during/emit/
event delivery/terminate). Per-state during count helpers, stable
chart-hash via FNV-1a. Action observation moved out of run_action
and into call sites so ActionKind is accurate.
Public API on the generated machine: journal(), take_journal(),
clear_journal(), CHART_HASH.
Phase 3 — verification crate (Creusot scaffolding)
verification/{Cargo.toml,mise.toml,requirements.txt,INVARIANTS.md}
verification/src/{event_queue.rs,timer_table.rs} — Pearlite
contracts on simplified mirrors of the runtime types. cargo
creusot generates Coma IR cleanly; VCs not yet discharged.
Correspondence tests drive the verified mirror and the runtime
type with the same op sequences and assert observable parity.
Tests — 113 deterministic-flow tests across 22 files. Each compares a
hand-built expected journal byte-for-byte against actual, anchored
to a spec section: initial entry, lateral/self/up transitions,
bubbling, timers, emit, ordering, durings, step/dispatch
equivalence, root-targeting, current_state, termination.
Tooling — mise.toml (root): stable Rust + cargo subcommands.
verification/mise.toml: pinned nightly-2025-11-13 + opam + python
venv + uv. just verify is fully self-installing.
Bug fix — root state targetable by the chart's own name (e.g.
`on(Trig) => ChartName;`) per spec §"How transitions work".
CHART_HASH — stable FNV-1a fingerprint over the chart's structural
definition; mismatch on replay = different chart.
40 lines
1.7 KiB
TOML
40 lines
1.7 KiB
TOML
[package]
|
|
name = "hsmc-verification"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
license.workspace = true
|
|
authors.workspace = true
|
|
repository.workspace = true
|
|
homepage.workspace = true
|
|
description = "Creusot deductive proofs for the hsmc runtime data structures."
|
|
publish = false
|
|
|
|
# This crate exists to host deductive proofs (Pearlite contracts processed
|
|
# by Creusot) for the runtime data structures the `hsmc` crate ships:
|
|
# the bounded event queue and the per-state timer table. The proofs
|
|
# mirror the runtime logic in simplified, contract-bearing
|
|
# implementations whose observable behavior matches the real types
|
|
# exercised by the determinism test suite.
|
|
#
|
|
# Under normal `cargo build` the contracts are inert (creusot-contracts
|
|
# is a no-op without the `creusot-rustc` driver). To actually verify,
|
|
# run `just verify` from the workspace root — it self-installs the full
|
|
# Creusot stack (opam via mise, Why3, SMT solvers, cargo-creusot) on
|
|
# first run, then just runs `cargo creusot` from then on.
|
|
#
|
|
# See `INVARIANTS.md` for the spec-rule → proof mapping.
|
|
|
|
[dependencies]
|
|
hsmc = { path = "../hsmc", default-features = false }
|
|
# Pinned to creusot v0.9.0 — last tagged release with `creusot-std`.
|
|
# `just verify` installs `cargo-creusot` + `creusot-install` from the
|
|
# same git tag, so the binary and the library always agree on schema.
|
|
creusot-std = { git = "https://github.com/creusot-rs/creusot", tag = "v0.9.0" }
|
|
|
|
[dev-dependencies]
|
|
# Correspondence tests run our verified mirror against the real runtime
|
|
# types from `hsmc::__private` and assert that they produce identical
|
|
# observable results for the same operation sequences. This is how we
|
|
# tie the proofs to the shipped code.
|
|
hsmc = { path = "../hsmc", default-features = false }
|