All notable changes to Lockstep are recorded here. Format follows Keep a Changelog, SemVer applies starting at 1.0.
0.1.0 — 2026-05-07
Initial public release.
Engine
- User-level scheduler (
Lockstep.Controller) that intercepts every sync point and decides which actor runs next. - Four strategies:
:random,:pct,:fair_pct,:pos. PCT is Burckhardt et al. ASPLOS'10. Fair-PCT is Coyote's hybrid. POS is Probabilistic Operating System scheduling — best for tight read-modify-write races. - Iterative-deepening PCT (
:idpct) for hard-to-find deep races. - Reads-From Fuzzing (RFF) — coverage-guided exploration variant.
Test surface
Lockstep.Test— ExUnit case template with actest/3macro that runs the body N times under different schedules.Lockstep.Runner.run/2— programmatic API for non-ExUnit callers.Lockstep.Linter— flags baresend/spawn/Process.send_afterin test bodies that should useLockstep.*equivalents.
OTP wrappers
Wrappers that route OTP traffic through the controller:
Lockstep.GenServer— drop-in replacement forGenServer.Lockstep.GenStatem— drop-in for:gen_statem.Lockstep.Agent,Lockstep.Task,Lockstep.Task.Supervisor.Lockstep.Registry,Lockstep.Supervisor.Lockstep.spawn/1,Lockstep.send/2,Lockstep.recv_first/1,Lockstep.send_after/3,Lockstep.cancel_timer/1,Lockstep.monitor/1,Lockstep.demonitor/2.
NIF / shared-state wrappers
Sync points so read-modify-write composition is interleavable:
Lockstep.ETS— wraps:ets.{insert, lookup, update_counter, ...}.Lockstep.Atomics— wraps:atomics.Lockstep.PersistentTerm— wraps:persistent_term.
Compile-time rewriters
Lockstep.Rewriter— AST rewriter swappingGenServer→Lockstep.GenServeretc.Lockstep.ErlangRewriter— same, for.erlsource.Lockstep.MixCompiler— drivesPath.wildcard→ preprocess → AST parse → rewrite → write. Use for testing third-party libraries.Lockstep.MixCompiler.Preprocessors— built-in source-string preprocessors:strip_compile_time_external_reads/2— removes@moduledoc File.read!(...)blocks.strip_code_ensure_loaded/2— comments out module-levelCode.ensure_loaded!.unwrap_optional_dep_guards/2,inline_json_dispatch/2,inline_optional_module_list/2,preserve_aliased_module_names/2— for handling common optional-dep gating patterns when rewriting third-party deps.
Trace, replay, shrink
Lockstep.Trace— recorded schedule format with aLOCKSTEP\0magic header and binary serialization.Lockstep.Replay— re-execute a saved trace deterministically.Lockstep.Shrink— minimize a counterexample via delta debugging.mix lockstep.replay --trace <path>— CLI helper.
Property checking
Lockstep.Checker.Linearizable— Knossos-style linearizability checker.Lockstep.Checker.SequentialConsistency.Lockstep.Checker.Causal— causal consistency.
Cluster simulation
Lockstep.Cluster.start_nodes/1— spawn N simulated nodes.Lockstep.Cluster.partition/3andheal/0— network partition / heal cycles.Lockstep.Cluster.stop_node/1andstart_node/1— node crash / recovery.- Cross-node
{name, node}send routing through the controller.
Causal slice + LLM explainer
Lockstep.CausalSlice— backward-slice traces from the failing step using a happens-before graph.Lockstep.LLMExplainer— optional Anthropic Claude integration for explaining counterexamples.
What's NOT shipped (yet)
- Hot code reloading (no plans).
- Distributed-Erlang test cluster scaffolding (use the in-process
Lockstep.Clusterinstead). - True formal verification — Lockstep is bug-finding + reproducibility, not proof.
- Stable wire protocol for trace files — format may change in 0.x.