epiphany/crates/epiphany-determinism/README.md

88 lines
4.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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. 56 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
1. **No NaN/inf/`-0.0` in canonical state.** `CanonicalF64` is the only way to
put a float into canonical form; it rejects NaN/inf and maps `-0.0` to
`+0.0`. Canonical equality is byte equality of the little-endian
serialization. Decode rejects non-finite payloads as corruption.
2. **All hashing is domain-separated BLAKE3-256.** `Preimage` puts the 8-byte
`DomainTag` first, every time. `DomainTag` is a closed vocabulary (built-ins
plus `MUSCS` extension tags, printable ASCII) with a private field, so a
foreign or non-ASCII tag can't be minted; `derive_system_counter` takes a
`SystemDomainTag`, so only a system tag can seed a system identifier.
`trunc64`/`trunc128` take the *leading* bytes **big-endian**, matching the
spec's reference code exactly.
3. **Canonical iteration is a specified total order.** Reach for
`CanonicalMap`/`CanonicalSet` (BTree) instead of `HashMap`/`HashSet`, or
`sort_canonical` (gated on `CanonicalByteOrder`) 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.
- **`blake3` is 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-checks` stay on in release so identifier/coordinate
arithmetic faults loudly rather than wrapping.
- **`unsafe` is forbidden** crate-wide (`#![forbid(unsafe_code)]`).
## Building and testing
```sh
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)
- [x] `cargo test` clean.
- [x] 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.