Skip to content

Console Pin Gate cannot build any objectui pin at/after 6d5368ac8: the lazy-linter counter-probe is blind to the OBJECTSTACK_SPEC_DIST injection #10136

Description

@os-project-manager

Measured in a dedicated worktree at origin/main + the pin bump from #10129, not recalled.

scripts/build-console.sh cannot build objectui at main (0fd11444a89e57114903afa2cc8115a3871f3e16). The console build dies in generateBundle:

[plugin assert-lazy-linter-stays-lazy]
RolldownError: [assert-lazy-linter-stays-lazy] counter-probe failed: no eagerly loaded chunk
contains an `@objectstack/spec` module. The spec is reached synchronously from the app entry,
so it must be in the eager closure — its absence means this walk is reading the graph wrongly,
not that the bundle improved. Fix the walk before trusting the linter assertion below.
(entry chunks: assets/index-mpVXni3j.js; eager chunks: 59/508)

This blocks #10129 (bump the pin to current objectui main) and it will turn Console Pin Gate red on any PR that moves .objectui-sha to a commit at or after objectui 6d5368ac8 — the commit that added the probe (objectui#5323, "keep the lazily-imported @objectstack/lint out of the eager chunk").

The two mechanisms, and why they are incompatible

Ours (#8134, hook added in objectui#4854).build-console.sh exports OBJECTSTACK_SPEC_DIST so the console bundles this tree's spec instead of the last published one from objectui's lockfile. objectui's apps/console/vite.config.ts honours it through resolveSpecDistInjection, which rewrites all 18@objectstack/spec* specifiers to absolute paths in the framework tree:

@objectstack/spec/ai => /path/to/objectstack/packages/spec/dist/ai/index.mjs
@objectstack/spec/api => /path/to/objectstack/packages/spec/dist/api/index.mjs
... (18 aliases, one per exports-map entry)

That helper already knows this rewrite moves the spec out of node_modules, and it compensates where it must: it returns a widenedvendorChunkTest, so the chunk grouping keeps recognising the injected spec —

/[\\/]node_modules[\\/](@objectstack)[\\/]|\/path\/to\/objectstack\/packages\/spec[\\/]/

Theirs (objectui#5323).assertLazyLinterStaysLazy() in the same vite.config.ts carries its own private module-id regex and is not widened:

constSPEC=/@objectstack[\\/+]spec/;

Under the injection, zero emitted module ids match it — the ids are now framework-tree absolute paths with no @objectstack segment at all. So the counter-probe, whose whole job is to refuse a verdict when the walk sees nothing, correctly refuses — and takes the build with it. The counter-probe is not wrong about what it saw; it is reading a module-id shape that our injection deliberately abolished.

Reproduction — the injection is the only variable

Same objectui build tree, same pin, same command:

OBJECTSTACK_SPEC_DISTresult
set (what build-console.sh does)Build failed in 11.73s, counter-probe error above
unsetEXIT=0, dist written
# fails
bash scripts/build-console.sh
# succeeds — identical tree, injection removedcd .cache/objectui-0fd11444a89e
OBJECTSTACK_CLIENT_DIST=/path/to/objectstack/packages/client \
pnpm --filter @object-ui/console exec vite build

CI reproduces it as-is: Console Pin Gate runs bash scripts/build-console.sh, and the probe is registered unconditionally in the plugins array (its own comment says "Runs on CI/Vercel too"). The runner's framework path (/home/runner/work/objectstack/objectstack/packages/spec) has no @objectstack segment either, so the mismatch is not local-path-specific.

Where the fix belongs

objectui, apps/console/vite.config.ts — the file already computes the widened test three lines away:

constvendorObjectstackTest=specDistInjection ? specDistInjection.vendorChunkTest : VENDOR_OBJECTSTACK_TEST;

assertLazyLinterStaysLazy() should consume the injection-aware location the same way instead of hardcoding SPEC, i.e. take the spec test as a parameter. Contract-first: the defect is that one consumer of resolveSpecDistInjection's output does not read that output — widening a tolerance on our side, or dropping the injection, would both be workarounds for a producer that already publishes the right answer.

Note the LINT half of the probe needs the same review: @objectstack/lint is not injected today, so its regex still matches — but #9659 proposes injecting four more @objectstack/* packages the same way, and lint is a plausible member of that set.

A companion objectui PR is required; this repo cannot fix it alone. Until it lands, the pin cannot move past objectui 6d5368ac8 with a green Console Pin Gate.

Not the remedy

Back-link: blocks objectstack#10129. Related: #9707 (the finding objectui#5323 answers), #9659 (more packages proposed for the same injection).

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions