Repository navigation
fix(app-shell,plugin-detail,i18n): console, record-page and Studio UX from the 2026-10-05 cloud acceptance (objectui#11659) - #11663
Merged
Conversation
…space", not "Open Production" (objectui#11659) A new customer has exactly one environment, and "production" is control-plane vocabulary. The `cloud:onboarding-next` ready-state button now resolves `cloudOnboarding.openWorkspace` (zh 进入工作区) in all ten packs, and the hint under it says "workspace" instead of "production environment". The destination is unchanged: the page's sso-open URL. Claude-Session: https://claude.ai/code/session_64cb68a6-01c7-4dc6-acc6-ccb459c90ef2 Co-authored-by: Claude <noreply@anthropic.com>
…bjectui#11659) The URL slug field is gone from `CreateWorkspaceDialog`: the slug is generated from the name by the same rule as before, still sent with the create call, and stays editable in organization settings. A slug collision is no longer the user's to fix here, so it is retried with a short random suffix (three attempts in all); other refusals show as before. Claude-Session: https://claude.ai/code/session_64cb68a6-01c7-4dc6-acc6-ccb459c90ef2 Co-authored-by: Claude <noreply@anthropic.com>
…s first session (objectui#11659) The reminder was gated on a home-visit count: quiet on the first home mount, shown on the second. A new user who builds their first app and returns to home makes that second mount inside the first sitting, which is where the acceptance run saw it. The gate now reads elapsed time: quiet for 12 hours after the first home visit on the device, so it first shows on a later day's visit. The component moves to its own module so it can be tested directly. Claude-Session: https://claude.ai/code/session_64cb68a6-01c7-4dc6-acc6-ccb459c90ef2 Co-authored-by: Claude <noreply@anthropic.com>
…hone number (objectui#11659) The phone cell draws its icon, number and copy button in one inline-flex box, which the chip's `truncate` span clips without an ellipsis: a 9rem chip read 0574-876 for 0574-8765-4321. A `phone` chip now takes the wide basis `email` and `url` already take. Claude-Session: https://claude.ai/code/session_64cb68a6-01c7-4dc6-acc6-ccb459c90ef2 Co-authored-by: Claude <noreply@anthropic.com>
…ind, not its type id (objectui#11659) `DashboardDefaultInspector` printed the stored `type` beside each widget title (按客户状态统计数量 · bar). It now prints the name the add-widget picker shows for that kind, in the designer's language, with the id on hover; an uncatalogued type still prints its id. Claude-Session: https://claude.ai/code/session_64cb68a6-01c7-4dc6-acc6-ccb459c90ef2 Co-authored-by: Claude <noreply@anthropic.com>
…m its zh copy (objectui#11659) The list heading read 自动化 · flow and the top bar 默认 OFF · 审阅后再启用. They now read 自动化 and 默认停用 · 审阅后再启用, and the canvas hint drops 可视化编排. The en heading drops the type as well. Claude-Session: https://claude.ai/code/session_64cb68a6-01c7-4dc6-acc6-ccb459c90ef2 Co-authored-by: Claude <noreply@anthropic.com>
…wn module (objectui#11659) `RecoveryPasswordReminder.tsx` exported its gate and storage keys beside the component, which `react-refresh/only-export-components` flags. The gate moves to `recoveryReminderGate.ts`; behaviour is unchanged. Claude-Session: https://claude.ai/code/session_64cb68a6-01c7-4dc6-acc6-ccb459c90ef2 Co-authored-by: Claude <noreply@anthropic.com>
…the next case (objectui#11659) Its `mockRejectedValueOnce(...).mockResolvedValueOnce(...)` queue survives `vi.clearAllMocks()`: with the retry ablated, the unconsumed resolved value answered the next case's first call and failed it too. A whole implementation keyed on the slug fails only the case it belongs to. Claude-Session: https://claude.ai/code/session_64cb68a6-01c7-4dc6-acc6-ccb459c90ef2 Co-authored-by: Claude <noreply@anthropic.com>
…asting it (objectui#11659)
`{ fields: ['phone', 'status'] }` satisfies the renderer's declared
schema prop, so the `as any` the new pin carried was an avoidable lint
warning.
Claude-Session: https://claude.ai/code/session_64cb68a6-01c7-4dc6-acc6-ccb459c90ef2
Co-authored-by: Claude <noreply@anthropic.com>
Contributor
✅ Console Performance Budget
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
Size Limits
|
hotlong
marked this pull request as ready for review
October 6, 2026 00:56
hotlong
enabled auto-merge
October 6, 2026 00:56
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #11659
Six console, record-page and Studio UX items from the 2026-10-05 cloud acceptance run, each executed as ruled on the card. Dispatched by the epic objectstack-ai/cloud#2636 PM loop; session
https://claude.ai/code/session_64cb68a6-01c7-4dc6-acc6-ccb459c90ef2.What changed, per ruling
CloudOnboardingNext(thecloud:onboarding-nextwidget) now resolvescloudOnboarding.openWorkspace, which replacescloudOnboarding.openProductionin all ten packs. The hint under the button (cloudOnboarding.hintReady) was the secondary 「生产环境」 wording in the same block; it now says workspace in all ten packs. Destination unchanged: the button still navigates to the page'sopenProductionUrl(pinned by the new zh case).CreateWorkspaceDialog. The slug is still generated from the name by the samenameToSlugrule and sent with the create call; the owner can change it in organization settings (SettingsPagekeeps its slug input). Because the user can no longer fix a taken slug in the dialog, a slug collision (ORGANIZATION_ALREADY_EXISTS, which is what better-auth's create route throws for a taken slug, orORGANIZATION_SLUG_ALREADY_TAKEN) is retried with a short random suffix, three attempts in all. Any other refusal is shown as before. Submit is still gated on a non-empty slug, which is non-empty exactly when the trimmed name is.sessionStorageis per tab, so a "new session" read from it fires in any second tab of the same first sitting;AuthClientSessioncarries the bearer token, and an SSO re-entry can mint a new one within one sitting).A device holding the old
'1'flag starts the 12 hours over instead of reading it as long ago, and unavailable storage stays quiet. The component moved out ofHomePage.tsxintoRecoveryPasswordReminder.tsx, with the gate inrecoveryReminderGate.ts; neither is exported from the package entry.HeaderHighlight(plugin-detail), mounted byrecord:highlightsinside the record drawer'sRecordDetailView. The phone cell draws a dial icon, the number and a copy button in oneinline-flexbox, and the chip'struncatespan cannot put an ellipsis on an inline-flex child: it clips it mid-glyph. Aphonechip now takes the wide basis thatemailandurlalready take, so a whole number shows; the full value stays in the chip's hover title.DashboardDefaultInspector's widgets list printed the storedtypebeside each title. It now prints the add-widget picker's name for that kind (engine.widgetPicker.type.*: zh 柱状图, en "Bar chart"), with the id on hover. An uncatalogued type still prints its id.flowandOFF. 自动化 · flow becomes 自动化; 默认 OFF · 审阅后再启用 becomes 默认停用 · 审阅后再启用 (matching the pillar's own 已启用 / 已停用); 可视化编排 · 点选节点配置 becomes 点选画布上的节点即可配置. The en heading drops the type too ("Automations"). The pillar is not hidden; whether it is offered is cloud#2627's call.Premises checked
cloudOnboarding.openProduction, rendered byCloudOnboardingNext). But cloud'spackages/service-tenant/src/pages/welcome.page.tscarries its own copy that QUOTES the old label, so after this lands and the pin moves, cloud's page will say one thing and the button another. Cloud was not edited. What cloud needs, all insidegettingStarted()andcardGrid():gs_1) ends with enEnter it with "Open Production" above., zh 从上方的「打开生产环境」进入。, ja 上の「本番環境を開く」から入ります。, es Entra desde «Abrir producción» arriba. Each should quote the new label: "Open workspace", 「进入工作区」, 「ワークスペースを開く」, «Abrir espacio de trabajo». The same sentence opens with "Your production environment is already set up" / 你的生产环境已自动就绪, which is the same operator wording.workspace-slug-inputinCreateWorkspaceDialog. Hiding it keeps validation and submit working (pinned), and adds collision retry because the field was the user's only way to recover from a taken slug.home.recoveryReminder.messageis rendered only byRecoveryPasswordReminder, whichHomePagemounts in both its empty and its app-list branches.HeaderHighlightinpackages/plugin-detail, viarecord:highlights. Item 5: the widgets list inDashboardDefaultInspector(the dashboard's default right panel in Studio). The card's middle dot was a paraphrase: the title and the type sit in separate elements.Verification
Final head for the unions below: tests and type-check for app-shell and i18n at
5ffdd171c, plugin-detail at992c3c2cc(the one later commit touches only a plugin-detail test file).pnpm exec vitest run packages/app-shell/pnpm exec vitest run packages/plugin-detail/pnpm exec vitest run packages/i18n/pnpm --filter @object-ui/app-shell run type-checktsconfig.test.jsonlists all five touched app-shell test filespnpm --filter @object-ui/plugin-detail run type-checkpnpm --filter @object-ui/i18n run type-checknode scripts/check-changeset-presence.mjspnpm run check:new-line-citationscheck:i18n-keys,check:i18n-drift,check:i18n-designer-parity,check:changeset-claims,check:pending-changeset-literals,check-changeset-no-major--no-inline-config)Lint is a declared narrowing, not the repo-wide
pnpm lint(CI runs that): the population is the branch's touched.ts/.tsxfiles, 24 by eslint's own JSON file count, andeslint.config.jsenables no type-aware linting (noparserOptions.projectorprojectService), so this diff cannot move a verdict on an untouched file. The warnings on the touched files are pre-existingno-explicit-anyand one pre-existingset-state-in-effecton the dialog's reset effect; twoanys moved with the reminder fromHomePage.tsxinto its new module.This machine is macOS, so the shared verify lock ran in its declared unlocked mode (no
flock): these runs had no mutual exclusion with sibling agents.Ablation, one per item at least
Each leg mutated the committed source through
scripts/ablation-replace.mjs(anchor must hit once), ran the item's test, and restored withgit checkout HEAD, proven by blob hash equal to HEAD and an emptygit diff HEAD.openWorkspaceback to 打开生产环境true(visit-count behaviour)phonedropped from the wide familyw.typeagainThe first retry-ablation run also failed the following case: the retry case's
…Oncequeue survivedvi.clearAllMocks()and answered the next case. The case now uses a whole implementation keyed on the slug, and the re-run fails only the retry case.Browser
NOT VERIFIED IN BROWSER, all six items: the console needs a backend, and the dev harnesses that run without one (
preview-gallery.html,record-header-preview.html) do not mount these surfaces. The item-4 mechanism was measured on a static probe that mirrors the chip's CSS (border-box sizing, 9rem vs 16rem basis, atruncatespan around an inline-flex phone box): on the 9rem basis the clip box was 103px for 164px of content and the number was cut mid-glyph with no ellipsis; on the 16rem basis the box was 215px and nothing was clipped. That is a CSS measurement, not a screenshot of the product. The epic's final re-walk covers the zh-CN and en screenshots.Acceptance notes
StudioDesignSurface's automation canvas header still prints a literalflow · NAMEchip beside the hint when a flow is open, in every locale. It is outside this card's claimed file surface, so it is untouched here; it is the same "dropflow" family as ruling 6.workspace.slugLabelandworkspace.slugHintare now unread in all ten packs; left in place (the dead-key report is report-only).git merge-treeof the two heads is clean.Generated by Claude Code