Test strategy and evidence tiers

Tests are classified by purpose even when they share the top-level tests/ tree. Markers express the execution tier; a new test should use the most specific applicable marker and location.

Class Marker/location Purpose
Unit subsystem directories under tests/ Local behavior and invariants
Integration integration Multi-component/backend workflows
Regression regression A previously observed, reproducible defect
Property property Generated or metamorphic invariants
Compatibility compatibility Supported dependencies, platforms, and file formats
Golden golden Small, reviewed deterministic behavior snapshots
Verification bridge verification Python/schema/checker/formal interfaces
Performance benchmark, perf/ Timing/memory history, not normal unit tests
Scientific experiment experiments/ Research hypothesis evaluation, not a unit test

Every reproducible bug fix adds a regression test. Randomized tests use explicit seeds or deterministic generators; floating-point assertions state a mathematically justified tolerance and, if needed, a platform scope. Golden baseline updates must identify the generating command, declared environment, and the reason the changed result is scientifically correct.

scripts/ci/test_profiles.py is the executable source of truth for every release profile. make test-fast resolves mr-fast; make test and make test-coverage resolve tag-core; make test-min-torch resolves the explicit lower-bound minimum-torch compatibility profile. Those base profiles exclude dependency-backed success paths. make test-onnx, make test-jax, and make test-viz install and execute their named optional profiles; make test-paper-contract verifies the frozen 0.4.3 replay boundary, and make test-scientific-contract verifies the bounded current benchmark contract. Every profile must collect at least one node and its collection manifest contains a sorted, hashed node list. Profile manifests also record the path-universe count and marker deselection count, so a release baseline distinguishes a deliberately filtered profile from silently lost collection nodes without parsing pytest's human summary.

make test-all runs the full base/optional/package profile set in its declared environment. The separately provisioned lower-bound minimum-torch profile is run with make test-min-torch after installing its declared Torch version. For a frozen candidate that already has reviewed baselines, run make test-coverage VERIFY_RELEASE_RATCHETS=1 QUALIFICATION_COMMIT=<C>; this same canonical command produces the evidence and then blocks on exact test and coverage ratchets. Do not enable that switch against a moving development tree or use it to generate a baseline. make test-release-blockers is a supplemental fail-closed sweep of every contract found red by the v0.6.1 audit; it emits a JUnit report and exact node manifest but does not replace the complete profile matrix. Distribution smoke tests run through make build or make check-dist. Long experiments and performance benchmarks use their own commands/manifests and must not silently become part of an ordinary unit-test selector. The optional scripts/local_ci.sh wrapper delegates only to these Make targets and preserves their exit statuses while retaining local logs.