Skip to content

loop: the differential tool counted unmeasured files as agreement - #2170

Open
gHashTag wants to merge 1 commit into
masterfrom
w699-measure-honesty
Open

loop: the differential tool counted unmeasured files as agreement#2170
gHashTag wants to merge 1 commit into
masterfrom
w699-measure-honesty

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

Closes #2166

The defect, in one table

Same binaries, same 150-file slice, two versions of the same tool [measured]:

tool what it printed
five categories 150 unchanged, 0 field-loss, 0 unknown — total agreement
six categories 59 unchanged, 91 not-evaluated (both-error), coverage 39.3 %

Nothing about the compilers changed between those two lines. The first is the
shape that had been quoted in pull requests.

unchanged was carrying two statements at once — "both binaries parsed the file
and the field sets are identical" and "neither binary parsed the file" — and both
incremented the same counter. No reviewer and no threshold could separate them.
Over the 634-spec library the split was 330 measured against 286 unmeasured: a
52 % base reported as 100 %.

The 39.3 % figure is for that slice, not for the corpus; the slice is the
alphabetically first 150 files and is unusually damaged.

What changes

  • Six mutually exclusive categories, and the partition is asserted at
    runtime
    . Claiming exclusivity in a docstring is not a check.
  • Every not-evaluated row carries a reason code: both-error,
    base-timeout, candidate-timeout, environment-failure,
    excluded-source-loss, or a named other. "No verdict" for six reasons is six
    different facts, and only some of them are about the compiler. An uncoded
    not-evaluated is a hard error, exit 2.
  • No PASS while any unknown remains, whatever the other counts say.
  • Coverage printed on every run, and required in the same sentence as any "no
    regressions" claim. A caveat in a neighbouring paragraph does not travel with the
    number — readers quote numbers, not paragraphs.
  • --exclude-status holds out unrecoverable-source-loss files under their own
    code, and refuses to run if the list selects nothing — a silently empty
    exclusion yields a report claiming files were held out when none were.

Full corpus, one completed run, one threshold [measured]

1089 files, uniform 12 s, /tmp/t27c.m2162base/tmp/t27c.m2162fix:

category count
unchanged / ok 524
unchanged / fail 343
regressions (ok → fail) 0
strict-improvement 1 (specs/tri/collections/array.t27)
not-evaluated / both-timeout 195
not-evaluated / candidate-timeout 26

Coverage 868/1089 = 79.7 %. The zero above is a statement about those 868
files and about parse verdicts and field sets only. It says nothing about generated
code, type inference, diagnostics or timing.

Earlier 25 s runs are not aggregated with this one. A run at 25 s and a run at
12 s do not produce comparable not-evaluated sets, and joining them manufactures
a difference.

The 26 moved files are the threshold, not a slowdown [measured]

ok → timeout in one direction and 0 back looks like a slowed candidate, so it was
timed rather than argued: three runs each way per file.

value
median candidate/base ratio 1.010
range 0.985 – 1.026
the files' own runtime 10.8 – 11.7 s against a 12 s wall

A 1–3 % jitter is enough to carry a file taking 11.5 s across a 12 s boundary. The
one-directionality is machine load during a 13-minute run, not a regression. This
is R14 predicting the pattern and then being confirmed on an independent run.

Disclosed overlap

cost.py, diffbin.py, damage*.py, triage.py and loop-tools-tracked.sh also
appear in the branches behind #2159 and #2161. They are duplicated here on
purpose: a measurement fix must not sit in a deferred branch while its output is
being quoted in review. Whichever lands first, the other needs a rebase, and the
diffbin.py in this PR supersedes both.

Also here

  • R15unchanged may never mean "we could not compare".
  • R16 — a silent gate is fixed by a configuration test, not by vigilance.
  • corpus-parse, corpus-status, diffmodes, loop-rules registered in
    loop-tools-tracked.sh, which fails on an untracked tool — the exact state that
    already destroyed two of these scripts and every number they had produced.

Not claimed

Coverage did not improve. It was 52 % before and it is 52 % now on that
library; what changed is that the number is visible. Coverage rises only by
repairing files or excluding them with a status — never by recategorising them.

`tri diffbin` reported five categories, and the first one carried two different
statements at once: "both binaries parsed and the field sets are identical", and
"neither binary parsed the file". Both incremented the same counter.

Same binaries, same 150-file slice, two versions of the same tool [measured]:

  five categories:  150 unchanged, 0 field-loss, 0 unknown      -- total agreement
  six categories:    59 unchanged, 91 not-evaluated (both-error) -- coverage 39.3%

Nothing about the compilers changed between those two lines. The first line is the
shape that had been quoted in pull requests. Over the 634-spec library the split
was 330 measured against 286 unmeasured: a 52 % base printed as 100 %.

What changes:
  * six mutually exclusive categories, with the partition ASSERTED at runtime
    rather than claimed in a docstring
  * every not-evaluated row carries a reason code -- both-error, base-timeout,
    candidate-timeout, environment-failure, excluded-source-loss, or a named
    other. "No verdict" for six reasons is six facts, and only some of them are
    about the compiler. An uncoded not-evaluated is a hard error, exit 2.
  * no PASS while any unknown remains, whatever the other counts say
  * coverage printed on every run, and required in the same sentence as any "no
    regressions" claim. A caveat in a neighbouring paragraph does not travel with
    the number; readers quote numbers, not paragraphs.
  * --exclude-status takes a corpus-status JSON and holds out
    unrecoverable-source-loss files under their own code. It REFUSES to run if the
    list selects nothing, because a silently empty exclusion produces a report
    claiming files were held out when none were.

Full corpus, single completed run, uniform 12 s threshold, 1089 files [measured]:
524 unchanged/ok, 343 unchanged/fail, 0 regressions, 1 strict-improvement, 221
not-evaluated (195 both-timeout, 26 candidate-timeout). Coverage 868/1089 = 79.7 %.

The 26 ok->timeout files are the threshold, not a slowdown. Timed directly, three
runs each way: median candidate/base ratio 1.010, min 0.985, max 1.026, on files
taking 10.8-11.7 s against a 12 s wall [measured]. A 1-3 % jitter moves them
across it.

Also: R15 and R16 added to docs/loop/LOOP-RULES.md and resealed; corpus-parse,
corpus-status, diffmodes and loop-rules registered in loop-tools-tracked.sh, which
fails on an untracked tool -- the exact state that already destroyed two of these
scripts and every number they had produced.

Overlap disclosed: cost.py, diffbin.py, damage*.py, triage.py and
loop-tools-tracked.sh also appear in the branches behind #2159 and #2161. They are
included here because a measurement fix must not sit in a deferred branch while
its output is being quoted. Whichever lands first, the other needs a rebase; the
diffbin.py here supersedes both.

Not claimed: that coverage improved. It did not. Coverage rises only by repairing
files or excluding them with a status -- never by recategorising them.
@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-14 21:47:50 UTC

Summary

Status Count
Total Open PRs 26
PRs with Failing Checks 11
PRs with All Checks Green 15
READY 7
FAILING 11
PENDING 0

Seal Status

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

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.

diffbin: 'unchanged' counted 286 unmeasured files as agreement; 52% coverage was reported as 100%

1 participant