The repo's last unverified surface gets a gate. A decoded-RGBA golden
comparator (dimensions first, then raw pixels — never encoded PNG bytes,
proven by a re-encode-invariance test) with three-artifact failure output
and a reviewed-bless mechanism; four golden states over the real Engraver —
as opened, after a scripted pencil insert (target derived through the
session's own inverses, pitch/beat value-asserted exactly), after undo
(asserted equal to the as-opened baseline byte-for-byte, bypassing the
bless path so a broken undo can never bless itself green), and the slurred
casting-off fixture (system count value-asserted). Every state renders
twice and must match itself. Three user-reviewed baselines; rasterize()
split into a pixmap core so the goldens lock the exact surface the GUI
displays; one additive CI step uploads failure artifacts; DECISIONS.md
records the calls, including two engraving gaps locked knowingly (no clef
restatement on later systems; uneven system spacing).
Seven mutations executed and independently re-verified by the coordinator;
full gate green (fmt, clippy 0, workspace 0 failed, docs, conformance 8/8,
requirement counts unchanged).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Wires the session's undo/redo into the GUI: ↶ Undo / ↷ Redo toolbar buttons,
add_enabled-gated by can_undo()/can_redo() so they grey out when there is
nothing to do, and Ctrl/Cmd+Z (undo) / Ctrl/Cmd+Shift+Z or Ctrl/Cmd+Y (redo)
shortcuts read with modifier checks (first in handle_keys, so a modified Z is
not also taken as a plain key). A run_history helper handles the
Option-returning steps, reporting "nothing to undo/redo" when the stack is
empty. These run in the toolbar/key path, before the frame's rerender slot, so
there is no stale-texture concern. Module doc, help text, and the crate
description are updated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NAtEiJtt9yKVV1zjKYmZhS
A toolbar palette — 1 / 1/2 / 1/4 / 1/8 / 1/16 — sets the selected note or
rest's written value via set_selection_duration(NoteValue::whole_note_fraction),
with the editor's make-room overwrite when lengthening; refusals (tuplet member,
decomposed event, non-note selection) surface in the status line. The palette
lives in the toolbar, which runs before the frame's rerender slot, so it has no
stale-texture concern. Adds epiphany-core as a direct dependency for NoteValue
(already a transitive workspace member, so no MSRV/CI impact). The module doc and
crate description are updated; only an undo UI remains unbuilt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NAtEiJtt9yKVV1zjKYmZhS
A new demo binary crate that proves the EditorSession seam end to end. It renders
the session's resolved layout with epiphany-render-svg, rasterizes that SVG with
resvg into an egui texture, resolves clicks back to staff-space world coordinates
to select, and drives all six note-editing intents from a toolbar and keyboard
(delete, chromatic transpose, staff-step move, add chord note, insert-after). A
debug panel shows the selection and the last applied op, proving the op log is
usable. Intentionally narrow: no duration editing, empty-space insert, or undo UI.
The one piece of nontrivial logic — the screen<->world map a click depends on — is
a pure ViewMap that inverts render-svg's translate(-min_x, max_y) scale(1 -1)
transform, unit-tested for round-trip, the y-up corners, and the logical-vs-ceiled
size mapping (the texture is displayed at the SVG's logical size with a uv crop, so
the click plane is not stretched by the pixmap's rounded-up dimensions). rerender
updates view box, logical size, and texture together on success and clears the
texture on a rasterization failure, so the pixels never disagree with the click
plane.
eframe + resvg are the workspace's first heavy external deps. eframe is pinned to
0.29 for the classic App::update(ctx) + panel API (0.35 redesigned App around
ui()). The crate needs a newer toolchain than the workspace MSRV, so CI excludes
it from the pinned-1.77 workspace commands and checks it in a separate
current-stable editor-gui job; the rest of the workspace is unaffected.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NAtEiJtt9yKVV1zjKYmZhS