P13-S18: the invariant-20 outcome matrix, and what the residue actually is
Invariant 20 has nine non-success paths, not the three P13-S18 recorded. Only
three are abstentions: agreement-Indeterminate, boundary-Indeterminate, and an
incomputable boundary delta. Two are delegated to invariant 10, two are vacuous,
one is inapplicable, one is P13-S19's pickup deferral. The entry had been
counting all of it as gap.
Delegation is proved, not asserted. Deleting invariant 10's per-measure arm
leaves the condition unreported by the entire workspace suite except by the two
tests that name it; the same holds for the instance-local-grid arm. A delegation
nobody discharges would have been an abstention with a better name.
Every abstention cell carries a paired positive control, because silence is the
same observation for all nine paths. Each test asserts zero violations on the
fixture that takes the claimed path, then changes only that path's dependency
and asserts the clause decides with the expected witness. The control has to
observe the clause the cell names: S8's first version restored the governing
search by moving prev, which broke prev<->x comparability and left the boundary
silent for a second reason, signing the cell by inference. Moving the grid edge
instead keeps both measures c4-comparable and the boundary clause itself fires.
S2 has no such option -- a WallClock delta is never computable -- so its control
legitimately observes prev's agreement, and that exception is S2's alone.
Three shapes claimed a clause pair no single measure exhibited: m0 carried a
resolving signature at index 0 and m1 carried None, so the pair was really
A4+B1 on one measure and A1+B4 on the other. A boolean over the whole invariant
cannot see that, which is how it survived the first pass.
No behaviour change. check_measure_meter_consistency's executable body is
byte-identical to f33673d at 4871 bytes, verified by brace-matching from the
signature rather than a sentinel; every red observation came from fixture data or
from invariant 10, never from invariant 20's own logic.
P11-C5 was never this residue's gate -- it is a re-anchoring proximity metric.
P13-S23 is filed for the real dependency: placing anchor pairs on a common
timeline and measuring musical distance wherever c1-c5 do not already yield
both. It owns two disjoint deficiencies, since c3 and c5 order without
supplying any delta.
Executed against spec/CONTRACT_P13S18_MATRIX.md, 18 cells and 10 mutations.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QjsEnYhm1gPpf6ii2iFxFV
This commit is contained in:
parent
35e34d948e
commit
339269b3cf
File diff suppressed because it is too large
Load Diff
|
|
@ -203,7 +203,7 @@ and core says so.** With a nonzero offset the selector does not bound the
|
|||
point: `Region{edge: Start, off: Musical(100)}` is **not** provably before
|
||||
`Region{edge: End, off: Zero}` without knowing the region's length. The same
|
||||
holds for `Measure` Start vs End — and
|
||||
`crates/epiphany-core/src/invariants.rs:400`ff records exactly this: the
|
||||
`crates/epiphany-core/src/invariants.rs:466`ff records exactly this: the
|
||||
prototype anchor resolver places `Measure` **start** anchors and `Region`
|
||||
edges but returns `None` for a `Measure` **end**, because a coordinate
|
||||
"cannot be placed without the deferred tempo/measure-length machinery."
|
||||
|
|
@ -344,7 +344,8 @@ is deliberate:
|
|||
**not** a safety property.
|
||||
|
||||
File the residue as **P13-S18**: invariant 20's agreement and boundary checks
|
||||
are partial, and P11-C5 resolved positions are what would close them.
|
||||
are partial, and **P13-S23** — the general common-timeline/musical-distance
|
||||
capability, filed against this residue — is what would close them.
|
||||
**Status: open, deliberately.**
|
||||
|
||||
**Pin 8 — referential preconditions.**
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Contract — P13-S18: the invariant-20 outcome matrix
|
||||
|
||||
**Status:** DRAFT.
|
||||
**Status:** RATIFIED.
|
||||
|
||||
**Rung type:** diagnostic and bookkeeping. **No behaviour change.** No graph that
|
||||
violates invariant 20 today may stop violating it, and no graph that passes today
|
||||
|
|
@ -30,7 +30,7 @@ and re-confirmed unaffected at `f33673d` (see §4).
|
|||
- **Same id, same position — `End`↔`End` is comparable *when its offsets
|
||||
compare*.** c2 requires `ia == ib && pa == pb` and then delegates to
|
||||
`measure20_offset_order`, which returns `None` for `Musical`↔`WallClock`
|
||||
(`:2427`–`:2428`). So "any `Measure` end anchor" is false as written, but
|
||||
(`:2428`–`:2429`). So "any `Measure` end anchor" is false as written, but
|
||||
the counter-example is conditional and must be stated that way.
|
||||
- **Distinct ids — `End` anchors remain incomparable**, because c3 returns
|
||||
`None` unless `*pa == MeasurePosition::Start` with both offsets `Zero`. A
|
||||
|
|
|
|||
|
|
@ -95,8 +95,9 @@ visible — a value with a wire form and no canonical carrier to reach it.)
|
|||
| P13-S15 | **The `OperationKind` wire golden lock stops at discriminant 29, so kinds 30–39 — ten of them, every kind appended since the lock was written — have no byte-level lock at all.** `operation_kind_wire_discriminants_are_golden` (`crates/epiphany-ops/src/payload.rs:2189`) declares `let table: [(OperationKind, u8); 30]` (`:2233`), covering 0..=29 and asserting for each that `kind.discriminant()` has not moved *and* that the discriminant byte truly leads the canonical encoding. **Absent from that table: `TransposeInterval` (30, Push 4a), `CreateInstrument` (31, G1), `SetCanvasLayoutDefaults` (32) and `SetSpellingPrecedence` (33, G2a), `SetTuningContext` (34, G2b), `CreateStaffGroup` (35), `CreatePartDefinition` (36), `CreateAnalysisLayer` (37) and `CreateView` (38, G3a), and `CreateMeasure` (39, G3b).** Their wire discriminants are unlocked: a hand edit to `OperationKind::discriminant()`'s match — itself the site Push 4a got wrong — would move any of the ten silently, and the encoding-leads-with-the-byte assertion never runs for them. **The shape is the failure this project keeps rediscovering:** a hand-maintained parallel table that quietly stopped being extended, exactly like the four literal sites found at Push 4a and the six found during G2a — and the golden lock is the one guard specifically meant to catch that class, so its own staleness is the worst place for it. The gap widened from four kinds to ten while the entry sat open, which is itself the argument for closing it now that the genesis ladder has stopped appending | this file (found 2026-07-28 by the G-minor implementation while building s1's coverage; **scope corrected 2026-07-30**, after the genesis ladder closed at G3b — the original text scoped the repair to kinds 30–33 and an array length of `; 34`, both of which were accurate when written and are now six kinds short. Re-verified against the working tree at `4f141ce`: the length literal is still `30`, and no arm for 30–39 appears in the table) | **RESOLVED 2026-07-30** (its own rung, no rider). **Never a live incorrectness:** every one of the ten discriminants was correct throughout, and `binary_format.tex:1443`ff (kind table rows 30–39) and `:1548`–`:1552` (tag table rows 30–39) carry them normatively — the gap is the *absence of a guard*, not a wrong byte. **The repair, as landed:** `operation_kind_wire_discriminants_are_golden`'s table goes from 30 to **40** entries, locking kinds 30–39 individually — each row asserting both that `kind.discriminant()` has not moved and that the discriminant byte leads the canonical encoding. **No wire, schema-version, or specification change**: this adds a guard over assignments that were already normative. **Mutation evidence:** `OperationKind::discriminant()`'s `SetTuningContext` arm was edited 34 → 44 and the extended lock failed (*"wire discriminant for SetTuningContext moved — canonical encodings are append-only"*); with the same mutation still applied, restricting the loop to `&table[..30]` — the exact pre-repair coverage — made it **pass**, which is P13-S15 itself reproduced in the tree rather than argued for. Both edits restored by hand. **On the sibling:** the tag half is total by construction and needs no extension. `the_tag_vocabulary_is_complete` (`payload.rs:2652`) is derived, not hand-written — it computes `first_unknown_discriminant()` from `PAYLOAD_FREE`'s maximum and asserts the payload-free discriminants are exactly `0..unknown` minus `Registered`'s, dense and each decoding — so it already covers 30–39, and `operation_kind_tag_vocabulary!` makes a tag without a discriminant a compile error rather than a silent omission. **One residue, scoped out and stated rather than papered over:** density plus round-trip does not pin *which* tag holds which byte, so a permutation inside the dense range (swapping two assigned discriminants) survives both that test and `phase3_tag_discriminants_are_golden` (`payload.rs:2728`), which pins literals for 24–29 only. The same permutation on the *kind* side is caught by this rung's extended table. The tag-side gap is **not** part of this rung and is **filed as P13-S22** rather than left as a closing remark — a residue recorded only inside a resolved row is a residue that gets lost |
|
||||
| P13-S16 | **`StaffGroup.members` and `Staff.group` may disagree in both directions, and nothing detects it.** The two fields encode the same relation twice. `Staff.group` (`core_spec.tex:5578`, `graph.rs:819`) names the group a staff belongs to; `StaffGroup.members` (`core_spec.tex:4231`, `graph.rs:1614`) lists the staves in a group. **The specification declares both and states neither an authority nor an agreement requirement.** Graph invariant 10 checks that each side *resolves* — a staff's group is declared (`invariants.rs:1126`), a group's members are declared (`:1135`) — and never that the two agree, so **both stale forms pass every check in the tree**: a *missing* member (`s.group == Some(g)` while `g.members` omits `s`) and a *spurious* member (`g.members` contains `s` while `s.group` is `None` or names a different group). Genesis G3a ruled `Staff.group` the sole authority and `StaffGroup.members` a non-authoritative denormalized projection (`spec/CONTRACT_GENESIS_G3A_ENTITIES.md` §1.1, disposition B, ratified 2026-07-29) — a normative semantic ruling that makes the disagreement *defined* rather than merely undetected, but does not make it *impossible*: G3a stores the projection without maintaining it | `spec/CONTRACT_GENESIS_G3A_ENTITIES.md` §1.1 (found 2026-07-29 during G3a contract review; the authorship cycle is what surfaced it — with mints only, no authoring order produces an agreeing pair, since `CreateStaff` requires its group live at `reduce.rs:4117` and `CreateStaffGroup` requires its members live) | **open.** Deliberately no code change in G3a. The fix is disposition **A**: maintain the projection under reduction — `create_staff` with `group: Some(g)` appends to `g.members` — plus a candidate **graph invariant 21** enforcing agreement in both directions, and a decision on whether a re-carried `CreateStaffGroup` compares against its *carried* `members` (empty) or the current derived state. **Consumers must read `Staff.group`, never `StaffGroup.members`, for membership** until that lands. Sequence it after G3b so an invariant append is not competing with G3b's invariant 20 |
|
||||
| P13-S17 | **Binary Format revision history omitted genesis tranche G2b entirely, including the accept-set raise it performed.** `spec/binary_format.tex`'s Revision History chapter ran G2a 0.12.0 straight to G-minor 0.13.0 to G3a 0.14.0, with no row anywhere recording G2b (`spec/CONTRACT_GENESIS_G2B_TUNING.md`, kind/tag 34, `SetTuningContext`) — even though `OperationEnvelopeBlock`'s accept-set raise 2→3, the first accept-set move since genesis tranche G2a explicitly recorded staying at 2, reached the normative tables (the per-chunk-role accept-set prose at `binary_format.tex:2353`–`:2363`, which names the `OperationEnvelopeBlock` role's maximum as 3 "as of genesis tranche G2b", and the `OperationKind` minor-additive bullet at `:2395`–`:2418`, which records "genesis tranche G2b took 34 (`SetTuningContext`)") and never the history. G2b's own contract touch table row 27 required "version, Revision History row" among the four-document ritual, and the rung was signed off without it — the gate did not catch a documentation MUST because nothing tests the revision history | `spec/CONTRACT_GENESIS_G3A_UNDO_REPAIR.md` §0 (found 2026-07-29 during the G3a undo-repair contract review, verified against the working tree: `binary_format.tex:3599`, `:3628`, `:3643` before this rung's edit) | **RESOLVED in this same commit.** The chronology is restored: G2b lands as its own 0.14.0 row between G-minor and G3a, and G3a renumbers to 0.15.0 (`spec/CONTRACT_GENESIS_G3A_UNDO_REPAIR.md` Packet B, pins B2–B3). A new scoped guard in `epiphany-testkit` makes the omission recurrence-detectable — a distinct principal marker per standalone-row rung (G2a, G-minor, G2b, G3a — G1 is deliberately unguarded, having no standalone row of its own), strictly ordered, with G2b's content anchored within its own row segment — so the entry is filed and closed by the same packet that finds it, unlike **P13-S15** and **P13-S16**, which stay open because their fixes are sequenced to later rungs |
|
||||
| P13-S18 | **Graph invariant 20's agreement and boundary-consistency checks are partial, and nothing yet closes the residue.** Genesis tranche G3b (`spec/CONTRACT_GENESIS_G3B_MEASURE.md` pin 7) makes invariant 20 ABSTAIN — emit no violation — wherever pin 6's comparable relation cannot order two measure starts or pin 6b's musical delta cannot be computed between them: cross-clock offsets (`Musical` vs `WallClock`), differing boundary selectors (`pos`/`edge`), and any `Measure` *end* anchor (unresolvable without the deferred tempo/measure-length machinery, `invariants.rs:400`ff). This is deliberate — base-ingested data may predate the rule, so flagging every incomputable case would make the invariant useless on real scores — but it is a real gap: a score whose measure/meter disagreement happens to fall in one of these incomputable shapes passes invariant 20 silently | `spec/CONTRACT_GENESIS_G3B_MEASURE.md` pin 7 (filed 2026-07-30 during the G3b contract's own drafting, ratified as deliberate abstention rather than a defect) | **open, deliberately.** Closing it needs the deferred P11-C5 resolved-position machinery: once a `Measure` end, or an event position on a wall-clock-placed region, can be placed on a common timeline, the comparable relation and the musical delta both widen and the abstention residue shrinks. No code change is owed by G3b itself |
|
||||
| P13-S18 | **Graph invariant 20's agreement and boundary-consistency checks are partial, but only three of the checker's nine non-success paths are the real gap — not the whole checker, as first filed and over-sized.** `check_measure_meter_consistency` (`invariants.rs:2662`) has nine non-success paths across its two clauses, enumerated and classified by both its own doc comment and `spec/CONTRACT_P13S18_MATRIX.md`'s 18-cell outcome matrix (agreement: A1-A4; boundary: B1-B5). A1 (`None` declared signature) is **inapplicable** — nothing to disagree with. A3/B3 (`Governing20::None`, an empty governing candidate set) are **vacuous** (pin 6c case 1). A2/B2 (an unresolving declared or governing signature) are **delegated** to invariant 10's own resolution check (`invariants.rs:1220`ff, its per-measure and instance-local-grid arms) — verified, not merely asserted: the matrix rung's mutations M7/M8 delete each arm in turn and show the SAME condition go unreported by the ENTIRE workspace suite, not merely by invariant 20. B1 (the first measure) is the already-filed pickup/anacrusis deferral, **P13-S19**. **Exactly three paths are genuine abstention: A4 and B4 (`Governing20::Indeterminate` — the comparable relation cannot place a candidate) and B5 (a decided governing selection with no computable musical delta — order without distance).** Also corrected: the earlier **"any `Measure` *end* anchor is incomparable"** claim was wrong only in its "any" — same-id, same-position `End`<->`End` IS comparable under c2 **when its offsets compare** (`measure20_offset_order`, `:2419`, returns `None` only for `Musical` against `WallClock`); distinct-id `End` anchors genuinely are incomparable (c3 restricts to `Start`+`Zero`) and do reach A4/B4/B5; and the `resolve_anchor` `Measure` arm citation (now `:503`-`:516`, formerly miscited as `:400`ff — see the companion line-number repair to `CONTRACT_GENESIS_G3B_MEASURE.md:206`) names the missing duration machinery, not invariant 20's own execution path, which never calls `resolve_anchor`. And the `WallClock`-anchored measure start `epiphany-ops::valuegen::measure` (`ops/src/valuegen.rs:447`) actually emits does **not** uniformly abstain both clauses: against `WallClock`-anchored meter changes (c5) agreement DECIDES and only the boundary clause abstains (B5, since `measure20_musical_delta` never returns a `WallClock` delta); against `Region`-anchored meter changes both abstain (A4/B4), because `WallClock` against `Region` has no comparability arm at all | `spec/CONTRACT_P13S18_MATRIX.md` pin 8 (ratified 2026-07-31, a diagnostic and bookkeeping rung: test coverage over `check_measure_meter_consistency`'s existing nine paths plus these three ledger repairs, no behaviour change) | **open, at its true size.** A4, B4 and B5 remain real, still gated on the deferred common-timeline machinery — but the capability that closes them is now filed as **P13-S23** (below), not P11-C5: P11-C5 is a narrower re-anchoring proximity metric this entry previously over-cited as the gate; P13-S23 is the broader "place any anchor pair on a common timeline and measure musical distance" capability that actually owns A4, B4 and B5 |
|
||||
| P13-S19 | **`CreateMeasure`'s ordering and boundary-distance preconditions are vacuous for an instance's first measure, so pickup/anacrusis measures are unauthored by this rung.** Genesis tranche G3b (`spec/CONTRACT_GENESIS_G3B_MEASURE.md` pin 9) makes clauses 1 and 3 of `create_measure`'s append-only discipline vacuous when there is no predecessor measure, and invariant 20's boundary clause is symmetrically exempt for a first measure (core specification, invariant 20's doc comment) — a partial first measure MUST NOT be refused or flagged by either. This is a scoped deferral, not an oversight: a pickup measure's *own* internal consistency (its declared duration against its content) is a decomposition-sum question, not a measure-to-measure boundary question, and modelling it correctly needs a notion of "partial measure" this rung does not introduce | `spec/CONTRACT_GENESIS_G3B_MEASURE.md` pin 9 (filed 2026-07-30 during the G3b contract's own drafting) | **open, deliberately.** A pickup/anacrusis authoring story — whatever shape it takes — is later schema-fill work, sequenced after the genesis ladder closes |
|
||||
| P13-S20 | **`decode.rs`'s `precondition_reason` decoder stopped at discriminant 13, so `PreconditionFailureReason` 14 (`AcousticRealizationPinned`) and 15 (`TranspositionOutOfRange`), both live since Push 4a, encoded but could not decode.** A materialized effect carrying either reason failed canonical round-trip in production code, undetected because `epiphany-testkit`'s `precondition_failure_reason` generator (`generators.rs:417`, then `rng.below(14)`) never drew past 13 despite its doc comment claiming "every core and registered variant" | `spec/CONTRACT_GENESIS_G3B_MEASURE.md` §0 / touch-table row 12a (found 2026-07-30 during the G3b contract's own drafting, verified against the working tree: `decode.rs:205`ff ended at 13, `generators.rs:417` drew `below(14)`) | **RESOLVED in this rung** (genesis tranche G3b packet 1, `e64a4b7`). `decode.rs`'s `precondition_reason` now decodes discriminants 14 through 18 (the pre-existing 14/15 hole plus G3b's own 16–18), and `generators.rs`'s `precondition_failure_reason` now draws `below(19)` with arms for all of them — the generator's doc comment claim is true again, and the decode hole this rung found already latent in the tree, not introduced by it, is closed alongside G3b's own additions |
|
||||
| P13-S21 | **The wire specification never documented `PreconditionFailureReason` 14 and 15, so the decoder hole P13-S20 repaired had no normative text to be measured against.** `binary_format.tex`'s bounded reason table (`\sectionsc{Bounded Enumerations}`) ran `\tablenums{13}` straight to G3b's `\tablenums{16}`, and Push 4a's own Revision History row recorded only `OperationKind` `\tablenums{30}` (`TransposeInterval`) while saying nothing about the two reasons it appended in the same epoch. `AcousticRealizationPinned` and `TranspositionOutOfRange` appeared **nowhere** in the document, though the Operation Catalog documented both at 0.8.0 and `effect.rs` has carried both since Push 4a. This is P13-S20's specification-side twin: the same two variants, the same silence, and the reason a decoder that stopped at 13 could sit in the tree unchallenged — a conforming implementer reading only the wire specification would have built exactly that decoder and been right | Found 2026-07-30 while verifying genesis tranche G3b packet 3b (`d58eee8`), whose touch-table row 28 scoped the reason table to discriminants 16–18 only; the executing agent correctly declined to widen scope and reported the gap instead | **RESOLVED in this rung** (the G3b pre-push repair). The bounded table gains `\tablenums{14}` and `\tablenums{15}` with their refusal conditions, and Push 4a's Revision History row is amended to record both appends in its own epoch — no version bump and no new history row, because this documents an assignment that has been normative since Push 4a rather than making one. `binary_format_history.rs` gains a bounded regression test requiring both names in the reason table **and** in Push 4a's own row segment, so neither the G3b row's prose nor the Operation Catalog's coverage can satisfy it |
|
||||
| P13-S22 | **`OperationKindTag`'s normative tag-to-byte mapping is asserted for a minority of the vocabulary; the rest is defended only incidentally, by frozen byte artifacts that cannot say what broke.** P13-S15 closed the `OperationKind` half with one table covering 0..=39. The tag half has no equivalent. **Semantic locks — a named tag bound to a literal byte — exist only for:** 24–29 (`phase3_tag_discriminants_are_golden`, `payload.rs:2728`), 34 (one assertion inside a G2b reduction test, `reduce.rs:12744`), 35–38 (`t1_g3a_kinds_and_tags_are_35_to_38_in_both_spaces`, `reduce.rs:15931`), 39 (`payload.rs:2936`); **16** (`Registered`, whose corpus row is emitted under its *variant* name at `ops/src/vectors.rs:210` and whose committed literal leads with `0x10` at `spec/vectors/decode_vectors.txt:80`, so the drift comparison binds the association); and — incidentally — 1, spelled in a comment inside a golden blob (`barrier.rs:1058`, *"len 1, DeleteEvent (tag 1)"*). **Tags 0, 2–15, 17–23, and 30–33 have no semantic lock at all.** The derived tests do not supply one: `the_tag_vocabulary_is_complete` (`payload.rs:2652`) proves **completeness, density, and round-trip** — that the payload-free discriminants are exactly `0..unknown` with no gaps and each decodes — which constrains the *shape* of the assignment, not *which tag holds which byte*, and `operation_kind_tag_vocabulary!` guarantees coverage rather than value. **What actually catches a permutation is byte-level goldens that embed the tag by accident**, and they diagnose it as a blob mismatch: three probes, three catches, none of them naming a tag (below) | this file (found 2026-07-30 while closing P13-S15, whose kind-side extension made the asymmetry visible; **the entry was rewritten the same day after its own probes falsified its first draft.** That draft claimed a permutation was invisible and named 32↔33 as the demonstration. Three permutations were then executed against the working tree at `dcb28f0` and **all three failed**, so the claim was wrong and the severity is lower than filed: 32↔33 (`SetCanvasLayoutDefaults`/`SetSpellingPrecedence`) → caught by `the_committed_corpus_matches_the_generator` (`testkit/src/vectors.rs:225`); 1↔2 (`DeleteEvent`/`ModifyEvent`) → caught by `edit_barriers_blob_bytes_are_golden` (`layout-ir/src/barrier.rs:1061`); 2↔3 (`ModifyEvent`/`RespellPitch`) → caught by the corpus again. Each mutation was restored by hand and the suite returned to 1541/0) | **open.** **Not a live incorrectness, and — corrected — not an undefended one either:** every tag discriminant is currently correct, `binary_format.tex:1548`–`:1552` carries the mapping normatively, and no probe escaped. **The gap is intent and diagnosis, not exposure.** A permutation fails as *"the committed corpus does not match the generator"* or *"blob bytes are not golden"* — artifacts that regenerate, and whose failure reads as corpus drift rather than as a moved wire discriminant. **The corpus's tag coverage is deliberate, not accidental** — `ops/src/vectors.rs:201`–`:204` emits one row per tag straight from the vocabulary and names the reason: *"A hand-picked subset is how `TransposeInterval` shipped encoding to a byte its own decoder rejected: the corpus never named it."* **But those rows lock byte→byte, not variant→byte.** Each is named `tag_{discriminant}` and carries `[discriminant]`, both derived from the value alone, so `tag_32` asserts that `0x20` round-trips — never that `SetCanvasLayoutDefaults` is 32. Every one of the 40 rows is identical under a permutation; what actually moves is their **order**, since `PAYLOAD_FREE` is declaration order. That is why the 32↔33 probe failed, and it is exactly the property `Registered`'s row has and the numbered rows do not — its row is named for the variant. **The gap is that one row's discipline is not the vocabulary's.** **Likely shape of the repair:** one table over the whole tag vocabulary asserting tag → byte directly, superseding the six scattered fragments rather than adding a seventh — a seventh band is how this got here — so that moving a tag fails by *name*. **Probe design note for whoever takes this:** do not reuse 32↔33 or 1↔2; both are now known to be caught, and a probe that fails proves the lock exists, not that it is missing. The mutation that would sign this rung is the **inverse**: delete the proposed table and show that some permutation then passes, or show the surviving failure names no tag. **Its own rung, not a rider** |
|
||||
| P13-S23 | **No filed candidate owns "place any anchor pair on a common timeline and measure musical distance along it" — P13-S18 previously mis-cited a narrower capability as its gate.** Two disjoint deficiencies, both owned by this candidate. (1) **No ordering.** The pair is not comparable under any of `measure20_comparable_order`'s five shapes c1-c5 (`invariants.rs:2457`) at all — whether the failure is in the **referent** (distinct `Event` ids; distinct `Measure` ids outside c3's `Start`+`Zero` restriction), the **variant or selector** (`Event` against `Measure`, `Measure` against `Region`, differing `pos`/`edge`), or the **clock** (`Musical` against `WallClock`, including inside `measure20_offset_order`, `:2419`) — this is what invariant 20's A4 and B4 are made of. (2) **Ordering without a usable delta.** The pair IS comparable and still yields no musical distance: c3 supplies a vector index (an order, never a distance), and c5 compares two `WallClock`s, and `measure20_musical_delta` (`:2522`) never returns a `WallClock` delta (`:2527`) — this is what invariant 20's B5 is made of. Scoping this as merely "anchors of differing shapes" or "not directly comparable under c1-c5" would exclude B5 entirely — S5 (distinct-id `Measure` `Start`/`Zero`) is c3-comparable and S1 (`WallClock` measures, `WallClock` meter changes) is c5-comparable, and both still reach B5 — an earlier draft of this filing made exactly that narrower mistake. **Explicitly broader than P11-C5**: P11-C5 (`PASS11_WORKLIST.md:159`) is a re-anchoring proximity metric that resolves "when the graph-mutation phase tracks resolved positions", and covers narrowly the two-distinct-`Event`s case (`CONTRACT_GENESIS_G3B_MEASURE.md:223`, `effect.rs:139`-`:142`'s `PositionOutsideRegion` Reserved note); P13-S23 is the timeline itself, whatever positions get placed on it. Names its dependents: invariant 20's A4, B4 and B5, and `PositionOutsideRegion`'s Reserved status | `spec/CONTRACT_P13S18_MATRIX.md` pin 10 (filed 2026-07-31 during the same rung that corrected P13-S18's over-narrow P11-C5 citation) | **open.** No code owed by this rung. Closing it needs the deferred common-timeline/duration machinery — once a `Measure` end, a distinct-id `Measure`/`Event` referent, or an `Event` position on a wall-clock-placed region can be placed on a common timeline with a musical distance, invariant 20's A4/B4/B5 residue and `PositionOutsideRegion`'s Reserved status shrink together |
|
||||
|
|
|
|||
Loading…
Reference in New Issue