diff --git a/spec/binary_format.pdf b/spec/binary_format.pdf index 7fa6837..4dcdc3f 100644 Binary files a/spec/binary_format.pdf and b/spec/binary_format.pdf differ diff --git a/spec/binary_format.tex b/spec/binary_format.tex index 0095dc4..5d9b4d7 100644 --- a/spec/binary_format.tex +++ b/spec/binary_format.tex @@ -235,7 +235,7 @@ {\Large\scshape\color{epiphanyslate}Binary Format}\\[6pt] {\large\itshape\color{epiphanyslate}A companion to the Core Specification}\\[14pt] {\color{epiphanygold}\rule{3in}{0.8pt}}\\[24pt] - {\normalsize\color{epiphanyink}Version 0.5.0 --- Schema major 2 (data-model expansion: cross-cutting bodies, repeats/voltas, staff/instrument/metadata fills; total default-fill migration)}\\[4pt] + {\normalsize\color{epiphanyink}Version 0.6.0 --- Repeat authoring (OperationKind/Tag 28/29; the born-at-v2 create, the major-0 delete)}\\[4pt] {\small\color{epiphanyslate}Normative for the byte layouts it defines} \vfill \end{titlepage} @@ -1132,7 +1132,10 @@ The public per-value codec --- the seam between this document and the Operation Catalog's value-typed payloads (Operation Catalog, \sectionsc{Value-Typed Payloads}, requirement \texttt{req:catalog:value-encoding}) --- is defined for exactly these -twenty-two types (the Phase-3 operation tranche added the last four): +twenty-three types (the Phase-3 operation tranche added +\texttt{Staff}/\texttt{TimeSignature}/\texttt{TempoSegment}/% +\texttt{StaffLineConfiguration}; the repeat-authoring revision added +\texttt{RepeatStructure}): \begin{quote} \texttt{Event}, \texttt{Rest}, \texttt{Pitch}, \texttt{IdentifiedPitch}, @@ -1142,7 +1145,7 @@ twenty-two types (the Phase-3 operation tranche added the last four): \texttt{DecompositionAttachment}, \texttt{SpellingSourceKind}, \texttt{ScoreMetadata}, \texttt{MetricGrid}, \texttt{Staff}, \texttt{TimeSignature}, \texttt{TempoSegment}, -\texttt{StaffLineConfiguration}. +\texttt{StaffLineConfiguration}, \texttt{RepeatStructure}. \end{quote} The seam introduces \textbf{no new bytes}: a value's stand-alone canonical @@ -1298,7 +1301,7 @@ AcceptLoser, \tablenums{1} KeepWinner, \tablenums{2} Override \label{req:binfmt:kind-discriminants} The \texttt{OperationKind} wire discriminant is one byte, golden-locked to the table below. The vocabulary is \textbf{append-only}: new primitive kinds -take discriminants past \tablenums{27}; the assignments below never change. +take discriminants past \tablenums{29}; the assignments below never change. \end{requirement} Each row also pins the payload's byte layout; the field \emph{set and order} @@ -1415,6 +1418,14 @@ sequence sorted ascending by canonical bytes. $\mathrm{lp}$(\texttt{StaffLineConfiguration}) if present \cat{} \texttt{visible} (bool, 1) & \sectionsc{SetStaffLayout} \\ + \tablenums{28} & \texttt{CreateRepeatStructure} & + $\mathrm{lp}$(\texttt{RepeatStructure}) --- the schema-major-2 + layout, unconditionally (born at v2; + Section~\ref{sec:evolution:major2}) & + \sectionsc{Repeat Structures} \\ + \tablenums{29} & \texttt{DeleteRepeatStructure} & + \texttt{repeat} (16) & + \sectionsc{Repeat Structures} \\ \bottomrule \end{longtable} \endgroup @@ -1459,7 +1470,7 @@ assigned independently of Section~\ref{sec:ops:kinds}, with both encode and validating decode. One byte; only \texttt{Registered} carries a payload (its \texttt{OperationKindRegistryId}, 16 big-endian bytes, total 17). Unknown discriminants and wrong lengths are decode errors. Append-only past -\tablenums{27}. +\tablenums{29}. \end{requirement} \begingroup\small @@ -1482,6 +1493,7 @@ discriminants and wrong lengths are decode errors. Append-only past \tablenums{11} & \texttt{InsertStaffInstance} & \tablenums{23} & \texttt{SetMetricGrid} \\ \tablenums{24} & \texttt{InsertStaff} & \tablenums{25} & \texttt{SetTimeSignature} \\ \tablenums{26} & \texttt{SetTempoSegment} & \tablenums{27} & \texttt{SetStaffLayout} \\ + \tablenums{28} & \texttt{CreateRepeatStructure} & \tablenums{29} & \texttt{DeleteRepeatStructure} \\ \bottomrule \end{longtable} \endgroup @@ -1495,7 +1507,9 @@ discriminants and wrong lengths are decode errors. Append-only past \texttt{OperationKindTag::\allowbreak InsertStaff}. The mismatch is intentional (the tag space predates the M2c naming) and is pinned here so barrier -authors target the right tag. +authors target the right tag. The repeat-structure pair projects +name-verbatim (\texttt{CreateRepeatStructure}/% +\texttt{DeleteRepeatStructure}), as the cross-cutting tags do. \section{Stamps and Causal Contexts} \label{sec:ops:stamp} @@ -2292,9 +2306,16 @@ The \emph{only} minor-additive mechanism in schema major~0 is \textbf{appending discriminants to open vocabularies}: \begin{itemize} - \item \texttt{OperationKind}: append at ${\geq}\,\tablenums{24}$ - (Requirement~\ref{req:binfmt:kind-discriminants}); - \item \texttt{OperationKindTag}: append at ${\geq}\,\tablenums{24}$ + \item \texttt{OperationKind}: append at ${\geq}\,\tablenums{30}$ + (Requirement~\ref{req:binfmt:kind-discriminants}; the Phase-3 + tranche took \tablenums{24}--\tablenums{27} under this mechanism, + and the repeat pair \tablenums{28}/\tablenums{29} in the + schema-major-2 revision --- the discriminant space is one append-only + table across majors, but a kind's \emph{block stamp} follows minimal + stamping over its payload: \tablenums{28}'s payload embeds a v2 + layout, so its blocks stamp major~2, + Section~\ref{sec:evolution:major2}); + \item \texttt{OperationKindTag}: append at ${\geq}\,\tablenums{30}$ (Requirement~\ref{req:binfmt:kind-tag}); \item \texttt{OperationPayload}: append at ${\geq}\,\tablenums{4}$ (Section~\ref{sec:ops:payload}); @@ -2523,12 +2544,28 @@ The major is assigned per payload type, exactly as in major~1: \begin{itemize} \item \textbf{Snapshot-only:} \texttt{Instrument} (no operation embeds - one) and \texttt{RepeatStructure} (no operation embeds one \emph{at - this revision}; the repeat-authoring operations planned for the same - push are born at v2 and change nothing about lower majors). These - reach only the acceleration full-\texttt{Score} snapshot. - \item \textbf{Canonical operation layer:} seven existing operation - payloads embed filled values --- + one); it reaches only the acceleration full-\texttt{Score} snapshot. + (\texttt{RepeatStructure} was snapshot-only when this section was + first ratified; the repeat-authoring pair moved it to the canonical + operation layer --- next bullet.) + \item \textbf{Canonical operation layer:} eight operation + payloads embed filled values. \texttt{CreateRepeatStructure} (this + revision --- Operation Catalog \sectionsc{Repeat Structures}, + discriminant \tablenums{28}) embeds the v2 \texttt{RepeatStructure} + layout unconditionally (\texttt{kind} and \texttt{voltas} are not + optional fields) and is \emph{born at v2}: no lower-major layout for + its payload exists, so every block carrying one stamps major~2 under + minimal stamping. Its sibling \texttt{DeleteRepeatStructure} + (\tablenums{29}) carries a bare identifier --- a major-0 layout --- + so minimal stamping gives its blocks major~0; the kind discriminant + itself is an append-only schema-\emph{minor} vocabulary event (the + same append mechanism the Phase-3 tranche used for + \tablenums{24}--\tablenums{27} --- a mechanism claim only: what a + kind's blocks \emph{stamp} always follows minimal stamping over its + payload, as discriminant \tablenums{24}'s always-major-2 + \texttt{CreateStaff} shows). Neither changes anything about + lower-major layouts. The seven payloads of the first ratification + embed filled values --- \texttt{CreateCrossCutting} and \texttt{ModifyCrossCutting} (a \texttt{CrossCuttingValue} embedding \texttt{Slur}, \texttt{Tie}, \texttt{Beam}, or \texttt{Spanner}); \texttt{CreateStaff} (a @@ -2567,8 +2604,12 @@ The major is assigned per payload type, exactly as in major~1: \textbf{1} (the major-1 bool is always present); \texttt{CreateStaffInstance} / \texttt{SetStaffLayout} $\Rightarrow$ \textbf{2} iff their \texttt{staff\_lines\_override} - is \texttt{Some}, else \textbf{0}; every other payload keeps its - prior major. A block stamps the maximum over its payloads. + is \texttt{Some}, else \textbf{0}; + \texttt{CreateRepeatStructure} $\Rightarrow$ always \textbf{2} + (born at v2); \texttt{DeleteRepeatStructure} $\Rightarrow$ + \textbf{0} (a bare identifier under a minor kind append); every + other payload keeps its prior major. A block stamps the maximum + over its payloads. (Operation names are the Operation Catalog's; core Chapter~6's enum spells the creates \texttt{InsertStaff} / \texttt{InsertStaffInstance} / \texttt{InsertRegion}.) @@ -3122,6 +3163,20 @@ layouts of Section~\ref{sec:values:representative}. implementation phases land). Semantics: core specification schema-major-2 revision (leaf-type definitions, clef/key content-model ratification, \texttt{ClefId} retirement, strictly-authored timestamp requirement). \\ + \today & Operation vocabularies & 0.6.0 --- Repeat authoring + (schema-major-2 revision, Phase D): appends \texttt{OperationKind} + \tablenums{28} (\texttt{CreateRepeatStructure}, + $\mathrm{lp}$(\texttt{RepeatStructure}), born at v2 --- every block + carrying one stamps major~2 under minimal stamping) and \tablenums{29} + (\texttt{DeleteRepeatStructure}, bare identifier --- minimal stamping + over its major-0 payload layout gives major~0; the discriminant itself + a schema-\emph{minor} vocabulary append), with the + matching \texttt{OperationKindTag} \tablenums{28}/\tablenums{29} + (name-verbatim projection). No existing assignment changed; + Section~\ref{sec:evolution:major2} restates the per-payload stamping + with the pair. Semantics: Operation Catalog \sectionsc{Repeat + Structures}, 0.7.0; re-anchoring row (nearest-surviving-anchor across + every anchor site, cascade when none): core Chapter~6 rule table. \\ \bottomrule \end{longtable} diff --git a/spec/core_spec.pdf b/spec/core_spec.pdf index 974fcc4..9974575 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 d87272f..4910cf4 100644 --- a/spec/core_spec.tex +++ b/spec/core_spec.tex @@ -6159,6 +6159,10 @@ pub enum OperationKind { DeleteCrossCutting(DeleteCrossCuttingPayload), ModifyCrossCutting(ModifyCrossCuttingPayload), + // Repeat-structure operations + CreateRepeatStructure(CreateRepeatStructureOp), + DeleteRepeatStructure(DeleteRepeatStructureOp), + // Region and structure operations ChangeRegionTimeModel(ChangeRegionTimeModelOp), InsertRegion(InsertRegionOp), @@ -7421,6 +7425,16 @@ table is normative. as for slurs (surviving-endpoint collapse); per-spanner-kind proximity bounds are a deferred refinement \\ + Repeat structure & Anchor & + Re-anchor to the nearest surviving anchor; cascade-delete only + when no anchor survives & + as for spanners; the rule spans \emph{every} event-referencing + anchor site of the structure --- \texttt{start}/\texttt{end}, + the kind's jump targets (\texttt{DaCapo.end\_target}, + \texttt{DalSegno.segno}/\texttt{end\_target}), and each + volta's span (ratified with the repeat-authoring pair, + schema-major-2 revision) \\ + Marker & Anchor & Re-anchor to nearest event in same staff instance & proximity max: same staff instance; orphan on failure \\ @@ -7962,6 +7976,17 @@ pub enum CrossCuttingStructure { } \end{lstlisting} +The enum above is the data model's full cross-cutting family; the +\emph{wire} vocabulary the cross-cutting operations admit at this +revision (\texttt{CrossCuttingValue}, Binary Format companion) is the +four-kind subset \texttt{Tie}/\texttt{Slur}/\texttt{Beam}/% +\texttt{Spanner}. A \texttt{RepeatStructure} is authored by the +dedicated \texttt{CreateRepeatStructure}/% +\texttt{DeleteRepeatStructure} pair (Operation Catalog +\sectionsc{Repeat Structures}; ratified schema-major-2 revision), not +through \texttt{CreateCrossCutting}; the remaining variants await +their own authoring primitives. + \textbf{Invariant preconditions} (Slur case): \begin{itemize} \item The slur's id is unique within the cross-cutting registry. @@ -10810,6 +10835,10 @@ pub enum OperationKindTag { SetTimeSignature, SetTempoSegment, SetStaffLayout, + // Schema-major-2 revision (repeat authoring). The pair keeps + // its kind names verbatim, as the cross-cutting tags do. + CreateRepeatStructure, + DeleteRepeatStructure, } pub enum BarrierScope { @@ -11085,11 +11114,16 @@ truncated bodies of the cross-cutting structures (\texttt{Slur}, Chapter~5 definitions. The same per-payload-type rules apply: the canonical-base \texttt{MaterializedState} embeds none of these values and stays major~0; the filled values reach the acceleration snapshot -\emph{and}, through the seven operation payloads that embed them +\emph{and}, through the eight operation payloads that embed them (\texttt{CreateCrossCutting}, \texttt{ModifyCrossCutting}, \texttt{InsertStaff} and \texttt{InsertStaffInstance} (the Operation Catalog's \texttt{CreateStaff} / \texttt{CreateStaffInstance}), -\texttt{SetStaffLayout}, \texttt{SetMetadata}, and --- transitively, +\texttt{SetStaffLayout}, \texttt{SetMetadata}, +\texttt{CreateRepeatStructure} (the repeat-authoring revision --- it +embeds the filled \texttt{RepeatStructure} unconditionally, so it is +\emph{born at v2} and every block carrying one stamps major~2; its +\texttt{DeleteRepeatStructure} sibling carries a bare identifier, a +major-0 layout, and stamps major~0), and --- transitively, because an embedded \texttt{Region} may carry a \texttt{StaffInstance} whose \texttt{staff\_lines\_override} embeds the filled \texttt{StaffLineConfiguration} --- \texttt{InsertRegion} @@ -15339,6 +15373,22 @@ layouts they own versus inherit: total default-filling migration: Binary Format companion 0.4.0~$\rightarrow$~0.5.0. \\ + \today & Schema major 2 (repeat authoring, Phase D) & + The dedicated \texttt{CreateRepeatStructure}/% + \texttt{DeleteRepeatStructure} pair enters the operation set: + Chapter~6's \texttt{OperationKind} enum and Chapter~8's + \texttt{OperationKindTag} listing gain the two variants (repeats are not + \texttt{CrossCuttingValue} kinds on the wire --- the reconciliation + note follows the \texttt{CrossCuttingStructure} listing), and the + re-anchoring rule table gains the Repeat-structure~/ Anchor row + (re-anchor to the nearest surviving anchor across \emph{every} + event-referencing anchor site --- \texttt{start}/\texttt{end}, jump + targets, volta spans --- cascade-delete only when none survives). + Six-part schemas: Operation Catalog \sectionsc{Repeat Structures}, + 0.6.0~$\rightarrow$~0.7.0. Wire discriminants 28/29 and the + per-payload stamping (create born at v2; delete a minor kind append + at major~0): Binary Format companion 0.5.0~$\rightarrow$~0.6.0. + \\ \bottomrule \end{longtable} diff --git a/spec/operation_catalog.pdf b/spec/operation_catalog.pdf index 8e00fd4..30118ed 100644 Binary files a/spec/operation_catalog.pdf and b/spec/operation_catalog.pdf differ diff --git a/spec/operation_catalog.tex b/spec/operation_catalog.tex index 5f0690b..3bb7859 100644 --- a/spec/operation_catalog.tex +++ b/spec/operation_catalog.tex @@ -226,7 +226,7 @@ {\Large\scshape\color{epiphanyslate}Operation 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.6.0 --- Pass-12 G-ratification (meta-operation edge semantics, system-derived immutability, recreate vocabulary, slot retirement)}\\[4pt] + {\normalsize\color{epiphanyink}Version 0.7.0 --- Schema-major-2 repeat authoring (the CreateRepeatStructure / DeleteRepeatStructure pair)}\\[4pt] {\small\color{epiphanyslate}Normative for the operation kinds it defines} \vfill \end{titlepage} @@ -842,6 +842,73 @@ anchor; there is no \texttt{DeleteStaff} in this catalogue revision --- an empty-only staff delete mirroring the container discipline is a later schema-fill). +\section{Repeat Structures} +\label{sec:k0:repeat-structures} + +Ratified with the schema-major-2 revision: the dedicated authoring pair for +\texttt{RepeatStructure} (core specification Chapter~5 +\sectionsc{Repeat Structures}). Repeats live in the cross-cutting registry +but are \emph{not} \texttt{CrossCuttingValue} kinds on the wire --- the +cross-cutting operations admit only +\texttt{Tie}/\texttt{Slur}/\texttt{Beam}/\texttt{Spanner} +(Section~\ref{sec:k0:create-cross-cutting}) --- so the pair is a +first-class primitive mirroring the cross-cutting disciplines. + +\textbf{Payload schema.} \texttt{CreateRepeatStructureOp \{ repeat: +RepeatStructure \}} --- the full value (schema major 2): identity, the +\texttt{start}/\texttt{end} anchors, the \texttt{RepeatKind}, and the +volta list. \texttt{DeleteRepeatStructureOp \{ repeat: RepeatStructureId +\}}. + +\textbf{Canonical encoding.} Create: the length-framed canonical bytes of +\texttt{repeat} (the schema-major-2 layout). Delete: the bare identifier. +The create's payload embeds the v2 \texttt{RepeatStructure} layout +unconditionally (\texttt{kind} and \texttt{voltas} are not optional +fields), so under minimal stamping a block carrying one stamps schema +major~2 --- the create is \emph{born at v2}. The delete's payload is an +identifier --- a major-0 layout --- so minimal stamping gives its blocks +major~0; the kind discriminant itself is an append-only schema-\emph{minor} +vocabulary event (the same append mechanism as the Phase-3 tranche; the +stamp itself always follows minimal stamping over the payload, per the +Binary Format companion \sectionsc{Schema Major 2}). + +\textbf{Reduction rule.} Set-union creation and a delete-wins tombstone, +mirroring the cross-cutting family. A create mints the repeat live if its +id is fresh and \emph{every} event-referencing anchor site resolves to a +live event --- \texttt{start}/\texttt{end}, the kind's jump targets +(\texttt{DaCapo.end\_target}, +\texttt{DalSegno.segno}/\texttt{end\_target}), and each volta's +\texttt{start}/\texttt{end} --- since the mint must leave the graph +satisfying the reference-resolution invariants; a dead anchor is a +precondition no-op (\texttt{TargetMissing}). A repeat create of a live id +reads \texttt{AlreadyApplied} without value comparison (the cross-cutting +discipline; the \texttt{RecreateContentMismatch} scope of +Section~\ref{sec:k0:create-staff} is unchanged). A delete tombstones the +repeat (idempotent on re-delete, delete-wins); deleting a missing id is a +no-op precondition failure. Graph-aware reduction adds or removes the +structure from the cross-cutting registry. + +\textbf{Conflict cases.} None at reduction time (set-union creation; +delete-wins is idempotent). + +\textbf{Undo semantics.} Undo of a create tombstones the minted repeat +(Section~\ref{sec:k0:undo}). A delete mints nothing, so the prototype's +minted-object undo does not re-introduce the tombstoned structure +(P11-C8). + +\textbf{Re-anchoring.} The structure participates in the re-anchoring rule +table when a referenced event is later tombstoned: re-anchor to the +nearest surviving anchor, cascade-delete only when none survives --- as +for spanners, spanning \emph{every} anchor site +(\texttt{start}/\texttt{end}, jump targets, volta spans). The rule row is +the core specification's (Chapter~6 re-anchoring rule table, ratified with +this pair). + +\textbf{Authoring advisory.} The volta well-formedness constraints of +core Chapter~5 (endings non-empty, 1-based, ascending) are +\emph{advisory}: surfaced at authoring time under interactive validation, +never enforced under reduction. + \section{SetUserSystemBreak} \label{sec:k0:set-user-system-break} @@ -1246,6 +1313,16 @@ a fresh design. creation, LWW structural overwrite, and LWW advisory respectively. \end{description} +\section*{Added in the schema-major-2 revision (Chapter~\ref{ch:k0})} + +\begin{description} + \item[Create / delete repeat structure] + Section~\ref{sec:k0:repeat-structures} --- net-new primitives (never + drafted as framework slots). Set-union creation with the + all-anchors-live precondition and a delete-wins tombstone; the create + is born at v2, the delete stamps major~0. +\end{description} + \section*{Retired slots (ratified Pass~12: outside the operation set)} \begin{description}