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 a ctest/3 macro that runs the body N times under different schedules.
  • Lockstep.Runner.run/2 — programmatic API for non-ExUnit callers.
  • Lockstep.Linter — flags bare send/spawn/Process.send_after in test bodies that should use Lockstep.* equivalents.

OTP wrappers

Wrappers that route OTP traffic through the controller:

NIF / shared-state wrappers

Sync points so read-modify-write composition is interleavable:

Compile-time rewriters

  • Lockstep.Rewriter — AST rewriter swapping GenServerLockstep.GenServer etc.
  • Lockstep.ErlangRewriter — same, for .erl source.
  • Lockstep.MixCompiler — drives Path.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-level Code.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 a LOCKSTEP\0 magic 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

Cluster simulation

Causal slice + LLM explainer

What's NOT shipped (yet)

  • Hot code reloading (no plans).
  • Distributed-Erlang test cluster scaffolding (use the in-process Lockstep.Cluster instead).
  • True formal verification — Lockstep is bug-finding + reproducibility, not proof.
  • Stable wire protocol for trace files — format may change in 0.x.