Skip to content

tests_referenced: cover scripts/*.sh self-tests, where one arm had no registration at all (#2129) - #2238

Merged
bong-water-water-bong merged 1 commit into
mainfrom
pkg/scripts-selftests
Nov 12, 2026
Merged

bong-water-water-bong merged 1 commit into
mainfrom
pkg/scripts-selftests

Conversation

@bong-water-water-bong

@bong-water-water-bong bong-water-water-bong commented Nov 12, 2026 •

Copy link
Copy Markdown
Collaborator

A self-test that no runner ran, in the one directory the coverage tool did not read.

The finding

scripts/pkg-proof.sh          --self-test   -> passes on its own; NO ctest row, no workflow step
scripts/ci-runner-health.sh   --self-test   -> registered (2 mentions)
scripts/npu-window11.sh       --self-test   -> registered (2 mentions)

tools/ci/tests_referenced_check.py covers tests/*.sh, tests/*_test.py and tools/**/*.py. Self-tests in scripts/ were outside its corpus, so one of three was dead code that every gate called green.

pkg-proof.sh --self-test exercises the row/summary accounting on stubs — it is the thing that tells a reader whether a packaging run proved anything — and it needs no container, no device and no build. There was simply no row.

This is the #1824/#2018/#2088 shape again: coverage that is a set, and a directory missing from the corpus. The third time today a check was green because it was not looking.

Two changes, the second one is the point

  • The corpus includes scripts/*.sh, and the count walks the same two directories, so the summary line cannot claim more than the corpus covers. 34 → 38 self-tests.
  • cmake/tests-pkg-proof.cmake registers the arm that was missing — a family file, because the glob at CMakeLists.txt's end picks it up and 25 open PRs are editing that file. ci_targets_check.py --where pkg_proof_self → cmake/tests-pkg-proof.cmake:23.

Verified in both directions on the real tree

with the row      -> all 85 test script(s) are referenced ...; 38 tool/script self-test(s) and 44 python test(s) are registered   rc 0
without the row   -> scripts/pkg-proof.sh declares a self-test and no runner names it -- ... the arm is dead code               rc 1

Two arms in the tool's own --self-test pin the new corpus. My first version of that arm failed (rc 2, wanted 1) — and it failed for an instructive reason: with an empty tests/ directory the tool answers 2 "cannot tell" before it ever reaches the scripts/ file, so the fixture now carries a clean tests/ corpus. A test for a new corpus has to satisfy the old one first.

Where the corpus stops, and why that boundary was measured

os/ also contains the string --self-test — twice — and it is not in the corpus, deliberately:

os/mini/release-check.sh     has a real --self-test, and is registered (5 mentions)                 -> safe either way
os/v3/puppy/vm-check.sh      contains "1bit-release-check --self-test 2>&1 | tail -1"              -> a GUEST command it runs,
                                                                                                      not its own self-test

A corpus that matched the string across os/ would demand a ctest row for vm-check.sh, which has no self-test to run — a false red on a legitimate file. So the boundary is: directories where the string has only ever meant "this file has a self-test". scripts/ was such a directory and one of its three was unregistered; os/ is not, and the day a real self-test lands there the extension comes with a positive test (the file's own argument parsing), not a mention.

That is also why the check is a string test rather than something cleverer: three files matched in scripts/, all three real, and the first false positive I found was the reason to stop at a directory boundary instead of widening until it broke.

…e and one dead arm (engine#2129)

`tools/ci/tests_referenced_check.py` covers `tests/*.sh`, `tests/*_test.py` and `tools/**/*.py` -- self-tests in `scripts/`
were outside its corpus. So this was invisible:

    scripts/pkg-proof.sh                --self-test   -> passes on its own; no ctest row, no workflow step
    scripts/ci-runner-health.sh         --self-test   -> registered (2 mentions)
    scripts/npu-window11.sh             --self-test   -> registered (2 mentions)

One of three was dead code that every gate called green, which is the class this tool exists for and the third time today a
check was green because it was not looking. `pkg-proof.sh --self-test` exercises the row/summary accounting on stubs (it is
what tells a reader whether a packaging run proved anything), and it needs no container, no device and no build -- there was
simply no row.

Two changes, and the second is the one that matters:

  * the corpus now includes `scripts/*.sh`, counted by the same two-directory walk as the tool self-tests, so the summary
    line cannot claim more than the corpus covers (34 -> 38 self-tests, the three scripts plus one more tool);
  * `cmake/tests-pkg-proof.cmake` registers the arm that was missing. A family file rather than a line in CMakeLists.txt,
    because the glob at its end picks it up and 25 open PRs are editing that file.

Verified both directions on the real tree:
  with the row      -> "all 85 test script(s) are referenced ...; 38 tool/script self-test(s) ...", rc 0
  without the row   -> "scripts/pkg-proof.sh declares a self-test and no runner names it -- ... the arm is dead code", rc 1

Two arms in the tool's own self-test pin the new corpus, and the fixture carries a clean `tests/` corpus deliberately: with an
empty one the tool answers 2 "cannot tell" before it ever reaches the scripts/ file, which is how my first version of the arm
failed (rc 2, wanted 1).
@github-actions

Copy link
Copy Markdown

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

🎫 Ticket compliance analysis 🔶

2018 - Partially compliant

Compliant requirements:

  • The corpus now includes scripts/*.sh which covers the missing directory
  • The specific case of scripts/pkg-proof.sh --self-test is now registered

Non-compliant requirements:

  • The existing six unregistered tests are not addressed in this PR

Requires further human verification:

  • Verification that the six existing unregistered tests are either registered or added to the allow-list with reasons

2129 - Partially compliant

Compliant requirements:

  • The submodule is correctly pinned to 7a1f2b81ce17
  • The engine does not build or reference mtmd
  • The engine reads jinja files from the correct pin

Non-compliant requirements:

  • The new check tools/ci/submodule_pin_check.py is not included in this PR

Requires further human verification:

  • Verification that the submodule state is correct and no leading + or - exists in git submodule status
⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Missing scripts/* coverage

The tool now covers scripts/*.sh for self-tests, but the existing six unregistered tests from the original issue are not addressed in this PR.

def unregistered_selftest_tools(root):
    """tools/**/*.py and scripts/*.sh that declare a self-test and that no RUNNER names (engine#1901, engine#2129).

    `scripts/*.sh` was outside this corpus until a self-test there was found with no row at all: `scripts/pkg-proof.sh
    --self-test` passes on its own and no ctest row or workflow step ran it, so the arm was dead code that every gate
    called green. A self-test is a claim about a script, and the claim needs a runner whichever directory the script is in.
    """
    tools = root / "tools"
    scripts = root / "scripts"
    cand = []
    if tools.is_dir():
        cand += [p for p in tools.rglob("*.py")]
    if scripts.is_dir():
        cand += [p for p in scripts.glob("*.sh")]
    if not cand:
        return []
    runner_text = []
Incomplete self-test handling

The function _selftest_tools now includes scripts/*.sh but does not distinguish between helper files and actual test files, which could lead to false positives.

def _selftest_tools(root):
    """Every file the corpus above covers that declares a self-test -- counted with the same two directories."""
    out = []
    for sub, pat in (("tools", "**/*.py"), ("scripts", "*.sh")):
        d = root / sub
        if d.is_dir():
            out += [p for p in d.glob(pat) if SELFTEST.search(p.read_text(errors="replace"))]
    return out

@bong-water-water-bong bong-water-water-bong left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VERDICT at ecdd624: READY

The self-test rule now covers scripts/*.sh, which is the last file kind it was blind to — "tools/**/*.py and scripts/*.sh that declare a self-test and that no RUNNER names". The rule started at tests/*.sh (#1800/#1835), reached tools/**/*.py (#1901), and a scripts/ entry that ships a --self-test was the same hole one directory over.

And it registers the case it found: add_test(NAME pkg_proof_self COMMAND scripts/pkg-proof.sh --self-test) — so the rule's first discovery is wired rather than allow-listed. That ordering matters: a checker that lands with its own finding exempted teaches the next reader that the list is where discoveries go to rest.

The generalisation is worth naming because it is the third time today: "a thing that claims it can be verified, and nothing verifies it" is a defect regardless of whether the thing is a test, a tool or a script.

@bong-water-water-bong

Copy link
Copy Markdown
Collaborator Author

VERDICT: READY at ecdd624 — and the shape is right: it fixes the instance and the blindness that hid it.

The finding is the "green because nothing ran" class, precisely located

scripts/pkg-proof.sh        --self-test  -> passes on its own; NO ctest row, no workflow step
scripts/ci-runner-health.sh --self-test  -> registered (2 mentions)
scripts/npu-wind…

"A self-test that no runner ran, in the one directory the coverage tool did not read" — the second clause is what makes this a defect worth a PR rather than a chore. tests_referenced_check.py was the check I verified on main earlier tonight (all 83 test script(s) are referenced … 35 tool self-test(s)), and it was reporting exhaustively about two directories while a third went unread. A checker whose own scope is narrower than the thing it certifies is the recurring shape on this board, and it is worse here because the output reads like a complete statement.

Both halves are in the diff

cmake/tests-pkg-proof.cmake        | 23 +++++  (register the arm that had no row)
tools/ci/tests_referenced_check.py | 39 +++++, 6 ---  (read scripts/*.sh self-tests)

Register the instance, widen the instrument — exactly right, and in that order: registering alone would have left the next scripts/*.sh --self-test invisible again.

Two asks

  1. say the sweep is complete — the checker now reads tests/, tools/ and scripts/. If cmake/, bench/ or npu/ hold anything with a --self-test, name them as read-and-clean or as deliberately out of scope. Otherwise this PR will be repeated for the next directory, and each repetition looks like progress;
  2. confirm the widened checker is red before the registration — the two halves have to be independent: with only the checker change, pkg-proof.sh must be reported unregistered; with only the registration, the checker must not be needed. One line each (before: FAIL scripts/pkg-proof.sh, after: ok) is the proof that neither half alone is doing the work.

@bong-water-water-bong bong-water-water-bong left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VERDICT: READY at ecdd624

A self-test that nothing ran, in the one directory the coverage tool did not read — and the fix closes the directory, not the instance.

The finding, verified: scripts/ holds exactly three scripts that declare a self-test, and before this PR two were named by a runner (ci-runner-health.sh, npu-window11.sh) while
scripts/pkg-proof.sh was named by nothing:

$ grep -l self-test scripts/*.sh            -> ci-runner-health.sh  npu-window11.sh  pkg-proof.sh
$ for f in …; grep -rl "$f" CMakeLists.txt cmake/*.cmake .github/workflows/*.yml
  ci-runner-health.sh  1 runner file
  npu-window11.sh      1 runner file
  pkg-proof.sh         1 runner file      <- this one is the new row

Ran the checker at this head: tests_referenced: all 85 test script(s) are referenced (1 deliberately not a row: anchor_rerun.sh); 38 tool self-test(s)… — rc 0.

The fix is the right shape: scripts joins the corpus with its own glob (("scripts", "*.sh")), so the next self-test added there is covered automatically rather than the tool gaining a
pkg-proof exception. That is the difference between fixing the instance and closing the directory, and it is why this is worth more than the one add_test(NAME pkg_proof_self …) it carries.

And a check I ran on the refusal path, because a coverage tool that cannot tell "nothing to check" from "clean" is the failure mode this session has hit four times: a root with a scripts/ but no
tests/ gets

tests_referenced: cannot tell: no tests/ directory under <root>

— a refusal, not a pass. So the new directory coverage did not quietly turn a broken invocation into a green one.

One note: the corpus now spans tests/*.sh, tests/*_test.py, tools/**/*.py and scripts/*.sh — four globs with four different conventions (*_test.py versus *.sh). Worth a line in the
docstring saying that is deliberate (each directory's own convention), because the next person will assume the tool missed a pattern rather than mirroring a directory.

@bong-water-water-bong
bong-water-water-bong merged commit 5d2b62e into main Nov 12, 2026
10 checks passed
@bong-water-water-bong
bong-water-water-bong deleted the pkg/scripts-selftests branch November 12, 2026 02:06
bong-water-water-bong pushed a commit that referenced this pull request Nov 12, 2026
Answers the CHANGES at 5a3653b and af44615, and it is the gate this session has been
about all day: a self-test that no runner names is dead code.

    $ python3 tools/ci/tests_referenced_check.py --check --root .
    tests_referenced: tools/ci/conflict_triage.py declares a self-test and no runner names
    it -- add a ctest row ...

The irony is mine rather than the reviewer's: #2238 (which I reviewed) exists because
`scripts/pkg-proof.sh --self-test` had no runner, and I then shipped a tool whose
`--self-test` had none.

One row beside CMakeLists.txt:376, alongside the other `tools/ci` self-tests:

    add_python_test(conflict_triage_self ${CMAKE_SOURCE_DIR}/tools/ci/conflict_triage.py --self-test)

Verified: `tests_referenced_check.py --check` -> rc 0 ("41 tool self-test(s) and ...
all referenced"); fresh configure rc 0; `ctest -R conflict_triage` -> 1 row, passed;
`ci_targets_check.py --check` -> 9 baselined, none new; `copyright.py --check` rc 0.

The tool itself is unchanged, so the real-merge table stands: 202 paths,
content=73 add/add=129.
bong-water-water-bong added a commit that referenced this pull request Nov 12, 2026
…m the index not the file body (#2278)

* tools/ci: conflict_triage classifies a merge's conflicts by kind, from the index not the file body

Slice of engine#2138 (the AMD-rebase merge, lead pi-hrx-compat): the tool, not the merge.

The issue's own table names the reason a file-by-file walk is the wrong instrument:

    ggml/src/ggml-hrx/kernel-corpus | 41 paths, mostly add/delete or rename with no markers | 30

A conflict with no markers is invisible to every text-based tool: `grep '^<<<<<<<'` reports
103 files on that merge while git reports 149 paths (engine#1945's triage). So the categories
have to come from `git merge-tree --write-tree`, which reports them without a checkout, and
they decide the work:

    content   markers to resolve, one judgement per hunk        -> a person reads both sides
    add/add   both sides added the path                         -> often --ours wholesale
    mod/del   one side deleted, the other changed it            -> intent, not text
    rename    a rename on one side, an edit on the other        -> follow the lineage first
    unmapped  git named it in no message and it has no markers  -> reported, never guessed

Run against the real merge (fork, `7a1f2b81c` vs AMD's `9bf587131`, read-only):

    conflict_triage: 202 conflicted path(s): content=73 add/add=129

which is exactly git's own 73 + 129 -- and it is what a text search cannot produce, because
`add/add` on the `ggml-hrx` tree is a whole-tree add against a base that has none of it.

That run found a defect in the first version and it is pinned by an arm: the classifier
suffix-matched the path list instead of reading git's message, so 5 of 202 paths whose message
did name them fell to `unmapped`. `message_path()` now takes the path from git's own wording
(both the `Merge conflict in <path>` and the `<path> deleted in ...` shapes, spaces included),
and the counts match git's to the path.

--self-test: 13 arms, ok. --json for a machine-readable table.

Refs engine#2138, engine#1945.

* tools/ci: conflict_triage refuses a ref it cannot resolve, and says so with exit 2

Found by A/B on the tool itself, before a reviewer could: a typo'd ref printed
"no conflicts" and exited **0**.

`git merge-tree --write-tree` returns **1** both for "conflicts found" and for
`<ref> - not something we can merge`, so the return code cannot tell them apart and the
tool took the clean path. That is the unreadable-is-not-zero defect inside the tool that
exists to make a merge legible.

Two fixes:

- `must_resolve()` runs `git rev-parse --verify --quiet <ref>^{commit}` on HEAD, theirs
  and --base before asking git to merge them, and refuses with exit 2 when one does not
  resolve;
- a "not something we can merge" message on the conflict path is an error rather than a
  conflict-free answer, as a second line of defence.

And `die()` now exits **2** for a usage or git error, because `raise SystemExit("text")`
exits **1** -- this tool's "conflicts found" code, so a bad ref would have been
indistinguishable from a merge that needs work.

Exit codes are now measured, not asserted: 2 for "I could not answer" (bad ref, bad base),
1 for "conflicts" (202 paths on the real merge), 0 for "none". Fourteen self-test arms,
including one that measures `die()`'s code in a child process.

* ci: give conflict_triage's self-test a runner

Answers the CHANGES at 5a3653b and af44615, and it is the gate this session has been
about all day: a self-test that no runner names is dead code.

    $ python3 tools/ci/tests_referenced_check.py --check --root .
    tests_referenced: tools/ci/conflict_triage.py declares a self-test and no runner names
    it -- add a ctest row ...

The irony is mine rather than the reviewer's: #2238 (which I reviewed) exists because
`scripts/pkg-proof.sh --self-test` had no runner, and I then shipped a tool whose
`--self-test` had none.

One row beside CMakeLists.txt:376, alongside the other `tools/ci` self-tests:

    add_python_test(conflict_triage_self ${CMAKE_SOURCE_DIR}/tools/ci/conflict_triage.py --self-test)

Verified: `tests_referenced_check.py --check` -> rc 0 ("41 tool self-test(s) and ...
all referenced"); fresh configure rc 0; `ctest -R conflict_triage` -> 1 row, passed;
`ci_targets_check.py --check` -> 9 baselined, none new; `copyright.py --check` rc 0.

The tool itself is unchanged, so the real-merge table stands: 202 paths,
content=73 add/add=129.

---------

Co-authored-by: bong-water-water-bong <bong@water>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant