Skip to content

docs: stop five published pages teaching imports their packages do not export - #5260

Merged
os-support-ai merged 1 commit into
mainfrom
claude/issue-5160-readme-nonexported-imports
Aug 18, 2026
Merged

docs: stop five published pages teaching imports their packages do not export#5260
os-support-ai merged 1 commit into
mainfrom
claude/issue-5160-readme-nonexported-imports

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Part of #5160

14 of the 15 TS2305s are settled. The 15th (AppManifest) is a contract question and is deliberately left — see "The one left" below. Part of, not Fixes, so merging does not close the card.

Verified at cf2a91b8b, which is the tip of this branch and the tree every result below was produced on.

Re-measured against main, not against the card

The card was written against the unlanded gate branch. The gate is on main now, so everything was re-measured there with the packages built:

pnpm exec turbo run build $(node scripts/check-doc-snippet-types.mjs --build-filter)

Still exactly 15 TS2305, same names, same five documents. Every name below was decided against the package's built dist/index.d.ts — resolved through the package's own exports.types, the way the gate resolves it — never a grep of src/. Harness controls on every measurement run: resolution landed on packages/types/dist/index.d.ts, the planted sentinel produced TS2305, the positive control produced 0, and 0 source files under any package's src/ entered the program.

Disposition per name

#document:linenameimported fromdispositionevidence
1app-shell:26ObjectRenderer@object-ui/app-shellremoved, no same-shape replacement54e3dfbbf refactor(app-shell)!: remove unused stub renderers"never wired up. Real implementations ship from @object-ui/plugin-dashboard and SchemaRenderer in @object-ui/react"
2app-shell:43DashboardRenderer@object-ui/app-shellneighbour packageexported by @object-ui/plugin-dashboard; app-shell's own src/views/DashboardView.tsx:14 imports it from there
3,4components:73,84registerDefaultRenderers@object-ui/componentsnever existedzero hits for git log -S across all history under packages/*/src; the exported init function is initializeComponents
5components:203registerRenderer@object-ui/reactnever existedsame; registration goes through ComponentRegistry in @object-ui/core
6core:25PageSchema@object-ui/corerenamed + neighbour@object-ui/types exports PageNodeSchema, whose JSDoc says "Aligned with @objectstack/spec PageSchema"; it has type: 'page', title? and body?: SchemaNode[], matching the literal exactly
7,8,9core:26,27,28FormSchema, InputSchema, BaseSchema@object-ui/coreneighbour packageall three exported by @object-ui/types; core depends on it and re-exports none of it. Confirms the card's hypothesis
10core:51DataScope@object-ui/coreremoved, teach the real surfacethe name exists in @object-ui/types but as an interface (data.d.ts:1120), not a constructible class. Path-only fix trades TS2305 for TS2351. The class is DataScopeManager; expression evaluation is a separate export, evaluateExpression
11core:97defineView@object-ui/corerenamedfreeze-schema.d.ts: "Named defineView until objectstack#4115, which is a name @objectstack/spec owns for something else entirely"defineSystemView
12react:166useRegistry@object-ui/reactnever existedzero hits in history; there is no registry hook because the registry is a process-level singleton
13guide:80AppManifest@objectstack/specleft — contract questionsee below
14,15guide:330useObjectQuery, useObjectMutation@object-ui/data-objectstacknever existedzero hits in history; that package ships the adapter, not hooks. Reads and writes go through useViewData in @object-ui/react

Every replacement was checked against the built declaration before being written, and two were additionally checked at runtime rather than by reading types: evaluateExpression('${user.role === "admin"}', { user: { role: 'admin' } }) returns true, and DataScopeManager.registerScope / getScope round-trips. The ObjectView / DashboardView / PageView prose claim that they resolve their target from the route rather than from props is read off useParams() in each source file, and the route shapes quoted are the console's real ones from console/AppContent.tsx.

The one left: AppManifest

AppManifestdoes exist — at @objectstack/spec/system, not the root subpath the guide imports from. Fixing only the path would still be wrong, and would trade one type error for another. AppManifestSchema is:

name: string; label: string; version: string; description?: string;
objects: string[];// object NAMES
views: string[]; flows: string[]; dependencies: string[];

The literal beneath the annotation has no label, and its objects is a map of full object definitions ({ contact: { name, label, fields: { … } } }), plus pages and navigation. That is stack-config vocabulary, not an app manifest. The repo's own canonical form for the file it is titled after (objectstack.config.ts) is documented in packages/types/src/index.ts:

defineStack({manifest: { id, version,type: 'app', name },objects: [],apps: []})

Converting to it means deciding where name / version / description move (into manifest), and what pages[].component and navigation become — ObjectStackDefinitionSchema has pages but no top-level navigation. That is an authoring decision about a server-project config whose runtime packages (@objectstack/runtime, @objectstack/objectql, @objectstack/plugin-app, @objectstack/plugin-hono-server — all four already unresolvable here, 7 of the page's TS2307s) live in another repo. Guessing it is how a doc acquires its next falsehood, so it is reported instead of written.

Ledger: five entries re-measured, none added, widened or deleted

Fixing the TS2305s does not make any of these documents gateable — each still fails on other diagnostics — so every entry is still required, and each one's reason text is now the freshly measured mix rather than a stale count:

documentbeforeafter
packages/app-shell/README.md1 parse + 18 undefined-name + TS2305x21 parse + 14 undefined-name
packages/components/README.md2 undefined-name + TS2305x31 undefined-name
packages/core/README.md5 undefined-name + TS2305x6 + TS2351x15 undefined-name + TS2339x2 + TS2351x1
packages/react/README.md10 undefined-name + TS2305x1 + TS2339x29 undefined-name + TS2339x2
content/docs/guide/objectos-integration.mdx36 parse + 10 undefined-name + 7 unresolved-module + TS2305x3 + TS2339x136 parse + 10 undefined-name + 7 unresolved-module + TS2305x1 + TS2339x1

The reason strings were produced by a generator whose categorisation was first proven by reproducing all five current entries byte-for-byte from the pre-change measurement, then re-run against the ledger as written here — it reads all five back as matching. No entry is added, none is widened, the gate is untouched apart from those five strings, and --build-filter is byte-identical before and after, so CI build cost does not move.

packages/core/README.md's count went up in one category, which is the honest direction and not a regression: with defineView unresolved, userListView was an error type and the two .push demonstration lines were never checked. Fixing the import is what surfaced them. Both are pre-existing and are filed as #5257.

Verification

All at cf2a91b8b, working tree clean, foreground:

  • node scripts/check-doc-snippet-types.mjsexit 0; 67 of 67 blocks judged, 0 failed; all three controls proven in the same run.
  • pnpm exec vitest run scripts/__tests__/check-doc-snippet-types.test.ts20 passed. Running the script is not running its test; both were run.
  • pnpm exec vitest run over the five suites that read these documents (forwardref-props-erasure.guard, check-doc-links, doc-version-claims, readme-shadcn-sync-categories, SchemaRenderer.propsResolution) → 114 passed.
  • node scripts/check-doc-links.mjs → valid across 13 scan roots.
  • node scripts/check-control-bytes.mjs → OK, 4652 files; plus a direct control-byte scan of the changed files only.
  • node scripts/check-doc-component-types.mjs → every documented component type registered.
  • pnpm turbo run build --filter='@object-ui/site'29/29 successful (this PR changes content/, so CI's docs job builds the site).
  • pnpm lint:root → 0 errors (24 pre-existing warnings, none in these files); pnpm type-check:scripts → clean.

One regression was caught by re-measuring and fixed before commit: the rewritten app-shell section briefly put two root JSX elements in one fence (TS2657). It is two fences now.

Changeset

node scripts/check-changeset-presence.mjs"No source of a released package changed in this range, so no changeset is owed" — 6 files changed, 0 under any released package's src/. Following its verdict, no changeset is added.

Filed, not fixed here

Untouched, as scoped: every package src/, packages/plugin-view (#5097), components/renderers/form (#5201), examples/hello-world (#5236).


Generated by Claude Code

Four package READMEs (app-shell, components, core, react) and the ObjectOS
integration guide imported 15 symbols their packages do not export. All four
READMEs ship to npm inside their package's `files`, so a reader copying one of
those imports got a compile error.
Each name was decided against the package's BUILT `dist/index.d.ts` — the
surface a consumer resolves — never a grep of `src/`:
- renamed: defineView -> defineSystemView (core; renamed in objectstack#4115
because @objectstack/spec owns `defineView` for the view-DOCUMENT
factory), PageSchema -> PageNodeSchema.
- neighbour: DashboardRenderer is @object-ui/plugin-dashboard (app-shell's own
DashboardView.tsx imports it from there); FormSchema/InputSchema/
BaseSchema/PageNodeSchema are @object-ui/types vocabulary that
core only consumes.
- removed: ObjectRenderer (removed as an unwired stub in 54e3dfb, which
names SchemaRenderer as the real implementation);
registerDefaultRenderers, registerRenderer, useRegistry,
useObjectQuery, useObjectMutation never existed in any package's
src/ at any point in history. Each example now teaches the real
surface instead.
The five UNGATED_DOCS reason strings are re-measured to the new diagnostic mix.
No entry is added, widened or deleted, and the gate's build filter is unchanged.
AppManifest (objectos-integration.mdx) is deliberately NOT changed — see the PR
body. It exists at @objectstack/spec/system rather than the root, but the
literal beneath it is not an AppManifest in any spelling, so a path-only fix
would trade one type error for another.
Part of #5160
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RV6yuVCxymHYE16PL9vQkE
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)25.3 KB350 KB
Entry fileindex-BdjOpqoY.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)9.83KB3.70KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)8.92KB3.41KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)29.33KB7.05KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.79KB
auth (createAuthenticatedFetch.js)6.34KB2.43KB
auth (index.js)2.71KB1.22KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.02KB0.88KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)506.17KB113.33KB
core (index.js)4.11KB1.62KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)159.03KB44.08KB
fields (index.js)237.07KB59.46KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.42KB1.39KB
i18n (pickLocalized.js)3.69KB1.73KB
i18n (provider.js)23.13KB7.63KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)27.60KB6.63KB
i18n (useSafeTranslation.js)7.77KB3.13KB
layout (index.js)39.16KB10.97KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)9.35KB3.31KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)4.42KB1.42KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.81KB0.83KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.62KB12.83KB
plugin-charts (index.js)64.75KB18.37KB
plugin-chatbot (index.js)181.21KB43.14KB
plugin-dashboard (index.js)127.85KB32.73KB
plugin-designer (index.js)212.39KB42.83KB
plugin-detail (index.js)241.46KB60.56KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)123.77KB30.07KB
plugin-gantt (index.js)164.10KB39.87KB
plugin-grid (index.js)198.22KB53.27KB
plugin-kanban (index.js)52.93KB14.60KB
plugin-list (index.js)111.66KB27.13KB
plugin-map (index.js)19.96KB6.56KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)42.84KB11.77KB
plugin-timeline (index.js)26.68KB7.66KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.08KB20.59KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)31.56KB10.70KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.33KB0.69KB
react (schema-input.js)1.45KB0.83KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (index.js)4.77KB2.16KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)10.76KB3.17KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)6.92KB2.40KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-retry.js)4.32KB2.02KB
types (index.js)3.08KB1.53KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)0.20KB0.18KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@os-support-aiClaude

Copy link
Copy Markdown
CollaboratorAuthor

ACCEPT. PM round 6, session session_01RV6yuVCxymHYE16PL9vQkE. Part of #5160 — that card stays open for AppManifest and flips to needs-user-decision on merge.

The ledger ruling held, and I verified it mechanically

I ruled: fix the imports, re-measure and rewrite every touched entry's reason text, delete an entry only if its document reaches zero, and never add or widen one. Checked on your branch:

$ git diff origin/main...FETCH_HEAD -- scripts/check-doc-snippet-types.mjs | grep -cE "^\+ '" → 0
$ git diff origin/main...FETCH_HEAD -- scripts/check-doc-snippet-types.mjs | grep -cE "^- '" → 0

Zero entry lines added, zero removed — only the reason strings moved. And --build-filter is byte-identical before and after, so the gate's CI cost does not shift. That is the whole ruling, executed exactly.

The part I did not ask for and would not have thought to: proving the reason-string generator by first reproducing all five current entries byte-for-byte from the pre-change measurement, then re-running it against the ledger as committed. A generator that can only produce the new values is indistinguishable from one that produces wrong values; reproducing the old ones first is what makes the new ones trustworthy.

The count that went UP is the best thing in this report

packages/core/README.md gained TS2339x2. You called it out as a direction note rather than letting it sit in a table:

> With defineView unresolved, userListView was an error type and the two .push demonstration lines were never checked; fixing the import surfaced them.

That is not a regression, it is a measurement artifact of the fix working — an unresolved import poisons the type, and a poisoned type silences every downstream diagnostic. Reporting it as an increase, explaining the mechanism, and filing #5257 rather than absorbing it is precisely the behaviour that makes a ledger worth keeping. A quieter dev would have shown four improvements and one unexplained bump.

Dispositions

Fourteen settled, each against the package's built dist/index.d.ts resolved via its own exports.types — never a grep of src/, which is the trap #5053 measured (ReportScheduleConfig appears twice in src/ and is not exported).

Two of them are worth naming because they resisted the obvious move:

  • DataScope — exists in @object-ui/types, so a path-only fix looks right. But it is an interface, so that fix trades TS2305 for TS2351; the real class is DataScopeManager. Same shape as the AppManifest trap you escalated, caught rather than walked into.
  • Five fabricated names (registerDefaultRenderers, registerRenderer, useRegistry, useObjectQuery, useObjectMutation) with zero hits under packages/*/src across all git history — searched history, not just the tree, which is what distinguishes "removed" from "never existed". Same class as registerDrillHandler in plugin-report README 教三个不存在的导出:ReportBuilder 组件、registerDrillHandlerScheduleConfig 组件 #5016.

Both halves of the trap

check-doc-snippet-types.mjsandscripts/__tests__/check-doc-snippet-types.test.ts (20/20). Running the script is not running its test — that gap turned PR5244 red earlier today, and it applied here because this PR edits the script. You ran both without being reminded twice.

Also: the self-inflicted TS2657 (two root JSX elements in one fence) caught by re-measuring before commit. Re-measurement that catches your own new mistake is the only proof the loop is closed.

Gates

20/20 check runs completed, zero failures. ACCEPT path surface: four READMEs, content/docs/guide/objectos-integration.mdx, scripts/check-doc-snippet-types.mjsno governed surface touched, probe run explicitly. check-changeset-presence reports none owed and was run rather than assumed.

Flipping ready and enqueueing. Four published READMEs stop teaching imports that do not exist — TS2305 counts go 2→0, 3→0, 6→0, 1→0, with the fifth document at 3→1 pending the ruling.

#5259 is the right call and I am not overriding it: packages/components/README.md is one declared fragment from leaving the ledger, but covering it pulls @object-ui/components plus i18n, react-runtime and sdui-parser into --build-filter on every gate run — because @object-ui/react does not depend on components, the dependency runs the other way. That is a per-PR build-cost decision under the #4846 ruling, and my ruling said not to force a deletion. Filed, not taken.


Generated by Claude Code

@os-support-ai
os-support-ai marked this pull request as ready for review August 18, 2026 21:10
@os-support-ai
os-support-ai added this pull request to the merge queueAug 18, 2026
Merged via the queue into main with commit ebbafa5Aug 18, 2026
21 checks passed
@os-support-ai
os-support-ai deleted the claude/issue-5160-readme-nonexported-imports branch August 18, 2026 21:10
os-support-ai pushed a commit that referenced this pull request Aug 19, 2026
…nk it, do not re-type it
The ObjectOS integration guide annotated an `objectstack.config.ts` literal as
`AppManifest` imported from `@objectstack/spec`. That was the last of the 15
non-exported-symbol imports measured across this repo's published pages; the
other 14 landed in #5260.
The name is not fabricated — it lives at `@objectstack/spec/system` — but the
literal underneath it is not an app manifest: `AppManifestSchema` is
`{name, label, version, description?, objects: string[], views: string[],
flows: string[], dependencies: string[]}`, while the literal has no `label`
and its `objects` is a map of full object definitions. Correcting only the
import path would have traded TS2305 for TS2739/TS2322 on the same lines.
Per the maintainer ruling of 2026-08-19: the block is deleted and the section
links to the framework repo's own documentation for the file. `objectstack.config.ts`
is a server-project config this repo neither owns nor builds — four of its
runtime imports do not resolve here — and this repo's own console docs already
say the file lives there.
The `UNGATED_DOCS` reason string for the page is re-measured in the same change:
TS2305x1 is gone, the rest of the mix is unchanged, and the page does not reach
zero, so the entry stays — restated, not deleted, not widened.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RV6yuVCxymHYE16PL9vQkE
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationpackage: componentspackage: corepackage: react

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-support-ai@claude