Skip to content

chore(ci): the merge gate tests in --release; release workflow gains --test-threads=1 - #750

Merged
cryptskii merged 1 commit into
mainfrom
chore/ci-board-release-profile
Aug 30, 2026
Merged

chore(ci): the merge gate tests in --release; release workflow gains --test-threads=1#750
cryptskii merged 1 commit into
mainfrom
chore/ci-board-release-profile

Conversation

@cryptskii

@cryptskii cryptskii commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator

The merge gate ran the test suite in the debug profile while the release
workflow ran it in release. The debug gate was the anomaly, and the codebase
already says so in two places:

  • The crypto property-test suites scale their case counts up outside debug
    (if cfg!(debug_assertions) { 3 } else { 10 } in sphincs_pbt_tests.rs,
    determinism_pbt_tests.rs, kyber_pbt_tests.rs, signatures.rs), so the
    gate has been running the reduced variant of exactly the properties it
    exists to check.
  • state_machine/mod.rs documents a hash-adjacency tamper check that
    "silently did not execute in a debug run, which is the profile the suite is
    usually exercised in."

The gate should exercise the profile that ships. It now does.

Changes

ci.yml — both test commands gain --release. The separate
cargo build --locked --workspace --all-features step deliberately stays
debug
: with the test step on release, the gate now compile-checks both
profiles instead of one.

release.yml — the workspace test line gains --test-threads=1. The
dsm_sdk suites share process-global singletons and #[serial] only
serializes #[serial] tests against each other, so this workflow was running
a parallelism the merge gate never exercised — a latent flake source, now
closed. The storage-node line is untouched in both workflows: that crate has
no shared-singleton problem and has always run parallel.

The local board definition (CLAUDE.md, gitignored) is updated to match.

What the profile switch changes semantically

  • The PBT suites run their full case counts in the gate for the first time.
  • debug_assert!s (sphincs length checks, the SMT collision check) no longer
    execute in the Test step — but they still execute in CI on every run: the
    Coverage job (cargo llvm-cov, ci.yml:273) runs the full workspace suite in
    debug, serial, and is untouched here. Across the two jobs the gate now
    exercises BOTH profiles at run time, where before it ran debug twice.
  • Integer overflow wraps in release where debug panics; no
    overflow-checks override exists anywhere in the workspace. The value paths
    use checked_* arithmetic by doctrine, and the release board passing with
    an identical test inventory is the run-level evidence the suite does not depend on
    debug-only panics. If wrap-on-overflow in the shipped artifact is itself
    unwanted, overflow-checks = true under [profile.release] is a separate
    decision — it changes production behavior, so it is flagged here rather
    than bundled.

Verification (new gate, exact commands, pinned 1.98.0)

workspace  --release   3919 passed / 0 failed across 72 suites, exit 0
node       --release   270 passed / 0 failed, exit 0
make lint              exit 0
production safety      exit 0

Timing on this machine: the debug board spent ~32 min executing tests
(20 min of it in the dsm_sdk lib suite alone, dominated by unoptimized
SPHINCS+). Release: 9m17s
total wall including the cold compile
, 4.5 min of it test execution — ~7×
faster on the test half even while the property suites run 3× the cases.

Test-inventory parity was checked, not assumed: the release run's one-test
delta against the last debug board is #749's rounding vector, which merged
between the two runs; ignored counts are identical (17), and no
cfg(not(debug_assertions)) test exists anywhere in the workspace.

…--test-threads=1

The merge gate ran the suite in debug while the release workflow ran release.
The debug gate was the anomaly, and the codebase said so: the crypto property
tests scale their case counts UP outside debug (3 -> 10), so the gate ran the
reduced variant of exactly the properties it exists to check, and
state_machine/mod.rs documents an adjacency check that "silently did not
execute in a debug run, which is the profile the suite is usually exercised
in". The gate now exercises the shipped profile.

ci.yml: both test commands gain --release. The all-features Build step stays
debug deliberately — the gate now compile-checks both profiles.

release.yml: the workspace test line gains --test-threads=1. The dsm_sdk
suites share process-global singletons and #[serial] only serializes
#[serial] tests against each other, so this workflow ran a parallelism the
merge gate never exercised. The storage-node line is untouched in both
workflows — that crate has always run parallel, green.

Semantics of the switch: debug_assert!s no longer execute in the gate (they
supplement Result-returning checks; the debug Build step still compiles
them), and overflow wraps where debug panics — value paths use checked_*
arithmetic by doctrine, and the release board is green with an identical test
inventory. overflow-checks=true in [profile.release] would change production
behavior and is left as a separate decision.

New gate run locally, exact commands, pinned 1.98.0: workspace 3919/0 across
72 suites; node 270/0; make lint exit 0; production safety exit 0. Wall
clock: 9m17s including the cold release compile, vs ~32 min of test
execution alone under debug.
@cryptskii
cryptskii merged commit 668cf90 into main Aug 30, 2026
18 checks passed
@cryptskii
cryptskii deleted the chore/ci-board-release-profile branch August 30, 2026 04:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant