2102 lines
137 KiB
Markdown
2102 lines
137 KiB
Markdown
# Contract — P13-S29: the violation tag stops multiplexing
|
||
|
||
STATUS: RATIFIED; DISPATCHED.
|
||
|
||
**Ratified 2026-08-12 on the authority of the repository owner**, the final
|
||
whole-artifact review returning zero findings. Review-round records accumulate
|
||
above §0.
|
||
|
||
**THE PINS ARE FROZEN. They may be executed, not edited.** A defect found during
|
||
execution is **reported, not patched in place** — if it needs a pin change, that
|
||
is its own amendment with its own review round.
|
||
|
||
Owning candidate: **P13-S29**, filed by
|
||
`spec/CONTRACT_P13S26_INVARIANT10_SURFACE.md` pin 7.
|
||
|
||
Rung class: **behaviour change.** A public type is renamed, a public field
|
||
changes type, a targeted selector deliberately returns less than it does today,
|
||
a public `Display` changes for one arm, and a normative requirement is minted.
|
||
|
||
---
|
||
|
||
### REVISION R — review round 18. Four blockers, one smaller, two cleanups. ALL ACCEPTED.
|
||
|
||
1. **[P1] Assertion 3's slice was ambiguous and destructive.** The module header
|
||
is a **28-line `//!` run** with breaks at `:2`, `:9`, `:13`, `:22`; asserting
|
||
the whole run equals a four-line paragraph would have **deleted 24 lines of
|
||
retained header**. **Fixed** — insertion and boundaries are pinned. *Placed
|
||
**after** the title paragraph rather than prepended: prepending would make its
|
||
first sentence the module's rustdoc summary line, displacing "The Chapter 5
|
||
graph invariants".*
|
||
2. **[P1] Assertions 4 and 5 did not have the boundaries they claimed** — the
|
||
rustdocs are not "immediately preceding" their declarations; the **derive
|
||
attribute sits between**. **Fixed** — a three-step algorithm: declaration, its
|
||
derive line, then the `///` block above *that*.
|
||
3. **[P1] Pin 1a and the pinned prose disagreed.** Pin 1a promises all three
|
||
blocks state the two-arm split *and* that a requirement failure is not an
|
||
invariant failure; the struct rustdoc stated neither and the enum rustdoc only
|
||
the first. **Fixed by strengthening the blocks**, so pin 1a's claim is true of
|
||
each **individually**, not merely of the three collectively.
|
||
4. **[P1] M20h, M20j and M20k were not applicable mutations** — "append a
|
||
sentence" names no sentence. **Fixed** — each pins its exact added line, as
|
||
M20f, M20g and M20i already did.
|
||
5. **[P2] Revision Q corrected M20f's rationale but not the two live statements
|
||
it contradicts.** **Fixed** — both now say a call whose result is **asserted**
|
||
would widen M3/M9's radii; an ignored one would not.
|
||
|
||
**Two cleanups landed with them:**
|
||
|
||
- **`invariants.rs:8` carries `` [`InvariantViolation`] `` in retained header
|
||
prose.** Gate 6 forbids that token in Rust code, so leaving it unpinned made
|
||
**gate 6 unsatisfiable**. Pin 9 now owns its rename.
|
||
- **"Every assertion has an ADDITIVE discriminator" was false** — M20i is a
|
||
**reordering**. Now "non-deletion".
|
||
|
||
*The round also noted my tally of 11 M20-rows was 12; the contract states no such
|
||
count, which is why it did not stale.*
|
||
|
||
---
|
||
|
||
### REVISION Q — review round 17. Four blockers, one smaller. ALL ACCEPTED.
|
||
|
||
1. **[P1] M20f did not compile and did not demonstrate its stated radius.** The
|
||
file imports only the three pinned names, and `valid_score` lives at
|
||
`epiphany_core::generators::valid_score` (`lib.rs:89`, `generators.rs:96`).
|
||
**And its result was discarded**, so even qualified it would not have put the
|
||
test in M3's or M9's radius. **Fixed** — the call is fully qualified, and the
|
||
rationale is corrected: M20f signs the **file-content prohibition**; the radius
|
||
concern is *why* that prohibition exists, not what M20f exhibits.
|
||
2. **[P1] Assertions 3–5 had no pinned expected text.** Pin 1a states a
|
||
*requirement*; a requirement is not an expected value, and an executor would
|
||
have written the production string and copied it into the test — asserting
|
||
nothing. **Fixed** — the module paragraph and both rustdocs are pinned **as raw
|
||
source**.
|
||
3. **[P1] Assertions 1–5 had no extraction boundaries**, and assertion 1 is
|
||
**unsound without one**: `#[derive(Clone, PartialEq, Eq, Debug)]` occurs
|
||
**twice** in `invariants.rs` — on the violation type (`:249`) and on
|
||
**`DeferredCheck`** (`:286`), which §0.5 deliberately retains — so a file-wide
|
||
search **survives M20**. **Fixed** — every slice is symbolic and anchored to
|
||
the declaration it precedes.
|
||
4. **[P1] Equality was unsigned for assertions 2–4.** M20g and M20h discriminated
|
||
only 1 and 5; the rest were deletion-only, which a needle or subset
|
||
implementation satisfies. **Fixed** — **M20i, M20j, M20k**. *M20i **reorders**
|
||
rather than adds: every trait this enum can usefully derive is already there,
|
||
and a per-trait needle check passes on a reordering while equality fails.*
|
||
5. **[P2] Finding 5 of round 16 reached the touch row but not pin 1b's premise.**
|
||
**Fixed** — the pin now claims absence of a **complete explicit three-name**
|
||
observer, not absence of any: migrated `score_graph.rs` does resolve
|
||
`ViolationKind` through the root.
|
||
|
||
---
|
||
|
||
### REVISION P — review round 16. Three blockers, two smaller. ALL ACCEPTED.
|
||
|
||
1. **[P1] Pin 1b's no-call constraint was unobserved.** Assertion 6 checked only
|
||
the import line, so the body could start calling `check_requirement` while
|
||
every mutation and gate behaved as expected — **silently widening M3's and
|
||
M9's radii**, which is exactly what the type-level constraint exists to
|
||
prevent. **Fixed** — assertion 6 is **whole-file equality** against the fenced
|
||
source, and **M20f** adds a call while keeping the imports intact.
|
||
2. **[P1] `production_source()` is not reachable where pin 1b put its guard.** It
|
||
is a **private `fn` of `mod g3a_tests`** (`invariants.rs:4679`), so a guard
|
||
"beside pin 10's tests" cannot call it and the prescription was not literally
|
||
implementable. **Fixed** — the guard is placed **inside `mod g3a_tests`**, and
|
||
the two alternatives (a second slicing helper, widening that one's visibility)
|
||
are named and declined as surface for no gain.
|
||
3. **[P1] Assertions 1–5 were not fully signed.** M20/M20a remove a trait;
|
||
M20b–d delete whole prose units — all of which a guard that merely *searches*
|
||
for `Eq`, `Hash` or one phrase satisfies, while failing every promise the pin
|
||
makes. **Fixed** — all six assertions are **equalities**, and **M20g** (adds a
|
||
trait) and **M20h** (appends a sentence) are the discriminators: a subset or
|
||
needle check accepts both; only equality rejects them.
|
||
4. **[P2] Assertion 6 restated its import in the wrong register** — an inline
|
||
Markdown copy wrapped across source lines, against the one-line Rust in the
|
||
fenced block. **Fixed** — the fenced source is its sole authority, and
|
||
assertion 6 no longer respells it.
|
||
5. **[P2] Touch row 4c overstated exclusivity.** `tests/score_graph.rs` is an
|
||
integration test too, and once its `.invariant` comparisons migrate it must
|
||
resolve `ViolationKind` from the root, `invariants` being private. **Fixed** —
|
||
4c is the unique **explicit three-name** observer, not the only observer of the
|
||
re-export.
|
||
|
||
---
|
||
|
||
### REVISION O — review round 15. Three blockers, three smaller. ALL ACCEPTED.
|
||
|
||
1. **[P1] M19 could not produce its promised failure.** `mod invariants` is
|
||
**private** (`lib.rs:76`), so deleting a name from the root re-export is an
|
||
**unresolved import** — a compile error, which observes nothing and which gate
|
||
7 cannot record as a failing assertion. The mutation's claim that the function
|
||
"remains public at its module path" was false for the same reason. **Fixed** —
|
||
**M19 is withdrawn**; the re-export is **compiler-observed**, in the same class
|
||
as pin 1's rename. What a mutation *can* reach is whether the test imports all
|
||
three names, which is now assertion 6 of the source guard, signed by **M20e**.
|
||
2. **[P1] Pin 1b's source guard was one-fifth signed.** M20 exercised one derive
|
||
line; a guard implementing only that passed while omitting `ViolationKind`'s
|
||
derives, the module header, and both rustdocs. **Fixed** — **six** independent
|
||
assertions, signed by **M20 and M20a–M20e**. *M20a removes `Hash` rather than
|
||
`Ord`, because `Ord` would not compile — and a compile error observes
|
||
nothing.*
|
||
3. **[P1] Pin 1b named no locations, and the touch table did not cover it.**
|
||
**Fixed** — the integration test is
|
||
`crates/epiphany-core/tests/public_surface.rs` (**new touch row 4c**), the
|
||
source guard lands in `invariants.rs` (**row 1 updated**), and **the
|
||
integration test is pinned type-level only**: a function-item coercion and a
|
||
`matches!` arm, calling nothing. *Invoking `check_requirement` there would
|
||
silently widen M3's and M9's radii to include it.*
|
||
4. **[P2] The README propagation fix stopped one hop short again.** Pin 9 still
|
||
reproduced the cell inline while pin 9a was meant to be sole authority.
|
||
**Fixed** — pin 9 defers.
|
||
5. **[P2] Pin 1b created new landing-time falsehoods** — *"no test or gate reads
|
||
them"* and *"omitting the re-export leaves the suite green"* become false when
|
||
pin 1b lands. **Fixed** — scoped to the **ratified input**, as pin 13 now is.
|
||
6. **[P2] §3's observer inventory was stale**, naming pins 3a, 10 and 11 only.
|
||
**Fixed** — two classes: *behavioural/classification* (3a, 10, 11) and
|
||
*structural*, reading declarations rather than running the checker (1b, 2, 8).
|
||
|
||
---
|
||
|
||
### REVISION N — review round 14. Four blockers, three smaller. ALL ACCEPTED.
|
||
|
||
1. **[P1] M18 was named in pin 2 but absent from §3 — and I deleted it.**
|
||
Revision M replaced the span from `M17·C1` to `M8` to insert the measured
|
||
radii, and **M18 sat inside that span**. Gate 7 covers §3's mutations, so a
|
||
mutation named only in a pin is a mutation nothing runs. **Restored**, with
|
||
that note in its cell. *A span replacement is how I edit; this is the first
|
||
time it silently removed a neighbour, and it did so in the round that was
|
||
correcting radii.*
|
||
2. **[P1] M7d was not compile-complete.** `violating_score` matches exhaustively
|
||
on `GraphInvariant` (`generators.rs:502`), so a variant without an arm is a
|
||
**compile error, which observes nothing**. **Fixed** — M7d now pins a
|
||
`violating_score` arm returning an unchanged valid score, while still omitting
|
||
the variant from `all()`.
|
||
3. **[P1] Parts of the public API had no observer.** Pin 1a's derives and
|
||
rustdocs were prose, and **touch row 2's root re-export could be omitted with
|
||
the suite green**, since every pinned caller lives inside `invariants.rs`.
|
||
**Fixed** — **pin 1b**: an **integration** test importing the three names from
|
||
`epiphany_core`'s root (a unit test cannot observe this — it reaches the
|
||
module path regardless), plus a derives/rustdoc source guard. Signed by
|
||
**M19** and **M20**.
|
||
4. **[P1] The invariant-side `Display` fixture was unpinned**, and the choice
|
||
decides which cell the test lands in — C1's, C2/C3's, M11's, or none.
|
||
**Fixed** — pinned to a **reversed aleatoric bound**, acquired from
|
||
`check_invariants`; **M11's cell now names the test.**
|
||
5. **[P2] §3 still said only M2a was measured.** **Fixed** — four cells were:
|
||
M2a and M17·C1–C3, and *every one differed from what static reading
|
||
predicted.*
|
||
6. **[P2] The README oracle had a live duplicate.** Pin 9 quoted the cell inline
|
||
while claiming exactness; pin 9a holds the fenced source. **Fixed** — pin 9
|
||
now defers to pin 9a as sole authority.
|
||
7. **[P2] Pin 13 carried another landing-time falsehood** — *"the open S29 row
|
||
exists today"* becomes false once execution resolves it. **Fixed** — scoped to
|
||
the **ratified input**.
|
||
|
||
---
|
||
|
||
### REVISION M — review round 13. Five blockers. ALL ACCEPTED.
|
||
|
||
1. **[P1] Revision L's two propagation fixes never reached the live pins.** The
|
||
README cell stayed an inline double-backtick construct, and pin 13 still said
|
||
both additions are compared as *"the whole normalised added record"* —
|
||
contradicting its own preceding paragraph. **Fixed** — **pin 9a** carries the
|
||
cell as fenced raw source, and pin 13 states outright that the phrase
|
||
described gate 15 only and was never true of gate 10.
|
||
2. **[P1] The C4–C10 cleanliness claim was unsatisfiable for C6/C7.** "Only its
|
||
own requirement-arm violation" contradicts this contract's own finding that
|
||
C6's fixture emits **both**. **Fixed** — the property is **"no invariant-arm
|
||
violation"**, which is what the pinned assertion always said and what the
|
||
structural exclusion needs.
|
||
3. **[P1] M17's radii were guesses, and all three were wrong. Measured with
|
||
compiling proxies:** **C1 = 18 existing tests**, spanning four
|
||
`review_fix_tests` modules, the g3b matrix tests and — unguessed — **four
|
||
generator tests**, since `violating_score(CrossCuttingRefsResolve)` stops
|
||
violating it. **`f4` is not among them**: its ghost-anchor is C2's, exactly as
|
||
the round said. **C2 = 1** (`f4`). **C3 = 0** — nothing in the tree carries a
|
||
dangling tempo *end* anchor. **C2 and C3 now pin their replacement label**,
|
||
since a different one changes which `check_requirement` retrieves the
|
||
violation.
|
||
|
||
*Two measurement faults are recorded because each nearly became a result:* a
|
||
first proxy hit `E0501` — the `flag` closure holds a unique borrow of `out` —
|
||
and reported **0 failures for both C2 and C3**, *a compile error observing
|
||
nothing*, the trap this repository names and that these contracts cite. A
|
||
second attempt used `cargo test`'s `error: test failed` as a compile signal
|
||
and misread a real 1-failure result as non-compiling. **The third used
|
||
`cargo build --tests` and `error[`**, and only its numbers are pinned.
|
||
4. **[P1] M7b's radius was false.** `every_invariant_has_a_negative_generator`
|
||
iterates `all()`, so replacing an entry means it visits the replacement twice
|
||
and never asks for the removed variant. **A test driven by the mutated list
|
||
cannot detect an omission from that list.** **Fixed** —
|
||
`graph_invariant_all_is_unchanged` alone.
|
||
5. **[P1] Pin 8 froze `all()`, not the enum.** A fully implemented 22nd variant
|
||
**omitted from `all()`** leaves the canonical sequence untouched and every gate
|
||
green — the same hole M18 closes for `ViolationKind`, since a variant nothing
|
||
enumerates is a variant nothing observes. **Fixed** — a second, independent
|
||
**declaration inventory** read from the `enum GraphInvariant` source, signed by
|
||
**M7d**.
|
||
|
||
---
|
||
|
||
### REVISION L — review round 12. Four behavioural blockers, two propagation defects. ALL ACCEPTED.
|
||
|
||
1. **[P1] C1–C3 were tested but never mutation-signed.** §3 opened at C4, so an
|
||
implementation moving a tempo anchor — or the whole reference surface — to a
|
||
requirement arm was **observed by tests nothing verified**. **Fixed** —
|
||
**M17·C1, M17·C2, M17·C3**, each a complete reclassification with an
|
||
exhaustive radius. As predicted, **C2 is the wide one**: it reaches the mixed
|
||
fixture *and* the legacy ghost-anchor assertion in
|
||
`f4_tempo_segment_structural_defects_fire`.
|
||
2. **[P1] Pin 8's freeze was only count-signed.** M7 adds a 22nd entry, so a test
|
||
asserting `all().len() == 21` satisfies it while leaving unobserved: the same
|
||
variants **reordered**, one **replaced or duplicated** at length 21, and two
|
||
`number()` arms **swapped**. **Fixed** — the test compares a **canonical
|
||
`(variant, number)` sequence**, pinned in full, and **M7a/M7b/M7c** sign
|
||
order, membership and mapping separately.
|
||
3. **[P1] M2a's radius was unestablished for this rung's prospective fixtures.**
|
||
The disposable run measured existing consumers; each new C4–C10 test also
|
||
carries a negative `check_invariant` assertion, and any unrelated invariant
|
||
tripped by a not-yet-built fixture would add it. **Fixed structurally, not by
|
||
estimate** — a **fourth pinned assertion** on each of the seven requires the
|
||
fixture's aggregate **invariant arm to be empty**, which removes the
|
||
possibility rather than predicting it.
|
||
4. **[P1] Pin 2's "exactly two arms" had no observer.** A complete third arm with
|
||
a `Display` arm and no emitter **compiles and leaves every gate green**.
|
||
**Fixed** — `violation_kind_has_exactly_two_arms` compares the enum's
|
||
declaration to pin 2's by equality, and **M18** is that third arm.
|
||
5. **[P2] The README's "verbatim" cell was still an inline Markdown construct**
|
||
whose own backticks forced outer delimiters, leaving two readings. **Fixed** —
|
||
fenced raw source, as revision K did for `APPEND`.
|
||
6. **[P2] Pin 13's final sentence still repeated the superseded method.**
|
||
**Fixed** — deleted; gate 10 reconstructs from removed-plus-added.
|
||
|
||
---
|
||
|
||
### REVISION K — review round 11. Three blockers, two lifecycle/precision defects. ALL ACCEPTED.
|
||
|
||
1. **[P1] `APPEND` was pinned in the wrong source register.** A Markdown
|
||
blockquote's `>` prefixes are part of the raw text and survive
|
||
whitespace-collapsing, while the ledger row has none — so the reconstruction
|
||
could never match. **Fixed** — `APPEND` is a **fenced raw-source block**.
|
||
2. **[P1] Pin 13's closing paragraph never received the ledger fix**, still
|
||
describing gate 10 as an added-lines check. **Fixed** — and the paragraph now
|
||
says *why the two gates differ*: a new Revision History row genuinely is a run
|
||
of added lines, while an append to a one-line table row rewrites that line, so
|
||
only gate 15 can use the added-lines method.
|
||
3. **[P1] The README guard forbade digits, not restated counts.** *"all
|
||
twenty-one variants returned by `GraphInvariant::all()`"* carries no digit and
|
||
recreates the defect exactly. **Fixed** — the invariant-description cell is
|
||
**pinned verbatim and compared by equality**, which is the only form that
|
||
rejects a spelled-out count.
|
||
4. **[P2] "The real set is 20" conflicted with M2a's own cell**, which also
|
||
carries `invariant_selector_discriminates_its_payload`. **Fixed** — 20 is the
|
||
measured **pre-existing/legacy** radius; the cell is those 20 **plus** the new
|
||
test.
|
||
5. **[P2] The `reduce.rs` contingency was temporally impossible** — re-verified
|
||
"at execution", but a row added "before dispatch" cannot follow, since pin 12
|
||
dispatches at ratification. **Fixed by doing the verification now**:
|
||
`reduce.rs` contains **zero `.invariant` accesses** and both `GraphInvariant`
|
||
uses pass a variant as an argument. Re-verified at revision K, and if it turns
|
||
out wrong during execution, **execution stops and an amendment adds the row**.
|
||
|
||
---
|
||
|
||
### REVISION J — review round 10. Five blockers. ALL ACCEPTED.
|
||
|
||
1. **[P1] M2a's derivation equated object identity with state identity.** Tests
|
||
mutate the score between assertions — `invariants.rs:3216` removes the overlap
|
||
*before* its negative; `invariants.rs:4457` installs the tempo map only
|
||
*after* one — so a positive assertion proves nothing about the state the
|
||
negative selector sees. And **`m35` was not one binding group at all**: its
|
||
negative uses `lone`, its positive a separately built score
|
||
(`invariants.rs:4939`).
|
||
2. **[P1] M2a's candidate surface was incomplete.** `!fires(…)` is not the
|
||
surface; the mutation changes **every** `check_invariant` consumer — direct
|
||
zero-result assertions (`invariants.rs:5158`, the S2/S7/S8 matrix cells) and
|
||
**behavioural** ones, notably **`generators.rs:953`, where `shrink` uses the
|
||
selector to choose candidates**, plus test-scope consumers in
|
||
`reduce.rs:16586`.
|
||
|
||
**Both fixed by measuring, as ruled.** A disposable implementation —
|
||
`check_invariant` with its payload filter removed — was run against the full
|
||
workspace with `--no-fail-fast`. **The measured *pre-existing* set is 20
|
||
tests, all in `invariants::g3b_measure20_tests`; M2a's cell is those 20 plus
|
||
`invariant_selector_discriminates_its_payload`.**
|
||
Against revision I's derived 13: **3 in common, 10 false positives, 17
|
||
missed** — the two sets are nearly disjoint. *Static adjacency did not
|
||
approximate this radius; it produced a different one.* The tree was restored
|
||
and re-verified at 43 suites / 1586 before continuing.
|
||
3. **[P1] The pinned Revision History row had its delimiter backwards.** The
|
||
existing final row already terminates with `\\` immediately before
|
||
`\bottomrule` (`core_spec.tex:17031`), so a block **beginning** with `\\`
|
||
produces two separators before the new row and none after. **Fixed** — no
|
||
leading delimiter, a terminating one, and the insertion point pinned.
|
||
4. **[P1] The ledger reconstruction could not hold.** The S29 line **ends with
|
||
the table's terminal `|`**, so appending after the whole line writes outside
|
||
the row. **Fixed** — the comparison strips the trailing delimiter from both
|
||
sides and requires it restored on the added line. **Gate 10's superseded
|
||
added-lines-only instruction is replaced** by the reconstruction.
|
||
5. **[P1] The README digit gate was unsatisfiable at row scope.** The row's final
|
||
cell necessarily reads `Ch. 5 §"Graph Invariants"`, so a digit scan over the
|
||
line rejects the correct edit. **Fixed** — the numeral prohibition is scoped
|
||
to the row's **invariant-description cell**.
|
||
|
||
---
|
||
|
||
### REVISION I — review round 9. Three blockers, two smaller. ALL ACCEPTED.
|
||
|
||
1. **[P1] M2a had no precommitted failure oracle.** A 19-test search surface with
|
||
the set deferred left gate 7 nothing fixed to compare against. **Derived and
|
||
pinned: 13 named tests.** Method, stated in §3: enumerate the 19 negative
|
||
selector assertions, keep those where a **positive** assertion falls in the
|
||
same *binding group* — the same score instance. **Two directions of error are
|
||
named rather than hidden** (a rebinding through an unrecognised helper
|
||
over-counts; a score violating an invariant no assertion names under-counts),
|
||
and execution reconciles against the thirteen. *This is the one cell derived
|
||
by reading pre-existing tests rather than constructed from pinned ones, and it
|
||
is flagged as such — M2a mutates code this rung creates, so it cannot be
|
||
measured beforehand, only precommitted.*
|
||
2. **[P1] Pin 13 promised exact comparisons and supplied semantic summaries.**
|
||
**Fixed** — the Revision History row is pinned as **verbatim LaTeX**, and the
|
||
ledger append as **verbatim text**. The extraction boundaries are pinned too,
|
||
and the ledger's is the subtle one: **the S29 entry is a single-line table
|
||
row, so an append shows as one removed and one added line and the added line
|
||
is not the append.** The comparison is therefore
|
||
**`added == removed + " " + APPEND`**, which checks the whole logical record
|
||
without pinning the pre-existing cell.
|
||
3. **[P1] The README repair perpetuated the defect it found.** Writing `21` for
|
||
`19` restates a count that has already staled twice, against the rule
|
||
`invariants.rs`' own module header states — *"no prose here restates it"*.
|
||
**Fixed** — the README becomes **symbolic**, *"all variants returned by
|
||
`GraphInvariant::all()`"*, and **gate 16 fails on a digit there**.
|
||
4. **[P2] M3 was not a complete mutation.** **Fixed** — the predicate is
|
||
**replaced** by `matches!(v.kind, ViolationKind::Invariant(_))`, matching every
|
||
invariant variant and no label, which is what its radius assumed.
|
||
5. **[P2] Gate numbering ran 14, 16, 15.** **Fixed** — 1 through 16 in order,
|
||
which matters because execution evidence is keyed by gate number.
|
||
|
||
---
|
||
|
||
### REVISION H — review round 8. Five blockers. ALL ACCEPTED.
|
||
|
||
1. **[P1] The new selector tests were not propagated through the radii.**
|
||
**Fixed** — M1·C5 and M1·C8 gain
|
||
`requirement_selector_discriminates_its_payload` (built from C5 and C8); M3
|
||
and M9 gain it; **M11 gains `invariant_selector_discriminates_its_payload`,
|
||
whose invariant-4 half is the very violation M11 retags.** **M2a was not
|
||
"alone":** `m39_unresolvable_reference_is_invariant_10_only` asserts
|
||
`fires(CrossCuttingRefsResolve)` **and** `!fires(MeasureMeterConsistency)`, so
|
||
`Invariant(_)` breaks it, as it does
|
||
`matrix_b2_governing_signature_unresolving_delegated`. **The candidate surface
|
||
is enumerated — 19 tests carry a negative selector assertion — and the exact
|
||
set is measured at execution**, since which of them fail depends on whether
|
||
their score violates anything else. **M3a's radius was right and its reason
|
||
wrong:** under M3a *alone* C6 and C7 still share a label, so M6 is irrelevant
|
||
to it; what excludes every other test is that each presents one label.
|
||
2. **[P1] The equality transition stopped before its consumers.** Pin 3 still
|
||
cited retired stems; M12pre–M13neutral named "positive 1–5"; M14a–c named stem
|
||
assertions. **Fixed.** And **M15a/M15b could no longer sign the structural
|
||
assertion**, since equality fails first on a mis-sliced block — **so that
|
||
assertion is retired as redundant** and both are ordinary equality mutations.
|
||
3. **[P1] Pin 9's prose outcomes had no landing observer** — every gate could
|
||
pass with all of them omitted. **Fixed** — **gate 16**, scoped per site. The
|
||
sweep also gained two more: `review_fix_tests_4`'s module doc calls its tempo
|
||
subject *"invariants"*, and **`check_invariants`' public rustdoc never says it
|
||
returns both arms** — the one place a caller looks before relying on pin 4's
|
||
comprehensiveness. **The "six" tally is removed**: the set grew in two
|
||
consecutive rounds, and a count beside a table that can grow is the defect
|
||
this family keeps finding.
|
||
4. **[P1] Pin 13's gates observed tokens, not records.** A truncated or misplaced
|
||
addition carries the token and passes. **Fixed** — both gates slice the
|
||
**added record** from the staged diff and compare it in **normalised
|
||
whole-record form** against pin 13's text.
|
||
5. **[P1] The `Display` test's acquisition path was unpinned**, and the choice
|
||
decides M3's radius. **Fixed** — acquisition is **from `check_invariants`**,
|
||
pinned, which keeps the test out of M3's radius as the table assumes.
|
||
|
||
---
|
||
|
||
### REVISION G — review round 7. Five blockers. ALL ACCEPTED.
|
||
|
||
1. **[P1] S8 neutrality was bypassable by additive prose.** Five required
|
||
sentences plus three forbidden stems all pass on
|
||
`A \texttt{Constant} segment's \texttt{end\_tempo} \MUST{} be absent.` —
|
||
stem-free, and it **resolves P13-S8**. **Fixed by taking the cleaner option:**
|
||
pin 3a asserts **normalised exact equality** against pin 3's pinned source.
|
||
Pin 3 declares that block complete, so equality is the assertion that matches
|
||
the pin, and it needs to anticipate nothing — *no closed stem inventory can be
|
||
trusted to anticipate the sentence someone will actually write.* **M14e** is
|
||
that sentence, and the demonstration.
|
||
2. **[P1] Both selectors' payload discrimination was unsigned.** Every fixture
|
||
presented one variant or one label, so implementations matching
|
||
`Invariant(_)` or `Requirement(_)` — **ignoring the argument** — satisfied
|
||
every assertion. **Fixed** — two fixtures carrying **two** invariant variants
|
||
and **two** requirement labels, with exact projections, signed by **M2a** and
|
||
**M3a**. M2/M3 signed arm selection only.
|
||
3. **[P1] The real-violation `Display` oracle was not independent.** An expected
|
||
string built from `violation.witness` moves with the actual when M10 restores
|
||
the suffix, so the test would not fail. **Fixed** — an **independent**
|
||
assertion that the witness contains no `req:` comes **first**, and the wrapper
|
||
equality is then built from the witness that assertion has already checked.
|
||
4. **[P1] The prose migration stopped at the `/// 10.` block.** Five more live
|
||
statements become false — the tempo, aleatoric and accidental headers, the
|
||
migrated negative's message, and `README.md:25`, which exposes the old type
|
||
**and a count already stale at 19**. **Fixed** — pin 9 covers all six, with
|
||
touch rows 4a and 4b. **`DECISIONS.md` is not rewritten**: it gains an explicit
|
||
supersession note, because a decision record that is edited stops recording
|
||
why the multiplexing was once defensible.
|
||
5. **[P1] Both permanent history additions were authorized without pinned
|
||
content**, and their gates were satisfiable by baseline artifacts — the
|
||
Revision History chapter and the open S29 row both exist today. **Fixed** —
|
||
**pin 13** pins distinguishing content for each, and gates 10 and 15 are
|
||
rescoped to **added lines in the staged diff**. *Third occurrence of the
|
||
touch-row-without-a-pin class in this family, which is why it is pinned rather
|
||
than tidied.*
|
||
|
||
---
|
||
|
||
### REVISION F — review round 6. Three blockers, one precision issue. ALL ACCEPTED.
|
||
|
||
1. **[P1] Pin 10's pair matrix was incomplete, and M10's radius contradicted
|
||
it.** Only C6 and C7 had pinned witnesses; C4, C5, C8, C9 and C10 would have
|
||
been derived at execution. **Fixed** — the matrix is closed, and it
|
||
distinguishes two forms, because the checker does: **C4–C7's witnesses are
|
||
fixed strings and are pinned as equalities**; **C8–C10's are `format!`-built
|
||
and carry ids**, so what is pinned is the **discriminating substring** — enough
|
||
to separate same-label siblings without pinning `Debug` output a fixture
|
||
change would move. **M10's radius gains
|
||
`accidental_incompatible_reports_tuning_requirement`**: restoring the suffix
|
||
changes C10's witness, so every observer of that witness fails.
|
||
2. **[P1] M6 described an impossible selector outcome.** After C6 is mislabelled,
|
||
C7 still emits under `req:time:tempo-segment-order` from the same fixture, so
|
||
`check_requirement` for that label is **not** empty. **Fixed** — M6 pins the
|
||
real outcome: the expected **C6 pair** is absent while **C7's pair remains**,
|
||
and both assertions fail on the *pair*. *The old "returns nothing" rationale
|
||
contradicted the very masking that motivated pairs in revision E.*
|
||
3. **[P1] M13post did not sign both closing sentences.** Positive 4 was one
|
||
literal holding two independent sentences, and M13post deleted the whole
|
||
paragraph — so a guard implementing only the first sentence would still fail
|
||
it and satisfy the plan, leaving the **S8-neutrality sentence unobserved**.
|
||
**Fixed** — positives 4 and 5 are separate, with **M13post** and
|
||
**M13neutral** deleting one sentence each.
|
||
4. **[P2] Pin 11b's assertion shape moved the observation count.** Two predicates
|
||
as two assertions would make the module 5 observations and the inventory 26,
|
||
against gate 13's 25. **Fixed** — pinned as **one combined assertion**,
|
||
inventory unchanged at 25, and described as **combined witness predicates**
|
||
rather than an exact witness, since the full string carries `Debug` ids.
|
||
|
||
---
|
||
|
||
### REVISION E — review round 5. Four blockers, two smaller. ALL ACCEPTED.
|
||
|
||
1. **[P1] C6 could be masked by C7, so M6 was not guaranteed to fail.** C6's
|
||
natural fixture also overlaps, so after mislabelling C6 alone, C7 keeps
|
||
supplying `req:time:tempo-segment-order` and both label-only assertions still
|
||
pass. **Fixed** — pin 10's requirement-arm template asserts **`(kind,
|
||
witness)` pairs**, with the witnesses pinned verbatim from the checker:
|
||
`tempo segments are out of start order` and `tempo segments overlap in musical
|
||
time`. *The alternative isolated C6 fixture needs an end-before-start segment,
|
||
a shape the checker should never see.*
|
||
2. **[P1] Pin 11b's inventory was still wrong.** **Three** observations use
|
||
`witness.contains(…)`; the fourth is a `fires()` call observing selector
|
||
non-emptiness. **Fixed** in §0.4, pin 11b and revision D's record. The
|
||
"exact-witness assertion" also named no expected value — **now two exact
|
||
predicates**: the witness **ends with** `interval algebra` and **contains no**
|
||
`req:`. **M10's radius gains the legacy test**, which those predicates make it
|
||
fail.
|
||
3. **[P1] M16b risked proving the wrong assertion.** The test asserts
|
||
`accidental_extensions.is_empty()` *before* the selector call; inserting the
|
||
extension above that line trips the precondition first. **Fixed** — the
|
||
mutation is pinned complete and **ordered**: `let mut`, the emptiness
|
||
assertion kept in place, then the `edo-31` space and the `CmnChromatic`
|
||
extension inserted **after** it. Both edits are named so incompatibility is
|
||
not inferred.
|
||
4. **[P1] Pin 3 pinned a complete source that the guard only half observed.**
|
||
Deleting the opening `\MUST{}` sentence or the closing neutrality paragraph
|
||
passed pin 3a and every gate — and the second is the sentence that makes the
|
||
requirement S8-neutral in prose. **Fixed** — four exact positives covering
|
||
every sentence, with **M12pre** and **M13post** signing the two that were
|
||
unguarded.
|
||
5. **[P2] The stem guard did not specify case normalisation.** *"Canonically, …"*
|
||
escapes a case-sensitive search while M14a–c all still pass. **Fixed** — the
|
||
slice is lowercased before scanning, and **M14d** uses an uppercase stem to
|
||
sign the fold.
|
||
6. **[P2] M15a/M15b named an assertion but no test.** **Fixed** — both name
|
||
`tempo_segment_shape_requirement_states_its_clauses_and_stays_s8_neutral`.
|
||
|
||
---
|
||
|
||
### REVISION D — review round 4. Four blockers, three propagation errors. ALL ACCEPTED.
|
||
|
||
1. **[P1] Pin 11b contradicted pin 8a.** All four accidental observations
|
||
identify the rule by `v.witness.contains("accidental-modification-compatibility")`
|
||
— **the exact suffix pin 8a deletes**. *(Revision E: **three** of the four do;
|
||
the fourth is a `fires()` call.)* A selector-only migration would make
|
||
the positive fail and leave both negatives passing *vacuously*, since
|
||
`.all(|v| !v.witness.contains(…))` is true of every violation once the suffix
|
||
is gone. **Fixed** — pin 11b pins replacement **predicates**: negatives assert
|
||
`check_requirement(…).is_empty()`; the positive asserts non-empty plus a
|
||
label-free witness property.
|
||
2. **[P1] M9 and gate 13 had the negative-test logic backwards.** M9 makes
|
||
`check_requirement` return nothing, so both negatives **pass vacuously** and
|
||
are *not* in its radius — I had counted them as failures, asserting the very
|
||
vacuity the migration removes as though it were detection. And M1·C10 cannot
|
||
prove them non-vacuous: **their fixtures emit no violation to re-tag.**
|
||
**Fixed** — **M16a** and **M16b** make each negative's own fixture violate, and
|
||
M3/M9's legacy set is stated as **four test functions**, not nine
|
||
observations.
|
||
3. **[P1] Pin 3a claimed exact literals and supplied none**, and pin 3 never
|
||
pinned the requirement's source or placement, so M12/M13 were not literal
|
||
mutations. **M15's premise was also false** — the following requirement does
|
||
not carry the non-constant clause, and the later `end_tempo` occurrence is in
|
||
a rationale. **Fixed** — pin 3 pins the complete source and its placement;
|
||
pin 3a's positives are exact normalised literals from it; and the boundary is
|
||
observed **structurally**: the slice contains exactly one `\label{` and no
|
||
inner `\begin{requirement}`. **One assertion catches over-reach and
|
||
under-reach alike**, so **M15a/M15b** are ordinary failing mutations and the
|
||
start boundary is covered too.
|
||
4. **[P1] Gate 7 was unsatisfiable for M15**, which demanded a verbatim failing
|
||
assertion for a mutation whose success was another mutation ceasing to fail.
|
||
**Fixed by removing the passing control entirely** — §3 now states this rung
|
||
has **no passing-outcome mutation**, so gate 7 applies uniformly.
|
||
5. **[P2] §0.4 omitted `accidental_compatibility_tests`** from the measured blast
|
||
radius; revision C's correction reached pin 11 and gate 13 and stopped before
|
||
the section that claims to inventory the radius. **Fixed.**
|
||
6. **[P2] The live status still read revision B.** **Fixed.**
|
||
7. **[P2] §3 still said radii derive from pin 10's tests** — repeating the exact
|
||
omission revision C corrected. **Fixed** — pins 3a, 10 **and** 11.
|
||
|
||
---
|
||
|
||
### REVISION C — review round 3. Four blockers, three smaller. ALL ACCEPTED.
|
||
|
||
1. **[P1] Pin 11's table totalled 22.** The `f3_aleatoric_bounds` row already
|
||
counted its invariant-4 assertion, so "nine further" double-counted it.
|
||
**Measured and fixed** — eight further, in exactly the four tests the round
|
||
named: `f4_…offset_kind` 1, `f5_…tempo_conversion` 2, `f6_…namespaces` 3,
|
||
`f10_…member_notation` 2. Eight plus the `f3` invariant-4 gives the nine
|
||
other-invariant assertions; 12 CCRR + 9 = 21.
|
||
2. **[P1] The migration surface omitted `accidental_compatibility_tests`** —
|
||
four selector-based observations in three tests (`invariants.rs:4594`–`:4663`).
|
||
**Fixed** — pin 11b. **The sharper half is the two negatives:** they assert the
|
||
selector returns *empty*, so under pin 5 they stay green and go **vacuous**,
|
||
remaining green through any future accidental-compatibility regression. A
|
||
migration repairing only the loudly-failing test leaves two tests silently
|
||
weakened.
|
||
3. **[P1] §3 derived radii from pin 10 alone, ignoring the legacy observers.**
|
||
**Fixed** — M1 is derived per condition (including that **C6/C7 fail their
|
||
pin-10 test alone**, since the legacy fixture trips both and re-tagging one
|
||
leaves the assertion passing), M3 and M11 gain their legacy observers, and M9
|
||
is re-derived. **M9 also still named the deleted
|
||
`comprehensive_check_retains_both_arms` — a live one-hop error from revision
|
||
B, now removed and recorded as such.** **Pin 6a** newly *requires* the
|
||
architecture M9 assumed: both selectors are projections of `check_invariants`.
|
||
4. **[P1] Pin 3a was not a complete guard artifact.** **Fixed** — test name,
|
||
exact slice endpoint (the **first** `\end{requirement}`, because `end_tempo`
|
||
appears later in Chapter 3 and a loose slice would pass on another
|
||
requirement's prose), normalisation rule, exact positive literals, and a
|
||
**closed forbidden-stem inventory** — `canonic`, `normaliz`, `prefer` — with
|
||
**M14a, M14b, M14c** exercising each separately. **M15** is a passing-outcome
|
||
control that signs the slice endpoint itself.
|
||
5. **[P2] Touch row 1 omitted pin 3a.** **Fixed.**
|
||
6. **[P2] Revision B overclaimed M7's verification.** Six of the seven exist
|
||
today; `graph_invariant_all_is_unchanged` is **prospective**, pinned by pin 10.
|
||
**Fixed.**
|
||
7. **[P2] "No free-text arm" was literally inaccurate** — `Requirement` carries a
|
||
`&'static str`. **Fixed** — the rule is *no unclassified fallback arm*: every
|
||
violation names either a numbered invariant or a real requirement label.
|
||
|
||
---
|
||
|
||
### REVISION B — review round 2. Five blockers, two smaller. ALL ACCEPTED.
|
||
|
||
1. **[P1] Pin 10's assertion template was impossible for C1–C3.** It required
|
||
every condition to be *absent* from the invariant selector and returned by
|
||
`check_requirement` — but C1–C3 deliberately stay invariant 10. **Fixed** —
|
||
the template splits by arm, two assertions for the invariant arm and three for
|
||
the requirement arm.
|
||
2. **[P1] Pin 11's inventory was false.** Measured: `review_fix_tests_4` holds
|
||
**21 `fires()` assertions**, of which **12** target `CrossCuttingRefsResolve`
|
||
and 9 target other invariants; of the 12, **5 migrate and 7 stay**. My "21
|
||
`CrossCuttingRefsResolve` assertions" counted identifier occurrences over the
|
||
wrong line range. **Fixed** — pin 11 carries the per-test table, gate 13
|
||
requires 21 preserved / 5 migrated / 16 unchanged, and §0.4 and revision A's
|
||
record are swept.
|
||
|
||
*Two details only reading the tests reveals:* `f4`'s fourth assertion is a
|
||
**ghost region**, i.e. anchor existence, so it **stays**; and its out-of-order
|
||
fixture — `seg(2,3)` then `seg(1,2)` — trips **both C6 and C7** in one
|
||
assertion.
|
||
3. **[P1] M7 invented an implementation step and truncated its radius.** `shrink`
|
||
has no per-invariant `match`, so no passthrough is needed to compile.
|
||
**Fixed** — four pinned edits, and the radius is **seven** tests, because
|
||
`Probe22` enters `all()` with a fixture that violates nothing. **Six exist
|
||
today and were verified; `graph_invariant_all_is_unchanged` is prospective**,
|
||
pinned by pin 10 of this contract.
|
||
4. **[P1] Pin 3a's clause guard was present but unsigned.** M8 deletes the whole
|
||
requirement, proving only that the slice anchor exists. **Fixed** — M12, M13
|
||
and M14, one per clause. M14 is the one that matters: it is the edit a
|
||
well-meaning later reader would make, and it silently resolves P13-S8 inside a
|
||
requirement minted specifically not to.
|
||
5. **[P1] M2's radius named a test its pin left insensitive.**
|
||
`mixed_fixture_splits_by_arm` was specified against the aggregate only, which
|
||
widening `check_invariant` does not change. **Fixed** — pin 10 requires it to
|
||
exercise **all three surfaces**, M3's radius expands to match, and the
|
||
duplicate `comprehensive_check_retains_both_arms` is dropped rather than kept
|
||
as a second observation of the same assertion.
|
||
6. **[P2] M6 claimed all three assertions detect it.** Two do; the third is a
|
||
**positive control**. **Fixed.**
|
||
7. **[P2] Pin 1a attached the `BTreeSet` rationale to the wrong type.** It
|
||
constrains `ViolationKind: Ord`, not the struct's derives. **Fixed** — the
|
||
struct's retention is justified as public-API preservation, separately.
|
||
|
||
---
|
||
|
||
### REVISION A — review round 1. Nine findings, eight blocking. ALL ACCEPTED.
|
||
|
||
1. **[P1] Coverage was by label, not by emitted condition.** One fixture per
|
||
*label* can miss half of a shared label's surface — both tempo-shape
|
||
conditions, both order conditions, both aleatoric conditions. **Fixed** —
|
||
pin 10's matrix is **per condition**, and pin 11 pins the migration of
|
||
`review_fix_tests_4`'s assertions, preserving reversed aleatoric bounds as
|
||
**invariant 4**. *(This entry said "21 `CrossCuttingRefsResolve` assertions";
|
||
revision B measured 21 `fires()` assertions of which 12 target that variant.)* Without that pin, execution
|
||
could satisfy the suite by deleting or softening the tests that fail under
|
||
the new selector.
|
||
2. **[P1] The mutation matrix was neither executable nor exhaustive.** Radii
|
||
were guessed per mutation rather than derived against a named test set; M7
|
||
would have stopped at a non-exhaustive-match **compile error**, which
|
||
observes nothing; M8's radius was wrong. **Fixed** — §3 derives every radius
|
||
from pin 10's named tests, by construction, and M7 pins a complete compilable
|
||
variant.
|
||
3. **[P1] Gate 6 was unsatisfiable.** `DeferredCheck.invariant` is deliberately
|
||
retained (§0.5), and this contract and the ledger quote `InvariantViolation`
|
||
historically. **Fixed** — the identifier check is scoped to **Rust code**, and
|
||
the field migration to **`WellFormednessViolation` consumers**, with
|
||
`DeferredCheck.invariant` explicitly allowed.
|
||
4. **[P1] The contract's own lifecycle was unowned** — touch row 9 permitted a
|
||
status edit no pin required. **Fixed** — pin 12 and gate 14.
|
||
5. **[P1] Gate 12 contradicted itself**, requiring the baseline to stay at
|
||
`CLAUDE.md`'s figures while the rung adds tests. **Fixed** — gate 1 owns the
|
||
new total; gate 12 owns the *targeted* `requirement_labels` run with the
|
||
temporary row absent and the label defined.
|
||
6. **[P1] Pin 3's normative content was unobserved.** M8 proves only that a
|
||
block and label exist. **Fixed** — pin 3a adds a prose guard over the
|
||
requirement's clauses.
|
||
7. **[P1] The public API surface was incomplete**, and pin 4 overclaimed.
|
||
**Fixed** — pin 1a pins derives and documentation; pin 4 now says it
|
||
preserves rule **coverage**, not caller **meaning**, and lists what does
|
||
change.
|
||
8. **[P1] The accidental witness already embeds its own label**
|
||
(`invariants.rs:1594`), so the requirement `Display` form would render it
|
||
twice. **Fixed** — pin 8a strips the suffix, and the `Display` test uses a
|
||
**real** accidental violation, not a synthetic value.
|
||
9. **[P2] Touch row 1 carried a pre-change grep count.** "Five emission sites
|
||
re-tagged" is false: one must stay invariant 10, and the tempo site splits by
|
||
condition. **Fixed** — the row describes the transformation.
|
||
|
||
---
|
||
|
||
## §0. What was verified before drafting
|
||
|
||
### 0.1 The defect, and why it is not internal
|
||
|
||
`GraphInvariant::CrossCuttingRefsResolve` is emitted from **five sites in four
|
||
functions**. Only `check_cross_cutting_refs`, plus the tempo map's two
|
||
segment-anchor conditions, are reference resolution.
|
||
|
||
`check_invariant(score, which)` is `pub` and re-exported from `epiphany_core`'s
|
||
root, and `impl Display for InvariantViolation` renders:
|
||
|
||
```
|
||
invariant 10 (CrossCuttingRefsResolve) violated: non-constant tempo segment is missing its end_tempo
|
||
```
|
||
|
||
A Chapter 3 tempo rule, attributed in user-visible text to a Chapter 5 graph
|
||
invariant, through a public API.
|
||
|
||
### 0.2 The classification is per emitted condition, and it is P13-S26's
|
||
|
||
S26 derived and ruled it; this rung implements it. **Pin 10 carries the closed
|
||
matrix**; the summary is that anchor existence stays invariant 10 and the seven
|
||
rider conditions move to four labels.
|
||
|
||
### 0.3 `GraphInvariant` does not move
|
||
|
||
- `core_spec.tex` states **"This enumeration contains exactly 21 invariants"**.
|
||
- The enum is *"numbered as in §Graph Invariants"*, so a variant with no
|
||
enumeration entry has no number to return.
|
||
- S26 ruled invariant 10 stays **normatively** reference resolution.
|
||
|
||
Minting variants would also owe a negative generator and a shrink path each —
|
||
`every_invariant_has_a_negative_generator` and
|
||
`every_invariant_shrinks_to_a_small_witness` iterate `all()`. **This rung adds no
|
||
variant, so neither obligation grows.**
|
||
|
||
### 0.4 The blast radius, measured
|
||
|
||
- **No wire reach.** `GraphInvariant`'s only uses outside `epiphany-core` are two
|
||
**test-scope** sites in `reduce.rs` (nearest `#[cfg(test)]` at `:9663`), and
|
||
both name a *variant*, not the field.
|
||
- **`.invariant` on the violation type: four consumers outside `invariants.rs`** —
|
||
`tests/score_graph.rs` ×2, `src/generators.rs` ×2.
|
||
- **`review_fix_tests_4` (`invariants.rs:4217`–`:4591`) holds 21 `fires()`
|
||
assertions**, all via `check_invariant`. **12 target `CrossCuttingRefsResolve`;
|
||
9 target other invariants.** Of the 12, **5 are riders that migrate** and **7
|
||
are genuine invariant 10 that stay** — the split is pin 11's table. Pin 11 owns
|
||
all 21.
|
||
- **`accidental_compatibility_tests` (`invariants.rs:4594`–`:4663`) holds 4
|
||
selector-based observations in 3 tests**: **three** identify the rule by the
|
||
witness suffix pin 8a deletes, and **one** is a `fires()` call observing only
|
||
selector non-emptiness — see pin 11b, which is why a selector-only migration is
|
||
not enough.
|
||
- **`check_invariants` has ~10 consumer files.** Pin 4 keeps it comprehensive.
|
||
- **Current derives:** `#[derive(Clone, PartialEq, Eq, Debug)]`.
|
||
|
||
### 0.5 `DeferredCheck` is checked and excluded
|
||
|
||
It carries a `GraphInvariant` and renders *"invariant N (…) deferred"*, so it
|
||
resembles the defect. It is not: its only producer,
|
||
`deferred_region_overlaps`, tags `GraphInvariant::RegionExtents` — a **genuine**
|
||
invariant, correctly attributed. **Not renamed, not re-typed**, and its
|
||
`.invariant` field is explicitly exempt from gate 6.
|
||
|
||
### 0.6 The tempo-shape rule, and P13-S8
|
||
|
||
Enforced today, verbatim:
|
||
|
||
```rust
|
||
TempoShape::Constant => seg.end_tempo.as_ref().is_none_or(|et| et == &seg.start_tempo)
|
||
TempoShape::Linear | TempoShape::Exponential | TempoShape::Curve => seg.end_tempo.is_some()
|
||
```
|
||
|
||
**P13-S8 asks whether `Constant` + `Some(equal)` is canonical or normalizes to
|
||
`None`.** Pin 3 states the **compatibility** enforced today and takes no position
|
||
on canonical form, so the label survives whichever spelling S8 ratifies.
|
||
|
||
### 0.7 One consequence for P13-S26's landed text
|
||
|
||
S26's pin 5 put a note in the `/// 10.` doc block saying the riders *"are
|
||
reported under this same tag"*, naming P13-S29 as owner. **This rung makes that
|
||
false**, and pin 9 updates it. Not a violation of S26's frozen pin: pins govern
|
||
their own execution, not the tree forever.
|
||
|
||
---
|
||
|
||
## §1. Pins
|
||
|
||
### Pin 1 — the type becomes neutral
|
||
|
||
`InvariantViolation` → **`WellFormednessViolation`**; field `invariant` →
|
||
**`kind: ViolationKind`**. A type called `InvariantViolation` cannot honestly
|
||
carry a requirement failure, and the struct is public.
|
||
|
||
### Pin 1a — derives and documentation are pinned
|
||
|
||
- `WellFormednessViolation` **retains** `#[derive(Clone, PartialEq, Eq, Debug)]`
|
||
exactly, as measured in §0.4. The rationale is **public-API preservation**: the
|
||
struct is public, and a rung that renames a type has no business also narrowing
|
||
what callers can do with it.
|
||
- `ViolationKind` derives **`Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash,
|
||
Debug`** — matching `GraphInvariant`'s own derives. **`Ord` is load-bearing
|
||
independently:** `generators.rs` collects violation kinds into a `BTreeSet`,
|
||
which requires it. *That collection constrains this enum, not the struct's
|
||
derives; an earlier draft attached the rationale to the wrong type.*
|
||
- The module header and both types' rustdoc state the two-arm split and that a
|
||
requirement failure is **not** an invariant failure.
|
||
|
||
### Pin 2 — `ViolationKind` has exactly two arms
|
||
|
||
```rust
|
||
pub enum ViolationKind {
|
||
Invariant(GraphInvariant),
|
||
Requirement(&'static str),
|
||
}
|
||
```
|
||
|
||
**No third arm, and no unclassified fallback arm.** `Requirement` does carry
|
||
text — a `&'static str` label — so the rule is not "no text"; it is that **every
|
||
violation names either a numbered invariant or a real requirement label**, with
|
||
nothing in between. A condition with no label does not belong here, which is why
|
||
pin 3 mints one rather than adding an `Other`.
|
||
|
||
**The two-arm rule has an observer, because otherwise it has none.** A complete
|
||
third arm — variant, `Display` match arm, and no emitter — **compiles and leaves
|
||
every other gate green**, since nothing produces it. `violation_kind_has_exactly_two_arms`
|
||
therefore asserts the enum's shape: the source's `enum ViolationKind` block,
|
||
whitespace-collapsed, **equals** pin 2's declaration above. **M18** adds a
|
||
complete, compiling third arm with a `Display` arm and no emitter, and must fail
|
||
it.
|
||
|
||
### Pin 3 — `req:time:tempo-segment-shape` is minted, source and placement pinned
|
||
|
||
**Placement:** immediately after `req:time:tempo-segment-order`'s
|
||
`\end{requirement}` in `spec/core_spec.tex`, before whatever follows it.
|
||
|
||
**Source, verbatim — this is what execution writes:**
|
||
|
||
```latex
|
||
\begin{requirement}
|
||
\label{req:time:tempo-segment-shape}
|
||
A tempo segment's \texttt{shape} and its \texttt{end\_tempo} \MUST{} be
|
||
compatible. If \texttt{shape} is \texttt{Constant} and \texttt{end\_tempo}
|
||
is present, it \MUST{} equal \texttt{start\_tempo}. If \texttt{shape} is
|
||
\texttt{Linear}, \texttt{Exponential} or \texttt{Curve}, \texttt{end\_tempo}
|
||
\MUST{} be present.
|
||
|
||
This requirement states the compatibility that is enforced. It does not
|
||
determine whether a constant segment records an \texttt{end\_tempo} at all.
|
||
\end{requirement}
|
||
```
|
||
|
||
**It takes no position on canonical form.** P13-S8 decides whether `Constant` +
|
||
`Some(equal)` is canonical or normalizes to `None`; this text is true under
|
||
either, and the closing sentence says so without settling the question. *Pin 3a
|
||
observes this block by **exact equality**, so no phrase or stem inventory
|
||
governs its wording.*
|
||
|
||
Moves `requirement_labels.rs`' three counts. **Measured at execution, never
|
||
predicted.**
|
||
|
||
**Pin 3 also deletes the temporary allowlist row.** Naming the label broke the
|
||
citation gate immediately; one `DISCUSSED_NOT_CITED` row was added as
|
||
**prerequisite review scaffolding — not dispatch, licensing no other pin work** —
|
||
on the owner's authorization. Pin 3 removes it when it mints the requirement,
|
||
because the row's claim (*discussed, never cited*) becomes false then. Removed by
|
||
hand if S29 is abandoned or the label changes.
|
||
|
||
### Pin 3a — the requirement's clauses are guarded, and the guard is pinned
|
||
|
||
**Test:** `tempo_segment_shape_requirement_states_its_clauses_and_stays_s8_neutral`,
|
||
in `invariants.rs` beside pin 10's tests.
|
||
|
||
**Slice.** `spec/core_spec.tex`, whitespace-collapsed: from the
|
||
`\begin{requirement}` immediately preceding `\label{req:time:tempo-segment-shape}`
|
||
to the **first** `\end{requirement}` at or after that label.
|
||
|
||
**No separate structural boundary assertion.** Revision F added one — exactly one
|
||
`\label{`, no inner `\begin{requirement}` — to catch a mis-sliced block. **Under
|
||
equality it is redundant**: a slice extended past its `\end{requirement}` or
|
||
started at an earlier `\begin{requirement}` is *unequal* to pin 3's source and
|
||
fails on that. Retained as two assertions, M15a and M15b could no longer sign it
|
||
independently, since equality fails first. **It is retired, and M15a/M15b are
|
||
ordinary equality mutations.**
|
||
|
||
**Content assertion — normalised exact equality against pin 3's pinned source.**
|
||
The slice, whitespace-collapsed, **equals** pin 3's block, whitespace-collapsed.
|
||
Nothing weaker.
|
||
|
||
**Why equality rather than required phrases plus a forbidden-stem list.** Pin 3
|
||
declares the block *complete source*, so equality is the assertion that matches
|
||
the pin. Every weaker form leaves an **additive** hole: a guard checking five
|
||
required sentences and three forbidden stems passes on
|
||
|
||
```latex
|
||
A \texttt{Constant} segment's \texttt{end\_tempo} \MUST{} be absent.
|
||
```
|
||
|
||
which contains no `canonic`, `normaliz` or `prefer` — and **resolves P13-S8
|
||
inside a requirement minted specifically not to.** No closed stem inventory can
|
||
be trusted to anticipate the sentence someone will actually write. Equality needs
|
||
to anticipate nothing.
|
||
|
||
**The cost is intended:** any later edit to this requirement breaks the guard and
|
||
forces deliberate review, which is what a frozen normative block should do.
|
||
|
||
*(This replaces revision E's five positive literals and revision D's stem
|
||
inventory; both are subsumed. M12, M13, M13post, M13neutral and M14a–M14d all
|
||
now fail this one assertion, each with its own `assert_eq!` diagnostic naming
|
||
what differs.)*
|
||
|
||
### Pin 4 — `check_invariants` stays comprehensive
|
||
|
||
It returns **both** arms, so every broad caller keeps exactly the **rule
|
||
coverage** it has today and no rule stops being checked anywhere.
|
||
|
||
**It does not preserve caller *meaning*, and this pin does not claim to.** What
|
||
changes for callers: the type name, the field name and type, the targeted
|
||
selector's results (pin 5), `Debug` output, and the rider arm's `Display`.
|
||
|
||
### Pin 5 — `check_invariant` filters the `Invariant` arm only
|
||
|
||
Matches only `ViolationKind::Invariant(which)`. **This is the deliberate
|
||
behaviour change:** `check_invariant(score, CrossCuttingRefsResolve)` returns
|
||
**only genuine invariant-10 failures**.
|
||
|
||
### Pin 6 — `check_requirement` is added, symmetric
|
||
|
||
`check_requirement(score, label: &str) -> Vec<WellFormednessViolation>`, matching
|
||
only `ViolationKind::Requirement(label)`. A rung that made invariant failures
|
||
selectable while leaving requirement failures reachable only by scanning the
|
||
comprehensive result would have moved the asymmetry, not removed it.
|
||
|
||
### Pin 6a — both selectors are projections of `check_invariants`
|
||
|
||
`check_invariant` and `check_requirement` are **filters over the comprehensive
|
||
result**, not independent traversals. One traversal produces every violation;
|
||
each selector projects one arm out of it.
|
||
|
||
**Pinned because §3's M9 depends on it.** If the selectors traversed the score
|
||
independently, narrowing `check_invariants` would not reach them, and M9's radius
|
||
— the widest in the rung, and the measure of what pin 4 protects — would be
|
||
wrong. An architecture assumed by a mutation must be required by a pin.
|
||
|
||
### Pin 7 — the two `Display` forms are exact
|
||
|
||
- Invariant arm: `invariant {n} ({variant:?}) violated: {witness}` — **unchanged**.
|
||
- Requirement arm: `requirement {label} violated: {witness}`.
|
||
|
||
**A requirement failure never renders the word `invariant` and never renders a
|
||
number.**
|
||
|
||
### Pin 8 — `GraphInvariant` is untouched, and the freeze is sequence-signed
|
||
|
||
No variant added or removed; `number()` unchanged; `core_spec.tex`'s count claim
|
||
unchanged.
|
||
|
||
**`graph_invariant_all_is_unchanged` compares `GraphInvariant::all()` to this
|
||
canonical `(variant, number)` sequence, in order, by equality:**
|
||
|
||
```
|
||
EventVoiceBacklink=1 VoiceEventBacklink=2 VoiceEventsSortedNonOverlap=3
|
||
EventCoordinateModel=4 ContainmentTree=5 StaffInstanceResolves=6
|
||
RegionExtents=7 MeasureSingleInstance=8 AnchorOffsetModel=9
|
||
CrossCuttingRefsResolve=10 UniqueIdentifiers=11 PitchIdUnique=12
|
||
SpellingScopeResolves=13 DecompositionTargetResolves=14 DecompositionSum=15
|
||
TupletSum=16 TiePairing=17 VoiceOriginConsistent=18
|
||
BarlineGroupSameRegion=19 MeasureMeterConsistency=20 StaffGroupMembershipAgreement=21
|
||
```
|
||
|
||
**A length check is not the freeze.** M7 adds a 22nd entry, and a test asserting
|
||
only `all().len() == 21` fails it — while leaving unobserved: the same variants
|
||
in a **different order**, one entry **replaced or duplicated** with the length
|
||
still 21, and two `number()` arms **swapped**. M7a, M7b and M7c sign those three
|
||
independently.
|
||
|
||
**And `all()` is not the enum.** A **fully implemented 22nd variant that is
|
||
omitted from `all()`** leaves the canonical sequence untouched and every gate
|
||
green — the same hole M18 closes for `ViolationKind`, since a variant nothing
|
||
enumerates is a variant nothing observes. The test therefore carries a **second,
|
||
independent inventory**: the `enum GraphInvariant` **declaration** is read from
|
||
source and its variant list, in order, must equal the canonical sequence's.
|
||
**M7d** declares a complete 22nd variant with a `number()` arm and **no `all()`
|
||
entry**, and must fail on that inventory and nothing else.
|
||
|
||
### Pin 8a — the accidental witness stops embedding its label
|
||
|
||
`check_accidental_modification_compatibility`'s witness ends
|
||
`"… (req:tuning:accidental-modification-compatibility)"`. Under pin 7 the label
|
||
becomes the `Display` prefix, so the suffix **is deleted** — otherwise a real
|
||
violation renders the label twice.
|
||
|
||
**Pin 10's `Display` test uses a real accidental violation**, produced by the
|
||
checker, not a hand-built `WellFormednessViolation`. A synthetic value cannot
|
||
observe this, because the duplication lives in the *witness the checker writes*.
|
||
|
||
### Pin 9 — consumers migrate, and **every** live statement made false is corrected
|
||
|
||
The four `.invariant` consumers migrate to `.kind`. **The prose migration does not
|
||
stop at the `/// 10.` block.** Every live statement made false is pinned below;
|
||
**no count is stated**, because the set grew in two consecutive rounds and a
|
||
tally beside a table that can grow is the defect this family keeps finding:
|
||
|
||
| Site | What becomes false |
|
||
|---|---|
|
||
| `invariants.rs:8`, the module header | *"a typed [`InvariantViolation`] witness"* — gate 6 forbids that token in Rust code, so pin 1b pins its replacement, `` [`WellFormednessViolation`] `` |
|
||
| `invariants.rs`, the `/// 10.` doc block | S26's rider note: the riders are no longer *"reported under this same tag"*, and P13-S29 is no longer their pending owner. Rewritten to name the four labels |
|
||
| `invariants.rs:1421` region | the tempo-map header says its conditions are *"surfaced here under invariant 10"* |
|
||
| `invariants.rs:1500` region | the aleatoric header says dangling references *"go under invariant 10"* |
|
||
| `invariants.rs:1557` region | the accidental header says it is *"surfaced under an existing `GraphInvariant` tag rather than minting a new one"* — **it now carries its own requirement label.** The same comment cites `core_spec.tex:3120`, **a line locator already wrong before this rung**; it is replaced by the symbolic `req:tuning:accidental-modification-compatibility`, which is what it meant |
|
||
| `invariants.rs:4624` | the migrated negative's message calls it *"the compatibility invariant"* |
|
||
| `crates/epiphany-core/README.md:25` | exposes **`InvariantViolation`** and *"all 19 enumerated graph invariants"* — **the count was already stale** (20 since G3b, 21 since S16). **Its invariant-description cell is replaced with the text pin 9a pins; pin 9a is the sole authority and this row does not restate it** |
|
||
| `review_fix_tests_4`'s module doc | describes its subject as *"tempo-map segment invariants"* — after this rung they are requirements, not invariants |
|
||
| `check_invariants`' public rustdoc | does not say it returns **both** arms. Pin 4 makes comprehensiveness the property callers depend on; the doc must state it, since that is the one place a caller looks before relying on it |
|
||
|
||
**`crates/epiphany-core/DECISIONS.md:1061` records the multiplexing as current
|
||
policy**, wiring the accidental check into `check_invariants` as *"the
|
||
`req:tuning:accidental-modification-compatibility` invariant"*. **It is not
|
||
rewritten.** A decision record is a record of what was decided; it gains an
|
||
explicit **supersession note** naming P13-S29 and the date, leaving the original
|
||
decision legible. *Rewriting it would destroy the reasoning that made the
|
||
multiplexing defensible at the time, which is exactly what a later reader needs
|
||
in order to understand why it was accepted and then reversed.*
|
||
|
||
### Pin 1b — the public surface has observers
|
||
|
||
**As of the ratified input**, pin 1a's derives and rustdocs are prose that no
|
||
test or gate reads, and touch row 2's root re-export has **no complete explicit
|
||
observer**: the migrated `tests/score_graph.rs` will resolve `ViolationKind`
|
||
through the root, so the re-export is not unobserved outright — but no test names
|
||
all three exported items, so dropping `check_requirement` alone would leave the
|
||
suite green. *Scoped to the ratified input: once
|
||
this pin lands, both statements are false of the tree.*
|
||
|
||
**`crates/epiphany-core/tests/public_surface.rs`** — a new integration test,
|
||
`public_violation_surface_is_reexported`, **type-level only**:
|
||
|
||
```rust
|
||
use epiphany_core::{check_requirement, ViolationKind, WellFormednessViolation};
|
||
|
||
#[test]
|
||
fn public_violation_surface_is_reexported() {
|
||
let _: fn(&epiphany_core::Score, &str) -> Vec<WellFormednessViolation> = check_requirement;
|
||
let _ = |k: &ViolationKind| matches!(k, ViolationKind::Requirement(_));
|
||
}
|
||
```
|
||
|
||
**It calls nothing.** *A call whose result were **asserted** would put this test
|
||
in M3's and M9's radii; an ignored call would not, as M20f shows. The file stays
|
||
type-level so the question never arises — a function-item coercion and a
|
||
`matches!` arm observe the surface without producing a violation.*
|
||
|
||
**The re-export is compiler-observed, not mutation-observed.** `mod invariants`
|
||
is **private** (`lib.rs:76`), so deleting a name from the root re-export is an
|
||
**unresolved import** — a compile error, which observes nothing and which gate 7
|
||
cannot record as a failing assertion. It is in the same class as pin 1's rename:
|
||
the compiler is the observer.
|
||
|
||
**`violation_types_declare_their_pinned_derives`**, placed **inside
|
||
`mod g3a_tests`** — *not merely "beside pin 10's tests": `production_source()` is
|
||
a private `fn` of that module (`invariants.rs:4679`), so a guard anywhere else
|
||
cannot call it, and the alternatives (a second slicing helper, or widening that
|
||
one's visibility) add surface for no gain.*
|
||
|
||
**Six assertions, each an independent promise, each an EQUALITY, and each with
|
||
a pinned extraction boundary.**
|
||
|
||
| # | Slice — symbolic, never a file-wide search | Assertion |
|
||
|---|---|---|
|
||
| 1 | locate `pub struct WellFormednessViolation {`; take the line **immediately preceding** it | **equals** `#[derive(Clone, PartialEq, Eq, Debug)]` |
|
||
| 2 | locate `pub enum ViolationKind {`; take the line **immediately preceding** it | **equals** `#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]` |
|
||
| 3 | in the module header, from the pinned paragraph's **first line** through the **next blank `//!`** | **equals** the module paragraph below |
|
||
| 4 | locate `pub struct WellFormednessViolation {`; require its preceding line to be assertion 1's derive; take the contiguous `///` block **immediately preceding that derive** | **equals** the struct rustdoc below |
|
||
| 5 | the same, for `pub enum ViolationKind {` and assertion 2's derive | **equals** the enum rustdoc below |
|
||
| 6 | the whole of `public_surface.rs` | **equals** the fenced source above |
|
||
|
||
**Assertions 4 and 5 cannot say "immediately preceding the declaration": the
|
||
derive attribute sits between.** The algorithm is therefore three steps —
|
||
declaration, then its derive line, then the `///` block above *that*.
|
||
|
||
**Assertion 1 is unsound without its boundary.**
|
||
`#[derive(Clone, PartialEq, Eq, Debug)]` occurs **twice** in `invariants.rs`
|
||
today: on the violation type (`:249`) and on **`DeferredCheck`** (`:286`), which
|
||
§0.5 deliberately retains. **A file-wide search survives M20**, because removing
|
||
`Eq` from one leaves the other matching.
|
||
|
||
**Assertion 3 replaces nothing.** The module header is a **28-line `//!` run**
|
||
with paragraph breaks at `:2`, `:9`, `:13` and `:22`; asserting the whole run
|
||
equals a four-line paragraph would **delete 24 lines of retained header**. The
|
||
pinned paragraph is **inserted after the title paragraph's blank `//!`** — *not
|
||
prepended: prepending would make its first sentence the module's rustdoc summary
|
||
line, displacing "The Chapter 5 graph invariants"* — and the slice is bounded by
|
||
that paragraph's own first line and the next blank `//!`.
|
||
|
||
**The three prose blocks are pinned here as raw source**, not described. *Pin 1a
|
||
states a requirement; a requirement is not an expected value, and an executor
|
||
would otherwise write the production string and copy it into the test, which
|
||
asserts nothing.* **Each block states both of pin 1a's promises** — the two-arm
|
||
split, and that a requirement failure is not an invariant failure — *so pin 1a's
|
||
claim is true of each block individually, not merely of the three collectively.*
|
||
|
||
Module paragraph:
|
||
|
||
```rust
|
||
//! Violations carry a two-armed [`ViolationKind`]: `Invariant` for the Chapter 5
|
||
//! graph invariants, `Requirement` for a normative requirement named by its
|
||
//! label. A requirement failure is not an invariant failure, and neither arm is
|
||
//! a fallback for the other.
|
||
```
|
||
|
||
`WellFormednessViolation` rustdoc:
|
||
|
||
```rust
|
||
/// A well-formedness failure: one [`ViolationKind`] — `Invariant` or
|
||
/// `Requirement` — and the witness identifying the smallest offending objects.
|
||
/// A requirement failure is not an invariant failure.
|
||
```
|
||
|
||
`ViolationKind` rustdoc:
|
||
|
||
```rust
|
||
/// What a [`WellFormednessViolation`] failed. `Invariant` names a numbered
|
||
/// Chapter 5 graph invariant; `Requirement` names a normative requirement by its
|
||
/// label. A requirement failure is not an invariant failure, and there is no
|
||
/// third arm and no unclassified fallback.
|
||
```
|
||
|
||
**One retained header line must also be renamed, and pin 9 owns it:**
|
||
`invariants.rs:8` reads *"a typed [`InvariantViolation`] witness"*. **Gate 6
|
||
forbids that token in Rust code**, so leaving it unpinned would make gate 6
|
||
unsatisfiable; it becomes `` [`WellFormednessViolation`] ``, the rest of that
|
||
sentence unchanged.
|
||
|
||
**Every assertion has a NON-DELETION discriminator**, because deletion-only
|
||
mutations are satisfied by needle and subset implementations: **M20g** (1),
|
||
**M20i** (2), **M20j** (3), **M20k** (4), **M20h** (5), **M20f** (6). *"Additive"
|
||
would be inaccurate — M20i is a **reordering**. Revision P signed only 1 and 5
|
||
this way and left 2, 3 and 4 deletion-only, so a subset implementation of any of
|
||
those three passed the whole plan.*
|
||
|
||
**Assertion 6 is the whole file, not its import line.** *An import-only check
|
||
leaves the body free to start calling `check_requirement` — and a call whose
|
||
result were asserted would widen M3's and M9's radii, which is the outcome the
|
||
type-level constraint exists to prevent. It is not restated here: the fenced Rust block above is its sole
|
||
authority, one line per line, and a second "exact" spelling wrapped into Markdown
|
||
prose would be a different string.* **M20f** adds a call while keeping the
|
||
imports intact.
|
||
|
||
### Pin 9a — the README's invariant-description cell, verbatim
|
||
|
||
Raw source, fenced so it has exactly one interpretation:
|
||
|
||
```
|
||
`check_invariants` over all variants returned by `GraphInvariant::all()`, with a typed `WellFormednessViolation` witness per check
|
||
```
|
||
|
||
Gate 16 compares that row's second cell to this, by equality after whitespace
|
||
collapse. **Equality, not a numeral scan:** a scan over the line rejects the
|
||
correct edit — the row's final cell necessarily reads `Ch. 5 §"Graph Invariants"`
|
||
— and a scan for digits passes on *"all twenty-one variants"*, recreating the
|
||
defect without one.
|
||
|
||
### Pin 10 — the closed per-condition matrix, and the tests
|
||
|
||
**Coverage is per emitted condition, not per label.** Each row gets a fixture and
|
||
a named test. **The assertion template differs by arm**, because C1–C3 stay
|
||
invariant 10 and the requirement template is impossible for them:
|
||
|
||
- **C1–C3 (invariant arm), two assertions:** the aggregate `check_invariants`
|
||
result carries `ViolationKind::Invariant(CrossCuttingRefsResolve)`; and
|
||
`check_invariant(score, CrossCuttingRefsResolve)` **returns** it.
|
||
**Every C4–C10 fixture violates no invariant at all** — its aggregate
|
||
`check_invariants` result carries **no invariant-arm violation**, and that is a
|
||
**pinned fourth assertion** on each of the seven.
|
||
|
||
*The property is "no invariant arm", not "only its own violation": C6's fixture
|
||
emits **both** C6 and C7, as this contract establishes and as pairs exist to
|
||
handle. A cleanliness claim of "only its own" would be unsatisfiable for that
|
||
pair and for C7's.*
|
||
|
||
*This is what keeps those seven out of M2a's radius **structurally rather than by
|
||
assumption**. Each carries a negative `check_invariant` assertion; under M2a's
|
||
wildcard that assertion fails if the fixture emits **any** invariant violation.
|
||
An unrelated invariant tripped incidentally by a not-yet-built fixture would put
|
||
the test in M2a's cell — which the measured legacy set cannot anticipate, because
|
||
these fixtures do not exist yet. Requiring an empty invariant arm removes the
|
||
possibility instead of estimating it.*
|
||
|
||
- **C4–C10 (requirement arm), three assertions, each on a `(kind, witness)`
|
||
**pair**, never on the label alone:** the aggregate contains
|
||
`(Requirement(label), witness)` for that row; the same fixture yields
|
||
**nothing** from `check_invariant(score, CrossCuttingRefsResolve)`; and
|
||
`check_requirement(score, label)` **returns that pair**; and — the fourth —
|
||
the aggregate's **invariant arm is empty**.
|
||
|
||
**Pairs are required because three labels are shared by two conditions each, and
|
||
one fixture can trip both.** C6's natural fixture — `seg(2,3)` then `seg(1,2)` —
|
||
is *also* overlapping, so it emits C6 **and** C7 under the same label. A
|
||
label-only assertion would still pass after C6 alone was mislabelled, because C7
|
||
keeps supplying the label. The pinned witnesses, verbatim from the checker:
|
||
|
||
**The matrix is closed. C4–C7's witnesses are fixed strings in the checker and
|
||
are pinned exactly; C8–C10's are `format!`-built and carry ids, so what is pinned
|
||
is the discriminating substring** — enough to tell same-label siblings apart,
|
||
without pinning `Debug` output a fixture change would move.
|
||
|
||
| Condition | Assertion on the witness | Form |
|
||
|---|---|---|
|
||
| C4 | `constant tempo segment has end_tempo != start_tempo` | **equals**, fixed string |
|
||
| C5 | `non-constant tempo segment is missing its end_tempo` | **equals**, fixed string |
|
||
| C6 | `tempo segments are out of start order` | **equals**, fixed string |
|
||
| C7 | `tempo segments overlap in musical time` | **equals**, fixed string |
|
||
| C8 | contains `ordering references event` | **contains**, id-bearing |
|
||
| C9 | contains `bounds key event` | **contains**, id-bearing |
|
||
| C10 | ends with `interval algebra` **and** contains no `req:` — **one combined assertion** | **combined predicate**, id-bearing |
|
||
|
||
*The alternative to pairs — an isolated C6 fixture — would need an
|
||
end-before-start segment, which is unnatural and tests a shape the checker should
|
||
never see.*
|
||
|
||
| # | Emitted condition | Arm | Test |
|
||
|---|---|---|---|
|
||
| C1 | `check_cross_cutting_refs` — any condition | invariant 10 | `cross_cutting_refs_stay_invariant_ten` |
|
||
| C2 | tempo segment **`start`** anchor existence | invariant 10 | `tempo_start_anchor_stays_invariant_ten` |
|
||
| C3 | tempo segment **`end`** anchor existence | invariant 10 | `tempo_end_anchor_stays_invariant_ten` |
|
||
| C4 | `Constant` with `end_tempo` ≠ `start_tempo` | `req:time:tempo-segment-shape` | `tempo_constant_mismatch_reports_shape` |
|
||
| C5 | non-constant missing `end_tempo` | `req:time:tempo-segment-shape` | `tempo_nonconstant_missing_end_reports_shape` |
|
||
| C6 | segment start ordering | `req:time:tempo-segment-order` | `tempo_out_of_order_reports_order` |
|
||
| C7 | segment overlap | `req:time:tempo-segment-order` | `tempo_overlap_reports_order` |
|
||
| C8 | aleatoric **`ordering`** event outside region | `req:time:aleatoric-reference-locality` | `aleatoric_ordering_outside_region_reports_locality` |
|
||
| C9 | aleatoric **`bounds`** key outside region | `req:time:aleatoric-reference-locality` | `aleatoric_bounds_outside_region_reports_locality` |
|
||
| C10 | accidental modification expressibility | `req:tuning:accidental-modification-compatibility` | `accidental_incompatible_reports_tuning_requirement` |
|
||
| — | reversed aleatoric bounds | **invariant 4, unchanged** | `reversed_aleatoric_bounds_stay_invariant_four` |
|
||
|
||
**C4 and C5 share a label and are separate conditions; so do C6/C7 and C8/C9.
|
||
One fixture per label would leave one of each pair unexercised.**
|
||
|
||
**Whole-surface tests**, in addition:
|
||
|
||
- `mixed_fixture_splits_by_arm` — **the fixture is pinned**: one score carrying a
|
||
dangling tempo **`start`** anchor (C2) **and** an out-of-region aleatoric
|
||
**`ordering`** event (C8). **It exercises all three surfaces, not the aggregate
|
||
alone**, or it is insensitive to the selectors it exists to separate:
|
||
- the aggregate carries **both** kinds;
|
||
- `check_invariant(score, CrossCuttingRefsResolve)` returns **the anchor only**;
|
||
- `check_requirement(score, "req:time:aleatoric-reference-locality")` returns
|
||
**the rider only**.
|
||
|
||
*An aggregate-only form would leave M2 and M3 undetected here, which is why
|
||
§3's radii name this test for both.*
|
||
- `invariant_selector_discriminates_its_payload` — **a fixture violating two
|
||
different invariants**, C1's cross-cutting reference **and** a reversed
|
||
aleatoric bound (invariant 4). `check_invariant(score, CrossCuttingRefsResolve)`
|
||
returns **only** the invariant-10 violation; `check_invariant(score,
|
||
EventCoordinateModel)` returns **only** the invariant-4 one.
|
||
- `requirement_selector_discriminates_its_payload` — **a fixture violating two
|
||
different requirement labels**, C5's tempo shape **and** C8's aleatoric
|
||
locality. `check_requirement` for each label returns **only** that label's
|
||
violation.
|
||
|
||
*Both exist because every other fixture in pin 10 presents its selector with a
|
||
single variant or a single label. Against those, an implementation matching
|
||
`ViolationKind::Invariant(_)` or `ViolationKind::Requirement(_)` — **ignoring
|
||
the payload entirely** — satisfies every assertion. M2 and M3 sign arm
|
||
selection; these two and M2a/M3a sign that the selector reads its argument.*
|
||
|
||
- `display_renders_each_arm_exactly` — **two assertions on the requirement side,
|
||
in this order**, because the second alone is circular:
|
||
|
||
1. **independent:** the violation's `witness` contains **no** `req:`;
|
||
2. **then** `assert_eq!(violation.to_string(), format!("requirement {} violated: {}", label, witness))`,
|
||
the wrapper built from the witness assertion 1 has already checked.
|
||
|
||
*Assertion 2 alone cannot fail under M10: an expected string built from
|
||
`violation.witness` moves with the actual when the suffix returns. Assertion 1
|
||
is the independent oracle, and it is what makes M10 fail here.* **The invariant side's fixture is pinned: a reversed aleatoric bound**, which
|
||
emits `EventCoordinateModel` — invariant 4 — acquired from `check_invariants`
|
||
like the requirement side. *The choice changes radii, so it cannot be the
|
||
executor's: a C1 fixture would put this test in M17·C1's cell, a tempo-anchor
|
||
fixture in M17·C2/C3's, and reversed bounds put it in **M11's**, which is where
|
||
it now belongs and where M11's cell names it.*
|
||
|
||
**The violation is acquired from `check_invariants`, the aggregate — pinned,
|
||
not incidental.** Acquiring it through `check_requirement` would put this test
|
||
in M3's radius; through the aggregate it is not. *Leaving the path to the
|
||
executor would leave M3's cell true or false depending on a choice no pin
|
||
made.*
|
||
- `graph_invariant_all_is_unchanged` — the same 21, in order.
|
||
*`comprehensive_check_retains_both_arms` is **not** a separate test:* it would
|
||
duplicate the mixed fixture's first assertion exactly. Pin 4's coverage is
|
||
observed by that assertion and by M9's radius, which reaches every aggregate
|
||
assertion in the rung.
|
||
|
||
### Pin 11 — every legacy observer is migrated, not deleted
|
||
|
||
**Two modules observe the riders through the selector, and both are in scope.**
|
||
|
||
#### 11a — `review_fix_tests_4` (`invariants.rs:4217`–`:4591`), 21 assertions
|
||
|
||
| Test | Assertions | Disposition |
|
||
|---|---|---|
|
||
| `f3_aleatoric_dag_referencing_absent_event_fires` | 1 CCRR | **migrates** — C8 |
|
||
| `f3_aleatoric_bounds_key_absent_and_reversed_window_fire` | 1 CCRR + 1 `EventCoordinateModel` | the CCRR one **migrates** — C9; **the invariant-4 one is untouched** |
|
||
| `f4_tempo_segment_structural_defects_fire` | 4 CCRR | **3 migrate** — C5, C4, and one fixture tripping **both C6 and C7** (`seg(2,3)` then `seg(1,2)` is out of order **and** overlapping); **the 4th stays**, a ghost-region anchor — C2 |
|
||
| `f8_structural_reference_resolution` | 5 CCRR | **all stay** — genuine invariant 10 |
|
||
| `f9_dangling_decomposition_tuplet_reference_fires` | 1 CCRR | **stays** — genuine invariant 10 |
|
||
| `f4_tempo_segment_offset_kind_is_checked_by_invariant_9` | 1 `AnchorOffsetModel` | unchanged |
|
||
| `f5_overlapping_metric_regions_caught_via_tempo_conversion` | 2 `RegionExtents` | unchanged |
|
||
| `f6_time_signature_uniqueness_and_namespaces` | 3 `UniqueIdentifiers` | unchanged |
|
||
| `f10_tuplet_ratio_inconsistent_with_member_notation_fires` | 2 `TupletSum` | unchanged |
|
||
|
||
**21 preserved: 12 CCRR (5 migrate, 7 stay) + 9 other-invariant (1 in the `f3`
|
||
row above, 8 in the four rows beneath it).**
|
||
|
||
#### 11b — `accidental_compatibility_tests` (`invariants.rs:4594`–`:4663`), 4 observations in 3 tests
|
||
|
||
**A selector-only migration is insufficient here, and would leave the module
|
||
worse than it is now.** **Three** of the four observations identify the rule
|
||
through `v.witness.contains("accidental-modification-compatibility")` — **the
|
||
exact suffix pin 8a deletes**; the fourth is a `fires()` call, which observes
|
||
only selector non-emptiness.
|
||
|
||
| Test | Observations | Selector-only migration |
|
||
|---|---|---|
|
||
| `cmn_chromatic_accidental_in_edo_31_fires` | 2 — one `fires()`, one `witness.contains` | **Fails** — the witness no longer contains the label |
|
||
| `cmn_chromatic_accidental_in_cmn_12_does_not_fire` | 1 | **Passes vacuously** — `.all(|v| !v.witness.contains(…))` is true of *every* violation once the suffix is gone, including a real one |
|
||
| `a_score_with_no_accidental_extensions_never_fires_this_check` | 1 | **Passes vacuously**, same predicate |
|
||
|
||
**Pinned replacement predicates:**
|
||
|
||
- **Both negatives:** `check_requirement(&s, "req:tuning:accidental-modification-compatibility").is_empty()`.
|
||
The label moves from the witness text to the selector, which is where pin 2
|
||
put it.
|
||
- **The positive:** that same call is **non-empty**, and its witness is checked
|
||
by **one combined assertion** — *ends with* `interval algebra` **and** *contains
|
||
no* `req:`. **One assertion, not two**, so the module's observation count stays
|
||
at **4** and pin 11c's inventory stays at 25; splitting it would make the
|
||
inventory 26 and gate 13's figure wrong.
|
||
|
||
*These are **combined witness predicates**, not an exact witness: the full
|
||
string carries `Debug`-formatted ids that a fixture change would move. The
|
||
label is now the `Display` prefix; asserting it inside the witness is what pin
|
||
8a removed.*
|
||
|
||
**The two negatives are the sharper half.** A migration repairing only the loudly
|
||
failing test leaves two tests green, weaker than before, and reporting nothing.
|
||
|
||
#### 11c — the standing rule
|
||
|
||
**All 25 observations preserved. Exactly 9 migrated** (5 in 11a, 4 in 11b),
|
||
**and the 4 in 11b have their predicates replaced, not merely their selector**.
|
||
**Exactly 16 unchanged.** None deleted, none softened — *the failure mode this
|
||
pin prevents is an execution that makes the suite green by removing or hollowing
|
||
the tests that caught the change.*
|
||
|
||
**Reversed aleatoric bounds keep asserting invariant 4.** Correctly tagged before
|
||
this rung and not a rider; sweeping them into the requirement arm would introduce
|
||
the defect S29 removes.
|
||
|
||
### Pin 12 — this contract's own lifecycle
|
||
|
||
- **On ratification:** the status block reads exactly
|
||
`STATUS: RATIFIED; DISPATCHED.`, and the **frozen-pins statement** is added,
|
||
word for word as P13-S16, S27 and S26 carry it.
|
||
- **On landing:** exactly `STATUS: LANDED by this commit.` — **no hash**; a
|
||
commit cannot carry its own id, and if one is wanted it arrives by a later
|
||
administrative amendment.
|
||
- **On landing**, all review-round blocks above §0 are marked a **dated
|
||
historical record**.
|
||
|
||
Touch row 9 authorizes these edits; **this pin is what requires them.**
|
||
|
||
### Pin 13 — the two permanent history additions, with pinned content
|
||
|
||
Touch rows 5 and 8 license a `core_spec.tex` Revision History row and an S29
|
||
ledger append. **Neither was required by any pin, and neither gate could observe
|
||
one**: in the **ratified input** — the tree as it stands at ratification — the
|
||
Revision History chapter already exists and the S29 row is already present and
|
||
open, so a gate asserting their presence passes on the baseline artifact.
|
||
*Scoped to the ratified input deliberately: after execution the S29 row is
|
||
resolved, so a clause saying it "exists today, open" would be false at landing.* **This is the
|
||
third occurrence of the touch-row-without-a-pin class in this rung's family**
|
||
(S26's Revision History row, S26's own status block, and now these two), which is
|
||
why it is pinned rather than tidied.
|
||
|
||
**Revision History row — pinned source, verbatim.** Appended immediately before
|
||
`\bottomrule` in `core_spec.tex`'s Revision History `longtable`:
|
||
|
||
```latex
|
||
\today & \sectionsc{Graph Invariants}, \sectionsc{Time and Duration} &
|
||
\textbf{P13-S29: the violation tag stops multiplexing.} Graph invariant~10
|
||
reported Chapter~3 and Chapter~4 failures under its own number, through a
|
||
public API. The violation type becomes \texttt{WellFormednessViolation}
|
||
carrying a two-armed \texttt{ViolationKind}: an invariant arm and a
|
||
requirement arm naming a \texttt{req:} label. Invariant~10 keeps only
|
||
reference resolution; tempo segment shape, tempo segment order, aleatoric
|
||
reference locality and accidental modification expressibility now report
|
||
under their own requirements. \sectionsc{Time and Duration} gains
|
||
Requirement~\ref{req:time:tempo-segment-shape}, stating the enforced
|
||
shape/\texttt{end\_tempo} compatibility without determining whether a
|
||
constant segment records an \texttt{end\_tempo} at all. The enumeration is
|
||
unchanged.
|
||
\\
|
||
```
|
||
|
||
**The delimiter placement is pinned and was wrong in revision I.** The existing
|
||
final row already terminates with `\\` immediately before `\bottomrule`
|
||
(`core_spec.tex:17031`), so a block **beginning** with `\\` yields two separators
|
||
before the new row and none after it. The new row carries **no leading `\\` and a
|
||
terminating one**, and is inserted between that existing `\\` and `\bottomrule`.
|
||
|
||
**Extraction:** the contiguous run of **added** lines in
|
||
`git diff --cached -- spec/core_spec.tex` that lies inside the Revision History
|
||
chapter. Whitespace-collapsed, it **equals** the block above, likewise collapsed.
|
||
|
||
**S29 ledger append — pinned text, and an exact whole-line reconstruction.** The
|
||
ledger's S29 entry is a **single-line markdown table row**, so an append shows in
|
||
the diff as one removed line and one added line; **the added line is not the
|
||
append**. `APPEND` is exactly the following, as **raw source** — a fenced block,
|
||
not a blockquote, because blockquote `>` prefixes are part of the raw text and
|
||
whitespace-collapsing does not remove them, while the ledger row contains none:
|
||
|
||
```
|
||
**RESOLVED 2026-08-11 by `spec/CONTRACT_P13S29_VIOLATION_KIND.md`, disposition (b) type-neutral.** `InvariantViolation` becomes `WellFormednessViolation` with `kind: ViolationKind`, whose two arms are `Invariant(GraphInvariant)` and `Requirement(&'static str)`. `check_invariants` stays **comprehensive** — every broad caller keeps its rule coverage — while `check_invariant` deliberately narrows to the invariant arm and a symmetric `check_requirement` is added. `req:time:tempo-segment-shape` is minted for the one rider that had no label, stating enforced compatibility without resolving P13-S8. **`GraphInvariant` did not move: 21 variants, unchanged.**
|
||
```
|
||
|
||
**Extraction and comparison, exact — and the terminal delimiter is the trap.**
|
||
The S29 line **ends with the table's terminal `|`**, so the append goes *inside*
|
||
the row, before that delimiter; concatenating after the whole line would write
|
||
outside the table. Let `removed` and `added` be the S29 row's removed and added
|
||
lines. Then, whitespace-collapsed, with `strip(x)` removing a trailing `|` and
|
||
surrounding space:
|
||
|
||
**`strip(added) == strip(removed) + " " + APPEND`**, **and** `added` ends with
|
||
`|`.
|
||
|
||
*Revision I compared `added == removed + " " + APPEND`, which no correct edit can
|
||
satisfy. This compares the whole logical record without pinning the pre-existing
|
||
cell, and still rejects a truncated append — which carries the distinguishing
|
||
token and fails the equality.*
|
||
|
||
**Both gates observe the record, not a token — by different means, because the
|
||
two additions differ in shape. Neither is "the whole normalised added record":
|
||
that phrase described only gate 15 and was never true of gate 10.** Gate 15 slices the **added Revision History
|
||
row** out of `git diff --cached`'s additions and compares it, normalised, against
|
||
pin 13's block: a new table row is genuinely a run of added lines. **Gate 10
|
||
cannot do that**, because the S29 entry is one line and an append rewrites it —
|
||
so it uses the **removed-plus-added reconstruction** above, not an added-lines
|
||
check. *Checking for `req:time:tempo-segment-shape` or
|
||
`WellFormednessViolation` anywhere in the additions passes on a truncated or
|
||
misplaced record — the token is present, the record is not. Both gates therefore
|
||
compare the **whole logical record** — gate 15 the added row, gate 10 the
|
||
reconstruction — and a shortened addition fails either.*
|
||
|
||
|
||
---
|
||
|
||
## §2. Touch table
|
||
|
||
| # | Path | Why |
|
||
|---|---|---|
|
||
| 1 | `crates/epiphany-core/src/invariants.rs` | pins 1, 1a, **1b (its source guard lands here)**, 2, 3a (its guard lands here), 4, 5, 6, 6a, 7, 8, 8a, 9, 10, 11. **The transformation, not a re-tag count:** `check_cross_cutting_refs`' emission is unchanged; `check_tempo_maps`' single `flag` closure **splits by condition** into an invariant arm (C2, C3) and a requirement arm (C4–C7); `check_aleatoric_models`' two `CrossCuttingRefsResolve` pushes become requirement-arm (C8, C9) while its `EventCoordinateModel` push is untouched; `check_accidental_modification_compatibility`'s becomes requirement-arm (C10) and loses its witness suffix |
|
||
| 2 | `crates/epiphany-core/src/lib.rs` | re-exports: renamed type, `ViolationKind`, `check_requirement` |
|
||
| 3 | `crates/epiphany-core/src/generators.rs` | `.invariant` → `.kind` (two sites) |
|
||
| 4 | `crates/epiphany-core/tests/score_graph.rs` | `.invariant` → `.kind` (two sites) |
|
||
| 4a | `crates/epiphany-core/README.md` | pin 9 — the exposed type name, and the already-stale invariant count |
|
||
| 4b | `crates/epiphany-core/DECISIONS.md` | pin 9 — a supersession note; **the original decision is not rewritten** |
|
||
| 4c | `crates/epiphany-core/tests/public_surface.rs` | pin 1b's integration test, **new file** — the only **explicit three-name** observer of touch row 2's root re-export. *Not the only observer of that re-export: `tests/score_graph.rs` is an integration test too, and once its `.invariant` comparisons migrate it must resolve `ViolationKind` from the root, `invariants` being private* |
|
||
| 5 | `spec/core_spec.tex` | pin 3's requirement; Revision History row |
|
||
| 6 | `spec/core_spec.pdf` | tracked build product of row 5 |
|
||
| 7 | `crates/epiphany-testkit/tests/requirement_labels.rs` | pin 3's counts; pin 3's deletion of the temporary allowlist row |
|
||
| 8 | `spec/PASS13_CANDIDATES.md` | S29 status append |
|
||
| 9 | `spec/CONTRACT_P13S29_VIOLATION_KIND.md` | pin 12's transitions and historical marking |
|
||
| 10 | `spec/EVIDENCE_P13S29_EXECUTION.md` | gate evidence destination |
|
||
|
||
**Deliberately absent:** `epiphany-ops/src/reduce.rs` — its two `GraphInvariant`
|
||
uses are test-scope and pass a *variant* as an argument, and **`reduce.rs`
|
||
contains zero `.invariant` field accesses**, so it compiles unchanged.
|
||
**Re-verified before ratification, at revision K** — *not "at execution": pin 12
|
||
dispatches at ratification, so a row added "before dispatch" after an
|
||
execution-time discovery is temporally impossible. If this turns out wrong
|
||
during execution, **execution stops and an amendment adds the row**, like any
|
||
other frozen-pin defect.*
|
||
|
||
---
|
||
|
||
## §3. Mutation plan
|
||
|
||
Every guard is verified by re-introducing the defect and **observing** it. **A
|
||
compile error observed nothing.** Restore by hand-editing, never with git.
|
||
|
||
**Radii are derived against every observer this rung pins, in two classes.**
|
||
*Behavioural and classification* observers are pins 3a, 10 and 11; *structural*
|
||
observers — reading declarations rather than running the checker — are pins 1b,
|
||
2 and 8. **Not guessed, and not against pin 10 alone.** The derivation is given per row so
|
||
review can check it rather than take it. *Deriving against pin 10 alone was
|
||
revision C's finding 3; repeating the phrase would repeat the omission.*
|
||
|
||
**This rung has no passing-outcome mutation.** Every mutation below must produce
|
||
a failure, so gate 7 applies uniformly.
|
||
|
||
**Four cells were measured, not derived, and the difference matters.** Most radii
|
||
here follow from tests **this contract pins**. **M2a's and M17·C1–C3's** do not:
|
||
they reach pre-existing tests the contract did not write and whose fixtures it
|
||
does not control, so each was run against a disposable implementation and its
|
||
observed set pinned. *Every one of the four differed from what static reading
|
||
predicted — M2a by 10 false positives and 17 omissions, M17·C1 by naming 7 where
|
||
18 fail and including a test (`f4`) that belongs to C2, M17·C2 and C3 by
|
||
predicting legacy observers that measurement put at 1 and 0.*
|
||
|
||
**Execution measured a fifth and sixth cell, M1·C6 and M1·C7; amendment 1 records them and authorizes their corrected radii.** They are not among the four because they reach only tests this contract writes — the criterion that sent the other four to measurement was *reaching tests the contract did not write*, and that criterion was wrong. **The operative property is whether a fixture is shared, not who authored the test.**
|
||
|
||
**Static derivation was attempted and failed.** Revision I enumerated the 19
|
||
`!fires(…)` assertions and grouped them by score binding, yielding 13 tests.
|
||
**Measured against a disposable implementation — `check_invariant` with its
|
||
payload filter removed, full workspace, `--no-fail-fast` — the **pre-existing**
|
||
set is 20, and against revision I's derived 13 the two are almost disjoint: 3 in
|
||
common, 10 false positives, 17 missed.** *M2a's full radius is those 20 **plus**
|
||
`invariant_selector_discriminates_its_payload`, the test this rung adds; 20 is
|
||
the legacy figure, not the cell.*
|
||
|
||
Three reasons the static method could not work, each confirmed by the run:
|
||
|
||
- **Binding identity is not state identity.** Tests mutate the score between
|
||
assertions — `invariants.rs:3216` removes the overlap *before* its negative
|
||
assertion; `invariants.rs:4457` installs the tempo map only *after* one. A
|
||
positive assertion proves nothing about the state the negative selector sees.
|
||
- **`m35` was not one binding group at all** — its negative uses `lone` while its
|
||
positive builds a separate score (`invariants.rs:4939`), contradicting the
|
||
criterion outright.
|
||
- **`!fires(…)` was never the whole surface.** The mutation changes *every*
|
||
`check_invariant` consumer: direct zero-result assertions (`invariants.rs:5158`,
|
||
the S2/S7/S8 matrix cells), and behavioural consumers — **`generators.rs:953`,
|
||
where `shrink` uses the selector to choose candidates** — plus test-scope
|
||
consumers in `reduce.rs:16586`.
|
||
|
||
**The measured 20 are pinned in M2a's cell, alongside the new test.** *One caveat, stated because the
|
||
proxy is not the post-rung code: it was measured against today's single-arm type,
|
||
so it over-approximates for any test observing a **rider** violation through the
|
||
selector — after this rung those move to the requirement arm and `Invariant(_)`
|
||
will not return them. **None of the 20 is a rider test** (all are
|
||
`g3b_measure20_tests`, measure/meter territory), so the set is expected to hold;
|
||
execution confirms it and any difference is a finding.*
|
||
|
||
| M | Mutation (complete, applicable) | Must fail — exhaustively, and why |
|
||
|---|---|---|
|
||
| M1·C4…C10 | Re-tag **one** rider emission back to `ViolationKind::Invariant(CrossCuttingRefsResolve)` — **seven separate mutations, one per requirement condition** | That condition's pin-10 test, **plus its legacy observer, plus the requirement discriminator where it uses that condition**: `requirement_selector_discriminates_its_payload` is built from **C5 and C8**, so **M1·C5 and M1·C8 also fail it**. Derived per condition: **C4, C5** also fail `f4_tempo_segment_structural_defects_fire`; **C8** also fails `f3_aleatoric_dag_referencing_absent_event_fires` **and** `mixed_fixture_splits_by_arm` (C8 is in the pinned mixed fixture); **C9** also fails `f3_aleatoric_bounds_key_absent_and_reversed_window_fire`; **C10** also fails the migrated `cmn_chromatic_accidental_in_edo_31_fires` **and** `display_renders_each_arm_exactly`, whose requirement side uses a real accidental violation. **C6 and C7 each fail *both* pin-10 order tests, and the legacy `f4` assertion fails for neither.** `f4` holds one fixture tripping both conditions and asserts on the label, so the surviving sibling keeps supplying it — but pin 10's C6 and C7 tests stand in that same relation to *each other*: both are `two_segments(seed, (2, 3), (1, 2))`, which pin 10 establishes emits C6 **and** C7. Re-tagging either puts an `Invariant` violation into both fixtures, so the sibling's **fourth** assertion — *the aggregate's invariant arm is empty* — fails alongside the mutated condition's own pair assertion. **Measured, not derived; the fixtures are shared by pin 10's deliberate choice and cannot be separated without the end-before-start segment pin 10 rejects.** |
|
||
| M2 | `check_invariant` matches both arms | **All seven** C4–C10 tests, via their absence assertion, **and** `mixed_fixture_splits_by_arm`, which pin 10 now requires to exercise **both selectors** and not only the aggregate. *Not* C1–C3, which assert presence and are unaffected by widening |
|
||
| M2a | `check_invariant` matches `ViolationKind::Invariant(_)`, ignoring `which` — **the wildcard replaces the payload match; the requirement arm is untouched** | `invariant_selector_discriminates_its_payload`, **and the 20 existing tests measured below**, all in `invariants::g3b_measure20_tests`: `agreement_and_boundary_hold_together`, `m35_pickup_successor_boundary_flags_wrong_distance`, `m37_incomparable_abstains`, `m38_pickup_first_measure_boundary_clause_not_flagged`, `m39_unresolvable_reference_is_invariant_10_only`, `matrix_a1_none_time_signature_inapplicable`, `matrix_a3_vacuous_agreement`, `matrix_b2_governing_signature_unresolving_delegated`, `matrix_b3_vacuous_boundary`, `matrix_s1_wallclock_measures_wallclock_meter_changes`, `matrix_s2_agreement_a4`, `matrix_s2_boundary_b4`, `matrix_s4_measure_same_id_end_end_decides`, `matrix_s5_measure_distinct_ids_start_zero`, `matrix_s6_event_same_id_live_event_decides`, `matrix_s7_agreement_a4`, `matrix_s7_boundary_b4`, `matrix_s8_agreement_a4`, `matrix_s8_boundary_b4`, `matrix_s9_heterogeneous_measure_anchors` |
|
||
| M3a | `check_requirement` matches `ViolationKind::Requirement(_)`, ignoring `label` | `requirement_selector_discriminates_its_payload` **alone**. Every other requirement-arm fixture presents its selector with **one** label, so a wildcard returns the same set as an exact match. *Not M6's test either — but not for the reason an earlier draft gave: M6 is a **separate** mutation, so under M3a alone C6 and C7 still carry the same label, and one fixture with one label cannot distinguish wildcard from exact* |
|
||
| M3 | `check_requirement`'s predicate is **replaced** — not supplemented — by `matches!(v.kind, ViolationKind::Invariant(_))`, matching **every** invariant variant and **no** requirement label | **All seven** C4–C10 tests via their retrieval assertion; `mixed_fixture_splits_by_arm` under pin 10's strengthened form; **and every migrated positive legacy observer.** Counted as **test functions, not observations**, the legacy set is exactly four: `f3_aleatoric_dag_referencing_absent_event_fires`, `f3_aleatoric_bounds_key_absent_and_reversed_window_fire`, `f4_tempo_segment_structural_defects_fire`, `cmn_chromatic_accidental_in_edo_31_fires`; **and `requirement_selector_discriminates_its_payload`**, whose exact projections both go empty. *The two migrated negatives assert emptiness and **pass** under M3 — they are not in this radius* |
|
||
| M4 | Render the requirement arm with the invariant form | `display_renders_each_arm_exactly` |
|
||
| M5 | Render the invariant arm with the requirement form | `display_renders_each_arm_exactly` |
|
||
| M6 | Give C6's emission the label `req:time:tempo-segment-shape` | `tempo_out_of_order_reports_order` **alone**, via **two** of its three assertions, and the outcome is pinned precisely because the masking makes it counter-intuitive: **`check_requirement(score, "req:time:tempo-segment-order")` is NOT empty** — C7 still emits under that label from the same fixture — but **the expected C6 pair `(Requirement(order), "tempo segments are out of start order")` is absent** while C7's pair remains, so both the aggregate and the selector assertions fail on the *pair*. **The third — targeted invariant-10 absence — still passes**, the kind remaining a `Requirement`; it is a positive control here, not a detector. *An earlier draft said the selector "returns nothing", contradicting the very masking that motivated pairs* |
|
||
| M7 | Add a 22nd variant **completely, and only these four edits**: the `GraphInvariant::Probe22` variant, a `number() => 22` arm, an `all()` entry **with its array length raised**, and a `violating_score` arm returning an unmodified valid score. **No `shrink` edit** — `shrink(score, inv)` has no per-invariant `match` and needs none to compile | **Seven tests**, because `Probe22` enters `all()` with a fixture that violates nothing: `graph_invariant_all_is_unchanged`; `m40_check_invariants_dispatches_invariant_20`; `every_invariant_has_a_negative_generator`; `every_invariant_shrinks_to_a_small_witness`; `shrink_is_idempotent`; `negative_generators_are_reasonably_targeted`; `full_invariant_sweep_via_public_api`. *An earlier draft named two and invented a `shrink` step* |
|
||
| M7a | **Order only:** swap the `all()` entries for `TupletSum` and `TiePairing`, leaving membership and `number()` untouched | `graph_invariant_all_is_unchanged` **alone** — length is 21 and membership identical, so nothing else notices |
|
||
| M7b | **Membership only:** replace `all()`'s `PitchIdUnique` entry with a second `TupletSum`, length still 21 | `graph_invariant_all_is_unchanged` **alone**. *Revision L also named `every_invariant_has_a_negative_generator`; that is false — it iterates `all()`, so it simply visits `TupletSum` twice and never asks for `PitchIdUnique`. A test driven by the mutated list cannot detect an omission from that list* |
|
||
| M7c | **`number()` only:** swap the arms for `BarlineGroupSameRegion` and `MeasureMeterConsistency` (19 ⇄ 20), leaving `all()` untouched | `graph_invariant_all_is_unchanged` **alone** — `all()` is identical and only the mapping moves |
|
||
| M7d | Declare a complete 22nd variant `GraphInvariant::Probe22` with a `number() => 22` arm **and a `violating_score` arm returning an unchanged valid score**, while **omitting it from `all()`** | `graph_invariant_all_is_unchanged`'s **declaration inventory alone** — `all()` is unchanged, so the sequence check passes and every generator test still enumerates 21. **The `violating_score` arm is required for the mutation to compile at all:** that function matches exhaustively on `GraphInvariant` (`generators.rs:502`), so a variant without an arm is a compile error, which observes nothing |
|
||
| M17·C1 | Re-tag `check_cross_cutting_refs`' emission to `ViolationKind::Requirement("req:time:tempo-segment-order")` | **Measured, 18 existing tests:** `full_invariant_sweep_via_public_api`, `every_invariant_has_a_negative_generator`, `every_invariant_shrinks_to_a_small_witness`, `negative_generators_are_reasonably_targeted`, `shrink_is_idempotent`, `m39_unresolvable_reference_is_invariant_10_only`, `matrix_b2_governing_signature_unresolving_delegated`, `inv10_resolves_annotation_layer_and_tuplet_parent`, `inv10_resolves_event_internal_references`, `inv10_resolves_graphic_object_references`, `inv10_flags_dangling_staff_instrument`, `inv10_flags_unresolved_time_signature_reference`, `f8_structural_reference_resolution`, `f9_dangling_decomposition_tuplet_reference_fires`, `inv10_flags_dangling_marker_lyric_and_gesture_refs`, `inv10_flags_dangling_repeat_kind_and_volta_anchors`, `inv10_flags_dangling_spanner_anchor`, `inv10_flags_dangling_sub_beam_event` — **plus** the new `cross_cutting_refs_stay_invariant_ten` and `invariant_selector_discriminates_its_payload`. *Revision L guessed 7, named `f4`, and missed the four generator tests entirely: `violating_score(CrossCuttingRefsResolve)` stops violating it, so the whole generator battery fails* |
|
||
| M17·C2 | Re-tag the tempo segment **`start`** anchor condition to `ViolationKind::Requirement("req:time:tempo-segment-order")` — **the label is pinned, since a different one changes which `check_requirement` call retrieves it** | **Measured: exactly one existing test**, `f4_tempo_segment_structural_defects_fire` — its ghost-region assertion, which is C2's and **not C1's** — **plus** the new `tempo_start_anchor_stays_invariant_ten` and `mixed_fixture_splits_by_arm` |
|
||
| M17·C3 | Re-tag the tempo segment **`end`** anchor condition to `ViolationKind::Requirement("req:time:tempo-segment-order")`, label pinned as above | **Measured: no existing test** — nothing in the tree carries a dangling tempo *end* anchor. Its radius is the new `tempo_end_anchor_stays_invariant_ten` **alone** |
|
||
| M20 | Remove `Eq` from `WellFormednessViolation`'s derives | `violation_types_declare_their_pinned_derives`, **assertion 1 alone**. *`Eq` is chosen because dropping it still compiles — `BTreeSet` needs `Ord` on `ViolationKind`, not `Eq` on the struct — so the guard is the only observer* |
|
||
| M20a | Remove `Hash` from `ViolationKind`'s derives | that test, **assertion 2 alone**. *`Hash` compiles without it; `Ord` would not, and a compile error observes nothing* |
|
||
| M20b | Delete the two-arm sentence from the module header | that test, **assertion 3 alone** |
|
||
| M20c | Delete `WellFormednessViolation`'s rustdoc | that test, **assertion 4 alone** |
|
||
| M20d | Delete `ViolationKind`'s rustdoc | that test, **assertion 5 alone** |
|
||
| M20e | Remove `ViolationKind` from `public_surface.rs`'s `use` line, dropping the `matches!` line with it so it still compiles | that test, **assertion 6 alone** |
|
||
| M20f | Add to `public_surface.rs`, keeping all three imports: `let _ = check_requirement(&epiphany_core::generators::valid_score(1), "req:time:tempo-segment-shape");` — **fully qualified, because the file imports only the three pinned names and `valid_score` lives at `epiphany_core::generators`** | that test, **assertion 6 alone**. **What it signs is the file-content prohibition, not a radius change:** this call discards its result, so it would *not* by itself put the test in M3's or M9's radius. The prohibition exists because a call whose result were **asserted** would, and assertion 6 is what keeps the file type-level so that never arises |
|
||
| M20g | Add `Hash` to `WellFormednessViolation`'s derives | that test, **assertion 1 alone** — *and it is the discriminator: a guard that searches for the pinned traits rather than comparing the line accepts an added one* |
|
||
| M20h | Append to `ViolationKind`'s rustdoc the line `/// Both arms are exhaustive over what the checker reports.` | that test, **assertion 5 alone** |
|
||
| M20i | **Reorder** `ViolationKind`'s derive list to `#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]` | that test, **assertion 2 alone**. *Reordering rather than adding, because every trait a simple field-less-payload enum can usefully derive is already there; a needle check for each trait passes on a reordering, and only equality fails* |
|
||
| M20j | Append to the module header's pinned paragraph the line `//! The arms are disjoint by construction.` | that test, **assertion 3 alone** |
|
||
| M20k | Append to `WellFormednessViolation`'s rustdoc the line `/// The witness is human-readable and not parsed.` | that test, **assertion 4 alone** |
|
||
| M18 | Add a **complete, compiling** third arm to `ViolationKind`: `Deferred(GraphInvariant)`, a `Display` match arm rendering it, and **no emitter anywhere** | `violation_kind_has_exactly_two_arms` **alone** — nothing emits it, so no classification, selector or `Display` test can observe it. *That is precisely why the arm count needs its own guard, and why this row must exist in §3: gate 7 covers §3's mutations, so a mutation named only in a pin is a mutation nothing runs* |
|
||
| M8 | Delete pin 3's requirement from `core_spec.tex` | `every_requirement_block_has_one_label`, `requirement_labels_follow_the_grammar`, `requirement_labels_are_unique_across_the_suite` — the three count-bearing tests — **and** `every_requirement_citation_is_defined`, since this contract cites the label. **Also** `tempo_constant_mismatch_reports_shape` and `tempo_nonconstant_missing_end_reports_shape`? **No** — the Rust label string is independent of the `.tex` block. **And** pin 3a's prose guard, whose slice anchor disappears |
|
||
| M9 | Narrow `check_invariants` to the `Invariant` arm | **Every observer of a requirement-arm violation, because pin 6a makes both selectors projections of it:** all seven C4–C10 tests; `mixed_fixture_splits_by_arm`; `display_renders_each_arm_exactly`, whose requirement side needs a real violation to exist; and the **four migrated legacy test functions** — `f3_aleatoric_dag_referencing_absent_event_fires`, `f3_aleatoric_bounds_key_absent_and_reversed_window_fire`, `f4_tempo_segment_structural_defects_fire`, `cmn_chromatic_accidental_in_edo_31_fires`; **and `requirement_selector_discriminates_its_payload`**. **The two migrated negatives are NOT in this radius:** M9 makes `check_requirement` return nothing, so their emptiness assertions **pass vacuously**. *An earlier draft had this backwards and counted them as failures — the same vacuity the migration exists to remove, asserted as if it were detection.* *Widest radius in the rung, and the measure of what pin 4 protects.* **`comprehensive_check_retains_both_arms` is NOT in this radius: revision B deleted it, and naming it here was a live one-hop error, not a historical quotation** |
|
||
| M10 | Restore the witness suffix `" (req:tuning:accidental-modification-compatibility)"` | `display_renders_each_arm_exactly` — the requirement side, whose expected string is exact and whose fixture is a real violation — **the migrated `cmn_chromatic_accidental_in_edo_31_fires`**, whose pinned witness predicate forbids `req:`, **and `accidental_incompatible_reports_tuning_requirement`**, whose C10 pair assertion carries the same predicate. *Earlier drafts named one, then two; restoring the suffix changes C10's witness, so every observer of that witness fails* |
|
||
| M11 | Retag reversed aleatoric bounds from `EventCoordinateModel` to the locality requirement | `reversed_aleatoric_bounds_stay_invariant_four`; **`display_renders_each_arm_exactly`, whose invariant-side fixture is that violation**; the legacy `f3_aleatoric_bounds_key_absent_and_reversed_window_fire`, whose invariant-4 assertion pin 11a leaves untouched; **and `invariant_selector_discriminates_its_payload`, whose invariant-4 half is that very violation and disappears** |
|
||
| M12pre | Delete pin 3's opening sentence — `A tempo segment's \texttt{shape} and its \texttt{end\_tempo} \MUST{} be compatible.` | `tempo_segment_shape_requirement_states_its_clauses_and_stays_s8_neutral`, **its equality** |
|
||
| M12 | Replace clause 2 with `If \texttt{shape} is \texttt{Constant}, \texttt{end\_tempo} \MUST{} equal \texttt{start\_tempo}.` — dropping *is present* | that test, **its equality** |
|
||
| M13 | Delete clause 3 — `If \texttt{shape} is \texttt{Linear}, \texttt{Exponential} or \texttt{Curve}, \texttt{end\_tempo} \MUST{} be present.` | that test, **its equality** |
|
||
| M13post | Delete only `This requirement states the compatibility that is enforced.`, keeping the sentence after it | that test, **its equality** |
|
||
| M13neutral | Delete only `It does not determine whether a constant segment records an \texttt{end\_tempo} at all.`, keeping the sentence before it | that test, **its equality**. *This is the sentence that keeps the requirement S8-neutral in prose. A mutation deleting the whole paragraph cannot sign it, because a guard checking only the first sentence would fail that too* |
|
||
| M14a | Append to the block: `A \texttt{Constant} segment's \texttt{end\_tempo} is canonically absent.` | that test, **its equality** |
|
||
| M14b | Append: `A \texttt{Constant} segment's \texttt{end\_tempo} is normalized to absent.` | that test, **its equality** |
|
||
| M14c | Append: `The preferred spelling omits \texttt{end\_tempo}.` | that test, **its equality** |
|
||
| M14d | Append: `Canonically, a \texttt{Constant} segment omits \texttt{end\_tempo}.` | that test's equality |
|
||
| M14e | Append: `A \texttt{Constant} segment's \texttt{end\_tempo} \MUST{} be absent.` — **stem-free, and it resolves P13-S8** | that test's equality. **This is the mutation the stem inventory could not catch**, and the reason pin 3a asserts equality: it uses no forbidden stem, states no preference, and settles S8 outright |
|
||
| M15a | Extend pin 3a's slice end to the **second** `\end{requirement}` | `tempo_segment_shape_requirement_states_its_clauses_and_stays_s8_neutral`, **its equality** — the slice is longer than pin 3's source |
|
||
| M15b | Start pin 3a's slice at the **preceding** `\begin{requirement}` | the same test and assertion, from the other direction. *Equality catches over- and under-reach alike; the separate structural assertion revision F added is retired as redundant* |
|
||
| M16a | In `cmn_chromatic_accidental_in_cmn_12_does_not_fire`, change the fixture's space from `cmn-12` to `edo-31`, making the accidental **incompatible** | that test, migrated — its `check_requirement(...).is_empty()` becomes false. **This is what proves the negative is non-vacuous**; M1·C10 cannot, because this fixture emits no violation to re-tag |
|
||
| M16b | In `a_score_with_no_accidental_extensions_never_fires_this_check`, **complete and ordered**: change `let s = valid_score(301);` to `let mut s = valid_score(301);`; **keep the existing `assert!(s.tuning_context.accidental_extensions.is_empty());` where it is**; then, **after** it and **before** the selector call, insert `s.tuning_context.default_pitch_space = PitchSpaceId::new("edo-31");` and `s.tuning_context.accidental_extensions.push(fixture_extensions("cmn-accidentals", PitchSpaceModification::CmnChromatic(1)));` | that test, migrated — its `check_requirement(…).is_empty()` becomes false. **The ordering is pinned, not incidental:** inserting the extension *before* the emptiness assertion trips that precondition first and proves nothing about selector non-vacuity. Both edits are needed for incompatibility: the space must be `edo-31` *and* the accidental `CmnChromatic`, exactly as `cmn_chromatic_accidental_in_edo_31_fires` builds it |
|
||
|
||
---
|
||
|
||
## §4. Gate
|
||
|
||
1. `cargo test --workspace` — **the `CLAUDE.md` baseline plus this rung's
|
||
net-new tests**, 0 failed, 0 ignored. **Gate 1 owns the new total.**
|
||
`--no-fail-fast` whenever anything is failing.
|
||
2. `cargo +1.95.0 clippy --workspace --all-targets -- -D warnings` — clean.
|
||
3. `cargo +1.95.0 fmt -p epiphany-core -p epiphany-testkit --check` — clean.
|
||
**Never `--all`.**
|
||
4. Every staged path is a §2 row; every §2 row staged or named unused.
|
||
5. `git diff --cached --check` clean.
|
||
6. **Identifier and field migration, scoped:**
|
||
- no `InvariantViolation` identifier remains **in Rust code** (`crates/**/*.rs`).
|
||
*This contract, the ledger and the annex quote it historically and are out of
|
||
scope;*
|
||
- no `.invariant` field access remains **on a `WellFormednessViolation`**.
|
||
**`DeferredCheck.invariant` is explicitly retained** (§0.5) and must still be
|
||
present.
|
||
Both greps recorded verbatim.
|
||
7. Every mutation of §3 observed, with the failing assertion verbatim and the
|
||
complete `--no-fail-fast` failure set, compared against its derived cell; any
|
||
mismatch is a finding. Evidence into `spec/EVIDENCE_P13S29_EXECUTION.md`.
|
||
8. **`GraphInvariant::all()` re-derived and confirmed at 21**, and
|
||
`core_spec.tex`'s count claim confirmed unchanged.
|
||
9. `cd spec && latexmk -xelatex -interaction=nonstopmode core_spec` — re-run
|
||
until *"There were undefined references"* clears; `core_spec.pdf` rebuilt.
|
||
10. **S29's ledger append**, verified by pin 13's **removed-plus-added
|
||
reconstruction**: `strip(added) == strip(removed) + " " + APPEND` with the
|
||
terminal `|` restored on `added`. **Not an added-lines-only check** — that
|
||
instruction was superseded, and an added line here is the *whole row*, not
|
||
the append.
|
||
11. **The temporary allowlist row is ABSENT** from the staged
|
||
`requirement_labels.rs`, and the two surviving rows are present and
|
||
unchanged. *A stale temporary row is **inert** once the label exists —
|
||
nothing but this gate would catch it.*
|
||
12. **`cargo test -p epiphany-testkit --test requirement_labels` passes with the
|
||
temporary row absent and the label defined.** This, with gate 11, is what
|
||
distinguishes *the citation gate passes because the label is now defined*
|
||
from *because it is still allowlisted* — states indistinguishable from
|
||
outside.
|
||
13. **Pin 11's inventory recorded and confirmed**, both modules: **25**
|
||
observations preserved, exactly **9** migrated (5 in `review_fix_tests_4`, 4
|
||
in `accidental_compatibility_tests`), exactly **16** unchanged, none deleted
|
||
and none softened. **The two migrated negative accidental assertions are
|
||
confirmed non-vacuous by M16a and M16b**, each of which makes its own fixture
|
||
violate. *M1·C10 cannot do this: those fixtures emit no violation to re-tag.*
|
||
14. **Pin 12's lifecycle:** the status block reads exactly
|
||
`STATUS: LANDED by this commit.` with **no hash**; the frozen-pins statement
|
||
is present and shows **no hunk** in a zero-context staged diff, having been
|
||
written at ratification; all review-round blocks above §0 are marked a dated
|
||
historical record.
|
||
15. **Read-checked, no machine observer:** pin 3's requirement sits in Chapter 3
|
||
immediately after `req:time:tempo-segment-order`'s `\end{requirement}`;
|
||
**the added Revision History row is sliced from the staged diff and compared
|
||
in normalised whole-record form** against pin 13's text — every fact it
|
||
pins, not just its distinguishing names;
|
||
the `/// 10.` rider note names the four labels and no longer names P13-S29 as
|
||
a pending owner.
|
||
16. **Pin 9's prose outcomes, each read-checked against its own site** — the
|
||
`/// 10.` rider note names the four labels and not P13-S29; the tempo,
|
||
aleatoric and accidental headers no longer say their conditions are surfaced
|
||
under invariant 10; the accidental header cites
|
||
`req:tuning:accidental-modification-compatibility` symbolically rather than
|
||
the stale `core_spec.tex:3120`; the migrated negative's message no longer
|
||
says *"compatibility invariant"*; `review_fix_tests_4`'s module doc no longer
|
||
calls its tempo subject an invariant; `check_invariants`' rustdoc states it
|
||
returns both arms; `README.md`'s invariant row: **its description cell equals pin 9a's
|
||
fenced source** after whitespace collapse; and `DECISIONS.md` carries a **supersession note** with the
|
||
original decision **intact**. *Every one of these can be omitted with all
|
||
other gates green.*
|
||
|
||
|
||
---
|
||
|
||
## §5. What ratification does NOT settle
|
||
|
||
- **P13-S8's canonical-form ruling.** Pin 3 states the enforced compatibility and
|
||
nothing more; pin 3a guards that it says nothing more.
|
||
- **Whether the riders should eventually leave `check_invariants` entirely**
|
||
(disposition (c)). Pin 4 keeps them for safety; a later rung may revisit it
|
||
with a migration path for all ~10 callers.
|
||
- **`DeferredCheck`'s shape.** §0.5 verified it is correctly attributed today. A
|
||
future deferred check for a non-invariant rule inherits this rung's problem.
|
||
- **The recurring citation-gate collision** — a contract proposing a label breaks
|
||
the gate the moment it is written, now four times. That belongs in `CLAUDE.md`
|
||
as a standing note, on its own terms, not here.
|
||
|
||
---
|
||
|
||
## §6. AMENDMENT 1 — §3's M1·C6 AND M1·C7 RADII, MID-EXECUTION
|
||
|
||
STATUS: RATIFIED; FROZEN. Execution of P13-S29 resumes at M2.
|
||
|
||
Ratified 2026-08-12 on the authority of the repository owner, the final review
|
||
round returning zero findings. The replacements are executed, not edited; a
|
||
further defect is its own amendment with its own review round.
|
||
|
||
**§3 was frozen and dispatched at `cea21cd`.** Ratification **authorizes and
|
||
freezes** this amendment; execution applies the replacements. §6.9 pins the
|
||
landed form and the order of the remaining steps.
|
||
|
||
**Scope — the complete write surface, all four parts.** A description of the
|
||
normative correction is not a description of what gets written, and an earlier
|
||
draft of this head said *"two radius cells and nothing else"* while prescribing
|
||
three further edits below it:
|
||
|
||
| | Edit | Where | Touch row |
|
||
|---|---|---|---|
|
||
| 1 | M1 row replacement | §3 (this file) | 9 |
|
||
| 2 | Preamble append | §3 (this file) | 9 |
|
||
| 3 | This amendment's own lifecycle transitions | §6 (this file) | 9 |
|
||
| 4 | Resolution/resumption append | `spec/EVIDENCE_P13S29_EXECUTION.md` | 10 |
|
||
|
||
**"Two edits, both in §3" describes edits 1 and 2 — the normative §3 correction
|
||
— and nothing else.** Edits 3 and 4 are lifecycle and record.
|
||
|
||
**One further act belongs to ratification rather than to execution:** the
|
||
ratification commit stages `spec/EVIDENCE_P13S29_EXECUTION.md` in its
|
||
**pre-amendment** state, under the same touch row 10, to serve as §6.5c-bis's
|
||
oracle. *It is listed here and not in the table because it is not an edit this
|
||
amendment makes — it is the act that gives the amendment something durable to be
|
||
checked against, and it must happen before edit 4.*
|
||
|
||
**What does not move:** no pin, no test, no fixture, no behaviour, no other §3
|
||
cell. It does not create, retire or renumber a mutation, and it **rewrites no
|
||
existing evidence** — §6.5d is the standing prohibition.
|
||
|
||
### 6.1 The defect
|
||
|
||
§3's M1 row closes:
|
||
|
||
> **C6 and C7 fail their pin-10 test alone**: the legacy `f4` assertion is one
|
||
> fixture tripping *both*, so re-tagging one leaves the other still reporting the
|
||
> same label and the legacy assertion still passes
|
||
|
||
**Measured, the radius of each is two, not one.** Transcripts: annex §5.3, §5.4.
|
||
|
||
| M | §3's cell | Measured |
|
||
|---|---|---|
|
||
| M1·C6 | `tempo_out_of_order_reports_order` | that test **and** `tempo_overlap_reports_order` |
|
||
| M1·C7 | `tempo_overlap_reports_order` | that test **and** `tempo_out_of_order_reports_order` |
|
||
|
||
### 6.2 Why — and what in the quoted sentence survives
|
||
|
||
**The sentence's claim about `f4` is correct and is retained.** `f4` is in
|
||
neither radius, for exactly the reason given: it holds one fixture tripping both
|
||
conditions and asserts on the label, which the surviving sibling keeps supplying.
|
||
Measurement confirms it.
|
||
|
||
**What the sentence omits is that pin 10's own C6 and C7 tests stand in the same
|
||
relation to each other.** Pin 10 pins four assertions per row; the fourth is
|
||
*the aggregate's invariant arm is empty*. Pin 10 also states, in terms:
|
||
|
||
> C6's natural fixture — `seg(2,3)` then `seg(1,2)` — is *also* overlapping, so
|
||
> it emits C6 **and** C7 under the same label.
|
||
|
||
Both tests are built by `two_segments(seed, (2, 3), (1, 2))`, differing only in
|
||
the seed. Re-tagging **either** condition therefore places an `Invariant`
|
||
violation in **both** fixtures, and the sibling's fourth assertion fails on it.
|
||
|
||
**The cell reasoned about the legacy observer and stopped there.** Having
|
||
established the shared-fixture property one clause earlier, it did not ask the
|
||
same question of the tests this contract itself writes.
|
||
|
||
### 6.3 What must NOT change in response
|
||
|
||
- **Not the fixtures.** The only shape isolating C6 is an end-before-start
|
||
segment, which pin 10 **rejects** as *"unnatural and tests a shape the checker
|
||
should never see."*
|
||
- **Not pin 10's fourth assertion.** §3's M2a derivation depends on it: it is
|
||
what keeps the seven C4–C10 tests out of M2a's radius *structurally rather than
|
||
by assumption*.
|
||
- **Not any other M1 cell.** C4, C5, C8, C9 and C10 were measured in the same
|
||
pass and **matched exactly** — 2, 3, 4, 2 and 3 respectively.
|
||
|
||
### 6.4 The correction is a strengthening, not a relaxation
|
||
|
||
**The amendment adds no observer.** Pin 10's tests already supplied both — its
|
||
own `(kind, witness)` pair assertion and the sibling's invariant-arm assertion
|
||
have detected each re-tagging since the moment those tests were written. What
|
||
changes is the **accounted and required** radius: §3 credited the mutation with
|
||
one observer and would have read the second as a mismatch, so the amendment
|
||
**recognizes** an observation the contract was under-counting.
|
||
|
||
That is a strengthening because the required radius is now two: a future
|
||
implementation that silenced the sibling assertion would fail this gate, where
|
||
under the dispatched cell it would have passed.
|
||
|
||
### 6.5 The replacements — edits 1, 2 and 4 of the scope table
|
||
|
||
**Touch rows 9 and 10 already cover both files this amendment writes to**
|
||
(`CONTRACT_P13S29_VIOLATION_KIND.md`, `EVIDENCE_P13S29_EXECUTION.md`). No touch
|
||
row is added.
|
||
|
||
#### 6.5a — §3's M1 row
|
||
|
||
Replace the sentence quoted in §6.1 with:
|
||
|
||
> **C6 and C7 each fail *both* pin-10 order tests, and the legacy `f4` assertion
|
||
> fails for neither.** `f4` holds one fixture tripping both conditions and
|
||
> asserts on the label, so the surviving sibling keeps supplying it — but pin
|
||
> 10's C6 and C7 tests stand in that same relation to *each other*: both are
|
||
> `two_segments(seed, (2, 3), (1, 2))`, which pin 10 establishes emits C6 **and**
|
||
> C7. Re-tagging either puts an `Invariant` violation into both fixtures, so the
|
||
> sibling's **fourth** assertion — *the aggregate's invariant arm is empty* —
|
||
> fails alongside the mutated condition's own pair assertion. **Measured, not
|
||
> derived; the fixtures are shared by pin 10's deliberate choice and cannot be
|
||
> separated without the end-before-start segment pin 10 rejects.**
|
||
|
||
#### 6.5b — §3's preamble count
|
||
|
||
§3's preamble opens a paragraph with:
|
||
|
||
> **Four cells were measured, not derived, and the difference matters.**
|
||
|
||
**Six are now measured**, and a count left standing beside what it counts is
|
||
itself one of the ledger's recurring defects. **Do not edit that sentence** — it
|
||
is an accurate statement about what was measured *before ratification*, and
|
||
rewriting it would destroy a true historical claim to fix a staleness. Instead
|
||
**append to the end of that same paragraph**:
|
||
|
||
> **Execution measured a fifth and sixth cell, M1·C6 and M1·C7; amendment 1
|
||
> records them and authorizes their corrected radii.** They are not among the
|
||
> four because they reach only tests this contract writes — the criterion that
|
||
> sent the other four to measurement was *reaching tests the contract did not
|
||
> write*, and that criterion was wrong. **The operative property is whether a
|
||
> fixture is shared, not who authored the test.**
|
||
|
||
*This is deliberately an append, not a rewrite: the paragraph's subject is the
|
||
pre-ratification derivation and its failures, and the amendment is a later event
|
||
in the same record.*
|
||
|
||
#### 6.5c — the annex append, pinned as a source template
|
||
|
||
`spec/EVIDENCE_P13S29_EXECUTION.md` gains a new final section **§8**. **It is
|
||
pinned as source, not described by its contents** — a content description admits
|
||
a truncated or differently scoped record that still satisfies every "carries X"
|
||
clause, which is what an earlier draft of this subsection did. **Exactly one
|
||
slot, `{RATIFICATION_HASH}`**; everything else verbatim.
|
||
|
||
~~~
|
||
## §8. Amendment 1: resolution and resumption
|
||
|
||
Amendment 1 is ratified at `{RATIFICATION_HASH}` and landed by this commit. It
|
||
corrects two radius cells in the contract's §3 and changes no pin, test, fixture
|
||
or behaviour.
|
||
|
||
**§5 and §7 above are the dated execution record and are not edited.** They
|
||
state what was expected, what was observed, and why execution stopped. The
|
||
mismatch they record is the reason this amendment exists; reconciling them would
|
||
remove it.
|
||
|
||
### 8.1 The corrected radii
|
||
|
||
| M | Dispatched cell (§5) | Corrected cell, measured |
|
||
|---|---|---|
|
||
| M1·C6 | `tempo_out_of_order_reports_order` | that test **and** `tempo_overlap_reports_order` |
|
||
| M1·C7 | `tempo_overlap_reports_order` | that test **and** `tempo_out_of_order_reports_order` |
|
||
|
||
Both were observed before the halt. The transcripts in §5.3 and §5.4 stand as
|
||
the observation and **were not re-run**: the amendment corrects the expectation
|
||
they were compared against, not the observation.
|
||
|
||
### 8.2 Resumption
|
||
|
||
The mutation sequence resumes at **M2**. M1 is complete — C4, C5, C8, C9 and C10
|
||
matched their dispatched cells, and C6 and C7 match the corrected cells above.
|
||
~~~
|
||
|
||
**Extraction endpoint — the same boundary rule as §6.5c-bis.** §8 runs from its
|
||
`## §8.` heading to the **last line before the next `## §` heading, or EOF if
|
||
none**. Normalize with §6.5c-bis's canonical serialization, then compare for
|
||
**equality**. Not "contains", not "mentions".
|
||
|
||
**Later evidence sections are expressly permitted and do not disturb A4.** M2
|
||
onward still needs its transcripts, and they land as **§9 and beyond**. *Had §8
|
||
been defined as "heading to EOF", the very next evidence section would have
|
||
invalidated A4 — a gate that the work it gates is guaranteed to break.*
|
||
|
||
**§5 is closed at M1 and must not be extended.** It is digest-frozen by
|
||
§6.5c-bis, so appending M2's rows to the expected-versus-observed matrix — the
|
||
obvious place for them — **would break A4(b).** §9 continues the matrix under
|
||
its own heading and carries M2 onward. *This is a consequence of freezing an
|
||
open section, and it is stated here because nothing else would warn the
|
||
executor before the gate failed.*
|
||
|
||
**`landed by this commit`, never a landing hash** — the annex lands *in* that
|
||
commit, and pin 12 already states why: *a commit cannot carry its own id.*
|
||
|
||
**§5 and §7 are NOT edited.** §5's table keeps its dispatched cells, its two ❌
|
||
marks and its *"the phase is halted at M1"* opening; §7 keeps the finding in the
|
||
tense it was found in. §6.5c-bis pins the oracle.
|
||
|
||
#### 6.5c-bis — the oracle for §5 and §7
|
||
|
||
**"Byte-identical to their pre-amendment state" needs something durable to
|
||
compare against, and the annex is untracked.** Once §8 is appended there is
|
||
nothing left to diff. Two measures, both required:
|
||
|
||
**1. The ratification act commits the pre-amendment annex.** Ratification stages
|
||
`spec/EVIDENCE_P13S29_EXECUTION.md` exactly as it stands at the halt — §1–§7,
|
||
**no §8** — under touch row 10. **That commit's blob is the named oracle**, and
|
||
A4 is checked with `git show <ratification-commit>:spec/EVIDENCE_P13S29_EXECUTION.md`.
|
||
*This is also what makes the amendment reviewable at all: an untracked evidence
|
||
file cannot be cited by a frozen document.*
|
||
|
||
**2. Digests, pinned here, as the oracle's oracle.**
|
||
|
||
**The canonical byte serialization, pinned exactly — a digest with an inferred
|
||
serialization is a digest nobody else can reproduce.** In order:
|
||
|
||
1. Read the file as bytes and **decode UTF-8**. The annex is **LF-only**; a CRLF
|
||
copy is out of scope and will not reproduce these hashes.
|
||
2. Find section starts by `^## §\d+\.` (multiline). A slice runs from its own
|
||
heading — **the heading line is included** — to the byte before the next such
|
||
heading, or to EOF for the last.
|
||
3. Split the slice into lines and **right-strip each line** (trailing spaces and
|
||
tabs).
|
||
4. **Repeat while the last retained line is empty *or* is exactly `---`: drop
|
||
it.** *One loop, not three passes — a `---` and the blank lines around it are
|
||
removed together however they interleave.*
|
||
5. **Join the retained lines with `\n`, and emit NO terminal newline.**
|
||
6. **SHA-256 over the UTF-8 bytes of that string.**
|
||
|
||
**Step 5 is the one that actually needs pinning.** An ordinary
|
||
`"\n".join(lines) + "\n"` — the natural way to write a file back out — yields
|
||
`53b32278…` for §5 and `eb704854…` for §7 instead of the pinned values. *The
|
||
digests reproduce only because there is no terminal newline, and nothing in an
|
||
earlier draft said so.*
|
||
|
||
*Steps 2–3 use `^## §\d+\.` and any line splitter that agrees with LF splitting;
|
||
verified that `str.splitlines()` and `split("\n")` produce identical digests for
|
||
both slices, the annex containing no form feed, vertical tab or U+2028.*
|
||
|
||
| Slice | SHA-256 | Lines |
|
||
|---|---|---|
|
||
| annex §5 | `40ce82a70339159024c69dd5e280d8bd6846efbeb1eecd5b7971a2737826f74b` | 134 |
|
||
| annex §7 | `cdd9bfd91da5091174201b1bc16aea6a5f162cc5f6d8553f6d58d7c56aacccd8` | 76 |
|
||
|
||
**The slice rule is what makes the §7 digest stable across the append.** §7
|
||
currently ends at EOF and will end at §8's heading; the rule ends it at the last
|
||
non-blank line either way, so **appending §8 must not move either digest.**
|
||
*A rule defined as "to EOF" would have made §7's digest change by construction
|
||
and the gate unfalsifiable.*
|
||
|
||
#### 6.5d — the prohibition on rewriting evidence
|
||
|
||
**An earlier draft's gate A4 would have rewritten §5's cells and removed the
|
||
halt notice. That is prohibited, and the prohibition is the reason this
|
||
subsection exists.**
|
||
|
||
§5 and §7 are the **dated record of what was expected, what was observed, and
|
||
why execution stopped.** Overwriting the expectation with the corrected one
|
||
would leave an annex in which the observed radius matches the recorded cell
|
||
everywhere — **an annex that no longer contains the reason this amendment
|
||
exists.** The mismatch *is* the evidence.
|
||
|
||
**The rule, stated generally:** an execution record is appended to, never
|
||
reconciled. A correction is a later event in the record, not a revision of an
|
||
earlier one. *This is the same discipline `PASS13_CANDIDATES.md` status cells
|
||
already carry — appended to, not rewritten — and the same reason §6.5b appends
|
||
to §3's preamble rather than editing its count.*
|
||
|
||
### 6.6 The generalization this amendment explicitly declines to make
|
||
|
||
**It would be wrong to conclude that same-label conditions always cross-talk.**
|
||
The same pass measured the other two shared-label pairs and found no cross-talk
|
||
in either:
|
||
|
||
- **C4/C5**, sharing `req:time:tempo-segment-shape`: `Constant`-with-mismatch and
|
||
non-constant-missing-`end_tempo` are mutually exclusive shapes.
|
||
- **C8/C9**, sharing `req:time:aleatoric-reference-locality`: distinct fixtures,
|
||
each aggregate carrying exactly one violation.
|
||
|
||
**The property that matters is fixture identity, not label identity**, and only
|
||
C6/C7 share a fixture shape.
|
||
|
||
### 6.7 The defect class, for the ledger
|
||
|
||
**The one-hop correction**, the recurring shape: a fact established in one pin
|
||
is not carried into the section that depends on it — here within a single table
|
||
cell, which cites the shared-fixture property about `f4` in one clause and
|
||
overlooks it about pin 10's own tests in the next.
|
||
|
||
§3's preamble already records that **all four** of its measured cells differed
|
||
from static reading, and measured them because they reached tests the contract
|
||
did not write. **C6 and C7 reach tests the contract *did* write — which is why
|
||
they were derived rather than measured.** Authorship of a test is not knowledge
|
||
of its fixture's reach.
|
||
|
||
### 6.8 Gate
|
||
|
||
- **A1.** §3's M1 row carries §6.5a's replacement text, and §3's preamble
|
||
paragraph carries §6.5b's appended sentences with its opening
|
||
*"Four cells were measured"* sentence **unedited**. The superseded sentence
|
||
survives in the file **exactly once**, inside §6.1's blockquote, where it is a
|
||
dated quotation of what was corrected — **not "absent from the file", which
|
||
this amendment makes permanently unsatisfiable by quoting it.** Checked by
|
||
stripping blockquote markers and counting: **one** occurrence, and it is
|
||
§6.1's.
|
||
- **A2.** M1·C6 and M1·C7 each observed, each failing **exactly**
|
||
`tempo_out_of_order_reports_order` and `tempo_overlap_reports_order`, with the
|
||
failing assertions verbatim in the annex — and each restoring to
|
||
`44 / 1604 / 0 / 0`.
|
||
- **A3.** **Measured against the halt checkpoint, not against `cea21cd`.** The
|
||
ratification commit predates every pin-10 test, so "no test differs from
|
||
`cea21cd`" is unsatisfiable by construction — the tests P13-S29 exists to add
|
||
necessarily differ from it. The checkpoint is the working tree at the M1 halt:
|
||
`44 suites / 1604 passed / 0 failed / 0 ignored`, annex §4. Against it:
|
||
**no implementation, test or fixture change is attributable to amendment 1**,
|
||
and **no staged hunk in `crates/` belongs to it.** Amendment 1's diff touches
|
||
exactly two files, `spec/CONTRACT_P13S29_VIOLATION_KIND.md` and
|
||
`spec/EVIDENCE_P13S29_EXECUTION.md`.
|
||
- **A4.** Two checks, both mechanical:
|
||
|
||
**(a) The append.** The annex's §8, normalized per §6.5c, **equals** §6.5c's
|
||
template with `{RATIFICATION_HASH}` filled — including the literal
|
||
`landed by this commit`. Whole-section equality, not presence of topics.
|
||
|
||
**(b) The preserved record.** Annex §5 and §7, sliced and normalized per
|
||
§6.5c-bis, hash to `40ce82a7…f74b` and `cdd9bfd9…ccd8`, and are byte-identical
|
||
to the same slices in `git show <ratification-commit>:spec/EVIDENCE_P13S29_EXECUTION.md`.
|
||
Halt notice and ❌ marks intact. **This check is also what observes the
|
||
ratification act**: if the ratification commit does not contain the
|
||
pre-amendment annex, the `git show` does not resolve and A4(b) cannot pass.
|
||
|
||
*A4 observes an append; it must never observe a reconciliation (§6.5d).*
|
||
- **A5.** §6's status block carries §6.9's exact ratified form, and — at landing
|
||
— its exact landed form and the historical marking.
|
||
|
||
**The contract's own top status has two permitted values, and A5 accepts
|
||
whichever the landing commit makes true:**
|
||
|
||
| Landing | Contract's top status must read |
|
||
|---|---|
|
||
| Amendment 1 lands **alone**, contract still mid-flight | `STATUS: RATIFIED; DISPATCHED.` — unchanged |
|
||
| Amendment 1 lands **in the same commit as P13-S29** | pin 12's exact landed transition, `STATUS: LANDED by this commit.` |
|
||
|
||
*An earlier draft required the first unconditionally, which **rejected
|
||
compliance with pin 12** in the same-commit case §6.9 explicitly permits — a
|
||
gate contradicting a lifecycle the same amendment allows.* **What A5 forbids
|
||
in both branches is unchanged: no pin-12 transition attributable to amendment
|
||
1 itself.** *Without A5 the scope table's edit 3 would be a prescribed edit no
|
||
gate observes.*
|
||
|
||
### 6.9 This amendment's own lifecycle
|
||
|
||
**Mirrors pin 12's form for the contract, with the transitions an amendment
|
||
needs and a contract does not.**
|
||
|
||
- **On ratification:** §6's status block reads exactly
|
||
|
||
`STATUS: RATIFIED; FROZEN. Execution of P13-S29 resumes at M2.`
|
||
|
||
and the **frozen-amendment statement** is added:
|
||
|
||
> The replacements are executed, not edited; a further defect is its own
|
||
> amendment with its own review round.
|
||
|
||
**This adapts P13-S26's formula and does not reproduce it word for word.**
|
||
The precedent reads *"The amended pins are executed, not edited; a further
|
||
defect is its own amendment with its own review round."*
|
||
(`CONTRACT_P13S26_INVARIANT10_SURFACE.md:1656`). **Amendment 1 amends no pin**
|
||
— it replaces two radius cells — so quoting the precedent exactly would assert
|
||
something false about this amendment. The second clause is verbatim; the first
|
||
substitutes *replacements* for *amended pins*. *An earlier draft claimed exact
|
||
reuse while paraphrasing; the claim, not the wording, was the defect.*
|
||
|
||
- **Ratification resumes execution, and Amendment 1's own execution comes
|
||
first.** The order is pinned:
|
||
|
||
1. **Ratify** — §6's status block takes the form above; the pre-amendment
|
||
annex is committed as §6.5c-bis's oracle.
|
||
2. **Apply edits 1, 2 and 4** — the M1 row replacement, the §3 preamble
|
||
append, and the annex §8 append.
|
||
3. **Pass A1–A5.**
|
||
4. **Resume the mutation sequence at M2.**
|
||
|
||
*"Ratification resumes execution at M2" must not be read as skipping steps 2
|
||
and 3: the amendment has its own execution, and M2 follows it.*
|
||
|
||
The resumption point is **M2** — not M1.
|
||
M1·C6 and M1·C7 were **already observed** (annex §5.3, §5.4); the amendment
|
||
corrects the expectation they were compared against, not the observation. The
|
||
tree is unchanged between those runs and this amendment — A3's checkpoint is
|
||
what establishes that — so **A2 is discharged by the existing dated
|
||
transcripts and requires no re-run.** *Re-running would produce a second,
|
||
identical transcript and a record implying the first was doubted.*
|
||
|
||
- **On landing:** exactly
|
||
|
||
`STATUS: LANDED by this commit.`
|
||
|
||
— **no hash**; a commit cannot carry its own id.
|
||
|
||
- **On landing**, §6's review-round record is marked a **dated historical
|
||
record**, in the form P13-S26 §9 uses: *§6's findings and dispositions are an
|
||
account of what was found and decided, and state no current condition.*
|
||
|
||
- **P13-S29's own §0-and-above review blocks are NOT marked historical by this
|
||
amendment.** Pin 12 marks them **on the contract's landing**, which has not
|
||
happened — execution is mid-flight. *Marking them here would date a record
|
||
whose subject is still live.*
|
||
|
||
**This amendment does not alter pin 12.** The contract's own status block still
|
||
reads `STATUS: RATIFIED; DISPATCHED.` and transitions to `LANDED` on the
|
||
contract's landing commit, which may be the same commit that lands this
|
||
amendment or a later one.
|