Skip to content

check-side-effects-array walks only the SOURCE BARREL's graph, so a registrar reachable only from a secondary entry form is outside the enumeration #8850

Description

@baozhoutao

scripts/check-side-effects-array.mjs derives its enumeration by walking ONE
graph: evaluatePackage calls walkEntryGraph(sourceBarrelAbs), where
sourceBarrelAbs is the single src/index.* that deriveSpellingMap finds.

But manifestEntryForms collects EVERY entry form the manifest publishes, and
every one of them is a module a consumer's bundler can resolve the package to.
A package with more than one entry therefore gets its array compared against an
enumeration derived from only one of them. A module that registers at load time
and is reachable only from a secondary entry is invisible to the walk: it is
never proposed as MISSING, and if the array does name it, it reads as STALE.

That is the same silent-drop failure class the gate exists to prevent — the
enumeration is quietly smaller than the promise the array makes.

Measured

@object-ui/types publishes a ./zod entry whose source barrel is
packages/types/src/zod/index.zod.ts. That file is NOT reachable from
packages/types/src/index.ts:

$ grep -n "zod" packages/types/src/index.ts
75:// they live on the main entry rather than under `/zod` (they carry no zod).
120:// envelope `{ dialect?, source }`. Its zod twin is `ExpressionWireSchema` on
121:// the `./zod` entry.
1170:// *types* only. The companion zod validators (`…Schema`) are deliberately NOT

...only comments. The walk from src/index.ts reaches 47 modules and none of
them is index.zod.ts, which is where the package's one load-time effect lives
(AnyComponentSchema = defineNodeComponentUnion(...), writing the node
recursion point's option slot).

⚠️ This matters for reading objectui#8578's headline number. That card
attributed the @object-ui/types reading of "0 module(s) with a top-level
registration, 47 walked"
to the classifier's blindness to a const
initializer. The classifier blindness was real and is fixed on that card, but
it was not the only cause: even with the classifier fixed, the walk never
reaches the module the effect is in. Verified after the objectui#8578 fix —
pointing scanModule straight at the file reports the registration, and the
package-level walk still does not include the file.

⚠️ @object-ui/types declares sideEffects: false today, so it is not in this
gate's population at all (readArrayPackages takes ARRAY declarations only).
This card is about the gate, not about that manifest — the defect applies to any
multi-entry package that declares an array, and @object-ui/app-shell already
publishes many entry forms.

What a fix has to answer

  1. Which entry forms should anchor a walk? Every form manifestEntryForms
    returns is a resolution target, but the gate only knows the SOURCE spelling
    for the one barrel deriveSpellingMap round-trips on. Mapping a published
    secondary form back to its source file is the inverse of toPublished and
    needs to fail loudly when it cannot.
  2. What is the union's cost? @object-ui/app-shell publishes 31 entries; a walk
    per entry has to stay a single de-duplicated module set or the walk time
    multiplies.
  3. Reachability (checkReachability) currently walks back to ONE barrel. With
    several entries a registrar is retained if ANY covered entry reaches it, so
    that check widens with the walk.

Related

objectui#8578 (the classifier fix, where this was measured) · objectui#6683 (the
gate's ruling and its enumeration rule) · objectui#8344 / objectui#8577.

Measured by the domain:devx developer seat working objectui#8578, session
session_01FhBNJcLRZLe8M87VcUgpKr. Generated with Claude Code.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions