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
Lands the renderer-against-stub slice of Agent I's visible engraving work
(spec/PHASE2_QUICKSTART.md). Two new crates; prerequisites (G Pass 11, H
spelling/decomposition) are in place. Real engraving + Minimal-tier solver
follow next phase.
epiphany-render-svg (the deliverable this phase):
- Renders a ResolvedLayoutIR to well-formed SVG 1.1, drawing each glyph as a
GENUINE Bravura SMuFL outline <path>. Outlines are extracted reproducibly
from the official OFL Bravura.otf by a committed generator
(tools/extract_bravura_outlines.py, OFL.txt); the font is not vendored, only
the generated Rust (src/outlines_generated.rs). Staff-space/y-up coords with
one global y-flip wrapper; viewBox in staff spaces, px scale on the root.
- Non-overreach: every element traces to a ResolvedGlyph (data-prov) or a
declared wrapper; a glyph lacking an outline is surfaced as a diagnostic and
drawn as a fallback rect, never silently dropped.
- Hand-rolled xml::check_well_formed (no XML dep); acceptance tests cross-check
with system xmllint when present.
- examples/render_fixture.rs demo (fixture name -> SVG stdout, --solver=stub|real).
- Golden-locked machine acceptance snapshot + full-SVG golden for
ten_measure_single_staff and valid_score_rich; deterministic output.
epiphany-engrave (honest scaffold):
- Engraver: a deterministic horizontal-spacing pass (first axis of the planned
two-pass spring layout). Reports SolverTier::Stub — NOT Minimal — until it
evaluates the declared hard constraints, guarded by a regression test. The
demo's --solver=real exercises it end to end.
Honesty notes (recorded as Pass-12 candidates P12-I1..I3 in spec/PASS12_BATCH.md
and the crates' DECISIONS.md): the v0 to_logical/to_constrained pipeline is a
structural placeholder (arbitrary glyph per object, y=0), so stub output is not
yet recognizable notation and the QUICKSTART human visual gate is a next-phase
gate; MUSCLOID layout-id derivation stays unwired; bundled BRAVURA_METRICS are
approximations that disagree with the real outlines.
Gates: cargo fmt + clippy -D warnings clean; cargo test --workspace 504 passed,
0 failed, 0 ignored (criterion 6 layout round-trip still green).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>