Push 3 ratify: extend the slur-rendering requirement + refresh slur_shape

The three slur refinements (dashed rendering, curve splitting, slur_shape
measured) lifted into the spec — Chapter 7 / Quality Metric Catalog only,
non-canonical, so no wire form and no companion-version move.

core_spec Ch7: req:layoutir:slur-curve extended — an authored non-Solid
SpanStyle line renders faithfully (the LineStyle rides the 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). Only the curvature-computing algorithm stays
forward-referenced out now (dash rendering no longer deferred).

quality_metric_catalog: the §slur_shape rationale and the notated-but-unrendered
open question refreshed to record slurs now render and are measured; the formula
(req:qmc:slur) is unchanged, so no catalog version move.

Revision-history row (Push 3); a Push-3 tranche in PASS12_RATIFICATION_LOG.md;
layout-ir DECISIONS cross-ref extended. Both specs build clean (latexmk
-xelatex, 0 undefined refs). No code change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Levi Neuwirth 2026-07-08 17:33:11 -04:00
parent 7d61271069
commit 449dd2ef8e
6 changed files with 79 additions and 19 deletions

View File

@ -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

View File

@ -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.

Binary file not shown.

View File

@ -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}

Binary file not shown.

View File

@ -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}}