#3235 · one dispatch engine for the test suite

A test file's coverage no longer depends on where it sits or who remembered to wire it.

BEFORE — two philosophies

LOCAL  npm test → run-all-tests.sh
  133 HAND-WIRED run_test lines
  vs 231 test files on disk
  wiring itself was a bug class:
  "bash <path>" / "node <path>"
  tripped the [[ -f ]] guard into
  silent SKIP — 3 real incidents
  (#3231, #3236, #3220 found 17
  files never wired at all)

CI     per-dir glob, everything runs

AFTER — one engine

LOCAL  npm test → run-all-tests.sh v4
  22 run_dir calls → the SAME
  scripts/ci/run-tests.sh glob
  CI uses. A new test file runs
  everywhere the moment it
  exists. No wiring step, no
  interpreter prefixes, no
  double-runs.

CI     unchanged (same engine)

Correction shipped inside this PR's framing

The earlier "123 of 133 lines carry || true so the local suite cannot fail" reading was WRONG: the v3 runner had no set -e, tallied every failure into TOTAL_FAILED, and exited 1 at the end. The || trues were vestigial. The real defects were the roster gap (~100 files running only in CI) and the wiring-to-forget class — which is what this PR removes. v4 also upgrades to full set -euo pipefail with recorded (never swallowed) exit captures.

Deliberate non-glob residue — every exception is explicit and justified

exceptionreason
tests/fixtures never globbedtest-helpers.sh is a sourced library; standalone exit 0 = fake coverage
tests/orphans runs advisory (env)detector-vs-ratchet split: reachability RATCHET (29 baseline) is the gate; the detector fails on all 29 accepted ones
scorecard + ci/lint.sh explicitnot test-*.sh, the glob cannot see them; scorecard stays WARN-only
vitest local-only blockCI runs it in 4 dedicated shards

The ratchet keeps its job — smaller and sharper

test-test-discovery.mjs: in-glob files are executed BY CONSTRUCTION,
so the orphan ratchet now guards only the residue outside GLOBBED_DIRS.
Held at 1/1 baseline after the rewrite.

Riding along in the same train

itemwhat
warn ratchettwo full-suite runs confirm the real count; baseline tightened from 348 accordingly
budget slackfattest model-facing descriptions trimmed; token caps ratcheted back down per the "never raise to clear a regression" rule