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
Split out of the work on #4538, which fixed @object-ui/react plus the dependency closure its entry evaluates through (types, core, i18n). The seven packages below carry the identical defect and were left out of that PR: two of them were held by other sessions at the time, and the rest were outside its declared file surface. They are recorded in the new gate's SPECIFIER_DEBT ledger so they cannot get worse; this card is to clear them.
#4538 remains the source of the analysis and is not addressed further here.
The defect
Node's ESM resolver does not extension-search relative specifiers. A bare tsc never rewrites import specifiers, so an extensionless ./Foo in the source is an extensionless ./Foo in the published dist, and importing the entry under plain Node fails with ERR_MODULE_NOT_FOUND. Bundled consumers are unaffected, which is why everything is green today.
Measured, 2026-08-18, on a full build of every published package
Specifier leg (pnpm check:esm-specifiers) — packages whose build preserves specifiers:
package
extensionless specifiers
@object-ui/app-shell
1259
@object-ui/fields
295
@object-ui/auth
54
@object-ui/mobile
27
@object-ui/collaboration
15
@object-ui/permissions
14
@object-ui/providers
9
Load leg (pnpm check:node-esm-load) — 17 of 39 published ESM entries import and evaluate. The remaining 22 break down as:
the 7 above, each failing on its own file;
11 more that fail on somebody else's file — plugin-calendar, plugin-designer, plugin-grid, plugin-list, plugin-timeline and plugin-view all die on packages/mobile/dist/useBreakpoint; plugin-detail, plugin-form, plugin-gantt and plugin-kanban on packages/permissions/dist/PermissionProvider; plugin-report on packages/providers/dist/DataSourceProvider;
2 that fail on a .css import from a third-party dependency (plugin-dashboard, plugin-map) — a different question, ledgered separately as LOAD_DEBT;
2 that are not importable by design (create-plugin is a bin-only CLI, runner is a built web app).
So clearing these seven takes the repo from 17 to 35 of 39 loadable entries. @object-ui/mobile at 27 specifiers and @object-ui/permissions at 14 are the cheapest wins by a wide margin.
The fix shape, already proven on four packages
Append the explicit extension to every relative specifier in the files the build emits (./x becomes ./x.js; a directory import becomes ./x/index.js). Resolve each one against the filesystem rather than pattern-matching — a specifier inside a comment must be left alone.
Delete the package's entry from SPECIFIER_DEBT in scripts/check-node-esm-load.mjs in the same commit — the ledger is a ratchet and fails on a stale entry.
⛔ Do not change moduleResolution in the roottsconfig.json. 38 packages extend it; a repo-wide flip is a much larger change and is not what this card is.
@object-ui/app-shell at 1259 specifiers is large enough that it probably deserves its own card rather than riding along with the small ones.
Split out of the work on #4538, which fixed
@object-ui/reactplus the dependency closure its entry evaluates through (types,core,i18n). The seven packages below carry the identical defect and were left out of that PR: two of them were held by other sessions at the time, and the rest were outside its declared file surface. They are recorded in the new gate'sSPECIFIER_DEBTledger so they cannot get worse; this card is to clear them.#4538remains the source of the analysis and is not addressed further here.The defect
Node's ESM resolver does not extension-search relative specifiers. A bare
tscnever rewrites import specifiers, so an extensionless./Fooin the source is an extensionless./Fooin the publisheddist, and importing the entry under plain Node fails withERR_MODULE_NOT_FOUND. Bundled consumers are unaffected, which is why everything is green today.Measured, 2026-08-18, on a full build of every published package
Specifier leg (
pnpm check:esm-specifiers) — packages whose build preserves specifiers:@object-ui/app-shell@object-ui/fields@object-ui/auth@object-ui/mobile@object-ui/collaboration@object-ui/permissions@object-ui/providersLoad leg (
pnpm check:node-esm-load) — 17 of 39 published ESM entries import and evaluate. The remaining 22 break down as:plugin-calendar,plugin-designer,plugin-grid,plugin-list,plugin-timelineandplugin-viewall die onpackages/mobile/dist/useBreakpoint;plugin-detail,plugin-form,plugin-ganttandplugin-kanbanonpackages/permissions/dist/PermissionProvider;plugin-reportonpackages/providers/dist/DataSourceProvider;.cssimport from a third-party dependency (plugin-dashboard,plugin-map) — a different question, ledgered separately asLOAD_DEBT;create-pluginis a bin-only CLI,runneris a built web app).So clearing these seven takes the repo from 17 to 35 of 39 loadable entries.
@object-ui/mobileat 27 specifiers and@object-ui/permissionsat 14 are the cheapest wins by a wide margin.The fix shape, already proven on four packages
./xbecomes./x.js; a directory import becomes./x/index.js). Resolve each one against the filesystem rather than pattern-matching — a specifier inside a comment must be left alone.module/moduleResolutiontonodenextin that package's owntsconfig.json, which makes a missing extension a compile error (TS2835/TS2834) instead of a review item. Done forpackages/reactin finding(react): the built dist emits extensionless relative imports, so plain Node ESM cannot load the published entry #4538.SPECIFIER_DEBTinscripts/check-node-esm-load.mjsin the same commit — the ledger is a ratchet and fails on a stale entry.⛔ Do not change
moduleResolutionin the roottsconfig.json. 38 packages extend it; a repo-wide flip is a much larger change and is not what this card is.@object-ui/app-shellat 1259 specifiers is large enough that it probably deserves its own card rather than riding along with the small ones.Generated by Claude Code