Skip to content

Commit aec5f7b

Browse files
refactor(app-shell)!: retire the 54 root-entry exports that nothing outside the package names (#26219)
<!-- claude-projects-attribution: {"github_login":"os-steve"} --> _Requested by **Steve** · [project thread](https://claude.ai/code/project/chan_01FdL1XeUyvVNxLreh3F4Qi9?thread=cmsg_01FdL1XeUyvVNxLreh3F4Qi9WDHUTc91Ru3wKHsnWYaas9)_ Part of #25922 (step 1 only: the zero-reference exports and the architecture guide; the package split and the designer-strings migration stay with the card). Clause-②: yes (narrowing) (removes published exports from `@object-ui/app-shell`; the seat records a TIER_DEFAULT contract review before landing) Metadata-protocol: none ## What changes - `ui/packages/app-shell/src/index.ts` stops publishing 54 names that no file in this repository outside the package names. Every defining module stays; only the root entry changes. The entry goes from 261 names to 209 (`main` added `InvitationSignUpPrompt` and `isDefaultProductName` meanwhile). One comment count in the entry follows (`11 TYPE-ONLY re-exports` is now 9). - `ui/docs/app-shell-extraction-guide.md` is rewritten to describe the package that ships: directory sizes, the groups of names the entry publishes, its load-time registrations, its dependencies and peer dependencies, and its three consumers here (`apps/console`, `examples/console-starter`, `examples/byo-backend-console`). The six compiled `tsx` usage blocks are kept byte for byte. - `ui/packages/app-shell/src/chrome/toast-helpers.ts`: its usage docblock imported `toastWithUndo` from `@object-ui/app-shell`, which this change makes false; it now names the module. - `.changeset/25922-app-shell-retire-unreferenced-exports.md`: `patch`, a **BREAKING** banner, a FROM → TO line for every retired name and the ADR-0087 marker (see Acceptance notes: that gate is red). ## How "zero references" was measured (main `fbb75998`) 1. Every name the root entry exports, read from `src/index.ts` with its `as` aliases resolved: 261 names (the card counted 262 at `7981384`). 2. For each name: `git grep -l -w -F NAME -- ui packages apps ':!ui/packages/app-shell/'`. Zero files means zero references. This counts every tracked file of every kind: code, tests, docs, changelogs, ADRs. 3. Positive control: `SchemaRenderer` is named in 1,088 files outside the package. 4. Result: 57 names with zero hits. Three are kept because the package's own README imports them in its examples, and `ui/scripts/check-readme-exports.mjs` reds when a README imports a missing export: `SignUpOffer`, `RuntimeBranding`, `studioOrgScopePath`. The other 54 are retired. 5. Over the whole tree instead of `ui/ packages/ apps/` the count is 56: `AssistantEditorContext` is also named in `docs/adr/0037-live-canvas-draft-preview.md`. It is retired, because the ADR names the module path (`app-shell/src/assistant/assistantBus.ts`), and that module still exports it. ## Removed from the root entry (54) - `src/providers/ExpressionProvider`: `useExpressionContext`, `ExpressionContextValue` (type) - `src/hooks/useUrlOverlay`: `UseUrlOverlayOptions` (type), `UrlOverlayControls` (type) - `src/hooks/useSettleSignal`: `SettleSignalState` (type) - `src/observability/settleSignal`: `isIdle`, `ObjectUiGlobal` (type) - `src/hooks/useRecentItems`: `RecentItemInput` (type), `RecentTextItem` (type) - `src/hooks/useRecentItemLabel`: `RecentItemLabelResolver` (type) - `src/utils/index`: `isOverrideOnlyViewer`, `actionAdmittedByOverride`, `bypassedApproverNames`, `DeclaredHomeApp` (type) - `src/hooks/useAiSurface`: `AiSurfaceState` (type) - `src/layout/index`: `PreviewBadgeProps` (type) - `src/chrome/index`: `RedirectWithSplashProps` (type), `toastWithUndo`, `ToastWithUndoOptions` (type) - `src/runtime-config`: `getCloudBase`, `getBrandColor`, `isRuntimeConfigInitialised`, `RuntimeFeatures` (type) - `src/views/index`: `RecordFormPageProps` (type), `DeclaredActionsBarProps` (type) - `src/hooks/index`: `addNavigationItem`, `removeNavigationItems`, `renameNavigationItems`, `navigationEqual`, `generateNavId` - `src/context/index`: `CommandPaletteContextValue` (type) - `src/console/auth/signUpOffer`: `SignUpOfferContext` (type) - `src/hooks/useChatConversation`: `HydratedUIMessage` (type) - `src/services/componentRegistry`: `listAppComponents`, `urlSegmentsToComponentRef`, `AppComponentRegistryEntry` (type) - `src/views/metadata-admin/PageShell`: `MetadataPageShell` (alias of `PageShell`) - `src/views/metadata-admin/registry`: `listMetadataResources` - `src/views/metadata-admin/useMetadata`: `useMetadataTypes`, `useTypesIndex`, `matchesQuery` - `src/views/metadata-admin/preview-registry`: `MetadataPreviewProps` (type) - `src/views/metadata-admin/inspector-registry`: `MetadataInspectorProps` (type) - `src/views/studio-design/StudioDesignSurface`: `StudioDesignSurfaceProps` (type) - `src/views/studio-design/studio-canvas-preview`: `getStudioCanvasPreview`, `listStudioCanvasPreviewTypes`, `StudioObjectRecordsCanvas`, `StudioCanvasPreview` (type), `StudioCanvasPreviewProps` (type) - `src/assistant/assistantBus`: `useAssistant`, `useRegisterAssistantEditor`, `requestAssistantOpen`, `AssistantEditorContext` (type), `AssistantEditorField` (type) ## Tests **Final head `41109b83`** (merge of `main` `46255b19`, which includes the gate fix #26319; no conflicts). On it: Console build 71/71 (VERDICT command-exit 0, tree clean); the full dogfood battery, closure 67/67 then 297 files passed / 3 skipped, 2527 tests passed / 18 skipped (VERDICT command-exit 0); CI `Test UI` 1–16/16, Type Check UI, Lint UI, Build & E2E UI and Check Changeset all success. None of the 54 names gained an outside reference on the new `main` (re-measured). Earlier runs, on head `5bf229f6`: - `pnpm exec turbo run build --filter='@object-ui/app-shell^...' --concurrency=2`: 64/64 tasks, lock VERDICT command-exit 0. - `pnpm --filter @object-ui/app-shell build && pnpm --filter @object-ui/app-shell type-check` (both `tsc --noEmit` and `tsc -p tsconfig.test.json`): VERDICT command-exit 0, 0 `error TS`. `dist/index.d.ts` no longer names `toastWithUndo` or `useAssistant`. - Narrowed vitest run: 14 app-shell test files that import or read the root entry (found by grepping the package's tests for the root `index` specifier and for `src/index.ts`), plus `product-neutral-renderer.ratchet.test.ts`: 14 files, 86 tests passed. `spec-symbol-parity.test.ts` and the console's `createdRecordPath.test.ts`, which reads `app-shell/src/index`: 2 files, 57 tests passed. The full app-shell suite is left to CI `Test UI`. - The migration lines were compiled. A scratch `.ts` imports from the built `dist/index.d.ts` and asserts that each of the 22 FROM → TO derivations in the changeset is a real type, not `any` and not `never`: `tsc` exit 0. The control file imports `toastWithUndo` and `SettleSignalState` and fails with `TS2305 ... has no exported member` twice, as the changeset says an importer will. - `pnpm exec turbo run build --filter=@object-ui/console --concurrency=2`: 71/71 tasks, VERDICT command-exit 0. The tree was clean afterwards, so the sdui record did not move (app-shell is outside the record). ## Gates - `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` on `41109b83`: 29 commands, all exit 0, including `node scripts/check-adr-0087-registration.mjs --base origin/main` (`runtime-export-retired` verified for all 54 operands, after #26319). `--ran`: 29 run, 0 NOT MEASURED. - `node scripts/check-platform-checklist.mjs --changed-from origin/main`: exit 0 (0 anchored files in the change set). - `ui/scripts/check-doc-links.mjs`: exit 0. The links in the rewritten guide resolve. - `ui/scripts/check-readme-exports.mjs`: exit 1, but only on 72 self-imports of packages outside app-shell's build closure that this container did not build (`cli`, `plugin-ai`, `plugin-gantt`, `plugin-map`, …). No app-shell README line is among them. CI runs it on a full build. - `ui/scripts/check-doc-snippet-types.mjs`: NOT MEASURED locally, because it needs nearly every ui package built. The guide's six `tsx` fences are byte-identical to main (`cmp` over the extracted fences), and the names they import (`AppShell`, `MinimalAppShellProps`) stay exported. CI runs it. - Full dogfood battery (owed because of the `!` in the title): measured on the final head `41109b83`, VERDICT command-exit 0 (see Tests). ## Acceptance notes - **ADR-0087 gate: green since #26319** (the gate now reads the ui workspace roots and `.tsx` declarations). History: before that fix it was red, and it was the gate's gap, not this diff's. The disposition that fits is `not-required (runtime-export-retired @object-ui/app-shell#NAME, ...)`. The gate refuses all 54 operands at predicate 1 with "no workspace manifest at fbb7599 is named `@object-ui/app-shell`": `PACKAGE_ROOTS` in `scripts/check-adr-0087-registration.mjs` is `['packages', 'apps', 'examples']`, while `pnpm-workspace.yaml` also lists `ui/packages/*`, `ui/apps/*` and `ui/examples/*`. A local probe that added the three `ui/` roots (restored afterwards, `git diff HEAD` empty) took predicate 1 to green for all 54, and left 16 refused at predicate 2 ("the declaration of NAME cannot be located at the merge base"): aliases (`MetadataPageShell`), shim re-exports (`RecentItemInput`, `RecentTextItem`) and `.tsx` declarations (`PreviewBadgeProps`, `RecordFormPageProps`, `StudioDesignSurfaceProps`, …). No other disposition fits honestly: `no-migration-prescription` would hold only on a detector miss, because the body prescribes 54 rewrites. Fixing the gate is outside this card's file surface; the seat decides how to route it. - `toastWithUndo` and `ToastWithUndoOptions` have no caller inside the package either, so `chrome/toast-helpers.ts` is now dead code. It is left in place, because the card retires exports, not modules. - Some retired types describe names the entry still exports, for example `MetadataPreviewProps` for `registerMetadataPreview` and `StudioCanvasPreviewProps` for `registerStudioCanvasPreview`. They are retired because the card's rule is "no caller, retire". The changeset gives each a compiled derivation from the name that stays. - Consumers outside this repository (cloud, hotcrm, npm) were not measured. - `docs/ARCHITECTURE.md` in the card does not exist on main under `ui/`. The file the card quotes ("Minimal application rendering engine", five exports, "~50KB") is `ui/docs/app-shell-extraction-guide.md`, which calls itself the architecture guide. That file is the one rewritten here, and it keeps its name because `ui/scripts/markdown-test-inputs.mjs` and `check-doc-snippet-types.test.ts` list it. --- _Generated by [Claude Code](https://claude.ai/code/session_012zuvAzwT4oemWPhAR81wRm)_ --- _Generated by [Claude Code](https://claude.ai/code)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 3db7bbf commit aec5f7b

4 files changed

Lines changed: 222 additions & 226 deletions

File tree

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
'@object-ui/app-shell': patch
3+
---
4+
5+
refactor(app-shell)!: retire the 54 root-entry exports that nothing outside the package names
6+
7+
`@object-ui/app-shell`'s root entry published 261 names. 57 of them appear in no file of this repository outside `ui/packages/app-shell/` (the measure covers `ui/`, `packages/` and `apps/`); three of those are taken by the package's own README examples and stay (`SignUpOffer`, `RuntimeBranding`, `studioOrgScopePath`). The other 54 leave the entry. Every module that defines them stays, and code inside the package keeps importing them from there; only the package entry stops publishing them. The entry now publishes 209 names (207, plus `InvitationSignUpPrompt` and `isDefaultProductName`, which main added meanwhile).
8+
9+
Clause-②: yes (narrowing)
10+
Metadata-protocol: none
11+
12+
<!-- adr-0087: not-required (runtime-export-retired @object-ui/app-shell#useExpressionContext, @object-ui/app-shell#UseUrlOverlayOptions, @object-ui/app-shell#UrlOverlayControls, @object-ui/app-shell#SettleSignalState, @object-ui/app-shell#isIdle, @object-ui/app-shell#ObjectUiGlobal, @object-ui/app-shell#ExpressionContextValue, @object-ui/app-shell#RecentItemInput, @object-ui/app-shell#RecentTextItem, @object-ui/app-shell#RecentItemLabelResolver, @object-ui/app-shell#isOverrideOnlyViewer, @object-ui/app-shell#actionAdmittedByOverride, @object-ui/app-shell#bypassedApproverNames, @object-ui/app-shell#DeclaredHomeApp, @object-ui/app-shell#AiSurfaceState, @object-ui/app-shell#PreviewBadgeProps, @object-ui/app-shell#RedirectWithSplashProps, @object-ui/app-shell#toastWithUndo, @object-ui/app-shell#ToastWithUndoOptions, @object-ui/app-shell#getCloudBase, @object-ui/app-shell#getBrandColor, @object-ui/app-shell#isRuntimeConfigInitialised, @object-ui/app-shell#RuntimeFeatures, @object-ui/app-shell#RecordFormPageProps, @object-ui/app-shell#DeclaredActionsBarProps, @object-ui/app-shell#addNavigationItem, @object-ui/app-shell#removeNavigationItems, @object-ui/app-shell#renameNavigationItems, @object-ui/app-shell#navigationEqual, @object-ui/app-shell#generateNavId, @object-ui/app-shell#CommandPaletteContextValue, @object-ui/app-shell#SignUpOfferContext, @object-ui/app-shell#HydratedUIMessage, @object-ui/app-shell#listAppComponents, @object-ui/app-shell#urlSegmentsToComponentRef, @object-ui/app-shell#AppComponentRegistryEntry, @object-ui/app-shell#MetadataPageShell, @object-ui/app-shell#listMetadataResources, @object-ui/app-shell#useMetadataTypes, @object-ui/app-shell#useTypesIndex, @object-ui/app-shell#matchesQuery, @object-ui/app-shell#MetadataPreviewProps, @object-ui/app-shell#MetadataInspectorProps, @object-ui/app-shell#StudioDesignSurfaceProps, @object-ui/app-shell#getStudioCanvasPreview, @object-ui/app-shell#listStudioCanvasPreviewTypes, @object-ui/app-shell#StudioObjectRecordsCanvas, @object-ui/app-shell#StudioCanvasPreview, @object-ui/app-shell#StudioCanvasPreviewProps, @object-ui/app-shell#useAssistant, @object-ui/app-shell#useRegisterAssistantEditor, @object-ui/app-shell#requestAssistantOpen, @object-ui/app-shell#AssistantEditorContext, @object-ui/app-shell#AssistantEditorField) No metadata moves: no spec key, authorable spelling, object definition or stored shape is added, removed, renamed or re-shaped, so there is nothing for `objectstack migrate meta` to rewrite. What retires is 54 names of `@object-ui/app-shell`'s published entry that no file in this repository outside the package names. The affected party is a TypeScript importer, and the compiler at that import delivers the break. -->
13+
14+
**BREAKING** (an export retirement), shipped as `patch`: no metadata protocol kind moves. An importer of a retired name gets `TS2305` ("has no exported member") at its import line.
15+
16+
Migration. A retired type that describes a name the entry still exports is derived from that name; everything else has no replacement on the entry.
17+
18+
- FROM `UseUrlOverlayOptions` TO `Parameters<typeof useUrlOverlay>[1]`.
19+
- FROM `UrlOverlayControls` TO `ReturnType<typeof useUrlOverlay>`.
20+
- FROM `SettleSignalState` TO `ReturnType<typeof useSettleSignal>`.
21+
- FROM `AiSurfaceState` TO `ReturnType<typeof useAiSurfaceEnabled>`.
22+
- FROM `CommandPaletteContextValue` TO `ReturnType<typeof useCommandPalette>`.
23+
- FROM `RecentItemInput` TO `Parameters<ReturnType<typeof useRecentItems>['addRecentItem']>[0]`.
24+
- FROM `RecentTextItem` TO `Extract<RecentItem, { label: string }>`.
25+
- FROM `RecentItemLabelResolver` TO `ReturnType<typeof useRecentItemLabel>`.
26+
- FROM `DeclaredHomeApp` TO `NonNullable<Parameters<typeof resolveDeclaredHomePath>[0]>[number]`.
27+
- FROM `RuntimeFeatures` TO `AppShellRuntimeConfig['features']`.
28+
- FROM `SignUpOfferContext` TO `Parameters<typeof decideSignUpOffer>[1]`.
29+
- FROM `HydratedUIMessage` TO `ReturnType<typeof toUIMessages>[number]`.
30+
- FROM `AppComponentRegistryEntry` TO `Parameters<typeof registerAppComponent>[0]`.
31+
- FROM `MetadataPreviewProps` TO `ComponentProps<MetadataPreview>` (`ComponentProps` from `react`).
32+
- FROM `MetadataInspectorProps` TO `ComponentProps<MetadataInspector>`.
33+
- FROM `StudioCanvasPreview` TO `Parameters<typeof registerStudioCanvasPreview>[1]`.
34+
- FROM `StudioCanvasPreviewProps` TO `ComponentProps<Parameters<typeof registerStudioCanvasPreview>[1]>`.
35+
- FROM `StudioDesignSurfaceProps` TO `ComponentProps<typeof StudioDesignSurface>`.
36+
- FROM `PreviewBadgeProps` TO `ComponentProps<typeof PreviewBadge>`.
37+
- FROM `RedirectWithSplashProps` TO `ComponentProps<typeof RedirectWithSplash>`.
38+
- FROM `RecordFormPageProps` TO `ComponentProps<typeof RecordFormPage>`.
39+
- FROM `DeclaredActionsBarProps` TO `ComponentProps<typeof DeclaredActionsBar>`.
40+
- FROM `useExpressionContext`, `ExpressionContextValue`, `isIdle`, `ObjectUiGlobal`, `isOverrideOnlyViewer`, `actionAdmittedByOverride`, `bypassedApproverNames`, `toastWithUndo`, `ToastWithUndoOptions`, `getCloudBase`, `getBrandColor`, `isRuntimeConfigInitialised` TO nothing (no replacement on the entry).
41+
- FROM `addNavigationItem`, `removeNavigationItems`, `renameNavigationItems`, `navigationEqual`, `generateNavId` TO nothing (no replacement on the entry).
42+
- FROM `listAppComponents`, `urlSegmentsToComponentRef` TO nothing (no replacement on the entry): `getAppComponent` and `componentRefToUrlSegments` stay.
43+
- FROM `MetadataPageShell`, `listMetadataResources`, `useMetadataTypes`, `useTypesIndex`, `matchesQuery` TO nothing (no replacement on the entry): `getMetadataResource`, `useMetadataClient` and `useGlobalDiagnostics` stay.
44+
- FROM `getStudioCanvasPreview`, `listStudioCanvasPreviewTypes`, `StudioObjectRecordsCanvas` TO nothing (no replacement on the entry): `registerStudioCanvasPreview` stays.
45+
- FROM `useAssistant`, `useRegisterAssistantEditor`, `requestAssistantOpen`, `AssistantEditorContext`, `AssistantEditorField` TO nothing (no replacement on the entry): `assistantBus` stays.
46+
47+
`ui/docs/app-shell-extraction-guide.md`, the package's architecture guide, is rewritten to describe the package that ships: what each directory holds, the groups of names the entry publishes, its load-time registrations, its dependencies, and its three consumers in this repository.

0 commit comments

Comments
 (0)