Skip to content

test: the last figures come off the run, and a typed one is refused - #452

Merged
firejune merged 2 commits into
mainfrom
test/the-summary-counts-its-controls
Sep 7, 2026
Merged

test: the last figures come off the run, and a typed one is refused#452
firejune merged 2 commits into
mainfrom
test/the-summary-counts-its-controls

Conversation

@firejune

@firejune firejune commented Sep 7, 2026

Copy link
Copy Markdown
Owner

Closes #451.

bun run typecheck clean, bun run lint clean, bun run selftest 562 PASS / 0 FAIL / 0 SKIP / 0 HOLE, exit 0 (559 on main).

The ruling

A suite's figure counts every case it prints, its own positive control included. It is in CLAUDE.md beside the floor rule, and it was needed because the tree answered the question both ways — four suites counted their control and two did not, so no single derivation reproduced the summary and #439 correctly left the last four figures standing rather than editing prose to match a script.

The reason for choosing inclusion is the only one available: the tally can only count printed lines. A convention that subtracts something the run printed cannot be derived at all and needs a hand-kept exception table beside it.

The four literals

clause was now
static-rig 4 n('static-rig')5
draw-order 6 n('draw-order')7
path / slider / per-skin 45 n('path-slider')47
positive controls 6 deleted

The fourth is deleted rather than derived, and that is the sharper half of the card. "Positive control" is a role, not a token on the line. Measured on the finished run: 17 case names begin CONTROL_, 29 contain "control" case-insensitively, and two of those 29 — M16_rim_vertex_pinned_to_the_control_bone, M19_idle_keys_the_mesh_control_bone — are mutants carrying the word because a control bone is a rig concept. In the other direction T04_GREYSCALE_ALPHA_STILL_PASSES and PS25 are genuine positive controls whose names say nothing at all.

⇒ Six, seventeen and twenty-nine were each a reading of it and none of them was the number. A derived-looking figure here would have been worse than the hand-written one, because it would have carried the derivation's credibility over an undefined quantity. It is replaced by a pointer with no count in it, which cannot go stale: "Each suite's own positive control is printed by name in its section above."

Every one of the 44 clauses was cross-checked against PASS/FAIL lines counted between section headers, and the six that already included their control were verified rather than assumed. None was off.

Two suites the summary was silent about

  • runMeshOutlineSuite ran ten controls and had no clause at all — not a wrong number, a missing one. It has one now, and the figure is on the tally.
  • runAtlasReaderSuite was the only corpus-dependent suite that returned before printing a section header, so its absence was invisible where the other five print a header plus a SKIP. It now says so out loud.

🔒 And printing the header only fixed the symptom. tallyFaults had no clause that could have caught it, because every clause it carried was about what a section said and this suite opened none — so a suite that reports it did not run and opened no section is now a fault by name (TY09).

The scanner (TY10, TY11)

#439 rejected this check as unbuildable while four literals legitimately stood. With none left, it is buildable, and the trap it had to get past is that the summary is full of literal numbers that are not figures: 2 of them a spine-core round trip, 26.25 degrees, [0, 360), 0 / 255, 99.5%, and the one that breaks a naive rule, the slider clause's verbatim `v + 360 === 360`.

So the rule is structural rather than lexical, taken from the summary's own grammar: it is a +-joined list, every clause opens with + (the head with green — ), and the figure is whatever fills that opening. A run-produced figure arrives through a hole between two literal chunks; a typed one sits inside a chunk. Prose numbers are never in that position — they sit mid-sentence, after a word.

On the finished file: 548 literal runs, 48 clause openings, 46 filled by a run-produced value, 0 written into the text, and 39 n('…') calls all sitting at an opening. No exception table.

🔒 Two-sided, for the reason TY01 and CUR01 are: TY10 also requires that openings were found at all, that some are value-filled, and that every n('key') sits at one — so a summary rewritten into an unrecognised shape goes red rather than quiet. TY11 runs the same scanner over a miniature carrying all three ambiguities at once, and its load-bearing clause is the negative one: the same text with the figure interpolated must fault in no way, without which a scanner that refused every clause opening would pass.

Mutants, planted in the real file and restored

mutant what fired
atlas-reader returns before its header the suite "atlas-reader" did not run and opened no section at all, so nothing this run printed says it was skipped — exit 2
a figure typed at an opening with the correct value 1 figure(s) are written into the text rather than counted: …+ 5 static-rig controls…
a derived figure moved off its opening …39 n('…') call(s) all sitting at one EXCEPT draw-order; none is written into the text
the new mesh-outline clause hand-written 1 figure(s) are written into the text rather than counted: …+ 10 mesh-outline controls…
the start anchor reworded the summary's own source was not found between … — the scan has nothing to read and cannot report a clean one
one throwaway case appended, summary untouched printed + 6 static-rig controls, 0 FAIL, exit 0

Negative controls for each refusal are listed in the suite: a suite that did not run but opened a section and said SKIP (held live by six such suites on a corpus-absent run), every prose number in the real summary, a comment quoting a stale figure, and all 39 real n() calls including the one nested inside a ${}.

🐛 A file that scans itself finds itself first

The first working TY10 reported four written figures and every one of them was this suite's own test data: SUMMARY_START, spelled whole, is the earliest match for itself, so the scan read the block comment above — including TY11's deliberately planted miniature — instead of the summary.

⭐ This is a new shape of a check that agrees with itself, and the distinguishing feature is that the check's subject matter was its own source. The anchor is now spelled in two pieces with the reason commented in place, and the fifth mutant exists to prove the failure is red rather than quiet.

The blind spot, and the half of it that closed

Two suite figures were hand-written outside the summary, where the scanner cannot see them, and the commander verified that this is not theoretical: BONEDIST_CONTROLS = 49 produced a green run, 0 FAIL, exit 0, with the summary printing 9 stage-3 bonedist controls over a suite that printed 4.

BONEDIST_CONTROLS is gone — it was literally n('bonedist') one hop out of the text, and the clause now asks the tally at the point of use. Two structural facts make that safe rather than lucky: the clause sits in an else-branch only reached when all three corpus suites ran, and tallyFaults' exit 2 runs above the line that defines n, so the other way countOf throws has already exited.

The mutant for it was run with the corpus parked on purpose, so the clause carrying the lie was never printed at all — and TY10 refused it anyway, because it reads the source rather than the output. That is the difference between closed and closed-on-machines-that-happen-to-have-a-corpus.

DIFF_IDENTITY_CONTROLS = 6 stays, and stays deliberately: it is half a decomposition (6 identity + 9 measure = the 15 the suite prints, verified this run), so n('diff') would give 15 and a split the tally cannot produce would be the same defect wearing a derivation. The blind spot is narrowed to one named constant, not closed, and it is filed rather than papered over.

🔒 A scanner for "a numeric constant whose only reader is the summary region" was rejected on measurement, not taste: it is buildable, and it goes red on DIFF_IDENTITY_CONTROLS on its first run. The only way to keep it green is an exception table naming that constant.

🐛 A dead branch, and the identical-looking one that is alive

Putting n('bonedist') at the call site exposed that the arm it went into was unreachable:

diffBad === null || checkBad === null || boneDistBad === null
  ? '⚠️ …'
  : `…` + (boneDistBad === null ? '' : `, + ${n('bonedist')} …`)

The outer condition already excludes boneDistBad === null, so the inner empty arm could never be taken. Removed with the reason in place, under #374's judgment that a branch nothing reaches is not a control. The rendered summary is byte-identical in both directions over the whole 44 KB paragraph, which is what proves it was dead.

⚠️ And the rule this suggests is the wrong rule. selftest.ts:24399 has the same silhouette — X === null ? '' : … nested inside a ternary — and it is live. Its inner condition is on a different variable with a different predicate: runMeshRungSuite keys on examples/6-arcs/export/…json, runMeshCheckSuite on examples/6-arcs/images and bench/reference/6-arcs/frames.json. Parking only the images reaches the empty arm: mesh-rung ran, mesh-check skipped, the summary printed + 1 rung-6 mesh render with no fidelity clause after it, run green.

⇒ The rule is not "delete X === null ? '' : … inside a branch". It is whether the enclosing condition already decides the inner one — and the two cases are indistinguishable by shape. The live one was proven by construction rather than argued from the paths, which is the standard check is held to.

Also measured and reported rather than assumed: inside the corpus else-branch the diff, diff measure and check clauses carry no conditional at all — there was never an arm to be dead. Only bonedist had the shape. The three .filter(Boolean) ternaries in the ⚠️ arm are all live; a corpus-absent run prints all three names.

Rejected, with the measurement that killed each

  • Refuse every numeric literal plus an exception table — the table is the defect.
  • "Every tallied suite must be named via n()" — the rule that would have caught mesh-outline having no clause. Needs a hand-kept exemption list: rig-spec, diff, bonedist, motion-parse, gallery-example, registered-cut and the three SUITES-loop keys all legitimately have none, and no derivation of that set was found. Left undone and reported.
  • Scan the rendered string instead of the source — impossible: + 6 diff identity controls (derived) and + 4 static-rig controls (typed) are the same characters once rendered. The distinction exists only in the source.
  • /\+\s*\d/ over the source's string literals — measured before the edits: 5 hits, 3 true, 2 false. The clause-opening rule scores 3 hits, 0 false on the same text.
  • Skipping ${} bodies wholesale — measured: loses the mesh-rung clause's nested ', + ' + n('mesh-check') and reports it misplaced. Replaced with a stack that descends.
  • lastIndexOf for the start anchor — a third occurrence would silently change which region is read; the split literal fails loudly instead.

firejune and others added 2 commits September 7, 2026 11:45
The tree answered this both ways — four suites counted their own positive
control in the figure beside them and two did not — so no single derivation
reproduced the summary and the last four figures in it had to stay literals.

The rule is chosen for one reason: the tally can only count printed lines, so
a convention that subtracts something the run printed cannot be derived at all
and needs a hand-kept exception table beside it.

The run's total count of positive controls is deleted rather than derived.
"Positive control" is a role and not a token on the line: M16 and M19 carry the
word only because a control bone is a rig concept, while T04 and PS25 are
positive controls whose names say nothing. Six, seventeen and twenty-nine were
each a reading of it and none of them was the number.

Refs #451.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The three figures the ruling settles go on the tally: static-rig 4 -> 5,
draw-order 6 -> 7, path/slider 45 -> 47. The fourth is deleted rather than
derived, because "positive control" is a role and not a token on the line —
17 case names begin CONTROL_, 29 contain the word, two of those 29 are mutants
carrying it because a control bone is a rig concept, and T04 and PS25 are
genuine controls whose names say nothing. It is replaced by a pointer with no
count in it.

Two suites the summary was silent about: runMeshOutlineSuite ran ten controls
with no clause at all and has one now, and runAtlasReaderSuite returned before
printing a header so its absence was invisible. TY09 makes the second one a
fault by name rather than a fixed symptom.

TY10 and TY11 refuse a figure typed into the summary instead of counted. The
rule is structural rather than lexical, because the summary legitimately holds
many numbers that are not figures: it is a +-joined list, and a run-produced
figure arrives through a hole between two literal chunks while a typed one sits
inside one. 548 literal runs, 48 clause openings, 46 value-filled, 0 written,
39 n() calls all at an opening, and no exception table.

BONEDIST_CONTROLS is gone; it was n('bonedist') one hop outside the text, where
raising it to 9 produced a green run printing a figure its suite contradicts.
DIFF_IDENTITY_CONTROLS stays: 6 is half a decomposition of the 15 its suite
prints, and a split the tally cannot produce would be the same defect wearing a
derivation.

Removing the dead arm around the bonedist clause leaves the rendered summary
byte-identical in both directions. The identical-looking arm at 24399 is live,
proven by parking one directory rather than argued from the paths.

Closes #451.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@firejune
firejune enabled auto-merge (squash) September 7, 2026 03:41
@firejune
firejune merged commit 9f5920a into main Sep 7, 2026
1 check passed
@firejune
firejune deleted the test/the-summary-counts-its-controls branch September 7, 2026 03:43
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.

four summary figures disagree with the run, and three of them are one convention question asked three times

1 participant