Commit Graph

18 Commits

Author SHA1 Message Date
Levi Neuwirth fc411ea7ac Ratify primitive band ownership in Chapter 7; scope canonical_bytes' doc
Review follow-up. Both findings were about documentation lagging a contract the
code now enforces, and the first is the one that matters: band ownership is the
solver-facing correctness contract, so it belongs in the spec, not only in a
crate's DECISIONS.md.

Chapter 7's ratified Stroke/Curve listings gain `vertical_band`, and a new
requirement (req:layoutir:primitive-band-ownership) states the rule as a MUST:
every primitive declares its owning band, the projection MUST name a band that
exists, and a vertical solver MUST take ownership from that declaration and MUST
NOT infer it from geometry. The rationale is recorded because the requirement
looks like a convenience until you see why it isn't: a stem shares its column
with the staff above, and a slur's endpoints are lifted clear of its own staff
into the zone where the nearest notehead belongs to the neighbour. A solver that
guesses from proximity tears such primitives off their notes when it renegotiates
the staff gaps -- which is exactly what happened, twice. The requirement also
records that only glyphs are band *members*, and that the reference is
non-canonical attribution metadata.

Stroke's stale "the vertical-band model does not contain" gloss is dropped.

canonical_bytes' doc claimed to encode "the full resolved layout". It encodes the
rendering fingerprint and deliberately excludes attribution metadata. Stating
that precisely required checking rather than paraphrasing: ResolvedGlyph drops
its band on the way out of the constrained stage, while Stroke and Curve -- whose
types are shared with that stage -- carry vertical_band through but never encode
it. Two layouts differing only in band ownership draw identically and hash alike.

Spec rebuilds clean: no LaTeX errors, no undefined references, new label
registered. Gate green, no golden churn.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 10:50:10 -04:00
Levi Neuwirth 449dd2ef8e Push 3 ratify: extend the slur-rendering requirement + refresh slur_shape
The three slur refinements (dashed rendering, curve splitting, slur_shape
measured) lifted into the spec — Chapter 7 / Quality Metric Catalog only,
non-canonical, so no wire form and no companion-version move.

core_spec Ch7: req:layoutir:slur-curve extended — an authored non-Solid
SpanStyle line renders faithfully (the LineStyle rides the Curve, whose listing
gains the field); a slur spanning a system break splits into per-system
sub-curves (de Casteljau; first segment keeps the slur's provenance, the rest
synthesized continuations). Only the curvature-computing algorithm stays
forward-referenced out now (dash rendering no longer deferred).

quality_metric_catalog: the §slur_shape rationale and the notated-but-unrendered
open question refreshed to record slurs now render and are measured; the formula
(req:qmc:slur) is unchanged, so no catalog version move.

Revision-history row (Push 3); a Push-3 tranche in PASS12_RATIFICATION_LOG.md;
layout-ir DECISIONS cross-ref extended. Both specs build clean (latexmk
-xelatex, 0 undefined refs). No code change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 17:33:11 -04:00
Levi Neuwirth 693150e43e Schema major 2 Phase F: ratify repeat + slur rendering into Chapter 7
The schema-major-2 push's rendering consumers (E1 repeat barlines/volta
brackets, E2 slur cubic-béziers) lifted into core spec Chapter 7 — layout-IR
only, non-canonical, so no wire form and no companion-version bump (Operation
Catalog stays 0.7.0, Binary Format 0.6.0), mirroring the schema-major-1 Phase-F
engrave-ratify-only precedent.

Three req:layoutir:* requirements added at §ResolvedLayoutIR:
- resolved-primitives: ResolvedLayoutIR carries non-glyph line Strokes (staff
  lines, stems, barlines, volta brackets — present since staff lines, never
  previously ratified) and cubic-bézier Curves (slurs, E2); each provenance-
  traced (the hit-test basis), re-spaced like a glyph, non-canonical. The
  struct listing gains strokes/curves and the Stroke/Curve shapes; the RenderIR
  provenance requirement widened from "originating ResolvedGlyph" to
  "ResolvedGlyph, Stroke, or Curve".
- repeat-render (E1): a barline-drawing RepeatStructure renders a repeat barline
  at each resolved boundary, each Volta a bracket with ending numbers;
  unresolvable boundaries draw no ink (honest placement); jump-kind marks and
  cross-region repeats deferred.
- slur-curve (E2): a Slur renders as a cubic bézier honoring CurvatureOverride;
  an endpoint not on a single staff of one region draws no curve; a non-Solid
  line style MUST be surfaced (diagnostic), not silently rendered solid.

The curvature-computing algorithm and the RenderIR encoding stay forward-
referenced out. Ch5 §Slurs / §Repeat Structures and the Ch7 Forward References
gain labels for the cross-references. Revision-history row + a schema-major-2
rendering tranche in PASS12_RATIFICATION_LOG.md; layout-ir DECISIONS carry the
Phase-F cross-refs. Spec builds clean (latexmk -xelatex, 0 undefined refs).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 16:23:12 -04:00
Levi Neuwirth 9b5339f8f3 Schema major 2 Phase D: the repeat-authoring pair (code tranche)
CreateRepeatStructure / DeleteRepeatStructure land end-to-end,
review-hardened (five-dimension workflow review; 19 findings triaged —
12 verifier agents lost to a session limit were verified by hand).

epiphany-ops:
- CreateRepeatStructureOp { repeat } (lp(RepeatStructure), wire 28,
  BORN AT V2: schema_major always 2 — kind/voltas are unconditional
  fields) and DeleteRepeatStructureOp { repeat } (bare id, wire 29,
  major 0: minimal stamping over a major-0 layout; the discriminant a
  schema-minor append). OperationKindTag 28/29 name-verbatim with
  validating decode; golden tables grown to 30; migrate/v0 identity
  arms; lib re-exports.
- Reduction: set-union mint (live-id => AlreadyApplied without value
  comparison — the cross-cutting discipline; RecreateContentMismatch
  scope unchanged) with the ALL-anchor-sites-live precondition;
  delete-wins tombstone; the "Repeat structure / Anchor" rule-table
  row wired into BOTH the ledger (reanchor_for_tombstone arm, min-id
  survivor, cascade when dry) and the graph (every dead site rewrites
  to the same survivor), agreement asserted by tests incl. the
  DalSegno jump-target case.
- Undo: materialize_graph_tombstones gains RepeatStructure — and the
  pre-existing SPANNER GHOST fix (an undone spanner mint never left
  the graph), regression-locked.
- validate.rs: VoltaEndingsIllFormed advisory (non-empty, 1-based,
  strictly ascending; interactive-only).
- Canonical-base honesty: blake3 re-pinned for the corpus stream
  shift, its comment corrected (the seeded repeat creates all no-op),
  and the property covered surgically by
  the_canonical_base_embeds_no_repeat_values (two reductions
  differing only in repeat v2 content => byte-identical bases).

epiphany-core:
- RepeatStructure::anchor_sites()/anchor_sites_mut(): THE single
  site-set walk (start/end, jump targets, volta spans), consumed by
  reduction, the editor barrier seam, the invariant walk, and the
  cross-reference index — replacing five hand-rolled copies and
  fixing a SIXTH, silently-stale one (indexes.rs had never learned
  the Phase-B kind/volta anchors; regression-locked).
- RepeatStructure joins the CanonicalValue seam (strict per-value
  decode); decode-fuzz corpus gains valid_score_rich_with_repeats
  (DalSegno + voltas) CORPUS-LOCAL — shared render fixtures stay
  repeat-free until E1 (zero golden churn).

editor-core / gui / testkit / layout-ir:
- Barrier seam: repeat_event_refs + subjects_of arms +
  graph_structure_endpoints arm, gated end-to-end by
  repeat_authoring_kinds_derive_subjects_and_gate_on_barriers.
- Generators: operation_payload -> below(30); graph-session gen ->
  below(14); ops fuzz gen_payload -> below(27); layout_stub
  gen_operation_kind_tag unstaled 24..=29 (the Phase-3 tags were
  already missing); GUI name table.

Spec touch-ups (review findings): catalog says "strictly ascending";
the survivor tie-break is now explicit in the core rule-table row and
catalog (identifier-order minimum among multiple survivors;
proximity-aware four-key selection deferred, as for spanners).

Trail: ops + core DECISIONS entries; spec/PASS13_CANDIDATES.md opens
the Pass-13 ledger at three candidates (P13-K1; P13-D1 undo-driven
tombstones bypass ledger re-anchoring — pre-existing class; P13-D2
cue-cascade repair-trail ordering).

Full gate: fmt, clippy -D warnings, rustdoc -D warnings, 30 workspace
suites, conformance scale 1 (8/8).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NEs4aYiu8MXjdYdMxw8PTd
2026-07-07 20:06:18 -04:00
Levi Neuwirth b816144a43 Schema major 2 Phase D: ratify the repeat-authoring pair (spec tranche)
CreateRepeatStructure / DeleteRepeatStructure enter the ratified
operation set — the dedicated pair for RepeatStructure (repeats live in
the cross-cutting registry but are deliberately NOT CrossCuttingValue
wire kinds; the reconciliation note follows Ch6's CrossCuttingStructure
listing).

operation_catalog (0.6.0 -> 0.7.0):
- New K0 §"Repeat Structures": the full six-part schema for the pair.
  Set-union mint with the ALL-anchors-live precondition (start/end, the
  kind's jump targets, each volta's span — the mint must leave the graph
  satisfying reference-resolution invariants; dead anchor =>
  TargetMissing no-op); live-id re-create reads AlreadyApplied without
  value comparison (cross-cutting discipline; RecreateContentMismatch
  scope unchanged); delete-wins tombstone; create-undo tombstones the
  mint, delete-undo does not restore (P11-C8); volta well-formedness
  stays advisory.
- K1 gains the "Added in the schema-major-2 revision" entry (net-new
  primitives, never drafted as slots).

binary_format (0.5.0 -> 0.6.0):
- OperationKind wire table appends 28 (lp(RepeatStructure)) / 29 (bare
  identifier); OperationKindTag 28/29, name-verbatim projection;
  requirement bounds move past 29.
- Honest per-op stamping ratified: the CREATE is born at v2 (kind/voltas
  are unconditional fields — no lower-major payload layout exists, so
  every block carrying one stamps major 2 under minimal stamping); the
  DELETE's bare-id payload is a major-0 layout, so minimal stamping
  gives its blocks major 0 — the kind discriminant itself being a
  schema-minor vocabulary append (mechanism claim only; the stamp always
  follows minimal stamping, as discriminant 24's always-2 CreateStaff
  shows).
- §Schema Major 2 restructured: RepeatStructure moves from the
  snapshot-only bullet to the canonical operation layer (eight embedding
  payloads now); the CanonicalValue seam grows to twenty-three
  (RepeatStructure joins — CreateRepeatStructure embeds it per
  req:catalog:value-encoding).

core_spec:
- Ch6 OperationKind + Ch8 OperationKindTag listings gain the variants;
  the CrossCuttingStructure/wire-vocabulary reconciliation note; the
  re-anchoring rule table gains the "Repeat structure / Anchor" row
  (re-anchor to the nearest surviving anchor across EVERY
  event-referencing anchor site; cascade-delete only when none
  survives — the spanner discipline); Ch8's schema-versioning paragraph
  now enumerates eight embedding payloads with the born-at-v2/major-0
  split; revision-history row.

Review-hardened: five-dimension workflow review, 22 findings, 9
confirmed + 1 recovered from a failed verifier (an API-error casualty,
assessed by hand) — all fixed (the load-bearing ones: Ch8's stale
seven-payload enumeration; the mis-attributed "Phase-3 precedent" gloss
that would have taught a false stamping rule; the pair filed under
"Snapshot-only"; the CanonicalValue seam omission). All three documents
compile clean, zero undefined references.

Code tranche follows this commit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NEs4aYiu8MXjdYdMxw8PTd
2026-07-07 17:31:51 -04:00
Levi Neuwirth 7c9d1c40aa Schema major 2 Phase A: ratify the v2 data-model wire form (spec only)
Push 2's spec-first phase. core_spec (schema-major-2 revision): defines
the nineteen leaf types Ch5's ratified shapes referenced but never
pinned (SlurKind, CurveDirection, CurvatureOverride, the shared
SpanStyle record consolidating the identical SlurStyle/TieStyle/
SpannerStyle triplet, SubBeam, BeamGeometryOverride, SpannerKind's five
payload types + a leading Generic migration default, Volta,
MetadataValue, Timestamp, SoundConfiguration, TranspositionInterval
(structural, advisory until Ch4 per the P12-K2 discipline),
UnpitchedMember + member-resolution semantics (first-match, no-match
tolerated; StaffPosition vertical convention explicitly deferred),
SpaceUnit, LineStyle, StaffBracketKind); ratifies the visible-slice
clef/key content model into Ch5 (Clef/ClefShape/KeySignature/
ClefChange/KeySignatureChange) and retires the ClefId sketch;
strictly-authored metadata timestamps (req:graph:metadata-timestamps);
metadata `additional` = ordered list, duplicates permitted; Ch8 gains
the major-2 paragraph; Ch6 OperationKind listing gains its seven
missing variants (staleness fix).

binary_format 0.4.0 -> 0.5.0: new "Schema Major 2" section — per-
payload-type major assignment (snapshot-only Instrument/
RepeatStructure; SEVEN canonical embedding payloads incl. CreateRegion
transitively and SetStaffLayout's direct staff_lines_override field);
the MINIMAL-STAMPING rule (a block stamps the lowest major whose
layouts decode its bytes — deterministic, per-payload table given;
extends the major-1 no-restamp principle); append-after-prior-major
wire layouts with field-order divergences called out; new leaf layouts
with framing pinned (SubBeam EventIds = framed leaves; UnpitchedMember
fields = bare primitives; SpaceUnit = framed 12); total default-fill
v1->v2 migration table (complete StaffLineConfiguration defaults at
all four embed sites; RepeatKind default SimpleRepeat{count:2});
accept-set {0,1,2} with per-role staging note; CanonicalValue seam
list corrected 18 -> 22 (staleness fix).

Two review rounds (8 + 9 findings, all fixed pre-commit — the
stamping-rule determinism contradiction, the CreateRegion transitive
embedding, SubBeam leaf framing, and the SetStaffLayout direct-field
site being the load-bearing ones). Both PDFs build clean, zero
undefined references. No code changes; Phase B (snapshot side) next.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NEs4aYiu8MXjdYdMxw8PTd
2026-07-07 15:05:48 -04:00
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 7045a13a18 Schema major 1 Phase F: ratify engrave I8/I9/I10 + process trail
Spec/process only, no code. Closes the schema-major-1 track (Phases A-F): the
two data-model batch rows parked behind the frozen-layout rule (P12-I7, P12-K7)
landed via Phases C/D1, and the three engrave/layout-ir dispositions the
implementation already made are ratified into the core spec.

- core_spec: three normative requirements ratifying the implemented behavior --
  break-constraint satisfaction (req:layoutir:break-satisfaction, I8: a
  SystemBreakAt/PageBreakAt is satisfied iff the final ResolvedLayoutIR starts a
  system/page at that slot), break-override attribution via a
  ConstrainedLayoutIR.break_origins sidecar declining to widen the constraint
  record (req:layoutir:break-origin-attribution, I9), and system-continuation
  synthesis Registered(SYSTEM_CONTINUATION_SYNTHESIS) with an (original, ordinal)
  instance key (req:layoutir:continuation-synthesis, I10). Revision-history row.
  PDF rebuilt (latexmk -xelatex, 0 undefined refs).
- PASS12_RATIFICATION_LOG: schema-major-1 tranche (I7/K7 landed + I8/I9/I10
  adopt), with the open cross-region-slur item flagged.
- PASS12_BATCH: struck I7/K7/I8/I9/I10; added P12-K12 (which region governs a
  cross-region slur's spanning permission -- implemented as conservative AND).
- engrave/layout-ir DECISIONS: ratification cross-refs; the P12-I7 note reworded
  so deferred Phase C' does not read as landed.
- .gitignore: spec/*.xdv (xelatex intermediate; the tracked PDF is committed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NEs4aYiu8MXjdYdMxw8PTd
2026-07-06 17:40:38 -04:00
Levi Neuwirth f4a2f1fdf0 Schema major 1 Phase A: ratify the v1 wire form + migration (spec only)
The first phase of the first-ever binary-format schema-major bump (v0 -> v1),
the machinery-first minimal major. Spec-only: ratifies the contract that
Phases B-F build against; no code changes.

core_spec.tex: defines the two referenced-but-undefined types that were the
P12-I7 / P12-K7 gaps -- CanvasLayoutDefaults (with core geometry primitives
CanvasSize/CanvasMargins in staff spaces via CanonicalF64, A4/8mm default,
since core has no geometry types and must not depend on layout-ir) and
PitchRange (advisory pitch compass used by Instrument.range and
IndeterminacyHints) -- and adds Region.permits_spanning_slurs (default false).
Records schema major 1 as the first data-model expansion major and tightens
the minor-version rule (a field add, even Option, is major; minor = append
discriminants to the companion's append-safe vocabularies only).

binary_format.tex -> 0.3.0: the full "Schema Major 1" section --
  - Where the changed fields reach: Canvas.layout_defaults and
    Instrument.range are snapshot-only (no CreateCanvas/CreateInstrument op),
    but Region.permits_spanning_slurs also reaches the CANONICAL CreateRegion
    operation payload (CreateRegion embeds the full Region). The canonical-base
    MaterializedState embeds none of these and stays major 0, byte-identical.
  - Cross-major reader rules: discard-and-regenerate non-canonical chunks;
    parse-or-read-only for canonical ones, so a major-0 reader opens a bundle
    carrying v1 CreateRegion ops read-only.
  - Accept-set gate [min,max] (rejects majors outside the set); per-payload-
    type major assignment; the changed v1 value layouts (the wire form ratifies
    the reduced reference-code layout, not the fuller data model); the total
    default-filling v0->v1 migration table (including the CreateRegion payload).
  - Length-prefix unification NARROWED to the resolved-layout (its own
    non-canonical LayoutCache): the barrier/extension blobs stay regime (b) u64
    because they ride the canonical manifest, which stays major 0.

Two review passes hardened this checkpoint. The first caught that Region is a
canonical operation payload (not cache-only, as the architecture analysis had
assumed) -- user chose to embrace it and build the canonical op-payload
migration. It also surfaced the barrier-blobs-in-manifest constraint that
narrows the unification. The second refined the minor-version delegation, the
accept-set outside-[min,max] semantics, and stale "no defined type" text in
the reference-suite / quality-metric companions and the engrave DECISIONS.

P12-I7 moved to IN PROGRESS (spec type defined here; code graph home lands in
Phase C). Both companions and the engrave DECISIONS reworded accordingly. All
four affected PDFs rebuild clean (0 undefined references).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NEs4aYiu8MXjdYdMxw8PTd
2026-07-05 18:05:38 -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 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 80e3fed99c spec: Pass 12 tranche 1 — align spec text with ratified dispositions
The 2026-07 compliance audit's spec-side batch: every place where
normative text trailed a disposition the project had already made (the
ratified Operation Catalog, a crate DECISIONS entry, or the
PHASE2_QUICKSTART model the implementation follows). No byte-layout or
architecture changes.

- Re-anchoring table: the Slur/Spanner rows now state the catalog's
  surviving-endpoint semantics (re-anchor while >=1 endpoint survives,
  cascade-delete only when none does).
- RewriteTuplets adopts the catalog's id-only v1 payload (TupletRewrite
  removed); graph-aware reduction MUST refuse the variant rather than
  fabricate rewritten values.
- Operation-envelope blocks are pure envelope vectors (a content-
  addressed chunk cannot embed its own id); per-block summaries
  (dvv_summary/min_stamp/max_stamp) relocated to the manifest's
  operation_block_summaries map; the order-blocks-by-min_stamp SHOULD
  dropped (the canonical encoding sorts chunk refs by encoded form).
- Ch2+Ch3 pre-passes respecified as canonical derived annotations —
  deterministic functions of (graph, profile, versioned algorithm id),
  recomputed on materialization, never stored; the incremental-re-run
  MUST demoted to MAY with unobservability required.
- Spelling precedence ties break by canonical attachment order (the
  creation-timestamp tie-break deleted; attachments carry none).
- ConflictRegistry moved off the Score root into canonical materialized
  state, matching Chapter 6.
- SolverTier gains the non-conformance Stub variant.
- The drafted ModifyEvent M2e text landed in the catalog (0.2.0 ->
  0.3.0): metric placement changes materialize behind a voice-occupancy
  placement precondition.

Dispositions logged in spec/PASS12_RATIFICATION_LOG.md; the Pass 12
batch itself stays open (no P12-H/K rows resolved). Also carries the
audit-filed batch rows P12-H6/H7/K3/K4.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NEs4aYiu8MXjdYdMxw8PTd
2026-07-02 17:04:14 -04:00
Levi Neuwirth 83bc202ff6 Pass 11 follow-up: disambiguate 'reserved built-in tags' in Appendix E
The Canonical Byte-Layout Reference used the phrase 'reserved built-in
tags' in two scopes: the system-derived-identifier section called it the
closed set of three (MUSCSVCE/MUSCSPCH/MUSCSANM), while the domain-tag
registry calls eleven tags 'reserved built-in'. The source section
(req:graph:system-derived) qualifies the three as tags 'for
system-derived identifiers'; the consolidation had dropped that
qualifier, leaving the single-import appendix internally ambiguous for
the Binary Format companion author.

- Restore the scope qualifier and cross-reference the full registry,
  noting the other reserved tags feed plain hashing preimages, not the
  system-derived counter.
- Tighten the 'canonical' gloss: canonical tags produce identifiers and
  content hashes that are part of the interoperable, durably persisted
  form (not loosely 'document state', which misreads the storage-layer
  chunk/manifest/blob tags).

Spec-text only; rebuilds clean (0 undefined refs, 261 pages, no new
overfull boxes). No code or byte-layout change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 14:35:30 -04:00
Levi Neuwirth dffac4c744 Pass 11: consolidated byte-layout appendix + pin ObjectKind/ResolutionAction discriminants
Adds Appendix E (Canonical Byte-Layout Reference) — the single
byte-convention table the Binary Format companion imports — and closes
two pins (ObjectKind, ResolutionAction discriminant bytes) that were
golden-locked in code but absent from spec text. Audit follow-up:
completed the domain-tag registry (added canonical MUSCCONF/MUSCENVH and
non-canonical MUSCFNTM) and corrected golden-lock wording for the two
non-literal-byte anchors (BlobId, RationalTime).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 13:16:20 -04:00
Levi Neuwirth 0d8ec61a3c Pass 11 audit follow-up: honest LayoutObjectId status + doc/test gaps
Independent audit of b2f2e20 / a7adbdc. The canonical, document-state byte
layouts were already correct and golden-locked; this closes the one real
spec-vs-code gap (in the non-canonical layout namespace) and the smaller
doc/test gaps around it.

LayoutObjectId (item 2.6): the spec normatively stated the id "is derived ...
with MUSCLOID" and the ratification log / layout DECISIONS header called it
"pinned" -- but no code uses MUSCLOID (stable_layout_id and
manifestation_layout_id are untagged; synthesized_layout_id borrows MUSCCONF),
and MUSCLOID cannot even be constructed: DomainTag::from_bytes accepts only
built-ins or MUSCS-prefixed tags, so wiring it requires changing the frozen
determinism crate (out of scope for a spec pass, and the spec itself says
MUSCLOID is not a canonical system tag). Kept MUSCLOID as the pinned Track-A
target and made every artifact honest that the v0 code is provisional:
  - spec: "is derived" -> "MUST be derived" (forward contract) + a note that
    the prototype mints provisional ids; changelog "pinned" -> "specified ...
    as the Track-A target".
  - records: ratification-log line 2.6 and layout DECISIONS header/body now
    state spec-pinned-but-code-provisional; stale "Pass 11 candidate 3"
    pointer now cites the ratified requirement.
  - provenance.rs comments name the MUSCLOID target and label the current
    derivation provisional.

Other fixes:
  - epiphany-core/DECISIONS.md: the Tuplet bullet still claimed degenerate
    ratios are caught by runtime invariant 16 "since a Tuplet is a plain
    struct" -- stale after the construction-time TupletRatio change. Rewritten.
  - codec.rs: added degenerate_tuplet_ratio_is_rejected_on_decode, guarding
    the TupletRatio::dec re-validation branch that no test exercised (the
    constructor was tested, the decode path was not).
  - spec: integrity-anomaly snippet kind.canonical_bytes() ->
    to_canonical_bytes() (the actual method).
  - ids.rs / reduce.rs: clarifying comments (ManifestId's intentional,
    golden-locked document_id/generation duplication; compute_promotions
    bucketing by voice == (staff_instance, original_voice) via Invariant 5).

Verification: cargo test --workspace (434 pass, +1), clippy --all-targets clean
(0 warnings), fmt clean; spec rebuilds (lualatex, 0 undefined refs, 254pp).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 10:02:05 -04:00
Levi Neuwirth a7adbdc5a1 Pass 11 follow-up: golden-lock the ratified discriminant tables; fix three spec-text inaccuracies
Audit follow-up to b2f2e20. The ratification was byte-faithful, but the
audit found a gap between the protection the worklist claims ("a
golden-bytes test already locks every byte-layout item") and the
protection actually in place for several newly-normative tables, plus
three small inaccuracies in the ratified spec text.

Golden locks (close the round-trip-vs-golden gap):
- ChunkKind: chunk_kind_discriminants_are_golden pins the literal 0..=8.
  ChunkKind::canonical_bytes() is in the chunk hash preimage, so the
  prior round-trip-only test would let a coordinated renumbering silently
  change every chunk content address while passing.
- CompressionAlgorithm: compression_algorithm_encoding_is_golden pins the
  exact bytes (None -> [0,0], not a bare tag).
- ProfileId (load-bearing superblock field): profile_id_discriminants_are_golden
  pins the u32 discriminants and the fixed 20-byte encoding.
- ResolutionAction / TransactionCategory / ObjectKind: *_discriminants_are_golden
  pin the canonical discriminants (ObjectKind feeds the anomaly id;
  ResolutionAction/TransactionCategory feed operation content hashes).
- IntegrityAnomalyId: integrity_anomaly_id_byte_form_is_locked golden-locks
  the MUSCSANM-derived id (cross-replica agreement is a conformance
  property; it previously had no byte-form golden).

Spec-text fixes (core_spec.tex):
- CompressionAlgorithm: "None = 0 (no payload)" was wrong; the code writes
  a fixed two bytes (discriminant + always-present parameter byte). Text
  now states the fixed-width framing.
- ProfileId: "a single discriminant followed by any variant payload" was
  wrong; it is a u32-LE discriminant + a fixed 16-byte registry id (zero
  unless Custom), 20 bytes total. Text now matches the only encoding.
- TupletRatio listing showed `pub` fields (freely constructible by struct
  literal), contradicting req:time:tuplet-ratio-construction. Listing now
  shows private fields + the checked `new`/`actual()`/`notated()`, matching
  the code.

Test honesty:
- testkit resolution_action generator now emits Dismiss (rng.below(6)); it
  previously skipped the variant, leaving the Dismiss path unfuzzed.

Verification: cargo test --workspace (433 pass, +7), clippy -D warnings
clean, fmt clean; spec rebuilds (lualatex/latexmk, 0 undefined refs, 254pp).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 09:22:55 -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 a2e9ec32f6 A B C D F 2026-06-19 12:42:31 -04:00