spsc-ring 0.1.0

Lock-free SPSC ring buffer — sequence-number protocol, cache-line padded, zero dependencies
Documentation
# Contributing

## Prerequisites

- Rust stable (MSRV 1.95) for normal development.
- `cargo` only — no build scripts, no external tools required for basic dev.
- Optional: Rust nightly + Miri (`rustup component add miri --toolchain nightly`) for memory safety checks.
- Optional: `cargo-instruments` (macOS) for profiling. Install: `cargo install cargo-instruments`.

## Building

```bash
cargo build
```

## Testing

```bash
cargo test
```

All tests must pass before a PR.

### Loom concurrency tests

Loom explores all thread interleavings to check for data races. Requires stable (1.95) but must be compiled with `--cfg loom`:

```bash
RUSTFLAGS="--cfg loom" cargo test loom_tests
```

These tests are slow by design — loom's state space is exponential. Run them when touching the unsafe core or the sequence-number protocol.

### Miri memory safety checks

Miri detects undefined behaviour, use-after-free, and invalid memory access. Requires nightly:

```bash
cargo miri test
```

## Formatting and linting

```bash
cargo fmt --all
cargo clippy --all-targets -- -D warnings
```

Both must be clean before committing.

## Running benchmarks

```bash
cargo bench
```

Benchmark results are not committed. Record significant results manually in a comment on the relevant PR or issue.

## Commit style

Conventional commits, single line. Format: `type(scope): short description`.
Types: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `ci`, `chore`.

## Pull requests

- One logical change per PR
- Tests must pass
- `cargo fmt` and `cargo clippy` must be clean

## Release process

### Branch strategy

`main` is always releasable — tagged commits only. Feature work lands on a
`release/vX.Y.Z` integration branch, not directly on `main`.

```
feat/xxx  ─┐
feat/yyy  ─┼─▶  release/vX.Y.Z  ─▶  main  (tag vX.Y.Z)
feat/zzz  ─┘
```

1. Open `release/vX.Y.Z` from `main` at the start of the milestone.
2. Each `feat/...` PR targets `release/vX.Y.Z`, not `main`.
3. Run the pre-release checklist as commits on `release/vX.Y.Z`.
4. One final PR merges `release/vX.Y.Z``main`; tag on the merge commit.

Hotfixes branch from the relevant tag and merge back to `main`.

### Pre-release checklist

- [ ] All tests pass: `cargo test`
- [ ] Doc tests pass: `cargo test --doc`
- [ ] Formatted: `cargo fmt --all -- --check`
- [ ] No lint issues: `cargo clippy --all-targets -- -D warnings`
- [ ] Release build clean: `cargo build --release --locked`
- [ ] Bench compiles: `cargo bench --no-run`
- [ ] Dry-run publish clean: `cargo publish --dry-run`
- [ ] `CHANGELOG.md` section dated and complete
- [ ] Public types have `///` rustdoc; `cargo doc --no-deps` zero warnings
- [ ] Version bumped in `Cargo.toml` and `Cargo.lock` updated

### Tagging and publishing

```bash
# 1. Bump version in Cargo.toml, update CHANGELOG date
cargo update -p spsc-ring

# 2. Commit on release branch, push, open PR
git commit -am "chore: release vX.Y.Z"
git push origin release/vX.Y.Z
gh pr create --title "chore: release vX.Y.Z" --base main

# 3. Wait for CI to pass, merge to main
git checkout main
git merge --no-ff release/vX.Y.Z

# 4. Tag and push — GitHub Actions publishes to crates.io
git tag -a vX.Y.Z -m "Release vX.Y.Z"
git push origin main
git push origin vX.Y.Z
```

Tags containing `-rc` (e.g. `v0.2.0-rc1`) follow the same steps but the
`publish` job is skipped — nothing sent to crates.io.

### Hotfix

```bash
git checkout -b hotfix/vX.Y.Z+1 vX.Y.Z
# apply fix, bump patch version in Cargo.toml
git commit -am "fix: description"
git tag -a vX.Y.Z+1 -m "Hotfix vX.Y.Z+1"
git push origin hotfix/vX.Y.Z+1 vX.Y.Z+1
git checkout main
git merge --no-ff hotfix/vX.Y.Z+1
git push origin main
```

### CHANGELOG format

Move `[Unreleased]` entries to a versioned section:

```markdown
## [0.2.0] — 2026-MM-DD

### Added
- 
### Fixed
- 
## [Unreleased]
```