Closes the three remaining item-5 sub-parts found in the audit.
② Typed tolerance + overflow (tempo.rs, invariants.rs):
- Replace the ad-hoc `f64::EPSILON` speed-degeneracy guards with a named
TempoIntegration `Tolerance` (relative, non-finite-safe), per Appendix D
"no ad-hoc epsilons"; aligns code with the module's own claim.
- Guard the continued-fraction convergent recurrence with checked i128 ops
(break on overflow) and bound the residual-fraction stop by 1/max_den
instead of f64::EPSILON, so a pathological input can't silently wrap.
- Endpoints::of: wall-clock event end uses checked_add -> Endpoints::Unknown
on overflow, not saturating_add (which could mask an ordering violation).
- Regression tests: equal-endpoint linear segment uses the constant limit;
extreme inversion inputs don't overflow.
① Region-overlap honesty (invariants.rs):
- Unresolvable region-overlap checks (symbolic anchors + shared staff extent)
were silently treated as valid. Add DeferredCheck + deferred_checks() to
surface them explicitly; check_invariants stays sound (no false positives).
- Test proves an undecidable overlap is reported as deferred, not passed, and
that a wall-clock-resolvable disjoint pair is neither violation nor deferred.
③ Identifier-derivation lock-down (graph.rs, pitch.rs, ids.rs):
- Golden-bytes tests pin derive_promoted_voice_id (MUSCSVCE 64-byte preimage),
derive_system_pitch_id (MUSCSPCH input layout), and the TypedObjectId
discriminant table + Registered layout, so an accidental layout change is
caught (the derivations were concrete but unlocked).
- canonical_pitch_bytes NFC-normalizes strings at the derivation boundary,
making the documented NFC guarantee explicit (no-op for the already-NFC
catalog ids).
- DECISIONS P11-1/3/6 updated to record the pinned-and-locked layouts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Implements a total, reversible canonical byte form for the entire
epiphany_core::Score graph, unblocking the byte-level full-Score serialization
gate that M3 had to defer.
epiphany-core/src/codec.rs:
- Score::canonical_bytes() / Score::decode_canonical() with a validating
ScoreDecodeError and a forward-only Reader cursor.
- A local Codec trait with generic combinators (Option/Vec/BTreeSet/BTreeMap/
tuple) and macros (struct_codec!/cstyle_enum_codec!/unit_codec!/
catalog_id_codec!) so encode and decode stay symmetric across ~110 types
spanning graph.rs, event.rs, pitch.rs, time.rs, tempo.rs.
- Uniform form: LE integers, one discriminant byte per tagged union, u32
counts/length-prefixes, every variable-width leaf length-prefixed, raw UTF-8
for free text (so decode(encode(x)) == x for any valid score; catalog ids are
already NFC). EventArena round-trips via iter_canonical + insert.
- Two pub(crate) accessors added for the codec: EventOrderingDAG::edges_ref,
SpellingPrecedence::order_ref.
- Tests: generator-score corpus (valid_score + valid_score_rich), exotic
event/pitch variants the generators omit, distinctness, and decoder
rejection of trailing/truncated/empty bytes.
epiphany-testkit:
- roundtrip::assert_score_serialization_stable: encode the real Score, store it
as a bundle Snapshot, reopen + hash-verify, decode to an equal Score, and
assert a byte-identical re-encode.
- convergence::materialized_score builds a real ~50-bar reduce_onto
materialization for the gate.
- criterion_4_full_score_byte_roundtrip flips from #[ignore] to a live gate;
wired into the conformance suite. Docs (lib.rs, README, core DECISIONS P11-4)
updated to reflect the landed codec.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The audit flagged Agent F's criterion 1 (convergence) and criterion 4
(serialization) as testing the reducer-bookkeeping projection
(MaterializedState) while claiming to be full-Score gates. This makes them
honest, per item 4 of the v0 follow-up plan.
Criterion 1 — real-Score convergence:
- generators::graph_edit_session builds a real ~50-bar, two-voice edit
session targeting a base Score's actual voices (so it survives reduce_onto,
which rejects unknown voices).
- convergence::{assert_graph_convergence, run_graph_convergence} reduce that
session onto a real epiphany_core::Score via OperationSet::reduce_onto and
assert the entire GraphMaterialization (graph + bookkeeping) is identical
across delivery orders, passes check_invariants, and genuinely grows both
voices (non-vacuity).
- acceptance criterion_1_convergence now drives this; the former bookkeeping
convergence is retained and renamed reducer_bookkeeping_convergence.
Criterion 4 — honest serialization tiers:
- criterion_4_canonical_serialization_stability keeps the real typed/manifest
round-trips; the MaterializedState round-trip is split out as
reducer_bookkeeping_serialization.
- full_score_materialization_is_reproducible asserts the materialized Score is
reproducible across orders (the determinism precondition for a byte codec),
achievable without the codec.
- criterion_4_full_score_byte_roundtrip is #[ignore]'d pending item 5's
whole-score codec (visible as ignored, never falsely green).
Negative regression guards (src/negative.rs): one guard per audited M1 defect
(inverted causal/HLC order, missing predecessor via vector, HLC 100/200/50
quarantine-from-0, tx rollback of member conflicts, causally-ordered
same-position non-promotion, partial-duration overlap), driven through the real
epiphany_ops API with explicit negative controls. Wired into acceptance and the
conformance suite. Crate/README docs updated to match.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
M1 — fix Agent C framework defects, tests-first:
- causal ordering: topologically order DVV edges instead of assuming HLC
alone implies causal order (false for adversarial remote envelopes);
HLC only breaks ties among ready operations.
- anomaly cutoff: quarantine from the earliest counter participating in
any violating HLC pair (suffix-minima), e.g. [100,200,50] quarantines
from counter 0, not counter 1.
- pending detection: DVV contiguous ranges use the zero-based per-replica
counter floor; first absent id in any asserted range holds the dependent
pending (vector coverage, not only dots).
- transaction snapshots: rollback removes member-generated conflicts.
- edge tests in concurrent_reduction.rs for all six audited cases.
M2 — reduce onto Agent B's real score graph:
- OperationSet::reduce_onto(&Score) -> GraphMaterialization { state, score }
mutates the real arena, voices, regions, tombstones, indexes, and
cross-cutting structures; base-free reduce() retained.
- VoiceOrigin::SystemPromoted now carries { winning_operation,
losing_operation, original_voice }; spec and Invariant 18 updated.
- graph-aware migration, forward undo, system breaks, promotion pre-pass.
- tests/graph_reduction.rs: 11 tests asserting check_invariants is clean,
plus a 64-seed order-independence sweep.
Pass-11 spec decisions resolved (blocking subset): DVV floor (P11-C7),
HLC-vs-causality, promoted-voice derivation inputs (P11-C4 / core P11-3).
Payload/Score canonical encoding remain deferred to the companion docs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Implements Agent E per spec/QUICKSTART.md — the layout intermediate
representation (Chapter 7) and the constraint-solver interface (Chapter 9):
* Four IR stages: LogicalLayoutIR -> ConstrainedLayoutIR ->
ResolvedLayoutIR -> RenderIR (interface only), with the composite-object
taxonomy, spring slots/constraints, vertical-band model, pages/systems,
engraving decisions + overrides, and the incremental dependency/cache model.
* TimeAxisModel tagged enum (Metric/Proportional/Aleatoric/Registered).
* Provenance back-references with manifestation- and synthesis-aware ids
((source, region) and (source, kind, ordinal)), so multiply-manifested and
synthesized objects never collide.
* In-tree Bravura GlyphCatalog (Send+Sync, metrics + render-data interface),
MUSCFNTM-tagged metrics hash with anchors hashed as a name-keyed map.
* Edit-barrier types keyed on OperationKindTag, with precise EditContext /
EditOracle scope/condition evaluation.
* StubSolver: returns SolveStatus::Solved with the input geometry verbatim;
spec-compliant SolveReport, Minimal tier + all-worst (unmeasured) metric
vector (no false conformance claim); rejects ill-formed input.
* f32 staff-space IR coordinates, quantized to the 1/1024 grid only at
canonical ResolvedLayoutIR serialization (Appendix D); non-finite geometry
is rejected, not normalized. Canonical encoding is injective in glyph
identity, provenance, engraving decisions, and catalog identity.
Re-points Agent F's testkit layout harness from its in-tree stub to the real
crate (v0 acceptance criterion 6) and expands its generators to E's public
surface. Expands Agent C's OperationKindTag to the full normative variant set
so edit barriers can prohibit every operation class.
Workspace gates green: fmt, clippy -D warnings, 377 tests, doc tests, rustdoc
-D warnings, and the conformance suite at scale 1. Decisions and Pass 11
candidates recorded in crates/epiphany-layout-ir/DECISIONS.md.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>