diff --git a/crates/epiphany-layout-ir/DECISIONS.md b/crates/epiphany-layout-ir/DECISIONS.md index cbc8f7e..3466e6a 100644 --- a/crates/epiphany-layout-ir/DECISIONS.md +++ b/crates/epiphany-layout-ir/DECISIONS.md @@ -571,9 +571,15 @@ these are E1 implementation decisions for the Phase-F ratification pass: > `req:layoutir:resolved-primitives` in core spec Chapter 7 (§ResolvedLayoutIR) > — the struct listing now carries `strokes`/`curves` and the `Stroke`/`Curve` > shapes, and the RenderIR provenance requirement was widened to name all three -> primitive kinds. The curvature *algorithm* and dash rendering stay -> forward-referenced out. Non-canonical, so no wire/companion-version change +> primitive kinds. Non-canonical, so no wire/companion-version change > (PASS12_RATIFICATION_LOG.md, schema-major-2 tranche). +> +> **Extended (Push 3, 2026-07-08):** the three E2 deferrals landed and +> `req:layoutir:slur-curve` was extended — dashed/dotted lines render faithfully +> (the `Curve` listing gains `line`), break-spanning slurs split into per-system +> sub-curves (de Casteljau), and `slur_shape_penalty` is measured (only the +> curvature *algorithm* stays forward-referenced out now). See the Push-3 +> tranche in PASS12_RATIFICATION_LOG.md and the engrave DECISIONS. The third pipeline primitive kind. Primitives were two parallel flat Vecs (`glyphs`, `strokes`) at each of the three IR stages; a `Curve` (four control diff --git a/spec/PASS12_RATIFICATION_LOG.md b/spec/PASS12_RATIFICATION_LOG.md index c66e089..eab65f7 100644 --- a/spec/PASS12_RATIFICATION_LOG.md +++ b/spec/PASS12_RATIFICATION_LOG.md @@ -208,3 +208,30 @@ stays 0.6.0 — layout geometry is non-canonical. curve splitting (de Casteljau), and the `slur_shape` quality metric moving off `0.0`-by-construction — all Standard-tier / Push-3 work, named in the crate DECISIONS, none a Pass-13 ambiguity. + +## Push-3 tranche (2026-07-08) — slur rendering completion + +The three slur refinements the schema-major-2 Phase-F ratification deferred, +landed and ratified. Layout-IR (Chapter 7) only, non-canonical — a +ratify-as-implemented with **no wire form and no companion version move** +(mirrors the schema-major-2 rendering tranche). Delivered as commits `c5173d2` +(dashed rendering), `5869691` (curve splitting), `7d61271` (slur_shape +measured). + +| Item | Disposition | Spec locus | Consumer | +|---|---|---|---| +| Dashed/dotted slur rendering | **adopt** — `req:layoutir:slur-curve` extended: an authored non-`Solid` `SpanStyle` line renders faithfully (the `LineStyle` rides the `Curve`, whose Ch7 listing gains the field); an implementation that defers the pattern must surface it, never silently render solid. The E2 `SlurLineStyleNotRendered` diagnostic is retired (the style is rendered, not deferred) | core_spec Ch7 §ResolvedLayoutIR (`req:layoutir:slur-curve`, `Curve` listing) | `epiphany-layout-ir` (`Curve.line`); `epiphany-render-svg` (`stroke-dasharray`) | +| Curve splitting across systems | **adopt** — `req:layoutir:slur-curve` extended: a slur spanning a system break splits into per-system sub-curves by de Casteljau (first segment keeps the slur's provenance, the rest synthesized continuations under `req:layoutir:continuation-synthesis`), replacing E2's draw-whole-in-start-system floating end | core_spec Ch7 §ResolvedLayoutIR (`req:layoutir:slur-curve`) | `epiphany-engrave` (casting `curve_fate`, `sub_cubic`) | +| slur_shape measured | **adopt (implement pinned formula)** — `slur_shape_penalty` moves off its `0.0` placeholder to the catalog's pinned `req:qmc:slur` formula (arc ratio ρ = apex/chord against the `[0.08, 0.25]` band). The Quality Metric Catalog's §`slur_shape` rationale and the notated-but-unrendered open question are refreshed to record slurs now render and are measured; the formula is unchanged, so no catalog version move | quality_metric_catalog §`slur_shape_penalty` (`req:qmc:slur`, rationale) | `epiphany-engrave` (`quality.rs::slur_shape_raw`) | + +**Version movements.** None: core spec Ch7 `req:layoutir:slur-curve` extended + +the `Curve` listing gains `line`; a revision-history row (Push 3); the Quality +Metric Catalog rationale refreshed (no formula change). Operation Catalog stays +0.7.0, Binary Format 0.6.0, Quality Metric Catalog 0.2.0 — all non-canonical / +formula-stable. + +**Deferred (documented, not open candidates).** Kind-differentiated slur +appearance (Phrase/Editorial's own line, distinct from the SpanStyle dash), +duration-aware slur height (would pull the clamped short/long slurs back into +the shallow-arc band), collision-aware slur reshaping (the Standard-tier +`slur_shape` driver) — all Standard-tier work. diff --git a/spec/core_spec.pdf b/spec/core_spec.pdf index 3e91326..8c77a2c 100644 Binary files a/spec/core_spec.pdf and b/spec/core_spec.pdf differ diff --git a/spec/core_spec.tex b/spec/core_spec.tex index 64395b8..540eda9 100644 --- a/spec/core_spec.tex +++ b/spec/core_spec.tex @@ -9289,6 +9289,10 @@ pub struct Curve { pub thickness: StaffSpace, pub layer: i32, pub style: GlyphStyle, + + /// The line pattern the renderer strokes the path with + /// (a slur's authored `SpanStyle.line`): solid, dashed, or dotted. + pub line: LineStyle, } \end{lstlisting} @@ -9333,19 +9337,24 @@ pub struct Curve { \begin{requirement} \label{req:layoutir:slur-curve} - \textbf{Minimal-tier slur rendering (ratified schema-major-2, - Phase~F).} A \texttt{Slur} (\ref{sec:graph:slurs}) \MUST{} render + \textbf{Slur rendering (ratified schema-major-2, Phase~F; extended + Push~3).} A \texttt{Slur} (\ref{sec:graph:slurs}) \MUST{} render as a cubic-B\'ezier \texttt{Curve} arcing between its two endpoint event columns, honoring an authored \texttt{CurvatureOverride} (direction and apex height) when present and choosing them otherwise. A slur whose endpoint does not resolve to a column on a single staff of one region draws \emph{no} curve: a traced anchor preserves its provenance rather than a floating arc. An authored - non-\texttt{Solid} \texttt{SpanStyle} line (dashed, dotted) \MAY{} - be deferred to a higher tier, but \MUST{} be surfaced (a layout - diagnostic), never silently rendered solid. The curvature-computing - algorithm and the dash rendering are engraving-specification - concerns (\ref{sec:layoutir:forward}). + non-\texttt{Solid} \texttt{SpanStyle} line (dashed, dotted) is + rendered faithfully as that pattern (its \texttt{LineStyle} rides + the \texttt{Curve}); an implementation that instead defers the + pattern \MUST{} surface the deferral (a layout diagnostic), never + silently rendering solid. A slur whose span crosses a system break + \MUST{} split into per-system sub-curves --- the first carrying the + slur's provenance, the rest engraver-synthesized continuations + (\ref{req:layoutir:continuation-synthesis}) --- rather than drawing + whole in one system. The curvature-computing algorithm remains an + engraving-specification concern (\ref{sec:layoutir:forward}). \end{requirement} \section{RenderIR (Interface Only)} @@ -15507,6 +15516,19 @@ layouts they own versus inherit: moves --- an engrave-side ratify-as-implemented, mirroring the schema-major-1 Phase~F precedent. \\ + \today & Layout IR (slur rendering completion, Push 3) & + The three slur refinements \ref{req:layoutir:slur-curve} deferred are + now landed and its requirement extended: an authored non-\texttt{Solid} + \texttt{SpanStyle} line renders faithfully (dashed / dotted --- the + \texttt{LineStyle} rides the \texttt{Curve}, whose listing gains the + field), a slur spanning a system break splits into per-system + sub-curves (de~Casteljau; first segment keeps the slur's provenance, + the rest synthesized continuations), and \texttt{slur\_shape\_penalty} + moves off its pinned $0.0$ to a real measurement (Quality Metric + Catalog \sectionsc{slur\_shape\_penalty} rationale refreshed; formula + unchanged, no version move). Layout geometry stays non-canonical --- no + wire form, no companion version moves. + \\ \bottomrule \end{longtable} diff --git a/spec/quality_metric_catalog.pdf b/spec/quality_metric_catalog.pdf index ce05f1c..65cbb7c 100644 Binary files a/spec/quality_metric_catalog.pdf and b/spec/quality_metric_catalog.pdf differ diff --git a/spec/quality_metric_catalog.tex b/spec/quality_metric_catalog.tex index 3c006e6..9c13324 100644 --- a/spec/quality_metric_catalog.tex +++ b/spec/quality_metric_catalog.tex @@ -601,18 +601,19 @@ all} and claims no conformance tier (the core's \texttt{Stub} tier). \begin{openquestion} \textbf{The notated-but-unrendered honesty edge.} A score whose -\emph{source} notates slurs, engraved by a solver that draws no slur -geometry, scores $\texttt{slur\_shape\_penalty} = 0.0$ under this rule --- -the axis sees no drawn slurs and finds nothing to penalize, even though -the output is arguably \emph{worse} than a badly-drawn slur. v0.1 -deliberately pins vacuous-$0.0$: the metric axes evaluate the geometry the -solver produced, and \emph{rendering completeness} --- whether notated +\emph{source} notates geometry a solver does not draw scores +vacuous-$0.0$ on that axis under this rule --- the axis sees nothing +drawn and finds nothing to penalize, even though the output is arguably +\emph{worse} than a badly-drawn one. The metric axes evaluate the geometry +the solver produced, and \emph{rendering completeness} --- whether notated content is realized at all --- is governed by constraint families and visual acceptance testing, not by the quality metrics. Should a future revision instead score notated-but-unrendered geometry classes at the worst value, so that the metric vector cannot flatter an incomplete renderer? Resolving this requires a normative definition of ``notated content that demands drawn geometry,'' which does not exist yet. +\emph{Slurs no longer instance this edge} (they render and are measured, +schema-major-2); it persists for still-logical-only classes such as beams. \end{openquestion} \section{Normalization Form} @@ -814,10 +815,14 @@ The anchor makes a semicircular slur ($\rho = 0.5$, $\mathit{raw}_u = 0.25$) exactly worst-tolerable, and a completely flat slur ($\rho = 0$, $\mathit{raw}_u = 0.08$) roughly a third of the way to failing. -The v0.1 reference pipeline draws no slur geometry (slurs exist logically, -not as curves), so this axis evaluates to $0.0$ today under the -vacuous-geometry rule --- the definition is pinned now so that the first -implementation to draw slurs is measured from its first release. +The implementation now \emph{draws} slurs as cubic-B\'ezier curves and +measures this axis directly (schema-major-2 rendering; the first +slur-drawing release, as the pinned definition anticipated). A layout with +no drawn slur curve still evaluates to $0.0$ under the vacuous-geometry +rule. A tier that draws the ideal shallow arc for every slur measures $0$ +on this axis; a fixed-height engraver scores non-zero on slurs whose span +pushes the arc ratio outside the $[0.08, 0.25]$ band (a very short or very +long slur), which a duration-aware height corrects. \end{rationale} \section{\texttt{beam\_slope\_penalty}}