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:
parent
7e7a43b050
commit
aff1809421
|
|
@ -107,11 +107,14 @@ substituting a vendor heuristic:
|
|||
|
||||
- **Spelling**: `SpellingAlgorithmId` `"default"` — a Temperley-style
|
||||
line-of-fifths preference algorithm, v1 (`epiphany-core/src/prepass.rs`).
|
||||
The identifier is the crate's proposal pending ratification (P12-H1). A
|
||||
profile requesting any other id errors; nothing is silently substituted.
|
||||
The identifier is ratified normative (Pass 12,
|
||||
`req:pitch:spelling-algorithm`). A profile requesting any other id errors;
|
||||
nothing is silently substituted.
|
||||
- **Notational decomposition**: `DecompositionAlgorithmId` `"default"` — the
|
||||
integer-grid metric splitter, v1, with its scope bounds recorded as
|
||||
P12-H4 (single governing meter, `MAX_DOTS = 1`, tuplet-nesting deferred).
|
||||
integer-grid metric splitter, v1, with its scope bounds ratified as
|
||||
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.
|
||||
- Both pre-pass outputs are **canonical derived annotations**: deterministic
|
||||
functions of `(materialized graph, profile, algorithm id)` recomputed on
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
the class identity (`TempoIntegration`: conversion residual in either
|
||||
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).
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -465,3 +465,18 @@ schema-major-1 tranche):
|
|||
`(original, ordinal)` `stable_semantic_instance_key`. Since `LayoutObjectId`s
|
||||
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`.
|
||||
|
||||
## 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`).
|
||||
|
|
|
|||
|
|
@ -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
|
||||
honors only the first governing meter — the reduction semantics are pinned
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@
|
|||
not into code improvisations. … Don't open Pass 12 until at least 3 items
|
||||
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
|
||||
collection; G ratifies (or defers/rejects) the batch when Phase 2's open
|
||||
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 |
|
||||
|----|--------|---------|--------------------|
|
||||
| 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-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-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-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-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-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~~ **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~~ **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~~ **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~~ **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-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-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-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-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-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-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-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-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-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-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-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-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-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-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~~ **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~~ **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~~ **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~~ **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~~ **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~~ **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~~ **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~~ **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~~ **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~~ **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~~ **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-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-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-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-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~~ **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~~ **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-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-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-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-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-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-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-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-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-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~~ **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~~ **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~~ **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~~ **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~~ **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~~ **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-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) |
|
||||
|
|
|
|||
|
|
@ -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
|
||||
is equally defensible. Tracked for ratification; the advisory is authoring-only
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -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.
|
|
@ -235,7 +235,7 @@
|
|||
{\Large\scshape\color{epiphanyslate}Binary Format}\\[6pt]
|
||||
{\large\itshape\color{epiphanyslate}A companion to the Core Specification}\\[14pt]
|
||||
{\color{epiphanygold}\rule{3in}{0.8pt}}\\[24pt]
|
||||
{\normalsize\color{epiphanyink}Version 0.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}
|
||||
\vfill
|
||||
\end{titlepage}
|
||||
|
|
@ -1562,7 +1562,9 @@ trailing bytes are decode errors.
|
|||
\tablenums{8} ExtensionPrecondition \cat{} id (16 BE);
|
||||
\tablenums{9} Registered \cat{} id (16 BE);
|
||||
\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} &
|
||||
(struct) \texttt{kind} (\texttt{RepairKind}) \cat{} \texttt{target}
|
||||
(\texttt{TypedObjectId}). \\
|
||||
|
|
@ -1581,7 +1583,10 @@ trailing bytes are decode errors.
|
|||
\tablenums{0} SameVoiceNearer; \tablenums{1} SameStaffInstanceNearer;
|
||||
\tablenums{2} SameStaffNearer; \tablenums{3} SameRegionNearer;
|
||||
\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} &
|
||||
\tablenums{0} ReplaceWithRest; \tablenums{1} RewriteTuplets;
|
||||
\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
|
||||
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}
|
||||
\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.
|
||||
Clarifies that any field add is a major change regardless of
|
||||
\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
|
||||
\end{longtable}
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -406,18 +406,22 @@ Section~\ref{sec:det:open}:
|
|||
the document have not yet been delivered:
|
||||
Appendix~\ref{app:deferred} catalogs them and distinguishes
|
||||
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
|
||||
Appendix~\ref{app:determinism}
|
||||
Section~\ref{sec:det:open}: the spelling pre-pass, the
|
||||
notational-decomposition algorithm, the tempo curve
|
||||
integration algorithm, and the
|
||||
Section~\ref{sec:det:open}: the tempo curve
|
||||
integration algorithm and the
|
||||
\texttt{wallclock\_to\_musical} root-finding algorithm.
|
||||
Cross-implementation byte equality of canonical score state
|
||||
\MUSTNOT{} be claimed for outputs derived from these
|
||||
algorithms until they are normatively specified or
|
||||
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
|
||||
identifier but not enumerated here; they are delivered as
|
||||
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
|
||||
measure.
|
||||
\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}
|
||||
\item The active key signature for the staff.
|
||||
\item The accidental context of prior pitches in the same measure
|
||||
|
|
@ -1357,20 +1363,53 @@ annotations produced.
|
|||
operation, which then outranks the pre-pass.
|
||||
\end{rationale}
|
||||
|
||||
\begin{openquestion}
|
||||
The melodic and harmonic context rules above are stated
|
||||
abstractly. The specific algorithm---whether based on
|
||||
Longuet-Higgins line-of-fifths distance, Temperley's
|
||||
preference rules, or another approach---is unresolved. The
|
||||
choice affects canonical state and must therefore receive one
|
||||
of the dispositions in Appendix~\ref{app:determinism}
|
||||
Section~\ref{sec:det:open}: delivery as a normative algorithm
|
||||
in a Spelling Pre-Pass companion specification,
|
||||
profile-declared by versioned identifier, or explicitly marked
|
||||
non-canonical (in which case automatic spellings are advisory
|
||||
and \texttt{UserChosen} attachments are the only canonical
|
||||
spellings).
|
||||
\end{openquestion}
|
||||
\begin{requirement}
|
||||
\label{req:pitch:spelling-algorithm}
|
||||
\textbf{Spelling algorithm disposition (ratified Pass 12).}
|
||||
The spelling pre-pass receives the \emph{profile-declared by
|
||||
versioned identifier} disposition of Appendix~\ref{app:determinism}
|
||||
Section~\ref{sec:det:open}. The reserved identifier
|
||||
\texttt{SpellingAlgorithmId} \texttt{"default"} denotes, at
|
||||
version~1, a Temperley-style line-of-fifths preference
|
||||
algorithm: each partition's tonal context is estimated as a
|
||||
centre of gravity on the line of fifths from the accidental,
|
||||
melodic, and harmonic context, and each pitch takes the
|
||||
enharmonic spelling nearest that centre. The ascending-runs-take-
|
||||
sharps / descending-runs-take-flats convention participates
|
||||
\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}
|
||||
\label{sec:pitch:absent-accidental}
|
||||
|
|
@ -2188,15 +2227,32 @@ pub enum DecompositionSource {
|
|||
\end{lstlisting}
|
||||
|
||||
The structure deliberately mirrors the spelling attachment model
|
||||
(Section~\ref{sec:pitch:spelling}): same sources, same precedence
|
||||
machinery, same pre-pass discipline.
|
||||
(Section~\ref{sec:pitch:spelling}): same sources, same source-rank
|
||||
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}
|
||||
|
||||
When a score is materialized, the decomposition pre-pass computes
|
||||
inferred decompositions, reported as derived annotations; an authored
|
||||
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}
|
||||
\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.
|
||||
\end{requirement}
|
||||
|
||||
\begin{openquestion}
|
||||
The specific algorithm for selecting decompositions when multiple
|
||||
are valid (e.g., $\frac{3}{8}$ in $\frac{4}{4}$ may be a dotted
|
||||
quarter or a quarter tied to an eighth depending on placement)
|
||||
involves style choices. The default rules must be specified;
|
||||
user-configurable alternate rule sets are likely needed. The
|
||||
notational-decomposition algorithm affects canonical state and
|
||||
must therefore receive one of the dispositions in
|
||||
Appendix~\ref{app:determinism}
|
||||
Section~\ref{sec:det:open}: delivery as a normative algorithm
|
||||
in the Notational Decomposition companion specification, or
|
||||
profile-declared by versioned identifier. Until that disposition
|
||||
is made, the default-decomposition output is non-canonical and
|
||||
cross-implementation byte equality \MUSTNOT{} be claimed for
|
||||
derived layouts.
|
||||
\end{openquestion}
|
||||
\begin{requirement}
|
||||
\label{req:time:decomposition-algorithm}
|
||||
\textbf{Decomposition algorithm disposition (ratified Pass 12).}
|
||||
The decomposition pre-pass receives the \emph{profile-declared
|
||||
by versioned identifier} disposition of
|
||||
Appendix~\ref{app:determinism} Section~\ref{sec:det:open}. The
|
||||
reserved identifier \texttt{DecompositionAlgorithmId}
|
||||
\texttt{"default"} denotes, at version~1, the integer-grid
|
||||
metric splitter, whose scope bounds are part of its normative
|
||||
definition:
|
||||
\begin{itemize}
|
||||
\item a single governing meter per region --- a mid-region
|
||||
meter change reduces cleanly into the region's grid (the
|
||||
Operation Catalog pins those semantics), but derived
|
||||
notation honours only the first governing meter until a
|
||||
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}
|
||||
\label{sec:time:tuplets}
|
||||
|
|
@ -2773,11 +2850,14 @@ pub struct SpellingRuleSet {
|
|||
\end{lstlisting}
|
||||
|
||||
\begin{openquestion}
|
||||
The catalog of registered spelling algorithms is the subject of the
|
||||
open question parked in Section~\ref{sec:pitch:prepass}. Candidates
|
||||
include Longuet-Higgins line-of-fifths distance, Temperley preference
|
||||
rules, Cambouropoulos pitch-spelling, and Meredith PS13. The chosen
|
||||
default and the parameter schemas are normative once decided.
|
||||
The default spelling algorithm is now ratified
|
||||
(Requirement~\ref{req:pitch:spelling-algorithm}:
|
||||
\texttt{"default"} = Temperley-style line-of-fifths preference,
|
||||
version~1). Still open: the catalog of \emph{additional}
|
||||
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}
|
||||
|
||||
\section{Accidental Registries}
|
||||
|
|
@ -3642,6 +3722,15 @@ reserves a dedicated replica namespace.
|
|||
regenerate the random portion until a non-reserved value is
|
||||
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
|
||||
\texttt{ReplicaId::SYSTEM\_DERIVED} namespace \MUST{} have their
|
||||
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 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]
|
||||
pub struct Canvas {
|
||||
/// Regions in this canvas. Each region declares its time and
|
||||
|
|
@ -4314,6 +4414,17 @@ pub struct Region {
|
|||
/// schema major 1.
|
||||
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 {
|
||||
/// Staff-based notation: one or more staves carrying voices and
|
||||
|
|
@ -6926,9 +7037,18 @@ pub enum ReanchorReason {
|
|||
SameRegionNearer,
|
||||
ExplicitFallback,
|
||||
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}
|
||||
|
||||
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"}
|
||||
|
||||
The notion of ``nearest surviving anchor'' is defined as a total
|
||||
|
|
@ -7022,13 +7142,19 @@ table is normative.
|
|||
User content never silently deleted. \\
|
||||
|
||||
Cue event & Source event &
|
||||
Cascade-delete &
|
||||
A cue with no source is meaningless. \\
|
||||
Cascade-delete on any source deletion &
|
||||
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 &
|
||||
Re-anchor to nearest surviving event of same staff instance;
|
||||
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 &
|
||||
Re-anchor: replace \texttt{EventPitch(PitchId)} with
|
||||
|
|
@ -7039,7 +7165,10 @@ table is normative.
|
|||
Analytical annotation & Anchor &
|
||||
Re-anchor to time range preserving original extent; orphan if
|
||||
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 &
|
||||
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
|
||||
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}
|
||||
|
||||
\begin{lstlisting}[language=Rust]
|
||||
|
|
@ -10364,6 +10508,20 @@ pub enum OperationKindTag {
|
|||
SetUserPageBreak,
|
||||
DeclareTransaction,
|
||||
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 {
|
||||
|
|
@ -10448,6 +10606,40 @@ pub enum BarrierCondition {
|
|||
preserving extension data by default.
|
||||
\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}
|
||||
\label{sec:format:textproj}
|
||||
|
||||
|
|
@ -11160,6 +11352,22 @@ pub enum SolverWarningKind {
|
|||
\texttt{Unsatisfiable}, with the partial layout marked as such.
|
||||
\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}
|
||||
\label{sec:solver:families}
|
||||
|
||||
|
|
@ -11190,6 +11398,21 @@ pub enum ConstraintStrength {
|
|||
vector.
|
||||
\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}
|
||||
|
||||
The constraint catalog (spring, collision, alignment, containment,
|
||||
|
|
@ -13555,13 +13778,16 @@ divergence. The specification fixes this at the encoding layer.
|
|||
\section{Open Algorithm Hooks}
|
||||
\label{sec:det:open}
|
||||
|
||||
Several algorithms remain open questions in the body of the
|
||||
specification: the spelling pre-pass (Chapter~\ref{ch:pitch}),
|
||||
the notational decomposition algorithm
|
||||
(Chapter~\ref{ch:time}), tempo integration for arbitrary curves
|
||||
Two algorithms remain open questions in the body of the
|
||||
specification: tempo integration for arbitrary curves
|
||||
and root-finding for \texttt{wallclock\_to\_musical}
|
||||
(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}
|
||||
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
|
||||
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
|
||||
\end{longtable}
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -226,7 +226,7 @@
|
|||
{\Large\scshape\color{epiphanyslate}Operation Catalog}\\[6pt]
|
||||
{\large\itshape\color{epiphanyslate}A companion to the Core Specification}\\[14pt]
|
||||
{\color{epiphanygold}\rule{3in}{0.8pt}}\\[24pt]
|
||||
{\normalsize\color{epiphanyink}Version 0.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}
|
||||
\vfill
|
||||
\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
|
||||
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
|
||||
behaviour defined there. The remaining (Phase-3) framework slots of
|
||||
Chapter~\ref{ch:k1} are \emph{unavailable} under the Phase-2 profile: an
|
||||
implementation \MUST{} reject (not silently ignore) an operation whose kind is one
|
||||
of those slots it does not implement.
|
||||
behaviour defined there. The former create-score/create-canvas framework slots
|
||||
of Chapter~\ref{ch:k1} are \emph{retired} (Pass~12): they are permanently
|
||||
outside the operation set, so no operation kind exists to reject.
|
||||
|
||||
\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}
|
||||
|
|
@ -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
|
||||
no-op (\texttt{TargetTombstoned}).
|
||||
|
||||
\begin{openquestion}
|
||||
\textbf{P12-K1.} A v0 \texttt{RespellPitch} carried only a content-hash \emph{fingerprint} of the
|
||||
spelling. The fingerprint cannot be inverted to a \texttt{PitchSpelling} without
|
||||
a side table, so the v0$\rightarrow$v1 migration (Chapter~\ref{ch:migration})
|
||||
recovers the spelling from the score graph context --- an explicit per-pitch
|
||||
spelling attachment whose canonical bytes hash to the fingerprint --- and, when
|
||||
the context lacks it, declares the envelope unmigratable (the bundle opens
|
||||
read-only). This is the one representative payload that is not self-contained
|
||||
under migration; the disposition (whether a richer v0 corpus, or a documented
|
||||
read-only fallback, is the long-term answer) is a Pass-12 question.
|
||||
\end{openquestion}
|
||||
\emph{Migration (ratified Pass~12, closing P12-K1).} A v0
|
||||
\texttt{RespellPitch} carried only a content-hash \emph{fingerprint} of the
|
||||
spelling. The fingerprint cannot be inverted to a \texttt{PitchSpelling}
|
||||
without a side table, so the v0$\rightarrow$v1 migration
|
||||
(Chapter~\ref{ch:migration}) recovers the spelling from the score graph
|
||||
context --- an explicit per-pitch spelling attachment whose canonical bytes
|
||||
hash to the fingerprint --- and, when the context lacks it, declares the
|
||||
envelope unmigratable (the bundle opens read-only). This read-only fallback
|
||||
is the \emph{long-term} disposition: no richer v0 corpus is or will be
|
||||
required (no production v0 corpus exists). It remains the one representative
|
||||
payload that is not self-contained under migration.
|
||||
|
||||
\section{ModifyEvent}
|
||||
\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
|
||||
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
|
||||
\emph{differing} values produce a \texttt{StructuralFieldCollision} on the field
|
||||
\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
|
||||
\texttt{chromatic\_steps} is a minimal CMN alteration shift that commutes except
|
||||
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
|
||||
(a deterministic repair, not a conflict).
|
||||
|
|
@ -617,6 +645,13 @@ policy.
|
|||
\textbf{Re-anchoring.} The structure participates in the re-anchoring rule table
|
||||
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
|
||||
(Chapter~\ref{ch:migration}) reconstructs the event-anchored \texttt{Tie},
|
||||
\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
|
||||
repeat create carrying a byte-identical value reduces idempotently, and 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
|
||||
staff group resolves --- the mint must leave the graph satisfying the
|
||||
reference-resolution invariants.
|
||||
|
|
@ -885,7 +926,8 @@ present) the length-framed \texttt{segment}.
|
|||
resolved start)} (tempo segment). A carried \texttt{TimeSignature} is minted
|
||||
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
|
||||
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
|
||||
reduction. A tempo-segment write preconditions that the \emph{resulting} map
|
||||
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
|
||||
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}
|
||||
Pass~11 added \texttt{ResolutionAction::Dismiss} (item 2.5) precisely so the
|
||||
\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
|
||||
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
|
||||
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
|
||||
profile-declared deterministic selection policy. This entry pins the schema
|
||||
for the explicit-operation path, which the core specification previously named
|
||||
only in prose. The profile-policy path remains unpinned and unimplemented ---
|
||||
a Pass-12 question (P12-K5).
|
||||
only in prose. The profile-policy path is \emph{deferred with a named landing
|
||||
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}
|
||||
|
||||
\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
|
||||
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{delete} primitives (a deterministic resurrection needs a system-derived
|
||||
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.
|
||||
\end{description}
|
||||
|
||||
\section*{Remaining framework slots (unavailable, MUST reject)}
|
||||
\section*{Retired slots (ratified Pass~12: outside the operation set)}
|
||||
|
||||
\begin{description}
|
||||
\item[Create score / canvas]
|
||||
The document root and the canvas are \emph{inline singletons}, not
|
||||
id-addressed objects: \texttt{TypedObjectId} has no Canvas kind, and the
|
||||
root is never op-minted --- genesis today is the empty-document
|
||||
constructor plus bundle creation, outside the operation set. Turning these
|
||||
into operations requires an addressable root/canvas object model (a
|
||||
graph-model decision for G, filed as a Pass-12 row), so the slots remain
|
||||
deliberately unavailable rather than force-designed.
|
||||
\item[Create score / canvas --- retired, closing P12-K8]
|
||||
The document root and the canvas are \emph{structural givens}, not
|
||||
operation products: \texttt{TypedObjectId} has no Canvas kind, the root is
|
||||
never op-minted, and genesis is normatively the empty-document constructor
|
||||
plus bundle creation, outside the operation set (core specification,
|
||||
Chapter~5 \sectionsc{The Canvas}). These are not ``unavailable slots''
|
||||
awaiting a design --- no operation kind will be assigned to them. The
|
||||
decision is revisited only if an addressable multi-canvas model is adopted
|
||||
at a future schema major.
|
||||
\end{description}
|
||||
|
||||
\begin{nongoal}
|
||||
|
|
|
|||
Loading…
Reference in New Issue