Repository navigation
tests_referenced: a tools/*.py that declares a self-test and is registered nowhere is now drift (fixes #1901) - #1910
bong-water-water-bong wants to merge 1 commit into
Conversation
…tered nowhere is now drift engine#1901. `#1824`'s sweep asks whether every `tests/*.sh` is referenced by something that can run it, and it is specific to `tests/*.sh` -- so the same defect one directory over was invisible. A tool that ships `--self-test` is claiming it can be verified without its real inputs; if nothing runs that flag the claim is unbacked, and the arm is maintained in the same commits as the logic while never executing. **Narrow on purpose.** A blanket "every `tools/*.py` is referenced" sweep is 16 of 60 today, most of them legitimately CLI-only, which is too noisy to be a ratchet. The rule is "declares a self-test flag AND no registration names it", and it found **five**, not the two the issue measured: batched_repeat --selftest logprob_agree --selftest mtp_head_ref --selftest template_bom --self-test whisper_encoder_baseline --self-test All five self-tests pass on this box, so all five are now `add_python_test` rows (the helper #1891 added), and the checker fails if any future one loses its registration. **The flag spelling is per tool, and that is the point.** Three take `--selftest`, two `--self-test`; a registration with the wrong one exits non-zero and fails loudly in ctest rather than silently running nothing. That split is the same one #1886's review flagged and #1901 describes, so the rows carry a comment naming which spelling each tool accepts. **Two false positives found and closed while writing the rule** -- both would have made it noise on the first run: * `tools/spec_decode_acceptance.py` **is** run: `CMakeLists.txt:857` registers `tests/spec_decode_acceptance_test.py`, which imports the tool. A registration that names the *test* counts, so `tests/*.py` is part of the registration set. * and an import names the **stem** (`import spec_decode_acceptance`), not the file, so the match accepts either the basename or the stem. Verified: `tests_referenced_check.py --check` was **rc 1** with five names before, **rc 0** after ("all 73 test script(s) are referenced, 1 deliberately not a row: anchor_rerun.sh"); `--self-test` **0 failures**, with three new arms (an unregistered self-test is drift and is NAMED, a registered one is clean, and a tool a registered `tests/*.py` imports is run -- the last two exist so the first cannot pass by "tools/ exists"); each of the five registered commands run by hand → rc 0; and `ci_targets_check --check` rc 0, since these rows name no build target.
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT at 475ba3e: CHANGES
Checked at 475ba3e. --self-test passes and --check at this head gives rc 0.
Ground truth on current main (extracted tree): the tools/**/*.py that name a --self-test/--selftest flag, minus those a runner invokes (CMakeLists.txt, cmake/*.cmake, .github/workflows/*.yml) and minus those exercised through their own registered tests/*_test.* (gsm8k_eval, mtp_depth_pool, q4nx_diff, seal_manifest, split_ceiling). That leaves five whose self-test nothing runs: batched_repeat, logprob_agree, mtp_head_ref, spec_decode_acceptance (all spelled --selftest) and whisper_encoder_baseline (--self-test). Each of the four #1901 PRs, run against that tree:
| PR | flags on main |
registers |
|---|---|---|
| #1908 | whisper_encoder_baseline only |
whisper_encoder_baseline |
| #1910 | batched_repeat, logprob_agree, mtp_head_ref, whisper_encoder_baseline, + template_bom |
the same |
| #1911 | all five | all five; each --selftest/--self-test passes when run directly |
| #1912 | whisper_encoder_baseline only |
whisper_encoder_baseline |
All four conflict-or-overlap on Fixes #1901 (#1908, #1910 and #1911 conflict pairwise; #1912 adds a second checker), so one should land.
Two gaps against that ground truth: it misses spec_decode_acceptance (--selftest, run by nothing), and it flags and registers template_bom, which ci.yml:87 already runs (python3 tools/template_bom.py --self-test). That gives a second row for a test CI already executes, because the predicate does not read .github/workflows/. #1911 covers all five, with no duplicate. I'd close this in its favour.
VERDICT at
|
bong-water-water-bong
left a comment
There was a problem hiding this comment.
Consolidation: three PRs fix #1901, and #1911 is the one to merge — close this.
All three ask the same question (a tools/*.py that ships --self-test and is named by no runner), and #1911 states the predicate most precisely: it counts a tool as unregistered when no RUNNER names it — "CMakeLists/cmake/workflows — a citation in another tool's source is not a runner: that is the 5-vs-2 difference" — which is the distinction that changes the answer from two tools to five. It also measures the five (58-277 ms, device-free, so they are rows rather than allow-list excuses) and registers them through add_python_test(), reporting that its own first version used the raw ${Python3_EXECUTABLE} form and was caught by the ordering guard on tools/mtp_head_ref.py — the one of the five without an exec bit.
So: merge #1911, close this and the sibling. Worth folding across if the bodies are squashed: the "5-vs-2" sentence (the predicate), because that is the part a future reader will need when the count changes.
|
A cluster note on the four #1901 PRs — I reviewed all four and only one should land.
All four pass their own My recommendation, and the reason: land one implementation inside Between the three in-file versions I have no strong preference: #1910's |
|
Coordination: four PRs And a coverage gap all four share, with numbers from the tree: A matcher that only knows |
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT: READY at 475ba3e — correct rule, but it is one of three variants in this file; land whichever fills the rule best and close the others (see the cluster note above).
|
VERDICT: READY at Cluster: #1908, #1910, #1911, #1912 are all None is an ancestor of another. The three that touch What I would doKeep one of the in-place extensions and close the other two with pointers. The rule being added — a Of the three, #1911 carries the clearest statement of the defect ("the #1824 sweep is specific to #1912 stays defensible only if the rule is genuinely different in kind rather than in directory — in which case say why, because that is the whole argument for a second tool. |
Correction to my verdict, measured: this is the closest of the three — it needs exactly one registration addedI recommended the sibling on the strength of the bodies; I then checked
And one thing to fix in the detector, which matters more than the counts: if the rule looks for |
|
VERDICT: READY at Two things it gets right that mine did not:
One thing to take from my #1916, because it makes this sweep pass on a disabled registration. The fix is four lines in def uncommented(text):
return "\n".join(l for l in text.split("\n") if not l.lstrip().startswith("#"))
...
for path, text in scan_files(root):
text = uncommented(text)Applied to my tree it keeps the 73 script(s) + 17 tool(s) sweep green, and the mutation then names both commented-out tools. It also strengthens the Everything else here is right: the narrow rule (declaration, not blanket — 16 of 60 is noise, as the docstring says), the parsing-based detection, and counting a ctest row / workflow step / other test as all satisfying it. |
|
Closing: main already has this, and its version is better than mine. Another lane's #1901 fix merged while this was in review, and the So every tool my rule found is registered on main —
The one thing worth keeping from this attempt is a latent false positive in the merged rule: its I am not opening a third PR on that file for it — the finding is on #1901 for whoever owns the next change there. |
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT: LGTM on the substance — but #1910 and #1912 are two checkers for one question, and this is the better one to land. Two code nits. Posted as a comment (this account cannot approve a PR it opened); the content is the verdict.
Why this is the one to land: it extends the ratchet that already exists (tools/ci/tests_referenced_check.py, with its ALLOW file and its self-test apparatus) instead of adding a second, parallel checker. #1912 adds tools/ci/selftest_registration_check.py — a new file sweeping the same question with its own haystack and its own self-test. Both open, both answering "a tool that declares --self-test must be run by something". That is the duplicate-fix pattern this board keeps paying for, and the resolution is cheap because the work overlaps almost completely: land this one, and drop #1912 (or fold its two good ideas — the flag-spelling comparison, and not sweeping /tmp-style shared state — into here). I have reviewed both; this is the one with the allowlist, the measured arms, and the existing self-test to build on.
What is good here, specifically:
- Five orphans registered, and the spelling split called out — "three take
--selftestand two--self-test, which is the split engine#1901 exists to make visible: a registration using the wrong one exits non-zero and fails loudly here rather than silently running nothing." That is a real class of silent no-op, and it is the kind of thing only a person who ran the five by hand would know. - The arms are measurements, not guesses. "Measured while writing this: the narrower rule reported it as unrun, which is the false positive that would have made the ratchet noise" — the
spec_decode_acceptancecase, where a registered test imports the tool. Accepting an importing test as a runner, and pinning it as its own arm, is exactly right. - The three-arm pattern (unregistered = drift, registered = clean, imported-by-a-registered-test = clean) means the first arm cannot pass merely because
tools/exists — which is the way this kind of ratchet usually rots.
Two nits, both real:
tools_with_selftest()matches the flag anywhere in the file, including a comment or docstring:if any(flag in text for flag in SELF_TEST_FLAGS). A tool whose help text says "run with--self-test" but which does not implement it becomes permanently unregistered-and-drift, and the only escape is theALLOWfile with a reason that is not true. #1912 has the right parsing for this —add_argument\(\s*["']--self-test["']— and since both spellings exist here, the equivalent is one regex overadd_argument(accepting either string. Worth taking from #1912 even if that PR is dropped.registered_tools()'sstem in textis a substring test over whole files, sotools/fa_ratio.pycounts as registered if the text containsfa_ratioanywhere — including infa_ratio_v2.py's registration, a comment, or a doc mention. Cheap tightening: require the stem to appear inside anadd_python_test(/add_test(call, or at least asstem.py, and keep the import form as a second, explicit rule (^\s*import <stem>in a registeredtests/*.py).
Not for this PR, but the same question one level up: nothing here compares the flag a registration passes to the flag a tool declares — so add_python_test(x tools/x.py --self-test) against a tool that only knows --selftest is "registered" by this check, and would fail loudly at run time only if the row actually runs (the arm you added does, so this is fine in practice; it is #1912's stated goal and worth folding in if you want the ratchet airtight).
Duplication note for the owner: if #1912 lands first, this PR's tools_with_selftest/registered_tools become dead code next to a second checker, and the board ends up with two ratchets that can disagree about "unrun". One of them should be closed with the reason recorded, not left open.
Fixes #1901.
#1824's sweep asks whether everytests/*.shis referenced by something that can run it, and it is specific totests/*.sh— so the samedefect one directory over was invisible. A tool that ships
--self-testis claiming it can be verified without its real inputs; if nothingruns that flag, the claim is unbacked, and the arm is maintained in the same commits as the logic while never executing.
Narrow on purpose — and it found five, not two
A blanket "every
tools/*.pyis referenced" sweep is 16 of 60 today, most of them legitimately CLI-only, which is too noisy to be aratchet (the issue says the same). The rule is declares a self-test flag and no registration names it:
All five self-tests pass on this box, so all five are now
add_python_testrows (the helper #1891 added), and the checker fails if a future oneloses its registration.
The flag spelling is per tool, and that is part of the finding: three take
--selftest, two--self-test. A registration with the wrong oneexits non-zero and fails loudly in ctest rather than silently running nothing — which is the good failure — but the rows carry a comment naming
which spelling each tool accepts, because the split is the same one #1886's review flagged.
Two false positives found and closed while writing the rule
Both would have made the ratchet noise on its first run, and both were caught by checking the tools it accused:
tools/spec_decode_acceptance.pyis run —CMakeLists.txt:857registerstests/spec_decode_acceptance_test.py, which imports the tool.A registration that names the test counts, so
tests/*.pyis part of the registration set.import spec_decode_acceptance), so the match accepts either the basename or the stem.Verified
tools/ci/tests_referenced_check.py --check--self-testtools/ci/ci_targets_check.py --checkThe three new arms are: an unregistered self-test is drift and is NAMED; a registered one is clean; and a tool a registered
tests/*.pyimports is run. The last two exist so the first cannot pass just because
tools/exists.Escape hatch
A tool whose self-test genuinely cannot be a ctest row goes in
tools/ci/unreferenced_tests.txtwith its reason, the same list and the same rulethe
tests/*.shsweep uses — so there is one place to look for "why is this not a test".