Skip to content

Pin the cause, not just the count - #2777

Merged
gHashTag merged 3 commits into
masterfrom
w699-pin-channel
Aug 29, 2026
Merged

Pin the cause, not just the count#2777
gHashTag merged 3 commits into
masterfrom
w699-pin-channel

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

Refs #2754

The ledger pinned how many tokens each spec discards. It did not pin which recovery took them, so a spec could swap 200 tokens of one defect for 200 of another and the ratchet would stay clean.

"discard_tokens": 208,
"discard_by_channel": { "bdd-block-fallback": 208 }

Three rules, and only the first is about drift

  • the split moving is a failure even when the total does not. 200 tokens lost to a braceless block falling back and 200 lost to a braced body being skipped are different findings.
  • the map must sum to the pinned total. A ledger that disagrees with itself is reported before it is used to judge anything. Two accounts of one quantity are kept deliberately — the 27-token gap in #2776 was found only because a second account existed to disagree with.
  • pinned by total and not by channel counts as unpinned. Half a bound is not a bound, so it lands in the same list for the same reason.

Seen failing on purpose, twice

Moving 5 tokens between two channels at a constant total:

DISCARD WORSENED   : 0
DISCARD IMPROVED   : 0
DISCARD CHANNEL    : 1

The two totals arms stay silent — which is the whole point. And inflating one channel without touching the total fires the self-consistency arm:

~ specs/base/ternary_add.t27 [parse-no-discard] pinned map sums to 215 but pinned total is Some(208)

Three unit tests cover the swap, the self-inconsistency, and the half-bound.

Blessed

86 entries, 30 408 tokens, per-channel sums agreeing with the totals exactly:

bdd-block-fallback   23852
brace-body            4602
top-level-resync      1894
clause-junk             33
stray-brace             27
cargo test --no-fail-fast   2432 passed, 0 failed
suite --ratchet             RATCHET: CLEAN, exit 0
check_seal_coverage.py      exit 0
check_specs_generate.py     exit 0
check_elab_ratchet.py       exit 0

🤖 Generated with Claude Code

W699 rung 7. The ledger pinned how many tokens each spec discards. It did not
pin WHICH recovery took them, so a spec could swap 200 tokens of one defect for
200 of another and the ratchet would stay clean.

`parse-no-discard` entries now carry `discard_by_channel`:

    "discard_tokens": 208,
    "discard_by_channel": { "bdd-block-fallback": 208 }

Three rules, and only the first is about drift:

  * the SPLIT moving is a failure even when the total does not move
  * the map must SUM to the pinned total -- a ledger that disagrees with ITSELF
    is reported before it is used to judge anything. Two accounts of one
    quantity are kept deliberately: the 27-token gap in the channel recording
    was found only because a second account existed to disagree with.
  * pinned by total and not by channel counts as UNPINNED. Half a bound is not
    a bound, and it lands in the same list for the same reason.

Seen failing on purpose, twice. Moving 5 tokens between two channels at a
constant total fires DISCARD CHANNEL while WORSENED and IMPROVED stay silent --
which is the whole point. Inflating one channel without touching the total fires
the self-consistency arm: "pinned map sums to 215 but pinned total is Some(208)".

Blessed: 86 entries, 30 408 tokens, and the per-channel sums agree with the
totals exactly.

    bdd-block-fallback   23852
    brace-body            4602
    top-level-resync      1894
    clause-junk             33
    stray-brace             27

    cargo test --no-fail-fast  2432 passed, 0 failed
    suite --ratchet            RATCHET: CLEAN, exit 0

Refs #2754

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

📓 NotebookLM Notebook linked to this PR

This notebook contains session context, decisions, and artifacts for this work.

@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-08-29 03:23:54 UTC

Summary

Status Count
Total Open PRs 8
PRs with Failing Checks 7
PRs with All Checks Green 1
READY 0
FAILING 7
PENDING 0

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=fcfb279c055c != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

W699 rung 8, and a correction to my own plan.

Last iteration's report named `brace-body` -- 4 602 tokens, 459 runs -- as "a
channel nobody has looked at" and proposed it as the next rung. Reading the
ledger that rung 7 had just filled:

    brace-body WITHOUT bdd-block-fallback:  3 specs,    88 tokens
    brace-body WITH it:                    40 specs, 4 514 tokens

Ninety-eight percent of it is collateral. A braced statement inside a braceless
block that fell back is the SAME event, reached through a second function --
`restore_bdd_fallback` resyncs, the resync meets a `{`, and `skip_brace_body`
consumes it. The split counted one event as two.

    while (i < 3) {          <- the block gives up here, bdd-block-fallback
        var j : usize = 0;   <- and everything inside is brace-body
    }

The channel is now contextual, using the flag rung 6 already had:

    bdd-block-fallback        23852
    brace-body/in-fallback     4345      93% is ONE class
    top-level-resync           1894
    brace-body                  257      the independent class, 10 specs
    clause-junk                   33
    stray-brace                   27

So the work I advertised at 4 602 tokens is 257. Recorded rather than quietly
re-scoped: a plan built on a number that has since been measured properly should
say so, especially when the number was mine.

Re-blessed (channel names changed): 86 entries, 30 408 tokens, sums consistent.

    cargo test --no-fail-fast  2432 passed, 0 failed
    suite --ratchet            RATCHET: CLEAN, exit 0
    check_seal_coverage.py     exit 0
    check_elab_ratchet.py      exit 0

Refs #2754

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-08-29 03:32:36 UTC

Summary

Status Count
Total Open PRs 8
PRs with Failing Checks 7
PRs with All Checks Green 1
READY 0
FAILING 7
PENDING 0

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=ae51527d5b42 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

…ount (167-169)

A channel split can count one event twice: 98% of the class I recommended as the
next rung turned out to be collateral of the class above it, and the work was
257 tokens rather than 4602.

Adding a second dimension to an amnesty means restating every rule that governed
the first, including the boring one that says a bound must exist.

And the derivable field stays: a second account of one quantity is the only thing
that can disagree with the first.

Refs #2754

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

📓 NotebookLM Notebook linked to this PR

This notebook contains session context, decisions, and artifacts for this work.

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

📓 NotebookLM Notebook linked to this PR

This notebook contains session context, decisions, and artifacts for this work.

@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-08-29 03:33:13 UTC

Summary

Status Count
Total Open PRs 8
PRs with Failing Checks 7
PRs with All Checks Green 1
READY 0
FAILING 7
PENDING 0

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=ae51527d5b42 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

@gHashTag
gHashTag merged commit ab0cb37 into master Aug 29, 2026
34 checks passed
@gHashTag
gHashTag deleted the w699-pin-channel branch August 29, 2026 03:43
gHashTag added a commit that referenced this pull request Aug 29, 2026
…ot one

W699 rung 12, plus the regression it caused and the ledger entry that caught it.

A body that OPENS with a call had no earlier clause to take a column from, so
`first_clause_col` was None and the bare-call arm never ran:

    bench ternary_not_performance
        @setEvalBranchQuota(10000);      <- and everything after it
        var result : i32 = 0;

The const/var arm already seeds the column from the statement itself (W904); this
is the same seed.

THE SEED EXPOSED A HOLE NOTHING HAD EVER TESTED. `given (exp, mant) = f(15)` is
an identifier followed by `(`, so the bare-call arm matched a CLAUSE KEYWORD.
Before the seed the arm could not reach a block's first token at all, which is
why the shape had never been reached. Clause keywords are now excluded.

    discarded tokens  23926 -> 23644   (-282)
    specs discarding     76 -> 75
    Zig 214, rustc 214, cc 163, iverilog 373, ALL FOUR 66 -- all held

THE PER-ENTRY RATCHET CAUGHT ITS AUTHOR, ONE DAY OLD. With only the seed, the
corpus total FELL and no acceptance column moved -- a clean win by every
aggregate. The ledger disagreed:

    > phi_split_optimality.t27    discards 214, pinned at 129 (+85)
    > phi_universal_attractor.t27 discards 108, pinned at  73 (+35)

A total that falls can hide two entries that rose. That is what #2777 was for.

AND MY FIRST FIX FOR IT WAS WRONG. I assumed the seed skewed the W905 clause
anchor and stopped writing `first_clause_col`. The total went 23 738 -> 24 046
and the spec was still broken: a plausible cause, disproved in one build. The
real one was the clause keyword.

Also here: docs/DISCARD_WHAT_IS_LEFT.md -- a census of the 964 remaining fallback
events, classified by reading the source line each fired on. 93.5% is
QUANTIFICATION in four notations, which makes #2774 not "a construct in 35 specs"
but nearly everything left. It also corrects this loop's own earlier report,
which called the 38 `for` events a Zig-capture syntax problem: 35 of the 38 are
quantifier SUFFIXES (`... for all Trit`) and belong to #2774.

    parse-conform              25/25, new case load-bearing
    cargo test --no-fail-fast  2432 passed, 0 failed
    suite --ratchet            RATCHET: CLEAN, ledger 167 -> 166
    check_seal_coverage.py     exit 0
    check_elab_ratchet.py      exit 0
    check_specs_generate.py    exit 0

Skill 179-181, including the one about this checkout being shared: this branch
was parked under me mid-iteration by another session and the work was finished
in a private worktree.

Refs #2754, #2774

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
gHashTag added a commit that referenced this pull request Aug 29, 2026
* wip(parser): seed the column for a body that OPENS with a call

W699 rung 12, PARKED UNMERGED. Written and measured, not landed: the repository
owner has forked to continue the parser line, and this touches the same arm.

A bench body beginning with a call --

    bench ternary_not_performance
        @setEvalBranchQuota(10000);
        var result : i32 = 0;

-- had no earlier clause to take a column from, so `first_clause_col` was still
None, the bare-call arm never ran, and the whole block fell back. The const/var
arm already seeds the column from the statement itself when it is the first thing
in the block (W904); this is the same seed. The `c > 1` guard against unindented
blocks is unchanged, and a failed parse un-seeds the column so a later shallower
statement cannot pass a guard on a column the block never established.

Measured in a dirty tree, which is how it was found:

    discarded tokens  23926 -> 23738   (-188)
    specs discarding     76 -> 75

NOT verified beyond that: no corpus run, no conformance case, no re-bless. Whoever
picks this up owes it those three things.

Refs #2754

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* wip(parser): the conformance case for rung 12, reunited with its fix

This case was written with the rung-12 fix and left behind in the working tree
when the fix was parked. On master it is a test for a fix that is not there:
`parse-conform` exits 1 with

    case     a_body_may_open_with_a_call
    expected Full with 1 decl(s), 0 discarded
    actual   Full with 1 decl(s), 14 discarded

A case and the change it covers are one unit. Splitting them leaves a red gate
behind and a fix nobody can tell is load-bearing.

Refs #2754

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(parser): a body may open with a call -- and a clause keyword is not one

W699 rung 12, plus the regression it caused and the ledger entry that caught it.

A body that OPENS with a call had no earlier clause to take a column from, so
`first_clause_col` was None and the bare-call arm never ran:

    bench ternary_not_performance
        @setEvalBranchQuota(10000);      <- and everything after it
        var result : i32 = 0;

The const/var arm already seeds the column from the statement itself (W904); this
is the same seed.

THE SEED EXPOSED A HOLE NOTHING HAD EVER TESTED. `given (exp, mant) = f(15)` is
an identifier followed by `(`, so the bare-call arm matched a CLAUSE KEYWORD.
Before the seed the arm could not reach a block's first token at all, which is
why the shape had never been reached. Clause keywords are now excluded.

    discarded tokens  23926 -> 23644   (-282)
    specs discarding     76 -> 75
    Zig 214, rustc 214, cc 163, iverilog 373, ALL FOUR 66 -- all held

THE PER-ENTRY RATCHET CAUGHT ITS AUTHOR, ONE DAY OLD. With only the seed, the
corpus total FELL and no acceptance column moved -- a clean win by every
aggregate. The ledger disagreed:

    > phi_split_optimality.t27    discards 214, pinned at 129 (+85)
    > phi_universal_attractor.t27 discards 108, pinned at  73 (+35)

A total that falls can hide two entries that rose. That is what #2777 was for.

AND MY FIRST FIX FOR IT WAS WRONG. I assumed the seed skewed the W905 clause
anchor and stopped writing `first_clause_col`. The total went 23 738 -> 24 046
and the spec was still broken: a plausible cause, disproved in one build. The
real one was the clause keyword.

Also here: docs/DISCARD_WHAT_IS_LEFT.md -- a census of the 964 remaining fallback
events, classified by reading the source line each fired on. 93.5% is
QUANTIFICATION in four notations, which makes #2774 not "a construct in 35 specs"
but nearly everything left. It also corrects this loop's own earlier report,
which called the 38 `for` events a Zig-capture syntax problem: 35 of the 38 are
quantifier SUFFIXES (`... for all Trit`) and belong to #2774.

    parse-conform              25/25, new case load-bearing
    cargo test --no-fail-fast  2432 passed, 0 failed
    suite --ratchet            RATCHET: CLEAN, ledger 167 -> 166
    check_seal_coverage.py     exit 0
    check_elab_ratchet.py      exit 0
    check_specs_generate.py    exit 0

Skill 179-181, including the one about this checkout being shared: this branch
was parked under me mid-iteration by another session and the work was finished
in a private worktree.

Refs #2754, #2774

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore(ledger): re-bless after merging master

The W700 pin (`max_gate_failures`) came in from master; the discard numbers are
this branch's. Their schema, my measurements.

Refs #2754

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant