Files
hack-house/tests/test_sor_config.py
T
leetcrypt c04f9aed23 R1: deterministic --sor-seed core for reproducible measurement
Adds the single stochasticity source for the SOR measurement instrument so
every later stochastic decision (path selection R4, churn/selector R7, padding
jitter R4) is driven by one --sor-seed and is byte-reproducible run-to-run —
the R1 acceptance check and instrument-validation gate item 2.

- hh/src/sor/mod.rs: SplitMix64 + SHA-256 domain-separated sub-streams +
  unbiased Lemire bounded sampling -> deterministic select_path/bringup.
  Pure bookkeeping: no forwarder, no socket, no engine. Isolated-engine
  containment assertions land with the R4 forwarder.
- hh/src/main.rs: `sor-bringup --sor-seed` emits the deterministic
  circuit-build sequence as JSON (observable reproducibility).
- cmd_chat/sor/config.py: bit-for-bit Python mirror so the seed means the
  same thing on both sides.
- Tests (Rust proptest+unit, Python pytest): SplitMix64 known-answer vector,
  same-seed determinism, seed divergence, bounded/no-panic, and a shared
  cross-language parity vector asserted identically in both suites.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-19 14:47:07 -07:00

59 lines
1.9 KiB
Python

"""R1 — deterministic seed core, and cross-language parity with the Rust mirror.
The parity vectors below are asserted identically in
hh/src/sor/mod.rs::tests::parity_vector. If either language changes the
algorithm, one of the two test suites fails — that is the reproducibility
contract for `--sor-seed`.
"""
from cmd_chat.sor.config import Domain, SorRng, Stream, bringup, select_path
def test_splitmix64_known_answer():
# Canonical SplitMix64 from initial state 0 (published first outputs).
s = Stream(0)
assert s.next_u64() == 0xE220A8397B1DCDAF
assert s.next_u64() == 0x6E789E6AA1B965F4
assert s.next_u64() == 0x06C45D188009454F
def test_same_seed_identical_bringup():
# R1 acceptance check, primitive form.
assert bringup(0xDEADBEEF, 8, 3, 5) == bringup(0xDEADBEEF, 8, 3, 5)
def test_different_seed_diverges():
assert bringup(1, 12, 3, 4) != bringup(2, 12, 3, 4)
def test_domains_decorrelated():
rng = SorRng(42)
assert rng.stream(Domain.PATH).next_u64() != rng.stream(Domain.CHURN).next_u64()
def test_select_path_distinct_in_range():
path = select_path(SorRng(7), 6, 3)
assert len(path) == 3
assert all(0 <= h < 6 for h in path)
assert len(set(path)) == len(path)
def test_next_below_in_range():
for seed in (0, 1, 42, 0xFFFFFFFF):
s = SorRng(seed).stream(Domain.CHURN)
for n in (1, 2, 3, 5, 8, 1000, 999983):
for _ in range(32):
assert 0 <= s.next_below(n) < n
def test_select_path_degenerate_hops_ge_pool():
# hops >= pool returns a full deterministic permutation, no panic.
path = select_path(SorRng(3), 4, 10)
assert sorted(path) == [0, 1, 2, 3]
def test_parity_vector_matches_rust():
# These EXACT values are baked into hh/src/sor/mod.rs::tests::parity_vector.
assert select_path(SorRng(42), 8, 3) == [5, 0, 6]
assert bringup(123456789, 5, 3, 3) == [[4, 1, 3], [3, 2, 0], [3, 0, 4]]