epiphany/spec/quality_metric_catalog.tex

1416 lines
63 KiB
TeX

% !TEX program = xelatex
%
% Epiphany --- Quality Metric Catalog (companion specification)
% Companion to the Core Specification. Compile with XeLaTeX.
%
% This document is versioned independently of the Core Specification
% (independent semver; see the Versioning note in the front matter). Its preamble
% is intentionally a self-contained copy of the core specification's preamble so
% the two documents build independently; factoring a shared preamble file is a
% later cleanup, not a v0.1 deliverable.
\documentclass[11pt,letterpaper]{report}
% ---------------------------------------------------------------------------
% Packages
% ---------------------------------------------------------------------------
\usepackage{fontspec}
\usepackage{geometry}
\geometry{
letterpaper,
top=1.05in,
bottom=1.05in,
left=1.15in,
right=1.15in,
headheight=15pt
}
\usepackage[english]{babel}
\usepackage{microtype}
\usepackage{parskip}
\usepackage{xcolor}
\usepackage{hyperref}
\usepackage{enumitem}
\usepackage{titlesec}
\usepackage{fancyhdr}
\usepackage{booktabs}
\usepackage{array}
\usepackage{longtable}
\usepackage{listings}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{tcolorbox}
\tcbuselibrary{breakable, skins}
% ---------------------------------------------------------------------------
% Color palette (shared with the core specification)
% ---------------------------------------------------------------------------
\definecolor{epiphanyteal}{HTML}{1A4044}
\definecolor{epiphanygold}{HTML}{8E6E2E}
\definecolor{epiphanyink}{HTML}{1F1B16}
\definecolor{epiphanyslate}{HTML}{6B6660}
\definecolor{epiphanycream}{HTML}{F8F4ED}
\definecolor{epiphanymist}{HTML}{ECE8E0}
\definecolor{epiphanycode}{HTML}{2A2520}
\definecolor{epiphanycrimson}{HTML}{7A2424}
\hypersetup{
colorlinks=true,
linkcolor=epiphanyteal,
citecolor=epiphanyteal,
urlcolor=epiphanygold,
pdftitle={Epiphany --- Quality Metric Catalog},
pdfauthor={The Epiphany Project},
pdfsubject={Quality Metric Catalog companion for the Epiphany music notation platform},
pdfkeywords={music notation, engraving, quality metrics, normalization, conformance tiers, solver profiles},
bookmarksnumbered=true,
bookmarksopen=true
}
% ---------------------------------------------------------------------------
% Typography (shared with the core specification)
% ---------------------------------------------------------------------------
\setmainfont{TeX Gyre Pagella}[Numbers={OldStyle, Proportional}, Ligatures={TeX, Common}]
\setsansfont{TeX Gyre Heros}[Scale=0.94, Ligatures={TeX, Common}]
\setmonofont{TeX Gyre Cursor}[Scale=0.88, Ligatures={TeX}]
\newfontfamily\titlefont{TeX Gyre Pagella}[Numbers={OldStyle}, Ligatures={TeX, Common}]
\newcommand{\tablenums}[1]{{\addfontfeatures{Numbers={Lining,Tabular}}#1}}
\newcommand{\sectionsc}[1]{{\addfontfeatures{Letters=SmallCaps}#1}}
% ---------------------------------------------------------------------------
% Section styling (shared with the core specification)
% ---------------------------------------------------------------------------
\titleformat{\chapter}[display]
{\normalfont\filright}
{\raggedright\color{epiphanygold}\fontsize{14pt}{16pt}\selectfont
\scshape Chapter\ \thechapter}
{16pt}
{\raggedright\color{epiphanyteal}\fontsize{32pt}{36pt}\selectfont\bfseries}
[\vspace{4pt}{\color{epiphanygold}\rule{2in}{0.6pt}}]
\titlespacing*{\chapter}{0pt}{-20pt}{30pt}
\titleformat{\section}
{\normalfont\Large\bfseries\color{epiphanyteal}}
{\color{epiphanygold}\thesection}{1em}{}
\titleformat{\subsection}
{\normalfont\large\bfseries\color{epiphanyteal}}
{\color{epiphanygold}\thesubsection}{1em}{}
\titleformat{\subsubsection}
{\normalfont\normalsize\bfseries\color{epiphanyink}}
{\thesubsubsection}{1em}{}
% ---------------------------------------------------------------------------
% Headers and footers (shared with the core specification)
% ---------------------------------------------------------------------------
\pagestyle{fancy}
\fancyhf{}
\renewcommand{\headrulewidth}{0pt}
\renewcommand{\footrulewidth}{0pt}
\fancyhead[L]{\small\scshape\color{epiphanyslate}Epiphany --- Quality Metric Catalog}
\fancyhead[R]{\small\itshape\color{epiphanyslate}\leftmark}
\fancyfoot[C]{\small\color{epiphanyslate}\thepage}
\renewcommand{\headrule}{
\color{epiphanygold!50}\hrule width\headwidth height 0.4pt
\vspace{1pt}
\color{epiphanygold!30}\hrule width\headwidth height 0.2pt
}
% ---------------------------------------------------------------------------
% Code listing style (shared with the core specification)
% ---------------------------------------------------------------------------
\lstdefinelanguage{Rust}{
keywords={fn,let,mut,pub,struct,enum,impl,trait,for,in,if,else,match,return,
use,mod,crate,self,Self,as,where,move,async,await,const,static,
ref,type,unsafe,extern,dyn,box,break,continue,loop,while},
keywordstyle=\color{epiphanyteal}\bfseries,
ndkeywords={i8,i16,i32,i64,i128,u8,u16,u32,u64,u128,f32,f64,bool,char,str,
String,Vec,Option,Result,Box,Rc,Arc,HashMap,BTreeMap,
NonZeroU16,NonZeroU32,NonZeroU64,Duration,Timestamp},
ndkeywordstyle=\color{epiphanygold}\bfseries,
sensitive=true,
comment=[l]{//},
morecomment=[s]{/*}{*/},
commentstyle=\color{epiphanyslate}\itshape,
stringstyle=\color{epiphanycrimson},
morestring=[b]",
morestring=[b]'
}
\lstset{
basicstyle=\ttfamily\small\color{epiphanycode},
backgroundcolor=\color{epiphanycream},
frame=leftline,
rulecolor=\color{epiphanygold!60},
framesep=8pt,
framerule=1.5pt,
xleftmargin=10pt,
xrightmargin=4pt,
breaklines=true,
showstringspaces=false,
numberstyle=\tiny\color{epiphanyslate},
numbersep=10pt,
captionpos=b,
aboveskip=10pt,
belowskip=10pt,
language=Rust
}
% ---------------------------------------------------------------------------
% Custom environments (shared with the core specification)
% ---------------------------------------------------------------------------
\newtcolorbox{openquestion}[1][]{
enhanced, breakable,
colback=epiphanymist, colframe=epiphanycrimson,
fonttitle=\bfseries\color{white}, title={\scshape\hspace{2pt}Open Question},
coltitle=white, colbacktitle=epiphanycrimson,
arc=1pt, boxrule=0pt, leftrule=2pt,
left=10pt, right=10pt, top=8pt, bottom=8pt,
attach boxed title to top left={xshift=0pt, yshift=0pt},
boxed title style={arc=0pt, sharp corners, boxrule=0pt, left=6pt, right=8pt, top=2pt, bottom=2pt},
#1
}
\newtcolorbox{rationale}[1][]{
enhanced, breakable,
colback=epiphanymist, colframe=epiphanyteal,
fonttitle=\bfseries\color{white}, title={\scshape\hspace{2pt}Rationale},
coltitle=white, colbacktitle=epiphanyteal,
arc=1pt, boxrule=0pt, leftrule=2pt,
left=10pt, right=10pt, top=8pt, bottom=8pt,
attach boxed title to top left={xshift=0pt, yshift=0pt},
boxed title style={arc=0pt, sharp corners, boxrule=0pt, left=6pt, right=8pt, top=2pt, bottom=2pt},
#1
}
\newtcolorbox{requirement}[1][]{
enhanced, breakable,
colback=white, colframe=epiphanygold,
fonttitle=\bfseries\color{white}, title={\scshape\hspace{2pt}Requirement},
coltitle=white, colbacktitle=epiphanygold,
arc=1pt, boxrule=0pt, leftrule=2pt,
left=10pt, right=10pt, top=8pt, bottom=8pt,
attach boxed title to top left={xshift=0pt, yshift=0pt},
boxed title style={arc=0pt, sharp corners, boxrule=0pt, left=6pt, right=8pt, top=2pt, bottom=2pt},
#1
}
\newtcolorbox{nongoal}[1][]{
enhanced, breakable,
colback=epiphanymist, colframe=epiphanyslate,
fonttitle=\bfseries\color{white}, title={\scshape\hspace{2pt}Non-Goal},
coltitle=white, colbacktitle=epiphanyslate,
arc=1pt, boxrule=0pt, leftrule=2pt,
left=10pt, right=10pt, top=8pt, bottom=8pt,
attach boxed title to top left={xshift=0pt, yshift=0pt},
boxed title style={arc=0pt, sharp corners, boxrule=0pt, left=6pt, right=8pt, top=2pt, bottom=2pt},
#1
}
\newcommand{\MUST}{\textbf{MUST}}
\newcommand{\MUSTNOT}{\textbf{MUST}\nobreak\ \textbf{NOT}}
\newcommand{\SHOULD}{\textbf{SHOULD}}
\newcommand{\SHOULDNOT}{\textbf{SHOULD}\nobreak\ \textbf{NOT}}
\newcommand{\MAY}{\textbf{MAY}}
\setlist[itemize]{topsep=2pt, itemsep=3pt, parsep=0pt}
\setlist[enumerate]{topsep=2pt, itemsep=3pt, parsep=0pt}
\setlist[description]{topsep=2pt, itemsep=5pt, parsep=0pt}
\AtBeginDocument{\color{epiphanyink}}
% ---------------------------------------------------------------------------
% Document
% ---------------------------------------------------------------------------
\begin{document}
\begin{titlepage}
\thispagestyle{empty}
\centering
\vspace*{2.2in}
{\color{epiphanygold}\rule{3in}{0.8pt}}\\[18pt]
{\titlefont\fontsize{34pt}{38pt}\selectfont\color{epiphanyteal}\bfseries Epiphany}\\[10pt]
{\Large\scshape\color{epiphanyslate}Quality Metric Catalog}\\[6pt]
{\large\itshape\color{epiphanyslate}A companion to the Core Specification}\\[14pt]
{\color{epiphanygold}\rule{3in}{0.8pt}}\\[24pt]
{\normalsize\color{epiphanyink}Version 0.3.0 --- Phase 3 (the normative metric set: formal definitions, normalization, weights, tier thresholds, profile registry; \texttt{spacing\_distortion} scoped to rhythmic columns; \texttt{vertical\_density\_penalty} counted per realization)}\\[4pt]
{\small\color{epiphanyslate}Normative for the metrics and thresholds it defines}
\vfill
\end{titlepage}
\tableofcontents
% ===========================================================================
\chapter{About This Companion}
\label{ch:about}
The \emph{Quality Metric Catalog} is a companion to the Epiphany Core
Specification. It fulfils the delegation of the core specification's
\sectionsc{Companion Specifications} appendix --- the section labeled
\texttt{sec:deferred:companions} --- which charters this document to
deliver ``per-metric normalization functions mapping raw measurements to
\texttt{NormalizedMetric} values, default tie-breaking weights, per-tier
metric thresholds, and the formal definition of each quality metric in the
normative metric set.''
This companion (v0.3.0) delivers all four chartered items, plus two small
registries the core specification names but defers here:
\begin{itemize}
\item the formal definition of each of the \textbf{nine normative metric
axes} --- the measured phenomenon, the raw measurement over resolved
layout geometry, and the normalization function with its pinned anchor
constant (Chapter~\ref{ch:metrics});
\item the \textbf{default tie-breaking weights}
(Chapter~\ref{ch:weights});
\item the \textbf{per-tier metric thresholds} for the Minimal and
Standard conformance tiers, the Advanced-tier extension rule, and the
\texttt{QualityFloorApproached} warning trigger
(Chapter~\ref{ch:thresholds});
\item the \texttt{QualityMetricKind} enumeration, which the core
specification references (as the payload of the
\texttt{QualityFloorApproached} solver warning) but never lists
(Section~\ref{sec:model:kind});
\item the \textbf{registered \texttt{SolverProfile} catalog}, which the
core specification's vocabulary appendix explicitly defers to this
companion (Chapter~\ref{ch:profiles});
\item the \textbf{Standard-tier constraint family} declaration, which the
core specification's Standard-tier requirement points at this companion
(Section~\ref{sec:thresholds:families}).
\end{itemize}
This document does \emph{not} cover:
\begin{itemize}
\item the reference suite's test scores, per-tier entry inclusion, and any
per-entry threshold overrides --- those are the \emph{Reference Suite}
companion's;
\item performance conformance (edit traces, frame budgets) --- the
\emph{Performance Reference Suite} companion's;
\item the reference solving algorithm --- the non-normative
\emph{Reference Algorithm} companion's.
\end{itemize}
\section{Relationship to the Core Specification}
\label{sec:about:relationship}
This companion does not restate the metric framework; it \emph{references}
it. The framework --- the \texttt{NormalizedMetric} validity rules (finite,
in $[0.0, 1.0]$, lower is better), the \texttt{QualityMetricVector} field
set, extension metrics, the \texttt{TieBreakingWeights} structure, the
Pareto-frontier design target, the conformance-tier ladder, and the
suite-based conformance model --- is the core specification's Chapter~9
(\sectionsc{The Constraint Solver Interface}, the \texttt{ch:solver}
chapter), in particular its \sectionsc{Quality Metrics},
\sectionsc{Conformance Tiers}, and \sectionsc{Conformance: The Reference
Suite} sections (\texttt{sec:solver:quality},
\texttt{sec:solver:tiers}, \texttt{sec:solver:conformance}).
Two core requirements bind this document into the conformance story:
\begin{itemize}
\item The core \sectionsc{Quality Metrics} normalization requirement:
``Per-metric normalization functions (mapping raw measurements to
$[0.0,1.0]$) are specified in the Quality Metric Catalog companion
document. Implementations \MUST{} use the catalog's normalization;
arbitrary normalization is non-conforming.'' Chapter~\ref{ch:metrics}
is that normalization.
\item The core tie-breaking requirement: ``Tie-breaking weights \MUST{}
have normative defaults specified in the Quality Metric Catalog.''
Chapter~\ref{ch:weights} is those defaults.
\end{itemize}
Where this document and a ratified core requirement disagree, \textbf{the
core requirement governs} and the discrepancy is a defect in this document.
Graph types, the layout IR pipeline
(\texttt{LogicalLayoutIR} $\rightarrow$ \texttt{ConstrainedLayoutIR}
$\rightarrow$ \texttt{ResolvedLayoutIR}),
the spring-slot and vertical-band models, and the built-in
\texttt{LayoutConstraint} kinds are the core specification's Chapter~7
(\texttt{ch:layout-ir}); this document's formulas range over those
structures without redefining them.
\begin{rationale}
\textbf{Versioning.} This companion is versioned independently of the core
specification (independent semver), like the Operation Catalog and the
Binary Format companions. Metric definitions and thresholds are expected to
be tuned on a faster cadence than the solver framework: threshold revisions
informed by reference-suite experience are \textsc{minor} revisions here and
require no core-spec change, while a change to the metric \emph{field set}
(a new normative axis) is a core-spec change first, mirrored here.
\end{rationale}
\section{Conformance}
\label{sec:about:conformance}
The metric definitions, normalization functions, default weights, threshold
tables, and profile registry in this document are \textbf{normative}. A
solver that reports a \texttt{QualityMetricVector} computed by any function
other than the ones defined here is non-conforming, per the core
\sectionsc{Quality Metrics} requirement quoted above.
Conformance \emph{claims} are evaluated on the Reference Suite companion's
entry set: a solver claiming tier $T$ must keep every normative metric
within tier $T$'s threshold (Chapter~\ref{ch:thresholds}) on every suite
entry required at tier $T$. This document defines \emph{what is measured
and how much is tolerable}; the Reference Suite companion defines
\emph{on which scores}.
Two boundaries of that claim, developed in Chapter~\ref{ch:model}:
\begin{itemize}
\item Metric values are \emph{diagnostic}, never canonical state
(Section~\ref{sec:model:diagnostic}). No byte of canonical document
state depends on them.
\item Numeric agreement across implementations is \emph{not} required
(Section~\ref{sec:model:determinism}). The cross-implementation
contract is threshold conformance, not value equality.
\end{itemize}
% ===========================================================================
\chapter{The Metric Model}
\label{ch:model}
\section{Diagnostic Status}
\label{sec:model:diagnostic}
The quality metric vector rides on the \texttt{SolveReport} (core
specification Chapter~9, \sectionsc{The Solver Report}:
\texttt{SolveReport.metric\_vector}). It describes the layout; it is not
part of the layout. The solver's canonical output ---
\texttt{ResolvedLayoutIR} --- carries no metric field, and the core
specification's observational-equivalence rule is stated over
\texttt{ResolvedLayoutIR} bytes alone.
\begin{requirement}
\label{req:qmc:diagnostic}
Quality metrics are \textbf{diagnostic output}, never canonical state.
\begin{itemize}
\item A \texttt{QualityMetricVector} appears only on the
\texttt{SolveReport}. The canonical serialized form of
\texttt{ResolvedLayoutIR} \MUSTNOT{} contain quality-metric values,
and a \texttt{NormalizedMetric} value \MUSTNOT{} enter canonical
document bytes by any other path.
\item Two solves whose \texttt{ResolvedLayoutIR} values are
byte-identical under canonical serialization are observationally
equivalent regardless of their metric vectors. A metric value
\MUSTNOT{} be an input to any canonical-state decision.
\end{itemize}
\end{requirement}
\begin{rationale}
Keeping metrics off the canonical path is what makes them safely
improvable. A solver revision that measures more honestly (or a catalog
revision that tunes a formula) changes reports, warnings, and conformance
verdicts --- but not one byte of any document. The reference implementation
already has this shape: \texttt{ResolvedLayoutIR} has no metric field, the
\texttt{SolveReport} is never serialized, and no consumer reads the vector
to make a state decision.
\end{rationale}
\section{Determinism and Numeric Agreement}
\label{sec:model:determinism}
\begin{requirement}
\label{req:qmc:determinism}
Within one implementation version, metric computation \MUST{} be
deterministic: identical solve inputs (the same
\texttt{ConstrainedLayoutIR}, configuration, and declared page geometry)
\MUST{} yield bitwise-identical \texttt{QualityMetricVector} values.
Across implementations (and across versions of one implementation),
numeric agreement is \textbf{not} required. Two conforming solvers \MAY{}
report different metric values for the same score; the
cross-implementation contract is the core specification's four
suite-conformance conditions --- in particular, that every metric is within
the claimed tier's threshold on every required suite entry --- not value
equality.
Metric values are ordinary IEEE~754 \texttt{f64} values subject to the
core \texttt{NormalizedMetric} validity rules (finite, in $[0.0, 1.0]$).
This document imposes no additional quantization, rounding, or evaluation-
order discipline on their computation.
\end{requirement}
\begin{rationale}
Different conforming solvers legitimately produce different layouts, so
their metric values differ even under identical formulas; demanding numeric
agreement would smuggle cross-implementation layout equality in through the
diagnostics. Within-implementation determinism, by contrast, is load-
bearing: reproducible reports are what make threshold conformance testable
and regressions attributable.
\end{rationale}
\section{The Normative Metric Set and \texttt{QualityMetricKind}}
\label{sec:model:kind}
The nine normative metric axes are the nine non-extension fields of the
core specification's \texttt{QualityMetricVector}. The core references a
\texttt{QualityMetricKind} enumeration (the payload of
\texttt{SolverWarningKind::QualityFloorApproached}) without listing it;
this catalog pins it.
\begin{requirement}
\label{req:qmc:kind}
The \texttt{QualityMetricKind} enumeration is exactly:
\begin{lstlisting}[language=Rust]
pub enum QualityMetricKind {
Collision,
Spacing,
SlurShape,
BeamSlope,
VerticalDensity,
SystemBreak,
PageFill,
CastingOff,
SymbolDensity,
}
\end{lstlisting}
Each kind names exactly one \texttt{QualityMetricVector} field and exactly
one \texttt{TieBreakingWeights} field, per
Table~\ref{tab:kind-mapping}. Extension metrics are not
\texttt{QualityMetricKind} values; they are identified by
\texttt{ExtensionMetricId}.
\end{requirement}
\begin{table}[h]
\centering
\small
\begin{tabular}{lll}
\toprule
\textbf{Kind} & \textbf{Vector field} & \textbf{Weight field} \\
\midrule
\texttt{Collision} & \texttt{collision\_penalty} & \texttt{collision} \\
\texttt{Spacing} & \texttt{spacing\_distortion} & \texttt{spacing} \\
\texttt{SlurShape} & \texttt{slur\_shape\_penalty} & \texttt{slur\_shape} \\
\texttt{BeamSlope} & \texttt{beam\_slope\_penalty} & \texttt{beam\_slope} \\
\texttt{VerticalDensity} & \texttt{vertical\_density\_penalty} & \texttt{vertical\_density} \\
\texttt{SystemBreak} & \texttt{system\_break\_penalty} & \texttt{system\_break} \\
\texttt{PageFill} & \texttt{page\_fill\_efficiency} & \texttt{page\_fill} \\
\texttt{CastingOff} & \texttt{casting\_off\_quality} & \texttt{casting\_off} \\
\texttt{SymbolDensity} & \texttt{symbol\_density\_uniformity} & \texttt{symbol\_density} \\
\bottomrule
\end{tabular}
\caption{The nine normative axes: kind, vector field, tie-breaking weight.}
\label{tab:kind-mapping}
\end{table}
A naming caution: three field names read as higher-is-better words ---
\begin{center}
\texttt{page\_fill\_efficiency},\ \texttt{casting\_off\_quality},\ \texttt{symbol\_density\_uniformity}
\end{center}
--- but they are not. The core specification fixes the orientation of
\emph{every} normative metric ($0.0$ best, $1.0$ worst tolerable), and
the definitions in Chapter~\ref{ch:metrics} follow it: each of the three
measures a \emph{deficiency} (unfilled page area, uneven casting-off,
uneven density).
\section{The Measurement Domain}
\label{sec:model:domain}
Every raw measurement in Chapter~\ref{ch:metrics} is a deterministic
function of three inputs, all of which exist at the moment the solver
assembles its \texttt{SolveReport}:
\begin{enumerate}
\item the solve's resolved output $L$ (a \texttt{ResolvedLayoutIR}:
positioned glyphs with bounding boxes, strokes, and the page/system
tree);
\item the solve's constrained input $C$ (a \texttt{ConstrainedLayoutIR}:
horizontal spring slots, vertical bands, declared constraints);
\item the declared page geometry the solve was configured with: the
content width $W$ and content height $H$, in staff spaces. (Schema
major~1 defines \texttt{Canvas.layout\_defaults} and its type
\texttt{CanvasLayoutDefaults}, P12-I7; the reference implementation's
code graph home lands in a later phase, so until then the geometry is a
solver parameter, and the Reference Suite companion requires each suite
entry to declare it.)
\end{enumerate}
Notation used throughout Chapter~\ref{ch:metrics}:
\begin{itemize}
\item $G$ is the set of resolved glyphs of $L$. For $g \in G$, the
\emph{ink box} $B(g) = [l_g, r_g] \times [b_g, t_g]$ is the glyph's
bounding box translated to its resolved position. Strokes (staff
lines, ledger lines, stems, barline strokes) are not members of $G$.
\item $\mathit{sys}(g)$ is the system that positioned $g$ under the
solve's casting-off; every system belongs to exactly one region, and
every page carries an ordered list of systems. A glyph positioned by
no system belongs to no collision pair and to no per-system
aggregate.
\item $\mathit{slot}(g)$ is the horizontal spring slot of $g$'s source
glyph in $C$ --- the musical time column that groups a chord's
noteheads with their accidentals, dots, and same-column symbols.
\item For a system $s$: its \emph{columns} are the ascending sequence of
distinct resolved baseline $x$-coordinates
$x^s_1 < \dots < x^s_{m_s}$ of the glyph-bearing slots realized in
$s$; its \emph{advances} are $a^s_i = x^s_{i+1} - x^s_i$ for
$i = 1, \dots, m_s - 1$ (equivalently, the spacing pass's per-slot
advances); $w_s$ is the width of $s$'s content extent (the horizontal
span of the ink boxes assigned to $s$); $n_s$ is the number of glyphs
assigned to $s$.
\item $\mathrm{CV}(v_1, \dots, v_k)$, defined for $k \ge 2$ with
$\operatorname{mean} > 0$, is the population standard deviation
divided by the arithmetic mean.
\item The arithmetic mean over an \emph{empty} index set is defined as
$0$ (this is the vacuous-geometry rule of
Section~\ref{sec:model:vacuous} in aggregate form).
\end{itemize}
Because numeric agreement across implementations is not required
(Requirement~\ref{req:qmc:determinism}), a formula may reference the
solve's \emph{own} internal assignments --- which glyph landed in which
system, which columns a system realizes --- without threatening
conformance: the assignments are deterministic within an implementation
version, which is all the metric contract needs. No formula in this
catalog requires an optical-spacing model, font metrics beyond glyph
bounding boxes, or any geometry class the layout pipeline does not
produce.
\section{The Vacuous-Geometry Rule}
\label{sec:model:vacuous}
Each axis in Chapter~\ref{ch:metrics} names its \emph{contributing units}:
the glyph pairs, systems, pages, gaps, slurs, or beams the raw measurement
ranges over. A layout may simply not contain a metric's geometry class ---
no drawn slurs, no beams, a single system, a single page.
\begin{requirement}
\label{req:qmc:vacuous}
When a normative metric's contributing-unit set is empty for a given
layout, the metric \MUST{} evaluate to exactly $0.0$: where there is
nothing to penalize, the penalty is zero. In particular:
\begin{itemize}
\item a layout containing no drawn slur geometry has
$\texttt{slur\_shape\_penalty} = 0.0$;
\item a layout containing no drawn beam geometry has
$\texttt{beam\_slope\_penalty} = 0.0$;
\item a region cast onto a single system contributes no units to
\texttt{system\_break\_penalty}, \texttt{casting\_off\_quality}, or
\texttt{symbol\_density\_uniformity}, and a single-page layout
contributes no units to \texttt{page\_fill\_efficiency} --- each axis
degenerates exactly as its per-axis definition states;
\item a solve configured without positive finite content bounds ($W$ or
$H$) has an empty contributing set for every axis defined over that
bound.
\end{itemize}
An implementation \MUSTNOT{} report a sentinel (such as $1.0$) for a
metric whose contributing-unit set is empty. The all-worst placeholder
vector remains correct only for a solver that \emph{computes no metrics at
all} and claims no conformance tier (the core's \texttt{Stub} tier).
\end{requirement}
\begin{openquestion}
\textbf{The notated-but-unrendered honesty edge.} A score whose
\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}
\label{sec:model:normalization}
Every normative axis uses the same one-parameter normalization shape, so
that anchors --- not curve families --- are the entire tuning surface.
\begin{requirement}
\label{req:qmc:normalization-form}
Each normative metric defines a raw measurement
$\mathit{raw} \ge 0$ (dimensionless, per its axis definition) and a pinned
anchor constant $R_{\mathrm{worst}} > 0$. The normalized value is the
clamped-linear map
\[
n \;=\; \min\!\left(1,\; \frac{\mathit{raw}}{R_{\mathrm{worst}}}\right),
\]
so that $\mathit{raw} = 0$ (the ideal) normalizes to $0.0$ and
$\mathit{raw} \ge R_{\mathrm{worst}}$ (the worst-tolerable anchor and
beyond) normalizes to $1.0$. Implementations \MUST{} use the per-axis raw
measurements and anchors of Chapter~\ref{ch:metrics} exactly; per the core
specification, arbitrary normalization is non-conforming. Extension
metrics \MAY{} use other normalization shapes but \MUSTNOT{} change
orientation or range.
\end{requirement}
% ===========================================================================
\chapter{The Nine Normative Metrics}
\label{ch:metrics}
Each section below defines one axis under a fixed template: the
\emph{phenomenon} (what an engraver would point at), the \emph{contributing
units} (what the raw measurement ranges over --- the set whose emptiness
triggers Requirement~\ref{req:qmc:vacuous}), the \emph{raw measurement},
and the \emph{normalization anchor} with a brief justification. All
lengths are in staff spaces; all raw measurements are dimensionless
ratios.
Four axes measure horizontal-distribution phenomena at different
granularities, and the boundaries are deliberate:
\begin{itemize}
\item \texttt{spacing\_distortion} is \emph{within-system} advance
regularity;
\item \texttt{system\_break\_penalty} is the \emph{per-break} absolute
cost of each chosen system break (looseness or overflow of
non-final systems);
\item \texttt{casting\_off\_quality} is \emph{across-system} width
evenness, including the final system (the stub-last-line failure);
\item \texttt{symbol\_density\_uniformity} is \emph{across-system}
crowding evenness (equal widths can hide very different symbol
densities).
\end{itemize}
\section{\texttt{collision\_penalty}}
\label{sec:metrics:collision}
\textbf{Phenomenon.} Overlapping ink between symbols that belong to
different musical time columns: a notehead striking the previous column's
accidental, a chord symbol over a barline, any cross-column ink contact.
Professional engraving contains none.
\begin{requirement}
\label{req:qmc:collision}
\textbf{Contributing units:} unordered glyph pairs $\{g, h\} \subseteq G$
with $\mathit{sys}(g) = \mathit{sys}(h)$ and
$\mathit{slot}(g) \ne \mathit{slot}(h)$.
A pair \emph{collides} when its ink boxes intersect with positive area in
both axes:
\[
\begin{gathered}
\min(r_g, r_h) - \max(l_g, l_h) > 0
\quad\text{and}\\
\min(t_g, t_h) - \max(b_g, b_h) > 0 .
\end{gathered}
\]
Edge-touching boxes do not collide. Pairs sharing a horizontal spring slot
are \textbf{excluded}: a column's internal cluster --- a chord's noteheads,
their accidentals, dots, and other same-slot symbols --- is arranged by the
constrained stage, and its legitimate internal ink contact is not a
spacing failure of the solver. Strokes are not glyphs and join no pair:
staff lines legitimately cross every notehead.
\textbf{Raw measurement:} with $P$ the set of colliding pairs,
\[
\mathit{raw} \;=\; \frac{|P|}{|G|}
\qquad (\mathit{raw} = 0 \text{ when } G = \emptyset).
\]
\textbf{Normalization:} $R_{\mathrm{worst}} = 0.05$;
$n = \min(1, \mathit{raw} / 0.05)$.
\end{requirement}
\begin{rationale}
The anchor says: one cross-column collision per twenty glyphs is
unmistakably broken layout --- the worst a report should be able to
distinguish. The count is divided by the glyph population, not by the pair
population, so that the measure does not vanish quadratically on large
scores: a score with one collision per page stays visible. The reference
pipeline evaluates overlap today only for \emph{declared}
\texttt{NoCollision} constraints; this axis is the full pairwise
same-system sweep over ink boxes, which is new but cheap work over data
the resolved layout already carries.
\end{rationale}
\section{\texttt{spacing\_distortion}}
\label{sec:metrics:spacing}
\textbf{Phenomenon.} Uneven horizontal distribution within a system: the
\emph{rhythmic} columns --- those carrying notes and rests --- bunched
together here and stretched apart there, where the underlying spring model
asked for near-uniform advances.
\begin{requirement}
\label{req:qmc:spacing}
\textbf{Rhythmic columns.} A \emph{rhythmic column} of a system is a
horizontal spring slot at least one of whose glyphs is a notehead or a
rest. The clef, key-signature, and time-signature lead and the barlines are
\textbf{not} rhythmic columns: their horizontal extent is notational
furniture, fixed by their content rather than by rhythm.
\textbf{Contributing units:} systems $s$ with at least three rhythmic
columns (so at least two rhythmic advances).
\textbf{Raw measurement:} let $x^s_1 < \dots < x^s_{k_s}$ be the reference
x-positions of the system's $k_s$ rhythmic columns in order, and
$a^s_i = x^s_{i+1} - x^s_i$ the advance between consecutive rhythmic columns
(a note-to-note advance spans any barline or furniture that falls between
the two, so barlines are transparent, not breaks in the sequence). Then
$\mathit{raw}_s = \mathrm{CV}(a^s_1, \dots, a^s_{k_s - 1})$, and the axis
raw value is the arithmetic mean of $\mathit{raw}_s$ over contributing
units.
\textbf{Normalization:} $R_{\mathrm{worst}} = 1.0$;
$n = \min(1, \mathit{raw})$.
\end{requirement}
\begin{rationale}
A coefficient of variation of $1.0$ means the typical advance deviates from
the mean by the whole mean --- spacing with no discernible regularity. v0.2
defines \emph{geometric} regularity over the \emph{rhythmic} columns
deliberately: the reference spring model's preferred widths are uniform, so
regular note/rest advances are exactly what its ideal output looks like,
and the collision minima (accidental overhangs, wide columns) that
legitimately perturb those advances are modest on realistic scores. The
axis is scoped to rhythmic columns because a leading clef, key signature,
or time signature is furniture whose width the spring model does not govern:
folding the wide clef-to-first-note gap into the CV would flag a
perfectly-spaced short line as distorted purely for carrying a clef ---
measuring furniture, not spacing.
\end{rationale}
\begin{openquestion}
\textbf{Optical spacing at the Standard tier.} Mature engraving spaces
rhythmic columns proportionally to musical duration (with an optical
correction), not uniformly; under a duration-proportional model, this
axis's ideal would be ``advances proportional to the column's duration
share,'' and a perfectly optically-spaced line would score \emph{worse}
than a uniform one under the v0.2 definition. When the layout pipeline
gains duration-aware preferred widths, should the Standard tier redefine
$\mathit{raw}_s$ as deviation from the duration-proportional ideal while
Minimal keeps geometric regularity? v0.2 scopes the geometric definition to
rhythmic columns (removing the leading-furniture false positive on short
scores) but still measures geometric, not duration-proportional, regularity.
\end{openquestion}
\section{\texttt{slur\_shape\_penalty}}
\label{sec:metrics:slur}
\textbf{Phenomenon.} Badly-shaped slur arcs: flat, tape-like slurs or
bulging semicircles, measured against the shallow-arc norm of engraving
practice.
\begin{requirement}
\label{req:qmc:slur}
\textbf{Contributing units:} drawn slurs in $L$ with chord length
$c > 0$, where the \emph{chord} is the segment between the \emph{whole}
slur's endpoints and the \emph{apex height} $h \ge 0$ is the maximum
perpendicular distance from the curve to its chord. The unit is the whole
slur, not a per-system fragment: a slur that a casting-off pass splits
across a system break is measured once, as the arc it was shaped to be, so
a well-shaped slur that happens to break is not spuriously penalized (its
fragments' diagonal chords each read flatter than the whole).
\textbf{Raw measurement:} per unit, with arc ratio $\rho = h / c$,
\[
\mathit{raw}_u \;=\; \max\bigl(0,\;\; 0.08 - \rho,\;\; \rho - 0.25\bigr),
\]
i.e.\ the shortfall below the ideal band $[0.08, 0.25]$ or the excess
above it; the axis raw value is the arithmetic mean over contributing
units.
\textbf{Normalization:} $R_{\mathrm{worst}} = 0.25$;
$n = \min(1, \mathit{raw} / 0.25)$.
\end{requirement}
\begin{rationale}
The band $[0.08, 0.25]$ brackets the shallow arcs engraving practice
prefers: an arc rising less than about $1/12$ of its span reads as a
straight line; one rising more than a quarter of its span begins to bulge.
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 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}}
\label{sec:metrics:beam}
\textbf{Phenomenon.} Over-steep beams. Engraving practice keeps beam
slants gentle regardless of the melodic interval they span.
\begin{requirement}
\label{req:qmc:beam}
\textbf{Contributing units:} drawn beam segments in $L$ with horizontal
run $\Delta x > 0$ (endpoint-to-endpoint).
\textbf{Raw measurement:} per unit, with absolute slope
$\sigma = |\Delta y| / \Delta x$,
\[
\mathit{raw}_u \;=\; \max\bigl(0,\; \sigma - 0.25\bigr);
\]
the axis raw value is the arithmetic mean over contributing units.
\textbf{Normalization:} $R_{\mathrm{worst}} = 0.25$;
$n = \min(1, \mathit{raw} / 0.25)$.
\end{requirement}
\begin{rationale}
Slopes up to $0.25$ (about $14^\circ$) are penalty-free --- within the
range engraving manuals tolerate for short, wide-interval beams --- and the
anchor places $\sigma = 0.5$ (about $27^\circ$, roughly double any
published maximum) at worst-tolerable. Like the slur axis, this is pinned
ahead of implementation: the v0.1 reference pipeline draws no beam
geometry, so the axis evaluates to $0.0$ under the vacuous-geometry rule.
\end{rationale}
\section{\texttt{vertical\_density\_penalty}}
\label{sec:metrics:vertical}
\textbf{Phenomenon.} Vertical crowding or sprawl: inter-staff and
inter-system gaps realized far from the spacing the band model asked for.
\begin{requirement}
\label{req:qmc:vertical}
\textbf{Contributing units:} each \emph{realization} in $L$ of a vertical
band of $C$ of kind \texttt{InterStaffGap} or \texttt{InterSystemGap} with
preferred height $p > 0$ (a band is realized wherever the adjacent content
it separates was laid out). A band realized in several systems contributes
\textbf{one unit per system}, not one per band: a vertical solve sizes each
system's gaps from that system's own content, so one band's realized height
genuinely differs from system to system. This matches how the realized
inter-system gaps are already counted --- one unit per adjacent system pair
on a page.
\textbf{Raw measurement:} per unit, with $r \ge 0$ the realized vertical
separation between the adjacent content extents the band separates
(measured in resolved coordinates),
\[
\mathit{raw}_u \;=\; \frac{|r - p|}{p};
\]
the axis raw value is the arithmetic mean over contributing units.
\textbf{Content extent} means \emph{every} primitive the adjacent band
owns --- glyphs, strokes, and curves alike, each attributed by its declared
\texttt{vertical\_band} (core spec
\sectionsc{ConstrainedLayoutIR}, primitive band ownership) --- and not the
band's glyph \texttt{members} alone. A staff's outermost ink is usually not
a glyph: ledger lines, stems, and slurs reach past every notehead. A solver
separates staves until their content clears the gap, so scoring it against
its noteheads alone would charge it for the very ink it made room for.
\textbf{Normalization:} $R_{\mathrm{worst}} = 1.0$;
$n = \min(1, \mathit{raw})$.
\end{requirement}
\begin{rationale}
A gap off by its own preferred size --- staves twice as far apart as asked,
or fully collapsed --- is unambiguous vertical failure; proportional
deviation makes one anchor serve both tight inter-staff gaps and wide
inter-system gaps.
The v0.1 reference pipeline preserved constrained $y$ verbatim, so realized
gaps equalled preferred gaps wherever bands were realized and the axis
reported its honest near-zero. The vertical spring solve has since landed
(inter-staff gap renegotiation and inter-system vertical justification), and
the axis now measures what it was defined to measure. The
\textbf{content extent} clarification above is the lesson from that landing:
the reference implementation read ``content extents'' as the band's glyph
\texttt{members}, because until primitive band ownership was ratified a band
listed no strokes or curves to own. A correctly separated two-staff system
then scored a saturated $1.0$ and tripped the \textsc{Standard} floor
warning --- the metric charging the solver for the ledger and slur ink it had
correctly cleared. The formula, units, anchor, and normalization are
unchanged; only a non-conforming measurement was.
The inter-system half of the axis is a genuine trade-off, not a defect: the
vertical justification pass deliberately stretches inter-system gaps past
preferred to fill a non-final page, trading this axis against
\texttt{page\_fill\_efficiency}. Both axes are reported; neither is wrong.
\textbf{Per-realization units} (0.3.0) followed from the same landing. While
the reference pipeline preserved constrained $y$ verbatim, a band had exactly
one realized height and the distinction was moot. Once the inter-staff solve
began sizing each system's gaps from that system's own content, a band's
realized height became per-system, and counting one unit per band would let a
well-solved system average away a badly spaced one. The axis is deliberately
symmetric: a gap wider than preferred is sprawl exactly as a narrower one is
crowding. A solver that only ever \emph{expands} a fixed stacking --- never
compressing an over-wide gap back toward preferred --- will therefore report
honest sprawl on its slack systems. That is the axis working, not
mis-measuring, and it is how the reference implementation's expand-only solve
was found: it now renegotiates in both directions.
Where a solver realizes each band's declared height exactly, the inter-staff
half of this axis reads its honest zero and serves as a \emph{self-check} on the
solve rather than a judgement on the score. A conforming implementation should
therefore measure the realized separation back from the geometry it produced,
not from the target it aimed at: the two agree only if the solve and the bake
both did what they claimed. The reference implementation reads it back from the
baked output, and that is how a defect in its multi-staff cascade --- one that
over-separated every pair below the first --- was caught.
\end{rationale}
\section{\texttt{system\_break\_penalty}}
\label{sec:metrics:system-break}
\textbf{Phenomenon.} Bad break choices, one system at a time: a non-final
system left loose (broken far short of the available width) or overfull
(content past the content width).
\begin{requirement}
\label{req:qmc:system-break}
\textbf{Contributing units:} non-final systems --- for each region, every
system the casting-off produced except the region's last --- defined only
when the declared content width $W$ is finite and positive.
\textbf{Raw measurement:} per unit,
\[
\mathit{raw}_s \;=\; \frac{|W - w_s|}{W},
\]
penalizing looseness ($w_s < W$) and overflow ($w_s > W$) alike; the axis
raw value is the arithmetic mean over contributing units.
\textbf{Normalization:} $R_{\mathrm{worst}} = 0.5$;
$n = \min(1, \mathit{raw} / 0.5)$.
A region cast onto a single system contributes no units (the break axis
degenerates to nothing-to-penalize, per
Requirement~\ref{req:qmc:vacuous}); the final system of each region is
never a unit, because a short last line is not a break failure.
\end{requirement}
\begin{rationale}
Non-final systems half-empty on average --- or overflowing by half the
content width --- mark casting-off that has effectively failed, hence the
$0.5$ anchor. The raw quantities are exactly what the reference
casting-off pass already computes: per-system content extents against the
declared content width, with breaks chosen among barline candidates.
\end{rationale}
\section{\texttt{page\_fill\_efficiency}}
\label{sec:metrics:page-fill}
\textbf{Phenomenon.} Underfilled non-final pages: vertical white space a
better page-break policy would have used. Despite the field's name, the
metric follows the fixed orientation --- it measures \emph{unfilled}
fraction, so $0.0$ is best.
\begin{requirement}
\label{req:qmc:page-fill}
\textbf{Contributing units:} non-final pages of $L$, defined only when
the declared content height $H$ is finite and positive.
\textbf{Raw measurement:} per unit, with $\mathit{span}_p$ the vertical
extent of page $p$'s content (from the top of its first system's content
extent to the bottom of its last system's content extent) and fill
fraction $f_p = \min(1, \mathit{span}_p / H)$,
\[
\mathit{raw}_p \;=\; 1 - f_p;
\]
the axis raw value is the arithmetic mean over contributing units.
\textbf{Normalization:} $R_{\mathrm{worst}} = 0.75$;
$n = \min(1, \mathit{raw} / 0.75)$.
A single-page layout contributes no units; the final page is never a
unit, because a short last page is not a fill failure.
\end{requirement}
\begin{rationale}
A non-final page three-quarters empty is a page break with no plausible
justification --- worst-tolerable. The span-based fill fraction is
computable directly from the casting-off pass's vertical cursor walk and
per-system extents, and clamping $f_p$ at $1$ keeps slight margin
overshoot from producing a negative raw value.
\end{rationale}
\section{\texttt{casting\_off\_quality}}
\label{sec:metrics:casting-off}
\textbf{Phenomenon.} Uneven casting-off across a region's systems taken as
a whole: some lines full, others sparse --- including the classic failure
this axis exists to catch, a stub final system carrying one straggling
measure. Despite the field's name, $0.0$ is best.
\begin{requirement}
\label{req:qmc:casting-off}
\textbf{Contributing units:} regions whose casting-off produced at least
two systems, each with content-extent width $w_s > 0$.
\textbf{Raw measurement:} per unit region $R$,
\[
\mathit{raw}_R \;=\; \mathrm{CV}\bigl(\, w_s : s \in \mathrm{systems}(R) \,\bigr),
\]
over \emph{all} of the region's systems, the final system included; the
axis raw value is the arithmetic mean over contributing units.
\textbf{Normalization:} $R_{\mathrm{worst}} = 0.5$;
$n = \min(1, \mathit{raw} / 0.5)$.
A single-system region contributes no units.
\end{requirement}
\begin{rationale}
Including the final system is the deliberate difference from
\texttt{system\_break\_penalty} (which exempts it): a lone stub last line
drags the width spread up and is penalized \emph{here}, as a global
casting-off failure rather than a per-break one. The anchor: per-system
widths whose standard deviation is half their mean describe a page where
line lengths visibly disagree.
\end{rationale}
\section{\texttt{symbol\_density\_uniformity}}
\label{sec:metrics:symbol-density}
\textbf{Phenomenon.} Uneven crowding across systems: one line crammed with
symbols, the next sparse --- even when the lines' widths agree. Despite the
field's name, $0.0$ is best.
\begin{requirement}
\label{req:qmc:symbol-density}
\textbf{Contributing units:} regions whose casting-off produced at least
two systems with $w_s > 0$.
\textbf{Raw measurement:} per unit region $R$, with per-system symbol
density $\rho_s = n_s / w_s$ (glyphs per staff space of content width),
\[
\mathit{raw}_R \;=\; \mathrm{CV}\bigl(\, \rho_s : s \in \mathrm{systems}(R),\ w_s > 0 \,\bigr);
\]
the axis raw value is the arithmetic mean over contributing units.
\textbf{Normalization:} $R_{\mathrm{worst}} = 0.5$;
$n = \min(1, \mathit{raw} / 0.5)$.
A single-system region contributes no units.
\end{requirement}
\begin{rationale}
Width evenness (\texttt{casting\_off\_quality}) and density evenness are
independent failures: equal-width systems can still alternate between
sixteenth-note walls and whole-note deserts when break choices ignore
content weight. Density varying by half its mean across systems reads as
visibly uneven engraving, hence the shared $0.5$ anchor.
\end{rationale}
% ===========================================================================
\chapter{Default Tie-Breaking Weights}
\label{ch:weights}
The core specification requires normative default
\texttt{TieBreakingWeights}: they select among Pareto-equivalent layouts,
deterministically, and are ``the basis for reference-suite conformance.''
\begin{requirement}
\label{req:qmc:weights}
The normative default tie-breaking weights are $1.0$ for every one of the
nine fields of \texttt{TieBreakingWeights}:
\begin{center}
\small
\begin{tabular}{lc@{\hspace{2.5em}}lc}
\toprule
\textbf{Weight} & \textbf{Default} & \textbf{Weight} & \textbf{Default} \\
\midrule
\texttt{collision} & \tablenums{1.0} & \texttt{system\_break} & \tablenums{1.0} \\
\texttt{spacing} & \tablenums{1.0} & \texttt{page\_fill} & \tablenums{1.0} \\
\texttt{slur\_shape} & \tablenums{1.0} & \texttt{casting\_off} & \tablenums{1.0} \\
\texttt{beam\_slope} & \tablenums{1.0} & \texttt{symbol\_density} & \tablenums{1.0} \\
\texttt{vertical\_density} & \tablenums{1.0} & & \\
\bottomrule
\end{tabular}
\end{center}
Implementations \MAY{} let users customize weights, per the core
specification; conformance evaluation on the reference suite uses these
defaults.
\end{requirement}
\begin{rationale}
No aesthetic priority ordering among the nine axes has been ratified, and
inventing one ahead of measurement experience would encode a preference no
evidence supports. Uniform weights are the honest neutral default --- they
make tie-breaking deterministic (the core's actual requirement) without
pretending to a house style. They also bless the reference
implementation's existing \texttt{Default} for \texttt{TieBreakingWeights}
(every field $1.0$). Revisions of this catalog are expected to tune the
defaults once reference-suite experience shows which axes dominate
perceived quality.
\end{rationale}
% ===========================================================================
\chapter{Per-Tier Metric Thresholds}
\label{ch:thresholds}
\section{The Default Threshold Table}
\label{sec:thresholds:table}
A tier's threshold for an axis is the maximum permitted
\texttt{NormalizedMetric} value on a reference-suite entry evaluated at
that tier. The core specification fixes the relationship: Minimal-tier
thresholds are relaxed relative to Standard; the Standard tier corresponds
to professional engraving quality.
\begin{table}[h]
\centering
\small
\begin{tabular}{lcc}
\toprule
\textbf{Axis} & \textbf{Minimal (max)} & \textbf{Standard (max)} \\
\midrule
\texttt{collision\_penalty} & \tablenums{0.90} & \tablenums{0.25} \\
\texttt{spacing\_distortion} & \tablenums{0.90} & \tablenums{0.40} \\
\texttt{slur\_shape\_penalty} & \tablenums{0.90} & \tablenums{0.30} \\
\texttt{beam\_slope\_penalty} & \tablenums{0.90} & \tablenums{0.30} \\
\texttt{vertical\_density\_penalty} & \tablenums{0.90} & \tablenums{0.40} \\
\texttt{system\_break\_penalty} & \tablenums{0.90} & \tablenums{0.35} \\
\texttt{page\_fill\_efficiency} & \tablenums{0.90} & \tablenums{0.40} \\
\texttt{casting\_off\_quality} & \tablenums{0.90} & \tablenums{0.35} \\
\texttt{symbol\_density\_uniformity} & \tablenums{0.90} & \tablenums{0.40} \\
\bottomrule
\end{tabular}
\caption{Default per-tier maximum \texttt{NormalizedMetric} values.
Minimal is uniformly more permissive than Standard on every axis.}
\label{tab:tier-thresholds}
\end{table}
\begin{requirement}
\label{req:qmc:thresholds}
The default per-tier thresholds are given by
Table~\ref{tab:tier-thresholds}. A solver claiming a tier \MUST{} keep
every normative metric at or below the tier's threshold on every
reference-suite entry required at that tier, per the core specification's
suite-conformance conditions. The Reference Suite companion \MAY{}
override these defaults for individual entries; absent an override, the
values of Table~\ref{tab:tier-thresholds} govern.
\end{requirement}
\begin{rationale}
\textbf{Minimal = 0.90 everywhere: relaxed but non-vacuous.} A Minimal
solver may be aesthetically mediocre --- the core says so --- but it must
not be \emph{pathological}, and its metric vectors must be accurate. A
uniform $0.90$ admits every honestly-mediocre layout while excluding two
things: layouts at an axis's worst-tolerable anchor, and the all-worst
placeholder vector of a solver that computes nothing. That second
exclusion is deliberate --- a solver reporting the unmeasured $1.0$
placeholder cannot pass the Minimal suite, which is exactly the
honest-tier discipline: measuring is part of the Minimal claim.
\textbf{Standard = 0.25--0.40 per axis: professional quality.} Collisions
get the tightest bound ($0.25$: at most one cross-column collision per
eighty glyphs) because they are the most jarring single defect. The
break-family axes ($0.35$) sit slightly tighter than the distribution and
vertical axes ($0.40$), whose v0.1 definitions are coarser proxies
(geometric spacing regularity; a not-yet-solved vertical dimension). Slurs
and beams ($0.30$) allow modest shape deviation across a piece. All values
are round v0.1 defaults chosen to be defensible, not optimal; the tuning
open question below owns their evolution.
\end{rationale}
\section{The Advanced Tier}
\label{sec:thresholds:advanced}
\begin{requirement}
\label{req:qmc:advanced}
The Advanced tier imposes the Standard-tier thresholds of
Table~\ref{tab:tier-thresholds} on the nine normative axes, \emph{plus}
per-extension thresholds on extension metrics: a registered extension
whose layout requirements are part of the Advanced reference suite
\MUST{} declare, in its extension declaration, a maximum
\texttt{NormalizedMetric} value for each extension metric it contributes,
and an Advanced-tier solver \MUST{} meet each declared threshold on every
Advanced suite entry that exercises that extension. An extension metric
with no declared threshold imposes no Advanced-tier obligation.
\end{requirement}
\section{The \texttt{QualityFloorApproached} Warning}
\label{sec:thresholds:floor}
The core specification gives \texttt{SolverWarningKind} a
\texttt{QualityFloorApproached} variant carrying a
\texttt{QualityMetricKind} payload, without defining its trigger. This
catalog pins it.
\begin{requirement}
\label{req:qmc:floor-warning}
A solver \SHOULD{} emit a \texttt{QualityFloorApproached} warning for
metric kind $k$ when the computed value of $k$'s axis exceeds
$\mathbf{0.8}$ times the applicable threshold for that axis. The
applicable threshold is the one selected by the solve's
\texttt{SolverProfile} (Chapter~\ref{ch:profiles});
the warning fraction is pinned at $0.8$ exactly. The warning is
diagnostic: emitting it does not change the solve's status, and a value
\emph{over} the threshold still warns (it exceeds $0.8$ of it a
fortiori) --- threshold \emph{enforcement} exists only in reference-suite
evaluation, not in ordinary solves.
\end{requirement}
\section{Standard-Tier Constraint Families}
\label{sec:thresholds:families}
The core specification's Standard-tier requirement obliges a Standard
solver to ``support every Standard-tier constraint family declared in the
Quality Metric Catalog.'' This section is that declaration.
\begin{requirement}
\label{req:qmc:standard-families}
The Standard-tier constraint families are the core specification's
built-in layout-constraint surface (Chapter~7,
\sectionsc{ConstrainedLayoutIR}):
\begin{itemize}
\item the \textbf{spring families}: horizontal spring slots and vertical
bands, with their min/preferred/max and stretch/compress parameters;
\item the five built-in \texttt{LayoutConstraint} kinds:
\texttt{NoCollision}, \texttt{Align}, \texttt{PositionWithin},
\texttt{SystemBreakAt}, and \texttt{PageBreakAt} (both
\texttt{Hard} and \texttt{Soft} break kinds).
\end{itemize}
These same families constitute ``the standard constraint families'' of
the core's Minimal-tier requirement: Minimal and Standard support the
same family set and differ in metric thresholds and incremental-solving
obligations, not in constraint vocabulary.
\texttt{LayoutConstraint::Registered} (extension-contributed) families
are per-extension obligations of the Advanced tier only.
\end{requirement}
\begin{openquestion}
\textbf{Threshold tuning.} Every number in
Table~\ref{tab:tier-thresholds} and every anchor constant in
Chapter~\ref{ch:metrics} is a v0.1 default pinned ahead of measurement
experience: no implementation has yet reported real vectors across the
reference suite. Once the reference implementation computes real metrics
on the v0.1 entry set, are the Standard columns achievable-but-meaningful
(neither trivially passed nor unreachable), and do any anchors need
rescaling? Threshold and anchor revisions are \textsc{minor} versions of
this catalog and are expected.
\end{openquestion}
% ===========================================================================
\chapter{The Registered Profile Catalog}
\label{ch:profiles}
The core specification's vocabulary appendix defines
\texttt{SolverProfile} as a registered profile identifier that ``selects
the solver's hard-constraint set, normalized-metric thresholds,
tie-breaking weights, and active extension catalog,'' and defers the
registry to this companion.
\begin{requirement}
\label{req:qmc:profiles}
The registered \texttt{SolverProfile} catalog is exactly three profiles:
\texttt{Draft}, \texttt{Standard}, and \texttt{Publication}. Their
selections:
\begin{center}
\small
\begin{tabular}{lllll}
\toprule
\textbf{Profile} & \textbf{Constraint families} & \textbf{Threshold column} &
\textbf{Weights} & \textbf{Extensions} \\
\midrule
\texttt{Draft} & Standard-tier set & Minimal
& defaults & none required \\
\texttt{Standard} & Standard-tier set & Standard
& defaults & none required \\
\texttt{Publication} & Standard-tier set & Standard
& defaults & none required \\
\bottomrule
\end{tabular}
\end{center}
\begin{itemize}
\item \emph{Constraint families}: all three profiles activate the
Standard-tier constraint families of
Requirement~\ref{req:qmc:standard-families}; hard constraints are
never traded away by any profile (the core's
hard-constraints-are-inviolable rule).
\item \emph{Threshold column}: the column of
Table~\ref{tab:tier-thresholds} the profile selects --- the thresholds
against which Requirement~\ref{req:qmc:floor-warning}'s warning
fraction is evaluated during ordinary solves. \texttt{Draft} selects
the Minimal column (few warnings, fast iteration);
\texttt{Standard} and \texttt{Publication} select the Standard
column. As of v0.2 no column tighter than Standard is ratified;
\texttt{Publication} is registered now so that documents and
configurations can name it, and a future revision \MAY{} give it a
tighter column without a schema change.
\item \emph{Weights}: all three profiles use the default tie-breaking
weights of Requirement~\ref{req:qmc:weights}.
\item \emph{Extensions}: no profile requires an active extension
catalog; extensions activate by document declaration, not by
profile.
\end{itemize}
\texttt{Standard} is the default profile.
\end{requirement}
\begin{rationale}
\textbf{Profiles are configuration; tiers are claims.} A
\texttt{SolverProfile} is a runtime input (\texttt{SolverConfig.profile})
that any solver may be asked to run under; a conformance tier is a claim
about the solver evaluated on the reference suite. The two meet in
exactly one place: the profile's threshold column determines which
thresholds the solver's own \texttt{QualityFloorApproached} diagnostics
reference during ordinary solves. Suite evaluation at a claimed tier
always uses that \emph{tier's} column, whatever profile the solver runs
under day to day. The three-profile registry matches the reference
implementation's existing \texttt{SolverProfile} enum
(\texttt{Draft} / \texttt{Standard} / \texttt{Publication}, default
\texttt{Standard}) so that registration blesses shipped reality rather
than inventing a parallel one.
\end{rationale}
% ===========================================================================
\chapter{Revision History}
\label{ch:history}
\begin{longtable}{p{2cm} p{2.5cm} p{9cm}}
\toprule
\textbf{Date} & \textbf{Section} & \textbf{Change} \\
\midrule
\endhead
\today & All & 0.1.0 --- Initial companion: pins the diagnostic-only
status of quality metrics, within-implementation determinism without
cross-implementation numeric agreement, the \texttt{QualityMetricKind}
enumeration, the measurement domain, and the vacuous-geometry rule;
defines all nine normative axes (phenomenon, raw measurement over
resolved geometry, clamped-linear normalization with pinned anchors);
sets the default tie-breaking weights (all $1.0$); establishes the
Minimal/Standard threshold table, the Advanced extension rule, the
\texttt{QualityFloorApproached} trigger ($0.8\times$ threshold), and
the Standard-tier constraint family declaration; registers the
\texttt{Draft}/\texttt{Standard}/\texttt{Publication} profile catalog.
Open questions: the notated-but-unrendered honesty edge, optical
spacing at the Standard tier, threshold tuning pending reference-suite
experience. \\
\today & \hyperref[sec:metrics:spacing]{\texttt{spacing\_distortion}}
& 0.2.0 --- Scope the \texttt{spacing\_distortion} raw measurement to the
system's \emph{rhythmic} columns (slots bearing a notehead or rest),
excluding the clef / key-signature / time-signature lead and treating
barlines transparently (a note-to-note advance spans them). Resolves the
reference-suite false positive in which a short healthy line's wide
clef-to-first-note gap inflated the CV above the Standard warning floor
(measured 0.36--0.41 on the three- to eight-column entries $\to$
0.08--0.22, below the floor) without weakening the axis on real spacing
irregularity. Normalization anchor, orientation, range, thresholds, and
the eight other axes are unchanged; the optical-spacing open question
(duration-proportional spacing) stays open. Batch item P12-I12. \\
\midrule
\today & \hyperref[sec:metrics:vertical]{\texttt{vertical\_density\_penalty}}
& 0.3.0 --- Count \textbf{one contributing unit per realization} of an
\texttt{InterStaffGap} band rather than one per band, matching how realized
inter-system gaps were already counted. The inter-staff vertical solve sizes
each system's gaps from that system's own content, so a band's realized
height is per-system; one unit per band let a well-solved system average away
a badly spaced one. Also \emph{clarifies} (no semantic change) that the
``content extents'' the raw measurement compares are every primitive the
adjacent band owns --- glyphs, strokes, and curves, each attributed by its
declared \texttt{vertical\_band} --- and not the band's glyph
\texttt{members}, a reading that was arguably unimplementable before
primitive band ownership was ratified. Raw formula, normalization anchor,
orientation, range, thresholds, and the eight other axes are unchanged. The
reference implementation's non-conforming glyph-only measurement is fixed
alongside. \\
\bottomrule
\end{longtable}
\end{document}