Spec-revision pass (architecture unchanged) converting the v0 implementation's provisional, golden-locked choices into ratified core_spec.tex text, so durable byte layouts are fixed before the next-phase build-outs. Worklist: spec/PASS11_WORKLIST.md; per-item dispositions: spec/PASS11_RATIFICATION_LOG.md. Adopt-and-pin (bytes): TypedObjectId 16-bit BE discriminant table 0..=27 (added the 5 variants the code carried); promoted-voice (MUSCSVCE), synthetic-pitch (MUSCSPCH, tuning always in identity), and integrity-anomaly (MUSCSANM, now a reserved built-in tag) derivations; ChunkKind/ProfileId/CompressionAlgorithm discriminants; ManifestId preimage (manifest_id excluded); RationalTime/scalar layouts + the codec convention baseline the Binary Format companion inherits. Decide-and-pin: tempo Linear interpolates speed (not bpm); StructuralFieldCollision tags the winner Conflicted; lifted the >2-way / partial-overlap voice-promotion rule to normative; pinned TransactionCategory and ObjectKind core vocabularies; added ResolutionAction::Dismiss so the Dismissed state is reachable by an authored op; pinned the (non-canonical) LayoutObjectId derivation (MUSCLOID). Fixes: blob hashing is bare MUSCBLOB||payload (deleted the contradictory "identically to chunks" phrasing); equal-generation superblock rule (DivergentSameGeneration); defined ProfileConstraints with the required RetentionPolicy + first-declared precedence; made the DVV zero-based floor normative; reconciled the invariant count to 19 and named the three construction-time MUSTs — TupletRatio now rejects degenerate ratios at construction (zero term or actual==notated), enforced by a checked constructor + codec decode validation. Code changes carry regression tests; byte-layout golden tests now cite their ratified requirements. Workspace green: cargo test, clippy -D warnings, fmt; spec builds (lualatex, 253pp). Per-crate DECISIONS files annotated with the ratification status. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011giSRaHCFCGm1Z2SWv6JHt |
||
|---|---|---|
| .. | ||
| examples | ||
| src | ||
| tests | ||
| Cargo.toml | ||
| README.md | ||
README.md
epiphany-determinism
The reproducibility-contract primitives for Epiphany, implementing the
normative requirements of Appendix D (Determinism Contract) of the core
specification (spec/core_spec.pdf). This is Agent A's crate per
spec/QUICKSTART.md: the smallest scope, landing first, with every other
crate depending on it.
Canonical document state must be independent of platform, CPU, locale, thread scheduling, hash-map iteration order, floating-point environment, compression settings, and wall-clock timing. — Appendix D, Thesis
Everything in this crate exists to make that hold by construction. It is pure value types and pure functions: no async, no I/O, no platform calls. It is the strict single-threaded baseline that every parallel or accelerated implementation must reproduce bit-for-bit.
What's here
| Area | Items | Spec |
|---|---|---|
| Spatial grid | QuantizedCoord (1/1024 staff space, round-ties-to-even) |
App. D §"Quantized Layout Coordinates"; Ch. 7 §7.2 |
| Content addressing | ContentHash, ChunkId, blake3_256, trunc64, trunc128, Preimage, derive_system_counter |
Ch. 8 §"Content Hashing"; Ch. 5–6 derivations |
| Domain tags | DomainTag (closed vocabulary) + MUSC* constants, SystemDomainTag, bundle/superblock magic |
Ch. 8 §"Domain-Separated Preimages"; Ch. 5 §"System-Derived" |
| Tolerances | Tolerance, ToleranceClass (the five classes), ToleranceGovernance |
App. D §"Tolerance Classes" |
| Float hygiene | CanonicalF64, canonical_f64_bytes, canonicalize_zero, debug_assert_canonical |
App. D §"Floating-Point Values in Canonical State" |
| Canonical order | CanonicalEncode/CanonicalDecode, sort_canonical, CanonicalMap/CanonicalSet |
App. D §"Ordered Iteration over Sets and Maps" |
| Fuzz harness | fuzz::run_round_trip_fuzz, examples/fuzz_roundtrip |
hand-off gate |
The three determinism rules this crate enforces mechanically
- No NaN/inf/
-0.0in canonical state.CanonicalF64is the only way to put a float into canonical form; it rejects NaN/inf and maps-0.0to+0.0. Canonical equality is byte equality of the little-endian serialization. Decode rejects non-finite payloads as corruption. - All hashing is domain-separated BLAKE3-256.
Preimageputs the 8-byteDomainTagfirst, every time.DomainTagis a closed vocabulary (built-ins plusMUSCSextension tags, printable ASCII) with a private field, so a foreign or non-ASCII tag can't be minted;derive_system_countertakes aSystemDomainTag, so only a system tag can seed a system identifier.trunc64/trunc128take the leading bytes big-endian, matching the spec's reference code exactly. - Canonical iteration is a specified total order. Reach for
CanonicalMap/CanonicalSet(BTree) instead ofHashMap/HashSet, orsort_canonical(gated onCanonicalByteOrder) before it affects canonical output.
Implementation decisions
Per QUICKSTART "Decisions you'll need to make", the calls that touch this crate:
- Sync only (decision 4). No async traits anywhere; nothing here needs them.
blake3is the sole dependency. One content-hash algorithm for this format version (Ch. 8); no second hash, no RNG dependency (the fuzz harness uses a vendored SplitMix64 so failures reproduce from a seed).- MSRV 1.77 for
f64::round_ties_even. The spec uses no exotic Rust features;overflow-checksstay on in release so identifier/coordinate arithmetic faults loudly rather than wrapping. unsafeis forbidden crate-wide (#![forbid(unsafe_code)]).
Building and testing
cargo test -p epiphany-determinism # unit + integration + 1M fuzz gate
cargo clippy --all-targets -- -D warnings # lint clean
cargo run --release --example fuzz_roundtrip -- 10000000 # extended soak
Hand-off criteria (QUICKSTART, Agent A)
cargo testclean.- Round-trip canonical encode/decode fuzz harness runs 1M iterations
without panic (
fuzz_round_trip_one_million_iterations; extended soak via the example binary).
Scope boundaries
ChunkKind, SchemaVersion, ChunkRef, and the full chunk hash_preimage
live in epiphany-bundle (Agent D); the typed graph identifiers and the full
derive_conflict_id live in epiphany-core/epiphany-ops (Agents B/C). This
crate provides only the shared primitives those derivations compose from
(DomainTag, Preimage, trunc64/trunc128, canonical float bytes), so
there is no dependency cycle and exactly one definition of each contract type.
Ambiguities encountered while building are not resolved in code — they are batched as Pass 11 candidates against the spec (QUICKSTART, Process notes). None were required for this crate.