CONTRIBUTING.md

Contributing to strata

Design authority lives in ../proposal/ — start with 01-design-principles.md (P-1..P-11) and the decisions register ../proposal/decisions.md (D-001–D-080). Code that contradicts a settled decision is wrong even if it works.

Promotion rule: probes → crates

Probe code (../probes/) is rewritten with its tests carried, never copied. A promotion PR states which probe it promotes; the probe's test corpus and gap ledger come along as the crate's test suite. Probe code itself is a design artifact, not a dependency.

Invariants that gate merges

  • D-053 fuzz suites: fmt/parse invariants are CI-fuzzed from day one — idempotence (fmt∘fmt = fmt), lossless round-trip (text(tree) == input, including comment count and anchors), parse-error input returned untouched, cross-platform determinism.
  • No-panic: tool crates must not panic on any input; malformed input yields P-9 diagnostics (strata-diag/0, see docs/diagnostics.md), never a crash.
  • Determinism (P-6): no wall clock, no env reads, no iteration-order nondeterminism, no HashMap ordering in any output path. cargo xtask ci runs the test suite twice and byte-compares generated artifacts; a diff fails the build.

Run the full gate locally before pushing:

1cargo xtask ci # whole workspace
2cargo xtask ci -p strata-cli # scoped, while sibling crates are mid-build
3cargo xtask circt # source → compiler → pinned external CIRCT gate

(fmt-check → clippy -D warnings → tests ×2 + artifact byte-compare.)

The CIRCT contract compiles the Counter source fixture through strata compile before passing the generated MLIR through the pinned full CIRCT bundle and Icarus Verilog. Set CIRCT_BIN to the bundle's bin directory, or put its tools on PATH; see tests/circt/README.md. Ordinary CI does not assume this external toolchain is installed. Set STRATA_CI_CIRCT=1 to explicitly include the fail-closed CIRCT contract in cargo xtask ci; the CI log states when it was not requested.

Spec divergences

If implementation forces a divergence from ../proposal/, do not silently adapt: record it in a SPEC-ISSUES.md at the crate root (what diverged, why, which proposal section/decision it touches). These files feed back into ../proposal/ — a divergence is resolved either by fixing the code or by a decisions-register event, never by drift.