epiphany/crates/epiphany-core/src
Levi Neuwirth e7ebd8ac9c P13-S2: the alteration is space-relative, and the core fails closed
`cmn-24` was declared in the built-in pitch-space table as "CMN extended with
24-EDO quarter-tone accidentals" while Chapter 2 fixed a `Cmn` position's
absolute semitone at `nominal.chromatic() + alteration + 12*octave` for every
space, unqualified. Two ratified MUSTs, each correct in its own chapter,
jointly unsatisfiable -- P13-I1's two-listings drift in another costume.

The tracker parked this as "a data-model major". It is not.
`req:binfmt:frozen-layout` names `PitchSpacePosition` as one of four open
value-layer vocabularies, so three of the four available options cost no schema
event at all. The one that *is* a major -- regrading `alteration` onto a finer
fixed unit -- is also the only one that rewrites the canonical bytes of every
pitch ever authored, and it buys a single grid while `edo-31`/`53`/`72` stay
unrepresentable. It is explicitly ruled out.

Ratified instead: a `Cmn` alteration and a `CmnChromatic` modification are
denominated in steps of the enclosing pitch space's chromatic layer. One rule,
not a special case for one catalog row -- it settles `cmn-24`, `maqam-base`,
and `PitchSpaceModification::CmnChromatic` together. `cmn-12`'s step is the
semitone, so every score in existence keeps its meaning and **not one canonical
byte moves**; `canonical_pitch_bytes` writes the space id before the position,
so a `cmn-24` E-half-flat and a `cmn-12` E-flat already derive different
`PitchId`s.

The defect was larger than `cmn-24`. Nothing bound a `Cmn` position to a
12-chromatic space: `ScalePosition { space: "edo-31", position: Cmn { .. } }`
constructed, validated, encoded and transposed, and meant nothing. Neither
`Pitch::transposed` nor `twelve_tet_semitone` ever read the space. Until Push
4b resolves `PitchSpaceId` to a `DiatonicOverChromatic` structure, both now
fail closed outside provable built-in `cmn-12` -- a capability check, not a
claim that the identifier defines the structure. False refusal for a
score-defined 12-chromatic space is accepted over silently wrong arithmetic.

No wire change. `TransposeRefusal::PitchSpaceUnavailable` is a new *diagnostic*
mapping to the existing `PreconditionFailureReason::PitchSpaceMismatch` (6);
appending a discriminant for a guard Push 4b must delete would have reserved a
permanent wire value for a temporary mechanism, in exactly the artifact the
fail-closed ruling exists to protect. Assignments 10-15 are untouched.
Operation Catalog 0.9.0 records the broadened case *and* amends the 0.8.0
rationale, which asserted that discriminant 6 never consults a pitch-space
registry -- true of the non-`Cmn` check, false of this one.

Two spec-side fixes found in review, neither visible to any test: the
`TranspositionInterval` listing had lost its `pub chromatic_steps: i32,`
declaration to a comment rewrite, leaving a one-field struct above the sentence
"Both components are load-bearing"; and `pitch.rs` still documented
`alteration` as "in semitones", contradicting the requirement landing beside
it. Both new requirements are now cited from the code that implements them --
the label checker catches cited-but-undefined, not the reverse.

Push 4b keeps the registry work and loses the contradiction. P13-S4 is the last
item open in Batch 3.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 09:00:09 -04:00
..
prepass Schema major 2 Phase B: snapshot side + honest stamps (data-model fills) 2026-07-07 16:30:07 -04:00
codec.rs Text Projection: the Chapter-5 value layer, from one field list 2026-07-21 12:17:49 -04:00
event.rs Land M1 + M2 (Agent C): framework edge fixes and real-Score graph integration 2026-06-21 16:37:51 -04:00
fuzz.rs Schema major 2 Phase D: the repeat-authoring pair (code tranche) 2026-07-07 20:06:18 -04:00
generators.rs Schema major 2 Phase B: snapshot side + honest stamps (data-model fills) 2026-07-07 16:30:07 -04:00
graph.rs TransposeInterval: the faithful transpose, and the frozen one it replaces 2026-07-09 15:46:43 -04:00
ids.rs Text Projection: every graph id projects, because graph_id! says so 2026-07-21 13:41:40 -04:00
indexes.rs Schema major 2 Phase D: the repeat-authoring pair (code tranche) 2026-07-07 20:06:18 -04:00
invariants.rs Schema major 2 Phase D: the repeat-authoring pair (code tranche) 2026-07-07 20:06:18 -04:00
lib.rs Text Projection: the Chapter-5 value layer, from one field list 2026-07-21 12:17:49 -04:00
pitch.rs P13-S2: the alteration is space-relative, and the core fails closed 2026-07-22 09:00:09 -04:00
prepass.rs A transposition moves the authored spelling; recording Propagated is not enough 2026-07-09 16:40:06 -04:00
tempo.rs Push 4: Binary Format companion, F1 benches, subquadratic reduction order 2026-07-02 19:02:07 -04:00
textvalue.rs Text Projection: the Chapter-5 value layer, from one field list 2026-07-21 12:17:49 -04:00
textvalue_event.rs Text Projection: the Chapter-5 value layer, from one field list 2026-07-21 12:17:49 -04:00
textvalue_graph.rs Text Projection: the Chapter-5 value layer, from one field list 2026-07-21 12:17:49 -04:00
textvalue_impls.rs Text Projection: every graph id projects, because graph_id! says so 2026-07-21 13:41:40 -04:00
textvalue_pitch.rs Text Projection: the Chapter-5 value layer, from one field list 2026-07-21 12:17:49 -04:00
textvalue_time.rs Text Projection: the Chapter-5 value layer, from one field list 2026-07-21 12:17:49 -04:00
time.rs Text Projection: the Chapter-5 value layer, from one field list 2026-07-21 12:17:49 -04:00