# Changelog
All notable changes to Lockstep are recorded here.
Format follows [Keep a Changelog](https://keepachangelog.com/),
[SemVer](https://semver.org/) 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:
- `Lockstep.GenServer` — drop-in replacement for `GenServer`.
- `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 swapping `GenServer` →
`Lockstep.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
- `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/3` and `heal/0` — network
partition / heal cycles.
- `Lockstep.Cluster.stop_node/1` and `start_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.Cluster` instead).
- True formal verification — Lockstep is bug-finding +
reproducibility, not proof.
- Stable wire protocol for trace files — format may change in
0.x.
[0.1.0]: https://github.com/b-erdem/lockstep/releases/tag/v0.1.0