This repository was archived by the owner on Oct 26, 2026. It is now read-only.
Repository navigation
Commit f9f4a62
fix(app-shell,plugin-detail,i18n): console, record-page and Studio UX from the 2026-10-05 cloud acceptance (objectui#11659) (#11663)
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
1. **Cloud home primary button reads 「进入工作区」 / "Open workspace".**
`CloudOnboardingNext` (the `cloud:onboarding-next` widget) now resolves
`cloudOnboarding.openWorkspace`, which replaces
`cloudOnboarding.openProduction` in 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's `openProductionUrl`
(pinned by the new zh case).
2. **Create-workspace dialog asks for the name only.** The "URL slug"
field is gone from `CreateWorkspaceDialog`. The slug is still generated
from the name by the same `nameToSlug` rule and sent with the create
call; the owner can change it in organization settings (`SettingsPage`
keeps 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, or
`ORGANIZATION_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.
3. **Backup-password reminder stays quiet in the first session.**
Mechanism: elapsed time. The reminder is quiet for 12 hours after the
first home visit on the device, so it first shows on a later day's
visit. Why this and not the alternatives:
- the old gate counted home visits (quiet on the first mount, shown on
the second), and "build the first app, come back to home" is the second
mount inside the first sitting, which is exactly what the acceptance run
saw;
- `sessionStorage` is per tab, so a "new session" read from it fires in
any second tab of the same first sitting;
- the client holds no session id to compare (`AuthClientSession` carries
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 of `HomePage.tsx` into
`RecoveryPasswordReminder.tsx`, with the gate in
`recoveryReminderGate.ts`; neither is exported from the package entry.
4. **Record drawer header does not cut the phone number.** The highlight
row is `HeaderHighlight` (plugin-detail), mounted by `record:highlights`
inside the record drawer's `RecordDetailView`. The phone cell draws a
dial icon, the number and a copy button in one `inline-flex` box, and
the chip's `truncate` span cannot put an ellipsis on an inline-flex
child: it clips it mid-glyph. A `phone` chip now takes the wide basis
that `email` and `url` already take, so a whole number shows; the full
value stays in the chip's hover title.
5. **Studio dashboard widgets list shows a localized widget kind.**
`DashboardDefaultInspector`'s widgets list printed the stored `type`
beside 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.
6. **Studio automation pillar zh copy drops `flow` and `OFF`.** 自动化 ·
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
- **C1, half true.** The button text on the cloud home comes from
objectui (`cloudOnboarding.openProduction`, rendered by
`CloudOnboardingNext`). But cloud's
`packages/service-tenant/src/pages/welcome.page.ts` carries 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 inside `gettingStarted()` and
`cardGrid()`:
- Step 1's description (`gs_1`) ends with en `Enter 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.
- Step 1's title and the hero subtitle say 打开你的环境 / "Open your
environment"; optional alignment with 进入工作区.
- The "Manage your environments" card description says
你的生产环境,以及需要时的开发副本. That card is the environments surface, where
production vs dev is the point; recommended to leave it.
- **C2, true.** The slug field was the `workspace-slug-input` in
`CreateWorkspaceDialog`. 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.
- **C3, true.** zh `home.recoveryReminder.message` is rendered only by
`RecoveryPasswordReminder`, which `HomePage` mounts in both its empty
and its app-list branches.
- **C4, located.** Item 4: `HeaderHighlight` in
`packages/plugin-detail`, via `record:highlights`. Item 5: the widgets
list in `DashboardDefaultInspector` (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 at `992c3c2cc` (the one later commit
touches only a plugin-detail test file).
| gate | result |
|---|---|
| `pnpm exec vitest run packages/app-shell/` | 1010 files passed, 1
skipped; 10040 tests passed (exit 0) |
| `pnpm exec vitest run packages/plugin-detail/` | 239 files passed, 1
skipped; 2385 tests passed (exit 0) |
| `pnpm exec vitest run packages/i18n/` | 79 files passed; 1289 tests
passed (exit 0) |
| `pnpm --filter @object-ui/app-shell run type-check` | exit 0;
`tsconfig.test.json` lists all five touched app-shell test files |
| `pnpm --filter @object-ui/plugin-detail run type-check` | exit 0 |
| `pnpm --filter @object-ui/i18n run type-check` | exit 0 |
| `node scripts/check-changeset-presence.mjs` | exit 0 |
| `pnpm run check:new-line-citations` | 0 new citations over the 25
branch files, exit 0 |
| `check:i18n-keys`, `check:i18n-drift`, `check:i18n-designer-parity`,
`check:changeset-claims`, `check:pending-changeset-literals`,
`check-changeset-no-major` | all exit 0 |
| eslint on the 24 touched TS files (`--no-inline-config`) | 0 errors |
Lint is a declared narrowing, not the repo-wide `pnpm lint` (CI runs
that): the population is the branch's touched `.ts`/`.tsx` files, 24 by
eslint's own JSON file count, and `eslint.config.js` enables no
type-aware linting (no `parserOptions.project` or `projectService`), so
this diff cannot move a verdict on an untouched file. The warnings on
the touched files are pre-existing `no-explicit-any` and one
pre-existing `set-state-in-effect` on the dialog's reset effect; two
`any`s moved with the reminder from `HomePage.tsx` into 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 with `git checkout HEAD`, proven by blob hash equal
to HEAD and an empty `git diff HEAD`.
| item | mutation | red |
|---|---|---|
| 1 | zh `openWorkspace` back to 打开生产环境 | 1 failed / 7 (the zh case) |
| 2 | slug input put back in the dialog | 1 failed / 7 (no-slug-field
case) |
| 2 | collision retry removed | 1 failed / 7 (retry case) |
| 3 | gate answers `true` (visit-count behaviour) | 2 failed / 8 (both
first-sitting cases) |
| 4 | `phone` dropped from the wide family | 1 failed / 3 |
| 5 | list prints `w.type` again | 2 failed / 8 (zh and en) |
| 6 | zh heading back to 自动化 · flow | 1 failed / 4 |
The first retry-ablation run also failed the following case: the retry
case's `…Once` queue survived `vi.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, a `truncate` span 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
literal `flow · NAME` chip 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 "drop `flow`" family as ruling 6.
- Link-shaped cell renderers (phone, email, url) draw an inline-flex
root, so a highlight value that outgrows even the wide basis is still
clipped without an ellipsis; the hover title carries it. Polish, no
carrier.
- `workspace.slugLabel` and `workspace.slugHint` are now unread in all
ten packs; left in place (the dead-key report is report-only).
- 「工作区」 now names the environment on the cloud home and in the
environment home's loading text, and the organization in the
create-workspace dialog. Since the environment is named after its
workspace (the naming collapse), a new customer sees one thing; noted,
not changed.
- Overlap: objectui#11662 (the parallel card's PR) touches the same ten
packs, on other keys. A `git merge-tree` of the two heads is clean.
---
_Generated by [Claude
Code](https://claude.ai/code/session_64cb68a6-01c7-4dc6-acc6-ccb459c90ef2)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent fc3c2cc commit f9f4a62
25 files changed
Lines changed: 808 additions & 149 deletions
File tree
- .changeset
- packages
- app-shell/src
- console
- home
- __tests__
- organizations
- __tests__
- views/metadata-admin
- inspectors
- i18n/src/locales
- plugin-detail/src
- __tests__
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
16 | | - | |
| 16 | + | |
17 | 17 | | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
18 | 23 | | |
19 | 24 | | |
20 | 25 | | |
21 | 26 | | |
22 | | - | |
| 27 | + | |
23 | 28 | | |
24 | 29 | | |
25 | 30 | | |
| |||
53 | 58 | | |
54 | 59 | | |
55 | 60 | | |
56 | | - | |
| 61 | + | |
57 | 62 | | |
58 | 63 | | |
59 | 64 | | |
| |||
118 | 123 | | |
119 | 124 | | |
120 | 125 | | |
121 | | - | |
| 126 | + | |
122 | 127 | | |
123 | 128 | | |
124 | 129 | | |
| |||
194 | 199 | | |
195 | 200 | | |
196 | 201 | | |
197 | | - | |
| 202 | + | |
198 | 203 | | |
199 | 204 | | |
200 | 205 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
18 | | - | |
| 18 | + | |
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| 31 | + | |
31 | 32 | | |
32 | 33 | | |
33 | 34 | | |
| |||
38 | 39 | | |
39 | 40 | | |
40 | 41 | | |
41 | | - | |
| 42 | + | |
42 | 43 | | |
43 | 44 | | |
44 | 45 | | |
| |||
231 | 232 | | |
232 | 233 | | |
233 | 234 | | |
234 | | - | |
235 | | - | |
236 | | - | |
237 | | - | |
238 | | - | |
239 | | - | |
240 | | - | |
241 | | - | |
242 | | - | |
243 | | - | |
244 | | - | |
245 | | - | |
246 | | - | |
247 | | - | |
248 | | - | |
249 | | - | |
250 | | - | |
251 | | - | |
252 | | - | |
253 | | - | |
254 | | - | |
255 | | - | |
256 | | - | |
257 | | - | |
258 | | - | |
259 | | - | |
260 | | - | |
261 | | - | |
262 | | - | |
263 | | - | |
264 | | - | |
265 | | - | |
266 | | - | |
267 | | - | |
268 | | - | |
269 | | - | |
270 | | - | |
271 | | - | |
272 | | - | |
273 | | - | |
274 | | - | |
275 | | - | |
276 | | - | |
277 | | - | |
278 | | - | |
279 | | - | |
280 | | - | |
281 | | - | |
282 | | - | |
283 | | - | |
284 | | - | |
285 | | - | |
286 | | - | |
287 | | - | |
288 | | - | |
289 | | - | |
290 | | - | |
291 | | - | |
292 | | - | |
293 | | - | |
294 | | - | |
295 | | - | |
296 | | - | |
297 | | - | |
298 | | - | |
299 | | - | |
300 | | - | |
301 | | - | |
302 | 235 | | |
303 | 236 | | |
304 | 237 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
0 commit comments