Reproducibility and validation
Cursor records and replay manifests
An owned fixed-path sequence needs a canonical cursor record and a compatible stream ID for replay:
record = cursor_checkpoint(freeze(rng))
cursor = restore_cursor(record)
@assert cursor_position(cursor) == cursor_position(freeze(rng))The record contains the schema version, owner UUID, generator ID, stream ID, key codec, key words, block, lane, and extension table. It omits the package version, revision, timestamps, machine data, and sampler configuration.
The built-in stream IDs are:
counter-cursor-philox4x32-10-v1counter-cursor-philox4x32-7-v1counter-cursor-threefry2x32-v1counter-cursor-ars5-v1counter-cursor-squares64-v1
Cursor restoration alone does not reproduce a full application. For generic Random, Distributions, Turing, AbstractMCMC, or other consumers, retain a separate manifest. Record exact Julia, package, consumer, and dependency versions. Also record the machine and worker layout, sampler configuration, model and callback fingerprints, chain count, and starting cursor.
The canonical record exposes the complete key and position. Validation does not authenticate, encrypt, detect substitution, or recover corruption. Add those properties with a caller-owned envelope.
Public vectors
test/public_vector_matrix.jl covers generator blocks and the immutable key surface. test/cursor_public_vectors.toml covers cursor families, starting lanes, alignment, mutable calls, checkpoints, and terminal boundaries. The Distributions fixture covers the fixed cursor distributions.
Golden records compare only canonical checkpoint fields. A separate acceptance manifest records provenance. Every host has ARS5 metadata, but hosts without AES skip execution.
Regenerate vectors only for an approved stream change. A changed cursor vector requires a new stream ID, a migration note, and backend acceptance.
CI matrix
Release CI separates these scopes:
- focused Random dispatch, sampler, value, consumption, inference, allocation, and ambiguity checks on Julia 1.10, 1.11, and 1.12;
- full core suites on Julia 1.10 and latest stable;
- the focused matrix on nightly as an advisory allowed-failure job;
- each isolated extension on its supported minimum and latest Julia versions;
- the isolated Turing and AbstractMCMC suite on its supported Julia range;
- executable notebook, documentation, and example jobs; and
- isolated Aqua and focused JET quality checks.
The main package uses only the Random and Serialization standard libraries at runtime. Optional and quality dependencies remain in isolated environments.
A Julia release becomes replay-validated after the focused hook matrix passes on that release.
CPU and CUDA release gates
Performance reports remain outside the candidate tree. Binding CPU rows cover a homogeneous scalar chain against the frozen legacy adapter, a 2^20 fill, and packed BitArray generation. Each row uses warmed paired samples in one process and a band of max(3 * robust_sigma, 5%). Scalar primitive rows permit no compiled allocations. An injected slowdown must fail a binding row.
The 0.1.0 accelerator qualification covers Philox4x32 and Threefry2x32 on the KernelAbstractions CUDA backend. Its twelve rows test rand!, randn!, and randexp! with Float32 and Float64 at length 2^20.
Each row verifies a real CuArray and CUDA.CUDABackend(), device-side mutation, synchronization, raw inputs, pre-transform values, ending and terminal cursors, and paired mutable-to-immutable overhead at most 1.05. Normal and exponential acceptance uses direct ULP distance, disjoint calibration and acceptance cursor ranges, a 32-ULP ceiling, and a deliberate perturbation that must fail. A device slowdown must also fail.
The primary acceptance host is batserv01. The fallback hosts are cslg-02 through cslg-04. Each binding report records the host, device, driver, backend, Julia, package, and dependency versions, stream IDs, transforms, arithmetic law, commit, Git tree, and tracked worktree state.
Reactant and Enzyme use separate accelerator tests. CPU tracing or AD tests do not prove accelerator execution. Reactant support in 0.1.0 is an experimental functional preview. A100 functional acceptance passed, but the qualification rows failed. In one Reactant 0.2.279 A100 run, the full mutable lifecycle measured 5.05 to 8.43 times the immutable graph across twelve length-2^20 rows. A separate minimal device-resident Philox rand(Float32) shape without transfers measured 1.1964 times as much. Reactant has no performance guarantee. Use the qualified KernelAbstractions CUDA path for supported host-dispatched GPU fills.
External statistical checks
The on-demand policy requires a 1 GiB local smoke test for every stream mode. PractRand processes 1 TiB for each supported raw generator stream and 256 GiB for family, split, fold, range, and conditioned-key streams. BigCrush tests one raw and one derived stream for each generator. Each configured class uses three fixed seeds.
Reports retain the commit, host, Julia, package, and tool versions, seed, mode, byte count, command, status, and raw output. The report states are pass, fail, and incomplete. ARS5 without AES is unavailable, not fail.
The full statistical gate applies to core and key-derivation changes. Block on confirmed Philox R10, Threefry, ARS5, or transform failures. Fix or remove experimental R7 and Squares64 streams when their validation fails.