Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Release checklist

This page documents the steps required before publishing any matten release. It is the canonical gate referenced by RFC-015.

This page covers whether a release is fit to go out. It does not decide when one happens — that is RFC-094’s release cadence policy: a correctness fix to published code is a patch and ships as soon as it is reviewed; anything adding public API is a minor and batches until two or more themes have landed, 28 days have passed, or the owner asks; and a change that does not reach crates.io is not a release at all. The last is testable rather than editorial — if git diff --name-only <last-tag>..HEAD -- crates/ is empty, there is nothing to release.

Before every release

Release tags use bare SemVer with no v prefix, for example 0.46.0.

1. Source verification

cargo fmt --all --check
cargo fmt --manifest-path tools/matten-report/Cargo.toml --check
cargo fmt --manifest-path tools/matten-migrate/Cargo.toml --check
bash scripts/check-core-dependency-boundary.sh   # RFC-022 core boundary gate
bash scripts/check-published-dependency-isolation.sh  # RFC-049 §B1 per-crate peer-dep isolation
bash scripts/check-matten-data-scope.sh          # RFC-042 matten-data anti-scope guard
bash scripts/check-benchmark-dependency-sync.sh  # benchmark harness ndarray pin == workspace requirement
bash scripts/check-streaming-scope.sh            # RFC-037 streaming / large-CSV anti-scope guard
bash scripts/check-release-docs.sh               # doc-truth + examples naming-band guards
bash scripts/check-doc-code.sh                   # every non-ignored ```rust block in docs/src compiles
bash scripts/check-report-demos.sh               # docs/src/reports/*.md match matten-report's current output
bash scripts/check-tool-tests.sh                 # RFC-117: workspace-excluded tools' own shell test suites
cargo clippy --all-targets --all-features -- -D warnings
cargo clippy --all-targets --no-default-features -- -D warnings
cargo clippy --all-targets --no-default-features --features dynamic -- -D warnings
RUSTFLAGS="-D warnings" cargo check --all-targets --all-features
cargo test --all-targets
cargo test --doc --all-features

2. Feature matrix

cargo test --no-default-features
cargo test --no-default-features --features serde
cargo test --no-default-features --features json
cargo test --no-default-features --features csv
cargo test --no-default-features --features dynamic
cargo test --no-default-features --features dynamic,json
cargo test --no-default-features --features dynamic,csv
cargo test --no-default-features --features dynamic,json,csv
cargo test --all-features

3. Examples

cargo check --examples
cargo check --examples --all-features
cargo run --example 00_quickstart
cargo run --example 06_broadcasting
cargo run --example 08_slicing_builder
cargo run --example 12_boundary_error_handling
cargo run --example 57_visual_shape_axis_summary
cargo run --example dynamic_00_quickstart --features dynamic,json,csv
cargo run --example dynamic_05_dirty_csv_cleanup --features dynamic,json,csv
cargo check -p matten --example dynamic_09_visual_readiness_summary
cargo run -p matten --example dynamic_09_visual_readiness_summary --features dynamic
cargo run -p matten-data --example data_06_visual_readiness_summary
cargo run -p matten-mlprep --example mlprep_visual_standardize_summary
cargo check --manifest-path tools/matten-report/Cargo.toml
cargo test --manifest-path tools/matten-report/Cargo.toml
bash tools/matten-report/tests/process-boundary.sh
bash tools/matten-report/tests/module-boundaries.sh
bash tools/matten-report/tests/module-boundaries.sh --self-test
cargo clippy --manifest-path tools/matten-report/Cargo.toml -- -D warnings
cargo run --manifest-path tools/matten-report/Cargo.toml -- --demo data-readiness
cargo run --manifest-path tools/matten-report/Cargo.toml -- --demo data-readiness --output target/matten-report-demo.md
cargo run --manifest-path tools/matten-report/Cargo.toml -- --demo data-readiness --format html --output target/matten-report-data-readiness.html
cargo run --manifest-path tools/matten-report/Cargo.toml -- --demo data-readiness --format json --output target/matten-report-data-readiness.json
cargo run --manifest-path tools/matten-report/Cargo.toml -- --input tools/matten-report/fixtures/small.csv --kind data-readiness --select sales,cost
cargo run --manifest-path tools/matten-report/Cargo.toml -- --input tools/matten-report/fixtures/small.csv --kind data-readiness --select sales,cost --format html --output target/matten-report-input.html
cargo run --manifest-path tools/matten-report/Cargo.toml -- --input tools/matten-report/fixtures/non_numeric.csv --kind data-readiness --select sales,cost --format html --output target/matten-report-input-error.html
cargo run --manifest-path tools/matten-report/Cargo.toml -- --input tools/matten-report/fixtures/small.csv --kind data-readiness --select sales,cost --format json --output target/matten-report-input.json
cargo run --manifest-path tools/matten-report/Cargo.toml -- --input tools/matten-report/fixtures/non_numeric.csv --kind data-readiness --select sales,cost --format json --output target/matten-report-input-error.json
cargo run --manifest-path tools/matten-report/Cargo.toml -- --demo shape-flow
cargo run --manifest-path tools/matten-report/Cargo.toml -- --demo shape-flow --output target/matten-report-shape-flow.md
cargo run --manifest-path tools/matten-report/Cargo.toml -- --demo shape-flow --format html --output target/matten-report-shape-flow.html
cargo run --manifest-path tools/matten-report/Cargo.toml -- --demo shape-flow --format json --output target/matten-report-shape-flow.json
cargo run --manifest-path tools/matten-report/Cargo.toml -- --demo dynamic-readiness
cargo run --manifest-path tools/matten-report/Cargo.toml -- --demo dynamic-readiness --output target/matten-report-dynamic-readiness.md
cargo run --manifest-path tools/matten-report/Cargo.toml -- --demo dynamic-readiness --format html --output target/matten-report-dynamic-readiness.html
cargo run --manifest-path tools/matten-report/Cargo.toml -- --demo dynamic-readiness --format json --output target/matten-report-dynamic-readiness.json
cargo run --manifest-path tools/matten-report/Cargo.toml -- --demo mlprep-standardization
cargo run --manifest-path tools/matten-report/Cargo.toml -- --demo mlprep-standardization --output target/matten-report-mlprep-standardization.md
cargo run --manifest-path tools/matten-report/Cargo.toml -- --demo mlprep-standardization --format html --output target/matten-report-mlprep-standardization.html
cargo run --manifest-path tools/matten-report/Cargo.toml -- --demo mlprep-standardization --format json --output target/matten-report-mlprep-standardization.json
cargo run --manifest-path tools/matten-report/Cargo.toml -- --demo educational-path
cargo run --manifest-path tools/matten-report/Cargo.toml -- --demo educational-path --output target/matten-report-educational-path.md
cargo run --manifest-path tools/matten-report/Cargo.toml -- --demo educational-path --format html --output target/matten-report-educational-path.html
cargo run --manifest-path tools/matten-report/Cargo.toml -- --demo educational-path --format json --output target/matten-report-educational-path.json
cargo check --manifest-path tools/matten-migrate/Cargo.toml
cargo test --manifest-path tools/matten-migrate/Cargo.toml
cargo clippy --manifest-path tools/matten-migrate/Cargo.toml -- -D warnings
cargo run --manifest-path tools/matten-migrate/Cargo.toml -- list-targets
cargo run --manifest-path tools/matten-migrate/Cargo.toml -- inspect tools/matten-migrate/fixtures/simple-core-project
cargo run --manifest-path tools/matten-migrate/Cargo.toml -- report tools/matten-migrate/fixtures/simple-core-project
cargo run --manifest-path tools/matten-migrate/Cargo.toml -- report tools/matten-migrate/fixtures/simple-core-project --output target/matten-migration-report.md
cargo run --manifest-path tools/matten-migrate/Cargo.toml -- suggest --target ndarray tools/matten-migrate/fixtures/receiver-method-project
cargo run --manifest-path tools/matten-migrate/Cargo.toml -- suggest --target polars-pandas tools/matten-migrate/fixtures/common-rust-collisions-project
cargo run --manifest-path tools/matten-migrate/Cargo.toml -- suggest --target stay-with-matten tools/matten-migrate/fixtures/simple-core-project
cargo run --manifest-path tools/matten-migrate/Cargo.toml -- explain-api Tensor::matmul
cargo run --manifest-path tools/matten-migrate/Cargo.toml -- explain-api matmul
cargo run --manifest-path tools/matten-migrate/Cargo.toml -- explain-api matten_ndarray::to_arrayd
cargo run --manifest-path tools/matten-migrate/Cargo.toml -- explain-api matten_data::Table
cargo run --manifest-path tools/matten-migrate/Cargo.toml -- check-bridges tools/matten-migrate/fixtures/ndarray-bridge-project
cargo run --manifest-path tools/matten-migrate/Cargo.toml -- check-bridges tools/matten-migrate/fixtures/simple-core-project

4. MSRV

cargo +1.85.0 build
cargo +1.85.0 test --all-features --quiet

5. Public API audit

Compare the current public surface against docs/src/reference/public-api-snapshot.md.

Allowed root exports:

  • Tensor
  • MattenError
  • DataFormat
  • MattenLimits
  • SliceBuilder
  • Element (under #[cfg(feature = "dynamic")])
  • NumericPolicy (under #[cfg(feature = "dynamic")])

Allowed #[doc(hidden)] exports (compiler visibility only, not user-facing):

  • IntoSliceRange
  • SliceConvert
  • SliceSpecRepr

Run a spot-check:

grep -n "^pub use" src/lib.rs

Verify no module accidentally became pub mod.

cargo public-api snapshot (manual, pre-v1.0 minimum-viable step; RFC-066 NF-2, re-confirmed open by the RFC-074 re-audit). Not wired as a CI gate or project dependency. Before a minor/major release that touches public API surface, run it by hand for matten and any companion whose surface changed, and reconcile the output against docs/src/reference/public-api-snapshot.md and each crate’s ## Public API README block:

cargo install cargo-public-api   # one-time, not a project dependency
cargo public-api --manifest-path crates/matten/Cargo.toml
cargo public-api --manifest-path crates/matten-ndarray/Cargo.toml
cargo public-api --manifest-path crates/matten-mlprep/Cargo.toml
cargo public-api --manifest-path crates/matten-data/Cargo.toml
cargo public-api --manifest-path crates/matten-stats/Cargo.toml

Wiring this into CI (toolchain pinning, nightly requirements) is a separate, explicit decision — do not add it silently as part of a routine release.

6. Documentation truth pass

# No stale version strings in user-facing files
grep -R "Status:.*0\.[0-9]\{2\}\." README.md docs/src/ src/lib.rs || true

# No stale "matten 0.x" in runtime messages
grep -rn "matten 0\." src/ | grep -v "CHANGELOG\|#\[" || true

# No version-specific claims in lib.rs crate docs
grep "This is.*0\." src/lib.rs || true

7. CHANGELOG

  • Every API change has a changelog entry.
  • Changelog entries describe actual changes, not planned ones.
  • No changelog entry claims a fix that is not in the code.
  • If the entire scope of this release is local-tool-only (workspace-excluded, publish = false crates such as tools/matten-report or tools/matten-migrate), the CHANGELOG entry must include a one-line justification for cutting a lock-step family checkpoint despite no published-crate change (RFC-075 §3.1).

8. Version bump

Update Cargo.toml version. During v0.x, patch releases (0.13.x) should not introduce new public API unless a minor release (0.14.0) is intended.


Additional gates for minor releases (0.14.0, 0.15.0, …)

  • New public API has a corresponding accepted RFC.
  • Public API snapshot is regenerated and reviewed.
  • mdBook examples for new APIs compile and run.
  • Migration guide updated if any method signature changed.

Public-dependency-minor changes

When a published crate re-exposes a third-party type in its public API (for example matten-ndarray exposing ndarray::ArrayD<f64> through to_arrayd/from_arrayd), changing the supported minor of that dependency is a public-API compatibility event — not a routine cargo update — and is handled as a lock-step family minor (RFC-030). Before releasing such a change:

  • The change has an accepted RFC recording the supported version(s) and the decision (a single bump vs. a bounded range). Precedent: RFC-062 (ndarray0.17), which weighed a 0.16+0.17 range before the maintainer chose a single-version requirement to keep Cargo.toml simple.
  • If a range is supported, CI verifies the crate’s tests, doctests, and examples against each supported minor — e.g. cargo update -p <dep> --precise <ver> in a fresh checkout (so the per-job lockfile edit is not committed). A single-version requirement needs only the normal job against the resolved patch (document which patch CI targets).
  • No version-conditional bridge/crate code. If the unchanged crate cannot compile against every supported minor, narrow the range instead of adding #[cfg(...)] branches or per-version feature flags.
  • Docs state that the resolved dependency minor is part of the crate’s public type identity, name any yanked patch that is excluded and not a tested target, and note that docs.rs renders a single resolved minor even though CI verifies the full range.
  • MSRV is re-verified with the new dependency version in the graph. A dependency’s own rust-version is not sufficient — its transitive dependencies can raise the floor independently.
  • Core matten dependency isolation is re-confirmed (the published-dependency-isolation guard still passes; the change must not leak a peer dependency into the core graph).
  • If the dependency is also used by the workspace-excluded benchmark harness (e.g. a peer pin in benchmarks/Cargo.toml), its pin is synced by hand and check-benchmark-dependency-sync.sh passes — the harness cannot inherit { workspace = true }, so this guard catches a forgotten sync.

Workspace core-dependency requirement

Companion crates inherit core matten through [workspace.dependencies] as matten = { version = "0", path = "crates/matten", default-features = false } (RFC-064). Do not narrow this requirement during routine family releases. User docs and examples still show explicit matched release pins so downstreams see the supported family set.


Push, confirm CI green, then publish

This section applies to every release, patch included — not only minor ones. Pushing, confirming CI, tagging, and publishing happen regardless of release size, so this lives outside ## Additional gates for minor releases on purpose: a patch release must not be able to read that heading and skip straight to tagging.

Push, confirm CI green, then tag

The release sequence is push → confirm CI green → tag → publish, in that order, for a reason at each step:

  1. Push main. CI runs on push; it cannot report on a commit that has not been pushed yet.

  2. Confirm CI is green on the commit just pushed — not “CI was green recently,” not the previous run, the commit that is about to be tagged. A red run on that commit stops the release. Do not tag or publish until it is green. Check with:

    gh run list --limit 5
    

    or the repository’s Actions tab, and match the run against the commit SHA just pushed.

  3. Tag, only after step 1 has already landed on the remote. A tag pointing at a commit absent from the remote is the orphaned-tag defect this project repaired once, for 0.38.0/0.39.0.

  4. Publish — see below.

0.46.0 was tagged and published across four consecutive red CI runs because this step did not exist: every local gate passed, and the workflow result on the commit just pushed was never checked (RFC-117, RFC-118). This step does not automate that check — it only makes it impossible to miss by accident.

Publishing: one workspace command, not five per-crate ones

cargo publish --workspace --dry-run
cargo publish --workspace

Publish the whole workspace in one invocation. Cargo resolves the order itself and — the reason this matters — verifies every crate before uploading any, so a failure in the last companion aborts before core is irreversibly live. crates.io has no unpublish, only yank, which makes a half-published family a permanent artifact of the registry rather than a mistake you can undo.

This supersedes the older instruction to publish matten first and then each companion in dependency order. That sequence predates cargo publish --workspace and carried exactly the partial-publication hazard above; it was still being followed as late as the 0.42.0 release, where the owner stopped it before the first upload. Keep the following in mind, but do not turn them back into a manual sequence:

  • matten is still published before the companions — cargo does this for you.
  • A companion dry-run run on its own may fail before core is visible on crates.io. That is a sequencing artifact, not a dependency-policy failure, and --workspace avoids it entirely.
  • If the broad version = "0" requirement is intentionally changed, update RFC-030/RFC-064, this checklist, companion README compatibility notes, and package dry-run expectations in the same review slice.

Verify afterwards against the sparse index, not the JSON API:

curl -s https://index.crates.io/ma/tt/matten-stats | grep '"vers":"<version>"'

https://crates.io/api/v1/crates/<name> now returns HTTP 403 under the crates.io data-access policy, so a verification step built on it reports nothing and looks like a failed publish.


v1.0.0 gate

v1.0.0 requires explicit confirmation from the maintainer (nabbisen). It is not triggered automatically by any feature or test passing.

Before v1.0.0, the project should have:

  • stable core public API;
  • clear dynamic on-ramp story;
  • strong, scoped examples;
  • reliable diagnostics;
  • documented companion-crate boundary (RFC-022);
  • clean feature matrix across all profiles;
  • an RFC-067 family maturity table in the v1.0 release RFC if any lock-step family crate remains production-ready candidate.