The spec's domain-tag registry reserves a non-canonical MUSCLOID layout tag for
LayoutObjectId derivation (req:layoutir:object-id-derivation, Pass-11 item 2.6),
but it was never realized in code: layout-ir minted provisional, untagged ids and
synthesized objects borrowed MUSCCONF. This wires the ratified derivation.
- epiphany-determinism: add the reserved built-in DomainTag::LAYOUT_OBJECT_ID
(`MUSCLOID`), non-canonical/layout-namespace like FONT_METRICS (following the
SYSTEM_ANOMALY Pass-11 precedent of adding a reserved tag). The tag-enumeration
tests now derive from BUILTINS so they cannot drift; the spelling is locked and
from_bytes resolves it as a non-system builtin.
- layout-ir provenance.rs: all three LayoutObjectId derivations route through
MUSCLOID exactly per the requirement -- single keyed on source.canonical_bytes(),
multiply-manifested on (source, region), synthesized on (source, synthesis_kind,
instance_key); synthesized no longer borrows MUSCCONF. A reference-lock test
pins the derivation and proves it is genuinely domain-separated; another asserts
the three keying schemes do not collide (safe by the discriminant-led,
fixed-width canonical_bytes).
- layout-ir engraving.rs: EngravingDecisionId borrowed MUSCCONF for the same
reason; moved it onto MUSCLOID too, keeping its `engraving-decision` prefix so it
cannot alias a layout-object id within the namespace.
Layout ids are non-canonical (never document state, in no content hash), so this
changed id *values* but no durable or interchanged artifact: the only golden churn
is the data-prov hex in the four render goldens (every changed line is a data-prov;
geometry/structure byte-identical).
Spec/status sync: core_spec.tex descriptive notes (the requirement tail, the
domain-tag registry row, the registry intro, and the revision-history entry) now
say the reference implementation wires MUSCLOID as of P12-I2; MUSCLOID is moved out
of the "deferred to the companions" (not-ratified/provisional) list and given a
non-canonical anchor paragraph after the reference-implementation-locks table.
PASS12_BATCH.md marks P12-I2 resolved; PASS11_RATIFICATION_LOG.md keeps the
historical row with a "superseded by P12-I2" note; layout-ir/DECISIONS.md updates
the ratified-block note, the id bullet, and the open candidate (now RESOLVED).
Full gate green: build, fmt, clippy, 587 tests, conformance scale 1.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|---|---|---|
| .. | ||
| 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.