Commit Graph

364 Commits

Author SHA1 Message Date
Levi Neuwirth 8073282803
CLAUDE.md: P13-S26's amendment 3 is landed, and there were four
The tracks table said "amendment 3 open" and never mentioned amendment 4. Both
landed on 2026-08-11, before P13-S29 was even ratified: amendment 3 ratified
7c8a30d and executed bff7be0, amendment 4 ratified a347a03 and executed 3fda93b.
The contract's §8 and §9 have read "STATUS: LANDED by this commit." since.

Found by checking the opener against the contract before scoping work it implied
was outstanding. This is the hazard the file itself names two lines above the
table -- an opener can lag the truth by several rungs, read the whole cell -- and
here the opener was the thing lagging. The S26 ledger cell was already correct.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-12 17:09:18 +02:00
Levi Neuwirth 552aacac2c
CLAUDE.md: drop a live count and disambiguate the citation-gate rule
Two corrections to the rule added in df5da35.

"This has now happened four times" was a live count in a standing rule, and it
would go stale at the next occurrence — the same defect the rule sits beside, and
the same one this repo keeps paying for in restated test counts. Now count-free:
"This has recurred across multiple contracts."

"Nothing is wrong with the tree" was ambiguous in the one way that matters here,
because two baselines are in play. Nothing tracked has regressed: no committed
file is wrong and HEAD is still green. What is red is the baseline you can
actually observe, because the suite reads the working directory and the untracked
draft is in it. The distinction is the whole point of the rule, so it now says
both halves and adds why it matters anyway: that observable baseline is the one
the mutation discipline depends on, so the effect is the same as a real
regression.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-12 17:00:30 +02:00
Levi Neuwirth df5da3512c
CLAUDE.md: the recurring citation-gate collision becomes a standing rule
A contract that proposes a req: label breaks the citation gate the moment it is
written. requirement_labels.rs scans spec/ as files, not as git objects, so an
untracked draft is already in scope: the instant a draft cites a label the .tex
does not define, every_requirement_citation_is_defined goes red. Nothing is wrong
with the tree, and the known-green baseline the mutation discipline depends on is
gone. Four occurrences now, each rediscovered from scratch.

The procedure, as four points: a proposed label requires a temporary
DISCUSSED_NOT_CITED row as review scaffolding; that scaffolding authorizes no
dispatch work; the minting pin owns its removal, because the row's claim
(discussed, never cited) becomes false when the requirement lands; and a landing
gate must prove the citation test passes because the label exists, not because it
remains allowlisted — asserting the row absent and the \label present, since
those two states are indistinguishable from a green test alone and a stale row is
inert.

Placed after the touch-table rule, whose "recurring escapees" note is the same
shape of hazard: a mechanical consequence of how the suite reads spec/, invisible
until it bites, and cheap once written down.

Its own change, not folded into P13-S29: the rule outlives the rung that
prompted it, and CLAUDE.md is not in that contract's touch table.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-12 16:58:14 +02:00
Levi Neuwirth f87554786a
P13-S29 amendment 2 LANDED: the S29 ledger row carries its date correction
Appends a correction inside the S29 ledger row, before its terminal |: actual
resolution and landing were both 2026-08-12 — ratified cea21cd, amendment 1 at
29ef3af/e7bd12c, landed 52fcf37. The pinned "RESOLVED 2026-08-11" sentence
stands, because this ledger's status cells are appended to, never rewritten
(CLAUDE.md:12).

Nothing else moves. Pin 13 keeps its verbatim APPEND, annex §11.1 keeps the
deviation in the tense it was found, and gate 10 stays discharged — it is a
landing gate whose reconstruction was true of 52fcf37 and has no standing form.
§7.4 says so explicitly, because an executor re-running it would read the
failure as a defect and "repair" it by deleting the correction, restoring a date
everyone now knows is wrong.

  B1  added row == trim(ORACLE) + " " + CORRECTION + " |", both oracles read
      from RC 9cc2913; one removed and one added S29 row; CORRECTION exactly
      once in spec/PASS13_CANDIDATES.md
  B2  annex byte-identical to 52fcf37; contract prefix byte-identical to
      52fcf37 with the remainder beginning the §7 separator; RC->LC contract
      diff exactly one status line swapped and four marker lines added
  B3  RC names only the contract; this commit names only the contract and the
      ledger; neither names crates/, .pdf or .tex
  B4  44 suites / 1606 passed / 0 failed / 0 ignored
  B5  §7's landed status exact and hashless, the complete historical marker
      present line for line, and the frozen statement byte-identical to RC

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-12 16:56:45 +02:00
Levi Neuwirth 9cc2913fab
P13-S29 amendment 2 RATIFIED: pin 13's append date, administrative
Pin 13's APPEND opens "RESOLVED 2026-08-11"; actual resolution and landing were
both 2026-08-12, as the contract's own ratification line and amendment 1's both
say. The pinned date is the date the append text was drafted, frozen before the
dates diverged. Gate 10 rejected the artifact over exactly this character at
landing and annex §11.1 flagged it rather than settling it — the gate working.

The correction is appended to the ledger row; pin 13, annex §11.1 and the
original sentence are all left standing. The reason is the append-only
convention CLAUDE.md:12 states, not that history would otherwise change: 52fcf37
is immutable, and gate 10's observation remains true of it whatever a later
commit says. An earlier draft gave that false reason and §7.2 records it as
false, because it is the more persuasive one and would otherwise be re-derived.

This commit ratifies only. Per §7.0 the ledger correction is deliberately
UNSTAGED here and lands in the next commit, so that this commit is the immutable
oracle B1 reads both ORACLE and CORRECTION from. An oracle taken from the
working copy is not an oracle: an executor editing template and artifact together
would satisfy it.

B2's third part pins the ratification-to-landing surface exactly — one status
line swapped, four lines added for the marker, nothing else — so §7's frozen
body, including §7.3's template and this gate, cannot be edited during landing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-12 16:55:46 +02:00
Levi Neuwirth 85990298c4
Reconcile CLAUDE.md's green baseline after P13-S29
43 suites / 1586 -> 44 / 1606, and the provenance sentence gains S29's entry:
twenty net-new tests, the suite count moving with its one new file,
crates/epiphany-core/tests/public_surface.rs.

CLAUDE.md is not in P13-S29's touch table, so this is its own commit rather than
a hunk inside the landing. It remains the single origin for both numbers;
HANDOFF_2026-08-07.md already defers to it in all four places and restates
nothing.

The two-tracks table records P13-S29 LANDED (52fcf37), its amendment 1 ratified
at 29ef3af and executed at e7bd12c.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-12 16:35:25 +02:00
Levi Neuwirth 52fcf3739a
P13-S29 LANDED: the violation tag stops multiplexing
Graph invariant 10 reported Chapter 3 and Chapter 4 failures under its own
number, through a public API. `InvariantViolation` becomes
`WellFormednessViolation` carrying a two-armed `ViolationKind`: `Invariant` for
a numbered graph invariant, `Requirement` for a normative rule named by its
`req:` label. Invariant 10 keeps only reference resolution.

`check_invariants` stays comprehensive, so every broad caller keeps its rule
coverage; `check_invariant` narrows to the invariant arm and a symmetric
`check_requirement` is added. Both are projections of the aggregate. Four rules
move to their own labels, one of which this rung mints:
`req:time:tempo-segment-shape`, stating the enforced shape/end_tempo
compatibility without resolving P13-S8. `GraphInvariant` did not move: 21
variants, unchanged.

  44 suites / 1606 passed / 0 failed / 0 ignored   (1586 -> 1606, 43 -> 44)
  clippy -D warnings clean; fmt -p epiphany-core -p epiphany-testkit clean
  core_spec.pdf rebuilt, undefined references cleared

Gates 1-16 pass; evidence in spec/EVIDENCE_P13S29_EXECUTION.md. All 54 mutations
of §3 observed, none compile-only, none passing. Amendment 1 corrected M1·C6 and
M1·C7 from one observer to two after measurement contradicted the derived cell.

Six execution faults are recorded rather than left in the transcript, none a
contract defect. Three are worth naming here because no tool would have caught
them:

- Pin 10's eleventh row was read as a note, not a test, so
  `reversed_aleatoric_bounds_stay_invariant_four` was never written. M11's cell
  named it, and the omission surfaced only as a radius mismatch.
- `display_renders_each_arm_exactly` carried a comment stating its pinned
  fixture correctly above code that built a different one. Pin 10 had foreclosed
  the choice precisely because it moves radii; with the fixture repaired the
  test entered M11's cell and left M17·C1's, both as pinned.
- Pin 9's `/// 10.` rider note was the one prose row left unmigrated, naming
  three labels where four were required and still filing the multiplexing as
  pending. Gate 16 states these outcomes have no machine observer; eight rows
  were verified by their own stale phrase, and the ninth was not there.

Gate 10 rejected the ledger append over one character: the artifact read
2026-08-12 where pin 13 pins 2026-08-11. The artifact was corrected to the pin,
and the date question is flagged for the owner as a possible administrative
amendment rather than settled here.

CLAUDE.md's baseline still reads 43 suites / 1586 tests and is not in the touch
table; it follows in a separate reconciliation commit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-12 16:34:38 +02:00
Levi Neuwirth e7bd12c19e
P13-S29 amendment 1 executed: edits 1, 2 and 4; A1-A5 pass; mutations resume at M2
Edit 1 — §3's M1 row now states the measured radius: C6 and C7 each fail *both*
pin-10 order tests, and the legacy `f4` assertion fails for neither. The
superseded sentence survives exactly once, in §6.1's blockquote, where it is a
dated quotation of what was corrected.

Edit 2 — §3's preamble gains an append. Its "Four cells were measured" sentence
is left unedited: it is accurate about what was measured before ratification,
and rewriting it would destroy a true historical claim to fix a staleness. Six
cells are now measured, and the append says which two joined and why the
criterion that excluded them was wrong.

Edit 4 — the annex gains §8, equal to §6.5c's pinned source template with its
single hash slot filled. §5 and §7 are untouched and hash to the values pinned
at ratification; verified byte-identical against 29ef3af's blob, halt notice and
both mismatch marks intact. The execution record is appended to, never
reconciled — the mismatch is the evidence.

  A1  §3 correction, superseded sentence occurring exactly once
  A2  discharged by the dated transcripts in annex §5.3 and §5.4; not re-run
  A3  no implementation, test or fixture change attributable to the amendment;
      commit touches exactly two spec files; workspace at 44/1604/0/0
  A4  §8 equals the template; §5 and §7 byte-identical to the oracle
  A5  §6 in its ratified form; pin 12's transitions untouched

M1 is complete. C4, C5, C8, C9 and C10 matched their dispatched cells; C6 and C7
match the corrected cells. The mutation sequence resumes at M2, and its
transcripts land in annex §9 — §5 is closed at M1 by the digest gate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-12 13:49:54 +02:00
Levi Neuwirth 29ef3af69c
P13-S29 amendment 1 RATIFIED: M1·C6/C7 radii, with the pre-amendment annex as its oracle
Execution of P13-S29 halted at M1 on a radius mismatch. §3 pinned M1·C6 and
M1·C7 as failing "their pin-10 test alone"; measured, each fails both pin-10
order tests. The tree is correct and the cell is not.

Pin 10 builds both tests from `two_segments(seed, (2, 3), (1, 2))` and pins a
fourth assertion — the aggregate's invariant arm is empty. It also establishes
that this fixture emits C6 *and* C7, and expressly rejects the end-before-start
segment that would separate them. So re-tagging either condition puts an
Invariant violation into both fixtures and the sibling's fourth assertion fails.
§3's cell reasoned about the legacy `f4` observer — correctly; `f4` is in neither
radius — and never asked the same question of the tests this contract writes.

The one-hop correction, inside a single table cell. §3 measured four cells
because they reached tests the contract did not write; C6 and C7 reach tests it
did write, which is why they were derived and why the derivation was trusted.
Authorship of a test is not knowledge of its fixture's reach.

C4, C5, C8, C9 and C10 were measured in the same pass and matched exactly, so
the correction is not generalized: C4/C5 and C8/C9 also share labels and show no
cross-talk. The operative property is a shared fixture, not a shared label.

This commit ratifies only. It carries §6 in its frozen form and the
pre-amendment annex — §1–§7, no §8 — which §6.5c-bis names as the oracle for the
byte-identity gate. §5 and §7 record what was expected, what was observed and
why execution stopped; they are appended to, never reconciled, because the
mismatch is the evidence.

  annex §5  sha256 40ce82a70339159024c69dd5e280d8bd6846efbeb1eecd5b7971a2737826f74b  134 lines
  annex §7  sha256 cdd9bfd91da5091174201b1bc16aea6a5f162cc5f6d8553f6d58d7c56aacccd8   76 lines

Edits 1, 2 and 4 follow in their own commit, then A1–A5, then M2.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-12 13:47:41 +02:00
Levi Neuwirth cea21cd8f9
P13-S29 RATIFIED; pins frozen, dispatched
Graph invariant 10 reported Chapter 3 and Chapter 4 failures under its own
number, through a public API: check_invariant is pub and re-exported, and
Display rendered a tempo rule as "invariant 10 (CrossCuttingRefsResolve)
violated". Disposition (b), type-neutral: InvariantViolation becomes
WellFormednessViolation carrying a two-armed ViolationKind. check_invariants
stays comprehensive, so every broad caller keeps its rule coverage; the
deliberate behaviour change is that check_invariant narrows to the invariant
arm, with a symmetric check_requirement added. GraphInvariant does not move --
21 variants, unchanged, and no new negative generator or shrink obligation.

req:time:tempo-segment-shape is minted for the one rider that had no label,
stating the enforced shape/end_tempo compatibility without resolving P13-S8's
canonical-form question, so the label survives whichever spelling S8 ratifies.

Eighteen review rounds. Four mutation radii were measured against disposable
implementations rather than derived, and every one of the four differed from
what static reading predicted: M2a by ten false positives and seventeen
omissions, M17-C1 by naming seven where eighteen fail and including a test that
belongs to C2, M17-C2 and C3 by predicting observers that measurement put at one
and zero. Two of those measurements first produced a compile error reporting
zero failures -- a compile error observes nothing -- and one misread cargo test's
"error: test failed" as a compilation signal; only the third method is pinned.

Several defects were structural rather than arithmetic. Both selectors could
have matched their arm while ignoring their payload, satisfied by every fixture
presenting a single variant or label. A complete third ViolationKind arm, or a
fully implemented 22nd GraphInvariant omitted from all(), compiles and leaves
every gate green -- a variant nothing enumerates is a variant nothing observes.
The accidental tests identified their rule by a witness suffix this rung
deletes, so a selector-only migration would have left two negatives green and
vacuous. And invariants.rs:8 carries the old type name in retained header prose,
which would have made gate 6 unsatisfiable.

Prerequisite review scaffolding, applied earlier under a narrow authorization
and committed here because ratification is what changes its staging state: one
temporary DISCUSSED_NOT_CITED row for req:time:tempo-segment-shape, deleted by
pin 3 when the requirement lands, with landing gates for its absence and for the
baseline being green because the label is defined rather than still allowlisted.

Baseline unchanged at 43 suites, 1586 passing; no implementation target has been
modified.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-12 00:05:32 +02:00
Levi Neuwirth 3fda93bc6b
P13-S26 amendment 4 EXECUTED: section 8.4's M27 sentence corrected
Section 8.4's M27 entry said M27 varies which clause is chosen. It now says each
of M22-M26 presupposes that selection succeeded and M27 attacks whether
selection is permitted at all. M25 is what varies which clause is chosen; a
correct implementation rejects M27 before selecting any clause.

Section 8.6 is untouched and verified so with a zero-context diff: its sentence
appears in the staged diff only as hunk context, never as an addition or a
deletion. It says M27 was the step no mutation had reached, which is true, and
an earlier draft of amendment 4 would have rewritten it.

Contract-only, three hunks: the replaced sentence, section 9's landed status
literal, and section 9's historical marker naming amendment 4. No annex edit --
its record that the correction was open as of bff7be0 remains true. Baseline
unchanged at 43 suites, 1586 passing; this commit changes prose only.

Section 9.6's gate observed, all items: one path staged; within section 8.4's
M27 entry the old sentence absent and the replacement present exactly once;
section 8.6 unchanged under zero context; within section 9's slice the landed
literal and an amendment-4-specific marker present; diff check clean.

One nuance in the ratified gate rationale is worth recording rather than
patching, since section 9 is frozen. Item 2 argues the scope is mandatory
because a file-wide form is unsatisfiable, section 9.1 quoting the old sentence
and 9.3 the replacement. Measured: under a normalising reader -- blockquote
prefixes stripped, whitespace collapsed, which is how every guard in this
repository reads .tex -- file-wide is indeed 1 and 2, and unsatisfiable. Under
raw exact matching against the source's own line wrapping it is 0 and 1, and
would pass. Section 9.6 does not say which reader it means. The scoping is right
under either, and item 4's scope is mandatory under both, the file carrying
eleven copies of the landed literal.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-11 20:52:34 +02:00
Levi Neuwirth a347a03c16
P13-S26 amendment 4 RATIFIED; one sentence in section 8.4 to be replaced
Section 8.4's M27 entry closes by saying M27 varies which clause is chosen. It
does not. M25 varies which clause is chosen -- it moves \MUST{} into the recap
and the clause moves with it, which is exactly how M25 discriminates the
last-period rule -- and a correct implementation rejects M27 before selecting
any clause at all, on the exactly-one assertion. M27 uniquely varies whether
selection is unambiguous and therefore permitted.

Section 8.6 is NOT affected and must not be touched. It says only that M27 was
the step no mutation had reached, which is true. An earlier draft of this
amendment proposed rewriting it, which would have damaged an accurate historical
statement in frozen text to repair a different sentence's error. That near-miss
is kept in the record because it is the same class as the defect being repaired.

Contract-only: touch row 7 alone. The annex needs no edit -- its record that the
correction was open as of bff7be0 remains true, and an append would add only
redundant lifecycle prose. Rewriting it would be the worse error, but that is
not what is being declined.

A prose-only replacement has no test to sign it, so section 9.6 is the observer,
and both of its slice checks exist because an unscoped form fails in opposite
directions. Scoped to section 8.4's M27 entry, the old sentence must be absent
and the replacement present exactly once -- file-wide that is unsatisfiable by a
correct execution, since section 9.1 quotes the old sentence and 9.3 quotes the
replacement. Scoped to section 9, the landed status literal and a marker naming
amendment 4 must be present -- unscoped that passes on lifecycle text section 9
never wrote, the file already carrying the same literal for the contract, for
section 6 and for section 8. Section 8.6 is verified unchanged with a
zero-context diff, on pin 11's precedent.

No behaviour, test or normative semantics changes. The prose diff is itself
observable, which is what 9.6 observes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-11 20:48:53 +02:00
Levi Neuwirth bff7be0f9d
P13-S26 amendment 3 EXECUTED: test 3 selects the normative clause
Test 3 asserted phrase presence over the whole requirement block, so a referent
could leave the sentence carrying the normative force and survive in the closing
recap. Execution measured that escape and the annex recorded it; this commit
closes it by strengthening the guard rather than softening pin 4a's claim.

Test 3 now selects the normative clause -- the sentence carrying the sole
\MUST{} -- and runs all four assertions on that slice alone. Both halves of the
start rule are load-bearing and the helper's doc comment says why: last ". "
before the occurrence, falling back to just after the label only when there is
none. An unconditional fallback would return one slice spanning label to recap,
containing every needle; a period-only rule would swallow the label, which is
not a sentence.

Six mutations, six matching radii, test 3 alone in every case. Each attacks a
different layer: M22-M24 vary what the selected clause contains, M25 varies
which sentence is selected, M26 varies the fallback boundary -- starting after
the label versus widening before it -- and M27 varies whether selection is
unambiguous and therefore permitted at all. M27 is the one that reaches the
exactly-one assertion, because an assertion guarding the precondition of
selection cannot be exercised by any mutation that presupposes selection
succeeded.

Rows 4, 6, 7 and 8 only. core_spec.tex is not touched: the requirement's text
was always correct and only the guard was weak. The rung's original 38/38
matrix is preserved unchanged and amendment 3's evidence is appended beside it,
not merged into it.

One prose defect in ratified section 8.4 remains OPEN and is deliberately not
repaired here: that entry says M27 varies which clause is chosen, which M25 does
and M27 does not, since a correct implementation rejects M27 before selecting
any clause. Section 8.6 is unaffected and states something true. The annex
carries the corrected characterization and records the correction as open;
frozen text stays frozen regardless of severity, so the repair belongs to its
own amendment, which is not part of this commit.

Baseline unchanged at 43 suites, 1586 passing: amendment 3 alters an existing
test's scope and adds none.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-11 20:39:41 +02:00
Levi Neuwirth 7c8a30d282
P13-S26 amendment 3 RATIFIED; test 3 to be clause-scoped
Execution measured that pin 4a claims more than test 3 delivers. M12's first
application deleted the ordering referent from the requirement's normative
clause and left it standing in the closing recap; test 3 stayed green, because
it asserts phrase presence over the whole requirement block. A referent can
therefore leave the sentence where it does normative work and survive anywhere
else in the block.

Two repairs were available. Softening pin 4a to promise only what block-scoped
presence delivers would have made the contract honest and the guard no better,
leaving a measured escape undetected in a rung whose subject is documentation
drifting because nothing watches it. This amendment strengthens the guard
instead, so pin 4a's claim becomes true rather than smaller.

Test 3 will select the normative clause -- the sentence carrying the sole
\MUST{} -- and run all four assertions on that slice alone. The selector took
four rounds to get right and both halves of its start rule are load-bearing:
last ". " before the occurrence, falling back after the label only when there is
none. Revision B made the fallback unconditional, which would have handed M25 a
slice spanning label to recap containing every needle; revision C restored the
rule the fallback exists for.

Six signing mutations, one per step of the selector: M22 and M23 the referents'
clause scope, M24 the locality phrase, M25 the last-period rule, M26 the
fallback anchor, M27 the exactly-one-\MUST{} assertion. M27 closes the last open
item -- an assertion specified without asking what would exercise it -- and it is
the only mutation that varies which clause is chosen rather than what the clause
contains. Each carries a complete before/after requirement block so it applies
literally.

The section is an additive override: pin 4a and section 3 are frozen and are not
rewritten, the mutations are section 8's rather than inserted into section 3's
table, and the annex's 38/38 matrix is preserved with M22-M27 evidence appended.
Execution touches rows 4, 6, 7 and 8 only; core_spec.tex is not touched, because
the requirement's text was always correct and only the guard was weak.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-11 20:14:27 +02:00
Levi Neuwirth 96f6ede268
P13-S26 post-acceptance reconciliation: the two documents held back
Separated from eddf6e9 on S16's precedent: the execution commit carries only
touch-table paths, and the tracking documents are reconciled once the rung is
accepted.

CLAUDE.md's Green baseline moves 1583 -> 1586 and gains the suite count, 43. It
is now the single origin for BOTH figures, and the entry says why they can move
independently: P13-S26 added three tests in one new file, so the suite count
moved with the test count. A rung that only adds tests moves one figure. That
distinction was implicit before and is the kind of thing a reader reconciles
against on arrival.

The handoff continues not to restate the count -- the discipline S16 introduced
after the figure was kept in three places and went stale in all three -- and its
open-candidate paragraph now says so explicitly for the count of open rows too,
rather than carrying a tally that the next filing staleness. It records S16 and
S26 as landed, names S29 and S30 as filed by S26's execution, and notes
amendment 3 open against S26's own pin 4a.

Verified after editing, not before: 43 suites, 1586 passed, 0 failed, 0 ignored.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-11 19:31:35 +02:00
Levi Neuwirth eddf6e9c6d
P13-S26 EXECUTED: invariant 10 names its derived reference surface
Item 10 said only that "every cross-cutting structure's references resolve to
extant objects", naming no individual class, while the checker enforced a
surface spanning cross-cutting structures, structural top-level references,
meter references at every level a MeterChange appears, an attachment-internal
reference, event-internal references and the tempo map's segment anchors. The
Rust doc comment named many of those and not all. The two were incomplete in
different places, so neither could be repaired from the other; both are now
written from one table derived by reading every emitted condition in the four
functions that raise the tag -- 41 tokens, each with its resolution target and a
symbolic anchor back to the control flow that enforces it.

Two of the ledger row's own claims did not survive scoping and were corrected at
ratification rather than carried: the G3a aside is ambiguous, not false, and the
two-sided repair stands on incompleteness rather than on a falsehood.

Guarded by exact (token, target) set equality in a new testkit suite, against an
oracle validated before use. Ordering and vocabulary are separate assertions
because an out-of-vocabulary term sorts perfectly well. Duplicates are checked on
the raw extraction, which set comparison cannot see. Item 10's opening sentence
is the slice anchor as a complete literal, required to occur exactly once, so
pin 3's retention of it is machine-observed rather than asserted. t12 is narrowed
and renamed, not deleted: cargo test -p epiphany-core must still fail when the
doc block is destroyed, and testkit is another crate.

Chapter 3 gains req:time:aleatoric-reference-locality -- an aleatoric region's
ordering and bounds references must name events of that same region, a locality
rule the checker always enforced and no requirement stated. Its three count
constants were measured at execution, never predicted: 214/285/285 -> 215/286/286.

38 mutations, 38 matching radii, every one against the full workspace with
--no-fail-fast and restored by hand write-back. M3 is the single passing control:
with equality weakened to actual.is_subset(&expected), M1-B stops failing, which
is what makes exactness load-bearing rather than assumed. Two harness faults
halted the run and are recorded in the annex rather than smoothed over; the
second exposed a real weakness in the requirement guard, reported and left for
amendment 3.

Files two candidates this rung does not repair: P13-S29, the invariant-10 tag
multiplexing Chapter 3/4 failures through a public API and its Display; and
P13-S30, the repository-wide assumption that TeX is spelled exactly, whose
requirement-block branch is demonstrated by this rung's own M20.

Baseline 42 suites/1583 -> 43/1586: one new suite, three tests, none removed.
Clippy and the pinned fmt gate clean on 1.95.0; core_spec.pdf rebuilt with zero
undefined references.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-11 18:11:25 +02:00
Levi Neuwirth 86bf7c65b9
P13-S26 amendment 2: amendment 1's lifecycle statements
Ratifying amendment 1 discharged its prescriptions and left its prose
describing the state it was written in. Section 6 went on calling itself a
draft, its replacement "proposed", its ratification act pending, and its review
questions open -- while its own status line read RATIFIED and the hold had been
lifted at f9170b0. This does not rewrite that commit; it corrects what
ratification could not correct by itself.

Pin 11 did not cover any of it. Its landing edit reached section 6's revision
records only, so the preamble, the section and subsection lead-ins, and the
review disposition were owned by nothing -- the same shape as the defect pin 11
exists to prevent, one layer in: a document describing a state it is not in,
this time about its own amendment rather than about the rung. Ratification is
not self-applying. A frozen prescription discharges; the prose around it does
not, unless something owns it.

Applied: the preamble becomes a dated record ending the hold at f9170b0, past
tense throughout; 6.3 and 6.7 are marked ratified, with 6.7's two
ratification-act edits marked discharged and its closing paragraph put in past
tense where it had asserted the amendment was not yet ratified; 6.8 becomes a
closed review disposition, each question answered and attributed to the round
that answered it.

Pin 11's third landing edit and gate 13 are widened from "revision records" to
section 6's revision records, preamble and lifecycle records. Widened rather
than re-enumerated: listing the sentences that had gone stale would leave the
next one unowned in exactly the way this amendment repairs. Gate 13 still reads
the status line specifically and never searches the section for DRAFT, which
the revision records legitimately contain.

No implementation target is touched. core_spec.tex, invariants.rs, the ledger
and the guard file remain untouched at 01c621d; baseline unchanged at 1583
passing across 42 suites. Execution resumes at pin 3 with amendment 1's shape
unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-11 15:05:59 +02:00
Levi Neuwirth f9170b0ed9
P13-S26 amendment 1 RATIFIED; pins 3, 6 and 11 amended
Execution was dispatched, began, and stopped at pin 3 before its first edit:
pin 3 required item 10 to keep an opening sentence scoped to "cross-cutting
structures" -- a defined term denoting pin 1 group A -- while gaining a nested
list spanning every group. Reported, not patched, per the frozen-pin
discipline; this is that amendment, after five review rounds.

Item 10 gains a subordinated universal deferring to explicit permission only:
"Except where the re-anchoring rules of Chapter~\ref{ch:semops} explicitly
permit transient dangling states during edits, every graph reference resolves
to an extant object." The ratified sentence is retained verbatim beneath it
with its own exception and cross-reference, so nothing normative is removed.

Three subordination forms were tried and the reasoning behind the first two was
itself defective twice. A cross-cutting-scoped exception is not shown wrong --
only unproved, since deciding it needs the exception's surface derived. A bare
"as the re-anchoring rules permit" is ambiguous: it can be read as deferring to
coverage, and coverage is not permission. The re-anchoring table does reach
group E (Cue source, Trajectory endpoint pitch), but both rows prescribe
cascade deletion or immediate replacement -- neither leaves anything dangling,
so reach establishes governance, not permission. The surface derivation is
presented for disposition, not filed: no ledger row is added, and filing in
this contract means a row.

Pin 6 gains the new anchor, an exactly-once requirement within
req:graph:score-graph-invariants, and M21 to sign it. M19 is rebuilt: it
truncates the real opening AND places one complete anchor after the nested
list, so uniqueness stays at one and does not mask the mutation, a prefix slice
passes, and the pinned complete-literal slice starts past the list and fails --
the two anchor kinds driven to opposite verdicts by one mutation.

Two edits belong to this ratification act rather than to pin 11, because the
contract was already dispatched and its top status already untrue; deferring
them would have left the document lying about its lifecycle for the whole of
execution. Both are applied here: this section's status literal, and a
clause-level replacement in the top status paragraph, pinned as Markdown source
so that the ratification date, the owner's authority and the no-count rule all
survive. Pin 11 keeps only the landed forms.

Baseline unchanged at 1583 passing across 42 suites. No pin 3 or pin 6
implementation target has been modified; execution resumes at pin 3.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-11 14:59:08 +02:00
Levi Neuwirth 01c621d64e
P13-S26 RATIFIED; pins frozen, not dispatched
The final whole-artifact check returned zero findings. Ratified on the
authority of the repository owner. Contract status: RATIFIED, PINS FROZEN --
executed, not edited; a defect found during execution is reported as its own
amendment with its own review round. NOT YET DISPATCHED: ratification and
dispatch are separate acts and no execution has begun. The status line states
no count of the review passes, per the rule this contract adopted after its own
tallies went stale twice.

Two of the ledger row's own claims did not survive scoping, and the row is
appended -- never rewritten -- with both corrections. The doc comment's G3a
aside is ambiguous, not false: G3a's pin 6 is titled "doc-only" and 6c5e69f
wrote the aside, so "this prose" is self-referential. The row's "claims a
specification repair that never landed" reading is withdrawn, and with it the
"only artifact pointing at the gap" rationale. The two-sided repair stands on a
different footing: the normative enumeration and the doc comment are incomplete
mirrors of each other, incomplete in different places, so neither may be
repaired from the other. The surface is derived from the check bodies instead --
41 tokens, each carrying its resolution target and a symbolic code anchor.

Review scaffolding, applied earlier under a narrow authorization and committed
here because ratification is what changes its staging state: two
DISCUSSED_NOT_CITED rows in requirement_labels.rs. The citation scan reads the
filesystem rather than git, so this contract naming two not-yet-existing labels
broke the mandated green baseline for three review passes before it was
measured. The req:graph: row is permanent -- it never becomes a requirement and
survives only in M6's evidence. The req:time: row is temporary, deleted by pin 4
when the requirement lands, because at that moment its own claim ("discussed,
never cited") turns false; gate 12 checks that deletion, since a stale row is
inert and nothing else would catch it.

The rung also files two candidates it does not repair: P13-S29, the invariant-10
tag multiplexing Chapter 3/4 failures through a public API and its Display; and
P13-S30, the repository-wide assumption that TeX is spelled exactly, which
misses \label {x}, \begin {requirement}, \end {requirement} and \chapter {X}.
S30 carries four consequences with the conditions under which each is silent or
loud -- three of them silent only conditionally, two distinct panic paths, and a
full inventory of the ten known consumer sites across three files, all
test-scope.

Baseline unchanged at 1583 passing across 42 suites; clippy and the pinned
four-crate fmt gate clean on 1.95.0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-11 13:19:26 +02:00
Levi Neuwirth fcc3fb6b39
P13-S16 amendment 1, review round 1: two documents still described the old state
Both are the one-hop failure the amendment itself is largely about -- the
correction reached the top of each file and stopped.

CONTRACT_P13S16_PROJECTION.md
  The status block was moved to LANDED / RESOLVED, but two screens below it the
  ratification-time framing still read "not the fourth", "nothing is
  implemented", "every gate, test and mutation is specified and none has been
  run", and "4a's landing obligation is outstanding by construction". A reader
  scrolling past the status line met the pre-execution contract presented as
  current.

  Everything from that point to 7 is now marked as a DATED RECORD, S27-style:
  retained rather than rewritten, because the pins are frozen and the review
  records are the review state. The four "what ratification does NOT settle"
  bullets keep their text and gain their outcomes -- t9 confirmed, t8d
  falsified, all gates and mutations run, 4a honoured then discharged at
  3328b2c, and the predicted post-execution amendments being this one.

EVIDENCE_P13S16_EXECUTION.md
  Its header still said it was "deliberately not staged", absent from the touch
  table, and that committing it would need an amendment adding a touch row --
  describing, in the present tense, the state the commit it arrived in had just
  ended. Recast to past tense, pointing at 7's touch row 12.

  The distinction it was drawing survives and is kept: the fourteen paths in
  aee4ff9 are the rung, this is the evidence the rung was reviewed against. It
  documents aee4ff9; it is not part of it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-10 17:50:42 +02:00
Levi Neuwirth a65d79d752
P13-S16 amendment 1: post-landing corrections, consolidated
Five corrections against CONTRACT_P13S16_PROJECTION.md, all against the
document rather than the code -- aee4ff9 is accepted and unchanged. Filed as
one amendment on the owner's decision because the findings are not
independent: two pairs share a root cause, and separate rounds would have
recorded symptoms while hiding the causes.

Root A -- the contract reasoned about MECHANISM where the question was what
the test ASSERTS. Findings 1 and 3. Both cells are right about the production
code and wrong about the observation, because a test that verifies its own
fixture is meaningful fails for a second reason no mechanism argument reaches.

Root B -- enumeration where completeness was required. Findings 2 and 4. Both
lists were built by reading one file. The contract already carries derive-do-
not-enumerate under pin 10a and 6 item 1, and broke it twice in its own
apparatus.

  1. Invariant 21 does not detect the undo residue (0.6, pin 5a, pin 6b). It
     abstains on dangling members by design; M5 shows invariant 10 firing
     instead. The hole was already covered before this rung. u5's direct
     members assertion is what signs pin 5 -- the fallback pin 6b itself names
     -- so nothing is unsigned.
  2. 3's M6a row names six failing tests; seven occur. The fifth all()
     consumer is in tests/score_graph.rs, outside the four-in-generators.rs
     list.
  3. 3's t8d-under-M2 survivor cell is falsified -- it fails on non-vacuity,
     not idempotence. The assertion must not be weakened: under M2 t8d is
     genuinely vacuous. The other falsifiable cell, t9 under M1, was CONFIRMED.
  4. Pin 10 cites four of the nine sites its instruction covers, and gate 6
     cannot see core_spec.tex's "exactly 20 invariants" sentence.
  5. cargo test --workspace truncates the failure set at the first failing
     suite -- exactly the condition every mutation creates. 3's uniform rule
     and gate 1 now specify --no-fail-fast.

Finding 6 is WITHDRAWN as false and retained as record. Pin 8's line numbers
were exact on the ratified tree 34232dc -- all four verified -- and only
stopped matching because this rung inserted ~1,500 lines above them. It had
been reported without the cited locations ever being measured. Writing the
amendment is what forced the check, which is an argument for consolidating
rather than filing six rounds.

Touch row 12 added, so spec/EVIDENCE_P13S16_EXECUTION.md is committed rather
than left untracked: the findings are conclusions, and the annex is the
evidence they were derived from, including the runs that falsified two of this
contract's own predictions. Its trailing whitespace is stripped so gate 4
passes, and it says so.

CLAUDE.md, the handoff and the ledger row are corrected in step -- all three
said "six findings", which is now the count before review rather than after.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-10 17:42:18 +02:00
Levi Neuwirth 3328b2c0e2
P13-S16 post-acceptance reconciliation: the three documents §4a held back
Contract 4a deliberately kept these out of aee4ff9 because they describe the
state of the repository rather than the change, and staging them during
execution would have asserted that S16 had landed. It has, so they move now.

CLAUDE.md
  - Green baseline 1577 -> 1583, still the single origin for the count.
  - Added: use --no-fail-fast whenever anything is failing. The bare command
    stops at the first failing suite, which is exactly the situation every
    mutation creates -- S16's M6a read six failures over four suites bare and
    seven over all forty-two with the flag.
  - The authority is currently 1, not 0, and a base materialized before S16
    must be rebuilt rather than reused.
  - The bump rule now names BOTH classes it always covered: a change to a
    reduction verdict OR to canonical reduced state. S16 carried one of each,
    and the state-only kind is the easier to overlook while invalidating a
    base just as completely.
  - Two-tracks table: S16 LANDED, with a pointer to its unamended findings.

spec/HANDOFF_2026-08-07.md
  - Chain state and §4.3 item 9 -> LANDED at aee4ff9, each retaining what it
    said before, since the block is a record of what moved.
  - The POST-S27 authority paragraph -> currently 1, both bump classes named.
  - Records the two S16 findings that bite outside their own contract: the
    --no-fail-fast truncation, and invariant 21 abstaining on dangling
    membership rather than detecting the undo hole 0.6 attributed to it.

spec/PASS13_CANDIDATES.md
  - The S16 row is appended to, not rewritten: ACCEPTED AND LANDED at aee4ff9,
    superseding its own "EXECUTED ... NOTHING IS STAGED" sentence, RESOLVED,
    and the six contract findings listed as outstanding follow-up.

The six findings remain unamended against CONTRACT_P13S16_PROJECTION.md. Its
pins are frozen, so each needs its own amendment and review round; recording
them at both ends is what keeps them visible until then.

spec/EVIDENCE_P13S16_EXECUTION.md stays untracked -- no touch row covers it,
and adding one is an amendment, not a keyboard decision.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-10 17:30:27 +02:00
Levi Neuwirth aee4ff92b7
P13-S16 EXECUTED: StaffGroup.members becomes a maintained projection
Disposition A replaces genesis tranche G3a's disposition B. Staff.group was
already the sole authority, but members was stored exactly as carried and
neither maintained nor trusted, so both disagreeing states were permitted
outcomes. Neither is authorable any more.

  - CreateStaffGroup refuses a non-empty carried members (ContainerNotEmpty).
    This is an empty-container precondition on the carried value, NOT a
    referential one, so unlike the sibling mints it is not graph-gated and
    holds base-free too. t7's assertion inverts for exactly that reason.
  - CreateStaff carrying group: Some(g) appends the staff to g's members in
    the graph, idempotently; undo of a staff strips it back out.
  - Graph invariant 21, StaffGroupMembershipAgreement, flags disagreement in
    either direction between live objects via two independently removable
    checks. It abstains on dangling membership -- an undeclared member is
    invariant 10's concern, not a disagreement.
  - staff_group_values keeps the carried value, and seed_from_graph reseeds it
    with members emptied, closing the reload hazard that only appears after a
    snapshot round trip.
  - CURRENT_REDUCTION_ALGORITHM_VERSION 0 -> 1 with its Bumps entry, naming
    both causes separately: CreateStaffGroup changes a reduction verdict,
    CreateStaff changes canonical reduced state. Either alone requires it.
    Bases materialized before this rung must be rebuilt, not reused.

Specification: operation_catalog.tex 0.15.0 and core_spec.tex's Revision
History; nine disposition-B prose sites rewritten, invariant 21 appended to the
Chapter 5 enumeration (count 20 -> 21), both PDFs rebuilt. No payload bytes
move, no schema or epoch moves, no vector artifact changes.

Evidence: 20 pins, 14 gates, 11 mutation executions. Baseline 1577 -> 1583
(six net-new tests). Both S27 tripwires fired on the bump and were updated to
independent literals, never to the constant.

Six findings reported against the contract rather than patched into it:
invariant 21's abstention vs the undo-hole attribution in 0.6/pin 5a/pin 6b;
M6a's failure set is seven, not six; t8d under M2 is falsified as a survivor;
pin 10 cites four of nine prose sites; cargo test --workspace truncates the
failure set without --no-fail-fast; pin 8's line numbers had drifted.

CLAUDE.md and spec/HANDOFF_2026-08-07.md are deliberately NOT in this commit
(contract 4a) and still describe the pre-bump state; their reconciliation is
post-acceptance work.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-10 17:18:20 +02:00
Levi Neuwirth 34232dc1a6
P13-S16 RATIFIED after twelve independent rounds; pins frozen, not dispatched
Ratification round 12 returned zero findings against 25b4925 -- the live
mutation-site locators, M7's field anchors, M6's structural mapping,
touch-table coverage, the gate and report consumers, and the expected-outcome
table all rechecked, with the revised m40 citations and the remaining named
mutation sites resolving against the tree. Ratified on the authority of the
repository owner.

Contract status block: RATIFIED, DISPATCHABLE, PINS FROZEN -- executed, not
edited; a defect found during execution is reported as its own amendment with
its own review round. The block's earlier promise to say RATIFIED when the
decision was taken is discharged, and it still states no round count, per
round 2's correction.

NOT YET DISPATCHED. Ratification and dispatch are separate acts, no execution
instruction has been given, and nothing is implemented -- so the ledger row
does NOT move to RESOLVED. The contract now distinguishes four states:
unblocked, ratified, dispatchable, resolved. This rung is the first three.

What ratification does not settle, recorded at the top of the contract:

- Two cells of §3's expected-outcome table -- t8d under M2, t9 under M1 -- are
  PREDICTIONS from pins not yet executed, stated so they can be falsified. A
  mismatch is a finding in the contract or the implementation.
- Every gate, test and mutation is specified and none has been run. Twelve
  rounds went into the claim that they can be run and that their results would
  be evidential; execution is what tests that claim.
- §4a's landing obligation is outstanding by construction: CLAUDE.md and the
  handoff carry statements pin 12's bump falsifies, and must not be staged
  during execution.
- The execution report is subject to independent review before completion is
  accepted, as S27's was -- which turned a clean paper record into seven
  post-execution amendments.

Round 11 is also recorded: pin 6's m40 locators had drifted to invariants.rs:6045,
the enclosing module's doc comment rather than m40's own. Fixed by the owner at
25b4925 to :6060-:6135 and gate 6 to :6063; verified against the tree.

The defect record, so ratification is not read as vindication: 32 findings
closed before it -- 19 in draft amendment 1 and revisions A-J, 13 across rounds
1-11. None was in the pins' substance. The maintenance rule, the refusal,
invariant 21, the undo strip and the authority bump have been stable since
draft amendment 1, and every single finding was in the evidence apparatus:
what observes a requirement, what channel carries an observation, who owns a
claim, and whether a locator resolves. That is where this contract was weak and
where execution should be read hardest.

Governing docs updated to the now-true state: CLAUDE.md's track head, the
handoff's POST-S27 chain row, and the S16 ledger cell, which supersedes its own
"has not been through adversarial review" sentence per the append-only
convention.

Documentation only: no .rs or .toml touched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 20:55:00 +02:00
Levi Neuwirth 25b492575e
S16: ratification round 11 -- rederive m40 locators 2026-08-09 20:47:46 +02:00
Levi Neuwirth 63a2dc8ce7
S16: ratification round 10 -- remove the tally from item 1's own explanation
Whole-artifact review of a5f3013 returned one blocking finding.

§6 item 1 declared that no count is stated there and then stated one: "M7's
split into M7a and M7b makes ten executions." §3's table now has eleven
mutation rows -- M1 through M5, M6a/M6b, M7a/M7b, M8, M9 -- because M6 split
too. This is a live report requirement, not dated history, so an execution
report could reconcile against the wrong set.

The paragraph indicted itself: its closing sentence warned that "a count here
goes stale the next time a mutation splits", and then M6 split and the count
went stale exactly as predicted, with the warning still attached to it.

Item 1 now reads: no count is stated here, §3's table is the single origin,
read its rows. The parenthetical records both stale values -- the original
"nine mutations (M1-M9)" and the replacement tally -- without restating a
current one.

This is revision J's rule, applied to item 1 after J applied it to item 2: an
explanation of a removed count must not restate a count. Items 1 and 2 are
adjacent lines, and J swept one of them. The neighbour-not-swept failure, in
the very pair of items that produced the rule.

Swept for other live mutation tallies: three remain, all inside dated revision
records or quoting superseded text (revision B's finding cell, round 7's
record, and item 1's own parenthetical). The live requirement is count-free.

Round 9's field-declaration anchors are confirmed sound by the reviewer: both
declarations are unique in graph.rs, and a B-wording revert leaves each
declaration available, so the needle assertion rather than the locator produces
the required output. That closes round 9's second finding on evidence rather
than on derivation.

Committed one round late: the shell tooling failed mid-round after the edit
landed, so this change sat uncommitted and was reported as such rather than
claimed as done.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 20:42:36 +02:00
Levi Neuwirth a5f3013044
S16: ratification round 9 -- harden the locator, not only the assertion
Whole-artifact review of 942f261 returned one blocking finding. A sweep of it
escalated a second.

1. The expected-outcome table recombined M7a and M7b as "its own grep guard;
   the other guard." That recreates the exact ambiguity M7's split existed to
   remove: a report can say "own guard failed" without establishing which guard
   failed or which survived -- and round 8's full-suite rule reports tests by
   name, so a row naming none cannot be checked against it.

   Split into two rows with the exact names. M7a fails
   t14_staff_group_field_doc_comment_states_sole_authority (graph.rs:2136)
   while t14_staff_group_members_field_doc_comment_states_non_authoritative_projection
   (:2160) must pass; M7b the reverse. Each quotes its needle-miss message and
   the doc_block that message dumps.

   M7 was divided in draft amendment 1 precisely because one mutation covering
   two guards could pass with the other still weak. The table re-merged them
   for brevity. A summary row is a restatement, and a restatement of a
   distinction can drop it.

2. Sweep: M7b's required output was unobtainable. Both guards locate their doc
   block by searching for a phrase from the doc text, and :2163's anchor is the
   disposition-B claim pin 10 rewrites. Once the anchor is updated to the A
   wording, M7b's revert to B makes .find() return None and
   .expect("StaffGroup.members's doc comment is present") panics -- naming no
   needle and dumping no block. The required observation would be an anchor
   panic pointing at absent text.

   Pin 10 now requires the slice to be located from the FIELD DECLARATION --
   pub group: Option<StaffGroupId>, and pub members: Vec<StaffId>,, which no
   wording changes -- extending backwards over the contiguous /// lines. The
   block then exists under either disposition and the only way to fail is the
   needle assertion, with message and block intact.

   This is the absence-grep lesson one level down. Pin 10 hardened the NEEDLES
   against wording both dispositions satisfy and left the ANCHORS matching
   wording only one disposition has. A guard whose locator depends on the text
   it inspects fails before it can report, and failing early looks like failing
   correctly: the test is red, the mutation "worked", and the evidence never
   existed.

Still DRAFT, still unratified. No implementation work has begun.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 20:32:43 +02:00
Levi Neuwirth 942f261094
S16: ratification round 8 -- make the expected-outcome table evidential
Whole-artifact review of 2a445d1 returned one blocking finding: the table named
required survivors without requiring them to be run.

§6 consumed mutation output generally and no cell specifically -- t8c, t8d, u5,
pin 8's four, the structural gates -- and only M6 required its sibling's
verdict. "Report any mismatch" cannot detect a survivor that was never run: an
unrun test yields no mismatch and no evidence, so every survivor cell was an
unobserved claim, and the table read as evidential while being advisory.

One uniform rule now governs every mutation:

  1. full cargo test --workspace, with the COMPLETE observed failure set
     reported;
  2. the named failing tests' output, per the channel rules -- behaviour, not
     the fact of failure;
  3. each named required survivor's PASS VERDICT, by name;
  4. each named structural gate's output -- gate 8 under M1 and M8, gate 12
     under M6a/M6b, pin 10's guards under M7a/M7b.

An omitted named artifact is itself a finding, on the same footing as a wrong
outcome. §6 item 1 consumes the rule. M6's per-half list is now marked as the
general rule applied rather than a special case.

This is revision D's class -- a requirement nothing can fail -- reproduced by
the very table written to end the discovery model. Round 7 moved authorship of
the expected outcome from execution to the contract, which was right, and left
the outcome unobserved. A claim the contract owns is not thereby a claim
anything checks.

The finding also forced a distinction left implicit. The survivors column said
"notable", quietly meaning not exhaustive, so a uniform "run every named
survivor" rule had to say what IS exhaustive. Now stated: the MUST-fail column
is exhaustive, verified by requirement 1's full-suite run; the survivors column
is illustrative, naming the ones a reader would doubt, and everything outside
the failing column must survive whether named or not. Without the full-suite
run the failing column's completeness was unverified as well, so the fix closes
a second hole the finding did not name.

Three rounds running have the same shape: round 6 wrote a rule and exempted
three mutations, round 7 wrote a table and left it unrun, round 8 makes the
table evidential. Each fix was correct about what to specify and incomplete
about who observes it.

Still DRAFT, still unratified. No implementation work has begun.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 20:28:36 +02:00
Levi Neuwirth 2a445d16be
S16: ratification round 7 -- the contract owns the expected-outcome table
Whole-artifact review of 80be47c returned one blocking finding: round 6's
blast-radius rule contradicted itself.

It required every mutation to state every expected failing test, then left M1,
M2 and M5 for execution to derive -- the discover-the-radius model it claimed
to eliminate, with the expected set depending on the executor's reading. And
execution cannot both author the table and certify its own result against it.

The cited surfaces were also insufficient, not merely incomplete. Round 6
listed touch row 8, pin 1a and pin 8. None owns t8c, which pin 3a defines four
sections away asserting g.members == [s] -- exactly the value pin 2 maintains,
so M2 breaks it. Any derivation from the stated surfaces would have missed it.
The instruction was unfollowable as well as misassigned.

§3 now carries the contract's own per-mutation expected-outcome table: failing
tests, notable required survivors with the reason each survives, and structural
gate outcomes, for all ten mutation halves. Dependency surfaces are cited and
now include pins 3a, 4a, 5a, 6a and 7 alongside pin 1a, pin 8, touch row 8, and
check_invariant = check_invariants(...).filter(...).

Execution re-derives the table against the staged tree and reports any
mismatch, in either direction, as a finding against the contract or the
implementation. No cell is a licence to ignore an outcome.

Notable entries the table now owns rather than leaving open: M1 fails gate 8,
since the refusal is what that gate reads for; M8 fails gate 8 as its only
signature and must break nothing behavioural; M6a and M6b both fail gate 12
because a call site is gone; t8c, t8d, u5 and pin 8's four all survive M1
because they carry members: [] so the refusal never fires for them.

Cells carrying a reason -- t8d under M2, t9 under M1 -- are derivations from
pins not yet executed, stated so they can be falsified. That is the division of
labour the finding asks for: the contract predicts, execution measures, and a
mismatch is a finding against whichever is wrong. The table has no totals, so
it avoids the stale-count class entirely.

Still DRAFT, still unratified. No implementation work has begun.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 20:23:07 +02:00
Levi Neuwirth 80be47ca13
S16: ratification round 6 -- derive a mutation's blast radius, don't recall it
Whole-artifact review of 85429d6 returned one blocking finding: M6a's blast
radius was understated.

check_invariant is check_invariants(...).filter(...) (invariants.rs:313-:318),
so deleting the S->G dispatcher call silences that violation for every
consumer, not only the two tests M6a named. The full radius is six, each now
tabled with where it fails and why:

  m41...staff_names_absent_group          its own assert_eq! cardinality check
  invariant_21_negative_generator_...     same
  every_invariant_has_a_negative_generator  own assert! at generators.rs:994
  negative_generators_are_reasonably_targeted  own assert! at :1046
  every_invariant_shrinks_to_a_small_witness   INSIDE shrink, entry assert :933
  shrink_is_idempotent                         INSIDE shrink, same assertion

All six share one cause and all six are expected, not findings. The last two
panic with "shrink starting point must violate the target invariant", raised in
a function the mutation never edited, so they are to be reported as
shrink-entry failures rather than misread as a defect in shrink.

M6b's single expected failure -- m41b alone -- is now recorded as positive
evidence: the four all() consumers and the generator test all stay green
because every invariant-21 fixture is S->G, which confirms touch row 8's pinned
direction more directly than any assertion about the generator does.

Round 5 added the blast-radius rule and then enumerated the radius from memory.
Touch row 8 already lists those four consumers with these exact line numbers --
draft amendment 1 put them there as the two-crate root cause -- and M6a's
outcome was written without consulting the row that owns them. The document
knew; the mutation did not ask.

That is a new variety of the propagation failure. Revisions A-J recorded
corrections failing to reach a consumer; round 1 a declared peer; round 4 a
gate written later. This one is a fact recorded in one section not reaching a
requirement written in another -- nothing stale, nothing contradicted, and no
sweep for restated text would find it. It needed the question "what does this
section already know that this one should be using?"

So the fix is an obligation rather than a list: §3 now requires every mutation
to state its complete expected-failure set, derived from the recorded consumer
surfaces (touch row 8's four, pin 1a's three, pin 8's four), with any unlisted
failure treated as a finding in the contract or the implementation. M1's, M2's
and M5's radii are deliberately not enumerated here, since enumerating from
memory is what produced this finding; execution derives each and reports the
derivation.

Still DRAFT, still unratified. No implementation work has begun.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 20:16:29 +02:00
Levi Neuwirth 85429d6243
S16: ratification round 5 -- the assert macro is part of the channel
Whole-artifact review of e48bb8d returned one blocking finding: M6 was not
covered by round 3's own channel rule.

Pin 6a requires an exact violation set without saying how, so a conforming
assert!(violations.len() == 1 && ...) satisfies it and prints nothing on
failure -- and that assertion is precisely what M6 trips. Gate 6 and §6 item 2e
use the passing-test model, source assertions plus ok. So M6 reverted to "the
named test failed", the signature this contract rejects.

Pin 6a gains a harness for m41, m41b and the generator test: bind
check_invariants to a local before any assertion; make the cardinality check an
assert_eq! on that local with the full violations vector in its diagnostic; and
make it the first assertion after the bindings, since it is the one M6 trips.
Gate 6 now confirms the macro. M6a/M6b quote the failing output plus the
sibling's pass verdict.

Round 3 wrote the channel rule and applied it to M1, M2 and M5 -- the
mutations named in that round's finding -- and not to M6, which has the
identical need. Round 3's text even carved M6 out, listing it among mutations
that "already met the standard": true of its behavioural observation, which
names the state, and false of its channel, which had none.

The macro is part of the channel, not a style choice. assert_eq! prints
left/right; assert! prints only its message. Under M6a the S->G arm is gone,
check_invariants returns empty for m41's fixture, and assert_eq! prints 0
against 1 with an empty vector -- that is "the violation went unreported",
quoted rather than inferred. With assert! the same requirement is met with no
evidence. Where a mutation's observation IS the compared value, the pin must
name the macro; the rule is now at the head of §3 rather than left to each
mutation.

A second gap closed with it. M6a also breaks the generator test, since that
fixture is S->G. Unstated, an executor either reports a defect that is not one
or ignores a failure it cannot classify. M6b leaving the generator green is now
recorded as positive evidence that touch row 8's pinned direction holds. A
mutation must state every test it is expected to break, or its blast radius is
discovered instead of specified.

Still DRAFT, still unratified. No implementation work has begun.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 19:08:59 +02:00
Levi Neuwirth e48bb8d0b4
S16: ratification round 4 -- "the resulting value" is not a value when there are two reductions
Whole-artifact review of 3e0a4d3 returned one blocking finding in round 3's own
harness.

Pin 7a collapsed two fixtures into one binding. t8b runs TWO authoring orders
(§0.5) -- two reductions over two different groups -- but pin 7a bound "the
resulting StaffGroup.members" and one filtered invariant result. A single
members local satisfies the harness as written while leaving either mutation's
required observation absent, depending on which order it came from; and the
invariant result filtered from the wrong reduction is the wrong verdict, not a
missing one.

Pin 7a now binds four, before any assertion:

  1. spurious-order OperationEffect  (M1: becomes an applied effect)
  2. spurious-order members          (M1: the spurious membership in the graph)
  3. missing-order members           (M2: stays empty)
  4. missing-order invariant-21 violations (M2: the disagreement left behind)

Every assertion formats all four, so whichever assertion a mutation trips
carries both of that mutation's observations. Gate 14 must now establish WHICH
ORDER each binding came from rather than counting bindings. M1 and M2 name
their own order at every mention.

Round 3 fixed the channel and left the fixtures conflated. It correctly
established that a failing test has one output channel and that state must be
bound before the assertion a mutation trips, then described the state as though
t8b had one reduction. The ordering rule was right and the inventory was wrong,
which is why the harness looked complete: three plausible bindings, none wrong
on its face, and nothing in the pin revealing that two of them are per-order.

The generalisable form: a definite article asserts uniqueness exactly as
silently as a number asserts a total. "The resulting value" reads as precise
and hides the question of which one -- the singular-noun cousin of the count
defects this contract has been removing since revision A.

And gate 14 inherited gate 12's defect before gate 12's fix could reach it.
Gate 12 was rewritten in revision H because a four-line aggregate proved a
population and not a pairing; gate 14 was written in round 3 requiring "three
bindings" -- the same shape, one section over, three rounds later. Ratification
round 1 recorded a fix failing to reach a declared peer; this is a fix failing
to reach a gate written after it.

Still DRAFT, still unratified. No implementation work has begun.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 18:57:18 +02:00
Levi Neuwirth 3e0a4d38c1
S16: ratification round 3 -- a failing test has exactly one output channel
Whole-artifact review of e43cd34 returned one blocking finding: three
mutations required runtime state that none of their prescribed artifacts is
required to emit.

M1 wants the applied OperationEffect and minted members; M2 the still-empty
members and invariant-21 verdict; M5 the post-undo members plus the
invariant witness. But pin 7 says only that t8b inverts, and gate 13 and §6
item 2f prescribe source assertions plus a normal pass verdict -- a
passing-test evidence model. A mutated test stops at its first failed
assertion, so state carried anywhere else is never printed, and M5's witness
assertion may not execute at all.

Fixed by pinning observation harnesses:

- Pin 7a: t8b binds the OperationEffect, the resulting StaffGroup.members and
  the invariant-21 verdict to locals BEFORE its first assertion, and formats
  all three into EVERY assertion's failure message.
- Pin 5a: u5 binds the post-undo g.members and the check_invariants
  violations with witness ids before assertion 2, and formats both into
  assertions 2 and 3.
- Gates 13 and 14 quote those diagnostics from source. M1, M2 and M5 quote the
  resulting failure output verbatim.

The finding is revision E's, one case over. Revision E chose "quote the source
assertion plus the pass verdict," which is correct for a PASSING test, since
that is all a passing test emits. Mutations need the failing case, and the
failing case has exactly one channel: the diagnostic of the assertion that
fired. Settling the first did not settle the second.

The ordering half would have survived a careless fix. Putting each observation
in "its own" assertion reads as tidy and is precisely wrong: M1 trips t8b's
spurious-order assertion and M2 the missing-order one, so a message carrying
only its own value disarms whichever mutation trips the other. In u5 it is
worse -- M5 trips assertion 2, making assertion 3's witness unreachable by
construction. The state a mutation owes must be bound before the assertion
that mutation trips.

Rather than pin this three times, §3 now heads with the general rule, which
also covers the mutations the review did not cite: where the observation is a
single value under assert_eq!, the default left/right diagnostic carries it,
and M3, M4 and M9 qualify provided they compare the verdict rather than
assert!(matches!(...)), which prints nothing -- the report must state which
form each uses. Where the observation is composite, or behind an assertion the
mutation makes unreachable, a harness is required.

Still DRAFT, still unratified. No implementation work has begun.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 18:46:19 +02:00
Levi Neuwirth e43cd3410b
S16: ratification round 2 -- the status block stops describing the review
Whole-artifact ratification review of 5ec2ce0 returned one blocking finding.

The live status block still said this contract "has not been through
adversarial review rounds." That was true when written and false from the
first independent pass onward, and it sat in the "what remains before
dispatch" summary -- so a top-down reader received a false review-state signal
before reaching any record that contradicts it.

Replaced with a non-rotating pointer: the review records below are the review
state; the block states no count and no ordinal, and will say RATIFIED when
that decision is taken. Also sharpened the neighbouring sentence to name three
distinct states -- unblocked, ratified, dispatchable -- since conflating the
first two is the specific failure it cites from S27.

This is the status-block defect S27 spent amendments 4 through 7 removing,
reproduced here in its purest form. S27 established that a status line
describing the review must not describe the review: it must point at the
record that owns it, because every such line goes stale exactly when the
review advances, which is the one moment nobody is reading the status block.

What makes this worse than a stale count: a stale count reads as an error,
while "has not been through adversarial review rounds" reads as a verdict on
the artifact's maturity. A reader deciding whether to trust this draft would
have taken it as the answer, with ten revisions of independent review recorded
immediately below it.

And it is the whole-artifact question again. Rounds against edits ask "is this
change right?"; only a whole-artifact read asks "is anything the document says
about itself still true?" Round 1 found a missing permanent test that way;
round 2 found a false status claim. Both were invisible to every incremental
pass, and neither was in the content those passes were correcting.

Swept for other live review-state claims: none. The only remaining
"NOT RATIFIED" is the status line itself, which is the fact that changes at
ratification, and the false sentence survives only inside its own correction.

Still DRAFT, still unratified. No implementation work has begun.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 18:38:27 +02:00
Levi Neuwirth 5ec2ce0bbd
S16: ratification round 1 -- pin 5 gains a permanent regression test
First independent round against the draft as a whole rather than against the
previous revision's edits. One blocking finding, and it is one that ten
revisions of amendment review did not surface.

Pin 5's staff-undo repair was signed by M5 alone. No named test performed
CreateStaffGroup(g, []) -> CreateStaff(s, group: Some(g)) -> undo the staff ->
assert the still-live g.members no longer holds s.

Verified that nothing existing supplies it:

- Pin 8's four tests are group-undo guards. u2tomb_a (reduce.rs:17125) does
  undo a staff, but its assertions are that the undo tombstones the
  referencer, that T1's undo then proceeds, and that "the group leaves
  Score.staff_groups" (:17187) -- it undoes the group too, so no live group's
  members is ever inspected.
- Gate 6's m41/m41b build materialized fixtures and never run the reducer's
  undo path.

Pin 5a adds u5_undoing_a_staff_strips_it_from_the_live_groups_members with
three assertions: the group is still live (without which the test can pass
vacuously on a score where the group was undone too -- exactly how u2tomb_a
misses this path), g.members lacks s by id, and check_invariants reports no
StaffGroupMembershipAgreement violation. Gate 13 runs it. §6 item 2f reports
it. M5 now breaks it by name and reports the changed state -- the post-undo
g.members still containing s, with the invariant-21 witness -- rather than
stating a condition.

The finding is revision C's, on the sibling pin. Revision C established pin
3a's rule that a mutation demonstrates the hazard once and only a test keeps
it demonstrated, and applied it to pin 6 and M6. Pin 5 and M5 have the
identical shape and were left alone, two paragraphs from the sentence "pin 6
is coupled to pin 5 and they split only together."

So the lesson is not "check mutations for permanent tests" -- that was already
learned. It is that a coupling stated in prose does not propagate a fix. Every
fix-propagation failure in revisions A-J was a correction reaching a CONSUMER
one hop late; this one failed to reach a declared PEER.

Why ten revisions missed it: each reviewed the previous revision's edits, so
the question asked was always "is this change right?", never "is anything else
the same shape?" A first whole-artifact round asks the second question.

Swept the other mutations for the same shape: M1/M2 break t8b, M3/M4 break
t8c/t8d via pins 3a/4a and gate 9, M6 breaks m41/m41b, M7a/M7b break the two
grep guards, M9 uses t7, and M8's structural gate 8 is explicitly the only
signature available for a deletion no behaviour observes. M5 was the only gap.

Also fixed before commit: gate 13 was first inserted before gate 12.

Still DRAFT, still unratified. No implementation work has begun.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 18:32:22 +02:00
Levi Neuwirth 253249ec0b
S16 draft amendment 1 rev J: a correction that explains a count must not restate it
Independent review of 9e43994 returned one blocking finding in three live
consumers: adding gate 12 in revision G restored the tally defect this
contract had already removed twice.

Three sites still said §4 has "eleven gates, 1-11":

- revision C's disposition for its finding 3;
- gate 4's scope note;
- §6 item 2, immediately after the words "No count is stated here -- §4 is the
  single origin."

All three removed, not updated. The revision-C record now says only that the
4a. scope note was demoted. Gate 4's note identifies §4a without counting
gates. §6 item 2 keeps the pointer to §4 and adds only that lettered subchecks
report under their gate.

§6 item 2 is the one that indicts the method: it declared §4 the single origin
and restated a count in the same breath. Revision B removed "the nine gate
results" from that very item; revision C's correction then wrote the
then-current number into the explanation; revision G's new gate made it false
again.

The rule this makes explicit: a correction that EXPLAINS a removed count must
not restate the corrected value. Say what changed, not what the number now is
-- otherwise the record becomes a new instance of the defect it records, and
the next addition to the set falsifies the explanation instead of the
original. Every count this contract has removed was re-created by the prose
written to remove it.

The sweep confirms the rule is not "no numbers anywhere". A count at its
origin, immediately above the table enumerating the set -- pin 1a's three
revised tests, pin 8's four G3a tests -- is read off rather than restated, and
a change to the set edits the table and the adjacent word together. The defect
is a count living away from the set it counts.

Still DRAFT, still unratified. No implementation work has begun.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 18:19:02 +02:00
Levi Neuwirth 9e43994def
S16 draft amendment 1 rev I: where a pin defines the artifact, the gate cites it
Independent review of 5d2db93 returned one blocking finding: gate 8's new
method named a boundary that made the gate impossible to pass or honestly
fail.

Revision H said to quote create_staff_group's production body "to the
#[cfg(test)] boundary." But create_staff_group begins at reduce.rs:4458,
create_part_definition begins at :4515 and carries its own
PreconditionFailureReason::TargetMissing at :4554, and the next #[cfg(test)]
is at :9576. So the literal read spans roughly 5,000 lines and always contains
the very path the gate says must be absent, while any shorter read violates
the stated boundary.

Gate 8 now quotes exactly pin 1's slice: create_staff_group's body,
brace-matched from its fn line to its closing brace, production source only.

Pin 1 had the boundary right the whole time -- "slice the create_staff_group
body (brace-matched from its fn line to its closing brace, production source
only)". Revision H invented a second, looser boundary instead of citing the
pin. That is revision A's failure in a new place: importing a
plausible-sounding rule rather than re-deriving from the source that owns it.
There it was an S27 conclusion; here a boundary borrowed from a different kind
of check. The #[cfg(test)] boundary is the right instrument for "is this call
site production or test", which is what §0.4 used it for; it is the wrong
instrument for "where does this function end."

The rule: where a pin already defines the artifact, the gate CITES the pin, it
does not redescribe it. A redescription is a second definition, and two
definitions of one artifact are a contradiction waiting for someone to read
the looser one.

Worth noting the failure kind. This was not a gate that passes when it should
fail -- revision H's usual shape -- but a gate with no passing state at all.
It would have surfaced at execution, with an agent forced to choose between
obeying the boundary and obeying the requirement, and whichever it chose would
have been reported as a pass.

Still DRAFT, still unratified. No implementation work has begun.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 18:14:49 +02:00
Levi Neuwirth 5d2db937e9
S16 draft amendment 1 rev H: where a gate must establish a mapping, it cannot count
Independent review of 09d8439 returned one blocking finding. A sweep found a
second of the same family.

1. Gate 12's four-line aggregate could pass with one surface missing. Both
   definitions can exist (2 lines) while check_invariants calls
   check_staff_names_absent_group TWICE and check_group_lists_unowned_staff
   NEVER (2 lines). Four lines total, the stated "fewer than four fails" rule
   reports success, and M6b has no call site to delete.

   Replaced by four independent grep -c checks, each required to be exactly 1
   -- so a count ABOVE 1 now fails too, catching the doubled dispatch
   directly. Plus quoted context, because a count is not a mapping: each
   definition with its enclosing impl GraphIndex<'_> header, proving it is a
   method on the type check_invariants builds; each dispatch with the pub fn
   check_invariants header, proving the call is in the dispatcher M6 edits and
   not in a test or a second dispatcher.

   This is the contract's oldest defect class in new clothes. Revisions A-C
   removed counts that had gone stale; this one was never right -- an
   aggregate can be satisfied by the wrong distribution of the same total.
   Where a gate must establish a mapping, it cannot count. It has to check
   each element on its own, which is the structural sibling of the rule this
   document already carries: where a claim requires completeness, do not
   enumerate, derive.

2. Sweep: gate 8 asserted an absence with no method. "contains the
   empty-members refusal and no member-liveness/TargetMissing path" named no
   command, and a TargetMissing path can be spelled without either literal, so
   any grep would prove only that a chosen string is gone. Method pinned:
   quote create_staff_group's production body in full to the #[cfg(test)]
   boundary and read it, explicitly not a grep -- S27's gate-6a lesson and the
   reason its gate 6c quotes a definition rather than searching for it. M8
   signs exactly this gate, so a vacuous gate 8 leaves M8's deletion
   unobserved.

Both findings are gates that report success without observing what they
claim. One counted instead of pairing; the other asserted an absence with
nothing able to establish it. A structural gate needs a method, and the method
must distinguish the passing case from every failing one -- not merely from
the most obvious failing one.

Still DRAFT, still unratified. No implementation work has begun.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 18:09:08 +02:00
Levi Neuwirth 09d8439c93
S16 draft amendment 1 rev G: pin the structure a mutation deletes
Independent review of 2818ced returned one blocking finding: M6 was
unexecutable against a conforming implementation.

M6 assumed two independently removable arms, but pin 6 and pin 6a specify
behaviour only. A single shared comparison -- one walk emitting a violation
whichever way Staff.group and StaffGroup.members disagree -- satisfies m41,
m41b, the generator test and gate 6, and leaves nothing for M6 to delete one
at a time. Deleting the shared check disables both directions, so M6's
required "one test fails while the sibling passes" observation cannot be
produced at all. M6 was executable only against one implementation style,
which nothing required.

Pin 6b added: the mutation surface is pinned as two GraphIndex methods
following the crate's existing idiom --

  fn check_staff_names_absent_group(&self, out: &mut Vec<InvariantViolation>)
  fn check_group_lists_unowned_staff(&self, out: &mut Vec<InvariantViolation>)

both emitting StaffGroupMembershipAgreement violations, both dispatched from
check_invariants. The names are pinned because gate 12 greps for them and M6
deletes them by name -- the same reason S27 had to pin synthetic_for_fixture
after finding its gate searched for a name offered only as an example.

M6 is now M6a and M6b, each deleting one named call site. Gate 12 added:
structural, proving both definitions and both call sites exist -- four quoted
lines -- BEFORE M6 is attempted, so the surface's absence is a finding rather
than a mid-run discovery. Fewer than four lines is a pin 6b violation.

This is precedent, not invention: check_invariants (invariants.rs:257-:282)
already dispatches 23 check_* methods for 20 invariants, so more than one
method per invariant is the crate's existing shape. A shared helper both
methods call is explicitly permitted -- the deletable call site is what M6
needs, not a duplicated walk.

The class is one S27 hit twice, its M5 and M6 both rewritten after review
found no runnable observation behind them. The tell is identical: a mutation
phrased as an edit to a structure the pins never required. Behaviour pins
constrain outcomes; a mutation deletes code. Where a mutation is the
signature, the structure it deletes must itself be pinned -- otherwise the
contract is satisfiable in a shape that makes its own evidence unobtainable.

Also fixed before commit: gate 12 was first inserted before gate 11, leaving
the sequence 10, 12, 11. Moved, and a stray double blank line collapsed.

Still DRAFT, still unratified. No implementation work has begun.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 17:59:30 +02:00
Levi Neuwirth 2818ced229
S16 draft amendment 1 rev F: a transformation's output needs its input's guarantees
Independent review of abe2c35 returned one blocking finding, and it is both
prior revisions' lessons colliding.

The shrink leg had no observable direction or exactness guarantee. Row 8
requires the S->G fixture to survive shrinking, but:

- the named generator test asserted only on the raw violating_score(...);
- the shrunk score was checked solely by
  every_invariant_shrinks_to_a_small_witness (generators.rs:1003), whose
  !check_invariant(&small, inv).is_empty() is membership in ONE
  GraphInvariant variant -- and both directions of invariant 21 are the same
  variant, so a shrunk witness that flipped to G->S-only passes it. Because it
  calls check_invariant (singular) rather than check_invariants, a shrunk
  witness that gained an unrelated second defect passes too;
- §6 item 2d still said "quote the shrunk witness," which a passing test
  cannot emit.

So a shrunk witness that changed direction, or acquired a second defect while
retaining invariant 21, satisfied every assertion and every gate.

Fixed: the named test now asserts the same three properties TWICE -- on the
raw fixture and again on shrink(&that, StaffGroupMembershipAgreement): exactly
one violation and it is StaffGroupMembershipAgreement, the witness naming the
S->G ids, and G->S asserted satisfied. Gate 6 requires both legs. Item 2d
rewritten to revision E's source-assertion-plus-pass-verdict model. Item 2e
extended to both legs. Row 8's description of the existing shrink tests now
says plainly that they establish only that SOMETHING still fires, and that
direction and exactness after shrinking come solely from the named test's
shrunk leg.

Two lessons collided here. Revision E established that a gate must name
evidence its artifact produces and fixed gate 6 -- stopping one hop short of
item 2d, which is the fix-propagation failure revisions A-D kept recording.
And the underlying gap is revision D's: a requirement, "survives shrinking,"
with nothing able to fail it.

The generalisable rule now recorded: shrink is a TRANSFORMATION, and a
transformation's output needs the same guarantees asserted of its input.
Requiring a fixture to "survive" a transformation establishes only that
something survived. Every property the input was pinned for must be
re-asserted on the output, or the transformation is free to change what the
fixture proves.

Still DRAFT, still unratified. No implementation work has begun.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 17:51:21 +02:00
Levi Neuwirth abe2c359f7
S16 draft amendment 1 rev E: a gate must name evidence its artifact produces
Independent review of cae1d32 returned two blocking findings and one stale
rationale. Both blocking findings are in requirements revision D itself wrote,
and both are revision D's own closing lesson turned back on it.

1. Row 8's new generator test had no name, so nothing consumed it. Gate 6
   named only m41 and m41b; §6 item 2d asks for shrink evidence. Omitting the
   test entirely would still compile, satisfy all four all() loops, and pass
   every named gate.

   Named invariant_21_negative_generator_breaks_staff_to_group_only, with its
   three assertions spelled out: exactly one violation and it is
   StaffGroupMembershipAgreement, the witness naming the S->G ids, and the
   G->S direction asserted satisfied. Added to gate 6 and to new §6 item 2e.

   This is revision D's own lesson unapplied to itself: it closed by
   distinguishing a rule with no consumer from a rule with no observer, then
   wrote a requirement with neither. An unnamed artifact cannot be gated,
   because every gate here names what it checks.

2. Gate 6 demanded runtime evidence the prescribed tests cannot emit. It said
   to quote check_invariants' full return and witness ids, but these are
   assert!-style tests in m40's shape and cargo test prints ok, not local
   values. Obeying it literally would need unpinned --nocapture
   instrumentation added purely to produce a report, or source inference
   presented as observation.

   Evidence model now chosen explicitly: quote the SOURCE assertions plus the
   pass verdict. A passing exact-set assertion IS the observation -- the
   assertion text says what was checked, the verdict says it held. This
   follows S27's gate 6c, which quotes a struct definition rather than
   grepping for it: a quoted source construct is read, not inferred. It also
   adds no code to epiphany-core written solely for a report.

   The requirement was right and the mechanism was borrowed from gates that
   run commands and read stdout. A gate must name evidence the prescribed
   artifact actually produces; otherwise execution improvises, and improvised
   instrumentation is unpinned scope arriving through the report.

3. Gate 4's rationale still said row 11 is "conditional," which revision D
   changed to decided-unused. A fourth site under pin 10a said "carrying it
   conditionally costs nothing" -- found by sweep. Both updated. The subset
   rule itself is unaffected; only its rationale needed the current term.

Still DRAFT, still unratified. No implementation work has begun.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 17:42:22 +02:00
Levi Neuwirth cae1d32794
S16 draft amendment 1 rev D: a requirement no assertion can fail is not a requirement
Independent review of 25473a1 returned two blocking findings. A sweep
escalated one of them into a third. Both reported findings are the same
failure in different clothes: a requirement stated with nothing able to fail
it.

1. Pin 10a still deferred the label decision to execution -- twice reworded,
   never decided. The facts were readable in the .tex source the whole time:
   core_spec.tex:6529-:6648 is ONE requirement box carrying the single label
   req:graph:score-graph-invariants, with exactly 20 \items inside it.
   Invariant 21 is a 21st \item within that box, so pin 6 mints nothing. Pin
   10 rewrites prose plus a Revision History row and version bump, so it mints
   nothing either.

   DECIDED: neither document mints a label; touch row 11 is UNUSED and must
   not be staged; no counter moves. If execution finds otherwise that is a
   finding against this contract, not a keyboard decision. The counter table
   is retained for that case and for the next rung. Row 11 is kept rather than
   deleted because CLAUDE.md names the file as a recurring escapee -- a row
   reading "deliberately unused, and why" survives review; an absent row looks
   like an oversight.

   "Decide and report" reads like rigour and is its opposite: it makes the
   staged set and counter expectations depend on a choice made at the
   keyboard, so the touch table can be wrong in either direction and the
   report will agree with whatever happened.

2. Pin 6a required each fixture to violate its own direction only, and nothing
   could observe that. The prescribed model, m40, asserts only
   check_invariants(&s).iter().any(...) -- any() cannot see a second unrelated
   defect -- and gate 6 checked the target verdict and the opposite direction
   but never the absence of invariants 1-20. So a fixture carrying an
   unrelated second defect satisfied every stated gate and mutation outcome.

   Each m41/m41b must now assert the EXACT violation set: exactly one
   violation, StaffGroupMembershipAgreement, witness naming that direction's
   staff and group ids, opposite direction asserted satisfied. Gate 6 reports
   check_invariants' full return for both.

   Borrowing a test's shape imports its blind spots along with its virtue. m40
   was cited for its dispatch property, which is real and still applies;
   nothing about invariant 20 ever turned on exactness.

3. Sweep: the same blind spot covers touch row 8's generator, and worse.
   negative_generators_are_reasonably_targeted bounds kinds:
   BTreeSet<GraphInvariant> at <= 3, but both directions of invariant 21 are
   the SAME variant -- they collapse to one element, so no existing test can
   observe direction at all; the other three all() loops assert only
   !is_empty(). Row 8 now requires a dedicated permanent test that the
   generator violates S->G and not G->S.

Also fixed: revision D's block was first inserted inside revision C's,
orphaning C's closing paragraphs after it. Reordered, and the cross-revision
pattern paragraph moved to the end and extended.

That paragraph now carries rev D's converse: the fix-every-site rule asks who
READS a corrected rule; rev D asks what OBSERVES each requirement. Findings 2
and 3 were invisible to every sweep that looks for restated text, because
nothing was restated. A rule with no consumer goes stale; a rule with no
observer was never enforced at all.

Still DRAFT, still unratified. No implementation work has begun.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 17:22:31 +02:00
Levi Neuwirth 25473a1bc5
S16 draft amendment 1 rev C: a mutation is a test's signature, not its substitute
Independent review of 0a5b936 returned two blocking findings and one factual
error. The first two are one issue: invariant 21 mandates two directions, and
only one -- unspecified -- had durable evidence.

1. Neither direction had permanent named coverage. Pin 6 asked for "a score
   violating only invariant 21" (singular), gate 6 asked for one score, the
   generator carries one, and M6 observed both directions only while mutated.
   A mutation is reverted, so the restored suite could ship with one branch
   untested.

   Pin 6a added: two permanent, direction-isolated tests --
   m41_check_invariants_dispatches_invariant_21_staff_names_absent_group (S->G)
   and m41b_check_invariants_dispatches_invariant_21_group_lists_unowned_staff
   (G->S) -- each required to SATISFY the direction it does not break. Gate 6
   requires both verdicts. M6 now breaks those exact tests, one each, and
   requires the sibling to still pass; the surviving test passing is what
   proves the arms independent rather than one arm catching everything.

   This contract already stated the rule and did not apply it to itself: pin
   3a says "a mutation demonstrates the hazard once; only a test keeps it
   demonstrated." M6 was carrying both directions on mutation alone, three
   sections below that sentence.

2. "One named direction" delegated a design decision to execution. Either
   choice changes the generated witness and the shrink evidence, so reporting
   it afterward is not specifying it. Pinned to S->G in touch row 8, with the
   reason: smallest corruption of valid_score (drop the staff id from
   group.members, leave staff.group intact), matching every other arm's
   doctrine, and the exact shape pin 2's append failing produces -- which is
   what M2 observes.

   Three fixtures now have three distinct purposes: row 8's generator (S->G,
   survives shrink), pin 6a's two direction-isolated tests, and M6 as their
   signature. None stands in for another.

3. §6's revision-B history said §4 has "twelve entries -- 1-11 plus 4a," a
   false identity. The item numbered 4a. was a scope note with no command and
   no output -- it could not be "a gate result" -- and it collided with §4a,
   the landing-obligation section. Demoted out of the gate numbering into gate
   4's body. §4 now has eleven gates, 1-11, and §4a is unambiguous.

Still DRAFT, still unratified. No implementation work has begun.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 17:15:33 +02:00
Levi Neuwirth 0a5b93688b
S16 draft amendment 1 rev B: a correction propagates one hop and stops
Independent review of 3096c54 returned three blocking findings, all in
revision A's text, and each is a rule revision A had just corrected surviving
one step downstream of where it was fixed.

1. §6 item 2c still said "all three counters and their new values" -- the rule
   pin 10a corrected in the same revision. Third site of one false claim: the
   pin, then touch row 11 (caught by rev A's sweep), then the report item that
   READS the pin. Now points at pin 10a's table and requires naming which
   document minted the label.

2. §6 still demanded "the nine gate results" while §4 carries twelve entries
   (1-11 plus 4a). Revision A removed the identical tally from item 1 for
   mutations and left its neighbour on the next line standing. Count removed,
   §4 named as origin, 11a-e identified as subchecks of one gate rather than
   five separate results.

3. Touch row 8 still required violating_score's fixture to violate "both
   directions" while M6 requires direction-isolated fixtures -- incompatible
   evidence models in one contract. A both-direction generator remains
   reported after either M6 arm is deleted, so it cannot sign that arm's
   absence. Row 8 now specifies one named direction plus shrink survival; pin
   6/M6 own two separate isolated fixtures. violating_score returns one Score
   per variant and could not have carried both regardless.

Found by sweeping and fixed with them: gate 7 and §6 item 4 both said "the
four pin-8 tests." Correct today, but the same construction -- a count
restated away from its origin, and inconsistent with the two tallies just
removed. Pin 8's table named instead.

The pattern across revisions A and B is sharper than any single finding: a
correction propagates one hop and stops. Rev A fixed pin 10a and left touch
row 11; the sweep caught row 11 and stopped before §6's consumer. Rev A
removed item 1's mutation tally and left item 2's gate tally on the next line.
The fix-every-site rule is not satisfied by fixing the site and its obvious
neighbour -- it requires asking who READS the corrected rule.

Noted, not changed: §6's items run 2, 2b, 2c, 2d, 2a because 2a predates the
new items. Cosmetic, and renumbering would break pin 12's and gate 10's
references to item 2b.

Still DRAFT, still unratified. No implementation work has begun.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 16:45:50 +02:00
Levi Neuwirth 3096c54d09
S16 draft amendment 1 rev A: stop importing S27 conclusions unre-derived
Independent review of d06e2f7 returned six findings, five blocking, all in
draft amendment 1's own text. A sweep found a seventh: the same false claim at
a second site.

1. Report item 2d asked execution to decide a static fact the draft could
   read. shrink (generators.rs:932) does NOT match GraphInvariant -- it calls
   check_invariant(score, inv). The unverified claim was made twice, in item
   2d and in touch row 8. Both corrected. Item 2d replaced with the real
   obligation: invariant 21's fixture must survive shrinking (:1025), since
   shrink asserts on entry that its input still violates the target.

2. Pin 10a's "all three counters move if either document mints a label" is
   false. CORE_REQUIREMENT_COUNT is asserted only against core_spec.tex
   (requirement_labels.rs:259); a label in operation_catalog.tex moves the two
   suite counters only. Replaced with a per-document table.

   Sweep finding: touch row 11 carried the same false sentence and was left
   standing while pin 10a was fixed -- the fix-one-site defect, committed
   inside the edit that fixed the other site. Row 11 now points at pin 10a
   rather than restating it.

3. Gate 11 permitted the exact tautology it exists to prevent. "Updated, not
   silenced" does not forbid replacing the literals with
   CURRENT_REDUCTION_ALGORITHM_VERSION -- the tidiest-looking update, after
   which both operands move together and M5a/M5b are vacuous. Rewritten as
   11a-e requiring independent literal 1 values, never the constant, each
   quoted. S27 round 3 caught this substitution and roundtrip.rs:882 forbids
   it by name.

4. Gate 11 omitted roundtrip.rs:947, test 10b's mutation-only Err arm. Left at
   0, M5b aborts on the base comparison before reaching the two-field panic
   that is its required observation -- failing at the wrong assertion while
   observing nothing. Added as 11d, with 11e for the literal-preservation
   comments whose reasoning is what stops the next rung making substitution 3.

5. §6 demanded "the nine mutations (M1-M9)" while M7's split makes ten
   executions. Count removed; §3 is the single origin.

6. Pin 12 said no gate catches a missed bump except the tripwires, written in
   the same amendment that added gate 10, which compares the value against
   HEAD directly. Split: gate 10 guards this bump, 11a-e guard the wiring,
   only the general future case stays undetectable.

Tightening folded in with finding 1: M6's two fixtures must each violate ONE
direction only. A fixture disagreeing in both is still reported after either
arm is deleted, so the mutation appears to fail correctly while signing
nothing. The same trap applies to touch row 8's generator, whose all()-driven
consumers only ask whether 21 is reported.

Findings 1, 2, 3 and 6 share one root cause: an S27 conclusion applied without
re-derivation. S27's "name all three counters," its "no mechanism can detect a
semantics change," and its literal-independence rule are true statements about
S27; two are false or incomplete here and one was dropped where it was needed.
A ratified contract is reusable as a source of questions, not of answers.

Still DRAFT, still unratified. No implementation work has begun.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 16:39:12 +02:00
Levi Neuwirth d06e2f7266
S16 draft amendment 1: fourteen findings from ratification reconnaissance
Fourteen findings, thirteen blocking, against the draft BEFORE its first
ratification round. Nine from the recon pass, five from a second sweep of the
same defect classes. The contract is a DRAFT, so these are edits to an
unratified plan, not amendments to frozen pins.

Root cause, and the one that changes the rung's shape: invariant 21 is a
TWO-crate change. violating_score (epiphany-core/src/generators.rs:498)
matches GraphInvariant exhaustively, so the new variant does not compile
without an arm, and four all()-driven tests (:991, :1004, :1025, :1042) then
require a real generator rather than a stub. The contract had treated the enum
extension as local to invariants.rs. Nothing in its §0 inspection would have
surfaced this -- it appears at compile time, after execution begins.

Touch table gained five rows:
- epiphany-ops/src/lib.rs -- the bump and its Bumps entry. The rung's defining
  act had no pin, no touch row, no gate and no report item; it existed only as
  a note inside pin 0's discharge. Now pin 12, touch row 7, gate 10, item 2b.
- epiphany-core/src/generators.rs -- the root cause above.
- epiphany-testkit/src/roundtrip.rs and epiphany-textproj/src/serialize.rs --
  S27's two tripwires. Test 10b panics by design once the authority moves;
  test 10a asserts the literal 0 and its own doc says it is expected to fail
  when S16 bumps. Both fail gate 1 with no row to fix them in -- the same
  shape as S27's own gminor.rs failure. Gate 11 requires they be updated, not
  silenced: a tripwire accepting both values rebuilds the tautology S27
  existed to remove.
- requirement_labels.rs -- conditional, the escapee CLAUDE.md names by name.
  Pin 10a now forces an explicit decision on whether pin 6 or pin 10 mints a
  label; this rung touches both counted documents, and all three counters move
  if either does.

Gates: 2 and 3 now pin +1.95.0 (CI gates on it; this machine defaults to
1.97.1). Gate 3 formatted two crates of four and would have reported clean
over the two the new rows added. Gate 1 gained the 1577/0/0 baseline, three
delta buckets, and a 0-ignored requirement. Gate 4's "exactly §2" was the
formulation S27's round 17 found unsatisfiable with a conditional row.

Mutations: M1, M2 and M4 accepted "the named test fails" as their whole
signature; each now names the behaviour the mutated build produces -- the
applied spurious mint, the still-empty members, the re-carry misverdict. M3,
M5, M6 and M9 already met the standard. M7 covered two independently guarded
doc blocks while reverting one, so it could pass with the other guard still
weak; split into M7a and M7b, each quoting its own needle's non-match.

Locators: pin 8's four tests were identified by INTERIOR line numbers, a dozen
lines into each body, anchored to nothing searchable -- now named. t6/t7/t9
re-derived to :16158/:16231/:16461, with the trap recorded that reduce.rs has
two t6/t7 families and grepping "fn t6" lands on the wrong one.

New §4a, landing obligation: the bump falsifies live statements in
CLAUDE.md:106 and the handoff's POST-S27 block. Both are explicitly NOT staged
during execution -- staging them would assert the rung had landed while it
awaited acceptance -- and are required as post-acceptance reconciliation the
report must list as outstanding. Pin 11's ledger row is different and is
staged: a ledger records what a rung did; those two state what is true now.

Report item 2d requires execution to determine whether shrink() also matches
GraphInvariant exhaustively. Deliberately not guessed -- guessing about an
exhaustive match is what produced the root-cause finding.

Findings 5-8 are all defects S27 had already found and fixed in its own gate
set; this contract predates those corrections and inherited none of them. The
next contract drafted here should start from S27's §5.

No implementation work has begun. Still DRAFT, still unratified.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 16:26:12 +02:00
Levi Neuwirth d2e43b4204
S16: separate enforcement from detection in the pin-0 supersession
The supersession declared pin 0's "no mechanism to detect a
reduction-semantics change" false because version mismatches are now
rejected. That conflates two different claims, and it contradicted this same
contract's requirement 3 thirty lines below, which says no mechanism can
detect a missed bump. CLAUDE.md, the handoff, and epiphany-ops's own
authority doc all state the correct version.

Only one of the two claims moved:

- Declared-version mismatch -- a base whose recorded
  reduction_algorithm_version differs from the running authority -- is now
  ENFORCED, refused with CanonicalBaseRequiresRebuild on read and write.
- A semantics change is STILL UNDETECTABLE. Nothing compares the semantics
  the code implements against the number it declares, and nothing can.

So S27's enforcement is conditional on the bump discipline, not a substitute
for it. If this rung changes CreateStaffGroup's verdict and the bump is
missed, every base it produces declares 0, matches an authority still reading
0, and passes every check S27 installed -- the enforcement fires correctly on
a number that is itself wrong. That is exactly why pin 0's requirement 3
inverts into a mandatory bump rather than dissolving: S16's bump to 1 is the
human-enforced half of the guarantee, and the only half that applies to
itself.

Changes:
- The falsified-claims table splits the row in two: the accepted-stale-base
  consequence is false now; the no-detection claim is marked STILL TRUE.
- New "Enforcement is not detection" section states the split as a table so
  the two cannot collapse into each other again.
- The discharge marker before pin 0 no longer lists no-detection among the
  falsified claims and warns not to read the discharge as closing that gap.
- Pin 11's retained blockquote had the same defect: it was annotated "every
  claim in this quoted block is now false," but "no mechanism comparing
  either against the semantics it actually implements" is still true -- S27
  compares a declared number against a declared number. Annotation now
  separates what is false from what stands.

Documentation only.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 15:46:53 +02:00
Levi Neuwirth af378d2d0f
Handoff: make the POST-S27 block genuinely the sole source
The top block claimed to be "the only place" the new state is given, then
§1.4, §2.6, §4.3 and §1.5 restated current S27/S16/collision status anyway.
Rather than weaken the claim to match the text, the later sites are reduced to
closure pointers -- duplicated live state is the defect this whole sequence
has been about.

- §1.4 now gets the same treatment as §1.2: the ORIGINAL pre-S27 chain diagram
  is restored as a dated record under a section-level supersession marker, and
  the in-place rewrite is removed. This also covers the rest of §1.4, which was
  already stale in ways nothing had marked -- S27's "still DRAFT, now
  dispatchable" line and the three inherited items it now discharges.
- §2.6 and §4.3's collision notes reduced to "superseded -- see the collision
  row," with a pointer to §2.3, which remains the correct home for what
  actually blocks T1b and is unaffected.
- §4.3 items 7 and 9 reduced to closure pointers.
- §1.5 was a site nothing had touched: it stated S27 as UNBLOCKED and
  dispatchable as current fact. Now marked as an as-of-2026-08-07 snapshot
  with the ledger named authoritative per row.

No new state is stated anywhere below the top block; every later mention is a
supersession or closure marker. Documentation only.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 15:43:09 +02:00
Levi Neuwirth 9153623aa1
Post-S27 docs: scope the supersessions properly in handoff and S16 contract
Follow-up review found the previous reconciliation half-done in two places.
Documentation only; the accepted S27 code is untouched.

spec/HANDOFF_2026-08-07.md -- it declared CLAUDE.md the sole origin for the
green baseline and then stated the number twice anyway, once in its own update
table and once in §3.5. Both replaced by pointers; the figure now exists in
exactly one file. The §1.2 marker also said everything following it was
pre-S27 while two post-S27 notes sat inside that section. The notes are
deleted and their substance folded up into the top block's table rows -- the
permanent acceleration_snapshots warning onto the conformance row, the
"may not degrade to read-only" carry-over onto the errors row -- so §1.2 is
now purely a dated record. The marker is also scoped to §1.2 rather than
"everything after," which would have wrongly claimed §1.4 onward.

spec/CONTRACT_P13S16_PROJECTION.md -- pin 0 still carried live pre-S27
instructions: no authority exists, no mechanism detects a stale base,
ids.rs:288's catalog claim is false, this rung cannot execute, the ledger
stays blocked on P13-S27, and file S27. A status-and-ledger update did not
reach any of them.

- Pin 0 now carries a discharge marker BEFORE the pin, not only after it, so a
  top-down reader meets the correction before the false claims.
- The discharge answers each falsified claim individually in a table, and
  replaces all three numbered requirements. Pin 0's deliberate narrowing --
  that no history audit was done, so the stronger "never detectable" claim
  must not be written -- survives and still binds.
- Requirement 3 inverts rather than disappears: stale bases are now rejected
  and S27 owns those tests, so this rung must not add a second detection path;
  what it must do instead is bump CURRENT_REDUCTION_ALGORITHM_VERSION to 1.
- Pin 11's live "File P13-S27 in the same edit" instruction is struck inline,
  not only in its preamble, and the retained reasoning is properly blockquoted
  with every claim in it marked false.
- §6 report requirement 2a required confirmation that nothing was added
  detecting stale bases -- the opposite of what is now correct. Rewritten to
  require the version bump with its Bumps-list entry, no second detection
  path, and the unchanged operation_catalog.tex rebuild note.
- "The P13-S16 row is marked blocked on P13-S27" corrected; "does NOT move to
  RESOLVED" is retained, since it is still true and is the distinction that
  matters -- unblocked, dispatchable and resolved are three different states.

Line-number citations throughout the S16 contract predate S27's 795-line
bundle.rs change and are NOT re-derived here; that is recorded as part of
ratification rather than silently patched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 15:39:50 +02:00
Levi Neuwirth 8df798d907
Post-S27 doc reconciliation: CLAUDE, handoff, S16 contract, both ledger cells
P13-S27 landed at 4df8e25. Four documents carried live statements that the
landing invalidated, and they had to move together: updating the ledger alone
would have left the active S16 contract contradicting it.

CLAUDE.md
- Track head: P13-S27 LANDED; P13-S16 unblocked, contract still DRAFT.
- The T1b/S27 collision is resolved. T1b is NOT thereby free -- it stays
  blocked on Ruling B blocker (ii), versioned decode. A future
  epiphany-bundle rung re-creates the collision on its own terms.
- Green baseline 1570 -> 1577, and marked as the single origin for the count.
- "One live constraint" rewritten: the blanket no-canonical-base prohibition
  is lifted, replaced by the authority check (accepted when
  reduction_algorithm_version equals CURRENT_REDUCTION_ALGORITHM_VERSION,
  currently 0; CanonicalBaseRequiresRebuild on both read and write paths;
  legacy epoch still refuses outright), plus the bump discipline and the
  synthetic_for_fixture / production_caps split.

spec/HANDOFF_2026-08-07.md -- a dated snapshot, so it keeps its text and gains
a POST-S27 UPDATE block at the top that is the single place the new state is
given. Each invalidated site now points there instead of restating:
§1.2 constraint (dated record), the suspended conformance wiring (restored),
ReductionAuthorityUnavailable (deleted, replaced), §1.4 chain state, §2.6 and
§4.3 collision, §4.3 items 7 and 9. The three 1570 repetitions are replaced by
a pointer to CLAUDE.md -- a figure kept in four places goes stale in three.

spec/CONTRACT_P13S16_PROJECTION.md
- Status: DRAFT, UNBLOCKED 2026-08-09, NOT RATIFIED and therefore NOT
  dispatchable. Pin 0's blocker is discharged; core_spec.tex:11614 is met.
  Original status retained verbatim.
- Pin 11 amended: it mandated a ledger state of "blocked on P13-S27," which is
  now false -- a pin requiring a false ledger state would put the contract in
  contradiction with the ledger it governs. Its instruction to file S27 in the
  same edit is discharged.

spec/PASS13_CANDIDATES.md -- appended to both cells, per the append-only
convention.
- S16: unblocked, with the "additionally needs pin-2a's disposition" sentence
  explicitly superseded (settled from outside S27 by the format rung's pin 8);
  unblocked is not dispatchable; first act is bumping the authority to 1.
- S27: accepted and landed, with the gate figures, and a correction to pin
  10's own wording -- it said S16 becomes "dispatchable," but by this repo's
  definition S16 is unblocked, not dispatchable. Same unblocked/dispatchable
  conflation S27's round 1 committed.

Documentation only: no .rs or .toml touched, so the gates re-run against the
landed tree stand unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ps1szk2mSfgp4Cz21eVH9x
2026-08-09 15:24:21 +02:00