# Pass 11 — Ratification Log

One line per worklist item recording the disposition. `adopt` = blessed the
implementation's golden-locked choice as normative spec text. `decided-X` = a
real fork resolved to X with rationale in the spec. `fixed` = the spec text was
contradictory or missing and changed. Spec edits are in `core_spec.tex`; every
byte-layout golden test now cites its ratified requirement.

Date: 2026-06-21. Spec revision: **Pass 11 (spec ratification)**. Architecture
unchanged. The full worklist is `PASS11_WORKLIST.md`.

## Bucket 1 — Adopt-and-pin (bytes)

| Item | P11 id | Disposition | Spec locus | Test/code anchor |
|---|---|---|---|---|
| 1.1 `TypedObjectId` discriminants | P11-1 | **adopt** — pinned the 16-bit BE discriminant table 0..=27; added the 5 missing variants (Tuplet/RepeatStructure/LyricLine/ChordSymbol/View) the code carried; `Registered`=27 = disc(2)‖reg(16)‖raw_be(16); `ObjectKindRegistryId` is 128-bit | §"Identifiers", `req:graph:typed-object-id-discriminants` | `typed_object_id_byte_form_is_locked` |
| 1.2 Promoted-voice id | P11-3 / C4 | **adopt** — `MUSCSVCE` 64-byte preimage (staff_instance‖original_voice‖winning_op‖losing_op, each 16 BE); staff-instance recovered from containment; one derivation feeds both the reducer and Invariant 18 | §"System-Promoted Voices" | `promoted_voice_id_byte_form_is_locked` |
| 1.3 System-pitch id | P11-6 | **adopt + decided** — `MUSCSPCH` over (scale position, acoustic realization), strings length-prefixed + NFC at the boundary; **decided** the tuning reference is *always* part of intrinsic identity, including the `Inherit` presence marker | §"System-Derived Pitch Identity", `req:graph:system-derived-pitch-id` | `system_pitch_id_byte_form_is_locked` |
| 1.4 `IntegrityAnomalyId` + tag | P11-C2 | **adopt + decided** — `derive_system_id(MUSCSANM, kind.canonical_bytes())`; **decided** `MUSCSANM` is a reserved *built-in* tag (anomalies are core), moved from `new_extension` to `DomainTag::SYSTEM_ANOMALY`. No byte change | §"System-Derived Counter Collisions", `req:graph:integrity-anomaly-id`; tag added to §"System-Derived Identifier Namespace" | `domain.rs` builtins; `anomaly.rs::anomaly_domain_tag` |
| 1.5 ChunkKind/Profile/Compression | P11-D4 | **adopt** — ChunkKind 0..=8, ProfileId 0..=3, CompressionAlgorithm 0..=2, all single declaration-order discriminant bytes; ChunkKind byte is in the chunk hash preimage | §"Chunks" `req:format:chunkkind-discriminants`; §"Format Profiles" `req:format:profileid-discriminants` | `chunk.rs::discriminant`, `chunk_kind_discriminants_round_trip` |
| 1.6 `ManifestId` preimage | P11-D5 | **adopt** — `trunc128(BLAKE3("MUSCMNIF" ‖ document_id ‖ generation_le ‖ manifest_body))`, body excludes `manifest_id` (self-reference exclusion is normative) | §"Manifest Encoding", `req:format:manifest-id`; Appendix D entry updated | `bundle/ids.rs::derive` |
| 1.7 `RationalTime` + scalars | P11-4 | **adopt** — sign byte + u32-LE-length-prefixed BE numerator + u32-LE-length-prefixed BE denominator, always reduced; wall-clock integers little-endian | §"Binary Format Companion", `req:format:rationaltime-encoding` | `time.rs::CanonicalEncode for RationalTime` |
| 1.8 Codec conventions | P11-4 / D2 | **adopt as companion baseline** — LE ints; single discriminant byte per tagged union; u32 counts/length-prefixes on every variable-width leaf; raw UTF-8 free-text, NFC only for catalog ids at construction. Companion *inherits* this | §"Binary Format Companion", `req:format:codec-conventions` | `core/codec.rs` module doc |

## Bucket 2 — Decide-and-pin

| Item | P11 id | Disposition | Spec locus | Test/code anchor |
|---|---|---|---|---|
| 2.1 Tempo `Linear` parameter | P11-7 | **decided: speed-linear** — interpolates whole-notes-per-second (beat-unit-agnostic), not bpm/period; `Exponential` interpolates speed geometrically. Rationale: a tempo map may change beat unit across segments, so only speed gives a beat-unit-independent wall-clock schedule | §"Conversion", `req:time:linear-interpolates-speed` + rationale | `tempo.rs::SpeedModel` |
| 2.2 Field-collision effect tag | P11-C3 | **decided: winner-carries-`Conflicted`** — the later op (which materializes and noticed the collision) reads `Conflicted`; the earlier op keeps `Applied`. Chosen for order-independence; a UI reads the record's `loser` field for "your edit was overridden" | `req:semops:field-collision-effect` + rationale; RespellPitch reduction rule | `reduce.rs::respell_pitch` |
| 2.3 `>2`-way promotion | P11-C4 | **adopt + lifted to normative** — order-independent pre-pass: bucket by voice, walk by OperationId, retain a non-overlapping set, promote each overlapping loser (lowest-id retained survivor wins); applies to **partial** interval overlaps, not just identical onsets | §"System-Promoted Voices", `req:graph:promotion-generalization` | `reduce.rs::compute_promotions` |
| 2.4 Open-vocab enums | P11-C9 | **decided: pinned core sets, kept `Registered`** — `TransactionCategory ∈ {NoteEntry, Structural, Layout, Import, Registered}`; `ObjectKind ∈ {Voice, Pitch, Registered}` (narrower than the 28 object kinds: only kinds minted into the system namespace). **Discriminant bytes now pinned in spec text:** `TransactionCategory` 0–4 (was already pinned); `ObjectKind` Voice=0/Pitch=1/Registered=2 added to `req:graph:object-kind-vocab` because the byte feeds the `IntegrityAnomalyId` preimage and was golden-locked in code but absent from spec text | `req:semops:transaction-category`, `req:graph:object-kind-vocab` | `payload.rs`, `support.rs::object_kind_discriminants_are_golden` |
| 2.5 `ResolveConflict` Dismissed | P11-C10 | **decided: added `ResolutionAction::Dismiss`** (code + spec) — closes the half-unreachable state machine; the Dismiss action selects the `Dismissed` state, every other action selects `Resolved`. **Discriminant bytes now pinned in spec text** (`AcceptLoser`=0 … `Dismiss`=4, `Registered`=5) in new `req:semops:resolution-action-discriminants`: the action is encoded into the operation content hash and was golden-locked in code but absent from spec text | §"Conflict Resolution Operations", `req:semops:resolution-action-discriminants` | `conflict.rs::resolution_action_discriminants_are_golden`, `reduce.rs::resolve_conflict`, `resolve_conflict_with_dismiss_reaches_dismissed_state` |
| 2.6 Layout-object id | layout P11-2 | **decided: spec pins `MUSCLOID` tag; code adoption is Track A** — the spec specifies a `MUSCLOID`-tagged derivation keying multiply-manifested objects on `(source, region)`, synthesized objects on `(source, synthesis_kind, stable_semantic_instance_key)`. Non-canonical (not document state). The v0 `layout-ir` crate still mints **provisional** ids (untagged; synthesized borrows `MUSCCONF`) because the frozen determinism crate exposes no `MUSCLOID` tag — realizing the spec'd derivation is Track A work, not done in this pass. **(Superseded by P12-I2: the derivation is now wired — `epiphany-determinism` reserves the built-in `MUSCLOID` tag and `layout-ir` provenance routes through it.)** | §"Provenance", `req:layoutir:object-id-derivation` | `layout-ir` provenance (wired, P12-I2) |

## Bucket 3 — Fixes (spec was contradictory or silent)

| Item | P11 id | Disposition | Spec locus | Test/code anchor |
|---|---|---|---|---|
| 3.1 Blob hashing shape | P11-D3 | **fixed (spec bug)** — bare `BLAKE3("MUSCBLOB" ‖ payload)`; deleted the contradictory "identically to chunks" phrasing so the structured-vs-bare contradiction cannot recur | §"Blobs", `req:format:blob-hash-shape` | `determinism/hash.rs::of_blob` |
| 3.2 Equal-generation tie-break | P11-D1 | **fixed (gap) — adopted code rule** — equal generation + equal load-bearing fields {manifest_hash, manifest_schema_version, reduction_algorithm_version, profile_id} → equivalent, pick A; any divergence → `DivergentSameGeneration`, read-only. Advisory fields (commit_timestamp, offset/length) excluded | §"Superblock Selection" + rationale | `superblock.rs::selection_equivalent` |
| 3.3 RetentionPolicy placement | P11-D6 | **fixed (silent) — defined `ProfileConstraints`** (was a dangling forward reference) and placed the required `retention_policy` in it; **decided** multi-profile precedence = first-declared profile | §"Format Profiles", `req:format:profile-constraints` | `manifest.rs::ProfileConstraints` |
| 3.4 DVV zero-based floor | P11-C7 | **fixed (promote to normative)** — `vector[r]=n` ⟹ `(r,0..=n)` are predecessors; zero-based floor is normative so a one-based implementation can't diverge on pending detection. No behavior change | §"Causal Context via Dotted Version Vectors" | `causal.rs` |
| 3.5 Invariant count 18→19 | P11-2 | **fixed** — QUICKSTART 18→19; spec body states the count is 19 and names the three *construction-time* MUSTs (time-signature beat-group sum, ordering-DAG acyclicity, non-degenerate TupletRatio). **Tuplet honesty:** added `TupletRatio::new` rejecting degenerate ratios at construction (zero term or `actual==notated`) + codec decode validation; removed the now-redundant runtime sub-check | QUICKSTART; §"Graph Invariants" note; §"Tuplets" `req:time:tuplet-ratio-construction` | `graph.rs::TupletRatio::new`, `degenerate_tuplet_ratio_is_rejected_at_construction` |

## No-spec-change items (recorded resolved, no Pass 11 action)

`P11-C1` operation payload schemas → Track B (Operation Catalog). `P11-C5`
nearest-anchor stand-in → resolves with the graph-mutation phase. `P11-C6`
time-model compatibility → Track B. `P11-C8` forward undo → Track B. `P11-5`
Chapter 4 tuning catalog → Track C. `P11-D2` Binary Format companion → Track B
(item 1.8 baselines it). `layout P11-1` layout→ops dependency → crate-topology
call for the G–K re-cut (recommend blessing the dependency).

**Tally:** 8 adopt-and-pin, 6 decide-then-pin, 5 fix, 6 no-spec-change-defer =
25 candidate items. All 19 ratifiable items are ratified; the 6 deferrals are
recorded with their owning track.

## Deliverables

- **Canonical Byte-Layout Reference (Appendix E of `core_spec`).** A single,
  self-contained appendix consolidating every ratified discriminant table,
  derivation preimage, and primitive encoding from this pass into one place,
  for the Binary Format companion (Agent J) to import rather than re-derive
  from three crates. It includes a domain-tag registry (all ten reserved
  built-in `MUSC*` tags — nine canonical plus the non-canonical
  `MUSCFNTM` — and the `MUSCLOID` Track-A target), a golden-lock
  cross-reference table (each layout → its reference-implementation
  anchoring test), and an explicit "deferred to the
  companions" section naming what Pass 11 did **not** ratify (`OperationKindTag`
  discriminants, full composite struct layouts, `MUSCLOID`). The reference is a
  consolidation, not a second source of truth: every entry cites the
  requirement that governs it. Cross-referenced from §"Binary Format Companion"
  and the front-matter chapter table.
- **Ratification log** (this file): one line per worklist item with disposition.
- **Golden-test annotations**: every byte-layout golden test in
  `epiphany-core`, `epiphany-ops`, `epiphany-bundle`, `epiphany-determinism`
  cites its ratified `req:*` section.
- **Spec rebuilds clean** (lualatex/latexmk, 0 undefined references, 261 pages);
  `cargo test --workspace` 434 pass / 0 fail; `clippy -D warnings` and `fmt`
  clean.

## Follow-through gaps closed (this session)

Two enums that Pass 11 explicitly ratified (items 2.4, 2.5) had their
discriminant **bytes** golden-locked in code and labelled "RATIFIED by Pass 11"
but the **spec text** pinned only their vocabulary, not the byte values — a
divergence hole, since both feed content hashes. Closed by pinning the bytes:
`ObjectKind` (Voice=0/Pitch=1/Registered=2 → `IntegrityAnomalyId` preimage) in
`req:graph:object-kind-vocab`, and `ResolutionAction` (0…5 → operation content
hash) in the new `req:semops:resolution-action-discriminants`. `OperationKindTag`
discriminants remain deliberately deferred to Track B (their literal wire form
is the Operation Catalog's / Binary Format companion's to pin; the code locks
them only for mutual distinctness today).
