Repository navigation
Makes the verification real: the gates now run in CI, and every one is proven able to fail.
The defect this fixes
verify-bundle.mjs caught three real packaging omissions in three days — install.ps1/install.sh, PRIVACY.md and docs/roadmap.md were each present in the tree and absent from manifest.files, so the tarball would have shipped without them.
All three were caught locally, by hand. CI never ran that script: it imports index.js, which needs a local DSH installation, so the whole file was skipped — including the static packaging checks that need nothing but the tree. CI's own "Manifest files exist" step only checks six fixed paths, not that files is complete. The badge stayed green while the package was incomplete.
What changed
Split along the dependency line, not the topic line.
tools/verify-manifest.mjs— Node builtins only; owns every static check and runs in CI. One implementation, referenced byverify-bundle.mjs.tools/verify-bundle.mjs— 569 → ~200 lines; keeps only checks that must load the plugin, and reportsUNVERIFIEDrather thanPASSwhere it cannot look.tools/lib/report.mjs— one three-state reporter (pass/fail/unverified), so a check that could not run never reads as success, and tests can assert state instead of parsing console output.
tools/check-script-coverage.mjs catches the class, not the instance. Every tools/ script must be referenced by scripts, CI, tests or another tool — or listed in docs/script-baseline.json with a reason (≥20 characters; an exemption that is no longer needed is itself a failure). Its first run found four unreferenced scripts and five gates missing from CI.
Documented numbers are now measured. docs/stats.json + tools/status.mjs --write physically run each measurement and record the source; the README carries 61<!--stats:action_count--> claims that tools/check-docs.mjs verifies. Its first run found two wrong numbers in the README:
| Claim | Actual |
|---|---|
| 9 tools / 58 actions | 61 |
| 23 destructive actions | 29 (+4 github_api write methods, classified at run time) |
Two new test suites (32 tests)
test/wiring.test.mjs— asserts gates appear inside CIrun:blocks, not step names, because a step named "Static delivery gate" whose body isecho skippedsatisfies any name-based check. It caught thatnpm run releasedid not run the new static gates.test/gates.test.mjs— builds a genuinely broken tree per gate and asserts the matching result isFAIL, because "exit code ≠ 0" passes when the wrong check failed.
Verification
| Suite | Result |
|---|---|
| Offline tests | 207/207 (32 new) |
| Static gates | 4/4 (manifest / coverage / docs / encoding) |
| Full dynamic gate | passing |
| Parameters / guidance / snapshots / argv | 211/211 · 114/114 · 180/180 · 84/84 |
Note on scope
No tool behaviour changed — this release is entirely about whether the project can tell when it is wrong.
Full Changelog: v2.0.0...v2.1.0