Skip to content

tri gates mutate: the cache key must cover the instrument (Refs #2161) - #2630

Merged
gHashTag merged 1 commit into
masterfrom
fix/cache-key-covers-the-instrument
Aug 23, 2026
Merged

tri gates mutate: the cache key must cover the instrument (Refs #2161)#2630
gHashTag merged 1 commit into
masterfrom
fix/cache-key-covers-the-instrument

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

Gave the boundary operator the verdict filter that makes invert kill 72 of 78. It appeared to do nothing: 26/77 before, 26/77 after. Two runs, one number, an edit that looked inert.

The mutation cache keys on the gate's bytes and its control's bytes. Changing how sites are selected changes neither, so a rebuilt binary served 24 rows measured by the version before the change. --fresh gave 3/5, and only then was the filter's effect visible.

The key now includes sha256(current_exe()). Verified in three states:

state cached rows
same binary twice 2
rebuild the tool 0 — every row re-measured
same binary again 2

A cache that cannot see its own instrument change is the instrument lying about itself — R2 one level down — and the failure mode is the worst kind. Not a wrong number: an unchanged one, which reads as "your change had no effect" and invites a conclusion about the subject.

And the filter itself was wrong

The same measurement showed it. Sites went 77 → 5, and among the 72 removed:

gate before after
check_vector_data 6/6 0/0
check_seal_coverage 3/3 0/0
check_catalog_integrity 1/1 0/0

Those were killed mutants — proof the comparisons reach a verdict. A filter that drops them is wrong. Reverted.

It cannot be repaired by widening either: the missed sites append to a list that a later statement turns into a verdict. Verdict-reachability is a dataflow property, and widening a line-local pattern until the number looks agreeable is the move R2 forbids — the one tri damage's 429 already demonstrated.

So the 34% is not a defect. A boundary survivor means "moving this comparison did not change the verdict", which for a loop bound is correct. The kills identify the verdict-bearing half, after the fact, which is the only way it can be known.

The negative result is the deliverable. 194 tests pass. §106 and §107.

Refs #2161

Gave the boundary operator the verdict filter that makes `invert` kill
72 of 78. It appeared to do NOTHING: 26/77 before, 26/77 after. Two
runs, one number, an edit that looked inert.

The mutation cache keys on the gate's bytes and its control's bytes.
Changing how SITES ARE SELECTED changes neither, so a rebuilt binary
served 24 rows measured by the version before the change. `--fresh`
gave 3/5, and only then was the filter's effect visible.

The key now includes sha256(current_exe()). Verified in three states:
same binary twice caches 2 rows; a rebuild caches 0 and re-measures
every row; the same binary again caches 2.

A cache that cannot see its own instrument change is the instrument
lying about itself -- R2 one level down -- and the failure mode is the
worst kind. Not a wrong number: an UNCHANGED one, which reads as "your
change had no effect" and invites a conclusion about the subject.

AND THE FILTER ITSELF WAS WRONG, which the same measurement showed.
Sites went 77 -> 5, and among the 72 removed:

  check_vector_data        6/6 -> 0/0
  check_seal_coverage      3/3 -> 0/0
  check_catalog_integrity  1/1 -> 0/0

Those were KILLED mutants. Moving those comparisons demonstrably made
the control fail, which is proof they reach a verdict, so a filter that
drops them is wrong. Reverted.

It cannot be repaired by widening either: the missed sites append to a
list that a later statement turns into a verdict, several statements
away. Verdict-reachability is a dataflow property; a line-local pattern
cannot decide it, and widening one until the number looks agreeable is
the move R2 forbids and `tri damage`'s 429 already demonstrated.

So the 34% is not a defect. A boundary survivor means "moving this
comparison did not change the verdict", which for a loop bound is
correct. The kills are what identify the verdict-bearing half, after
the fact, which is the only way it can be known.

Refs #2161
@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-08-23 23:28:00 UTC

Summary

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

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=e6333575ec10 != 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).

@github-actions

Copy link
Copy Markdown
Contributor

📓 NotebookLM Notebook linked to this PR

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

gHashTag pushed a commit that referenced this pull request Aug 23, 2026
`fn f(error: Err)`, `fn update(key: K, fn: anytype)` and `union(input)` --
`error`, `fn` and `union` are keywords and the natural names for those things.
zig_ident already covered const decls, enum decls, struct fields, locals and
function names; parameters were the sixth site and expression names the
seventh.

Expression position needs a different rule than binding position: zig_ident
also quotes primitives, which is right for a binding and wrong in an
expression, where `@as(u8, x)` names u8 ordinarily and `@as(@"u8", x)` would
break a correct call. zig_expr_name quotes keywords only, segment by segment
across dots so `mod.union` becomes `mod.@"union"`, and leaves @-builtins
alone. The unused-parameter discard moved to the same spelling or it would
name something that no longer exists.

Valid specs 131 -> 132, specs behind a wall 134 -> 117, 0 regressed, gate
holds at 111. Errors 970 -> 1079: seventeen walls fell, and 7 files went from
1 error to many -- vsa/vsa_core 1 -> 52, base/types 1 -> 35. All of it was
already there.

Closes #2630
@gHashTag

Copy link
Copy Markdown
Owner Author

Correction: commit 7b23784 ("fix(emit): quote Zig keywords in parameter and expression names") ends with Closes #2630 and that is a mistake — I wrote the number before the issue was created and it landed as #2631.

That commit does not address this issue and must not close it. It touches zig_ident call sites in the Zig emitter only; nothing in it goes near the tri gate cache key.

Already pushed, so the message is not being rewritten. Flagging it here so the reference is not acted on at merge.

@gHashTag
gHashTag merged commit 7a5489e into master Aug 23, 2026
36 of 37 checks passed
@gHashTag
gHashTag deleted the fix/cache-key-covers-the-instrument branch August 23, 2026 23:43
gHashTag added a commit that referenced this pull request Aug 24, 2026
#2630 established that the boundary column's denominator holds two
populations -- comparisons that decide a verdict, and loop bounds and
display cutoffs that cannot -- and that no line-local filter separates
them, because a kill is the only proof of verdict-reachability and the
filter removed proven kills.

That leaves the column unreadable rather than wrong. `SURVIVED at
boundary lines 45, 91, 214, 223, 226, 409` gives a reader nothing to
act on.

Two changes, neither touching the measurement.

Print the source beside the line number, for this operator only:

  91   `if len(out) > 6:`      a display cutoff
  214  `while len(v) < N:`     a loop bound
  226  `while j < len(src):`   a scan bound
  223  `if b < 0:`             the only one worth reading

Five of six classify themselves at a glance. The reader does the
separation the tool cannot, in seconds rather than by opening the file.

And say what the denominator is, in the summary, only when this
operator ran -- so killed/total is not read as a rate.

The rule: when a metric mixes populations you cannot separate, do not
report a ratio; report the members. A rate over a mixed denominator
invites exactly the conclusion this command exists to prevent, and
invites it most from whoever computed it.

The killed count keeps its meaning: a LOWER BOUND, established after
the fact, on how many comparisons reach a verdict. Smaller than a
percentage, and true.

194 tests pass.

Refs #2161
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