The determinism test is the crate's guarantee that rayon changes nothing. It does not run the code it is guarding.
The parallel branch is unreachable in that fixture
sweep_color_groups (src/time_slice.rs:454-500) takes the par_iter branch only when group_len >= RAYON_THRESHOLD (64). The test builds 200 events at time = ev_i / 10 + 1 — 20 slices of 10 events. A color group is a subset of one slice's events, so group_len <= 10 < 64. The branch cannot be taken.
Confirmed by CPU-vs-wall time rather than by reading alone:
10 ev/slice (the test shape), RAYON_NUM_THREADS=8 : real 0.82 user 0.64 sys 0.24 <- ~1 core
500 ev/slice, RAYON_NUM_THREADS=1 : real 0.48 user 0.47 sys 0.02
500 ev/slice, RAYON_NUM_THREADS=8 : real 0.49 user 0.88 sys 1.15 <- >1 core
The residual thread activity at the test shape is log_evidence_internal's par_iter over slices, not the sweep.
Three further coverage gaps
One competitor of forty. It compares learning_curve("p0") only. A nondeterminism affecting any other competitor passes.
log_evidence is never compared — the quantity most exposed to accumulation order. Nor are ConvergenceReport::final_step or iterations.
All four thread counts run in one process, so the HashMap hasher seed is identical across them. Any nondeterminism from map iteration order is invisible to it by construction — which is exactly the defect in #62, and exactly why that one went unnoticed.
The good news
With a workload that does cross the threshold (4000 events, 200/slice, color group ~180), everything checked is bit-identical at 1/2/4/8 threads, and identical between the rayon and non-rayon builds:
All three rayon sites were also verified order-preserving by inspection: time_slice.rs:480 collects a Vec<EventUpdate> and applies it by zip over the range; history.rs:468 and :707par_iter().map().collect() then reduce in slice order.
So the parallel path is correct — this is a test-coverage defect, not a numerical one. But the test currently proves nothing about the thing it names.
Fix
Raise the events-per-slice so color groups exceed RAYON_THRESHOLD, or lower the threshold under cfg(test). Better still, assert that the parallel branch was actually taken, so the test cannot silently stop covering it again if the threshold or the fixture changes.
Compare all competitors' curves, plus log_evidence, final_step and iterations.
Add a cross-process determinism check (spawn the same binary N times and compare f64::to_bits), since the in-process form cannot see hasher-order effects at all.
The determinism test is the crate's guarantee that `rayon` changes nothing. It does not run the code it is guarding.
## The parallel branch is unreachable in that fixture
`sweep_color_groups` (`src/time_slice.rs:454-500`) takes the `par_iter` branch only when `group_len >= RAYON_THRESHOLD` (64). The test builds 200 events at `time = ev_i / 10 + 1` — 20 slices of 10 events. A color group is a subset of **one slice's** events, so `group_len <= 10 < 64`. The branch cannot be taken.
Confirmed by CPU-vs-wall time rather than by reading alone:
```
10 ev/slice (the test shape), RAYON_NUM_THREADS=8 : real 0.82 user 0.64 sys 0.24 <- ~1 core
500 ev/slice, RAYON_NUM_THREADS=1 : real 0.48 user 0.47 sys 0.02
500 ev/slice, RAYON_NUM_THREADS=8 : real 0.49 user 0.88 sys 1.15 <- >1 core
```
The residual thread activity at the test shape is `log_evidence_internal`'s `par_iter` over slices, not the sweep.
## Three further coverage gaps
1. **One competitor of forty.** It compares `learning_curve("p0")` only. A nondeterminism affecting any other competitor passes.
2. **`log_evidence` is never compared** — the quantity most exposed to accumulation order. Nor are `ConvergenceReport::final_step` or `iterations`.
3. **All four thread counts run in one process**, so the `HashMap` hasher seed is identical across them. Any nondeterminism from map iteration order is invisible to it *by construction* — which is exactly the defect in #62, and exactly why that one went unnoticed.
## The good news
With a workload that **does** cross the threshold (4000 events, 200/slice, color group ~180), everything checked is bit-identical at 1/2/4/8 threads, and identical between the `rayon` and non-`rayon` builds:
```
ranked digest=4ab5d3baa751487f le=c09062f06e1ec287
step0=3e8256d868000000 step1=3e64fb25d0000000 iters=8
scored digest=59f6c6501eca16cc le=c0caa1c6cff4f1be
filt_le=c0cb42eeaa0852c2 iters=21
lcurves digest=e302633757831a43
```
All three `rayon` sites were also verified order-preserving by inspection: `time_slice.rs:480` collects a `Vec<EventUpdate>` and applies it by `zip` over the range; `history.rs:468` and `:707` `par_iter().map().collect()` then reduce in slice order.
So **the parallel path is correct** — this is a test-coverage defect, not a numerical one. But the test currently proves nothing about the thing it names.
## Fix
- Raise the events-per-slice so color groups exceed `RAYON_THRESHOLD`, or lower the threshold under `cfg(test)`. Better still, assert that the parallel branch was actually taken, so the test cannot silently stop covering it again if the threshold or the fixture changes.
- Compare **all** competitors' curves, plus `log_evidence`, `final_step` and `iterations`.
- Add a cross-**process** determinism check (spawn the same binary N times and compare `f64::to_bits`), since the in-process form cannot see hasher-order effects at all.
Depends on / relates to #62.
Found by a floating-point audit, 2026-09-09.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
The determinism test is the crate's guarantee that
rayonchanges nothing. It does not run the code it is guarding.The parallel branch is unreachable in that fixture
sweep_color_groups(src/time_slice.rs:454-500) takes thepar_iterbranch only whengroup_len >= RAYON_THRESHOLD(64). The test builds 200 events attime = ev_i / 10 + 1— 20 slices of 10 events. A color group is a subset of one slice's events, sogroup_len <= 10 < 64. The branch cannot be taken.Confirmed by CPU-vs-wall time rather than by reading alone:
The residual thread activity at the test shape is
log_evidence_internal'spar_iterover slices, not the sweep.Three further coverage gaps
learning_curve("p0")only. A nondeterminism affecting any other competitor passes.log_evidenceis never compared — the quantity most exposed to accumulation order. Nor areConvergenceReport::final_steporiterations.HashMaphasher seed is identical across them. Any nondeterminism from map iteration order is invisible to it by construction — which is exactly the defect in #62, and exactly why that one went unnoticed.The good news
With a workload that does cross the threshold (4000 events, 200/slice, color group ~180), everything checked is bit-identical at 1/2/4/8 threads, and identical between the
rayonand non-rayonbuilds:All three
rayonsites were also verified order-preserving by inspection:time_slice.rs:480collects aVec<EventUpdate>and applies it byzipover the range;history.rs:468and:707par_iter().map().collect()then reduce in slice order.So the parallel path is correct — this is a test-coverage defect, not a numerical one. But the test currently proves nothing about the thing it names.
Fix
RAYON_THRESHOLD, or lower the threshold undercfg(test). Better still, assert that the parallel branch was actually taken, so the test cannot silently stop covering it again if the threshold or the fixture changes.log_evidence,final_stepanditerations.f64::to_bits), since the in-process form cannot see hasher-order effects at all.Depends on / relates to #62.
Found by a floating-point audit, 2026-09-09.