Commit Graph

13 Commits

Author SHA1 Message Date
Levi Neuwirth aff1809421 Pass 12 G-pass: ratify the full batch (28 rows) — spec tranche
The G-ratification pass over the accumulated PASS12_BATCH backlog
(worklist: spec/PASS12_WORKLIST.md; dispositions:
PASS12_RATIFICATION_LOG "G-pass tranche"). Four project-lead
decisions: K12 slur permission = AND, H7 authored-uninferred
annotations SURFACE, K4 ResolveConflict = no supersede, K8 genesis
outside the operation set. Three named deferrals: H2 (narrowed;
spelling-v2 + notation refinement), K2 (tuning catalog), K5 (Profile
Conformance companion).

core_spec: spelling + decomposition move to profile-declared with
ratified v1 defaults (req:pitch:spelling-algorithm,
req:time:decomposition-algorithm — two open-question boxes closed);
authored-uninferred surfacing (req:pitch:authored-uninferred);
decomposition precedence pinned FIXED; system-derived content
immutability (K3); genesis note (K8); slur AND advisory (K12);
re-anchoring table C1/C2/C3 + SameCanvasNearer variant (C4); barrier
matching + unsafe-tombstone semantics (req:format:barrier-matching,
req:format:unsafe-tombstone); solver kind-strength /
sub-conformant-report / Minimal-floor requirements (I4/I5/I6); stale
OperationKindTag listing gains the eleven appended tags.

operation_catalog 0.5.0 -> 0.6.0: K1 migration fallback long-term;
K4 no-supersede; K6 edge semantics (single-pass, quarantine excluded,
pending governs); K5 deferral pinned; K8 slots RETIRED; K10 reuse
blessed; K11 asymmetry normative; K12 AND; K2 prototype pin;
K3/K9 preconditions.

binary_format 0.3.0 -> 0.4.0: appended vocab discriminants
SystemDerivedContentImmutable(12), RecreateContentMismatch(13),
SameCanvasNearer(6); E5 tombstone-encoding open question.

All three PDFs rebuilt clean, zero undefined references. Batch rows
struck 28 -> 0 (tracker CLOSED); CONFORMANCE.md caveat dropped;
DECISIONS cross-refs in core/ops/layout-ir/editor-core (new file).

Code tranche (H7 surfacing, K3/K9/C4 discriminants) follows.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NEs4aYiu8MXjdYdMxw8PTd
2026-07-07 10:23:30 -04:00
Levi Neuwirth 0316160395 Phase 3 tranche 1: casting-off, K1 schema-fill, value-restoring undo
The chosen Phase-3 attack, run as two parallel waves. 829 workspace
tests pass; clippy -D warnings, fmt, and rustdoc clean; all three
spec documents build with zero undefined references.

Casting-off (epiphany-engrave/src/casting.rs, wired into the
Engraver):
- Greedy first-fit system breaking per region at measure-start
  barline columns; a measure that would overflow the content width
  starts a new system. Hard SystemBreakAt/PageBreakAt always
  honoured; soft breaks honoured unless pathological (skipped with
  the spec's warning + IrOverride-recorded decision).
- Vertical stacking from real content extents with the inter-system
  gap read from the vertical band model; page overflow starts the
  next page. World frame: pages stacked vertically, coordinates
  baked into glyphs/strokes, so the SVG renderer, hit-testing, and
  the GUI viewport are unchanged.
- Real ResolvedPage/ResolvedSystem trees (1-based page numbers,
  content bounding boxes, staves from staff-line segments, measures
  from barline columns); every chosen break appends an
  EngravingDecision with MUSCLOID EngravedBreak provenance,
  UserOverride-attributed via the new ConstrainedLayoutIR
  break_origins sidecar; staff lines split per system with
  synthesized continuation provenance.
- Break-constraint evaluation flips: satisfied iff the layout breaks
  at the slot. The two single-system tests invert deliberately
  (a hard break is now honoured; a user break is honoured and
  attributed instead of warned). Geometric constraints evaluate in
  the pre-casting spaced frame (documented).
- Page geometry is engraver-side PageGeometry (A4 portrait at an
  8 mm staff: page 105 x 148.5 staff spaces, margins 7.5, content
  90 x 133.5; arithmetic documented) — Canvas.layout_defaults has no
  graph home and is a schema-major addition (P12-I7).
  ENGRAVER_VERSION = 2. Goldens regenerated: ten_measure_single_staff
  engraves as 2 systems (viewBox 84x20.6, was 103x11);
  valid_score_rich as 3 systems; stub goldens byte-identical.

K1 schema-fill (Operation Catalog 0.4.0 -> 0.5.0, ratified first;
wire discriminants strictly appended):
- CreateStaff (24 / tag InsertStaff 24): set-union mint of a global
  Staff; CreateStaffInstance now preconditions that its referenced
  staff is live.
- SetTimeSignature (25): value-carrying meter-change LWW keyed by
  (region, resolved position); the carried TimeSignature mints
  set-union; StructuralFieldCollision on meter_sequence.
- SetTempoSegment (26): LWW keyed by (scope, resolved start) over
  the score or region tempo map; a write that would malform the map
  refuses with the appended PreconditionFailureReason 11
  (TempoMapMalformed).
- SetStaffLayout (27): LWW advisory over the staff instance's three
  inline layout fields.
- Create score/canvas remain deliberately unavailable slots: the
  root and canvas are inline singletons with no addressable object
  model (P12-K8), not force-designed.

Value-restoring undo (P11-C8 narrowed; catalog §UndoTransaction
rewritten and per-primitive undo notes updated):
- Canonical-order write chains (base-seeded) across all eleven LWW
  families. StrictInverse restores each written key to its
  chain-predecessor value iff the transaction's write is still the
  key's last writer, else refuses the whole undo with a
  TransactionConflict naming the superseder; BestEffort restores the
  still-last keys. Clean compensations are Applied; only minted-
  object tombstone repairs ride AppliedWithRepair (no new repair
  vocabulary). Mixed mint+overwrite transactions compose; strand
  guards refuse tombstoning mints still referenced by live
  non-members.
- Undo-of-undo pinned and tested: restorations are chain writes, so
  undoing the undo's transaction restores the undone value, and a
  second undo of the same transaction conflicts (absence-restores
  repeat idempotently — documented asymmetry, P12-K11).
- Permutation invariance pinned across five delivery orders; the
  convergence generators gain the new ops and a tx-then-undo flow.
- Still deferred in normative text: delete resurrection (needs a
  system-derived tag outside the ratified closed set), Transpose
  inversion (P12-K2), Cascade dependent closure.

Trackers: Binary Format companion 0.1.0 -> 0.2.0 (appended wire/tag
tables, PreconditionFailureReason 11, payload layouts, history row —
a schema-minor evolution under its own rules); nine new Pass-12 rows
(C5, K8-K11, I7-I10); core-spec OperationKind listing gains the four
kinds; revision-history rows in core spec and companion.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NEs4aYiu8MXjdYdMxw8PTd
2026-07-02 21:55:26 -04:00
Levi Neuwirth 3e91a8302a Push 4: Binary Format companion, F1 benches, subquadratic reduction order
The audit's fourth push: the biggest outstanding Phase-2 item plus the
performance gate. 793 workspace tests pass; clippy -D warnings, fmt,
and rustdoc (deny-warnings) clean; all three spec documents build with
zero undefined references.

Binary Format companion (spec/binary_format.tex, v0.1.0 — Agent J's
deliverable, 43 pages):
- Twelve chapters transcribed from the golden-locked implementation:
  encoding conventions (the three prefix/endianness regimes, a
  normative no-varint rule, reject-never-normalize decode discipline),
  identifiers imported from the core spec's Canonical Byte-Layout
  Reference, primitive value encodings, the whole-Score positional
  codec ratified as the schema-major-0 wire form, operation wire
  forms (envelope field order with the normative id-leads property,
  the OperationPayload 0..=3 and OperationKind 0..=23 tables,
  effects/conflict/anomaly/MaterializedState vocabulary), the bundle
  physical layout (64-byte header, 256-byte superblock, chunk
  preimages and framing, ChunkRef, manifest body order), the
  operation-index payload, and the extension-blob/edit-barrier byte
  forms.
- Ratifies P12-D1 (req:binfmt:opindex), P12-E1 (req:binfmt:ext-blobs),
  P12-E2 (req:binfmt:condition-depth, MAX_CONDITION_DEPTH = 64
  normative), and P12-E3 (req:binfmt:object-kind-open) — batch rows
  struck through; discharges the provisional-codec notes in core
  (P11-4), ops, and bundle (P11-D2/D4/D5) DECISIONS with ratification
  cross-references.
- Pins the frozen-layout schema-evolution keystone: within schema
  major 0 every positional struct layout is frozen; a field-set change
  is a schema-major change with migration — formally grounding the
  data-model-expansion staging decision. Open questions kept honest
  in-document: SnapshotId derivation, index-refresh threshold, u64/u32
  prefix unification at the next major.
- Not yet delivered from J's charter: the cross-implementation decoder
  test and the wire-format fuzzer (follow-up harnesses).

F1 benches (crates/epiphany-testkit/benches/, per the F0 decision):
- criterion 0.5.1 (workspace dev-dependency; MSRV 1.77 respected with
  documented transitive pins: clap 4.5.53, half 2.4.1).
- reduction bench at 1K/10K/50K envelopes with the Chapter-10 budget
  (>10,000 envelopes/second cold) written in the bench as a Pass/Xfail
  gate; bundle benches for the typical-edit commit (<=50 ms; measured
  ~14.7 ms on real disk after catching that tmpfs neuters fsync) and
  the open/bootstrap read (<=200 ms; measured ~60 us).
- CI: quick budget gates in the conformance job, full gates nightly.

Subquadratic canonical_reduction_order (the F-surfaces/K-fixes
handshake, closing K's 10K-envelope acceptance gate):
- The bench documented the failure (50K at ~1.7K env/s, a 29 s cold
  reduction; two O(n^2) loops); the fix replaces pair enumeration with
  threshold/frontier readiness per replica plus explicit-dot dependent
  lists and a stamp-tuple binary heap — O((n + sum(context)) log n),
  never materializing covered pairs.
- Byte-identical order: same edge relation, same ready predicate, same
  total order; the old implementation is retained as a test-only
  oracle with element-for-element order-equality property tests over
  fuzz sets, adversarial sets, and directed shapes (2,000-envelope
  full-coverage chains, dot cycles, duplicate-id stamp ties),
  mutation-tested for sensitivity.
- Measured: 1K 155K->674K env/s, 10K 12.5K->257K, 50K 1.7K->87K; all
  three scale points now pass and the 50K row is promoted from Xfail.

Also: fixed nine rustdoc private/unresolved intra-doc links that had
accumulated across the pushes (the CI deny-doc-warnings job would have
failed on them).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NEs4aYiu8MXjdYdMxw8PTd
2026-07-02 19:02:07 -04:00
Levi Neuwirth 92aaccf7e2 Pushes 1+3: fix the MUST-level violations, wire the types-only machinery
Two audit pushes whose code edits interleave line-by-line in the same
files (reduce.rs, bundle.rs, the DECISIONS logs), committed together so
the tree at every commit builds. Gate: 784 workspace tests pass, clippy
-D warnings clean, fmt clean.

Push 1 — the true MUST violations, all fixed:
- bundle: zstd read support on both read paths, output bounded by the
  declared uncompressed_length, typed decompression errors, explicit
  CompressedManifest rejection (zstd 0.13 workspace dep; write path
  stays uncompressed per the Phase-3 deferral).
- ops: system-derived counter collision check — mint registry seeded
  from the base graph, canonical-order pre-walk, halt via the new
  PendingReason::HaltedBySystemCollision (discriminant 4, additive)
  with transaction-atomicity and causal-dependent closure; neither
  input set occupies a collided counter. canonical_pitch_bytes made
  pub in core for the MUSCSPCH preimage.
- ops: Transpose skips tombstoned targets per the catalog; missing
  targets still refuse the whole operation.
- ops: marker re-anchoring recorded as a RepairRecord in the
  triggering operation's effect; ResolveConflict meta-conflicts name
  both resolvers; base-free pitch-id freshness; reserved effect
  vocabulary annotated.
- core: decomposition pre-pass honors authored attachments
  (resolve_decomposition, spec-default precedence); inversion
  tolerance typed as a TempoIntegration-class Tolerance.
- CONFORMANCE.md: the determinism conformance statement required by
  Appendix D — all seven declarations.

Push 3 — wiring the types-only machinery:
- layout-ir/engrave: to_constrained emits real constraints (successive
  notehead no-collision chains, per-glyph region containment, soft
  user-break constraints); ConstraintStrength{Required, Preferred}
  with strength-by-rule; Preferred violations surface as warnings, not
  failures; StubSolver reworked honest-but-renderable. SVG goldens
  byte-identical; snapshot constraint counts regenerated (0->90/15).
- layout-ir: to_logical projects user system/page breaks as anchored
  EngravingOverrides with paired UserOverride-sourced decisions
  (OverrideKind::SystemBreak/PageBreak carry TimeAnchor, ratified in
  the spec alongside).
- layout-ir/ops/editor-core: edit-barrier bridge — decode mirrors for
  the whole barrier tree (reject-never-normalize, NFC revalidation,
  MAX_CONDITION_DEPTH = 64), golden-locked blob codec for the
  ExtensionDeclaration fields, a barrier gate in apply and
  apply_transaction backed by a Score oracle and real containment
  contexts, and apply_unsafe recording the crossed extensions in
  extensions_requiring_tombstone() for the next bundle write.
- ops: ResolveEquivocation meta-operation per the newly ratified
  catalog entry — payload discriminant 3 (appended), set-level
  earliest-resolve-governs promotion, ResolveConflict-mirrored
  meta-conflicts, permutation-invariance fuzz; the missing golden
  locks on the OperationKind/OperationPayload wire tables added.
- ops/editor-core: validation modes — ValidationMode + a non-canonical
  advisory layer (validate.rs), an authoring gate before minting, and
  reduction pinned as replay mode by construction (canonical bytes
  untouched).
- bundle: the operation index (opindex.rs) — provisional golden-locked
  payload, binary-search locate, staleness defined as full-ChunkRef
  set equality against operation_roots, and the reject-and-rebuild
  discipline (a defective index is never bundle corruption).
- ops: re-anchoring rule table completed — the four-key "nearest"
  ordering computed from base-free ledger indices; markers re-anchor
  to the nearest live event in the same staff instance (replacing the
  Push-1 region-start stand-in); cue-source cascade; graphic-gesture
  Events/Range/Free rows; comment and analytical-annotation orphaning.
  Zero appended discriminants.

Spec enablers ratified with Push 3: catalog §ResolveEquivocation
(0.3.0 -> 0.4.0) and anchored break overrides; 16 new Pass-12 rows
filed (C1-C4, K5-K7, I4-I6, D1, E1-E5). The data-model payload
expansion (SlurKind, beam geometry, voltas, instrument bodies,
metadata) is deliberately staged to the Binary Format companion — the
positional graph codec has no value-level versioning, so filling those
structs is a schema-major break that should land once, with J.

Also carries the pre-existing editor-track increment: the atomic
tuplet overwrite (CascadeDeleteTuplets prunes decomposition
attachments naming the cascaded tuplet).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NEs4aYiu8MXjdYdMxw8PTd
2026-07-02 17:10:50 -04:00
Levi Neuwirth b3403c1d6a ops: ModifyEvent materializes metric placement changes (trim/move)
The make-room enabler: a ModifyEvent that moves a metric event's span
(different Musical position or duration) is now applied to the graph and the
owning voice re-sorted by ascending position (id-tiebroken, the order an
insert maintains), so invariant 3 (VoiceEventsSortedNonOverlap) holds. The
deferral documented in DECISIONS.md is lifted.

modify_event computes one sanction — the move is a valid metric move
(PlacementVerdict::Moved) and the replacement is well-formed — and uses it to
gate both the graph mutation (graph_replace_event) and the voice_occupancy
update, so the canonical index and the graph never diverge. The verdict is
read from voice_occupancy, the graph-independent placement index, so reduce()
and reduce_onto() agree on it; a move with a non-positive span or one that
would overlap a live sibling is refused as a clean NoOp(EventDurationInvalid)
rather than skipped silently. A non-metric move stays deferred, and a
malformed (empty) pitched replacement is neither materialized nor allowed to
move occupancy.

Tests: trim frees the voice slot (a later insert fits); a move onto a sibling
is refused; a trim materializes in the graph (reduce_onto, invariants hold);
a non-metric event is not rewritten onto the musical grid; a malformed move
does not free the slot.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NAtEiJtt9yKVV1zjKYmZhS
2026-06-30 10:43:10 -04:00
Levi Neuwirth dfdbc625b1 Agent K M2e review follow-up: tighten catalog accuracy + container creates
Address the two-pass review of the M2e catalog expansion (ca07c28). All gates
green: cargo test --workspace 535/0, conformance_suite scale 1, fmt + clippy
-D warnings clean, catalog PDF rebuilt (no undefined refs).

Pass 1 (doc-vs-implementation accuracy):
- Undo semantics narrowed to the prototype minted-object model (the catalog's
  own UndoTransaction model + P11-C8): the new K0 sections' minting members
  (insert/create) keep tombstone-the-mint undo; the non-minting ops (modify /
  transpose / deletes / settings) now state they synthesize no inverse, rather
  than promising rich restore/reintroduction the reducer does not implement.
- Spanner migration corrected: Tie/Slur/Beam reconstruct self-containedly while
  a Spanner remains read-only/unmigratable until the v0 projection carries its
  TimeAnchors (a Phase-3/Pass-12 extension); the "joins in M2" claim is removed,
  in both the CreateCrossCutting section and the migration chapter.
- The reduce()/reduce_onto() agreement claim (DECISIONS + the staff_based_regions
  comment) narrowed to regions represented in reducer state: op-created/deleted
  regions agree, but reduce_onto additionally seeds base regions a base-free
  reduce() never sees.

Pass 2 (empty-container enforcement, made real and complete):
- create_region / create_staff_instance / create_voice reject (ContainerNotEmpty)
  a carried value bearing ANY typed child object — not just the structural
  hierarchy. A region: no staff instances, barline-alignment groups, or graphic
  objects; a staff instance: no voices or measures; a voice: no events. Each is a
  distinct TypedObjectId the reducer mints separately, so a carried child would
  otherwise materialize an unminted object into the graph (a graph/ledger
  faithfulness gap). ClefChange/KeySignatureChange/metric-grid carry no
  TypedObjectId and are values, so they are correctly not gated. The check reads
  the carried value only, so reduce() and reduce_onto() agree.
- Catalog §Structural Containers states the precondition as "no typed child
  object" with the per-container enumeration, matching enforcement exactly.

Coverage: new graph_reduction tests create_rejects_a_non_empty_carried_container
(hierarchy children) and create_rejects_carried_non_hierarchy_children (barline
group / graphic object / measure). DECISIONS M2c gains the create-emptiness bullet.

Stages only ops + spec; the unrelated Agent-I working tree is left untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 09:52:13 -04:00
Levi Neuwirth ca07c28c82 Agent K M2e: catalog expansion + DECISIONS for the M2 broad-K0 groups
The documentation milestone deferred through M2a–M2d. Documentation only —
no Rust changes; the d93baac code gates (cargo test --workspace 533/0,
conformance_suite scale 1) are unchanged.

operation_catalog (v0.1.0 -> v0.2.0):
- Chapter K0 gains full six-part schema sections for every M2-implemented op:
  ModifyEvent; Identified-Pitch Operations (insert/delete/modify, with the
  note<->rest equivalence stated normatively); Transpose; DeleteCrossCutting;
  ModifyCrossCutting; Structural Containers (region/staff-instance/voice
  set-union mint + empty-only delete); Score Settings (advisory metadata,
  structural metric grid with the staff-based + live-time-signature
  preconditions, advisory page break under the resolved-position LWW key).
- Chapter K1 cleanup: the implemented groups now cross-reference their K0
  sections rather than sit in "MUST reject"; the stale Phase-3 listing of
  SetMetadata / SetMetricGrid / page-break advisory (implemented in M2d) is
  removed, and the remaining slots are split to the genuinely-unimplemented
  finer metric ops (time signature / tempo segment) and non-break layout.
- Intro, conformance-profile, and version strings updated for the expansion.
- PDF rebuilt with xelatex (18 pp, no undefined refs); .xdv removed, only
  tex+pdf tracked.

epiphany-ops/DECISIONS.md: new M2c (Group 3 — empty-only structural-container
delete; live-child indices; staff-extent maintenance) and M2d (Group 4 — the
per-op disciplines as review-hardened in d93baac: advisory metadata, metric
grid with both preconditions, resolved-position break key) entries, and a note
that the dedicated 10K-envelope reducer micro-bench (criterion 5) is Agent F's
worklist F1 — the M2 value-typed ops are already exercised at 10K*scale by the
conformance reduction-determinism / convergence gates.

The unrelated Agent-I working tree is left untouched; this commit stages only
spec/ + ops DECISIONS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 22:21:32 -04:00
Levi Neuwirth 0f1b209e54 Agent K: DeleteEvent re-anchoring — make the graph follow the ledger
Standalone follow-up to the M2b review: close the pre-existing reanchor /
graph-delete divergence, which unlocks at-scale criterion-1 coverage for the
Group-2 cross-cutting CRUD ops.

The divergence: a DeleteEvent tombstoning a slur/spanner endpoint re-anchored the
structure in the bookkeeping ledger (object stays Live) but materialize_graph_delete
removed it from the graph unconditionally — so the object was Live in
MaterializedState yet gone from the Score. Latent only because graph_edit_session
never created cross-cutting structures.

Fix (graph-materialization only; bookkeeping/convergence unchanged):
- materialize_graph_delete now mirrors reanchor_for_tombstone for slurs and
  spanners: an endpoint-deleted structure re-anchors onto its surviving endpoint
  (stays in the graph) and is removed only when no endpoint survives. A
  two-endpoint structure collapses onto the survivor (degenerate (B,B), but
  reference-clean — the cross-cutting invariant requires only live endpoints;
  proximity-aware target deferred, P11-C5). Ties (cascade) and beams
  (truncate-while->=2) were already consistent and are unchanged. This also fixes
  a latent dangling-spanner bug (spanners weren't handled on event delete at all).
- seed_from_graph records each base-score spanner's event-anchored endpoints in
  `structures`, so a seeded spanner re-anchors through the same rule as a created
  one.

Coverage:
- New reduce_onto tests: deleting one slur endpoint re-anchors in both graph and
  ledger (slur Live + collapsed onto survivor); deleting both cascades in both
  (slur Tombstoned + removed).
- graph_edit_session now creates slurs over replica-0 events and emits
  DeleteCrossCutting / ModifyCrossCutting, so criterion 1 (reduce_onto +
  check_invariants, across delivery permutations) exercises cross-cutting CRUD and
  slur re-anchoring at scale.

Docs: DECISIONS.md records the graph-follows-ledger re-anchoring decision and the
degenerate-collapse / P11-C5 deferral.

Gates: build/fmt/clippy -D warnings clean; cargo test --workspace green (ops
graph_reduction 20; criterion 1 green with cross-cutting wired in); conformance
scale 1 passes. The unrelated Agent-I working tree is left uncommitted; this
commit stages only ops/testkit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 17:23:11 -04:00
Levi Neuwirth c47f4b5cec Agent K M2a review follow-up: graph-materialization fixes for the leaf-field ops
From the M2a review (no bug in the bookkeeping reduction; the gap was that the
Group-1 ops' *graph* materialization — reduce_onto — was unexercised by the
gates, which hid two invalid-graph edges). Fixes are graph-materialization only;
the bookkeeping projection, and therefore convergence/determinism, is unchanged.

- DeleteIdentifiedPitch of a single-pitch note's last pitch left an empty
  (Chapter-5-invalid) PitchedEvent via EventArena::get_mut (which bypasses
  insert's well-formedness guard). It now degrades the note to a Rest of the
  same id/voice/position/duration; InsertIdentifiedPitch into a rest is the dual
  (rest -> one-pitch note), keeping the graph consistent with the bookkeeping
  that mints/tombstones the pitch object either way.
- ModifyEvent now skips placement-changing (move) and malformed-empty pitched
  replacements in the graph rather than corrupting invariant 3
  (VoiceEventsSortedNonOverlap) via get_mut; voice re-sort stays deferred and the
  LWW bookkeeping still records the modify.

Coverage: graph_edit_session (criterion 1, reduce_onto + check_invariants) now
emits all five Group-1 kinds, so the real-Score gate exercises their graph
mutations at scale; plus two targeted reduce_onto regression tests (note->rest,
rest->note) in tests/graph_reduction.rs.

Docs: DECISIONS.md records the note<->rest equivalence and the ModifyEvent
placement deferral (catalog section prose routed to M2e); Transpose / P12-K2 note
the i8-saturation caveat; valuegen::pitch_value_nth no longer implies spelling()
is injective.

Gates: build/fmt/clippy -D warnings clean; cargo test --workspace green (ops
graph_reduction 13, ops lib 51); conformance_suite scale 1 passes. The unrelated
Agent-I working tree is left untouched; this commit stages only ops/testkit/spec.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 18:25:48 -04:00
Levi Neuwirth 4556ede9f0 Phase 2 (Agent K) M1: value-typed operation payloads + Operation Catalog scaffold
Foundation milestone for Track B's Operation Catalog: shift epiphany-ops from
the v0 identifier-only payload projections to durable value-typed payloads, and
scaffold the companion spec. Scope: the representative §6.10 set (7 primitives +
2 meta-ops); the slice-driven K0 expansion follows.

Core (the K↔J seam):
- epiphany-core exposes a public `CanonicalValue` trait (canonical_bytes /
  decode_canonical) delegating to the existing private `Codec` machinery, for
  Event/Rest/PitchSpelling/Tie/Slur/Beam/Spanner/RegionTimeModel/TimeAnchor.
  No new byte layout — a value's bytes equal what the whole-score codec emits,
  so all goldens / criterion 4 stay byte-identical.

Ops (value-typed payloads, frozen reduction rules):
- InsertEventOp{staff_instance,event:Event}, RespellPitchOp{pitch,spelling:
  PitchSpelling}, CreateCrossCuttingOp{structure:CrossCuttingValue},
  ChangeRegionTimeModelOp{...,new_time_model:RegionTimeModel},
  SetUserSystemBreakOp{...,anchor:TimeAnchor}, ReplaceWithRest{rest:Rest}.
  Payloads frame each value's CanonicalValue bytes behind a u32 length prefix.
- reduce.rs: read-sites only moved onto the value (rules, conflicts, ordering,
  promotion, re-anchoring, undo, transactions unchanged); reduce_onto now
  materializes the real event/structure instead of the C4 placeholder.
  MaterializedState.spellings now stores PitchSpelling (encode + decode updated).
- v0.rs: frozen identifier-only shapes (migration regression guard).
- migrate.rs: migrate_v0_envelope(v0, &Score) + project_v1_to_v0 + MigrationError;
  deterministic and equivalence-preserving. Respell spelling recovered from the
  score context; irreversible case is P12-K1.
- valuegen.rs: shared value-type builders (reused by fuzz, migration, tests,
  testkit). Resolves P11-C1; P11-C10 Dismiss recorded.

Testkit (Agent F merge gate):
- migration.rs: reduce(v1)==reduce(migrate(project(v1))) byte-identical, plus
  migration determinism and a non-vacuity guard; wired into acceptance.rs as
  agent_k_migration_equivalence_gate. Generators/harnesses build v1 payloads.

Spec:
- spec/operation_catalog.{tex,pdf}: new companion (independent semver) — framework
  + per-primitive template, the 7+2 representative primitives, the v0→v1 migration
  contract, and K1 framework slots for the remaining K0 primitives. Builds clean.
- PASS12_BATCH.md: P12-K1 (respell fingerprint irreversibility).

Gates: cargo build/fmt/clippy -D warnings clean; cargo test --workspace green
(incl. criteria 1/4/5/6 and the new K gate); conformance_suite scale 1 passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 11:52:02 -04:00
Levi Neuwirth b2f2e204a7 Pass 11: ratify provisional byte choices into normative spec text
Spec-revision pass (architecture unchanged) converting the v0
implementation's provisional, golden-locked choices into ratified
core_spec.tex text, so durable byte layouts are fixed before the
next-phase build-outs. Worklist: spec/PASS11_WORKLIST.md; per-item
dispositions: spec/PASS11_RATIFICATION_LOG.md.

Adopt-and-pin (bytes): TypedObjectId 16-bit BE discriminant table
0..=27 (added the 5 variants the code carried); promoted-voice
(MUSCSVCE), synthetic-pitch (MUSCSPCH, tuning always in identity),
and integrity-anomaly (MUSCSANM, now a reserved built-in tag)
derivations; ChunkKind/ProfileId/CompressionAlgorithm discriminants;
ManifestId preimage (manifest_id excluded); RationalTime/scalar
layouts + the codec convention baseline the Binary Format companion
inherits.

Decide-and-pin: tempo Linear interpolates speed (not bpm);
StructuralFieldCollision tags the winner Conflicted; lifted the
>2-way / partial-overlap voice-promotion rule to normative; pinned
TransactionCategory and ObjectKind core vocabularies; added
ResolutionAction::Dismiss so the Dismissed state is reachable by an
authored op; pinned the (non-canonical) LayoutObjectId derivation
(MUSCLOID).

Fixes: blob hashing is bare MUSCBLOB||payload (deleted the
contradictory "identically to chunks" phrasing); equal-generation
superblock rule (DivergentSameGeneration); defined ProfileConstraints
with the required RetentionPolicy + first-declared precedence; made
the DVV zero-based floor normative; reconciled the invariant count to
19 and named the three construction-time MUSTs — TupletRatio now
rejects degenerate ratios at construction (zero term or
actual==notated), enforced by a checked constructor + codec decode
validation.

Code changes carry regression tests; byte-layout golden tests now
cite their ratified requirements. Workspace green: cargo test, clippy
-D warnings, fmt; spec builds (lualatex, 253pp). Per-crate DECISIONS
files annotated with the ratification status.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011giSRaHCFCGm1Z2SWv6JHt
2026-06-21 22:30:06 -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