Adds the tamper-evident event stream that makes every DV auditable. Each
measurable moment is appended as one JSON object per line to an append-only
output/sor-runs/<ts>/events.jsonl over the closed vocabulary {consent_request,
consent_accept, consent_reject, circuit_build, hop_add, bridge_forward,
churn_kill, churn_spawn, rebuild_start, rebuild_done}; on close the file is
SHA-256'd and the digest is sealed exactly once into manifest.json (the single
sanctioned None->hash completion of the manifest).
Records carry only metadata (fingerprints, byte counts, latencies, decisions),
never message plaintext, so the zero-knowledge relay property is preserved. The
deterministic replay_fixture_circuit emits a seed-driven event stream with no
engine, socket, or traffic (containment-safe) and is the basis of
instrument-validation gate item 6.
- cmd_chat/sor/events.py: EventLog (append-only, per-record schema),
replay_fixture_circuit, replay_and_seal.
- cmd_chat/sor/provenance.py: seal_manifest (seal-once events SHA + stop ts).
- tests: replay -> schema-valid JSONL whose SHA matches the manifest;
append-only (original prefix byte-identical after further appends);
seed-determinism modulo timestamps; seal-once immutability.
Live emit wiring into the _sor handlers lands with R4/R5.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
write_manifest() freezes at circuit-experiment start everything needed to
reproduce and audit a SOR run and writes an immutable
output/sor-runs/<ts>/manifest.json: the R1 --sor-seed, topology/selector/churn
schedule id, one persona fingerprint per participating node, worktree git SHA,
isolated engine kind + image digest, pip/cargo dependency freeze, and
start/stop timestamps. The events.jsonl SHA-256 field is reserved for R3.
Provenance only: no forwarder, no engine spawned. Defense-in-depth to keep
containment load-bearing, the schema refuses to record a non-isolated
("local") engine at run or node level; the binding assertion still lands with
the R4 forwarder.
- cmd_chat/sor/provenance.py: Node/RunManifest, node_fingerprint (bit-for-bit
mirror of persona.rs::fingerprint_of), git/deps capture, explicit
dependency-free schema validator.
- hh/src/persona.rs: fingerprint_of known-vector parity test.
- tests: R2 acceptance predicate (manifest present + schema-valid, non-empty
seed, >=1 fingerprint/node), immutability, containment rejection of local
engines, and cross-language fingerprint parity.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>