# Contributing
## Local CI (source of truth)
[`scripts/ci.sh`](https://github.com/photon-circus/ph-haptics/blob/main/scripts/ci.sh)
is the canonical gate list and the contributor
source of truth for merge readiness. When you add or reorder a gate, update
the script and the list below together.
Run from the repository root (Git Bash on Windows, or any bash):
```sh
bash scripts/ci.sh
```
### Gates (in order)
1. **Format** — `cargo fmt --all -- --check`
2. **Host lib tests** — `cargo test --locked --lib`
3. **Generator tests** — `cargo test --locked --features gen --bin ph-haptics-gen`
4. **Host gen check** — `cargo check --locked --all-targets --features gen`
5. **Host gen clippy** — `cargo clippy --locked --all-targets --features gen -- -D warnings` (all targets, so test code is linted too)
6. **Bare-metal check** — `cargo check --locked --target thumbv7em-none-eabihf --lib`
7. **Bare-metal clippy** — `cargo clippy --locked --target thumbv7em-none-eabihf --lib -- -D warnings`
8. **no_std/alloc feature guard** — `cargo tree` for the bare-metal target; fails if any crate in the default-feature graph resolves with its `std` or `alloc` **feature** enabled (crate *names* never appear: they are sysroot crates)
9. **Catalog compile** — run `ph-haptics-gen` over every `assets/phh-library/*.phh` into a temp directory
10. **Generate→compile roundtrip** — emit a small fixture through `ph-haptics-gen` into a temp crate and `cargo check` it against this package
11. **Mock-machine verify** — `scripts/mock-verify.sh` regenerates fixtures, checks mock formatting/tests/clippy, and asserts golden command/deadline traces
All cargo invocations in the scripts use `--locked` (except `cargo fmt` and the ephemeral generate→compile roundtrip crate, which has no committed lockfile).
### Toolchain / target
Root [`rust-toolchain.toml`](rust-toolchain.toml) pins Rust **1.92.0** with
`rustfmt` and `clippy`, and lists the `thumbv7em-none-eabihf` target. If the
bare-metal target is missing locally:
```sh
rustup target add thumbv7em-none-eabihf
```
## Contract validation
The crate contract is defined in [`docs/contract.md`](docs/contract.md). Changes
must preserve the host-compiler to static-catalog to embedded-scheduler path.
The canonical local CI proves compilation, tests, bare-metal compatibility,
bounded dependencies, catalog generation, a generate-to-compile roundtrip, and
the deterministic mock-machine command/deadline traces.
Board builds, physical motor behavior, and HIL are downstream firmware concerns
rather than crate-level merge gates. Run the mock alone with
[`scripts/mock-verify.sh`](https://github.com/photon-circus/ph-haptics/blob/main/scripts/mock-verify.sh);
see
[`mock/README.md`](https://github.com/photon-circus/ph-haptics/blob/main/mock/README.md).
## Security
Report security issues via [GitHub Security Advisories](https://github.com/photon-circus/ph-haptics/security/advisories)
or a private maintainer contact. Do not open a public issue for an undisclosed
vulnerability.
## Docs
- Product and proof contract: [`docs/contract.md`](docs/contract.md)
- Runtime / package boundary: [`docs/architecture.md`](docs/architecture.md)
- Generator design: [`docs/compiler-design.md`](docs/compiler-design.md)
- Public API: [`docs/public-api.md`](docs/public-api.md)
- Mock-machine proof: [`mock/README.md`](https://github.com/photon-circus/ph-haptics/blob/main/mock/README.md)