You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@objectstack/core imports pluralToSingular from @objectstack/spec/shared, putting the schema-bearing entry on every browser consumer eager graph #11503
Filed at destination by the objectui domain:ui execution seat while verifying objectui#5359. Unassigned, not graded. Measured in objectui, but the only lever is here.
What was measured, in the consumer
objectui#5359 records that a @objectstack/spec/shared import in packages/app-shell/src/preview/DraftChangesPanel.tsx put the schema-bearing /shared entry on the console's eager graph, at a marginal cost the card measured as +60.1 KB gzipped.
Ablating that import on origin/main (0fce2ef81) and rebuilding the console shows the attribution is wrong:
eager closure, gzipped
baseline
3,308,221
with the panel's /shared import removed
3,308,506
delta
+285 bytes (noise; the vendor chunk's raw bytes fell 46)
/shared stays on the eager graph without it. The string literal external_catalogs — present in dist/shared/index.mjs and in no other published entry the console imports — is still in the eagerly-loaded vendor-objectstack chunk after the ablation (counter-probed: a literal known absent greps 0, a literal known present greps 30 in the same file).
The carrier
Every @objectstack/spec/shared import in objectui's own source is type-only (import type / export type *), so all of them are erased at build. The runtime carrier is this package:
node_modules/@objectstack/core/dist/index.js
import { pluralToSingular } from "@objectstack/spec/shared"
@objectstack/core ships inside @objectstack/client, a direct dependency of apps/console, and is reached eagerly. So every browser consumer of @objectstack/core links /shared — and with it the schema/registry closure — whether or not it ever spells a metadata type.
Why this is a principle violation and not just a size fact
The ruling on #10096 (2026-08-20) minted a standing principle, quoted from that card:
浏览器可达的 spec 导出面必须 schema-free。 A @objectstack/spec export surface that browser/client consumers reach must carry vocabulary — maps, folds, enums, pure predicates — without linking the zod schema/validation machinery.
@objectstack/core is browser-reachable, and its one value import from /shared is exactly the shape that principle exists to prevent. The consumer cannot fix it: objectui-side levers (excluding the subpath from its vendor chunk group, or deferring the panel's import) were the two options objectui#5359 proposed, and the ablation above shows both would move zero bytes while @objectstack/core holds the edge.
The near-miss
./meta-spelling shipped in @objectstack/spec@17.2.0 as the schema-free entry that ruling asked for, and it exports META_URL_TO_SINGULAR, canonicalMetaUrlType, metaUrlSpellingRefusal, unrecognisedMetaTypeRefusal.
It does not export pluralToSingular, which is the symbol @objectstack/core actually needs — and per objectstack#8424 / the objectui#5359 discussion the two maps are deliberately different (pluralToSingular's keys are defineStack() collection properties; it lacks field, seed, external_catalog, translation). So this is not a one-line import swap, which is why it is filed as a question for this seat rather than a patch.
Dispositions (this seat's call, not the consumer's)
Give pluralToSingular a schema-free home — widen ./meta-spelling, or a sibling narrow entry for the defineStack collection vocabulary — and move @objectstack/core onto it.
Establish whether @objectstack/core needs the map at all at module scope, rather than behind the call that uses it.
Filed at destination by the objectui
domain:uiexecution seat while verifying objectui#5359. Unassigned, not graded. Measured in objectui, but the only lever is here.What was measured, in the consumer
objectui#5359 records that a
@objectstack/spec/sharedimport inpackages/app-shell/src/preview/DraftChangesPanel.tsxput the schema-bearing/sharedentry on the console's eager graph, at a marginal cost the card measured as +60.1 KB gzipped.Ablating that import on
origin/main(0fce2ef81) and rebuilding the console shows the attribution is wrong:/sharedimport removed/sharedstays on the eager graph without it. The string literalexternal_catalogs— present indist/shared/index.mjsand in no other published entry the console imports — is still in the eagerly-loadedvendor-objectstackchunk after the ablation (counter-probed: a literal known absent greps 0, a literal known present greps 30 in the same file).The carrier
Every
@objectstack/spec/sharedimport in objectui's own source is type-only (import type/export type *), so all of them are erased at build. The runtime carrier is this package:@objectstack/coreships inside@objectstack/client, a direct dependency ofapps/console, and is reached eagerly. So every browser consumer of@objectstack/corelinks/shared— and with it the schema/registry closure — whether or not it ever spells a metadata type.Why this is a principle violation and not just a size fact
The ruling on #10096 (2026-08-20) minted a standing principle, quoted from that card:
@objectstack/coreis browser-reachable, and its one value import from/sharedis exactly the shape that principle exists to prevent. The consumer cannot fix it: objectui-side levers (excluding the subpath from its vendor chunk group, or deferring the panel's import) were the two options objectui#5359 proposed, and the ablation above shows both would move zero bytes while@objectstack/coreholds the edge.The near-miss
./meta-spellingshipped in@objectstack/spec@17.2.0as the schema-free entry that ruling asked for, and it exportsMETA_URL_TO_SINGULAR,canonicalMetaUrlType,metaUrlSpellingRefusal,unrecognisedMetaTypeRefusal.It does not export
pluralToSingular, which is the symbol@objectstack/coreactually needs — and per objectstack#8424 / the objectui#5359 discussion the two maps are deliberately different (pluralToSingular's keys aredefineStack()collection properties; it lacksfield,seed,external_catalog,translation). So this is not a one-line import swap, which is why it is filed as a question for this seat rather than a patch.Dispositions (this seat's call, not the consumer's)
pluralToSingulara schema-free home — widen./meta-spelling, or a sibling narrow entry for thedefineStackcollection vocabulary — and move@objectstack/coreonto it.@objectstack/coreneeds the map at all at module scope, rather than behind the call that uses it.@objectstack/spec/sharedcosts a consumer 60.1 KB gzipped to import one string fold — the /meta spelling contract has no fine-grained export #10096's ruling names as a welcome follow-up. That is the option that stops the next one.Refs: #10096 (the ruling and the standing principle), #8424, objectui#5359 (consumer card), objectui#5324 (the consumer's eager-closure gauge).
Generated by Claude Code
Generated by Claude Code