determa-state 0.0.5

Determa State — Rust implementation of the Determa statechart engine (implements Determa State spec v0.0.5)
Documentation

Determa State-rust

A Rust implementation of the Determa State statechart engine.

Implements Determa State spec v0.0.5. Correctness is defined by the language-agnostic conformance suite at fruwehq/determa-state-conformance (pinned at tag v0.0.2 as a submodule under conformance-suite/); this engine is correct iff it passes every case.

What is Determa State?

Determa State is a language-agnostic statechart format: a machine is declared once in YAML and run by an implementation in any language, with all implementations held accountable by a shared conformance suite. It follows the run-to-completion and hierarchical-state-machine semantics of Miro Samek's Practical Statecharts in C/C++ (PSiCC) — the outermost state is top — and keeps the vocabulary of cns_statemachine (top, esvs, on_events, transition_to, defer, publish) while replacing raw guards/actions with CEL and a small structured action set.

This crate provides:

  • Full statechart semantics (SPEC §5): hierarchy with LCA exit/entry, run-to- completion, internal/local/external transitions, orthogonal regions + done, shallow/deep history, choice pseudostates, deferred events, and timers over a virtual clock.
  • Extended state (esvs) declared inside states, hierarchically scoped with shadowing (§4.4), plus external esvs driven by the reserved env event and the refresh action (§5.4).
  • Guards in CEL and a structured action set (assign/publish/refresh/ spawn/stop) whose computed values are CEL (§6).
  • Active objects — each instance owns an event queue; instances are spawned dynamically with deterministic ids and communicate only by publishing events (directed or by subscription/scope) over a pluggable bus (§5.7).
  • Faults via the reserved error event with atomic step rollback and a dead-letter (§5.10).
  • Versioned definitions + safe-point migration (§10).
  • Snapshot/restore and a passive per-step Observer (§8).
  • Mermaid export (§12).
  • An embeddable library API (§2) and the standard Determa State CLI (§13): all commands, exit codes, normative --json shapes, --store file:/mem:/sqlite:, batch/streaming run, and the §14 mode/inject/step/inspect verbs.

Build

cargo build --release
# the binary is target/release/Determa State

Run the conformance suite

git submodule update --init              # conformance-suite @ v0.0.2

# engine cases (SPEC §9)
cargo test --test conformance -- --nocapture

# black-box CLI cases (SPEC §13.6)
python3 conformance-suite/conformance/run_cli.py --cmd "$(pwd)/target/release/Determa State"

Both are wired into CI (.github/workflows/ci.yml), which fetches the suite at tag v0.0.5 and fails the build on any regression.

CLI

Determa State new t1 examples/minimal.yaml
Determa State send t1 coin --payload amount=100 --json
Determa State state t1 --json
Determa State list --json
Determa State validate examples/full.yaml
Determa State export examples/full.yaml

--store <spec> selects a backend: file:<dir> (default, portable snapshot files), mem: (ephemeral, in-process), or sqlite:<path>. See Determa State --help.

Library

use determa_state::{build_machine, load_machines, Engine, Value};
use std::collections::BTreeMap;

# fn main() -> Result<(), Box<dyn std::error::Error>> {
let docs = load_machines(include_str!("../examples/minimal.yaml"))?;
let machine = build_machine(&docs[0]).map_err(|e| format!("{e:?}"))?;
let mut engine = Engine::new();
engine.register(machine);
engine.create_root("t1", "turnstile", None, &BTreeMap::new())?;
engine.send("t1", "coin", Value::Map(
    [("amount".to_string(), Value::Int(100))].into_iter().collect()
))?;
let view = engine.state_view("t1")?;
assert_eq!(view.config, vec!["unlocked".to_string()]);
# Ok(()) }

Status

Pre-1.0 (0.0.x), tracking the synchronized Determa State spec/conformance version.

License

MIT — see LICENSE.