Release Process
Follow these steps to cut a NovaFabric release.
0. Migration compatibility rule (ADR-0180, expand-contract)
Every Alembic migration shipped in a release MUST be backward-compatible with the previous minor version's code (the N/N+1 window): additive changes first (new tables/columns nullable or defaulted), destructive contraction (drops, renames, type narrowing) only after one full minor cycle in which no shipped code path needs the old shape. A release containing a migration that breaks the previous minor's code against the new schema is blocked until the migration is split. Rationale and the full posture (single-writer active-passive, fencing invariant): ADR-0180.
1. Run tests
uv run pytest --benchmark-disable --cov=novafabric --cov-report=term-missingRequired: all tests pass, coverage ≥ 90%.
1a. Run the NovaSeal p99 latency gate
make benchmark
# or directly:
uv run pytest tests/seal/test_benchmark.py -v --benchmark-json=.benchmark-results/seal_latency.jsonRequired: NovaSeal.seal() p99 < 200 ms over 100 rounds.
1b. Verify the remaining CI gates are green
Three more blocking gates run in CI on every push; a release must not be tagged while
any is red on main (check the Actions tab, or run locally as below):
capture-overhead-gate— capture-overhead p95 (make benchmark-capture; p95 < 2.0 s over 30 rounds).web— the Astro site + dashboard build and typecheck (make site).integration— the testcontainers tier (uv run pytest tests/integrationwith Docker available; CI installs with--all-extras).
This section exists so the documented release gate names every CI job — guarded by
tests/docs/test_support_policy.py, which fails when a CI job is added without being
documented here. (The unit job's exact command parity is separately guarded by
tests/docs/test_makefile_matches_ci_gate.py.)
2. Run ruff
uv run ruff check src testsRequired: zero errors.
3. Run mypy
uv run mypy srcRequired: zero errors.
4. CLI smoke test
NOVAFABRIC_DB_PATH=/tmp/nf_smoke.db uv run novafabric register tests/fixtures/valid_model.yaml
NOVAFABRIC_DB_PATH=/tmp/nf_smoke.db uv run novafabric list
NOVAFABRIC_DB_PATH=/tmp/nf_smoke.db uv run novafabric inspect fraud-model@1.0.0
NOVAFABRIC_DB_PATH=/tmp/nf_smoke.db uv run novafabric validate tests/fixtures/valid_agent.yaml
NOVAFABRIC_DB_PATH=/tmp/nf_smoke.db uv run novafabric report
NOVAFABRIC_DB_PATH=/tmp/nf_smoke.db uv run novafabric report --format json
rm /tmp/nf_smoke.dbRequired: all commands exit 0.
5. Update CHANGELOG.md
Add a ## [x.y.z] — YYYY-MM-DD section with Added, Improved, and Fixed entries.
6. Bump version
Edit pyproject.toml:
version = "x.y.z"7. Commit and tag
git add CHANGELOG.md pyproject.toml
git commit -m "chore: release vx.y.z"
git tag vx.y.z
git push origin main --tags8. GitHub release
Create a GitHub release from the tag. Copy the relevant CHANGELOG section as the release body.