A W3C SCXML-conformant statecharts engine for Elixir. Ground-up rewrite of statifier v1.x, built against the SCION and W3C conformance corpora from day one.
v1 works, but its interpreter re-derived the SCXML semantics instead of porting the spec's algorithm, and the divergences account for nearly all of its remaining conformance failures. v2 is:
- a literal port of W3C SCXML Appendix D - same functions, same names
- a pure functional core returning effects - one semantics for every API, sessions and timers layered on top
- predicator as the datamodel - safe, non-evaluative expressions; no ECMAScript, no eval
- built corpus-first - 186+ SCION/W3C conformance tests and a forward-only regression ratchet inherited from v1, with the generator committed this time
Add statifier to your dependencies:
def deps do
[
{:statifier, "~> 2.0"}
]
endReleases follow SemVer; CHANGELOG.md
is the upgrade briefing, and its [2.0.0] section is written as a migration
document for 1.x users. (The pre-release SHA-pinning contract ended with
2.0.0 - ADR-0066.)
Persisted position and recording blobs refuse with a typed error on a
format-version or chart-identity mismatch rather than misreading.
Compile an SCXML document, initialize it, and send it events. Effects come back as data - the engine never performs them for you:
source = """
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="off">
<state id="off">
<transition event="toggle" target="on"/>
</state>
<state id="on">
<transition event="toggle" target="off"/>
</state>
</scxml>
"""
{:ok, machine} = Statifier.compile(source)
{machine_state, _effects} = Statifier.initialize(machine)
Statifier.active_leaf_states(machine_state)
#=> MapSet.new(["off"])
{:ok, machine_state, _effects} = Statifier.send_event(machine_state, "toggle")
Statifier.active_leaf_states(machine_state)
#=> MapSet.new(["on"])That four-function surface (compile/2, initialize/2, send_event/2,
active_leaf_states/1) is the whole entry point; sessions, durable timers,
persistence, and telemetry layer on top of it.
Published guides on hexdocs:
- Architecture - the layered design and the decisions behind it
- Datamodel - predicator expressions,
<data>,<assign>, and<script> - Extending - registering your own
<invoke>handlers - Persistence - chart identity, persisted positions, and resuming sessions
- Durable timers - scheduling delayed sends outside the session process
- Observability - trace effects and what to do with them
- OpenTelemetry - span topology and the OTel bridge
- Testing charts - testing your own state charts
- Chart patterns - patterns for external-resource verdicts (park/retry, fail-fast)
- Family reference - what the statifier sibling repos copy from here
Architecture Decision Records live in the repository at docs/adr/.
mix deps.get
mix quality --profile loop # fast inner loop
mix quality # full gate (required green before commit)Issue tracking is beads (bd ready to
find work). Workflow, model roles, and worktree conventions:
docs/workflow.md.
MIT - see LICENSE.