epiphany/crates/epiphany-layout-ir/src
Levi Neuwirth afb487c24d P13-I2: Staff::default_clef is the fallback, not decoration
to_constrained took the active clef from the staff instance's clef_sequence and
fell back to Clef::default() -- treble. A staff that declared its clef only on the
Staff, with no ClefChange, therefore drew a treble clef and placed every note
against it. The field was decorative in the projection.

It is the fallback. StaffContent now carries default_clef -- the clef belongs to
the Staff, the sequence to the StaffInstance, and resolving "the clef at time t"
needs both -- and active_clef_or(clefs, at, default) resolves against it.
active_clef remains as that with the treble default, for callers with no staff to
hand, so the public API is intact.

The part worth pausing on: epiphany-editor-core reads the same function for
hit-test pitch resolution. Fixing only the projection would have left a click on a
bass staff resolving its pitch as treble -- the engraved clef and the editor
disagreeing about what note is where. Both now go through active_clef_or.

Removal was rejected: the field is named for its purpose, is encoded on the wire,
and dropping it would be schema-major.

Zero golden churn: every fixture and generator declares treble, which is also
Clef::default(), so nothing that exists today moves. Locked by
a_staff_declaring_only_a_default_clef_engraves_in_it and mutation-verified by
restoring the Clef::default() fallback. Scoping that test by provenance was
necessary -- valid_score_rich has three staves and only one was re-clefed, so the
first assertion I wrote ("no gClef anywhere") failed against a correct fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 14:47:42 -04:00
..
barrier.rs Schema major 2 Phase D: the repeat-authoring pair (code tranche) 2026-07-07 20:06:18 -04:00
cache.rs Land epiphany-layout-ir (Agent E): layout IR + solver interface 2026-06-19 19:58:01 -04:00
constrained.rs P13-I2: Staff::default_clef is the fallback, not decoration 2026-07-09 14:47:42 -04:00
engrave_theory.rs layout-ir: staff_step_pitch, the clef-relative position inverse 2026-06-29 17:28:23 -04:00
engraving.rs Pushes 1+3: fix the MUST-level violations, wire the types-only machinery 2026-07-02 17:10:50 -04:00
glyph.rs Schema major 2 Phase E1: repeat barlines + volta brackets render 2026-07-07 21:51:11 -04:00
hittest.rs Let the band model carry staff attribution instead of inferring it 2026-07-09 10:37:27 -04:00
lib.rs P13-I2: Staff::default_clef is the fallback, not decoration 2026-07-09 14:47:42 -04:00
logical.rs P13-I2: Staff::default_clef is the fallback, not decoration 2026-07-09 14:47:42 -04:00
provenance.rs Phase 3 tranche 1: casting-off, K1 schema-fill, value-restoring undo 2026-07-02 21:55:26 -04:00
quality.rs Straighten the QMC version story in the docs that assert it 2026-07-09 11:54:25 -04:00
render.rs Schema major 2 Phase E2: slur curves + cubic-bézier primitive 2026-07-08 15:33:00 -04:00
resolved.rs Ratify primitive band ownership in Chapter 7; scope canonical_bytes' doc 2026-07-09 10:50:10 -04:00
roundtrip.rs Schema major 2 Phase E2: slur curves + cubic-bézier primitive 2026-07-08 15:33:00 -04:00
solver.rs Let the band model carry staff attribution instead of inferring it 2026-07-09 10:37:27 -04:00
spatial.rs Land epiphany-layout-ir (Agent E): layout IR + solver interface 2026-06-19 19:58:01 -04:00
time_axis.rs Agent I Phase 2-3: engrave recognizable notation from Score to SVG 2026-06-26 20:46:33 -04:00
vertical_band.rs Two-sided inter-staff renegotiation, and the cascade defect it uncovered 2026-07-09 13:32:37 -04:00