feat(ci): two conventions become gates (improvise-w8ih, improvise-4ktt)
The stamp gate is scripts/assemble-stamp.sh, taking FILE PATTERN pairs, and scripts/assemble-stamp-test.sh is its check_the_checker. Deleting the final `test -z "$missing"` makes four of its eight cases fail; before the extraction that same deletion was invisible, both misses printing while assemble.sh exited 0. It is a separate script because exercising it inside assemble.sh would need a fabricated web/pkg, which is a second answer to "what does the site assemble from" (improvise-vvl3). Wired into the `build` job, first, because it needs nothing and guards a step in that job. web/tests/bundle_freedom.test.js refuses a flat web/tests/ file that names the bundle directory -- the constraint keeping the `js` job at seconds rather than ~4m30s, stated in prose and checked by nothing. It scans its own filename too, so it cannot become the place a violation hides, and its companion asserts web/tests/bundle/ still holds a test that DOES use the bundle: a scoping rule is uninteresting if nothing falls outside it. Both faults were injected and watched to fail; evidence in context/test-evidence/tooling.md. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
// The `js` CI job must never need a built wasm bundle. See
|
||||
// context/code/clients.md; the split is what keeps it seconds, not ~4m30s.
|
||||
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync, readdirSync } from "node:fs";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const dir = fileURLToPath(new URL(".", import.meta.url));
|
||||
|
||||
/// Built by concatenation so this file carries no literal of the thing it
|
||||
/// forbids, and is therefore checked by itself rather than exempt from itself.
|
||||
const FORBIDDEN = "p" + "kg";
|
||||
|
||||
/// Comments may name the directory — that is what the header above does. Only
|
||||
/// what the code reaches for is a dependency, so strip comments first, exactly
|
||||
/// as render_surface.test.js does.
|
||||
const code = (name) =>
|
||||
readFileSync(dir + name, "utf8")
|
||||
.replace(/\/\*[\s\S]*?\*\//g, " ")
|
||||
.replace(/(^|[^:"'`])\/\/.*$/gm, "$1");
|
||||
|
||||
test("no test in web/tests/ reaches for a built bundle", () => {
|
||||
const siblings = readdirSync(dir).filter((f) => f.endsWith(".test.js"));
|
||||
assert.ok(siblings.length > 1, `found ${siblings.length} test files — the glob moved`);
|
||||
assert.ok(siblings.includes("bundle_freedom.test.js"), "this file must check itself");
|
||||
|
||||
const offenders = siblings.filter((f) => code(f).includes(FORBIDDEN));
|
||||
assert.deepEqual(
|
||||
offenders,
|
||||
[],
|
||||
`these belong in web/tests/bundle/, which the browser job runs: ${offenders}`,
|
||||
);
|
||||
});
|
||||
|
||||
test("the subdirectory that MAY use a bundle is not the one being checked", () => {
|
||||
// Reading it proves the exemption is a real directory rather than a
|
||||
// convention nobody kept, and that this check is scoped to the flat listing.
|
||||
const nested = readdirSync(dir + "bundle").filter((f) => f.endsWith(".test.js"));
|
||||
assert.ok(nested.length > 0, "web/tests/bundle/ is empty — the split lost its other half");
|
||||
assert.ok(
|
||||
nested.some((f) => readFileSync(dir + "bundle/" + f, "utf8").includes(FORBIDDEN)),
|
||||
"no bundle test reaches for a bundle, so this check has nothing to be scoped against",
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user