scripts/check-side-effects-array.mjs reports @object-ui/types as having 0 modules with a
top-level registration (its own --list output: "0 module(s) with a top-level registration, 47
walked"), while a bundler demonstrably drops a real load-time effect from that package.
Why the two disagree
The classifier sorts a module's top-level effects and counts a CALL STATEMENT. The effect it
misses is performed inside a const INITIALIZER:
export const AnyComponentSchema = defineNodeComponentUnion(z.discriminatedUnion('type', [ ... ]));
defineNodeComponentUnion writes the node recursion point's option slot as a side effect of
evaluating that initializer. To the classifier the module declares constants and does nothing; to
a bundler honouring "sideEffects": false the const is droppable when its binding goes unread,
and the write goes with it.
Measured
On this repo's own Vite/rollup lib build, an entry importing only CardSchema from
@object-ui/types/zod produces a 370,652-byte bundle with the fill ABSENT, and a nested off-spec
node is ACCEPTED — the pre-objectui#8344 accept set, silently. The same entry that also imports
AnyComponentSchema keeps the fill and REFUSES the node. So the effect is real, it is
load-time, and the gate that exists to enumerate exactly those effects scores the package zero.
Why this matters beyond one package
The gate's own file header states the design intent: an UNKNOWN effect must be an ERROR rather
than a quiet "not a registration", because "I did not recognise that" and "that is not a
registration" must not be the same answer. An effect inside an initializer currently takes the
second answer silently. Any package can acquire one the same way — a registry write, a cache
prime, a slot fill — and the gate will keep reporting zero.
⚠️ ⛔ This card does NOT ask for the @object-ui/types manifest to change; that decision is objectui#8577, and this classifier is wrong whichever way that decision
goes.
Sketch of what a fix has to answer
- Does a CALL inside a top-level
const initializer count as a registration? A bundler treats
it as droppable-with-the-binding rather than pure, so "it depends on whether the binding is
read" is a real answer the gate would have to model.
- If it counts,
@object-ui/types acquires a registering module and its manifest options change
with it — which is exactly the other card's decision, so the two want sequencing.
- If it does not count, the gate should say so explicitly rather than by silence, so the next
author does not read a zero as "this package has no load-time effects".
Related
objectui#8344 / objectui#8501 (where the blindness surfaced) · objectui#6683 (the gate's ruling
and its enumeration rule) · objectui#3943 (the wider consistency pin) · objectui#8577 (the manifest decision).
Measured by the domain:spec developer seat working objectui#8344, session
session_01CZY49skxUBYyJcdnTcYPrE. Generated with Claude Code.
Generated by Claude Code
scripts/check-side-effects-array.mjsreports@object-ui/typesas having 0 modules with atop-level registration (its own
--listoutput: "0 module(s) with a top-level registration, 47walked"), while a bundler demonstrably drops a real load-time effect from that package.
Why the two disagree
The classifier sorts a module's top-level effects and counts a CALL STATEMENT. The effect it
misses is performed inside a
constINITIALIZER:defineNodeComponentUnionwrites the node recursion point's option slot as a side effect ofevaluating that initializer. To the classifier the module declares constants and does nothing; to
a bundler honouring
"sideEffects": falsethe const is droppable when its binding goes unread,and the write goes with it.
Measured
On this repo's own Vite/rollup lib build, an entry importing only
CardSchemafrom@object-ui/types/zodproduces a 370,652-byte bundle with the fill ABSENT, and a nested off-specnode is ACCEPTED — the pre-objectui#8344 accept set, silently. The same entry that also imports
AnyComponentSchemakeeps the fill and REFUSES the node. So the effect is real, it isload-time, and the gate that exists to enumerate exactly those effects scores the package zero.
Why this matters beyond one package
The gate's own file header states the design intent: an UNKNOWN effect must be an ERROR rather
than a quiet "not a registration", because "I did not recognise that" and "that is not a
registration" must not be the same answer. An effect inside an initializer currently takes the
second answer silently. Any package can acquire one the same way — a registry write, a cache
prime, a slot fill — and the gate will keep reporting zero.
@object-ui/typesmanifest to change; that decision is objectui#8577, and this classifier is wrong whichever way that decisiongoes.
Sketch of what a fix has to answer
constinitializer count as a registration? A bundler treatsit as droppable-with-the-binding rather than pure, so "it depends on whether the binding is
read" is a real answer the gate would have to model.
@object-ui/typesacquires a registering module and its manifest options changewith it — which is exactly the other card's decision, so the two want sequencing.
author does not read a zero as "this package has no load-time effects".
Related
objectui#8344 / objectui#8501 (where the blindness surfaced) · objectui#6683 (the gate's ruling
and its enumeration rule) · objectui#3943 (the wider consistency pin) · objectui#8577 (the manifest decision).
Measured by the
domain:specdeveloper seat working objectui#8344, sessionsession_01CZY49skxUBYyJcdnTcYPrE. Generated with Claude Code.Generated by Claude Code