SetCanvasLayoutDefaults and SetSpellingPrecedence, kinds and tags 32/33, on the
SetMetadata LWW pattern: advisory last-writer-wins, no conflict, no idempotence
short-circuit, seeded from the base so a value-restoring undo of the first
operational write reaches the pre-operational value. Both carried types already
had Codec impls, so the packet designs no wire layout -- canonical_value!
delegation and one push_lp_bytes each, inheriting strict canonical-form
rejection rather than writing it.
Both stamp schema major 0 unconditionally, staying in the catch-all arm. The
op-block accept-set is untouched at 2; epiphany-bundle has an empty diff. The
raise to 3 belongs to G2b, and the chunk schema minor -- a MUST no writer has
ever honoured -- belongs to G-minor, filed as P13-S14 and deliberately not
fixed here.
Most of this commit is documentation the vocabulary had outgrown. G1 shipped
five normative falsehoods because its contract declared the wire surfaces out
of scope, and Push 4a left TransposeInterval out of both of core_spec's
normative listings. So binary_format's payload-layout and tag tables now reach
33 rather than 30, its snapshot-only bullet records that it is empty and why,
two spelled-out payload counts move from eight to nine, and core_spec's
listings gain all four missing kinds. The Pass-12 K8 doctrine is narrowed
rather than reversed: the root and canvas remain structural givens no operation
mints, and only the claim that the score's contents arrive outside the
operation set is superseded.
Two generators were stale by two tranches and fed corpora other suites treat as
exhaustive. layout_stub's is now derived from PAYLOAD_FREE with an explicit
Registered append instead of a hand-written match, so future built-ins follow
structurally; s10 asserts PAYLOAD_FREE union {Registered} so deleting that
append cannot pass.
Companion 0.8.0 -> 0.9.0, binary format 0.11.0 -> 0.12.0, catalog 0.9.0 ->
0.10.0 (covering G1 retroactively). 102 decode vectors, regenerated.
Coordinator verification: 1371 passed / 0 failed, clippy 0 warnings, fmt clean,
conformance 8/8 and 9/9, requirement_labels 6/6, four PDFs at 0 undefined
references, goldens byte-identical, accept-set confirmed still 2. Mutations
s3/s5/s7/s10 re-run independently and each observed to kill its test.
Two findings beyond the contract. max_supported_major is not reachable outside
epiphany-bundle -- mod bundle is private and the symbol is absent from its
pub use -- so the gate's "assert it in code" was unsatisfiable without touching
a crate the contract forbids; verified by reading the unedited source instead.
And core_spec carries two P12-K8 references, not one; the contract named only
the first, so the second is annotated here for consistency.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QjsEnYhm1gPpf6ii2iFxFV
|
||
|---|---|---|
| .. | ||
| examples | ||
| src | ||
| tests | ||
| Cargo.toml | ||
| DECISIONS.md | ||
| README.md | ||
README.md
epiphany-ops
The Epiphany concurrent semantics: the operations through which the score
graph becomes a live model, and the deterministic reduction by which a set of
operations becomes a materialized score state. Implements the normative
requirements of Chapter 6 (Semantic Operations and Concurrent Reduction) of
the core specification (spec/core_spec.pdf). This is Agent C's crate per
spec/QUICKSTART.md, building on Agent A's epiphany-determinism and Agent B's
epiphany-core.
A score's state is defined by the set of operations committed to it. Any materialized graph is a deterministic reduction of that set; caches, snapshots, and partial reductions are acceleration structures, never the source of truth. — Chapter 6, Design Principles
The thesis in one paragraph
The replicated operation set is a grow-only CRDT: replicas accumulate envelopes and converge on the same set. The materialized graph is not a CRDT — it is the deterministic reduction of that set in a single canonical order (causal-first, then the HLC tuple). Any permutation of the same envelopes reduces to byte-identical materialized state. That property is the determinism heart of the architecture, and the reduction fuzzer is its tripwire.
What's here
| Area | Items | Spec |
|---|---|---|
| Stamps | HybridLogicalClock, OperationStamp, the reduction & monotonicity tuples |
Ch. 6 §"Operation Identity and Stamps" |
| Causal context | CausalContext (dotted version vector), covers, the missing-predecessor signal |
Ch. 6 §6.2 |
| Payloads | OperationKind, the discriminator-only OperationKindTag, OperationPayload, the §6.10 representative ops |
Ch. 6 §"Operation Envelopes", §6.10 |
| Envelopes | OperationEnvelope, EnvelopeHash (MUSCENVH), well_formed (incl. stamp.id == id) |
Ch. 6 §6.4 |
| Slots | OperationSlot::{Single, Equivocated}, the order-independent (Pass-10) transitions |
Ch. 6 §6.5 |
| Anomalies | AnomalousReplicaSegment, IntegrityAnomaly/Kind, the HLC-monotonicity detector |
Ch. 6 §6.6; Ch. 5 §"System-Derived Counter Collisions" |
| Effects | OperationEffect, NoOpReason, the typed PreconditionFailureReason, RepairRecord/RepairKind |
Ch. 6 §6.3.2, §6.5 |
| Conflicts | ConflictRecord, ConflictKind, content-derived ConflictId (derive_conflict_id), the registry, resolution |
Ch. 6 §6.4 |
| Transactions / undo | TransactionDescriptor with the causal-prior-descriptor rule, UndoTransactionPayload / UndoPolicy |
Ch. 6 §6.6, §6.8 |
| Operation set | OperationSet: accept pipeline (well-formedness → slot → causal), grow-only |
Ch. 6 §"Envelope Acceptance" |
| Reduction | canonical_reduction_order (single function), MaterializedState, the reduction driver |
Ch. 6 §6.3 |
The determinism this crate enforces
- A single reduction-order function.
canonical_reduction_orderperforms deterministic causal topological ordering, using the intrinsic stamp tuple(physical, logical, replica, counter)only among ready operations. - Order-independent equivocation. A duplicate
OperationIdwith different canonical bytes transitions its slot toEquivocatedregardless of which envelope arrived first (Pass 10). Equivocated slots contribute nothing to reduction; dependents are held pending. - Content-derived facts.
ConflictIdandIntegrityAnomalyIdare derived from content, so two replicas reducing the same set agree on every conflict and anomaly id — the conflict registry and anomaly register are deterministic materialized facts, not local bookkeeping. - Byte-identical materialized state.
MaterializedState::canonical_bytesserializes the effect log, conflict registry, anomaly register, object existence, spellings, and LWW fields in their normative orders. - Real graph materialization.
OperationSet::reduce_onto(&base_score)returnsGraphMaterialization { state, score }. The graph is mutated in the same canonical order and compares by canonical event identity, independent of arena storage order.
Hand-off gates
Run the gate harnesses (QUICKSTART, Agent C):
cargo test -p epiphany-ops
cargo run --release -p epiphany-ops --example fuzz_reduction # 10k iters, seed 0
cargo run --release -p epiphany-ops --example fuzz_reduction 100000 7 # soak, seed 7
- Reduction determinism — every randomized envelope set reduces to byte-identical materialized state under any acceptance order (v0 acceptance criteria 1 and 5).
- Equivocation order-independence — every duplicate-id-with-different-bytes scenario equivocates regardless of arrival order (v0 acceptance criterion 3).
The integration tests (tests/concurrent_reduction.rs) exercise these plus
transaction atomicity, descriptor precedence, anomaly exclusion, and forward
undo through the public API.
Scope and decisions
Chapter 6 specifies the framework and a representative selection of
operations; the full ~60–80-primitive catalog is an explicit open question
(§6.11) deferred to the Operation Catalog companion. This crate implements the
framework in full and the representative operations, which is sufficient to
exercise every reduction discipline. The representative operations can also
reduce onto an epiphany_core::Score: insert/delete, voice promotion, supported
cross-cutting structures, system breaks, migration checks, transaction
rollback, and undo mutate the real graph while preserving Agent B's invariants.
reduce() remains the base-free CRDT/bookkeeping API; reduce_onto() is the
graph-aware editing path. See DECISIONS.md for remaining payload boundaries.
Per QUICKSTART "Don't do these": undo is the spec's forward compensating
operation, never inverse-based; unsafe is forbidden; everything is sync.