Commit Graph

4 Commits

Author SHA1 Message Date
Levi Neuwirth 306871ea29 Finish Agent B (item 5): tolerance/overflow, region-overlap honesty, id lock-down
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>
2026-06-21 18:48:03 -04:00
Levi Neuwirth f5aaa96b11 Land whole-score codec (item 5) and flip the M3 full-Score gate green
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>
2026-06-21 18:15:07 -04:00
Levi Neuwirth e9c4bad7a6 Land M1 + M2 (Agent C): framework edge fixes and real-Score graph integration
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>
2026-06-21 16:37:51 -04:00
Levi Neuwirth a2e9ec32f6 A B C D F 2026-06-19 12:42:31 -04:00