Pass 12 G-pass: ratify the full batch (28 rows) — spec tranche

The G-ratification pass over the accumulated PASS12_BATCH backlog
(worklist: spec/PASS12_WORKLIST.md; dispositions:
PASS12_RATIFICATION_LOG "G-pass tranche"). Four project-lead
decisions: K12 slur permission = AND, H7 authored-uninferred
annotations SURFACE, K4 ResolveConflict = no supersede, K8 genesis
outside the operation set. Three named deferrals: H2 (narrowed;
spelling-v2 + notation refinement), K2 (tuning catalog), K5 (Profile
Conformance companion).

core_spec: spelling + decomposition move to profile-declared with
ratified v1 defaults (req:pitch:spelling-algorithm,
req:time:decomposition-algorithm — two open-question boxes closed);
authored-uninferred surfacing (req:pitch:authored-uninferred);
decomposition precedence pinned FIXED; system-derived content
immutability (K3); genesis note (K8); slur AND advisory (K12);
re-anchoring table C1/C2/C3 + SameCanvasNearer variant (C4); barrier
matching + unsafe-tombstone semantics (req:format:barrier-matching,
req:format:unsafe-tombstone); solver kind-strength /
sub-conformant-report / Minimal-floor requirements (I4/I5/I6); stale
OperationKindTag listing gains the eleven appended tags.

operation_catalog 0.5.0 -> 0.6.0: K1 migration fallback long-term;
K4 no-supersede; K6 edge semantics (single-pass, quarantine excluded,
pending governs); K5 deferral pinned; K8 slots RETIRED; K10 reuse
blessed; K11 asymmetry normative; K12 AND; K2 prototype pin;
K3/K9 preconditions.

binary_format 0.3.0 -> 0.4.0: appended vocab discriminants
SystemDerivedContentImmutable(12), RecreateContentMismatch(13),
SameCanvasNearer(6); E5 tombstone-encoding open question.

All three PDFs rebuilt clean, zero undefined references. Batch rows
struck 28 -> 0 (tracker CLOSED); CONFORMANCE.md caveat dropped;
DECISIONS cross-refs in core/ops/layout-ir/editor-core (new file).

Code tranche (H7 surfacing, K3/K9/C4 discriminants) follows.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NEs4aYiu8MXjdYdMxw8PTd
This commit is contained in:
Levi Neuwirth 2026-07-07 10:23:30 -04:00
parent 7e7a43b050
commit aff1809421
14 changed files with 937 additions and 118 deletions

View File

@ -107,11 +107,14 @@ substituting a vendor heuristic:
- **Spelling**: `SpellingAlgorithmId` `"default"` — a Temperley-style - **Spelling**: `SpellingAlgorithmId` `"default"` — a Temperley-style
line-of-fifths preference algorithm, v1 (`epiphany-core/src/prepass.rs`). line-of-fifths preference algorithm, v1 (`epiphany-core/src/prepass.rs`).
The identifier is the crate's proposal pending ratification (P12-H1). A The identifier is ratified normative (Pass 12,
profile requesting any other id errors; nothing is silently substituted. `req:pitch:spelling-algorithm`). A profile requesting any other id errors;
nothing is silently substituted.
- **Notational decomposition**: `DecompositionAlgorithmId` `"default"` — the - **Notational decomposition**: `DecompositionAlgorithmId` `"default"` — the
integer-grid metric splitter, v1, with its scope bounds recorded as integer-grid metric splitter, v1, with its scope bounds ratified as
P12-H4 (single governing meter, `MAX_DOTS = 1`, tuplet-nesting deferred). normative bounds of the versioned algorithm (Pass 12,
`req:time:decomposition-algorithm`: single governing meter, `MAX_DOTS = 1`,
tuplet-nesting deferred; a wider algorithm is a version bump).
Same no-substitution rule. Same no-substitution rule.
- Both pre-pass outputs are **canonical derived annotations**: deterministic - Both pre-pass outputs are **canonical derived annotations**: deterministic
functions of `(materialized graph, profile, algorithm id)` recomputed on functions of `(materialized graph, profile, algorithm id)` recomputed on

View File

@ -416,3 +416,25 @@ the continued-fraction approximation. Note the class's *non-normative* unit
label is "wallclock seconds" while this residual is measured in whole notes; label is "wallclock seconds" while this residual is measured in whole notes;
the class identity (`TempoIntegration`: conversion residual in either the class identity (`TempoIntegration`: conversion residual in either
direction) is what is normative. direction) is what is normative.
## Pass 12 G-pass (2026-07-07): the H rows are ratified
All seven H rows are retired (dispositions in
`spec/PASS12_RATIFICATION_LOG.md`, "G-pass tranche"; worklist
`spec/PASS12_WORKLIST.md`). Summary: **H1** `"default"` = Temperley
line-of-fifths v1 is ratified normative (`req:pitch:spelling-algorithm`);
**H3** convention-as-tiebreak and **H5** region-time-model-independence are
pinned as properties of that versioned algorithm; **H4** the five
decomposition bounds are the declared normative bounds of `"default"` v1
(`req:time:decomposition-algorithm`; C5's derived-notation gap is subsumed);
**H6** decomposition precedence is ratified FIXED (not configurable — a
configurable order would be a schema-major `Score` field with no consumer);
**H2** narrowed (the content model landed in I-0; key-aware spelling is
algorithm-v2 territory, cancelling naturals a notation refinement); **H7**
decided the other way from the implementation: authored attachments on
inference-ineligible targets MUST surface in derived annotations
(`req:pitch:authored-uninferred`) — the code change lands with the G-pass
code tranche (authored-only resolution paths + distinct taxonomy buckets in
both pre-passes). Also ratified here: system-derived intrinsic content is
immutable under reduction (P12-K3; core Ch5 states it, the catalog pins the
precondition, `epiphany-ops` implements).

View File

@ -0,0 +1,22 @@
# epiphany-editor-core — Decisions
Decision log for the headless editing seam (`EditorSession`). Older decisions
for this crate were recorded in session notes and the Pass-12 batch rows it
filed (P12-E4, P12-E5); this file starts with their ratification.
## Pass 12 G-pass (2026-07-07): E4/E5 are ratified
Dispositions in `spec/PASS12_RATIFICATION_LOG.md` ("G-pass tranche").
**E4** adopt-as-implemented (`req:format:barrier-matching`): target-free
operations (`SetMetadata`, `DeclareTransaction`) are matched by score-wide
barriers only; opaque `Registered` operations match fully conservatively.
**E5** semantics ratified (`req:format:unsafe-tombstone`): crossing a barrier
immediately deactivates the extension's remaining barriers; the crossing MUST
be durably recorded at the next commit; a tombstoned `required = true`
extension leaves the bundle read-only for dependents. The manifest-side byte
encoding is deferred to the Binary Format companion (new open question there:
the manifest is frozen at major 0, so the record rides the blob layer or a
new chunk kind — next bundle-format tranche);
`extensions_requiring_tombstone()` remains the producer awaiting that
consumer.

View File

@ -465,3 +465,18 @@ schema-major-1 tranche):
`(original, ordinal)` `stable_semantic_instance_key`. Since `LayoutObjectId`s `(original, ordinal)` `stable_semantic_instance_key`. Since `LayoutObjectId`s
are non-canonical and re-derived per layout, the key need only be stable within are non-canonical and re-derived per layout, the key need only be stable within
a layout. Ratified as core spec `req:layoutir:continuation-synthesis`. a layout. Ratified as core spec `req:layoutir:continuation-synthesis`.
## Pass 12 G-pass (2026-07-07): I4/I5/I6 are ratified
Dispositions in `spec/PASS12_RATIFICATION_LOG.md` ("G-pass tranche"), all
adopt-as-implemented; these are deliberate Standard-tier design inputs.
**I4** strength is kind-determined (`req:solver:kind-strength`): no instance
strength field; breaks by `BreakKind` (Hard→Required, Soft→Preferred{1.0}),
other core families Required, `Registered` conservative Required; future
constraint families declare their strength in their normative definitions.
**I5** the stub's constraints-present-but-unevaluated report
(`SolvedWithWarnings` + `satisfied_hard_constraints == false` + warning) is
sanctioned (`req:solver:subconformant-report`). **I6** the implemented
emission set (successive-notehead no-collision chains + per-glyph containment
+ user-break constraints) is the normative Minimal-tier floor
(`req:layoutir:constraint-floor`).

View File

@ -916,3 +916,27 @@ of the same transaction could be defined as idempotent rather than
conflicting; (4) P12-C5 stands as filed (the decomposition pre-pass still conflicting; (4) P12-C5 stands as filed (the decomposition pre-pass still
honors only the first governing meter — the reduction semantics are pinned honors only the first governing meter — the reduction semantics are pinned
here and tested under `a_mid_region_meter_change_reduces_cleanly_p12_c5`). here and tested under `a_mid_region_meter_change_reduces_cleanly_p12_c5`).
## Pass 12 G-pass (2026-07-07): the K and C rows are ratified
All open K/C rows are retired (dispositions in
`spec/PASS12_RATIFICATION_LOG.md`, "G-pass tranche"). Adopted as implemented:
**K1** (migration read-only fallback is long-term), **K4** (earliest resolve
governs universally — no supersede; re-resolution is a future dedicated op;
no Conflict object kind), **K6** (single-pass promotion, quarantined resolves
never govern, pending resolves govern set-level, `TargetMissing` reuse kept),
**K10** (`TransactionConflict` reuse blessed for strand-blocks), **K11**
(undo idempotence asymmetry is normative), **K12** (cross-region slur = AND),
**C1** (cue cascades on any source death), **C2** (Range truncate = region
edge, zero offset), **C3** (annotation orphaning sanctioned), **C5** (folded
into H4's single-meter bound). Deferred with named sites: **K2** (tuning
catalog; prototype pinned as declared v1 behavior, replacement = payload
schema-major), **K5** (Profile Conformance companion; v1 profiles declare no
selection function). Decided with code to land in the G-pass code tranche:
**K3** refuse SYSTEM_DERIVED intrinsic-content rewrites
(`PreconditionFailureReason::SystemDerivedContentImmutable`, discriminant 12),
**K9** differing-value re-creates get `RecreateContentMismatch` (13),
**C4** rank-4 re-anchors get `ReanchorReason::SameCanvasNearer` (6; 5 was
already `DeclaredByExtension`). **K8** retired: genesis is outside the
operation set (catalog K1 slots removed, core Ch5 states it). Catalog
0.5.0 → 0.6.0; Binary Format 0.3.0 → 0.4.0.

View File

@ -5,7 +5,9 @@
not into code improvisations. … Don't open Pass 12 until at least 3 items not into code improvisations. … Don't open Pass 12 until at least 3 items
accumulate."* accumulate."*
**Status: OPEN.** Agent H's landing (spelling + decomposition pre-passes) **Status: CLOSED (G-pass, 2026-07-07).** Every row below is struck: the G-ratification pass (`PASS12_WORKLIST.md`, dispositions in `PASS12_RATIFICATION_LOG.md` "G-pass tranche") retired the full batch. New Pass-13 candidates open a fresh file.
**Original status: OPEN.** Agent H's landing (spelling + decomposition pre-passes)
surfaced five candidates, crossing the ≥3 threshold. This file is the running surfaced five candidates, crossing the ≥3 threshold. This file is the running
collection; G ratifies (or defers/rejects) the batch when Phase 2's open collection; G ratifies (or defers/rejects) the batch when Phase 2's open
questions are resolved. F collects, F does not resolve. questions are resolved. F collects, F does not resolve.
@ -28,41 +30,41 @@ code instead is the failure mode this batch exists to prevent.
| ID | Source | Summary | Disposition target | | ID | Source | Summary | Disposition target |
|----|--------|---------|--------------------| |----|--------|---------|--------------------|
| P12-H1 | `epiphany-core` H | Ratify `SpellingAlgorithmId::Default` = Temperley line-of-fifths v1 (Pass 11 closed before H landed; the id `"default"` is the crate's proposal until ratified — not a byte layout, so nothing golden-locks on it). | G (algorithm-choice ratification) | | ~~P12-H1~~ **RATIFIED (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-core` H | Ratify `SpellingAlgorithmId::Default` = Temperley line-of-fifths v1 (Pass 11 closed before H landed; the id `"default"` is the crate's proposal until ratified — not a byte layout, so nothing golden-locks on it). | G (algorithm-choice ratification) |
| P12-H2 | `epiphany-core` H | `KeySignatureChange` / `ClefChange` are anchor-only placeholders; context-aware spelling infers tonal context from the melody (line-of-fifths centre of gravity) rather than a *declared* key. A real key/clef content model would let spelling/decomposition honour declared keys and place cancelling naturals. Flagged as a graph-model gap. | G (graph model) | | ~~P12-H2~~ **DEFERRED-NARROWED (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-core` H | `KeySignatureChange` / `ClefChange` are anchor-only placeholders; context-aware spelling infers tonal context from the melody (line-of-fifths centre of gravity) rather than a *declared* key. A real key/clef content model would let spelling/decomposition honour declared keys and place cancelling naturals. Flagged as a graph-model gap. | G (graph model) |
| P12-H3 | `epiphany-core` H | Chromatic-run convention (ascending = sharps, descending = flats) is only a *tiebreak* in the centre-of-gravity rule, so an isolated chromatic run with no tonal context may pick the enharmonic the convention would not. Voice-leading refinement deferred. | G / Pass 12 (spelling) | | ~~P12-H3~~ **RATIFIED (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-core` H | Chromatic-run convention (ascending = sharps, descending = flats) is only a *tiebreak* in the centre-of-gravity rule, so an isolated chromatic run with no tonal context may pick the enharmonic the convention would not. Voice-leading refinement deferred. | G / Pass 12 (spelling) |
| P12-H4 | `epiphany-core` H | Decomposition simplifications: single governing meter per region (multi/mid-region meter changes deferred); region origin assumed a barline (anacrusis deferred); compound-meter beat grouping beyond the dyadic default; tuplet nesting and cross-beat tuplet members; double+ augmentation dots (`MAX_DOTS = 1`). | G (decomposition scope) | | ~~P12-H4~~ **RATIFIED (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-core` H | Decomposition simplifications: single governing meter per region (multi/mid-region meter changes deferred); region origin assumed a barline (anacrusis deferred); compound-meter beat grouping beyond the dyadic default; tuplet nesting and cross-beat tuplet members; double+ augmentation dots (`MAX_DOTS = 1`). | G (decomposition scope) |
| P12-H5 | `epiphany-core` H | Automatic spelling under aleatoric regions (the spec's open question). H spells pitches region-independently but performs no region-specific aleatoric spelling; defer if the algorithm does not generalise cleanly. | G / Pass 12 (open question) | | ~~P12-H5~~ **RATIFIED (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-core` H | Automatic spelling under aleatoric regions (the spec's open question). H spells pitches region-independently but performs no region-specific aleatoric spelling; defer if the algorithm does not generalise cleanly. | G / Pass 12 (open question) |
| ~~P12-I1~~ **RESOLVED (I-1)** | `epiphany-layout-ir` / `engrave` / `render-svg` I | The v0 pipeline was a **structural placeholder** (one *arbitrary* glyph per object at `y = 0`), not real notation. **Resolved by I-1 (Phase 2-3):** `to_constrained` now builds real notation — clef-relative noteheads (by `NoteValue`), spelling-derived accidentals, key/time signatures, rests, barlines, and the staff-line/stem strokes — and the Engraver re-spaces it; the human visual-acceptance gate is met (goldens locked against the stub *and* the real Engraver). The Ch 7 engraving-boundary question resolved to: notation construction lives in `to_constrained`, horizontal spacing in the Engraver. | ✅ done | | ~~P12-I1~~ **RESOLVED (I-1)** | `epiphany-layout-ir` / `engrave` / `render-svg` I | The v0 pipeline was a **structural placeholder** (one *arbitrary* glyph per object at `y = 0`), not real notation. **Resolved by I-1 (Phase 2-3):** `to_constrained` now builds real notation — clef-relative noteheads (by `NoteValue`), spelling-derived accidentals, key/time signatures, rests, barlines, and the staff-line/stem strokes — and the Engraver re-spaces it; the human visual-acceptance gate is met (goldens locked against the stub *and* the real Engraver). The Ch 7 engraving-boundary question resolved to: notation construction lives in `to_constrained`, horizontal spacing in the Engraver. | ✅ done |
| ~~P12-I2~~ **RESOLVED (wired)** | `epiphany-determinism` / `epiphany-layout-ir` I | Stable layout-object id derivation (`MUSCLOID`, Pass-11 item 2.6). **Wired:** `epiphany-determinism` now reserves the built-in `DomainTag::LAYOUT_OBJECT_ID` (`MUSCLOID`), and `layout-ir`'s provenance derivations (single / multiply-manifested / synthesized) plus the engraving-decision id route through it (no longer borrowing `MUSCCONF`). Layout ids stay non-canonical, so only `data-prov` hex in the render goldens changed; no durable/interchanged artifact. See `layout-ir/DECISIONS.md` and `req:layoutir:object-id-derivation`. | ✅ done | | ~~P12-I2~~ **RESOLVED (wired)** | `epiphany-determinism` / `epiphany-layout-ir` I | Stable layout-object id derivation (`MUSCLOID`, Pass-11 item 2.6). **Wired:** `epiphany-determinism` now reserves the built-in `DomainTag::LAYOUT_OBJECT_ID` (`MUSCLOID`), and `layout-ir`'s provenance derivations (single / multiply-manifested / synthesized) plus the engraving-decision id route through it (no longer borrowing `MUSCCONF`). Layout ids stay non-canonical, so only `data-prov` hex in the render goldens changed; no durable/interchanged artifact. See `layout-ir/DECISIONS.md` and `req:layoutir:object-id-derivation`. | ✅ done |
| ~~P12-I3~~ **RESOLVED (I-4a)** | `epiphany-layout-ir` I | The bundled `BRAVURA_METRICS` were *approximations* disagreeing with the renderer's genuine outlines. **Resolved by I-4a:** the metrics table is re-extracted from the **same** SHA-pinned `bravura-1.392` font the outlines come from, with bboxes rounded *outward* so each metric box contains the drawn ink (a `render-svg` test proves containment); `BRAVURA_VERSION = SemVer(1, 392, 0)`. A coupled barline-placement bug it surfaced (bottom-origin glyph floated) was fixed in the same increment. | ✅ done | | ~~P12-I3~~ **RESOLVED (I-4a)** | `epiphany-layout-ir` I | The bundled `BRAVURA_METRICS` were *approximations* disagreeing with the renderer's genuine outlines. **Resolved by I-4a:** the metrics table is re-extracted from the **same** SHA-pinned `bravura-1.392` font the outlines come from, with bboxes rounded *outward* so each metric box contains the drawn ink (a `render-svg` test proves containment); `BRAVURA_VERSION = SemVer(1, 392, 0)`. A coupled barline-placement bug it surfaced (bottom-origin glyph floated) was fixed in the same increment. | ✅ done |
| P12-K1 | `epiphany-ops` K | A v0 `RespellPitch` carried a `ContentHash` *fingerprint* of the spelling, not the `PitchSpelling`. The v0→v1 migration (Operation Catalog, M1) cannot invert a fingerprint, so it recovers the spelling from the score-graph context (an explicit per-pitch spelling attachment whose canonical bytes hash to the fingerprint) and returns `MigrationError::Irreversible` (bundle opens read-only) when the context lacks it. Every other representative payload migrates self-contained; this is the lone exception. Confirm the read-only fallback is the intended disposition vs. requiring a v0 corpus that preserves spelling pre-images. | G / Pass 12 (migration) | | ~~P12-K1~~ **RATIFIED (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-ops` K | A v0 `RespellPitch` carried a `ContentHash` *fingerprint* of the spelling, not the `PitchSpelling`. The v0→v1 migration (Operation Catalog, M1) cannot invert a fingerprint, so it recovers the spelling from the score-graph context (an explicit per-pitch spelling attachment whose canonical bytes hash to the fingerprint) and returns `MigrationError::Irreversible` (bundle opens read-only) when the context lacks it. Every other representative payload migrates self-contained; this is the lone exception. Confirm the read-only fallback is the intended disposition vs. requiring a v0 corpus that preserves spelling pre-images. | G / Pass 12 (migration) |
| P12-K2 | `epiphany-ops` K | The `Transpose` op (Operation Catalog, M2 Group 1) carries a minimal `chromatic_steps: i32` interval and `reduce_onto` applies it as a CMN *alteration* shift only. Faithful interval algebra (diatonic vs. chromatic intervals, octave/nominal renormalization, transposition in non-CMN pitch spaces) is the deferred Chapter 4 tuning-catalog territory. The prototype also clamps the shifted alteration to the `i8` range, so an extreme transpose silently saturates instead of renormalizing — another reason the representation needs pinning. Pin the interval representation and transposition semantics when the tuning catalog lands. | G / Pass 12 (tuning) | | ~~P12-K2~~ **DEFERRED (tuning track; pinned) (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-ops` K | The `Transpose` op (Operation Catalog, M2 Group 1) carries a minimal `chromatic_steps: i32` interval and `reduce_onto` applies it as a CMN *alteration* shift only. Faithful interval algebra (diatonic vs. chromatic intervals, octave/nominal renormalization, transposition in non-CMN pitch spaces) is the deferred Chapter 4 tuning-catalog territory. The prototype also clamps the shifted alteration to the `i8` range, so an extreme transpose silently saturates instead of renormalizing — another reason the representation needs pinning. Pin the interval representation and transposition semantics when the tuning catalog lands. | G / Pass 12 (tuning) |
| P12-H6 | `epiphany-core` H | Decomposition-attachment precedence: the spec says the decomposition pre-pass uses the "same precedence machinery" as spelling, but spelling's machinery is per-score *configurable* with `priority`/timestamp tie-breaks while `DecompositionAttachment` carries no `priority` and the graph has no `DecompositionPrecedence` field. The audit fix implements the fixed default order (`UserChosen > Imported > Propagated > Inferred`, canonical attachment order as tie-break). Decide whether decomposition precedence is configurable (a canonical-codec change) or fixed. | G / Pass 12 (decomposition) | | ~~P12-H6~~ **RATIFIED (fixed order) (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-core` H | Decomposition-attachment precedence: the spec says the decomposition pre-pass uses the "same precedence machinery" as spelling, but spelling's machinery is per-score *configurable* with `priority`/timestamp tie-breaks while `DecompositionAttachment` carries no `priority` and the graph has no `DecompositionPrecedence` field. The audit fix implements the fixed default order (`UserChosen > Imported > Propagated > Inferred`, canonical attachment order as tie-break). Decide whether decomposition precedence is configurable (a canonical-codec change) or fixed. | G / Pass 12 (decomposition) |
| P12-H7 | `epiphany-core` H | Authored decompositions for inference-ineligible events: an authored attachment is exactly how a user would notate an *ungriddable* event, but the derived-annotation surface (mirroring spelling, which likewise ignores attachments on spelling-unavailable pitches) only resolves overrides where inferred output exists. Needs a spec answer for both pre-passes. | G / Pass 12 (pre-passes) | | ~~P12-H7~~ **RATIFIED (surface; code tranche) (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-core` H | Authored decompositions for inference-ineligible events: an authored attachment is exactly how a user would notate an *ungriddable* event, but the derived-annotation surface (mirroring spelling, which likewise ignores attachments on spelling-unavailable pitches) only resolves overrides where inferred output exists. Needs a spec answer for both pre-passes. | G / Pass 12 (pre-passes) |
| P12-K3 | `epiphany-ops` K | Content modification of a `SYSTEM_DERIVED` pitch: `ModifyEvent`/`ModifyIdentifiedPitch` can rewrite a synthetic pitch's intrinsic content in place, silently invalidating the id's content-derivation (Invariant 11). The new reduction-time collision check deliberately does not treat in-place rewrites as mints. Decide whether reduction must refuse them outright. | G / Pass 12 (identity) | | ~~P12-K3~~ **RATIFIED (refuse; code tranche) (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-ops` K | Content modification of a `SYSTEM_DERIVED` pitch: `ModifyEvent`/`ModifyIdentifiedPitch` can rewrite a synthetic pitch's intrinsic content in place, silently invalidating the id's content-derivation (Invariant 11). The new reduction-time collision check deliberately does not treat in-place rewrites as mints. Decide whether reduction must refuse them outright. | G / Pass 12 (identity) |
| P12-K4 | `epiphany-ops` K | `ResolveConflict` beyond the concurrent case: the spec pins outcomes only for *concurrent* differing resolves; the implementation applies the same rule to causally-later resolves (so an intentional re-resolution cannot supersede) and reads `AlreadyApplied` for any resolve against a `Dismissed` conflict. Also: the meta-conflict record cannot name the contested conflict in `affected_objects` because `TypedObjectId` has no Conflict kind. Pin the causally-later semantics and decide whether conflict records need an addressable object kind. | G / Pass 12 (conflict resolution) | | ~~P12-K4~~ **RATIFIED (no supersede) (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-ops` K | `ResolveConflict` beyond the concurrent case: the spec pins outcomes only for *concurrent* differing resolves; the implementation applies the same rule to causally-later resolves (so an intentional re-resolution cannot supersede) and reads `AlreadyApplied` for any resolve against a `Dismissed` conflict. Also: the meta-conflict record cannot name the contested conflict in `affected_objects` because `TypedObjectId` has no Conflict kind. Pin the causally-later semantics and decide whether conflict records need an addressable object kind. | G / Pass 12 (conflict resolution) |
| P12-C1 | `epiphany-ops` C | Multi-source cue re-anchoring: the rule table's action is plain "cascade-delete" (implemented: any source deletion cascades, like Tie) but its rationale ("a cue with no source is meaningless") implies truncate-while-any-source-survives. Pin one reading. | G / Pass 12 (re-anchoring) | | ~~P12-C1~~ **RATIFIED (cascade) (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-ops` C | Multi-source cue re-anchoring: the rule table's action is plain "cascade-delete" (implemented: any source deletion cascades, like Tie) but its rationale ("a cue with no source is meaningless") implies truncate-while-any-source-survives. Pin one reading. | G / Pass 12 (re-anchoring) |
| P12-C2 | `epiphany-ops` C | Graphic-gesture Range "truncate" is underdetermined. Implemented reading: a dead event-anchored range endpoint moves to its containing region's edge (start→Start, end→End, zero offset). Define "truncate" normatively. | G / Pass 12 (re-anchoring) | | ~~P12-C2~~ **RATIFIED (truncate defined) (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-ops` C | Graphic-gesture Range "truncate" is underdetermined. Implemented reading: a dead event-anchored range endpoint moves to its containing region's edge (start→Start, end→End, zero offset). Define "truncate" normatively. | G / Pass 12 (re-anchoring) |
| P12-C3 | `epiphany-ops` C | Analytical-annotation range reconstruction: a wall-clock (region-relative) or indeterminate event span cannot be expressed as a stored `Range` anchor without region-origin resolution, so such annotations orphan. State whether orphaning is the sanctioned outcome or an expressible form is required. | G / Pass 12 (re-anchoring) | | ~~P12-C3~~ **RATIFIED (orphan sanctioned) (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-ops` C | Analytical-annotation range reconstruction: a wall-clock (region-relative) or indeterminate event span cannot be expressed as a stored `Range` anchor without region-origin resolution, so such annotations orphan. State whether orphaning is the sanctioned outcome or an expressible form is required. | G / Pass 12 (re-anchoring) |
| P12-C4 | `epiphany-ops` C | `ReanchorReason` has no same-canvas variant: a rank-4 (same-canvas) survivor is recorded `ExplicitFallback` rather than appending a discriminant. Ratify a beyond-region reason or bless the fallback recording. | G / Pass 12 (re-anchoring) | | ~~P12-C4~~ **RATIFIED (reason 6; code tranche) (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-ops` C | `ReanchorReason` has no same-canvas variant: a rank-4 (same-canvas) survivor is recorded `ExplicitFallback` rather than appending a discriminant. Ratify a beyond-region reason or bless the fallback recording. | G / Pass 12 (re-anchoring) |
| P12-K5 | `epiphany-ops` K | Equivocation resolution's third path — a profile-declared deterministic selection function (e.g. lowest-hash-wins) — is unpinned and unimplemented; the reducer has no policy hook. Referenced from the catalog §ResolveEquivocation rationale. | G / Pass 12 (equivocation) | | ~~P12-K5~~ **DEFERRED (profile companion) (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-ops` K | Equivocation resolution's third path — a profile-declared deterministic selection function (e.g. lowest-hash-wins) — is unpinned and unimplemented; the reducer has no policy hook. Referenced from the catalog §ResolveEquivocation rationale. | G / Pass 12 (equivocation) |
| P12-K6 | `epiphany-ops` K | `ResolveEquivocation` edge semantics to pin: cascaded resolves (a promoted candidate that is itself a resolve does not govern a further promotion — single-pass implemented, vs. fixpoint); interaction with HLC-monotonicity quarantine (may a quarantined resolve govern?); a resolve held pending by its own causal gaps still governs promotion (set-level rule) while its effect stays pending; whether the invalid-target/chosen no-op warrants a dedicated `PreconditionFailureReason` (implemented: reuses `TargetMissing`). | G / Pass 12 (equivocation) | | ~~P12-K6~~ **RATIFIED (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-ops` K | `ResolveEquivocation` edge semantics to pin: cascaded resolves (a promoted candidate that is itself a resolve does not govern a further promotion — single-pass implemented, vs. fixpoint); interaction with HLC-monotonicity quarantine (may a quarantined resolve govern?); a resolve held pending by its own causal gaps still governs promotion (set-level rule) while its effect stays pending; whether the invalid-target/chosen no-op warrants a dedicated `PreconditionFailureReason` (implemented: reuses `TargetMissing`). | G / Pass 12 (equivocation) |
| ~~P12-K7~~ **RATIFIED (schema-major-1 track, 2026-07-06; see PASS12_RATIFICATION_LOG)** | `epiphany-ops` K | Advisory-precondition catalog: the spec declares the duration-boundary advisory only for InsertEvent while the implementation also applies it to ModifyEvent's replacement value — state ModifyEvent's bucket explicitly. Also: which advisory checks are blocked on graph-model completion (Instrument declared range; a Region slur-spanning permission flag; which extent shapes constitute a resolvable musical end bound). | G / Pass 12 (validation) | | ~~P12-K7~~ **RATIFIED (schema-major-1 track, 2026-07-06; see PASS12_RATIFICATION_LOG)** | `epiphany-ops` K | Advisory-precondition catalog: the spec declares the duration-boundary advisory only for InsertEvent while the implementation also applies it to ModifyEvent's replacement value — state ModifyEvent's bucket explicitly. Also: which advisory checks are blocked on graph-model completion (Instrument declared range; a Region slur-spanning permission flag; which extent shapes constitute a resolvable musical end bound). | G / Pass 12 (validation) |
| P12-I4 | `epiphany-layout-ir` I | Constraint-strength attachment: Ch9 defines `ConstraintStrength` and says the solver consumes constraints "in normalized form", but neither the normalized form nor Ch7's `LayoutConstraint` provides a channel for an instance to carry strength. Implemented rule: break strength = `BreakKind` (Hard→Required, Soft→Preferred{1.0}); other core families Required; `Registered` conservative Required. Bless the rule or add a strength field. | G / Pass 12 (solver) | | ~~P12-I4~~ **RATIFIED (kind-determined) (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-layout-ir` I | Constraint-strength attachment: Ch9 defines `ConstraintStrength` and says the solver consumes constraints "in normalized form", but neither the normalized form nor Ch7's `LayoutConstraint` provides a channel for an instance to carry strength. Implemented rule: break strength = `BreakKind` (Hard→Required, Soft→Preferred{1.0}); other core families Required; `Registered` conservative Required. Bless the rule or add a strength field. | G / Pass 12 (solver) |
| P12-I5 | `epiphany-layout-ir` I | No renderable status exists for "constraints present but not evaluated": every renderable `SolveStatus` is documented as "all hard constraints satisfied", leaving a below-conformance passthrough solver no honest report. Implemented encoding: `SolvedWithWarnings` + `satisfied_hard_constraints == false` + a warning. Sanction it or define a non-evaluating-tier report shape. | G / Pass 12 (solver) | | ~~P12-I5~~ **RATIFIED (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-layout-ir` I | No renderable status exists for "constraints present but not evaluated": every renderable `SolveStatus` is documented as "all hard constraints satisfied", leaving a below-conformance passthrough solver no honest report. Implemented encoding: `SolvedWithWarnings` + `satisfied_hard_constraints == false` + a warning. Sanction it or define a non-evaluating-tier report shape. | G / Pass 12 (solver) |
| P12-I6 | `epiphany-layout-ir` I | The spacing pass MUST "build collision constraints" but no per-tier minimum emission set is named. Implemented floor: successive-notehead-column no-collision chains + per-glyph region containment + user-break constraints. A normative Minimal-tier floor would make the acceptance surface testable. | G / Pass 12 (solver) | | ~~P12-I6~~ **RATIFIED (Minimal floor) (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-layout-ir` I | The spacing pass MUST "build collision constraints" but no per-tier minimum emission set is named. Implemented floor: successive-notehead-column no-collision chains + per-glyph region containment + user-break constraints. A normative Minimal-tier floor would make the acceptance surface testable. | G / Pass 12 (solver) |
| ~~P12-D1~~ **RESOLVED (Binary Format 0.1.0 §7.6, `req:binfmt:opindex`)** | `epiphany-bundle` D | Operation-index provisional encoding (block-refs + id-sorted entries with u32 block ordinal and u32 in-block offset; golden-locked) awaiting Binary Format companion ratification, together with: the offset's meaning (first content byte within the uncompressed block payload), a normative definition of "stale" (implemented: index block-set ≠ manifest `operation_roots` under full-`ChunkRef` equality), the one-slot-per-id invariant, the load-bearing property that the envelope encoding *leads* with the 16-byte OperationId, and whether the commit-time "grown significantly" SHOULD gets a threshold or stays implementation-defined. Ratified as-implemented; refresh threshold pinned implementation-defined (open question retained in the companion). | ✅ done | | ~~P12-D1~~ **RESOLVED (Binary Format 0.1.0 §7.6, `req:binfmt:opindex`)** | `epiphany-bundle` D | Operation-index provisional encoding (block-refs + id-sorted entries with u32 block ordinal and u32 in-block offset; golden-locked) awaiting Binary Format companion ratification, together with: the offset's meaning (first content byte within the uncompressed block payload), a normative definition of "stale" (implemented: index block-set ≠ manifest `operation_roots` under full-`ChunkRef` equality), the one-slot-per-id invariant, the load-bearing property that the envelope encoding *leads* with the 16-byte OperationId, and whether the commit-time "grown significantly" SHOULD gets a threshold or stays implementation-defined. Ratified as-implemented; refresh threshold pinned implementation-defined (open question retained in the companion). | ✅ done |
| ~~P12-E1~~ **RESOLVED (Binary Format 0.1.0 §8.1, `req:binfmt:ext-blobs`)** | `epiphany-layout-ir` E | Provisional canonical byte form for the `EditBarrier`/`BarrierScope`/`BarrierCondition` tree and the two `ExtensionDeclaration` blobs (`push_set` framing, u64 LE lengths; golden-locked). Ratified as-implemented. | ✅ done | | ~~P12-E1~~ **RESOLVED (Binary Format 0.1.0 §8.1, `req:binfmt:ext-blobs`)** | `epiphany-layout-ir` E | Provisional canonical byte form for the `EditBarrier`/`BarrierScope`/`BarrierCondition` tree and the two `ExtensionDeclaration` blobs (`push_set` framing, u64 LE lengths; golden-locked). Ratified as-implemented. | ✅ done |
| ~~P12-E2~~ **RESOLVED (Binary Format 0.1.0 §8.2, `req:binfmt:condition-depth`)** | `epiphany-layout-ir` E | The spec places no bound on `BarrierCondition` recursion; the decoder needs one against adversarial bytes. `MAX_CONDITION_DEPTH = 64` implemented — the companion pins 64 as the normative bound (decoders MUST reject deeper; writers MUST NOT emit deeper). | ✅ done | | ~~P12-E2~~ **RESOLVED (Binary Format 0.1.0 §8.2, `req:binfmt:condition-depth`)** | `epiphany-layout-ir` E | The spec places no bound on `BarrierCondition` recursion; the decoder needs one against adversarial bytes. `MAX_CONDITION_DEPTH = 64` implemented — the companion pins 64 as the normative bound (decoders MUST reject deeper; writers MUST NOT emit deeper). | ✅ done |
| ~~P12-E3~~ **RESOLVED (Binary Format 0.1.0 §8.1, `req:binfmt:object-kind-open`)** | `epiphany-layout-ir` E | Barrier `ObjectKind` byte form = the `TypedObjectId` 16-bit discriminant (2 LE bytes) with open-value decode (unknown kinds never match, preserving append-only forward compat). Representation and open-value stance ratified. | ✅ done | | ~~P12-E3~~ **RESOLVED (Binary Format 0.1.0 §8.1, `req:binfmt:object-kind-open`)** | `epiphany-layout-ir` E | Barrier `ObjectKind` byte form = the `TypedObjectId` 16-bit discriminant (2 LE bytes) with open-value decode (unknown kinds never match, preserving append-only forward compat). Representation and open-value stance ratified. | ✅ done |
| P12-E4 | `epiphany-editor-core` E | Barrier matching for operations with no graph target (`SetMetadata`, `DeclareTransaction` — implemented: score-wide barriers only) and for opaque `Registered` operations (implemented: fully conservative match) is unspecified. | G (Ch. 8) | | ~~P12-E4~~ **RATIFIED (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-editor-core` E | Barrier matching for operations with no graph target (`SetMetadata`, `DeclareTransaction` — implemented: score-wide barriers only) and for opaque `Registered` operations (implemented: fully conservative match) is unspecified. | G (Ch. 8) |
| P12-E5 | `epiphany-editor-core` E | The unsafe-edit tombstone MUST has no defined mechanism: the manifest-side form (drop declaration + preserved roots? an explicit tombstone record?), interaction with `required = true`, and whether crossing immediately deactivates the extension's remaining barriers (implemented: yes, recorded via `extensions_requiring_tombstone()` for the next bundle write). | G (Ch. 8) || P12-C5 | `epiphany-ops`/`epiphany-core` C/H | Mid-region meter changes: `SetTimeSignature` (catalog §Meter and Tempo Overwrites) reduces a second `MeterChange` into a region's grid cleanly, but the decomposition pre-pass honours only the first governing meter (P12-H4's single-meter simplification), so derived notation ignores the change until multi-meter decomposition lands. Reduction semantics pinned; the derived-annotation gap is H4's. | G / Pass 12 (decomposition) | | ~~P12-E5~~ **RATIFIED semantics / encoding deferred (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-editor-core` E | The unsafe-edit tombstone MUST has no defined mechanism: the manifest-side form (drop declaration + preserved roots? an explicit tombstone record?), interaction with `required = true`, and whether crossing immediately deactivates the extension's remaining barriers (implemented: yes, recorded via `extensions_requiring_tombstone()` for the next bundle write). | G (Ch. 8) || ~~P12-C5~~ **RATIFIED (folded into H4) (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-ops`/`epiphany-core` C/H | Mid-region meter changes: `SetTimeSignature` (catalog §Meter and Tempo Overwrites) reduces a second `MeterChange` into a region's grid cleanly, but the decomposition pre-pass honours only the first governing meter (P12-H4's single-meter simplification), so derived notation ignores the change until multi-meter decomposition lands. Reduction semantics pinned; the derived-annotation gap is H4's. | G / Pass 12 (decomposition) |
| P12-K8 | `epiphany-ops` K | Create score / canvas remain unavailable K1 slots: the document root and canvas are inline singletons (no `TypedObjectId::Canvas`; the root is never op-minted — genesis is `Score::empty` + bundle creation). Turning them into operations needs an addressable root/canvas object model. Decide: define one, or ratify genesis as deliberately outside the operation set. | G (graph model) | | ~~P12-K8~~ **RATIFIED (genesis outside ops) (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-ops` K | Create score / canvas remain unavailable K1 slots: the document root and canvas are inline singletons (no `TypedObjectId::Canvas`; the root is never op-minted — genesis is `Score::empty` + bundle creation). Turning them into operations needs an addressable root/canvas object model. Decide: define one, or ratify genesis as deliberately outside the operation set. | G (graph model) |
| P12-K9 | `epiphany-ops` K | Differing-value re-creates (a live id re-carried with different content: `CreateStaff`, the carried `TimeSignature`, container creates) refuse with `TargetMissing`, which misnames the situation. Decide whether a dedicated `PreconditionFailureReason` (appended) is warranted. | G / Pass 12 (vocabulary) | | ~~P12-K9~~ **RATIFIED (reason 13; code tranche) (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-ops` K | Differing-value re-creates (a live id re-carried with different content: `CreateStaff`, the carried `TimeSignature`, container creates) refuse with `TargetMissing`, which misnames the situation. Decide whether a dedicated `PreconditionFailureReason` (appended) is warranted. | G / Pass 12 (vocabulary) |
| P12-K10 | `epiphany-ops` K | Undo strand-blocks (StrictInverse refusing to tombstone a minted object still referenced by a live non-member, e.g. a staff with a surviving instance) reuse `ConflictKind::TransactionConflict`. Decide whether undo refusals deserve their own conflict kind. | G / Pass 12 (undo) | | ~~P12-K10~~ **RATIFIED (reuse blessed) (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-ops` K | Undo strand-blocks (StrictInverse refusing to tombstone a minted object still referenced by a live non-member, e.g. a staff with a surviving instance) reuse `ConflictKind::TransactionConflict`. Decide whether undo refusals deserve their own conflict kind. | G / Pass 12 (undo) |
| P12-K11 | `epiphany-ops` K | An undo's value restorations enter the write chains as ordinary writes by the undo op, so a second undo of the same transaction sees the first as a superseding writer (Conflicted/skip) while absence-restorations repeat idempotently — a documented asymmetry. Decide whether chain writes need distinguished undo provenance so repeated undo is uniformly idempotent. | G / Pass 12 (undo) | | ~~P12-K11~~ **RATIFIED (asymmetry normative) (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-ops` K | An undo's value restorations enter the write chains as ordinary writes by the undo op, so a second undo of the same transaction sees the first as a superseding writer (Conflicted/skip) while absence-restorations repeat idempotently — a documented asymmetry. Decide whether chain writes need distinguished undo provenance so repeated undo is uniformly idempotent. | G / Pass 12 (undo) |
| P12-K12 | `epiphany-ops` K | Cross-region slur spanning permission: `Region.permits_spanning_slurs` (schema major 1, P12-K7) gates the CreateCrossCutting(Slur) advisory, but which region governs a slur whose endpoints lie in *different* regions is under-specified. Implemented as conservative **AND** (a boundary is permeable only when both endpoint regions permit); "the start region governs" or "either side" are equally defensible. The advisory is authoring-only and never alters reduction, so the choice is not byte-affecting. Ratify one reading. | G / Pass 12 (validation) | | ~~P12-K12~~ **RATIFIED (AND) (G-pass 2026-07-07; see PASS12_RATIFICATION_LOG)** | `epiphany-ops` K | Cross-region slur spanning permission: `Region.permits_spanning_slurs` (schema major 1, P12-K7) gates the CreateCrossCutting(Slur) advisory, but which region governs a slur whose endpoints lie in *different* regions is under-specified. Implemented as conservative **AND** (a boundary is permeable only when both endpoint regions permit); "the start region governs" or "either side" are equally defensible. The advisory is authoring-only and never alters reduction, so the choice is not byte-affecting. Ratify one reading. | G / Pass 12 (validation) |
| ~~P12-I7~~ **RATIFIED (schema-major-1 track, 2026-07-06; see PASS12_RATIFICATION_LOG)** | `epiphany-engrave` I | Page geometry had no graph home: the spec named `Canvas.layout_defaults` ("paper size, margins") but defined no type, and adding a `Canvas` field is a schema-major change under the companion's frozen-layout rule. Casting-off therefore uses an engraver-side `PageGeometry` default (A4 at an 8mm staff: 105x148.5 ss, 7.5 ss margins). **Phase A of the schema-major-1 bump defines the type** (`CanvasLayoutDefaults { page_size: CanvasSize, margins: CanvasMargins }` in staff spaces, A4/8mm default) and ratifies its v1 wire form (Binary Format 0.3.0); the **graph home lands in code in Phase C** (`Canvas` gains the field), after which the engraver reads it (Phase C) — until fully landed, solvers MAY default. | G (graph model, schema-major) | | ~~P12-I7~~ **RATIFIED (schema-major-1 track, 2026-07-06; see PASS12_RATIFICATION_LOG)** | `epiphany-engrave` I | Page geometry had no graph home: the spec named `Canvas.layout_defaults` ("paper size, margins") but defined no type, and adding a `Canvas` field is a schema-major change under the companion's frozen-layout rule. Casting-off therefore uses an engraver-side `PageGeometry` default (A4 at an 8mm staff: 105x148.5 ss, 7.5 ss margins). **Phase A of the schema-major-1 bump defines the type** (`CanvasLayoutDefaults { page_size: CanvasSize, margins: CanvasMargins }` in staff spaces, A4/8mm default) and ratifies its v1 wire form (Binary Format 0.3.0); the **graph home lands in code in Phase C** (`Canvas` gains the field), after which the engraver reads it (Phase C) — until fully landed, solvers MAY default. | G (graph model, schema-major) |
| ~~P12-I8~~ **RATIFIED (schema-major-1 track, 2026-07-06; core_spec `req:layoutir:break-satisfaction`)** | `epiphany-engrave` I | Break-constraint satisfaction predicate: implemented as "a `SystemBreakAt`/`PageBreakAt` is satisfied iff the final layout starts a system/page at that slot" (a region-first slot is trivially satisfied). Ch7/Ch9 never define satisfaction for break constraints; ratify the predicate. | G / Pass 12 (solver) | | ~~P12-I8~~ **RATIFIED (schema-major-1 track, 2026-07-06; core_spec `req:layoutir:break-satisfaction`)** | `epiphany-engrave` I | Break-constraint satisfaction predicate: implemented as "a `SystemBreakAt`/`PageBreakAt` is satisfied iff the final layout starts a system/page at that slot" (a region-first slot is trivially satisfied). Ch7/Ch9 never define satisfaction for break constraints; ratify the predicate. | G / Pass 12 (solver) |
| ~~P12-I9~~ **RATIFIED (schema-major-1 track, 2026-07-06; core_spec `req:layoutir:break-origin-attribution`)** | `epiphany-layout-ir` I | Honouring a user break must attribute the decision to its override (`DecisionSource::UserOverride(id)`), but constraints carry no override identity; implemented via a `ConstrainedLayoutIR.break_origins` sidecar populated by `to_constrained`. Bless the sidecar or widen the normalized constraint record. | G / Pass 12 (solver) | | ~~P12-I9~~ **RATIFIED (schema-major-1 track, 2026-07-06; core_spec `req:layoutir:break-origin-attribution`)** | `epiphany-layout-ir` I | Honouring a user break must attribute the decision to its override (`DecisionSource::UserOverride(id)`), but constraints carry no override identity; implemented via a `ConstrainedLayoutIR.break_origins` sidecar populated by `to_constrained`. Bless the sidecar or widen the normalized constraint record. | G / Pass 12 (solver) |

View File

@ -103,3 +103,67 @@ conservative **AND** (a boundary is permeable only when both endpoint regions se
`permits_spanning_slurs`); a "the start region governs" or "either side" reading `permits_spanning_slurs`); a "the start region governs" or "either side" reading
is equally defensible. Tracked for ratification; the advisory is authoring-only is equally defensible. Tracked for ratification; the advisory is authoring-only
and never alters reduction, so the choice is not byte-affecting. and never alters reduction, so the choice is not byte-affecting.
## G-pass tranche (2026-07-07) — the batch pass
The full G-ratification of the accumulated batch: all 28 open rows retired in
one deliberate pass (worklist: `PASS12_WORKLIST.md`). Four rows carried genuine
forks and were decided by the project lead; three rows defer to *named* landing
sites; the rest bless implemented, DECISIONS-recorded readings. Spec-first: the
normative text landed with this tranche; the small code tranche (H7 surfacing,
K3/K9 reasons, C4 variant) follows in its own commit.
**Key decisions (project lead, 2026-07-07):** P12-K12 cross-region slur
permission = **AND** (both endpoint regions); P12-H7 authored annotations for
inference-ineligible events **surface** in derived annotations; P12-K4
ResolveConflict = **no supersede** (earliest applied resolve governs
universally; re-resolution is a future dedicated op; no `TypedObjectId`
Conflict kind); P12-K8 **genesis outside the operation set** (create-score/
canvas slots retired, not "unavailable").
| Item | Disposition | Spec locus | Authority followed |
|---|---|---|---|
| P12-H1 spelling algorithm id | **adopt**`"default"` = Temperley-style line-of-fifths preference v1, ratified normative (`req:pitch:spelling-algorithm`); profile-declared disposition; no silent substitution. CONFORMANCE.md caveat dropped | core_spec Ch2 §Spelling Pre-Pass; Ch4 open question narrowed; Ch1 + App. D open-hooks lists updated | `epiphany-core/src/prepass.rs` |
| P12-H2 key/clef model | **defer (premise stale, verified)** — the content model *exists* (I-0: `Clef`, `KeySignature`, content-bearing changes) and layout consumes it; what remains is algorithmic. Key-aware spelling → a spelling-algorithm **v2** (versioned rev, deterministically invalidates derived output); key-aware accidental display / cancelling naturals → the notation-refinement backlog (major-2 / Standard-tier neighborhood) | `req:pitch:spelling-algorithm` states v1 does not consult declared keys | verified: 0 `KeySignature` refs in `prepass.rs`; `PlacedKeySignature` in layout-ir |
| P12-H3 chromatic-run convention | **adopt** — enharmonic choice absent tonal context is a property of the *versioned* algorithm; v1 = convention-as-tiebreak only; voice-leading refinement = future version, not a spec hole | `req:pitch:spelling-algorithm` | `prepass.rs` centre-of-gravity rule |
| P12-H4 decomposition scope bounds (+P12-C5 folded) | **adopt** — the five v1 bounds (single governing meter; barline origin; dyadic compound grouping; no nested/cross-beat tuplets; `MAX_DOTS = 1`) become *declared normative bounds* of `DecompositionAlgorithmId "default"` v1 (`req:time:decomposition-algorithm`); a wider algorithm is a version bump. C5: `SetTimeSignature` reduction semantics already pinned (catalog §Meter and Tempo Overwrites); the derived-notation gap is subsumed by the single-meter bound | core_spec Ch3 §Decomposition Pre-Pass | `prepass.rs` integer-grid splitter; ops `reduce.rs` meter LWW |
| P12-H5 aleatoric spelling | **adopt (open question closed)** — spelling is region-time-model-independent; no aleatoric-specific pass exists or is required; stated in the v1 algorithm definition | `req:pitch:spelling-algorithm` | `prepass.rs` (region-independent by construction) |
| P12-H6 decomposition precedence | **decide: FIXED** — the fixed default order (`UserChosen > Imported > Propagated > Inferred`, canonical attachment order tie-break) is ratified; *not* configurable (a configurable order = new canonical `Score` field = schema-major with no consumer). "Same precedence machinery" reworded to "same source-rank discipline" | core_spec Ch3 §Notational Decomposition | `prepass.rs::resolve_decomposition` |
| P12-H7 authored-uninferred surfacing | **decide: SURFACE (code follows)** — derived annotations MUST report the winning authored attachment for inference-ineligible targets, both pre-passes; taxonomy counts them distinctly (`req:pitch:authored-uninferred`). Derived-annotation-only: no canonical-byte impact | core_spec Ch2 (new requirement) + Ch3 cross-ref | decision reverses the implemented override-only mirror; code tranche implements |
| P12-K1 RespellPitch migration | **adopt** — context-recovery + `Irreversible` → read-only is the *long-term* disposition; no richer v0 corpus required (none exists). Open-question box → ratified migration note | operation_catalog §RespellPitch | `epiphany-ops/src/migrate.rs` |
| P12-K2 Transpose algebra | **defer (named site) + pin** — prototype semantics (CMN alteration shift, documented `i8` saturation) declared v1 behavior; faithful interval representation = *payload schema-major* landing with the Ch4 tuning catalog (Push 4) | operation_catalog §Transpose | `reduce.rs` transpose arm |
| P12-K3 system-derived content rewrite | **decide: REFUSE (code follows)** — reduction MUST refuse intrinsic-content rewrites of `SYSTEM_DERIVED`-namespace pitches; appended `PreconditionFailureReason::SystemDerivedContentImmutable` (12). Core Ch5 states immutability; catalog pins the precondition for ModifyEvent + ModifyIdentifiedPitch | core_spec Ch5 §System-Derived Identifiers; operation_catalog §ModifyEvent; binary_format vocab (12) | protects Invariant 11; code tranche implements |
| P12-K4 ResolveConflict beyond concurrent | **decide: NO SUPERSEDE** — earliest-applied-resolve governs universally; causally-later differing resolves + any resolve against `Dismissed` read `AlreadyApplied`; re-resolution = future `ReopenConflict`-class op; no `TypedObjectId` Conflict kind (meta-conflict names both resolvers) | operation_catalog §ResolveConflict | `reduce.rs` resolve arm (as implemented) |
| P12-K5 equivocation selection policy | **defer (named site)** — v1 profiles declare *no* selection function (now stated); the hook's definition belongs to the Profile Conformance companion; no reducer policy hook until then | operation_catalog §ResolveEquivocation rationale | deliberate absence in `reduce.rs` |
| P12-K6 equivocation edge semantics | **adopt** — single-pass promotion (no fixpoint); quarantined resolves never govern (verified in `reduce.rs` pre-pass comment + code); pending-by-causal-gaps resolves still govern (set-level); invalid-target/chosen no-op keeps `TargetMissing` (dedicated reason rejected — verdict does not change caller behavior) | operation_catalog §ResolveEquivocation (new Edge semantics block) | `reduce.rs` promotion pre-pass |
| P12-K8 create score/canvas | **decide: GENESIS OUTSIDE OPS** — root + canvas are structural givens; genesis = empty-document constructor + bundle creation, normative; K1 slots *retired* (no kind will be assigned); revisit only under an addressable multi-canvas major | core_spec Ch5 §The Canvas; operation_catalog K1 chapter + Conformance Profiles | `Score::empty` + bundle creation path |
| P12-K9 differing-value re-creates | **decide: DEDICATED REASON (code follows)** — appended `PreconditionFailureReason::RecreateContentMismatch` (13) replaces the misnaming `TargetMissing` reuse at every differing-value re-create site (CreateStaff, carried TimeSignature, container creates) | operation_catalog §CreateStaff + §Meter and Tempo Overwrites; binary_format vocab (13) | code tranche implements |
| P12-K10 undo strand-blocks | **adopt (bless reuse)** — a StrictInverse strand-block *is* a transaction-scoped conflict; `TransactionConflict` reuse ratified; detail lives in the conflict record | operation_catalog §UndoTransaction | `undo.rs` |
| P12-K11 undo idempotence asymmetry | **adopt** — restorations are ordinary chain writes (no distinguished undo provenance); second-undo conflict + idempotent absence-restores are normative; revisit only under undo-as-operation | operation_catalog §UndoTransaction | `undo.rs` write chains |
| P12-K12 cross-region slur governance | **decide: AND** — boundary permeable only when both endpoint regions permit; advisory-only, never byte-affecting | core_spec Ch5 (after `Region` listing); operation_catalog §CreateCrossCutting | `validate.rs` conservative AND (as implemented) |
| P12-C1 multi-source cue | **adopt** — cascade on *any* source deletion is normative; rationale prose fixed to match ("losing any source breaks quotation integrity"); truncate-while-any-survives recorded as rejected | core_spec §Re-Anchoring Rule Table (Cue row) | `reduce.rs` cue cascade |
| P12-C2 Range truncate | **adopt** — truncate = dead event-anchored endpoint moves to its containing region's edge (start→Start, end→End, zero offset) | core_spec §Re-Anchoring Rule Table (graphic-gesture row) | `reduce.rs` re-anchor ledger |
| P12-C3 annotation orphaning | **adopt** — orphaning is the sanctioned outcome for wall-clock/indeterminate spans inexpressible as stored `Range` anchors; an expressible form is future model work | core_spec §Re-Anchoring Rule Table (annotation row) | `reduce.rs` |
| P12-C4 same-canvas reason | **decide: APPEND (code follows)**`ReanchorReason::SameCanvasNearer` appended at discriminant **6** (5 was already owned by `DeclaredByExtension`); rank-4 survivors record it instead of `ExplicitFallback` | core_spec `ReanchorReason` listing + note; binary_format vocab (6) | code tranche implements |
| P12-E4 barrier matching | **adopt** — target-free ops (`SetMetadata`, `DeclareTransaction`) match score-wide barriers only; opaque `Registered` ops match fully conservatively (`req:format:barrier-matching`) | core_spec Ch8 | `editor-core` barrier gate |
| P12-E5 unsafe-edit tombstone | **adopt semantics + defer encoding (named site)**`req:format:unsafe-tombstone`: immediate deactivation of the crossed extension's remaining barriers; durable record MUST land at next commit; `required = true` → read-only for dependents. The manifest-side *byte encoding* is a new binary_format open question (manifest frozen at major 0 → blob-layer or new chunk kind; next bundle-format tranche) | core_spec Ch8; binary_format §extension blobs (open question) | `editor-core::extensions_requiring_tombstone()` (producer exists) |
| P12-I4 constraint strength | **adopt** — strength is *kind-determined*, no instance field (`req:solver:kind-strength`): breaks by `BreakKind` (Hard→Required, Soft→Preferred{1.0}), core families Required, `Registered` conservative Required; future families declare strength in their definitions. Deliberate Standard-tier design input | core_spec Ch9 §Strength Levels | `layout-ir` normalization |
| P12-I5 sub-conformant report | **adopt**`SolvedWithWarnings` + `satisfied_hard_constraints == false` + warning is the sanctioned constraints-present-but-unevaluated report; the one renderable status with unsatisfied-hard, because the field reports *evaluated* satisfaction (`req:solver:subconformant-report`) | core_spec Ch9 §SolveReport | `layout-ir` stub solver |
| P12-I6 Minimal constraint floor | **adopt** — the implemented emission set (successive-notehead no-collision chains + per-glyph containment + user-break constraints) is the normative Minimal floor (`req:layoutir:constraint-floor`); higher-tier floors defined when those tiers land | core_spec Ch7 §ConstrainedLayoutIR | `constrained.rs` emission |
**Ride-along staleness fix:** the Ch8 `OperationKindTag` listing gained the
eleven appended tags the code has carried since M2/Phase-3 (append-only
vocabulary; the listing had drifted).
**Version movements.** Operation Catalog 0.5.0 → 0.6.0. Binary Format
0.3.0 → 0.4.0 (vocab appends 12/13/6 + the E5 encoding open question). Core
spec: revision-history row "Pass 12 G-ratification (the batch pass)"; two
open-question boxes replaced by ratified requirements (spelling,
decomposition), one narrowed (Ch4 spelling-catalog), one added
(binary_format E5 encoding). All three PDFs rebuilt clean, zero undefined
references.
**Code tranche (follows this commit):** H7 authored-only surfacing + taxonomy
buckets (`prepass.rs`); K3 `SystemDerivedContentImmutable` (12); K9
`RecreateContentMismatch` (13); C4 `SameCanvasNearer` (6) — each with
regression tests and wire goldens.

297
spec/PASS12_WORKLIST.md Normal file
View File

@ -0,0 +1,297 @@
# Pass 12 — G-Ratification Worklist (the batch pass)
*Purpose: retire the accumulated `PASS12_BATCH.md` backlog — 28 open rows spanning
six agents — in one deliberate G pass, before the data-model schema-major-2 push
starts consuming graph-model decisions (H2, K8) and the Standard-tier solver push
starts consuming solver-contract decisions (I4/I5/I6).*
*Scope: a **spec revision pass** plus a small, explicitly-listed code tranche.
The architecture stays frozen. Most rows bless an implemented, DECISIONS-recorded
reading; four rows carried genuine forks and were decided by the project lead on
2026-07-07 (see "Key decisions" below); three rows defer to named future tracks
with rationale.*
*Working rule (Pass-11 precedent): **adopt** = bless the implementation's existing
choice in normative spec text. **decide** = a real fork, resolved and recorded
here. **defer** = punt to a *named* landing site with rationale — never a silent
drop. Every disposition lands in `PASS12_RATIFICATION_LOG.md`; every retired row
is struck through in `PASS12_BATCH.md` citing its disposition.*
---
## Key decisions this pass (project lead, 2026-07-07)
| Row | Decision |
|---|---|
| **P12-K12** | Cross-region slur spanning permission = **AND** (both endpoint regions must permit). As implemented; advisory-only, never byte-affecting. |
| **P12-H7** | Authored spelling/decomposition attachments on inference-ineligible events **surface in derived annotations** (authored-only resolution path + new taxonomy buckets). Code work in both pre-passes. |
| **P12-K4** | ResolveConflict: **no supersede** — earliest applied resolve governs universally (concurrent *and* causally-later); later resolves and resolves against `Dismissed` read `AlreadyApplied`. Re-resolution is a future dedicated operation. No `TypedObjectId::Conflict` kind; the meta-conflict names both resolver op ids, as built. |
| **P12-K8** | **Genesis outside the operation set** — the document root and canvas are structural givens (`Score::empty` + bundle creation), never op-minted. The K1 create-score/create-canvas slots are retired as *deliberately outside the operation set*, not "unavailable". Revisit only if multi-canvas becomes a real major-2+ feature. |
---
## Bucket 1 — Adopt-and-pin (spec text only; 19 entries / 20 rows)
No code changes; each blesses a deterministic implemented reading. Golden/test
anchors already exist for the byte-adjacent ones.
### 1.1 — P12-H1 — `SpellingAlgorithmId::Default` ratified
- **Spec locus:** core_spec Ch 2 (spelling pre-pass) + Appendix D §Open Algorithm Hooks.
- **Ratify:** `"default"` = the Temperley-style line-of-fifths preference algorithm,
v1 (`epiphany-core/src/prepass.rs`). The id is now the *spec's*, not the crate's
proposal. `CONFORMANCE.md` already declares it; drop its "pending ratification" caveat.
### 1.2 — P12-H3 — chromatic-run convention is algorithm-defined
- **Spec locus:** core_spec Ch 2, same section as 1.1.
- **Ratify:** enharmonic choice in the absence of tonal context is a property of the
*versioned* spelling algorithm, not spec-pinned; v1's centre-of-gravity rule with
the ascending-sharps/descending-flats convention **as tiebreak only** is the
ratified v1 behavior. A voice-leading refinement = a future algorithm version, not
a spec hole.
### 1.3 — P12-H4 (+ P12-C5 folded) — decomposition v1 scope bounds
- **Spec locus:** core_spec Ch 3 (decomposition pre-pass) + Appendix D hooks;
cross-ref operation_catalog §SetTimeSignature for C5.
- **Ratify:** the v1 `DecompositionAlgorithmId "default"` bounds become *declared
normative bounds of the versioned algorithm*: single governing meter per region;
region origin assumed a barline (no anacrusis); dyadic compound-meter grouping;
no tuplet nesting / cross-beat members; `MAX_DOTS = 1`. A wider algorithm is a
version bump that deterministically invalidates derived output (the derived-
annotation model already guarantees this).
- **C5 disposition:** reduction semantics of a mid-region `SetTimeSignature` are
already pinned (catalog §Meter and Tempo Overwrites); the derived-notation gap is
*subsumed by the H4 single-meter bound* — one log entry covers both rows.
### 1.4 — P12-H5 — aleatoric spelling open question closed
- **Spec locus:** core_spec Ch 2 open-question box (aleatoric regions).
- **Ratify:** spelling is region-time-model-**independent** (pitch identity does not
depend on the time model); there is no aleatoric-specific spelling pass. Close the
open question with that answer; aleatoric-aware refinements are algorithm-version
territory.
### 1.5 — P12-H6 — decomposition precedence is FIXED (decided: not configurable)
- **Spec locus:** core_spec Ch 3 §decomposition precedence.
- **Ratify:** decomposition precedence is the fixed default source order
(`UserChosen > Imported > Propagated > Inferred`, canonical attachment order as
tie-break) — **not** configurable. Rationale: configurability requires a new
canonical `Score` field (a schema-major) with no consumer; `DecompositionAttachment`
deliberately carries no `priority`. Revisit at a future major only if a use case
appears. The "same precedence machinery as spelling" sentence is reworded to "same
source-rank discipline" (spelling's *configurability* is spelling-specific).
### 1.6 — P12-K1 — v0 RespellPitch migration fallback
- **Spec locus:** operation_catalog §RespellPitch, §Migration.
- **Ratify:** context-recovery (explicit per-pitch attachment whose canonical bytes
hash to the fingerprint) + `MigrationError::Irreversible` → bundle read-only when
absent is the **long-term** disposition. No richer v0 corpus will be required
(there is no production v0 corpus).
### 1.7 — P12-K4 — ResolveConflict beyond the concurrent case *(decided above)*
- **Spec locus:** operation_catalog §ResolveConflict; core_spec Ch 6 §Conflict Records.
- **Ratify:** earliest-applied-resolve-governs applies to causally-later resolves
(they read `AlreadyApplied`); resolves against `Dismissed` read `AlreadyApplied`;
intentional re-resolution is out of the v1 operation set (a future `ReopenConflict`-
class op is the sanctioned path). Conflict records get **no** addressable
`TypedObjectId` kind; the meta-conflict names both resolver operation ids.
### 1.8 — P12-K6 — ResolveEquivocation edge semantics
- **Spec locus:** operation_catalog §ResolveEquivocation.
- **Ratify as implemented:** single-pass promotion (a promoted candidate that is
itself a resolve does not govern a further promotion — no fixpoint); the set-level
rule (a resolve held pending by its own causal gaps still *governs promotion* while
its own effect stays pending); invalid-target/chosen no-ops reuse `TargetMissing`
(consistent with the K9 disposition below, which scopes its new reason to
differing-value *re-creates* only). **Execution note:** read
`epiphany-ops` and write down the implemented quarantine interaction verbatim
(may a quarantined resolve govern?) — the ratification text records what the code
does; if the code turns out to have no defined behavior there, the text says
"quarantined resolves are excluded from governing" only if a test proves it.
### 1.9 — P12-K8 — genesis outside the operation set *(decided above)*
- **Spec locus:** operation_catalog K1 chapter (retire the two slots) + core_spec
Ch 5 (root/canvas genesis note) + Ch 6 (operation-set completeness statement).
### 1.10 — P12-K10 — undo strand-blocks keep `TransactionConflict`
- **Spec locus:** operation_catalog §UndoTransaction.
- **Ratify:** a StrictInverse strand-block (refusing to tombstone a minted object
still referenced by a live non-member) **is** a transaction-scoped conflict;
`ConflictKind::TransactionConflict` reuse is blessed — no new conflict kind. The
refusal detail lives in the conflict record's affected-objects/description, as built.
### 1.11 — P12-K11 — undo idempotence asymmetry ratified
- **Spec locus:** operation_catalog §UndoTransaction.
- **Ratify:** an undo's value restorations are ordinary chain writes by the undo op
(no distinguished provenance); a second undo of the same transaction sees the first
as superseding (`Conflicted` under StrictInverse, skipped under BestEffort) while
absence-restorations repeat idempotently. The asymmetry is documented normative
behavior. Revisit only under the deferred undo-as-operation (streaming-consistent
undo) track, which subsumes it.
### 1.12 — P12-K12 — cross-region slur permission = AND *(decided above)*
- **Spec locus:** core_spec validation/advisory section that defines the
`permits_spanning_slurs` advisory (schema-major-1 Phase A text) + catalog
§CreateCrossCutting advisory note.
- **Ratify:** a region boundary is permeable to a spanning slur only when **both**
endpoint regions permit. Advisory-only; never alters reduction.
### 1.13 — P12-C1 — multi-source cue re-anchoring = cascade
- **Spec locus:** core_spec §Re-Anchoring Rule Table (Cue row rationale).
- **Ratify:** the table's action column is normative as written — **any** source
deletion cascade-deletes the cue (like Tie). Fix the rationale prose to match
("a cue that loses any source loses its quotation integrity"); truncate-while-any-
survives is a rejected alternative, recorded in the log.
### 1.14 — P12-C2 — graphic-gesture Range "truncate" defined
- **Spec locus:** core_spec §Re-Anchoring Rule Table (graphic gesture row).
- **Ratify:** a dead event-anchored range endpoint moves to its containing region's
edge — start endpoint → region Start, end endpoint → region End, zero offset. As
implemented.
### 1.15 — P12-C3 — inexpressible reconstructed ranges orphan
- **Spec locus:** core_spec §Re-Anchoring Rule Table (analytical annotation row).
- **Ratify:** a wall-clock (region-relative) or indeterminate event span that cannot
be expressed as a stored `Range` anchor **orphans** (recorded as such); an
expressible form is future model work, not required.
### 1.16 — P12-E4 — conservative barrier matching
- **Spec locus:** core_spec Ch 8 (edit barriers / extension declarations).
- **Ratify:** operations with no graph target (`SetMetadata`, `DeclareTransaction`)
are matched by **score-wide barriers only**; opaque `Registered` operations match
**fully conservatively**. As implemented in editor-core's barrier gate.
### 1.17 — P12-I4 — constraint strength is kind-determined
- **Spec locus:** core_spec Ch 9 (normalized constraint form) + Ch 7 `LayoutConstraint`.
- **Ratify:** no per-instance strength field. Strength is determined by constraint
kind: break constraints by `BreakKind` (Hard → Required, Soft → Preferred{1.0});
the other core families Required; `Registered` conservatively Required. Future
(Standard-tier) constraint families **declare their strength in their normative
definition** — the channel is the kind, not the instance. This is a deliberate
Push-3 design input.
### 1.18 — P12-I5 — sub-conformant solver report shape
- **Spec locus:** core_spec Ch 9 (SolveStatus semantics; next to the Pass-12-tranche-1
`SolverTier::Stub` text).
- **Ratify:** a below-conformance passthrough solver reports constraints-present-but-
not-evaluated as `SolvedWithWarnings` + `satisfied_hard_constraints == false` + a
dedicated warning. Renderable, honest, makes no conformance claim.
### 1.19 — P12-I6 — the Minimal-tier constraint-emission floor
- **Spec locus:** core_spec Ch 9 (spacing-pass requirements).
- **Ratify:** the normative Minimal floor = successive-notehead-column no-collision
chains + per-glyph region containment + user-break constraints, exactly the
implemented emission set. Standard's floor is defined when the Standard tier lands
(Push 3). Makes the Minimal acceptance surface testable.
---
## Bucket 2 — Decide-then-build (spec text + code; 5 rows)
Spec-first discipline: the normative text lands in the same pass, the code follows
in a separate commit, each change regression-tested.
### 2.1 — P12-H7 — surface authored annotations for ineligible events *(decided above)*
- **Spec:** core_spec Ch 2 + Ch 3 pre-pass sections — derived annotations include, for
events/pitches the algorithm produces no output for, the winning **authored**
attachment (same source-rank discipline); taxonomy counts them in dedicated
authored-only buckets.
- **Code:** `epiphany-core/src/prepass.rs` — authored-only resolution path in both
`resolve_spelling`-adjacent and `resolve_decomposition` surfaces; new
`TaxonomyReport` buckets (e.g. `spellings_authored_uninferred`,
`decompositions_authored_uninferred`), serialized into the derivation fingerprint
(derived annotations only — **no canonical-byte impact**; the fingerprint is not
canonical state). Regression tests: an authored attachment on an ungriddable event
surfaces; an outranked one does not; fingerprint changes deterministically.
### 2.2 — P12-K3 — refuse content rewrites of SYSTEM_DERIVED pitches
- **Spec:** operation_catalog §ModifyEvent + §Identified-Pitch Operations gain the
precondition; core_spec Ch 5 Invariant 11 rationale cross-ref.
- **Code:** reduction-time precondition — a `ModifyEvent`/`ModifyIdentifiedPitch`
that would rewrite the *intrinsic content* of a `SYSTEM_DERIVED` pitch refuses as a
clean no-op with a **new appended** `PreconditionFailureReason` (proposed:
`SystemDerivedContentImmutable`). Append-only vocabulary = sanctioned minor
evolution (precedent: `TempoMapMalformed = 11`). Tests: direct refusal, reduce ==
reduce_onto agreement, wire golden for the new discriminant.
### 2.3 — P12-K9 — dedicated reason for differing-value re-creates
- **Spec:** operation_catalog (CreateStaff, carried TimeSignature, container creates).
- **Code:** appended `PreconditionFailureReason` (proposed: `RecreateContentMismatch`)
replacing the misnamed `TargetMissing` on live-id-re-carried-with-different-content
refusals. Same test discipline as 2.2.
### 2.4 — P12-C4 — appended `ReanchorReason::SameCanvasNearer`
- **Spec:** core_spec §Re-Anchoring Rule Table (rank-4 survivor recording).
- **Code:** append the discriminant (after `ExplicitFallback = 4`; before
`DeclaredByExtension`'s registered space — confirm the discriminant table allows a
clean append; if `DeclaredByExtension` already owns 5, take 6 and record why).
Rank-4 (same-canvas) survivors record it instead of `ExplicitFallback`. Wire golden
+ one re-anchoring test updated.
### 2.5 — P12-E5 — unsafe-edit tombstone: semantics now, encoding deferred
- **Spec (this pass):** core_spec Ch 8 ratifies the *semantics*: crossing a barrier
via `apply_unsafe` immediately deactivates the extension's remaining barriers for
the session; the crossing MUST be durably recorded at the next bundle commit; a
tombstoned `required = true` extension makes the bundle open **read-only** for
writers that honor the extension (they can no longer trust its invariants).
- **Deferred (named site):** the manifest-side *encoding* of the tombstone record —
the manifest is major-0-forever (schema-major-1 design decision), so the record
must ride the extension-declaration blob layer or a new chunk kind; that design
belongs to the next bundle-format tranche. Add an `openquestion` box to
`binary_format.tex` naming the constraint. Editor-core's
`extensions_requiring_tombstone()` is the implemented producer awaiting that
consumer.
---
## Bucket 3 — Defer-with-rationale (3 rows, named landing sites)
### 3.1 — P12-H2 — key/clef model: premise stale, remainder deferred
- **Finding (verified 2026-07-07):** the row's premise is stale — the content model
*exists* (I-0: `Clef`, `KeySignature`, content-bearing `ClefChange`/
`KeySignatureChange`) and layout consumes it (`PlacedKeySignature`, `active_clef`).
What remains is algorithmic: the spelling pre-pass never consults declared keys
(0 references in `prepass.rs`), and notation does no key-aware accidental
suppression / cancelling naturals.
- **Defer:** key-aware spelling → a **spelling algorithm v2** (versioned-algorithm
rev, invalidates derived output deterministically — no spec hole); key-aware
accidental display + cancelling naturals → the **notation/engraving refinement
backlog** (major-2 / Standard-tier neighborhood). Batch row struck with the
narrowed statement.
### 3.2 — P12-K2 — Transpose interval algebra → Chapter-4 tuning track
- **Defer:** the faithful interval representation (diatonic/chromatic, octave/nominal
renormalization, non-CMN pitch spaces) lands with the tuning catalog (Push 4).
**Pin now (one sentence each):** the v1 payload's `chromatic_steps: i32` semantics
= CMN alteration shift with documented `i8` saturation — a declared prototype whose
replacement is a *payload schema-major* under the companion's evolution rule; and
Transpose stays excluded from undo inversion (already documented).
### 3.3 — P12-K5 — profile-declared equivocation selection → profile track
- **Defer:** the third resolution path (profile-declared deterministic selection
function) stays unpinned; v1 profiles declare **none** (ratify that sentence in the
catalog §ResolveEquivocation rationale). The hook's definition belongs to the
Profile Conformance companion, which does not exist yet — named landing site.
---
## Execution plan
Order of work (each tranche gated; spec-first before code):
1. **Tranche A — core_spec pre-pass text** (H1, H3, H4+C5, H5, H6, H7-normative,
H2-narrowing): Ch 2/Ch 3 edits, two open-question boxes closed.
2. **Tranche B — operation_catalog text** (K1, K4, K6, K8, K10, K11, K12, K2-pin,
K5-pin, K3/K9-normative): catalog version bump 0.5.0 → 0.6.0.
3. **Tranche C — core_spec re-anchoring + barriers + solver** (C1, C2, C3, C4-normative,
E4, E5-semantics, I4, I5, I6) + binary_format openquestion (E5 encoding).
4. **Both PDFs rebuild clean** (lualatex core_spec; xelatex catalog; check
binary_format too), zero undefined refs. → **Commit 1 (spec).**
5. **Tranche D — code** (H7 surfacing + taxonomy; K3 + K9 reasons; C4 variant), full
gate (fmt, clippy -D warnings, workspace tests, conformance scale 1), review pass,
→ **Commit 2 (code).**
6. **Process trail:** PASS12_RATIFICATION_LOG "G-pass tranche" section (dispositions
table, version movements, key decisions); PASS12_BATCH rows struck (28 → 0 open);
crate DECISIONS cross-refs (core, ops, layout-ir, editor-core); CONFORMANCE.md
H1 caveat dropped. Rides Commit 1/2 as appropriate.
After this pass the batch is **empty** and Push 2 (data-model major 2) starts with
no pending graph-model questions: H2 narrowed, K8 decided, H6 decided.

Binary file not shown.

View File

@ -235,7 +235,7 @@
{\Large\scshape\color{epiphanyslate}Binary Format}\\[6pt] {\Large\scshape\color{epiphanyslate}Binary Format}\\[6pt]
{\large\itshape\color{epiphanyslate}A companion to the Core Specification}\\[14pt] {\large\itshape\color{epiphanyslate}A companion to the Core Specification}\\[14pt]
{\color{epiphanygold}\rule{3in}{0.8pt}}\\[24pt] {\color{epiphanygold}\rule{3in}{0.8pt}}\\[24pt]
{\normalsize\color{epiphanyink}Version 0.3.0 --- Phase 2/3 (canonical wire format: primitives through bundle physical layout + K0 and Phase-3-tranche payload framing; schema major~1 data-model expansion)}\\[4pt] {\normalsize\color{epiphanyink}Version 0.4.0 --- Pass-12 G-ratification (appended effect-vocabulary discriminants; unsafe-edit tombstone encoding open question)}\\[4pt]
{\small\color{epiphanyslate}Normative for the byte layouts it defines} {\small\color{epiphanyslate}Normative for the byte layouts it defines}
\vfill \vfill
\end{titlepage} \end{titlepage}
@ -1562,7 +1562,9 @@ trailing bytes are decode errors.
\tablenums{8} ExtensionPrecondition \cat{} id (16 BE); \tablenums{8} ExtensionPrecondition \cat{} id (16 BE);
\tablenums{9} Registered \cat{} id (16 BE); \tablenums{9} Registered \cat{} id (16 BE);
\tablenums{10} ContainerNotEmpty; \tablenums{10} ContainerNotEmpty;
\tablenums{11} TempoMapMalformed. \\ \tablenums{11} TempoMapMalformed;
\tablenums{12} SystemDerivedContentImmutable (Pass~12, P12-K3);
\tablenums{13} RecreateContentMismatch (Pass~12, P12-K9). \\
\texttt{RepairRecord} & \texttt{RepairRecord} &
(struct) \texttt{kind} (\texttt{RepairKind}) \cat{} \texttt{target} (struct) \texttt{kind} (\texttt{RepairKind}) \cat{} \texttt{target}
(\texttt{TypedObjectId}). \\ (\texttt{TypedObjectId}). \\
@ -1581,7 +1583,10 @@ trailing bytes are decode errors.
\tablenums{0} SameVoiceNearer; \tablenums{1} SameStaffInstanceNearer; \tablenums{0} SameVoiceNearer; \tablenums{1} SameStaffInstanceNearer;
\tablenums{2} SameStaffNearer; \tablenums{3} SameRegionNearer; \tablenums{2} SameStaffNearer; \tablenums{3} SameRegionNearer;
\tablenums{4} ExplicitFallback; \tablenums{4} ExplicitFallback;
\tablenums{5} DeclaredByExtension \cat{} id (16 BE). \\ \tablenums{5} DeclaredByExtension \cat{} id (16 BE);
\tablenums{6} SameCanvasNearer (Pass~12, P12-C4: semantically the
rank-4 proximity variant; appended at 6 because 5 was already
owned by DeclaredByExtension). \\
\texttt{TupletCompensationKind} & \texttt{TupletCompensationKind} &
\tablenums{0} ReplaceWithRest; \tablenums{1} RewriteTuplets; \tablenums{0} ReplaceWithRest; \tablenums{1} RewriteTuplets;
\tablenums{2} CascadeDeleteTuplets. (No payload; distinct from the \tablenums{2} CascadeDeleteTuplets. (No payload; distinct from the
@ -2095,6 +2100,20 @@ are carried \emph{opaquely inside the canonical manifest}
must continue to parse them as \texttt{u64}. Their unification waits for a must continue to parse them as \texttt{u64}. Their unification waits for a
future major that revises the manifest (Section~\ref{sec:evolution:major1}). future major that revises the manifest (Section~\ref{sec:evolution:major1}).
\begin{openquestion}
\textbf{Unsafe-edit tombstone encoding (from P12-E5).} Core Chapter~8 now
ratifies the unsafe-edit tombstone \emph{semantics} (immediate deactivation of
the crossed extension's remaining barriers; a durable record \MUST{} land at
the next commit; \texttt{required = true} interaction). The manifest-side
\emph{byte encoding} of that record is unresolved --- and constrained: the
manifest schema is frozen at major~0, so the record cannot be a new manifest
field. Candidate channels: a marker inside the extension-declaration blob
layer (this chapter's regime-(b) surface), or a dedicated chunk kind
referenced from \texttt{preserved\_chunk\_roots}. To be designed in the next
bundle-format tranche; the editor-side producer
(\texttt{extensions\_requiring\_tombstone()}) already exists.
\end{openquestion}
\section{Framing} \section{Framing}
\label{sec:barriers:framing} \label{sec:barriers:framing}
@ -2775,6 +2794,15 @@ layouts of Section~\ref{sec:values:representative}.
ops read-only), and the total default-filling v0${\to}$v1 migration table. ops read-only), and the total default-filling v0${\to}$v1 migration table.
Clarifies that any field add is a major change regardless of Clarifies that any field add is a major change regardless of
\texttt{Option}-ness. \\ \texttt{Option}-ness. \\
\today & Effect vocabularies / Extension blobs & 0.4.0 --- Pass-12
G-ratification: appends \texttt{PreconditionFailureReason}
\tablenums{12} (\texttt{SystemDerivedContentImmutable}, P12-K3) and
\tablenums{13} (\texttt{RecreateContentMismatch}, P12-K9), and
\texttt{ReanchorReason} \tablenums{6} (\texttt{SameCanvasNearer},
P12-C4) --- schema-\emph{minor} appends under Chapter~\ref{ch:evolution};
no existing assignment changed. Adds the unsafe-edit tombstone
\emph{encoding} open question (from P12-E5; semantics ratified in core
Chapter~8). Semantics: Operation Catalog 0.6.0. \\
\bottomrule \bottomrule
\end{longtable} \end{longtable}

Binary file not shown.

View File

@ -406,18 +406,22 @@ Section~\ref{sec:det:open}:
the document have not yet been delivered: the document have not yet been delivered:
Appendix~\ref{app:deferred} catalogs them and distinguishes Appendix~\ref{app:deferred} catalogs them and distinguishes
them from accidentally missing content. them from accidentally missing content.
\item Several algorithms affect canonical state and have not \item Two algorithms affect canonical state and have not
yet received one of the dispositions in yet received one of the dispositions in
Appendix~\ref{app:determinism} Appendix~\ref{app:determinism}
Section~\ref{sec:det:open}: the spelling pre-pass, the Section~\ref{sec:det:open}: the tempo curve
notational-decomposition algorithm, the tempo curve integration algorithm and the
integration algorithm, and the
\texttt{wallclock\_to\_musical} root-finding algorithm. \texttt{wallclock\_to\_musical} root-finding algorithm.
Cross-implementation byte equality of canonical score state Cross-implementation byte equality of canonical score state
\MUSTNOT{} be claimed for outputs derived from these \MUSTNOT{} be claimed for outputs derived from these
algorithms until they are normatively specified or algorithms until they are normatively specified or
profile-declared (Appendix~\ref{app:determinism} profile-declared (Appendix~\ref{app:determinism}
Section~\ref{sec:det:layers}). Section~\ref{sec:det:layers}). The spelling pre-pass and the
notational-decomposition algorithm received the
profile-declared-by-versioned-identifier disposition in
Pass~12
(Requirements~\ref{req:pitch:spelling-algorithm}
and~\ref{req:time:decomposition-algorithm}).
\item Extension registry catalogs are referenced by typed \item Extension registry catalogs are referenced by typed
identifier but not enumerated here; they are delivered as identifier but not enumerated here; they are delivered as
separate, versioned registry documents. separate, versioned registry documents.
@ -1322,7 +1326,9 @@ The pre-pass operates as follows:
\item Collect all pitches in the score, partitioned by voice and \item Collect all pitches in the score, partitioned by voice and
measure. measure.
\item For each partition, in time order, resolve each pitch's spelling \item For each partition, in time order, resolve each pitch's spelling
using: using the applicable context inputs (which of these a given
algorithm version consumes is part of its versioned definition;
see Requirement~\ref{req:pitch:spelling-algorithm}):
\begin{enumerate} \begin{enumerate}
\item The active key signature for the staff. \item The active key signature for the staff.
\item The accidental context of prior pitches in the same measure \item The accidental context of prior pitches in the same measure
@ -1357,20 +1363,53 @@ annotations produced.
operation, which then outranks the pre-pass. operation, which then outranks the pre-pass.
\end{rationale} \end{rationale}
\begin{openquestion} \begin{requirement}
The melodic and harmonic context rules above are stated \label{req:pitch:spelling-algorithm}
abstractly. The specific algorithm---whether based on \textbf{Spelling algorithm disposition (ratified Pass 12).}
Longuet-Higgins line-of-fifths distance, Temperley's The spelling pre-pass receives the \emph{profile-declared by
preference rules, or another approach---is unresolved. The versioned identifier} disposition of Appendix~\ref{app:determinism}
choice affects canonical state and must therefore receive one Section~\ref{sec:det:open}. The reserved identifier
of the dispositions in Appendix~\ref{app:determinism} \texttt{SpellingAlgorithmId} \texttt{"default"} denotes, at
Section~\ref{sec:det:open}: delivery as a normative algorithm version~1, a Temperley-style line-of-fifths preference
in a Spelling Pre-Pass companion specification, algorithm: each partition's tonal context is estimated as a
profile-declared by versioned identifier, or explicitly marked centre of gravity on the line of fifths from the accidental,
non-canonical (in which case automatic spellings are advisory melodic, and harmonic context, and each pitch takes the
and \texttt{UserChosen} attachments are the only canonical enharmonic spelling nearest that centre. The ascending-runs-take-
spellings). sharps / descending-runs-take-flats convention participates
\end{openquestion} \emph{only as a tiebreak} within the centre-of-gravity rule; an
isolated chromatic run with no tonal context may therefore
receive the enharmonic the convention alone would not pick, and
a voice-leading refinement is a future algorithm version, not a
deviation. Which of the context inputs enumerated above an
algorithm version consumes is part of its versioned definition:
\texttt{"default"} version~1 does \emph{not} consult declared
key signatures (a key-aware refinement is a future version) and
is region-time-model-independent --- pitches in aleatoric and
proportional regions are spelled by the same rule as metric
ones, and no region-specific spelling pass exists. A profile
requesting any other identifier \MUST{} error;
implementations \MUSTNOT{} silently substitute a different
algorithm.
\end{requirement}
\begin{requirement}
\label{req:pitch:authored-uninferred}
\textbf{Authored annotations for inference-ineligible targets
(ratified Pass 12).}
A stored spelling attachment whose target the pre-pass produces
\emph{no} inferred spelling for (an inference-ineligible pitch)
\MUST{} still surface in the resolved derived annotations: the
winning attachment under the precedence configuration
(Section~\ref{sec:pitch:precedence}) is reported with its
authored provenance, exactly as it would have been had it
outranked an inferred spelling. An authored attachment is
precisely how a user notates what the algorithm cannot infer;
the derived-annotation surface \MUSTNOT{} render it invisible.
Annotation taxonomy counts these authored-only resolutions
distinctly from authored-over-inferred overrides. The same rule
applies to the decomposition pre-pass
(Section~\ref{sec:time:notrhythm}).
\end{requirement}
\subsection{Absent Accidentals} \subsection{Absent Accidentals}
\label{sec:pitch:absent-accidental} \label{sec:pitch:absent-accidental}
@ -2188,15 +2227,32 @@ pub enum DecompositionSource {
\end{lstlisting} \end{lstlisting}
The structure deliberately mirrors the spelling attachment model The structure deliberately mirrors the spelling attachment model
(Section~\ref{sec:pitch:spelling}): same sources, same precedence (Section~\ref{sec:pitch:spelling}): same sources, same source-rank
machinery, same pre-pass discipline. discipline, same pre-pass output model. Unlike spelling, decomposition
precedence is \emph{not configurable} (ratified Pass~12): the fixed
default source order \texttt{UserChosen} $>$ \texttt{Imported} $>$
\texttt{Propagated} $>$ \texttt{Inferred} applies, with the score's
canonical attachment order as tie-break among equal-rank authored
attachments; \texttt{DecompositionAttachment} carries no
\texttt{priority} field and the graph carries no
\texttt{DecompositionPrecedence} configuration. Making precedence
configurable would add a canonical \texttt{Score} field (a
schema-major change under the Binary Format companion's evolution
rule) for which no consumer exists; the decision may be revisited at
a future schema major if a use case appears.
\subsection{The Decomposition Pre-Pass} \subsection{The Decomposition Pre-Pass}
When a score is materialized, the decomposition pre-pass computes When a score is materialized, the decomposition pre-pass computes
inferred decompositions, reported as derived annotations; an authored inferred decompositions, reported as derived annotations; an authored
higher-precedence attachment overrides the inferred value in the higher-precedence attachment overrides the inferred value in the
resolved annotation. The algorithm is, in outline: resolved annotation. An authored attachment targeting an event the
pre-pass produces \emph{no} inferred decomposition for (ungriddable,
non-metric, or an inapplicable event kind) surfaces as the resolved
annotation on its own, per
Requirement~\ref{req:pitch:authored-uninferred} --- authoring is how
a user notates exactly what the algorithm cannot infer. The
algorithm is, in outline:
\begin{enumerate} \begin{enumerate}
\item For each event in time order within a voice and measure, \item For each event in time order within a voice and measure,
@ -2224,22 +2280,43 @@ resolved annotation. The algorithm is, in outline:
annotations produced. annotations produced.
\end{requirement} \end{requirement}
\begin{openquestion} \begin{requirement}
The specific algorithm for selecting decompositions when multiple \label{req:time:decomposition-algorithm}
are valid (e.g., $\frac{3}{8}$ in $\frac{4}{4}$ may be a dotted \textbf{Decomposition algorithm disposition (ratified Pass 12).}
quarter or a quarter tied to an eighth depending on placement) The decomposition pre-pass receives the \emph{profile-declared
involves style choices. The default rules must be specified; by versioned identifier} disposition of
user-configurable alternate rule sets are likely needed. The Appendix~\ref{app:determinism} Section~\ref{sec:det:open}. The
notational-decomposition algorithm affects canonical state and reserved identifier \texttt{DecompositionAlgorithmId}
must therefore receive one of the dispositions in \texttt{"default"} denotes, at version~1, the integer-grid
Appendix~\ref{app:determinism} metric splitter, whose scope bounds are part of its normative
Section~\ref{sec:det:open}: delivery as a normative algorithm definition:
in the Notational Decomposition companion specification, or \begin{itemize}
profile-declared by versioned identifier. Until that disposition \item a single governing meter per region --- a mid-region
is made, the default-decomposition output is non-canonical and meter change reduces cleanly into the region's grid (the
cross-implementation byte equality \MUSTNOT{} be claimed for Operation Catalog pins those semantics), but derived
derived layouts. notation honours only the first governing meter until a
\end{openquestion} wider algorithm version lands;
\item the region origin is assumed to fall on a barline
(anacrusis/pickup handling deferred);
\item compound-meter beat grouping uses the dyadic default;
\item tuplet nesting and cross-beat tuplet members are out of
scope;
\item at most one augmentation dot
(\texttt{MAX\_DOTS}~$=$~1); a double-dotted value is
written as tied components --- correct, if not the most
compact.
\end{itemize}
A wider algorithm is a \emph{version bump}, which
deterministically invalidates derived output under the
derived-annotation model --- no state migration. Style-choice
selection among multiple valid decompositions (e.g.,
$\frac{3}{8}$ in $\frac{4}{4}$ as a dotted quarter versus a
quarter tied to an eighth) is fixed by the versioned algorithm;
user-configurable alternate rule sets, if ever wanted, are new
registered identifiers. A profile requesting any identifier
other than a registered one \MUST{} error; implementations
\MUSTNOT{} silently substitute.
\end{requirement}
\section{Tuplets as Grouping Objects} \section{Tuplets as Grouping Objects}
\label{sec:time:tuplets} \label{sec:time:tuplets}
@ -2773,11 +2850,14 @@ pub struct SpellingRuleSet {
\end{lstlisting} \end{lstlisting}
\begin{openquestion} \begin{openquestion}
The catalog of registered spelling algorithms is the subject of the The default spelling algorithm is now ratified
open question parked in Section~\ref{sec:pitch:prepass}. Candidates (Requirement~\ref{req:pitch:spelling-algorithm}:
include Longuet-Higgins line-of-fifths distance, Temperley preference \texttt{"default"} = Temperley-style line-of-fifths preference,
rules, Cambouropoulos pitch-spelling, and Meredith PS13. The chosen version~1). Still open: the catalog of \emph{additional}
default and the parameter schemas are normative once decided. registered spelling algorithms (candidates include
Longuet-Higgins line-of-fifths distance, Cambouropoulos
pitch-spelling, and Meredith PS13) and their parameter schemas,
which are normative once registered.
\end{openquestion} \end{openquestion}
\section{Accidental Registries} \section{Accidental Registries}
@ -3642,6 +3722,15 @@ reserves a dedicated replica namespace.
regenerate the random portion until a non-reserved value is regenerate the random portion until a non-reserved value is
obtained. obtained.
Because a system-derived identifier is content-derived, the
identified object's intrinsic content is \emph{immutable}: a
reduction \MUST{} refuse an operation that would rewrite the
intrinsic content of a \texttt{SYSTEM\_DERIVED}-namespace object
in place (ratified Pass~12; the Operation Catalog pins the
precondition and its failure reason). Rewriting the content would
silently invalidate the id's content derivation; the sanctioned
path is minting a replacement object.
System-derived identifiers within the System-derived identifiers within the
\texttt{ReplicaId::SYSTEM\_DERIVED} namespace \MUST{} have their \texttt{ReplicaId::SYSTEM\_DERIVED} namespace \MUST{} have their
64-bit counter portion derived deterministically by BLAKE3 64-bit counter portion derived deterministically by BLAKE3
@ -4239,6 +4328,17 @@ pub struct CueEvent {
The canvas is the spatial root of the score. It contains regions. The canvas is the spatial root of the score. It contains regions.
The score root and the canvas are \emph{structural givens}, not
operation products (ratified Pass~12): genesis is the creation of an
empty score together with its bundle, outside the operation set, and
neither object is ever minted, addressed, or deleted by an operation
(there is no \texttt{TypedObjectId} kind for either). This is
deliberate --- a document that could mint its own root would admit a
genesis race under concurrent editing, and every operation would need
a defined semantics against a not-yet-existing root. The decision may
be revisited only if an addressable multi-canvas model is adopted at
a future schema major.
\begin{lstlisting}[language=Rust] \begin{lstlisting}[language=Rust]
pub struct Canvas { pub struct Canvas {
/// Regions in this canvas. Each region declares its time and /// Regions in this canvas. Each region declares its time and
@ -4314,6 +4414,17 @@ pub struct Region {
/// schema major 1. /// schema major 1.
pub permits_spanning_slurs: bool, pub permits_spanning_slurs: bool,
} }
\end{lstlisting}
For a slur (or other spanner) whose endpoints lie in \emph{different}
regions, permission is governed conjunctively (ratified Pass~12):
the boundary is permeable only when \emph{both} endpoint regions set
\texttt{permits\_spanning\_slurs} --- a region that forbids spanning
is never crossed against its declaration, regardless of which side
the spanner starts on. The check is an authoring-time advisory only;
it never alters canonical reduction.
\begin{lstlisting}[language=Rust]
pub enum RegionContent { pub enum RegionContent {
/// Staff-based notation: one or more staves carrying voices and /// Staff-based notation: one or more staves carrying voices and
@ -6926,9 +7037,18 @@ pub enum ReanchorReason {
SameRegionNearer, SameRegionNearer,
ExplicitFallback, ExplicitFallback,
DeclaredByExtension(ReanchorReasonRegistryId), DeclaredByExtension(ReanchorReasonRegistryId),
/// A rank-4 (same-canvas) proximity survivor. Appended in
/// Pass 12 (P12-C4); its wire discriminant is 6 because
/// DeclaredByExtension already owned 5 when it was appended.
SameCanvasNearer,
} }
\end{lstlisting} \end{lstlisting}
A re-anchor that selects a rank-4 (same-canvas) survivor records
\texttt{SameCanvasNearer} (ratified Pass~12); before the variant was
appended, such repairs were recorded \texttt{ExplicitFallback}, a
recording this revision supersedes.
\subsection{Total Ordering for "Nearest"} \subsection{Total Ordering for "Nearest"}
The notion of ``nearest surviving anchor'' is defined as a total The notion of ``nearest surviving anchor'' is defined as a total
@ -7022,13 +7142,19 @@ table is normative.
User content never silently deleted. \\ User content never silently deleted. \\
Cue event & Source event & Cue event & Source event &
Cascade-delete & Cascade-delete on any source deletion &
A cue with no source is meaningless. \\ a multi-source cue cascades when \emph{any} source dies
(ratified Pass~12): losing any source breaks the cue's
quotation integrity; truncate-while-any-source-survives was
considered and rejected \\
Graphic gesture & Anchor event & Graphic gesture & Anchor event &
Re-anchor to nearest surviving event of same staff instance; Re-anchor to nearest surviving event of same staff instance;
for Free anchoring, no action; for Range anchoring, truncate & for Free anchoring, no action; for Range anchoring, truncate &
proximity max: same staff instance \\ proximity max: same staff instance. Truncate (ratified
Pass~12): a dead event-anchored range endpoint moves to its
containing region's edge --- a start endpoint to the region
start, an end endpoint to the region end, zero offset \\
Trajectory event & Endpoint pitch & Trajectory event & Endpoint pitch &
Re-anchor: replace \texttt{EventPitch(PitchId)} with Re-anchor: replace \texttt{EventPitch(PitchId)} with
@ -7039,7 +7165,10 @@ table is normative.
Analytical annotation & Anchor & Analytical annotation & Anchor &
Re-anchor to time range preserving original extent; orphan if Re-anchor to time range preserving original extent; orphan if
range cannot be reconstructed & range cannot be reconstructed &
--- \\ orphaning is the sanctioned outcome (ratified Pass~12) for a
wall-clock (region-relative) or indeterminate event span that
no stored \texttt{Range} anchor form can express without
region-origin resolution \\
Spelling attachment & Target pitch & Spelling attachment & Target pitch &
Transition to tombstoned-target state & Transition to tombstoned-target state &
@ -8579,6 +8708,21 @@ logical IR with composite objects flattened to individual glyphs,
each glyph carrying its bounding box, anchor, and constraint inputs each glyph carrying its bounding box, anchor, and constraint inputs
to the solver. to the solver.
\begin{requirement}
\label{req:layoutir:constraint-floor}
\textbf{Minimal-tier constraint-emission floor (ratified Pass 12).}
The spacing pass \MUST{} emit at least the following constraint
set --- the \emph{Minimal-tier floor}, the testable acceptance
surface for the \texttt{Minimal} conformance tier
(Chapter~\ref{ch:solver}): no-collision chains between
successive notehead-bearing columns; per-glyph containment
within the owning region's frame; and one constraint per user
break override (system and page). Richer emission sets
(inter-band collision, kerned optical adjacency, duration-
proportional spring preferences) belong to higher tiers, whose
floors are defined when those tiers are ratified.
\end{requirement}
\subsection{Glyph-Level Objects} \subsection{Glyph-Level Objects}
\begin{lstlisting}[language=Rust] \begin{lstlisting}[language=Rust]
@ -10364,6 +10508,20 @@ pub enum OperationKindTag {
SetUserPageBreak, SetUserPageBreak,
DeclareTransaction, DeclareTransaction,
Registered(OperationKindRegistryId), Registered(OperationKindRegistryId),
// Appended after Registered (append-only vocabulary; the
// tag's wire discriminants never reorder). Phase-2/Phase-3
// operation-catalog growth:
InsertIdentifiedPitch,
DeleteIdentifiedPitch,
ModifyIdentifiedPitch,
CreateVoice,
DeleteVoice,
SetMetadata,
SetMetricGrid,
InsertStaff,
SetTimeSignature,
SetTempoSegment,
SetStaffLayout,
} }
pub enum BarrierScope { pub enum BarrierScope {
@ -10448,6 +10606,40 @@ pub enum BarrierCondition {
preserving extension data by default. preserving extension data by default.
\end{requirement} \end{requirement}
\begin{requirement}
\label{req:format:barrier-matching}
\textbf{Barrier matching for target-free and opaque operations
(ratified Pass 12).}
An operation with no graph target (\texttt{SetMetadata},
\texttt{DeclareTransaction}) is matched by \emph{score-wide}
barriers only (\texttt{BarrierScope::WholeScore}); a barrier with
any narrower scope cannot match it, because there is no target to
test the scope against. An opaque \texttt{Registered} operation is
matched \emph{fully conservatively}: since its targets and effects
are unknown to a core implementation, it matches every active
barrier whose remaining predicates do not exclude it.
\end{requirement}
\begin{requirement}
\label{req:format:unsafe-tombstone}
\textbf{Unsafe-edit tombstone semantics (ratified Pass 12).}
Crossing a barrier by an unsafe edit immediately deactivates the
owning extension's \emph{remaining} barriers for the editing
session --- the extension's invariants are already forfeit, so its
other barriers no longer protect anything. The crossing \MUST{} be
durably recorded at the next bundle commit: the pending tombstone
set survives the session that performed the unsafe edit. A
tombstoned extension that was declared \texttt{required = true}
leaves the bundle openable read-only by implementations that
depended on that extension (its invariants can no longer be
trusted); implementations that never understood it proceed under
the unknown-extension rules above. The manifest-side \emph{byte
encoding} of the tombstone record is deferred to the Binary Format
companion (the manifest schema is frozen at major~0, so the record
must ride an append-safe channel); see the companion's open
questions.
\end{requirement}
\section{Text Projection} \section{Text Projection}
\label{sec:format:textproj} \label{sec:format:textproj}
@ -11160,6 +11352,22 @@ pub enum SolverWarningKind {
\texttt{Unsatisfiable}, with the partial layout marked as such. \texttt{Unsatisfiable}, with the partial layout marked as such.
\end{requirement} \end{requirement}
\begin{requirement}
\label{req:solver:subconformant-report}
\textbf{Sub-conformant report shape (ratified Pass 12).}
A below-conformance passthrough solver (\texttt{SolverTier::Stub})
presented with declared constraints it does not evaluate reports
\texttt{SolvedWithWarnings} with
\texttt{satisfied\_hard\_constraints == false} and a warning
naming the unevaluated-constraint condition. The layout stays
renderable; the report makes no conformance claim and satisfies
no minimum-tier requirement. This is the one sanctioned case in
which a renderable status carries
\texttt{satisfied\_hard\_constraints == false}: the field reports
\emph{evaluated} satisfaction, and a non-evaluating solver has
nothing to claim.
\end{requirement}
\section{Constraint Families} \section{Constraint Families}
\label{sec:solver:families} \label{sec:solver:families}
@ -11190,6 +11398,21 @@ pub enum ConstraintStrength {
vector. vector.
\end{requirement} \end{requirement}
\begin{requirement}
\label{req:solver:kind-strength}
\textbf{Strength is kind-determined (ratified Pass 12).}
A constraint instance carries no strength field; its strength is
determined by its kind. Break constraints take their strength
from \texttt{BreakKind}: \texttt{Hard} $\to$ \texttt{Required},
\texttt{Soft} $\to$ \texttt{Preferred} with weight $1.0$. Every
other core constraint family normalizes to \texttt{Required}.
\texttt{Registered} constraint kinds normalize conservatively to
\texttt{Required}. A future constraint family declares its
strength (and weight, if \texttt{Preferred}) in its normative
definition --- the strength channel is the \emph{kind}, not the
instance.
\end{requirement}
\subsection{Normative Constraint Families} \subsection{Normative Constraint Families}
The constraint catalog (spring, collision, alignment, containment, The constraint catalog (spring, collision, alignment, containment,
@ -13555,13 +13778,16 @@ divergence. The specification fixes this at the encoding layer.
\section{Open Algorithm Hooks} \section{Open Algorithm Hooks}
\label{sec:det:open} \label{sec:det:open}
Several algorithms remain open questions in the body of the Two algorithms remain open questions in the body of the
specification: the spelling pre-pass (Chapter~\ref{ch:pitch}), specification: tempo integration for arbitrary curves
the notational decomposition algorithm
(Chapter~\ref{ch:time}), tempo integration for arbitrary curves
and root-finding for \texttt{wallclock\_to\_musical} and root-finding for \texttt{wallclock\_to\_musical}
(Chapter~\ref{ch:time}). These algorithms affect canonical (Chapter~\ref{ch:time}). These algorithms affect canonical
state. state. The spelling pre-pass (Chapter~\ref{ch:pitch}) and the
notational decomposition algorithm (Chapter~\ref{ch:time})
were resolved in Pass~12 to the profile-declared disposition
below, each with a ratified default identifier
(Requirements~\ref{req:pitch:spelling-algorithm}
and~\ref{req:time:decomposition-algorithm}).
\begin{requirement} \begin{requirement}
Any algorithm that affects canonical state \MUST{} satisfy one Any algorithm that affects canonical state \MUST{} satisfy one
@ -14744,6 +14970,33 @@ layouts they own versus inherit:
which region governs a cross-region slur's spanning permission (implemented as which region governs a cross-region slur's spanning permission (implemented as
conservative AND, P12-K12). conservative AND, P12-K12).
\\ \\
\today & Pass 12 G-ratification (the batch pass) &
Retires the open Pass-12 batch (28 rows; dispositions in
\texttt{PASS12\_RATIFICATION\_LOG.md}). Algorithm dispositions: the spelling
pre-pass and notational decomposition move to profile-declared-by-versioned-
identifier with ratified v1 defaults
(Requirements~\ref{req:pitch:spelling-algorithm}
and~\ref{req:time:decomposition-algorithm}; closes P12-H1/H3/H4/H5/C5);
decomposition precedence pinned fixed (P12-H6); authored annotations for
inference-ineligible targets surface
(Requirement~\ref{req:pitch:authored-uninferred}, P12-H7). Identity:
system-derived intrinsic content immutable under reduction (P12-K3). Genesis
ratified outside the operation set (P12-K8). Cross-region slur permission =
AND (P12-K12). Re-anchoring: cue cascade-on-any-source, Range truncate
defined, annotation orphaning sanctioned, \texttt{ReanchorReason::
SameCanvasNearer} appended (P12-C1/C2/C3/C4). Barriers: target-free and
opaque-operation matching (Requirement~\ref{req:format:barrier-matching},
P12-E4); unsafe-edit tombstone semantics
(Requirement~\ref{req:format:unsafe-tombstone}, P12-E5; encoding deferred to
the Binary Format companion). Solver: kind-determined strength
(Requirement~\ref{req:solver:kind-strength}, P12-I4), sub-conformant report
shape (Requirement~\ref{req:solver:subconformant-report}, P12-I5), the
Minimal-tier constraint floor
(Requirement~\ref{req:layoutir:constraint-floor}, P12-I6). The stale
\texttt{OperationKindTag} listing gains the eleven appended tags. Companion
movements: Operation Catalog 0.5.0~$\rightarrow$~0.6.0, Binary Format
0.3.0~$\rightarrow$~0.4.0.
\\
\bottomrule \bottomrule
\end{longtable} \end{longtable}

Binary file not shown.

View File

@ -226,7 +226,7 @@
{\Large\scshape\color{epiphanyslate}Operation Catalog}\\[6pt] {\Large\scshape\color{epiphanyslate}Operation Catalog}\\[6pt]
{\large\itshape\color{epiphanyslate}A companion to the Core Specification}\\[14pt] {\large\itshape\color{epiphanyslate}A companion to the Core Specification}\\[14pt]
{\color{epiphanygold}\rule{3in}{0.8pt}}\\[24pt] {\color{epiphanygold}\rule{3in}{0.8pt}}\\[24pt]
{\normalsize\color{epiphanyink}Version 0.5.0 --- Phase 2/3 (K0 representative + broad-K0 M2 groups + Phase-3 first tranche)}\\[4pt] {\normalsize\color{epiphanyink}Version 0.6.0 --- Pass-12 G-ratification (meta-operation edge semantics, system-derived immutability, recreate vocabulary, slot retirement)}\\[4pt]
{\small\color{epiphanyslate}Normative for the operation kinds it defines} {\small\color{epiphanyslate}Normative for the operation kinds it defines}
\vfill \vfill
\end{titlepage} \end{titlepage}
@ -287,10 +287,23 @@ specification revision. The core specification changes only when the
A \textbf{Phase-2 profile} implementation \MUST{} implement every primitive in A \textbf{Phase-2 profile} implementation \MUST{} implement every primitive in
Chapter~\ref{ch:k0} --- the representative set and the M2 broad-K0 groups --- with Chapter~\ref{ch:k0} --- the representative set and the M2 broad-K0 groups --- with
the schema, reduction rule, conflict cases, undo semantics, and re-anchoring the schema, reduction rule, conflict cases, undo semantics, and re-anchoring
behaviour defined there. The remaining (Phase-3) framework slots of behaviour defined there. The former create-score/create-canvas framework slots
Chapter~\ref{ch:k1} are \emph{unavailable} under the Phase-2 profile: an of Chapter~\ref{ch:k1} are \emph{retired} (Pass~12): they are permanently
implementation \MUST{} reject (not silently ignore) an operation whose kind is one outside the operation set, so no operation kind exists to reject.
of those slots it does not implement.
\medskip
\noindent\textbf{Version 0.6.0 (Pass-12 G-ratification).} No payload byte
changes. Ratified: ResolveConflict beyond the concurrent case (P12-K4),
ResolveEquivocation edge semantics (P12-K6) and the profile-policy deferral
(P12-K5), the RespellPitch migration fallback as long-term (P12-K1), undo
strand-block conflict-kind reuse (P12-K10) and the idempotence asymmetry
(P12-K11), the Transpose prototype pin (P12-K2 deferral), the cross-region
slur AND advisory (P12-K12), and the create-score/canvas retirement (P12-K8).
Appended vocabulary (minor, append-only):
\texttt{SystemDerivedContentImmutable} (12, P12-K3) and
\texttt{RecreateContentMismatch} (13, P12-K9) in
\texttt{PreconditionFailureReason}.
% =========================================================================== % ===========================================================================
\chapter{The Catalog Framework} \chapter{The Catalog Framework}
@ -469,17 +482,17 @@ introduced the first one), under the active policy.
\textbf{Re-anchoring.} If the target pitch is tombstoned, the respelling is a \textbf{Re-anchoring.} If the target pitch is tombstoned, the respelling is a
no-op (\texttt{TargetTombstoned}). no-op (\texttt{TargetTombstoned}).
\begin{openquestion} \emph{Migration (ratified Pass~12, closing P12-K1).} A v0
\textbf{P12-K1.} A v0 \texttt{RespellPitch} carried only a content-hash \emph{fingerprint} of the \texttt{RespellPitch} carried only a content-hash \emph{fingerprint} of the
spelling. The fingerprint cannot be inverted to a \texttt{PitchSpelling} without spelling. The fingerprint cannot be inverted to a \texttt{PitchSpelling}
a side table, so the v0$\rightarrow$v1 migration (Chapter~\ref{ch:migration}) without a side table, so the v0$\rightarrow$v1 migration
recovers the spelling from the score graph context --- an explicit per-pitch (Chapter~\ref{ch:migration}) recovers the spelling from the score graph
spelling attachment whose canonical bytes hash to the fingerprint --- and, when context --- an explicit per-pitch spelling attachment whose canonical bytes
the context lacks it, declares the envelope unmigratable (the bundle opens hash to the fingerprint --- and, when the context lacks it, declares the
read-only). This is the one representative payload that is not self-contained envelope unmigratable (the bundle opens read-only). This read-only fallback
under migration; the disposition (whether a richer v0 corpus, or a documented is the \emph{long-term} disposition: no richer v0 corpus is or will be
read-only fallback, is the long-term answer) is a Pass-12 question. required (no production v0 corpus exists). It remains the one representative
\end{openquestion} payload that is not self-contained under migration.
\section{ModifyEvent} \section{ModifyEvent}
\label{sec:k0:modify-event} \label{sec:k0:modify-event}
@ -512,6 +525,17 @@ graph (re-sorting a non-metric voice is a deferred refinement); a malformed
same-placement field edits apply in place, preserving voice membership. Partial same-placement field edits apply in place, preserving voice membership. Partial
trimming of a tuplet member remains a later refinement. trimming of a tuplet member remains a later refinement.
\emph{System-derived content immutability (ratified Pass~12, closing
P12-K3).} A modification that would rewrite the \emph{intrinsic content} of a
pitch whose identifier lives in the \texttt{SYSTEM\_DERIVED} namespace is
refused as a clean precondition no-op with the appended reason
\texttt{SystemDerivedContentImmutable} (discriminant 12): the identifier is
content-derived, and an in-place rewrite would silently invalidate its
derivation (core specification, Chapter~5 system-derived identity). The same
precondition applies to \texttt{ModifyIdentifiedPitch}
(Section~\ref{sec:k0:identified-pitch}). The sanctioned path is minting a
replacement pitch.
\textbf{Conflict cases.} Two concurrent modifications of one event with \textbf{Conflict cases.} Two concurrent modifications of one event with
\emph{differing} values produce a \texttt{StructuralFieldCollision} on the field \emph{differing} values produce a \texttt{StructuralFieldCollision} on the field
\texttt{event}, recording the winner (later in canonical order) and the loser. \texttt{event}, recording the winner (later in canonical order) and the loser.
@ -581,7 +605,11 @@ general case (interval composition need not commute), so the resolved value is
the composition in canonical reduction order. In this prototype the composition in canonical reduction order. In this prototype
\texttt{chromatic\_steps} is a minimal CMN alteration shift that commutes except \texttt{chromatic\_steps} is a minimal CMN alteration shift that commutes except
at the alteration's \texttt{i8} saturation bound; rich interval algebra is at the alteration's \texttt{i8} saturation bound; rich interval algebra is
deferred (Chapter~4 tuning catalog; P12-K2). deferred (Chapter~4 tuning catalog; P12-K2). \emph{Pinned (Pass~12):} the
prototype semantics --- CMN alteration shift with documented \texttt{i8}
saturation --- are the declared v1 behavior; replacing the payload with a
faithful interval representation is a \emph{payload schema-major} under the
Binary Format companion's evolution rule, landing with the tuning catalog.
\textbf{Conflict cases.} None --- composition is deterministic in canonical order \textbf{Conflict cases.} None --- composition is deterministic in canonical order
(a deterministic repair, not a conflict). (a deterministic repair, not a conflict).
@ -617,6 +645,13 @@ policy.
\textbf{Re-anchoring.} The structure participates in the re-anchoring rule table \textbf{Re-anchoring.} The structure participates in the re-anchoring rule table
when one of its endpoints is later tombstoned (see DeleteEvent). when one of its endpoints is later tombstoned (see DeleteEvent).
\textbf{Authoring advisory (ratified Pass~12, closing P12-K12).} The
slur-spanning advisory reads
\texttt{Region.permits\_spanning\_slurs} \emph{conjunctively}: a slur (or
other spanner) whose endpoints lie in different regions passes the advisory
only when \emph{both} endpoint regions permit spanning. The check is
authoring-time only and never alters reduction.
\textbf{Migration coverage.} The v0$\rightarrow$v1 migration \textbf{Migration coverage.} The v0$\rightarrow$v1 migration
(Chapter~\ref{ch:migration}) reconstructs the event-anchored \texttt{Tie}, (Chapter~\ref{ch:migration}) reconstructs the event-anchored \texttt{Tie},
\texttt{Slur}, and \texttt{Beam} from the v0 reference (id plus event endpoints). \texttt{Slur}, and \texttt{Beam} from the v0 reference (id plus event endpoints).
@ -772,7 +807,13 @@ reference global staves, and until this primitive existed a resolvable staff
could only be base-seeded. A create mints the staff live if its id is fresh; a could only be base-seeded. A create mints the staff live if its id is fresh; a
repeat create carrying a byte-identical value reduces idempotently, and a repeat create carrying a byte-identical value reduces idempotently, and a
create whose id is already live with a \emph{differing} value is a create whose id is already live with a \emph{differing} value is a
precondition no-op. Graph-aware reduction additionally preconditions that the precondition no-op with the appended reason
\texttt{RecreateContentMismatch} (discriminant 13; ratified Pass~12, closing
P12-K9 --- the former \texttt{TargetMissing} reuse misnamed the situation:
the target is not missing, its content disagrees). The same reason applies
to every differing-value re-create: the carried \texttt{TimeSignature}
(Section~\ref{sec:k0:meter-tempo}) and the structural-container creates
(Section~\ref{sec:k0:structural-containers}). Graph-aware reduction additionally preconditions that the
referenced instrument is live and, when \texttt{group} is present, that the referenced instrument is live and, when \texttt{group} is present, that the
staff group resolves --- the mint must leave the graph satisfying the staff group resolves --- the mint must leave the graph satisfying the
reference-resolution invariants. reference-resolution invariants.
@ -885,7 +926,8 @@ present) the length-framed \texttt{segment}.
resolved start)} (tempo segment). A carried \texttt{TimeSignature} is minted resolved start)} (tempo segment). A carried \texttt{TimeSignature} is minted
set-union under the same discipline as \texttt{CreateStaff}: fresh id mints; set-union under the same discipline as \texttt{CreateStaff}: fresh id mints;
byte-identical re-carry is idempotent; a differing value under a live id is a byte-identical re-carry is idempotent; a differing value under a live id is a
precondition no-op. The time-signature value's beat-group sum is validated at precondition no-op (\texttt{RecreateContentMismatch},
Section~\ref{sec:k0:create-staff}). The time-signature value's beat-group sum is validated at
construction and again at decode, so a malformed value never reaches construction and again at decode, so a malformed value never reaches
reduction. A tempo-segment write preconditions that the \emph{resulting} map reduction. A tempo-segment write preconditions that the \emph{resulting} map
is well-formed (segments ordered and non-overlapping; a non-constant shape is well-formed (segments ordered and non-overlapping; a non-constant shape
@ -976,6 +1018,19 @@ action of \texttt{Dismiss} reaches the \texttt{Dismissed} state; any other actio
reaches \texttt{Resolved}. Re-resolving with the same action is idempotent; two reaches \texttt{Resolved}. Re-resolving with the same action is idempotent; two
concurrent resolves with differing actions produce a meta-conflict. concurrent resolves with differing actions produce a meta-conflict.
\emph{Beyond the concurrent case (ratified Pass~12, closing P12-K4).} The
earliest-applied-resolve-governs rule is \emph{universal}: a causally-later
resolve with a differing action does not supersede the first --- it reduces
\texttt{AlreadyApplied} --- and \emph{any} resolve targeting a
\texttt{Dismissed} conflict likewise reads \texttt{AlreadyApplied}.
Intentional re-resolution is deliberately outside the v1 operation set; a
future dedicated operation (a \texttt{ReopenConflict}-class primitive) is the
sanctioned path if it is ever needed. The meta-conflict record names both
resolver operation ids in \texttt{caused\_by}; conflict records themselves
have no \texttt{TypedObjectId} kind (deliberate --- they are materialized
state, not graph objects), so the contested conflict is identified by the
\texttt{equivocation}-style field key, not an object reference.
\begin{rationale} \begin{rationale}
Pass~11 added \texttt{ResolutionAction::Dismiss} (item 2.5) precisely so the Pass~11 added \texttt{ResolutionAction::Dismiss} (item 2.5) precisely so the
\texttt{Dismissed} state is reachable by an authored operation rather than merely \texttt{Dismissed} state is reachable by an authored operation rather than merely
@ -1016,6 +1071,17 @@ operations in \texttt{caused\_by} --- the same discipline as
\texttt{target} is not an equivocated slot, or whose \texttt{chosen} is not \texttt{target} is not an equivocated slot, or whose \texttt{chosen} is not
among the slot's candidates, is a precondition no-op. among the slot's candidates, is a precondition no-op.
\textbf{Edge semantics (ratified Pass~12, closing P12-K6).} Promotion is
\emph{single-pass}, not fixpoint: a promoted candidate that is itself a
\texttt{ResolveEquivocation} does not govern a further promotion in the same
reduction. A resolve in a \emph{quarantined} replica segment is excluded from
reduction and never governs. A resolve held \emph{pending} by its own causal
gaps still governs promotion --- the verdict is a pure function of the slot
map (set-level), while the resolve's own effect stays pending. The
invalid-target/invalid-chosen no-op reuses \texttt{TargetMissing}; a dedicated
reason was considered and rejected (the appended-reason budget is spent where
a distinct verdict changes caller behavior, which it does not here).
\textbf{Undo semantics.} Mints nothing; not inverted under the prototype's \textbf{Undo semantics.} Mints nothing; not inverted under the prototype's
minted-object undo (P11-C8). minted-object undo (P11-C8).
@ -1027,8 +1093,11 @@ The core specification names three resolution paths for an equivocated slot:
transport-level reconciliation, this explicit operation, and a transport-level reconciliation, this explicit operation, and a
profile-declared deterministic selection policy. This entry pins the schema profile-declared deterministic selection policy. This entry pins the schema
for the explicit-operation path, which the core specification previously named for the explicit-operation path, which the core specification previously named
only in prose. The profile-policy path remains unpinned and unimplemented --- only in prose. The profile-policy path is \emph{deferred with a named landing
a Pass-12 question (P12-K5). site} (Pass~12 disposition of P12-K5): v1 profiles declare \emph{no}
selection function, and the hook's definition belongs to the Profile
Conformance companion when it is written --- the reducer deliberately carries
no policy hook until a profile can declare one.
\end{rationale} \end{rationale}
\section{UndoTransaction (meta-operation)} \section{UndoTransaction (meta-operation)}
@ -1066,6 +1135,25 @@ clean compensation is \texttt{Applied}; a mixed one is
\texttt{AppliedWithRepair} carrying only the tombstone repairs) --- no new \texttt{AppliedWithRepair} carrying only the tombstone repairs) --- no new
repair vocabulary. repair vocabulary.
\emph{Strand-blocks (ratified Pass~12, closing P12-K10).} A
\texttt{StrictInverse} undo that refuses to tombstone a minted object still
referenced by a live non-member (e.g., a staff whose instance survives outside
the transaction) records \texttt{ConflictKind::TransactionConflict} --- the
reuse is blessed: the strand-block \emph{is} a transaction-scoped conflict of
the undo, and the conflict record's affected objects and description carry the
strand detail. No dedicated undo conflict kind is added.
\emph{Idempotence asymmetry (ratified Pass~12, closing P12-K11).} An undo's
value restorations enter the write chains as ordinary writes by the undo
operation --- no distinguished undo provenance. Consequently a \emph{second}
undo of the same transaction finds each restored key superseded by the first
undo and refuses (\texttt{Conflicted} under \texttt{StrictInverse}, skipped
under \texttt{BestEffort}), while \emph{absence} restorations (not
representable as chain writes) repeat idempotently. The asymmetry is
normative, documented behavior; a chain-native undo provenance would be
revisited only under the deferred undo-as-operation (streaming-consistent
undo) design, which subsumes this question.
\emph{Still deferred} (P11-C8, narrowed): re-introducing content tombstoned by \emph{Still deferred} (P11-C8, narrowed): re-introducing content tombstoned by
\emph{delete} primitives (a deterministic resurrection needs a system-derived \emph{delete} primitives (a deterministic resurrection needs a system-derived
identifier derivation the ratified closed tag set does not yet include); identifier derivation the ratified closed tag set does not yet include);
@ -1151,17 +1239,18 @@ a fresh design.
creation, LWW structural overwrite, and LWW advisory respectively. creation, LWW structural overwrite, and LWW advisory respectively.
\end{description} \end{description}
\section*{Remaining framework slots (unavailable, MUST reject)} \section*{Retired slots (ratified Pass~12: outside the operation set)}
\begin{description} \begin{description}
\item[Create score / canvas] \item[Create score / canvas --- retired, closing P12-K8]
The document root and the canvas are \emph{inline singletons}, not The document root and the canvas are \emph{structural givens}, not
id-addressed objects: \texttt{TypedObjectId} has no Canvas kind, and the operation products: \texttt{TypedObjectId} has no Canvas kind, the root is
root is never op-minted --- genesis today is the empty-document never op-minted, and genesis is normatively the empty-document constructor
constructor plus bundle creation, outside the operation set. Turning these plus bundle creation, outside the operation set (core specification,
into operations requires an addressable root/canvas object model (a Chapter~5 \sectionsc{The Canvas}). These are not ``unavailable slots''
graph-model decision for G, filed as a Pass-12 row), so the slots remain awaiting a design --- no operation kind will be assigned to them. The
deliberately unavailable rather than force-designed. decision is revisited only if an addressable multi-canvas model is adopted
at a future schema major.
\end{description} \end{description}
\begin{nongoal} \begin{nongoal}