From 0fb3a8084ff79d3a287b631f610ba1ff3a284c75 Mon Sep 17 00:00:00 2001 From: Paul Clark Date: Thu, 1 Oct 2026 18:59:37 -0400 Subject: [PATCH 1/2] Run the unit suites in CI, which nothing in this repository ran `package.json` has declared `"test": "vitest run"` for as long as the suites have existed, and no workflow ever called it. The publishing path waited on `npm run test:a11y` and nothing else, so five test files and 44 cases sat in the repository where anyone would look for them and never executed. Four of the five assert that the script engine REJECTS what it should reject -- the opcode disable list, malformed pushes, inspection of invalid scripts -- so a change that broke a reject path could reach the live site with every gate green. They pass as they stand: 5 files, 44 cases, 1.45s. Nothing about them needed fixing; they needed calling. The step goes before `npm run build` so a unit failure ends the run in seconds rather than after a Chromium download. `vitest run` exits 1 when it matches no files -- verified here by pointing it at a directory that does not exist -- so this step cannot pass by silently running nothing, which is the failure mode that made crypto-lab-padding-oracle#15 necessary. It also makes two sentences in this file true that were not. The auto-merge comments say a bump merges only if "this lab's own tests, build and axe/e2e run went green" and that the gate is "unit tests, build, axe WCAG and the e2e claims". The e2e half was accurate -- `playwright.config.ts` has `testDir: './e2e'`, so `claims.spec.ts` runs alongside `a11y.spec.ts`. The unit half was not, until this step. Both `deploy` and `dependabot-auto-merge` already name `build` in `needs:`, so the unit tests now gate the deploy and the Dependabot merge with no further wiring. Found by `tools/test-invocation.js`, reported as crypto-lab#39 and crypto-lab-bitcoin-script#24. Co-Authored-By: Claude Opus 5 --- .github/workflows/deploy.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index bfa7e96..850f664 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -26,6 +26,15 @@ jobs: node-version: 20 cache: npm - run: npm ci + # The unit suites, which nothing in this repository ran until now. Five + # files, 44 cases, four of them asserting the script engine REJECTS what + # it should reject -- so before this step a change that broke a reject + # path reached the live site with every gate green. Placed before the + # build so a unit failure fails the run in seconds rather than after a + # browser download. `vitest run` exits 1 when it matches no files, so + # this step cannot pass by silently running nothing. + - name: Unit tests (vitest) + run: npm test - run: npm run build - name: Install Playwright browser run: npx playwright install --with-deps chromium From d19ccd3fd0cd31f1a122bf24d1475879a6dbf2a4 Mon Sep 17 00:00:00 2001 From: Paul Clark Date: Thu, 1 Oct 2026 19:13:11 -0400 Subject: [PATCH 2/2] Move the gate to node 24, which is the version these suites can run on Adding the unit step revealed more than an uncalled suite: on the pinned node 20 the suites cannot run at all. Three of the five test files failed to start their worker with "webidl.util.markAsUncloneable is not a function" -- jsdom requires undici, whose CacheStorage calls it, and node 20.20.2 does not have it. Two files and 23 cases passed; the other three never executed, and vitest exited 1 with "3 errors". `npm ci` said so in advance on the same run: @asamuzakjp/css-color@7.0.1 and @asamuzakjp/dom-selector@9.2.1 both declare `node: ^22.22.2 || ^24.15.0 || >=26.0.0`, and the warnings scrolled past unread because nothing downstream of them ran. 24 rather than 22 because setup-node resolves 24 to a release at or above the 24.15.0 these packages require, and 36 labs in the fleet are already there, including crypto-lab-padding-oracle after the same class of fix. This is the cost of a suite with no caller stated precisely: it was not merely unrun, it had rotted to unrunnable, and the one signal that would have said so was a warning on a step whose output nobody had reason to read. Co-Authored-By: Claude Opus 5 --- .github/workflows/deploy.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 850f664..1728728 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -23,7 +23,14 @@ jobs: - uses: actions/checkout@v7 - uses: actions/setup-node@v7 with: - node-version: 20 + # 20 could not run this lab's unit suites at all. jsdom pulls undici, + # whose CacheStorage calls webidl.util.markAsUncloneable, and three of + # the five test files died starting their worker on node 20.20.2 with + # "markAsUncloneable is not a function". `npm ci` says the same thing + # in advance: @asamuzakjp/css-color and @asamuzakjp/dom-selector both + # declare `node: ^22.22.2 || ^24.15.0 || >=26.0.0`. Nothing noticed + # because nothing called the suites -- a gap that hides the next one. + node-version: 24 cache: npm - run: npm ci # The unit suites, which nothing in this repository ran until now. Five