Skip to content

chore(deps-dev): bump storybook from 8.6.15 to 8.6.17 - #772

Merged
github-actions[bot] merged 1 commit into
mainfrom
dependabot/npm_and_yarn/storybook-8.6.17
Feb 23, 2026
Merged

github-actions[bot] merged 1 commit into
mainfrom
dependabot/npm_and_yarn/storybook-8.6.17

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Feb 23, 2026

Copy link
Copy Markdown
Contributor

Bumps storybook from 8.6.15 to 8.6.17.

Release notes

Sourced from storybook's releases.

v8.6.17

8.6.17

  • Harden websocket connection

v8.6.16

8.6.16

  • No-op release. No changes.
Changelog

Sourced from storybook's changelog.

8.6.17

  • Harden websocket connection

8.6.16

  • No-op release. No changes.

8.6.14

8.6.13

8.6.12

8.6.11

8.6.10

8.6.9

8.6.8

... (truncated)

Commits
  • c6e550a Bump version from "8.6.16" to "8.6.17" [skip ci]
  • 9cf9d89 Core: Require token for websocket connections
  • 7e51515 Bump version from "8.6.15" to "8.6.16" [skip ci]
  • See full diff in compare view

Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options

You can trigger Dependabot actions by commenting on this PR:

  • @dependabot rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency
  • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)

Bumps [storybook](https://github.com/storybookjs/storybook/tree/HEAD/code/core) from 8.6.15 to 8.6.17.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v8.6.17/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v8.6.17/code/core)

---
updated-dependencies:
- dependency-name: storybook
  dependency-version: 8.6.17
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot @github

dependabot Bot commented on behalf of github Feb 23, 2026

Copy link
Copy Markdown
Contributor Author

Labels

The following labels could not be found: automated. Please create it before Dependabot can add it to a pull request.

Please fix the above issues or remove invalid values from dependabot.yml.

@vercel

vercel Bot commented Feb 23, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
objectui Ready Ready Preview, Comment Feb 23, 2026 8:43am
objectui-demo Error Error Feb 23, 2026 8:43am
objectui-storybook Error Error Feb 23, 2026 8:43am

Request Review

@github-actions
github-actions Bot merged commit 610c1f6 into main Feb 23, 2026
4 of 11 checks passed
@dependabot
dependabot Bot deleted the dependabot/npm_and_yarn/storybook-8.6.17 branch February 23, 2026 08:01
@github-actions

Copy link
Copy Markdown
Contributor

❌ Console Performance Budget

Metric Value Budget
Main entry (gzip) ** KB** KB
Entry file `` —
Status FAIL —

📦 Bundle Size Report

Package Size Gzipped
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 1.17KB 0.53KB
auth (AuthProvider.js) 7.36KB 1.78KB
auth (ForgotPasswordForm.js) 4.00KB 1.44KB
auth (LoginForm.js) 4.20KB 1.45KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 5.66KB 1.59KB
auth (UserMenu.js) 3.40KB 1.22KB
auth (createAuthClient.js) 2.78KB 0.98KB
auth (createAuthenticatedFetch.js) 1.24KB 0.60KB
auth (index.js) 1.18KB 0.51KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 1.57KB 0.57KB
collaboration (CommentThread.js) 18.38KB 4.49KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 3.65KB 1.42KB
collaboration (index.js) 1.16KB 0.50KB
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) 1847.17KB 433.11KB
core (index.js) 0.81KB 0.32KB
create-plugin (index.js) 10.13KB 3.17KB
data-objectstack (index.js) 38.87KB 9.57KB
fields (index.js) 92.37KB 18.57KB
i18n (i18n.js) 2.03KB 0.77KB
i18n (index.js) 1.79KB 0.72KB
i18n (provider.js) 3.21KB 1.09KB
layout (index.js) 97.78KB 25.90KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (index.js) 1.19KB 0.53KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 4.42KB 1.27KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.71KB 0.42KB
mobile (useResponsiveConfig.js) 1.36KB 0.63KB
mobile (useSpecGesture.js) 1.77KB 0.77KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 3.11KB 0.87KB
permissions (evaluator.js) 4.00KB 1.23KB
permissions (index.js) 0.85KB 0.40KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.52KB
permissions (usePermissions.js) 0.99KB 0.49KB
plugin-aggrid (AddressField-DjN2_Oa7.js) 3.05KB 0.76KB
plugin-aggrid (AgGridImpl-Dx7qLWE5.js) 7.04KB 2.33KB
plugin-aggrid (AutoNumberField-Cv75rRi8.js) 0.28KB 0.27KB
plugin-aggrid (FileField--Sh7TXn1.js) 5.90KB 2.10KB
plugin-aggrid (FormulaField-BTrEHvp3.js) 0.52KB 0.38KB
plugin-aggrid (GeolocationField-O2Zquk-4.js) 4.46KB 1.50KB
plugin-aggrid (GridField-D7USr6Uk.js) 1.71KB 0.68KB
plugin-aggrid (LocationField-Dvi2PlfB.js) 0.93KB 0.54KB
plugin-aggrid (MasterDetailField-CV5Y8pDE.js) 3.86KB 1.17KB
plugin-aggrid (ObjectAgGridImpl-iCFRNsdP.js) 920.44KB 203.73KB
plugin-aggrid (ObjectField-UmL0F44x.js) 1.61KB 0.77KB
plugin-aggrid (QRCodeField-BNtkxBkd.js) 3.38KB 1.23KB
plugin-aggrid (RichTextField-CkjlEAJt.js) 1.16KB 0.59KB
plugin-aggrid (SignatureField-C9-m1IYy.js) 3.33KB 1.29KB
plugin-aggrid (SummaryField-BuvV3onE.js) 0.48KB 0.37KB
plugin-aggrid (UserField-DNI1psi1.js) 2.44KB 0.93KB
plugin-aggrid (VectorField-D_abxOU0.js) 0.79KB 0.45KB
plugin-aggrid (index-2XWZiXSX.js) 19.95KB 5.03KB
plugin-aggrid (index.js) 0.22KB 0.16KB
plugin-ai (index.js) 25.35KB 6.39KB
plugin-calendar (index.js) 49.03KB 13.35KB
plugin-charts (AdvancedChartImpl-GErbMD6M.js) 126.98KB 26.25KB
plugin-charts (BarChart-C_I0OFbj.js) 542.77KB 135.30KB
plugin-charts (ChartImpl-CnD20l5F.js) 3.19KB 1.10KB
plugin-charts (index-Byep0tj1.js) 15.23KB 4.49KB
plugin-charts (index.js) 0.19KB 0.16KB
plugin-chatbot (index.js) 1140.69KB 333.05KB
plugin-dashboard (index.js) 156.26KB 40.27KB
plugin-designer (index.js) 328.33KB 65.94KB
plugin-detail (AddressField-Bi_9K5ey.js) 2.98KB 0.75KB
plugin-detail (AutoNumberField-BxnFqllo.js) 0.28KB 0.26KB
plugin-detail (AvatarField-C9FUxKb6.js) 2.62KB 1.07KB
plugin-detail (BooleanField-BCkmXd4D.js) 1.13KB 0.51KB
plugin-detail (CodeField-i_JEPSj1.js) 0.74KB 0.47KB
plugin-detail (ColorField-BQsJKzNa.js) 1.23KB 0.54KB
plugin-detail (CurrencyField-DSUtanfx.js) 1.48KB 0.73KB
plugin-detail (DateField-CAn-cbax.js) 0.54KB 0.37KB
plugin-detail (DateTimeField-BIzCSHQF.js) 0.71KB 0.42KB
plugin-detail (EmailField-Bk6yp-VU.js) 0.81KB 0.48KB
plugin-detail (FileField-BpW9a5Oq.js) 5.50KB 1.94KB
plugin-detail (FormulaField-CJkkwIK8.js) 0.51KB 0.38KB
plugin-detail (GeolocationField-DLF1NtE-.js) 3.71KB 1.21KB
plugin-detail (GridField-D_2YmoKb.js) 1.68KB 0.68KB
plugin-detail (ImageField-3ArGKB6o.js) 2.83KB 1.14KB
plugin-detail (LocationField-3bnKLoQg.js) 0.95KB 0.54KB
plugin-detail (LookupField-Bh0-xfDY.js) 4.00KB 1.38KB
plugin-detail (MasterDetailField-B_v8jiYi.js) 3.39KB 1.00KB
plugin-detail (NumberField-DbjXjbIC.js) 0.68KB 0.44KB
plugin-detail (ObjectField-Dw5lEPkB.js) 1.64KB 0.76KB
plugin-detail (PasswordField-D0yxmNpw.js) 1.21KB 0.62KB
plugin-detail (PercentField-BnwYQEvm.js) 1.89KB 0.84KB
plugin-detail (PhoneField-t10i5JOI.js) 0.80KB 0.48KB
plugin-detail (QRCodeField-C4g9y7Y6.js) 2.35KB 0.91KB
plugin-detail (RatingField-fQOqinqq.js) 1.62KB 0.66KB
plugin-detail (RichTextField-BhyWeaLY.js) 1.15KB 0.59KB
plugin-detail (SelectField-CS2Gu9Rn.js) 0.90KB 0.49KB
plugin-detail (SignatureField-vipzYcs6.js) 2.97KB 1.10KB
plugin-detail (SliderField-CssQLV9F.js) 1.00KB 0.49KB
plugin-detail (SummaryField-ugYPYxjP.js) 0.47KB 0.36KB
plugin-detail (TextAreaField-D6wWsnwh.js) 1.09KB 0.59KB
plugin-detail (TextField-C_DjLkJT.js) 0.82KB 0.42KB
plugin-detail (TimeField-Be3-n5Wq.js) 0.50KB 0.34KB
plugin-detail (UrlField-BjTRlLMx.js) 0.98KB 0.52KB
plugin-detail (UserField-DFMUacOQ.js) 2.33KB 0.90KB
plugin-detail (VectorField-CKg9jdGa.js) 0.78KB 0.44KB
plugin-detail (index-BbvBDEqN.js) 1846.04KB 432.18KB
plugin-detail (index.js) 0.90KB 0.51KB
plugin-editor (MonacoImpl-hfdmoz6k.js) 18.15KB 5.59KB
plugin-editor (index-CuYbY6xb.js) 10.10KB 3.32KB
plugin-editor (index.js) 0.19KB 0.15KB
plugin-form (index.js) 66.73KB 13.98KB
plugin-gantt (index.js) 244.31KB 58.97KB
plugin-grid (index.js) 95.22KB 24.91KB
plugin-kanban (KanbanEnhanced-_27OOHhL.js) 32.31KB 9.09KB
plugin-kanban (KanbanImpl-CgkoIanE.js) 14.19KB 4.18KB
plugin-kanban (index-CVyX-djg.js) 31.17KB 9.18KB
plugin-kanban (index.js) 0.42KB 0.26KB
plugin-kanban (sortable.esm-CNNHgHk5.js) 71.43KB 18.99KB
plugin-list (index.js) 1810.20KB 426.19KB
plugin-map (index.js) 130.47KB 31.67KB
plugin-map (maplibre-gl-DSpYxujd.js) 1416.27KB 302.72KB
plugin-markdown (MarkdownImpl-E6vCIsNj.js) 256.68KB 64.45KB
plugin-markdown (index-Dr10kVgr.js) 9.63KB 3.17KB
plugin-markdown (index.js) 0.19KB 0.15KB
plugin-report (index.js) 65.85KB 13.42KB
plugin-timeline (index.js) 107.97KB 25.07KB
plugin-view (index.js) 135.39KB 34.38KB
plugin-workflow (index.js) 82.94KB 17.11KB
react (LazyPluginLoader.js) 3.77KB 1.33KB
react (SchemaRenderer.js) 8.21KB 2.56KB
react (index.js) 0.66KB 0.38KB
tenant (TenantContext.js) 0.31KB 0.25KB
tenant (TenantGuard.js) 1.04KB 0.43KB
tenant (TenantProvider.js) 2.76KB 0.98KB
tenant (TenantScopedQuery.js) 0.77KB 0.44KB
tenant (index.js) 0.75KB 0.38KB
tenant (resolver.js) 2.64KB 0.76KB
tenant (useTenant.js) 0.50KB 0.32KB
tenant (useTenantBranding.js) 0.62KB 0.39KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.78KB 0.98KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 0.20KB 0.18KB
types (crud.js) 0.20KB 0.18KB
types (data-display.js) 0.20KB 0.18KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 0.73KB 0.39KB
types (disclosure.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (index.js) 1.25KB 0.58KB
types (layout.js) 0.20KB 0.18KB
types (mobile.js) 0.20KB 0.18KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (tenant.js) 0.20KB 0.18KB
types (theme.js) 0.20KB 0.18KB
types (ui-action.js) 0.20KB 0.18KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB
types (workflow.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

os-zhuang added a commit that referenced this pull request Jul 8, 2026
…st publish errors (cloud#771/#772) (#2351)

Trust-polish batch from the 2026-07-09 magic-flow acceptance run
(objectstack-ai/cloud#771, #772):

- The chat surface now speaks the CONVERSATION's language: a Chinese thread
  under an English console got English canned approval messages ("Looks good —
  build it as proposed."), English progress labels and English starter chips.
  detectConversationLanguage() reads the latest user message (CJK → zh) and
  wins over the UI locale; falls back to the UI language for fresh threads.
- Default agent tab prefers BUILD when the catalog offers it: the build
  surface is the one that resumes its in-progress conversation, so landing on
  the ask tab hid the user's build thread behind a tab switch ("my build chat
  disappeared" → they rebuild from scratch — the user-side path of cloud#769).
  Ask-only users are unaffected.
- Build persona stops masquerading as a data-Q&A box: its empty-state pitch
  and starter chips are now build-flavoured (zh + en), instead of the ask
  persona's "query and analyze your data" copy with metadata chips.
- Publish failure toast carries the real error: the handler threw
  `new Error(String(failedCount))`, so users saw "Publish failed — 2". Now it
  surfaces the first failed item's type/name/error (+N more) or the server
  error message.
- The floating panel's publish success now pulses emitMetadataRefresh() (the
  full-page AI route already did), so the launcher/app switcher lists the new
  app WITHOUT a page reload — "open it from the launcher" was a lie until F5.
- Re-hydrated tool-call-only turns no longer render their internal
  placeholder ("(called todo_write, propose_blueprint)") as prose; they
  collapse to a quiet localized activity note.

Build green (turbo app-shell+plugin-chatbot), vitest 1242 passed.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
os-zhuang added a commit that referenced this pull request Jul 14, 2026
…lier handoff card (#2458) (#2496)

When the `ask` agent declines a build-shaped request, the ~20s wait before the
"Open in Builder →" card is the LLM's time-to-tool-call. During it the chat
could show dead air: a blank bubble, or the static "执行过程" activity note when
the backend streamed a `(called …)` tool-call placeholder mid-stream.

`ChatbotEnhanced` now renders the existing `ThinkingDots` indicator whenever a
streaming assistant turn has nothing VISIBLE yet — whitespace-only content, a
`(called …)` placeholder, or reasoning hidden in `summary` mode. The static
"执行过程" note is kept only for FINISHED (re-hydrated) tool-call-only turns
(#772 preserved). The `builderHandoff` card already renders at `output-available`
with no prose gate, so it surfaces the instant the tool result lands; the typing
cursor now only paints beside real streaming prose.

Tests: card renders while streaming before prose; live dots (not 执行过程) for a
mid-stream placeholder; 执行过程 note preserved for a finished placeholder turn.

Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
akarma-synetal pushed a commit to akarma-synetal/objectui that referenced this pull request Aug 10, 2026
…3837) (objectstack-ai#3897)

* fix(app-shell): 方案卡的 Building… 徽标随 UI 语言取值,不再被会话语言门控 (objectstack-ai#3837)

`AiChatPage` 用 `convZh`(会话语言)门控四个字符串,因为 cloud 确认门
(`service-ai-studio` `confirm-gate.ts` `APPROVAL_RE`)只认中英,发进线程的
文本必须与线程本身同语言(objectstack-ai#772/objectstack-ai#2884)。该门上方注释的后半句写明了另一半规
则:button LABELS stay on the UI locale。

`planBuildingLabel`(objectstack-ai#2632 引入)落在了这句的错误一侧,中文会话恒取硬编码的
`正在搭建…`,两个后果都已实测:

- **混合语言的卡片**:英文控制台里,中文会话的方案卡 `Proposed plan` /
  `Build it` / `Built` / `Not yet built` 全英文,中间夹一个中文徽标。objectstack-ai#2458
  第 4 条记录的是同一个病的反方向。
- **翻译永远读不到**:中文会话恒走字面量,`console.ai.planBuilding` 的 zh
  值对中文读者无效。objectstack-ai#3546 切片四(PR objectstack-ai#3839)刚把该 key 补进十包,只能做围
  堵 —— 把 zh 值写成与字面量逐字节相同并把两者钉在一起。

徽标现在与相邻十二个标签一样读 `t('console.ai.planBuilding', …)`:十个包全
部可达(德文控制台 + 中文会话渲染 `Wird erstellt…`),zh 包成为该中文措辞的
唯一来源(值不变,中文读者看到的字符串与改动前完全一致)。

三条出站文本(`planApproveMessage` / `planApproveDefaultsMessage` /
`changesConfirmMessage`)一行未动,仍随会话语言 —— 复核确认三者都交给
`onSendMessage`(`ChatbotEnhanced.tsx:1598`、`:2395`)、由门读取,正是
`convZh` 分支存在的那一类;全文件再无其它 `*Label`/`*Title` 被该门控住
(`convZh` 全部读点:定义 1 处 + 这三条)。

钉子:

- `packages/app-shell/.../AiChatPage.planCardLocale.test.tsx`(新增)真渲染
  `ChatPane` + 真 `I18nProvider` + 真 `isConversationZh`,把
  `ChatbotEnhanced` 换成 props 记录器:en 控制台 + 中文会话 → `Building…`
  且卡上 `*Label` 无一含中日韩字符;de 控制台 + 中文会话 → `Wird erstellt…`
  (三方语言证明是包在应答,而非两路三元);zh 控制台 → `正在搭建…`;三条
  出站文本仍随会话。
- `packages/i18n/.../console-namespace-3546.test.tsx`:切片四埋的围堵钉按其
  自述翻转 —— 从「字面量与 zh 包逐字节相同」改为钉住门已移除,并把不变量放
  宽一步:`convZh` 只许门控出站 `*Message`,任何新读点都会红。

反向验证(方向先判后跑,与预判一致):还原三元 → 3 红 —— i18n 钉子按自定义
消息点名、en 控制台用例、de 控制台用例;zh 控制台用例与三条出站文本保持绿
(前者按设计逐字节相同,不具区分力,已在测试头注明)。

顺带:`conversationLanguage.ts` 模块头把 progress labels 也列进「随会话」,
该句在本改动后不再为真,收窄为「只治离开控制台发给 agent 的文本」。

写钉子时量到发送半边另有一个缺陷(zh 控制台 + 英文会话会把中文确认句发进英
文线程;`planAnswerMessage` 完全没有门控),不在本单范围,已立 objectstack-ai#3896。

测试:`packages/app-shell/src/console/ai` + `packages/i18n` 47 文件 654 通过;
两包 type-check 通过,全仓 `turbo run type-check` 78/78 通过;改动文件
eslint 零告警;`check-control-bytes` / `check-i18n-call-site-keys` /
`check-i18n-en-drift` 均通过(零 en 值变更)。

Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt

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

* test(app-shell): 钉子里的 agent 桩改用具名类型断言,不用 as never

评审可读性,零行为改动:`ChatPane` 的 agents 桩从 `as never` 改成
`as unknown as AgentDescriptor`(类型导入,运行期擦除;该模块在本文件里被
vi.mock,类型不受影响)。

Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal pushed a commit to akarma-synetal/objectui that referenced this pull request Aug 10, 2026
…ectstack-ai#3921)

objectstack-ai#772 / objectstack-ai#2884 立下的规则写在 `AiChatPage` 的门上:出站文本随**会话**语言,渲染
标签随 UI 语言。规则只实现了一半 —— 三条出站文本写作
`convZh ? '<中文字面量>' : t('console.ai.…')`,而 `t()` 读的是 **UI 包**,于是
「非中文」那一支答的是 UI 语言、不是英文;第四条 `planAnswerMessage` 连门都没过。

两个方向各一个已实测后果:

- **zh 控制台 + 英文会话发出中文。** zh 包定义了全部四个 key,所以 `t()` 是命中
  而非落到英文 defaultValue:点 Build it,进英文线程的是 `确认,开始搭建。`。cloud
  确认门(`service-ai-studio` `confirm-gate.ts` `APPROVAL_RE`)两种语言都认,构建
  照走,agent 随后把整条线程转成中文 —— 即 objectstack-ai#2884 的症状、触发方向相反。
- **一键回答芯片两个方向都发 UI 语言。** 完全未门控:中文会话里发出
  `For "…", go with: …`(objectstack-ai#772 开头那句抱怨的字面重演),zh 控制台下的英文会话里
  发出中文句子。

四个站点现在统一走一个取值器 `outboundAgentText.ts`:中文会话取 `zh` 包该 key,
其余会话取 `en` 包该 key,永不读 UI 包。三个控制台 AI 界面(`/ai` 页、chat dock、
Studio copilot)都挂同一个 `ChatPane`,一并生效。

直接读两个包而不用 `t(key, { lng })` 是刻意的:i18next 的答案取决于宿主 app 装了
哪些 bundle 以及 `fallbackLng`,而 zh 查询静默回落到 en 正是上面那个错语言 bug。
取值器内的兜底表按语言分,并被钉成与两个包逐字节一致 —— 万一某个包不再定义该 key,
中文会话兜底到中文,绝不兜到英文。

标签未动:仍随 UI 语言。objectstack-ai#3837 那条「`*Label` 漂回会话门就红」的钉子现在同时守住
反向 —— 出站 `*Message` 被重新塞回 `t()` 也会红。


Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt

Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal pushed a commit to akarma-synetal/objectui that referenced this pull request Oct 7, 2026
…8 cloud E2E (six of seven) (objectstack-ai#10924)

Refs objectstack-ai#10899 — six of its seven items land here; item 4 needs a
maintainer decision and the replay-ordering half of item 5 is
root-caused but not changed, so the card stays open.

Part of objectstack-ai/cloud#2440

Clause-②: no

One commit per item, each with its own test, ablation and changeset.
Session
`https://claude.ai/code/session_786273a0-0246-4bb2-b026-bb37ba5d7295`
(dispatch branch `claude/issue-10899-hosted-console-ux-defects`).

## Verdict per item

| # | Item | Verdict |
|---|---|---|
| 1 | Assistant FAB covers the dock's send button | **done** — the FAB
renders only while the dock is collapsed (`ConsoleLayout`) |
| 2 | Failed record comment shown as sent | **done** (objectui half of
cloud#2431, per the ruling that cloud mounts audit on hosted tenants) —
a comment/reply lands only after its `sys_comment` write resolves; a
failed write shows a localized toast and the composer keeps the draft |
| 3 | Dashboard 403 renders as a raw English exception | **done** —
`queryDataset` throws a typed `AnalyticsForbiddenError` for 403
`PERMISSION_DENIED`; `DatasetWidget` renders a localized no-access
state. The missing grant itself is cloud#2439 |
| 4 | Assistant scope chip says 「新建应用」 inside an app | **open — needs a
maintainer decision** (below). Not changed here |
| 5 | Empty 「执行过程」 blocks; replay orders steps differently | **empty
blocks: done**. **Ordering: root-caused, producer outside this change**
(below). Not changed here |
| 6 | Studio edit/design offered to a non-platform-admin | **done — the
producer is the console**. The server's permission answer is already
right; the console ignored it |
| 7 | Marketplace labels an older version as an update | **done** —
"update" means higher SemVer 2.0.0 precedence, at both call sites |

## What each commit does

- **Item 7** — `versionPrecedence.ts` orders two versions by SemVer
2.0.0 §11 (the grammar the package manifest declares for `version`).
`cloudUpdateAvailable` and the install dialog's per-environment
`hasUpdate` both use `isNewerVersion` instead of `!==`. Non-SemVer or
equal pairs offer no update.
- **Item 1** — the FAB is the dock's collapsed affordance (ADR-0057 open
question 2). `ConsoleLayout` now renders it only while `dock.expanded`
is false, which is the rule `ChatDockLauncher` already follows.
- **Item 6** — the page pencil (`PageView`) and the top-bar hammer
(`AppHeader`) required only the workspace-admin role, and an org owner
holds that role. Both now also require `manage_metadata` through
`useCanAuthorMetadata`, which reads `GET /api/v1/auth/me/permissions`.
HomePage's builder CTAs already use the same check. If the server
reports no `systemPermissions`, the check fails open, so older servers
keep the admin-only behaviour.
- Measured producer: on the PM's rig control DB (read-only), the
signed-up owner holds `cloud_control_plane_member` (no system
permissions) and `organization_admin_no_bypass` = `manage_org_users,
setup.access, setup.write`. Framework's `organization_admin` withholds
`manage_metadata` on purpose. So the server's answer was correct and the
console did not read it.
- **Item 2** — `RecordDetailView` no longer adds optimistic rows. It
awaits the `create`, then appends the row. On failure it shows
`toast.error(detail.commentFailed)` (new key, all ten packs) and rejects
back to the caller.
- The three composers (`RecordActivityTimeline`, `ThreadedReplies`,
`RecordComments`) now handle a rejected `onAddComment` / `onAddReply`
explicitly: they keep the draft. Before this, the throw escaped as an
unhandled rejection.
- `RecordDetailView.feedRecordScope.test.tsx` had a case that asserted
the opposite of the ruling ("keeps an unpersisted comment when the write
never lands"). It is rewritten to the ruled behaviour.
- **Item 3** — `queryDataset` gains a code-based branch for the
analytics read admission's `403` + `PERMISSION_DENIED`
(`readAdmissionDeniedError` in `@objectstack/service-analytics`). The
new `AnalyticsForbiddenError` carries `httpStatus: 403` and `code:
'PERMISSION_DENIED'`. `DatasetWidget` classifies the error with the
shared `classifyLoadError`, the same classifier the list view uses. For
`forbidden` it renders `dashboard.widgetForbiddenTitle` /
`widgetForbiddenMessage` (new, all ten packs). A 403 with no code keeps
the generic error.
- **Item 5 (empty blocks)** — a reloaded build hydrates one assistant
message per persisted step, and each step's text is the `(called …)`
placeholder. `ChatbotEnhanced` now shows the 执行过程 note only when the
turn shows no tool row and no build or design panel. The copy/regenerate
bar renders only for a turn with visible prose. The objectstack-ai#772 fallback, where
a placeholder turn with nothing else keeps its note, is preserved and
pinned.

## Item 4 — why it is not changed here

The in-app dock runs the build agent on an app-less, product-only
conversation scope (`ChatDock.tsx`, `chatConversationScope` with no
`appId`). It sends no package binding. So in ADR-0057 Amendment A1's
terms the chip is telling the truth: the thread is unbound, and "New
app" is the unbound label. A1.b also records the dock keeping the legacy
product-only key as a decision. Making the chip name the current app
means either:

- **A** — bind the dock's build thread to the current app's package
(`editPackageId` + `app:PKG:build` scope). The agent then gets a
declared write target, and the dock, `/ai/build?package=` and the Studio
copilot share one thread. This reverses the A1.b decision.
- **B** — relabel the unbound chip. The agent would still guess the
target app.

Recommendation: A, for the build product only, and only when the active
app is an authorable package. Details are in the report on the card. It
changes a decided ADR line, so it waits for the maintainer.

## Item 5 — replay ordering (measured, not changed)

I read the rig tenant DB (`ai_messages`, read-only). The follow-up
proposal turn (EFYj) was still persisting its last `todo_write` and
final prose at 04:36:42–44Z. The user's 「确认,开始搭建。」 (turn dh2L) was
persisted at 04:36:39Z. The conversation store orders by `created_at,
id` across turns (cloud
`packages/service-ai/src/conversation/objectql-conversation-service.ts`,
`MESSAGE_ORDER`). The replay therefore puts the confirm message inside
the previous turn's steps, while the live run showed that turn whole.

Two things contribute:
- the store orders by time, not by turn (cloud);
- the plan card's build button stays clickable while its own turn is
still streaming (`ChatbotEnhanced`).

Both are named in the report.

## Tests

All runs are on HEAD `d8969d4bc` unless noted.

- New pins (one per item, each ablated — revert the fix → red, restore →
`git diff HEAD` empty):
- item 7: `versionPrecedence-10899.test.ts`,
`MarketplacePackagePage.updateIsHigherVersion-10899.test.tsx` (ablation:
1 failed)
- item 1: `ConsoleLayout.fabYieldsToOpenDock-10899.test.tsx` (1 failed)
- item 6: `PageView.editInStudioNeedsAuthoring-10899.test.tsx`,
`AppHeader.designInStudioNeedsAuthoring-10899.test.tsx` (2 failed)
- item 2: `RecordDetailView.commentWriteFailure-10899.test.tsx` + the
rewritten feed-scope case (3 failed). Composer half:
`composerKeepsDraftOnRejection-10899.test.tsx` — with the `catch`
removed, the run exits 1 on unhandled rejections while the draft
assertions still pass. Keeping the draft used to be an accident of the
throw.
- item 3: `queryDataset.forbidden-10899.test.ts`,
`DatasetWidget.forbiddenState-10899.test.tsx` (2 failed)
- item 5: `ChatbotEnhanced.hydratedStepTurns-10899.test.tsx` (2 failed)
- Package suites: one `vitest run` over `packages/app-shell/
packages/plugin-chatbot/ packages/plugin-dashboard/
packages/data-objectstack/ packages/plugin-detail/ packages/i18n/` —
`Test Files 1409 passed | 2 skipped (1411)`, `Tests 14850 passed | 23
skipped (14873)`, exit 0
- Build: `turbo run build` for the six touched packages plus the
`@object-ui/app-shell^...` closure — 29/29 successful.
- Type-check: `turbo run type-check` for the six packages — 6/6
successful.
- `check:i18n-keys`, `check:i18n-drift`, `check:i18n-dead-keys`,
`check:new-line-citations` (0 new), `check:control-bytes`,
`check-changeset-presence` (6 changesets for 6 packages),
`check-changeset-no-major` — all exit 0.
- Lint, narrowed to this diff: `eslint --no-inline-config` over the 33
changed `.ts`/`.tsx` files. For every pre-existing file, the
error/warning counts at HEAD equal its counts at the merge base (the
only errors are 4 pre-existing `no-console` in
`data-objectstack/src/index.ts`, 4/127 → 4/127). New files have 0
errors. Type-aware linting is not enabled, so this diff cannot change
the verdict on any untouched file. The repo-wide lint belongs to CI.

## Acceptance notes

- ⚠️ The shared verify lock was **not taken**: the wrapper reported
`UNLOCKED (declared) · no usable flock on this host`. Build, type-check
and suites ran unserialized.
- NOT MEASURED: an in-browser check of the six fixes. The PM's rig was
observed through its screenshots and read-only DB reads only — no
sign-in, no writes.
- Out of scope, noted and not filed:
- `handleToggleReaction` still swallows a failed reaction write (same
optimistic shape as item 2; no carrier).
- The reply input (`ThreadedReplies`) renders only under an item with
`replyCount > 0`, and no feed read sets that, so a loaded discussion
offers no reply affordance.
- Other admin-role-only authoring affordances (view add/rename/delete in
`ObjectView`, the report editor, `ObjectDataPage`) do not read
`manage_metadata`. Same class as item 6, not measured on the control
plane.
- `ObjectChart`'s dataset path, `DatasetReportRenderer` and
`DashboardFilterBar` still print the (now typed, English) refusal
message instead of a localized state.
- Changesets: six, all `patch`.

---

_Generated by [Claude
Code](https://claude.ai/code/session_786273a0-0246-4bb2-b026-bb37ba5d7295)_

---------

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

This branch had an error being deployed

2 failed and 1 active deployments
Preview – objectui — 33361fef Deployed Feb 23, 2026 by vercel[bot]
Preview – objectui-storybook — 33361fef Deployed Feb 23, 2026 by vercel[bot]
Preview – objectui-demo — 33361fef Deployed Feb 23, 2026 by vercel[bot]
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.

0 participants