Skip to content

fix(app-shell): Home's activity card names each row's object by its label, through the bell's resolver (objectui#12238) - #12260

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-12238-home-activity-object-label
Oct 12, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-12238-home-activity-object-label

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #12238
Clause-②: no

Home's activity card printed each row's object by its API name (3 hours ago · crm_lead). It now renders the same ActivityObjectLabel the bell's Activity tab has rendered since objectui#12212, so both surfaces name an object one way: the label in the reader's language, the API name only as the fallback. One component, not a second resolver; nothing is copied into sys_activity.

Written by the os-dev run dispatched from the domain:ui seat 2, session https://claude.ai/code/session_01G5TSaEwbEQsKMjhzTB4rEd.

What changed

  • packages/app-shell/src/layout/ActivityObjectLabel.tsx (new). ActivityObjectLabel moves here out of InboxPopover.tsx: the same function body (now exported) and its docstring, with one paragraph added naming Home as the second consumer. Its private nonEmpty helper moves with it. ⛔ Not added to layout/index.ts or the package entry, so the published surface is unchanged.
  • layout/InboxPopover.tsx. Imports the component from the new module and drops the imports only it used (useObjectLabel, findByName, metadataText). Nothing else changes.
  • console/home/HomeRail.tsx, HomeActivity. The row's second line: FROM timeAgo(a.timestamp, displayLocale) · {a.objectName} TO the same time, then ActivityObjectLabel with objectName={a.objectName}. Two docstrings amended: HomeActivity now names the resolver, and HomeContinue's sentence that this module "does not itself load the metadata cache" now names the activity card's one read (the object list, only while a row is on screen), which this change would otherwise have made false.
  • .changeset/12238-home-activity-object-label.md: @object-ui/app-shell patch.

Measured before building

  • Location, by the package's own convention. layout/ already holds the activity and inbox modules that other directories import and the barrel leaves out: layout/activityItemType.ts (read by hooks/sharedUserFeeds.ts) and layout/inboxGrouping.ts (read by hooks/useHomeInbox.ts). console/home/ already imports from ../../layout/.
  • Providers. /home mounts HomeRoute inside ProtectedRoute, which wraps ConnectedShell, whose inner component mounts MetadataProvider. I18nProvider wraps App in apps/console/src/main.tsx. The bell already renders this component in the same subtree: HomeLayout mounts AppHeader variant="home", which mounts InboxPopover. Outside a provider, useMetadata and the two i18n hooks fall back without throwing; the existing HomeActivity.readingStates-12081 suite renders bare and stays green.
  • No third surface. layout/ActivityFeed.tsx renders no objectName and has no in-tree mount. The CommandPalette hit on objectName is a cmdk filter value, not display text.

Tests

New pin console/home/__tests__/HomeActivity.objectLabel-12238.test.tsx, shaped like the bell's InboxPopover.activityObjectLabel-12212.test.tsx: real HomeActivity, real I18nProvider, and a fixed MetadataCtx whose objects read is counted. Its cells:

  • en: crm_lead with a Lead definition reads Lead.
  • zh-CN: it reads 线索 from the bundle.
  • crm_gone, which has no definition and no bundle entry, reads crm_gone.
  • The summary renders as sent.
  • A card with no row reads no object list, and a card with rows reads it.

The bell's pin is unchanged, with no assertion edited, and it is green.

Ablation (direction written in the test header before the run)

The old line was planted back through ablation-replace.mjs: anchor hits went x1 → x0, replacement x0 → x1, blob 87321257e45f → dfa072c29798. Wrapped run of the Home pin:

× en: a business object is named by its label, not its API name       (expected 'crm_lead' to be 'Lead')
× zh-CN: the label comes from the object translation bundle             (expected 'crm_lead' to be '线索')
× a card with no row reads no object list; a card with rows reads it    (never read with rows on screen: expected 0 to be greater than 0)
Tests  3 failed | 2 passed (5)

The fallback and summary cells stayed green, as predicted. The restore is proven rather than assumed: the blob after restore equals the HEAD blob 87321257e45f, git diff HEAD is empty, and git status --porcelain prints 0 lines. The restored run of both pins: Tests 11 passed (11).

Local runs

At 3c8e2eb4, the code commit (HEAD 7217af89 adds only the changeset file):

  • Dependency closure: turbo run build --filter=@object-ui/app-shell^... gave 28/28 tasks, VERDICT command-exit 0.
  • vitest run over packages/app-shell/src/console/home/, packages/app-shell/src/layout/, chrome/KeyboardShortcutsDialog.wiredOnly-11674.test.tsx and hooks/__tests__/sharedInboxFeed.twoSurfaces.test.tsx: Test Files 84 passed (84), Tests 595 passed (595).
  • pnpm --filter @object-ui/app-shell type-check (tsc --noEmit && tsc -p tsconfig.test.json) exited 0. --listFiles on tsconfig.test.json lists the new test file (1 hit) and the bell's (1 hit).
  • pnpm --filter @object-ui/app-shell lint exited 0 with 0 errors. No warning falls on a line this PR adds; the one HomeRail.tsx warning is the pre-existing TFn any.

At 7217af89, these all exited 0: control-bytes, new-line-citations (0 new), vi-mock-inherit, vi-mock-specifiers, vi-mock-override-shape, test-path-roots, changeset-no-major, changeset-presence, changeset-claims, pending-changeset-literals, unreferenced-sources, phantom-deps, unused-deps, self-import, type-check:coverage, lint:coverage and i18n-keys.

Narrowing declared: the vitest set is the two directories plus the two tests outside them that import the bell or Home modules. The rest of pnpm test is CI's. NOT MEASURED locally:

  • check:eager-closure: it weighs a full apps/console production build, which is CI's Bundle Analysis job.
  • check:readme-exports: it refused on a prerequisite, unbuilt packages outside this closure. This PR touches no README or export.

Acceptance notes

  • nonEmpty now lives privately in three modules: hooks/useNavTargetLabel.ts, hooks/useRecentItemLabel.ts and layout/ActivityObjectLabel.tsx. That is the same count as before this PR, when the third copy was in InboxPopover.tsx. It is not consolidated here. Carrier: none.

Generated by Claude Code

…abel, through the bell's resolver (objectui#12238)

ActivityObjectLabel moves out of InboxPopover.tsx, unchanged in behaviour,
into layout/ActivityObjectLabel.tsx, which the bell and HomeActivity both
import. Not re-exported from any barrel or the package entry.

Claude-Session: https://claude.ai/code/session_01G5TSaEwbEQsKMjhzTB4rEd
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 71 chunks) 3129.2 KB 3204.6 KB
Main entry chunk (gzip) 73.1 KB 350 KB
Entry file index-ttcap9xZ.js —
Status PASS —

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 20.69KB 7.62KB
app-shell (runtime-config.js) 22.59KB 7.89KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.40KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.70KB 3.93KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 41.19KB 11.12KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.11KB 7.97KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.50KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 588.51KB 141.71KB
core (index.js) 10.18KB 4.04KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 244.49KB 68.27KB
fields (index.js) 280.00KB 71.39KB
i18n (LocalizationContext.js) 2.92KB 1.42KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.52KB 2.39KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 36.87KB 9.88KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 40.26KB 11.71KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 15.35KB 5.51KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.82KB 2.38KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.04KB 3.92KB
plugin-calendar (index.js) 54.31KB 15.86KB
plugin-charts (index.js) 84.72KB 23.27KB
plugin-chatbot (index.js) 201.72KB 48.07KB
plugin-dashboard (index.js) 144.20KB 38.95KB
plugin-designer (index.js) 233.77KB 50.02KB
plugin-detail (index.js) 251.02KB 66.27KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 178.42KB 46.28KB
plugin-gantt (index.js) 178.63KB 45.19KB
plugin-grid (index.js) 255.09KB 70.91KB
plugin-kanban (index.js) 53.23KB 16.71KB
plugin-list (index.js) 123.35KB 31.54KB
plugin-map (index.js) 27.24KB 9.03KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.12KB 12.29KB
plugin-timeline (index.js) 39.21KB 11.85KB
plugin-tree (index.js) 15.07KB 5.33KB
plugin-view (index.js) 92.11KB 23.27KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 12.07KB 3.68KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 120.63KB 39.56KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.50KB 2.06KB
react (schema-input.js) 4.31KB 2.07KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.07KB 1.30KB
sdui-parser (index.js) 7.30KB 3.12KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.81KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 23.87KB 7.83KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (cloud.js) 0.20KB 0.18KB
types (complex.js) 4.44KB 2.07KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 1.13KB 0.65KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 5.78KB 2.70KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (node-slots.js) 7.18KB 2.34KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.93KB 7.26KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.48KB 3.50KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

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

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 12, 2026 14:19
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 12, 2026
Merged via the queue into main with commit ee5c491 Oct 12, 2026
34 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-12238-home-activity-object-label branch October 12, 2026 14:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

app-shell: Home's activity card names each row's object by its API name (crm_lead), the defect objectui#12212 fixes in the bell

2 participants