test(gate): run scripts/dl-router/tests β 989 tests no gate had ever run - #306
Merged
Conversation
`scripts/dl-router/tests` was absent from `scripts/run-tests.sh`'s target list since the suite was written: 989 tests, zero of them gated. Same declarations-vs-instances shape as #298 (166 opencode tests) and #276 (913 guard-core tests) β one missing line in a target list. Adding it surfaced two SANDBOX-ONLY portability defects, both of the kind that are structurally invisible on a dev host: * test_setup_script.py's write_pgrep() wrote a stub with `#!/usr/bin/env bash`. The nix build sandbox has no /usr/bin/env; every NixOS dev host does. Now goes through the helper #298 landed. * test_cli.py / test_server_wiring.py hard-coded port 8799 for their "sidecar is DOWN/unreachable" assertions. That is a claim about the whole machine, not the test β an orphaned python3 (pid 2994086, started Aug 1 13:40, ppid 1) was listening on it and the test reached a REAL dl-router, failing with `sidecar HTTP 409: not_owned_tab`. Ports now come from a `closed_port` fixture. Shared instead of re-derived (RULES.md "One rule, one place"): * `scripts/collector/opencode/tests/_mockbin.py` -> `scripts/testlib/ mockbin.py`, importable by any suite. * #298's runtime-shebang scan was scoped to ONE directory, which is exactly why it could not see the dl-router defect. The scanner moved to `scripts/testlib/shebang_scan.py` and the guard is now REPO-WIDE (`scripts/tests/test_runtime_shebangs.py`) with a pinned allowlist that fails BOTH ways β an unpinned offender and a pin that matches nothing. MIN_TESTS 2850 -> 5600. The old floor had drifted below HALF the real total, so a whole 989-test suite could have vanished underneath it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ZacxDev
added a commit
that referenced
this pull request
Aug 3, 2026
β¦ed shebang The repo-wide runtime-shebang scanner (#306, scripts/tests/ test_runtime_shebangs.py) failed this file IN THE SANDBOX ONLY. The dev-host run was green because I ran this ONE file, and the scanner lives in another β a per-file run structurally cannot see a repo-wide guard. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ZacxDev
added a commit
that referenced
this pull request
Aug 3, 2026
β¦ver run (#309) `scripts/run-node-tests.sh` hard-coded its collection to one directory: FILES=(scripts/browser-bridge/tests/*.test.mjs) so every other `.test.mjs` suite in the repo was invisible to the only check that runs node. Measured at origin/main (13bc8bd): * scripts/dl-router/tests 508 tests, never gated * scripts/collector/browser-ext/tests 21 tests, never gated 529 tests, ungated since each suite was written. The gate reported `RESULT: PASS` with a 468-test total the whole time β a hard-coded list cannot know what it is not looking at. Fourth instance of the same shape (#276: 913 pytest tests behind one list entry, #298: 166, #306: 989). Adding two lines would leave the NEXT suite ungated identically, so collection is now DISCOVERY (bash globstar over scripts/**/*.test.mjs) plus a TWO-WAY PIN: * a discovered directory absent from SUITES -> FATAL (forces an accounting entry with a measured floor, rather than being swept in under the total) * a pinned suite discovery does not find -> FATAL (the suite vanished) Discovery alone would reintroduce the silent-collapse hole the old hard-coded glob at least did not have: an emptied dl-router/tests would just collect fewer files and still pass over a global floor. Each suite also runs in its OWN `node --test` invocation with its own TAP summary and its own floor. A single global floor of 970 is fully satisfied by browser-bridge (468) + dl-router (508) with browser-ext's 21 tests entirely gone; per-suite floors make that loud. A PORTABILITY DEFECT found while building this, worth recording because the first draft shipped it and the harness hid it: discovery used `find -printf '%h\n' 2>/dev/null`. `-printf` is a GNU extension, and THREE different `find`s are reachable from this repo β busybox under bash (~/.nix-profile/bin/find, rejects it), bfs 4.1.1 under the interactive zsh, GNU findutils in the nix sandbox. Paired with `2>/dev/null` the rejection became an EMPTY discovery list with no error β a false "no suites found". Collection is now a bash builtin (globstar), which depends on no external binary and behaves identically in every tier; `test_runner_does_not_use_find_printf` pins it. MEASURED, both tiers: nix build .#checks.x86_64-linux.nodetests 997 tests / 997 pass / 0 fail bash scripts/run-node-tests.sh (dev host) 997 tests / 997 pass / 0 fail 468 (baseline, browser-bridge) + 508 + 21 = 997. No unexplained delta. scripts/tests/test_run_node_tests_suites.py guards the pin, with its regression and invariant guards labelled honestly in the module docstring, mutation proofs that the guard goes red naming the offending directory, and a positive control on both parsers (the reassuring answer here is an empty set, which an unwired harness also produces). The 529 newly-gated tests are NOT regression coverage for this change β they are pre-existing tests whose value is that they now run at all. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
ZacxDev
added a commit
that referenced
this pull request
Aug 3, 2026
β¦dition (#310) * fix(gate): run-tests.sh could not check its own most important precondition Two measured holes, plus an honest correction to a third. 1. REQUIRED_TOOLS could not express the precondition that matters most. It is a list of BINARIES checked with `command -v`. pytest is not a binary this runner calls β it is a MODULE (`python -m pytest`) β so the one guard whose entire job is "the thing that runs the tests is present" was structurally unable to check pytest. It also asserted `python3` while the runner actually invokes `python`. MEASURED on the dev host with every REQUIRED_TOOLS binary present but no pytest importable: all 17 targets printed run-tests: ERROR β could not parse pytest's summary for <dir>. and the run ended `TOTAL collected=0 β¦ RESULT: FAIL`, exit 1. CORRECTION, stated because it changes the severity: the gate did NOT go green, and the briefed "reports per-target PASS with collected=0" does not exist on this revision β GUARD 4 (unparseable summary) and GUARD 3 (the collected floor) both fire. The defect is DIAGNOSTIC: seventeen copies of a message blaming pytest's OUTPUT FORMAT for a missing dependency, pointing at the wrong subsystem. That is the #276 shape β a real finding that reads like an environment fault. Now one named FATAL, exit 2, before any suite runs. 2. `declare -a RESULTS` / `declare -a SKIP_LINES` leave the arrays DECLARED BUT UNSET. Under `set -u` the first `${#arr[@]}` on a still-empty array aborts the command with "unbound variable" (measured, bash 5.3.15). With zero skips this printed a raw scripts/run-tests.sh: line 479: SKIP_LINES: unbound variable where GUARD 2's skip list belonged, and the unpinned-skip loop below it never executed. No `set -e`, so the script continued and the skip-TOTAL accounting still fired β the damage was confined to the DIAGNOSTIC path, at exactly the moment someone is reading why the gate is red. Fixed with `NAME=()`. 3. "printed RESULT: FAIL and exited 0" did NOT reproduce. Measured: exit 1. The structure forbids it β `RESULT: FAIL` is printed only when `fail != 0` and the next statement is `exit "$fail"`, whose only non-zero value is 1. The likely origin is reading the status through a pipeline (`| tail`), which yields the last command's status rather than the runner's. Pinned end-to-end anyway by `test_a_failing_run_never_exits_zero`, which forces a red run and asserts the two can never disagree β and pytest.fail()s if it could not force one, so it cannot pass vacuously. Known-bad states, each proven LOUD by before/after rather than by reading code: no pytest module before: 17 misleading errors, exit 1 after: one named FATAL, exit 2, no suite started empty target dir fails on the per-directory `collected 0 tests` floor typo'd target GUARD 5 aborts naming the entry and saying "does not exist" The last two were already guarded before this PR; nothing had ever proven those paths could fire, so they are labelled REACHABILITY proofs, not regression coverage. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(test): write the python shim via testlib.mockbin, not a hand-rolled shebang The repo-wide runtime-shebang scanner (#306, scripts/tests/ test_runtime_shebangs.py) failed this file IN THE SANDBOX ONLY. The dev-host run was green because I ran this ONE file, and the scanner lives in another β a per-file run structurally cannot see a repo-wide guard. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
scripts/dl-router/testswas absent fromscripts/run-tests.sh'sHERMETIC_TARGETSsince the suite was written. 989 tests that no gate has ever run. Same
declarations-vs-instances shape as #298 (166 opencode tests) and #276 (913
guard-core tests): one missing line in a target list gating hundreds of instances.
Numbers β BOTH tiers, base ref
4eb5798(#302)Baseline re-measured tonight at
4eb5798itself, not carried over from an earlier ref.4eb5798(base)4eb5798+ this PRnix build .#checks.x86_64-linux.pytests(authoritative)scripts/run-tests.sh --set allunder nix-shellThe two tiers report the same numbers before and after β deliberately checked,
because the defects this PR fixes are exactly the kind that make them disagree.
+996accounted for exactly, no silent uncollection:dl-router collects 991 / skips 0 in both tiers. Nothing is gated, nothing is
skipped, no assertion was weakened. The single skip in the run is the pre-existing
pinned
repo-coslive-store drift check.MIN_TESTS2850 β 5600. The old floor had drifted to less than half the realtotal β a floor under which an entire 989-test suite could have vanished undetected.
What adding the suite surfaced β two SANDBOX-ONLY portability defects
Both are the two-tier hazard from RULES.md, and they point in opposite directions.
1.
test_setup_script.py:134wrote a stub with#!/usr/bin/env bash.Probed directly: the nix build sandbox has no
/usr/bin/env; every NixOS devhost does.
patchShebangsfixes the source tree and cannot touch a file a testwrites while running. Now goes through the helper #298 landed.
π΄ The finding that matters more than the fix: with the bad shebang restored,
all 989 tests still PASSED in the sandbox. The stub could not exec at all, and
the
exit 0cases are precisely the ones asserting that "a brave binary is running"must not decide anything β so a
pgrepthat cannot run is indistinguishable fromone answering "no". The harness was inert and nothing in the suite could tell.
So this PR adds
test_the_fake_pgrep_actually_execs[0,1](the +2), which asserts thestub's exit code directly and makes the harness's own breakage loud in this suite
rather than visible only to the structural scan.
2.
test_cli.py/test_server_wiring.pyhard-coded port 8799 for their"sidecar is DOWN / unreachable" assertions. That is a claim about the whole machine,
not about the test. MEASURED on the workbench: an orphaned
python3(pid 2994086,started Aug 1 13:40, ppid 1, in a stale tmux-spawn scope) was listening on
127.0.0.1:8799, sotest_an_unreachable_sidecar_gives_an_actionable_messagereached a real dl-router and failed with
sidecar HTTP 409: not_owned_tab.Ports now come from a
closed_portfixture (bind:0, read, release). Failed on thedev-host tier only β the mirror image of defect 1.
One rule, one place
scripts/collector/opencode/tests/_mockbin.pyβscripts/testlib/mockbin.py(
git mv, content unchanged but for the docstring), importable by any suite.Reused, not reinvented β it still owns the shebang and still raises if a call site
supplies its own.
it could not see the dl-router defect sitting in the repo the whole time. The
scanner moved to
scripts/testlib/shebang_scan.pyand the guard is nowrepo-wide (
scripts/tests/test_runtime_shebangs.py), covering everytest_*.pyandconftest.pyunderscripts/. Needles are still assembled fromchar codes so the scan cannot match its own source.
matches nothing fails (a stale pin otherwise pre-approves whatever lands at that
path next). 8 entries, each naming how that site avoids
/usr/bin/env(
/bin/sh, a resolvedwhichresult, orsys.executable). No entry is/usr/bin/envβ the allowlist is not an escape hatch for this hazard.Verification β red/green matrix
Honest labelling: 989 of the 991 dl-router tests are pre-existing and are NOT
regression coverage for this change. Their value is that they now run at all.
4eb5798c76a4b1scripts/dl-router/tests(989)test_no_test_writes_a_usr_bin_env_shebang_at_runtimetest_setup_script.py:134on real codetest_the_fake_pgrep_actually_execs[0,1]test_every_allowlist_entry_still_matches_somethingHarness validation (RULES.md β validate against a known-bad state; pair every
reassuring zero with a positive control):
re-ran
nix build .#checks.x86_64-linux.pytests:RESULT: FAIL,5658 collected / 5656 passed / 2 failed, failing in both places βscripts/tests(the scan) andscripts/dl-router/tests(the self-check). Restored β green. The gate can go red./usr/bin/envβ probed it: a throwawayrunCommandLocalprintedNO-USR-BIN-ENV.not unpinnedandnot staleare both emptylists, indistinguishable from a scan wired to nothing. Two tests feed the same
scan_tree/_matchesa case that MUST produce a non-zero count and assert thenumber moves (1 on the positive control, 0 under test). A third pins that
SCAN_ROOTactually resolves to >50 files, so the scan cannot pass vacuously on anempty file set.
:8799was still listeningat the time of the final run (re-checked, not remembered) β so the dev-host green
is measured against the state that produced the original failure, not after
quietly clearing it. The orphan was left alone; it is not mine to kill.
_write_execallowlist needles were caught being wrong by the stale-pintest before this was committed.
Merged-tree check
Rebased onto current
origin/main(4eb5798, which landed after this work startedand touches
test_plugin.pyβ a file this PR also edits).git merge-tree --write-treeexited 0; the rebase applied clean; both tiers were then re-run onthe merged tree, not on the pre-rebase branch. The final numbers above are from
commit
c76a4b1itself, re-measured after the last amend.Reported, NOT fixed here
scripts/dl-router/tests/*.test.mjsβ 508 tests, also completely ungated.scripts/run-node-tests.shhard-codesFILES=(scripts/browser-bridge/tests/*.test.mjs),so
checks.nodetestshas never seen dl-router's 13.mjsfiles. Measured: 508tests, 508 pass, 0 fail. Identical shape to this PR, other language, and it is
the larger remaining hole β the sidecar's routing logic and the extension's cached
fallback are asserted against shared fixture tables, and only half of that pair is
gated. Separate PR; note that node's spec reporter emits
βΉ tests 508, not the# testsTAP line the runner greps for.not product logic. The 989 tests pass on the code as it stands.
rebase.autoStashappears to be enabled for this repo βgit rebaseprintedCreated autostash, i.e. git reached for the repo-global stash on my behalf.It was transient and the stack was verified intact afterwards (9 pre-existing
entries, none mine,
stash@{0}untouched), but per RULES.md this is the exactmechanism that let two parallel agents steal each other's work, and the guard: enforce
git stash+git clean -ffor Claude Code, not just opencodeΒ #295 guardcannot see it because git does it internally. Worth turning off.
Privacy
scripts/dl-routerhandles a private library and this repo is public. The suite'sfixtures are entirely synthetic by construction (
Jane Doe,acme-studio,example-site.test,tmp_pathroots) β no real path, directory name, filename orroute-log content is committed, and none appears in this PR. The only literal path
added anywhere is
/bin/sh.π€ Generated with Claude Code