Skip to content

fix(app-shell,plugin-chatbot,i18n): AI build surface UX — land on the running app, a task-named composer, one usage meter, a gauge that is not a spinner, a localized scope chip (objectui#11658) - #11662

Merged
hotlong merged 5 commits into
mainfrom
claude/issue-11658-ai-build-surface-ux
Oct 6, 2026
Merged

hotlong merged 5 commits into
mainfrom
claude/issue-11658-ai-build-surface-ux

Conversation

@hotlong

@hotlong hotlong commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

Fixes #11658

This fixes the five AI build surface items from the 2026-10-05 cloud acceptance run (the objectui half of cloud#2627, cloud#2634 and cloud#2435 item 8). Each item can be accepted on its own. The rulings on the card were applied as written.

What changed, per item

  1. After the first AI build, the user lands on the running app.
    • The post-build jump starts in objectui, not in cloud. ChatPane's built-moment transition navigates to /studio/PKG/interfaces. The ?surface=dashboard:NAME part is added afterwards by the Interfaces pillar's useSurfaceDeepLink mirror when it auto-opens the first nav leaf. The cloud build envelope supplies only the package id.
    • The transition now passes router state, STUDIO_RUN_LANDING from the new studioLanding.ts. The Interfaces pillar reads it once, at mount. It opens the canvas in 运行 / Run with the properties aside collapsed.
    • The first click on 设计 / Design brings back the design overlays and the aside that the landing collapsed. If the user collapses or expands the aside themselves, the landing no longer controls it.
    • Every other arrival opens in Design with the aside open, as before. That includes the explicit "Design in Studio" door and any reload or shared link, because router state does not travel in the URL (Commandment feat: add live playground for interactive schema demonstration #8: this is a one-shot arrival intent, not addressable state).
  2. The in-app composer names the task. When ChatPane runs the build agent scoped to a package (editPackageId), the placeholder is console.ai.askOrChangeApp. In zh it reads 「问问数据,或让我改改这个应用…」 and in en "Ask about your data, or ask me to change this app…". This applies to the console dock in a running app, the Studio dock and /ai/build?package=. The cold-start build surface and the ask agent keep their placeholders.
  3. The usage popover shows one meter.
    • The popover shows the pool's used share as a single percentage, console.ai.usage.poolUsed (for example "19% used").
    • The build / data-Q&A split is no longer drawn. Its keys meterBuild, meterAsk and breakdownTitle are removed from all ten packs.
    • useAiUsage still reads breakdown strictly from the wire. Nothing renders it any more (see Acceptance notes).
  4. The usage ring no longer looks like a spinner. The glyph (MeterGauge, which replaces MeterRing) is a closed outline in the tone colour around a pie wedge that fills clockwise from 12 o'clock. Before, it was a stroked arc over a faint 25%-opacity track. At low usage that drew a short open arc, which is the outline of a spinner. A pie inside a closed outline reads as a quantity at any fraction.
  5. The plan card's scope chip is localized and shows the app's label.
    • Both chip sites now read the pack sentence chatbot.plan.extendTarget instead of the English default "Adding to existing app". The two sites are the proposed-plan card and BlueprintProgressPanel, and they share one useExtendChip hook.
    • The chip names the target app by the label the host resolves. The new optional resolveAppLabel prop on ChatbotEnhanced does this, and ChatPane passes one built from the metadata apps. The machine name moves to the chip's tooltip.
    • A host planExtendLabel still takes precedence.

Mechanism assumptions (from the dispatch)

  • B1 verified. The navigation is decided inside objectui, in the built-moment effect in AiChatPage.tsx, the one that calls paneNavigate. The cloud side does not need to change.
  • B2 partly falsified. console.ai.askAgent is read at one source site, ChatPane's placeholder prop. ChatPane has three hosts: the full-page AiChatPage, the console ChatDock (ChatDockConversation), and the Studio dock (StudioAiCopilot). Fixing that one site covers all of them.
  • B3 verified. The literal appeared twice in code in ChatbotEnhanced: the planExtendLabel default and the BlueprintProgressPanel extendLabel default. A third occurrence was in a JSDoc. All three are gone.

Verification (at the head this PR was opened on)

  • New tests:
    • StudioDesignSurface.runLanding-11658.test.tsx (item 1, pillar)
    • AiChatPage.builtLandsRunning-11658.test.tsx (item 1, producer, with the "Design in Studio" door as the control)
    • AiChatPage.appContextComposer-11658.test.tsx (item 2, plus the host half of item 5)
    • The rewritten AiUsageIndicator.test.tsx blocks "the popover figure (one meter)" (item 3) and "the gauge glyph (not a spinner)" (item 4)
    • ChatbotEnhanced.extendChip-11658.test.tsx (item 5). This pins that the zh chip contains no ASCII-only literal: it has no Latin-letter run at all, and the target label in the fixture is Chinese.
  • Ablation: for each one, only the source was mutated, the mutation was proven to be on disk by counting the marker, the tests went red, then the file was restored with git checkout HEAD. The restore was proven by the on-disk blob hash equalling the HEAD blob and by an empty git diff HEAD, and the tests went green again.
    • Item 1 (pillar ignores the state): 2 red → restored 5/5 green.
    • Item 1 (Design does not hand the aside back): 1 red → restored 5/5 green.
    • Item 1 (producer navigates without the state): 2 red → restored 3/3 green.
    • Item 2 (no app-context branch): 2 red → restored 5/5 green.
    • Item 3 (indicator reverted to the base file): 2 red → restored 2/2 green.
    • Item 4 (same revert): 3 red → restored 3/3 green.
    • Item 5 (the chip goes back to an English template literal): 4 red → restored 6/6 green.
  • Gates, all with exit 0 unless noted:
    • type-check for @object-ui/i18n, @object-ui/plugin-chatbot and @object-ui/app-shell, after turbo run build --filter='@object-ui/app-shell^...'.
    • The test suites for packages/plugin-chatbot/ and packages/i18n/, and packages/app-shell/ (results are in the report comment).
    • check:i18n-keys, check:i18n-drift, check:i18n-dead-keys, check:new-line-citations (0 new citations), changeset:check, check:changeset-claims, check:pending-changeset-literals, and node scripts/check-changeset-presence.mjs.
  • Lint: a narrowed run of eslint --no-inline-config over the 20 changed .ts/.tsx files. Its one error, react-hooks/static-components in the DataPillar header, already exists on the base file and is suppressed inline in normal runs. Linting each of the four touched source files at base and at head gives identical per-rule counts. The repo-wide pnpm lint is left to CI.
  • NOT VERIFIED IN BROWSER, for all five items. The console has no cheap mock mode for the AI build surface or for the cloud usage endpoint, and the dispatch rules out booting a cloud stack. The epic's final re-walk covers it, including the URL the build lands on: /studio/PKG/interfaces?surface=dashboard:NAME, now in Run.

Acceptance notes

  • File surface. Item 1's landing half lives in packages/app-shell/src/views/studio-design/ (StudioDesignSurface.tsx, the new studioLanding.ts and its test). That is outside the claim's listed globs. I took it as "the post-build navigation site it finds", because the dispatch asks for the objectui half of the default tab and the collapsed panel, and both are state of the Interfaces pillar.
  • Out of scope. The cold-start build surface (no package) still reads "Ask Build…" / 「向 构建 提问…」. The ruling scopes item 2 to the in-app context, and "change this app" would be wrong with no app. This is not filed. If the maintainer wants it, it is a one-line follow-up at the same placeholder site.
  • Dormant read. useAiUsage still parses breakdown strictly, and no renderer reads it now. The wire contract was left alone. If cloud drops the field, its parser test is the place to retire it. No one owns that follow-up.

Generated by Claude Code

hotlong and others added 5 commits October 6, 2026 07:52
…d and names the target app by its label; the in-app composer names the task (objectui#11658 items 5, 2)

Item 5: both extend-mode chip sites (the proposed-plan card and the live
design panel) read the locale pack's `chatbot.plan.extendTarget` sentence
instead of the English literal the component defaulted to, and name the
target app by the label the host resolves (`resolveAppLabel`); the machine
name moves to the tooltip. A host `planExtendLabel` still wins.

Item 2: inside an app (the build agent scoped to a package) the composer
placeholder is `console.ai.askOrChangeApp`, never "Ask {agent}".

Co-authored-by: Claude <noreply@anthropic.com>
…ip's host-side app label (objectui#11658 items 2, 5)

Co-authored-by: Claude <noreply@anthropic.com>
…gauge no longer reads as a loading spinner (objectui#11658 items 3, 4)

Item 3: the popover shows the pool's used share as one percentage
(`console.ai.usage.poolUsed`); the build / data-Q&A split is no longer drawn
and its three keys (`meterBuild`, `meterAsk`, `breakdownTitle`) leave all ten
packs. `useAiUsage` still reads `breakdown` strictly off the wire.

Item 4: the header glyph is a closed, tone-coloured outline around a pie
wedge instead of a stroked arc over a faint track, so low usage reads as a
quantity, not a spinner.

Co-authored-by: Claude <noreply@anthropic.com>
…on the running app with the properties panel collapsed (objectui#11658 item 1)

The built-moment transition passes `STUDIO_RUN_LANDING` router state with
its navigation to the Interfaces pillar, which reads it once at mount: the
canvas opens in run mode with the properties aside collapsed, and the first
switch to Design re-opens the aside the landing collapsed. Every other
arrival, the explicit "Design in Studio" door included, opens on Design as
before.

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 331 chunks) 3318.9 KB 3330.4 KB
Main entry chunk (gzip) 152.1 KB 350 KB
Entry file index-OggOWht1.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) 17.22KB 6.37KB
app-shell (runtime-config.js) 22.52KB 7.86KB
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) 40.70KB 10.94KB
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) 574.72KB 137.94KB
core (index.js) 10.00KB 3.96KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 232.57KB 64.51KB
fields (index.js) 262.75KB 66.62KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
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.24KB 2.27KB
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) 35.66KB 9.49KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 41.18KB 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) 13.86KB 5.00KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.52KB 2.26KB
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) 53.17KB 15.46KB
plugin-charts (index.js) 84.26KB 23.05KB
plugin-chatbot (index.js) 198.39KB 47.02KB
plugin-dashboard (index.js) 143.58KB 38.81KB
plugin-designer (index.js) 231.41KB 48.84KB
plugin-detail (index.js) 247.21KB 65.03KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 177.09KB 45.89KB
plugin-gantt (index.js) 179.16KB 45.06KB
plugin-grid (index.js) 238.48KB 65.51KB
plugin-kanban (index.js) 52.17KB 16.37KB
plugin-list (index.js) 116.72KB 29.10KB
plugin-map (index.js) 25.60KB 8.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.12KB 12.29KB
plugin-timeline (index.js) 38.80KB 11.71KB
plugin-tree (index.js) 14.51KB 5.15KB
plugin-view (index.js) 90.23KB 22.73KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.81KB 3.58KB
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.08KB 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.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
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.25KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
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

@hotlong
hotlong marked this pull request as ready for review October 6, 2026 00:27
@hotlong
hotlong enabled auto-merge October 6, 2026 00:28
@hotlong
hotlong added this pull request to the merge queue Oct 6, 2026
Merged via the queue into main with commit fc3c2cc Oct 6, 2026
45 checks passed
@hotlong
hotlong deleted the claude/issue-11658-ai-build-surface-ux branch October 6, 2026 00:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

1 participant