The audit's fourth push: the biggest outstanding Phase-2 item plus the performance gate. 793 workspace tests pass; clippy -D warnings, fmt, and rustdoc (deny-warnings) clean; all three spec documents build with zero undefined references. Binary Format companion (spec/binary_format.tex, v0.1.0 — Agent J's deliverable, 43 pages): - Twelve chapters transcribed from the golden-locked implementation: encoding conventions (the three prefix/endianness regimes, a normative no-varint rule, reject-never-normalize decode discipline), identifiers imported from the core spec's Canonical Byte-Layout Reference, primitive value encodings, the whole-Score positional codec ratified as the schema-major-0 wire form, operation wire forms (envelope field order with the normative id-leads property, the OperationPayload 0..=3 and OperationKind 0..=23 tables, effects/conflict/anomaly/MaterializedState vocabulary), the bundle physical layout (64-byte header, 256-byte superblock, chunk preimages and framing, ChunkRef, manifest body order), the operation-index payload, and the extension-blob/edit-barrier byte forms. - Ratifies P12-D1 (req:binfmt:opindex), P12-E1 (req:binfmt:ext-blobs), P12-E2 (req:binfmt:condition-depth, MAX_CONDITION_DEPTH = 64 normative), and P12-E3 (req:binfmt:object-kind-open) — batch rows struck through; discharges the provisional-codec notes in core (P11-4), ops, and bundle (P11-D2/D4/D5) DECISIONS with ratification cross-references. - Pins the frozen-layout schema-evolution keystone: within schema major 0 every positional struct layout is frozen; a field-set change is a schema-major change with migration — formally grounding the data-model-expansion staging decision. Open questions kept honest in-document: SnapshotId derivation, index-refresh threshold, u64/u32 prefix unification at the next major. - Not yet delivered from J's charter: the cross-implementation decoder test and the wire-format fuzzer (follow-up harnesses). F1 benches (crates/epiphany-testkit/benches/, per the F0 decision): - criterion 0.5.1 (workspace dev-dependency; MSRV 1.77 respected with documented transitive pins: clap 4.5.53, half 2.4.1). - reduction bench at 1K/10K/50K envelopes with the Chapter-10 budget (>10,000 envelopes/second cold) written in the bench as a Pass/Xfail gate; bundle benches for the typical-edit commit (<=50 ms; measured ~14.7 ms on real disk after catching that tmpfs neuters fsync) and the open/bootstrap read (<=200 ms; measured ~60 us). - CI: quick budget gates in the conformance job, full gates nightly. Subquadratic canonical_reduction_order (the F-surfaces/K-fixes handshake, closing K's 10K-envelope acceptance gate): - The bench documented the failure (50K at ~1.7K env/s, a 29 s cold reduction; two O(n^2) loops); the fix replaces pair enumeration with threshold/frontier readiness per replica plus explicit-dot dependent lists and a stamp-tuple binary heap — O((n + sum(context)) log n), never materializing covered pairs. - Byte-identical order: same edge relation, same ready predicate, same total order; the old implementation is retained as a test-only oracle with element-for-element order-equality property tests over fuzz sets, adversarial sets, and directed shapes (2,000-envelope full-coverage chains, dot cycles, duplicate-id stamp ties), mutation-tested for sensitivity. - Measured: 1K 155K->674K env/s, 10K 12.5K->257K, 50K 1.7K->87K; all three scale points now pass and the 50K row is promoted from Xfail. Also: fixed nine rustdoc private/unresolved intra-doc links that had accumulated across the pushes (the CI deny-doc-warnings job would have failed on them). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NEs4aYiu8MXjdYdMxw8PTd |
||
|---|---|---|
| .. | ||
| src | ||
| Cargo.toml | ||
| DECISIONS.md | ||
| README.md | ||
README.md
epiphany-layout-ir
The Epiphany layout intermediate representation and constraint-solver
interface, implementing the normative requirements of Chapter 7 ("Layout
Intermediate Representation") and the interface of Chapter 9
("Constraint-Solver Interface") of the core specification
(spec/core_spec.pdf). This is Agent E's crate per spec/QUICKSTART.md — it
lands last among the implementation crates, building on Agent A's
epiphany-determinism and Agent B's epiphany-core (and on Agent C's
OperationKindTag for the edit-barrier types — see DECISIONS.md).
The IR sits between the score graph and two downstream consumers: the constraint solver, which resolves spacing and positioning, and the renderer, which produces final visual output. — Chapter 7
The score graph is the canonical truth about the music; this crate is a downstream projection of it. The transformation is a pipeline of four stages, each with its own type and a deterministic, provenance-preserving contract for the next.
What's here
| Area | Items | Spec |
|---|---|---|
| Stage 1 — logical | LogicalLayoutIR, LayoutRegion, composite LayoutObject, overrides/cross-region objects, to_logical |
Ch. 7 §"LogicalLayoutIR" |
| Stage 2 — constrained | ConstrainedLayoutIR, SpringSlot, LayoutConstraint, GlyphObject, to_constrained |
Ch. 7 §"ConstrainedLayoutIR" |
| Stage 3 — resolved | ResolvedLayoutIR, pages/systems/staves/measures, ResolvedGlyph |
Ch. 7 §"ResolvedLayoutIR" |
| Stage 4 — render (interface only) | RenderIR, RenderPrimitive, RenderIRProducer, to_render |
Ch. 7 §"RenderIR" |
| Time axis | canonical TimeAxisModel plus dynamic TimeAxis, including registered payload preservation |
Ch. 7 §"Layout Regions" |
| Provenance | Provenance, LayoutObjectId, SynthesisKind, stable_layout_id (a pure function of the source — stable across relayouts) |
Ch. 7 §"Provenance" |
| Engraving decisions | EngravingDecision/EngravingDecisionId/EngravingDecisionKind, DecisionSource |
Ch. 7 §"Engraving Decisions" |
| Vertical bands | VerticalBand/VerticalBandId/VerticalBandKind |
Ch. 7 §"Vertical Bands" |
| Incremental cache | LayoutCache, DependencyIndex, granular stage caches and invalidation |
Ch. 7 §"Incremental Layout and Caching" |
| Glyph catalog | GlyphCatalog (metric-lookup interface) + in-tree BravuraCatalog, GlyphCatalogIdentity, SmuflVersion, FontId, GlyphMetric/GlyphAnchor, BRAVURA_METRICS/BRAVURA_VERSION, metrics_hash_for (MUSCFNTM-tagged) |
Ch. 7 §"Glyph Catalog Interface" / §7.3.2 |
| Edit barriers | EditBarrier, BarrierScope, BarrierCondition, ObjectKind, EditContext (precise scope evaluation), keyed on Agent C's OperationKindTag |
Ch. 8 §"Edit Barriers" |
| Solver interface | ConstraintSolver (solve/solve_incremental, Send + Sync), SolverConfig/SolverBudget, SolverState, InvalidationSet, SolveReport, SolveStatus, SolverTier/SolverVersion, the v0 StubSolver |
Ch. 9 |
| Round-trip | round_trip, RoundTripReport, laid_out_object_ids |
Ch. 7 (v0 acceptance criterion 6) |
The stub solver
Per the QUICKSTART, the v0 constraint solver is a stub: StubSolver returns
SolveStatus::Solved with the input geometry verbatim (each glyph's resolved
position is exactly its constrained baseline), preserves provenance, and reports
all hard constraints satisfied. The real solver — Cassowary or otherwise — comes
later (Chapter 9 specifies the interface, not the algorithm); v0 only needs to
round-trip IR through the solver interface to prove the contracts hold. The one
stub validates the full Chapter 7 §7.3.2 catalog identity and all slot, band,
and geometry cross-references before reporting Solved. Explicit constraints
are rejected because this interface-only solver cannot honestly evaluate them.
The round-trip (v0 acceptance criterion 6)
round_trip runs graph → LogicalLayoutIR → ConstrainedLayoutIR →
stub-solved ResolvedLayoutIR → RenderIR and asserts the contract every stage
must satisfy:
- the stub solver reports
Solvedwith all hard constraints satisfied; - the complete
Provenanceof every object —source,synthesis,dependencies, andstable_id— survives every stage unchanged; - no two objects ever share a
stable_id, so manifestation multiplicity is preserved (a source manifested in two regions stays two layout objects); - the stub solver returns the input geometry verbatim;
- the set of score-graph sources recovered from the
RenderIRis exactly the set laid out — a surjection onto graph identity (one source may back several manifestations, each with its own stable id).
Agent F's testkit drives this same entry point (layout_stub::round_trip) on the
10-measure single-staff hand-off fixture and the rich multi-region generator.
Algorithmic scope
Per the QUICKSTART ("a prototype baseline, not the product"), this crate implements the Chapter 7 IR contracts and interface types, not a production engraving engine. The real spacing and casting-off algorithms, quality-metric computation, constraint solver, and renderer remain later implementations of these interfaces.
Determinism
IR coordinates are single-precision staff spaces (StaffSpace(f32),
Chapter 7 §7.2); the canonical ResolvedLayoutIR output quantizes them to
the 1/1024 grid at serialization time
(ResolvedLayoutIR::canonical_bytes), exactly as Appendix D §"Quantized Layout
Coordinates" prescribes — quantization absorbs all f32 variation below 1/2048
staff space, so the canonical output is independent of the floating-point
environment. The glyph-catalog identity hashes its consulted metrics (advance,
bounding box, named anchors) under the MUSCFNTM domain tag, and the
edit-barrier types carry a canonical encoding with set-valued fields emitted in
canonical byte order (sorted and de-duplicated). See DECISIONS.md.
Tests
cargo test -p epiphany-layout-ir covers each module plus the round-trip on
Agent B's valid_score / valid_score_rich generators. The end-to-end v0
acceptance gate (criterion 6) lives in the testkit.