Found while measuring #14680 (PR #15343). Recording only, unassigned.
The gap
#14680's own diagnosis names it: "no gate measures the weight of the lean entry's closure". That is exactly right, and it is why the regression it describes was invisible for the whole time it was live. The measurement in PR #15343 confirms it was worth catching — the one root-entry import cost @objectstack/objectql/core 6 modules and 498,616 bytes at module-init (ESM; 513,204 B for the CJS flavour), and no gate, test or CI job reported anything.
What exists today is packages/objectql/src/core-boundary.ratchet.test.ts (ADR-0076 D2). It is a good test and it is not this: it scans source text for imports of one forbidden package name.
const FORBIDDEN_PACKAGES = ['@objectstack/metadata-protocol'];
const FORBIDDEN_LOCAL = ['plugin', 'kernel-factory'];
So it catches the one edge it was written for, by name, and a heavyweight arriving through any other specifier is outside it by construction. @objectstack/metadata is not on the list, so the import that occasioned #14680 crossed nothing.
Why a byte figure is NOT the obvious answer
That same file argues, at length and with evidence, against selling this boundary with a number — the old "268KB" claim was raw source bytes of one file, later re-pointed at a whole package, and the re-measure showed a 21x spread straddling the quoted figure in both directions. Its conclusion is worth quoting because it constrains what a new gate may claim:
The claim worth making is EXCLUSION, and the test below is what pins it.
The measurement done for #14680 does not contradict that. It reports a module set, not a size headline: which files Node evaluates when the entry is loaded, recorded from a real load. The set is a decidable, unit-carrying property; the sum of its bytes is a derived convenience.
A shape worth considering, not prescribed
Extend the D2 ratchet from a source scan to a loaded-module assertion: build, load @objectstack/objectql/core in a child process, collect the evaluated module set through module.registerHooks, and assert that no path in it matches a forbidden set — @objectstack/metadata-protocol as today, plus the filesystem/watcher tier (chokidar, readdirp, glob, js-yaml) that the lean entry has no business loading.
Properties this would have that the source scan does not:
Costs to weigh, honestly: it needs the package built, so it is a different kind of test from the source scan beside it (which deliberately needs nothing); and a forbidden-list gate still cannot see a heavyweight nobody thought to list. A module-count ratchet would cover the second, at the price of a number that moves for innocent reasons.
Not in scope for the card that found it
#14680 is the repoint of one import. This is the gate that would have caught it, which is a different change with a different owner, and the design question above is a real one rather than a mechanical follow-up.
Re-check
git grep -n "FORBIDDEN_PACKAGES" -- packages/objectql/src/core-boundary.ratchet.test.ts
Generated by Claude Code
Found while measuring #14680 (PR #15343). Recording only, unassigned.
The gap
#14680's own diagnosis names it: "no gate measures the weight of the lean entry's closure". That is exactly right, and it is why the regression it describes was invisible for the whole time it was live. The measurement in PR #15343 confirms it was worth catching — the one root-entry import cost
@objectstack/objectql/core6 modules and 498,616 bytes at module-init (ESM; 513,204 B for the CJS flavour), and no gate, test or CI job reported anything.What exists today is
packages/objectql/src/core-boundary.ratchet.test.ts(ADR-0076 D2). It is a good test and it is not this: it scans source text for imports of one forbidden package name.So it catches the one edge it was written for, by name, and a heavyweight arriving through any other specifier is outside it by construction.
@objectstack/metadatais not on the list, so the import that occasioned #14680 crossed nothing.Why a byte figure is NOT the obvious answer
That same file argues, at length and with evidence, against selling this boundary with a number — the old "268KB" claim was raw source bytes of one file, later re-pointed at a whole package, and the re-measure showed a 21x spread straddling the quoted figure in both directions. Its conclusion is worth quoting because it constrains what a new gate may claim:
The measurement done for #14680 does not contradict that. It reports a module set, not a size headline: which files Node evaluates when the entry is loaded, recorded from a real load. The set is a decidable, unit-carrying property; the sum of its bytes is a derived convenience.
A shape worth considering, not prescribed
Extend the D2 ratchet from a source scan to a loaded-module assertion: build, load
@objectstack/objectql/corein a child process, collect the evaluated module set throughmodule.registerHooks, and assert that no path in it matches a forbidden set —@objectstack/metadata-protocolas today, plus the filesystem/watcher tier (chokidar,readdirp,glob,js-yaml) that the lean entry has no business loading.Properties this would have that the source scan does not:
engine.tsreachesderiveViewContainerObjectthrough@objectstack/metadata's ROOT entry, so objectql's lean ADR-0076core.tsclosure now pulls MetadataPlugin, chokidar, glob and js-yaml for a six-line pure function #14680 arrived;@objectstack/objectql/core's "268KB metadata protocol" figure is unverified at HEAD — the structural claim holds, the number does not reproduce #9803 discipline rather than reopening it;Costs to weigh, honestly: it needs the package built, so it is a different kind of test from the source scan beside it (which deliberately needs nothing); and a forbidden-list gate still cannot see a heavyweight nobody thought to list. A module-count ratchet would cover the second, at the price of a number that moves for innocent reasons.
Not in scope for the card that found it
#14680 is the repoint of one import. This is the gate that would have caught it, which is a different change with a different owner, and the design question above is a real one rather than a mechanical follow-up.
Re-check
Generated by Claude Code