CONTRIBUTING.md

# Contributing to Lockstep

Thanks for your interest. Lockstep is at v0.1.0 and looking for
real-world feedback. Here's how to contribute.

## Quick links

- **Bug reports**: open an issue with a minimal Lockstep test that
  demonstrates the problem and the strategy + seed it was found with.
- **Feature requests**: open an issue describing the use case before
  writing code.
- **Pull requests**: small + focused beats large + sweeping. Tests
  required.

## Development setup

```sh
git clone https://github.com/b-erdem/lockstep
cd lockstep
mix deps.get
mix test
```

Core tests run on a fresh clone with no external setup. Some
integration tests against external libraries (HyParView, DeltaCrdt,
Phoenix.PubSub, Horde, GenStage, etc.) require those libraries to
be cloned to specific paths — those tests skip cleanly if the paths
don't exist. See `test/erlang_pg_test.exs` for an example of the
skip pattern.

## Filing a bug

Lockstep test that reproduces the issue is the gold standard:

```elixir
defmodule MyBugTest do
  use Lockstep.Test

  ctest "minimal repro" do
    # ...
  end
end
```

Run it with:

```sh
mix test path/to/test.exs --seed 1
```

Include in your issue:
- Full Lockstep version (`mix deps`)
- Strategy + seed that triggers the bug
- The trace file (in `traces/`) if Lockstep saved one
- The Erlang/Elixir version

## Adding a strategy

Lockstep's strategies live in `lib/lockstep/strategy/`. Each
implements the `Lockstep.Strategy` behaviour. See
`lib/lockstep/strategy/random.ex` as the simplest example. Tests go
in `test/strategy_*_test.exs`.

## Adding an OTP wrapper

If you find an OTP primitive that Lockstep doesn't intercept yet,
the wrapper pattern is:

1. Add a module under `lib/lockstep/<primitive>.ex`.
2. Each public function calls `Lockstep.Controller.nif_sync/3` (or
   the appropriate sync-point function) before doing the actual
   work.
3. Add a clause to `Lockstep.Rewriter` so source code using the
   primitive is rewritten.
4. Tests in `test/<primitive>_*_test.exs`.

## Running the full test suite

Lockstep uses external libraries to validate its rewriter against
real-world code. To run the full integration suite:

```sh
# Clone the libraries Lockstep tests against:
mkdir -p /tmp && cd /tmp
git clone https://github.com/derekkraan/delta_crdt_ex
git clone https://github.com/derekkraan/merkle_map
git clone https://github.com/derekkraan/horde horde_src
git clone https://github.com/bitwalker/libring
git clone https://github.com/keathley/groot
git clone https://github.com/sasa1977/con_cache concache_src
git clone https://github.com/phoenixframework/phoenix_pubsub phoenix_pubsub_src
git clone https://github.com/dashbitco/nimble_pool
git clone https://github.com/beam-telemetry/telemetry
git clone https://github.com/toniqsystems/hlclock

# Then back to the lockstep repo:
cd /path/to/lockstep
mix test
```

Tests skip cleanly when their target source isn't on disk, so you
can run a partial set.

## Code style

- `mix format` before commit.
- Clear module-level `@moduledoc` explaining what + why.
- Function-level `@doc` for public API.
- Tests describe the bug shape they're hunting for (see existing
  tests' moduledocs).

## Hands-on engagement

If you want to apply Lockstep to a production BEAM system —
concurrency audit, custom test scaffolding, multi-node race-hunting
harness, or hardening on retainer — that's something I do directly.
Reach out: **[baris@erdem.dev](mailto:baris@erdem.dev)**.

## License

Apache 2.0. By contributing, you agree your contributions will be
licensed under the same.