Skip to content

fix(actions): forward bodyShape so a declared body wrap is honoured (objectstack#6938) - #3932

Merged
yinlianghui merged 3 commits into
mainfrom
claude/issue-os6938-bodyshape-forward
Aug 9, 2026
Merged

fix(actions): forward bodyShape so a declared body wrap is honoured (objectstack#6938)#3932
yinlianghui merged 3 commits into
mainfrom
claude/issue-os6938-bodyshape-forward

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixesobjectstack-ai/objectstack#6938

bodyExtra(objectstack#6837 / #3924)的姊妹单,同一个转发白名单形状,换一个键。

缺陷

bodyShape 是 spec 给 type: 'api' 动作的 body 包裹声明 —— 'flat'(默认)或 { wrap: key } 把采集到的参数嵌到该键下(better-auth organization/update 就是它存在的理由)。console apiHandler 无条件读它,而五个动作渲染器一个都不转发。于是声明了 bodyShape: { wrap: 'data' } 的 action:button 类动作实际发出扁平 body:端点在顶层收到参数,而声明看起来是"已兑现"的 —— 因为它能解析、能发布。

改动

  1. 四个 declared-action 渲染器(action-{button,group,icon,menu}.tsx)白名单补 bodyShape 转发,就在 #6837 刚补的 bodyExtra 旁边。
  2. ActionSchema(packages/types/src/ui-action.ts)声明该键,按 fix(actions): forward bodyExtra end-to-end through the action chain #3924 的先例从 SpecAction['bodyShape']派生,联合类型无法与契约漂移。
  3. ActionRunner.executeAPI(无宿主注册 api handler 时走的回退路径)也开始读它。这一条超出 issue 正文点名的四个文件,理由写在下面。

为什么连 ActionRunner 一起补

只修渲染器会留下同一缺陷的窄版:console apiHandlerRecordDetailView.apiHandler 都兑现 wrap,而 runner 回退不兑现 —— 同一个动作会因为承载它的宿主不同而改变 body 形状,这正是"声明 ≠ 兑现"再往下一跳。

关键是这里没有需要猜的语义。spec 自己的措辞是:{ wrap: 'data' } "nests the user-collected params under that key … while recordIdParam and other top-level keys stay flat"。两个 console 读点(useConsoleActionRuntime.tsx:277RecordDetailView.tsx:670)实现的正是这个次序 —— 先构造 wrap,再把 recordIdParam / organizationId / bodyExtra 平铺到顶层。所以只有一个读法要镜像,不是一个要做的选择。runner 现在与之逐字一致:包裹只覆盖采集到的 payload,bodyExtra 平铺在旁。

element:button 故意不补

它的转发列表逐字段镜像 spec 的 InlineActionSchema pick list(该文件自己的注释就这么写),而那份 pick list 不含 bodyShape —— 已用 git show origin/main:packages/spec/src/ui/action.zod.ts 亲验,13 个 pick 为 type name label target openIn method params bodyExtra confirmText successMessage errorMessage refreshAfter opensInNewTabbodyShape 不是 inline 词汇,而 spec 对这个边界的规矩是明写的:"Widen this when a renderer widens, not before",且窗口只能 spec 先行,不能渲染器先行。从 element:button 转发它就是被禁的那个方向。

spread 型宿主(DeclaredActionsBar / RelatedRecordActionsBridge / ObjectGrid)转发整个 def({ params: rawParams, ...rest }),天然携带该键,免改 —— 已抽查 DeclaredActionsBar.tsx:135,其注释本就点名 bodyShape

测试

新增两个文件,在两端断言:runner 收到什么(转发本身),以及线上是什么形状(转发加 body 组装)。只查 props 的测试会在 payload 依然丢失时保持绿色。

  • packages/components/src/__tests__/action-bodyShape-forward.test.tsx —— 四个渲染器各一条转发;端到端两条(真实 fetch,断言 { data: {...} },以及 bodyExtra 平铺在 wrap 旁);无 bodyShape 时扁平 body 的回归钉。
  • packages/core/src/actions/__tests__/ActionRunner.bodyShape.test.ts —— runner 自身 7 条:wrap 生效、无 params 时包裹 context record、bodyExtra 保持平铺、ApiConfig 分支同样生效、'flat' 与缺省两条扁平钉,以及一条 off-spec 值退化为文档默认值(而不是在线上造出一个字面量 undefined 键)。

反向验证(方向先判后跑,两次都是标准 red):

  • 只回退四处渲染器转发 → 4 条转发断言 + 2 条端到端 wrap 断言变红(expected undefined to deeply equal { wrap: 'data' }),扁平钉保持绿。
  • 只回退 runner 的 wrap 分支 → 4 条 runner wrap 断言 + 2 条端到端变红(expected { name: 'Acme Inc', slug: 'acme' } to deeply equal { data: { … } }),4 条渲染器转发断言与两处扁平钉保持绿。

如实记一处:那条 off-spec 退化用例在 runner 改动前后都是绿的(改动前 runner 根本不读该键,行为也是扁平),所以它对本次改动不具判别力 —— 它是往后防止 wrap 分支在坏值上造键的钉子,不是本次修复的证据。

验证

  • pnpm exec vitest run packages/components/ packages/core/ --maxWorkers=2174 files / 2358 tests passed
  • 消费半径复查(渲染器的宿主):pnpm exec vitest run packages/app-shell/ packages/plugin-grid/361 files / 3285 passed, 1 skipped
  • pnpm exec turbo run type-check --concurrency=278 successful, 78 total
  • pnpm check:control-bytes → OK(3808 个文本文件);pnpm changeset:check → OK
  • changeset:patch,覆盖 @object-ui/components / @object-ui/core / @object-ui/types

Base:5e524950d(含 #39247e5bb5d4e)。

正文点名的通用 pin test(渲染器转发键集 vs runtime 实读键集 diff)未在本 PR 落地,理由与后续单见评论。


Generated by Claude Code

`bodyShape` is the spec's body-wrapping declaration for a `type: 'api'`
action — `'flat'` (default) or `{ wrap: key }` to nest the collected params
under `key`. The console `apiHandler` read it unconditionally while ZERO
action renderers forwarded it, so an author declaring `bodyShape: { wrap:
'data' }` got a FLAT body on the wire: the endpoint received the params at
the top level and the declaration read as honoured because it parsed and
published. Same forwarding-whitelist shape as bodyExtra (objectstack#6837).
The four declared-action renderers (action:button / :group / :icon / :menu)
now forward the key, and `ActionSchema` declares it, typed by derivation
from the spec so the union cannot drift from the contract.
`ActionRunner.executeAPI` — the fallback path taken when no host registered
an `api` handler — now reads it too. Without that, fixing only the renderers
would have left a narrower version of the same defect: the console
apiHandler and RecordDetailView.apiHandler both wrapped and the runner's
fallback did not, so one action changed body shape with the host that ran
it. The wrap covers the collected payload only; bodyExtra and other
top-level keys stay flat — the spec's own wording for the key, and what both
console read-sites already implemented, so there was one reading to mirror
rather than a choice to make.
`element:button` deliberately does NOT forward it: its whitelist mirrors
spec's `InlineActionSchema` pick list field for field, and that pick list
(verified against packages/spec/src/ui/action.zod.ts on objectstack
origin/main) does not include `bodyShape`. It is not inline vocabulary, and
that boundary opens spec-first, never renderer-first.
Fixesobjectstack-ai/objectstack#6938
@vercel

vercelBot commented Aug 9, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectuiIgnoredIgnoredAug 9, 2026 8:30am

Request Review

@yinlianghuiClaude

Copy link
Copy Markdown
CollaboratorAuthor

通用 pin test 为何不在本 PR 落地

objectstack#6938 正文建议加一条 pin —— 把渲染器的转发键集与 runtime 实读键集 diff,让下一个新键响亮地失败而不是静默丢失。分诊已注记其为非绑定候选。评估后不在本 PR 落地,已单列为 objectstack-ai/objectstack#6975(finding,未派单)。

理由是它需要两份输入,而只有一份可机械推导:

  • 可推导:各渲染器的转发键集 —— AST 读取传给 execute(...) 的对象字面量。packages/core/src/actions/__tests__/actionKeys.pin.test.ts 已经在做同类走查(用 typescript 编译器 API 从接口读 ActionDef 成员),技法在仓内是成立的。
  • 不可推导:"runtime 实读的键"。读点横跨 packages/core(ActionRunner)与 packages/app-shell(useConsoleActionRuntime.apiHandlerRecordDetailView.apiHandler),git grep 'action\.' 会捞出一大堆 action.name / action.objectName / action.api / action.method,无法把"渲染器该转发的 body 路径键"与"runner 自己解析的机制键"分开。grep 出来的是一份误报清单,不是契约。

而且遗漏本身是承重的,不是噪声:recordIdParam 五个渲染器都不转发,这是对的 —— #6938 已核实,apiHandler 只在 if (rowRecord && action.recordIdParam) 下读它,而 rowRecord 只从 spread 型宿主来,那些宿主同时携带 recordIdParam,所以它在 declared 渲染器上不可达,不是坏的。element:button 不含 bodyShape 同样是刻意的(镜像 InlineActionSchema pick list)。

于是机械 diff 旁边必须再挂一份手工维护的"已论证豁免"清单 —— 那恰恰是这整条线索要消灭的那种会漂移的清单,只是上移了一层。这是"每个渲染器面欠 runtime 哪些键"的契约该落在何处的设计决策,不是能顺手拧上的测试,应由维护者定而不是 dev 在修 bug 途中猜。#6975 列了三个方向(声明式生成 / 仅钉渲染器间一致 / spec 侧标注)及各自代价,本 PR 刻意不在其间做选择。

本 PR 内的替代覆盖:两个新测试文件把本次修复的键钉在两端(runner 收到什么 + 线上什么形状),并对两处反向验证记录了预判方向。这不能防住下一个键 —— 那正是 #6975 的题目。


Generated by Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)28.1 KB350 KB
Entry fileindex-4FbG6W_b.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)8.66KB3.13KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)7.57KB2.97KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)22.10KB4.37KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)35.76KB9.11KB
auth (createAuthenticatedFetch.js)4.37KB1.69KB
auth (index.js)2.35KB1.07KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)4.91KB0.87KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)482.64KB106.39KB
core (index.js)3.00KB1.14KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)139.61KB35.99KB
fields (index.js)231.13KB56.80KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.32KB1.77KB
i18n (index.js)2.65KB1.06KB
i18n (pickLocalized.js)1.70KB0.83KB
i18n (provider.js)9.48KB3.27KB
i18n (useObjectLabel.js)27.59KB6.63KB
i18n (useSafeTranslation.js)4.52KB1.96KB
layout (index.js)38.53KB10.71KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)8.75KB3.06KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)3.67KB1.12KB
permissions (evaluator.js)4.41KB1.44KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.55KB0.71KB
plugin-ai (index.js)15.71KB3.79KB
plugin-calendar (index.js)44.98KB12.37KB
plugin-charts (index.js)61.04KB17.31KB
plugin-chatbot (index.js)180.33KB42.79KB
plugin-dashboard (index.js)117.21KB30.27KB
plugin-designer (index.js)210.51KB42.51KB
plugin-detail (index.js)236.63KB59.02KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)112.10KB27.10KB
plugin-gantt (index.js)162.55KB39.57KB
plugin-grid (index.js)187.63KB49.66KB
plugin-kanban (index.js)48.30KB13.28KB
plugin-list (index.js)109.67KB26.55KB
plugin-map (index.js)16.81KB5.24KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)40.58KB10.58KB
plugin-timeline (index.js)25.76KB7.33KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.03KB20.55KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.71KB3.53KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.67KB2.37KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)20.15KB6.72KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.02KB0.55KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)4.09KB1.74KB
sdui-parser (index.js)4.47KB2.03KB
sdui-parser (parse.js)10.04KB2.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)4.69KB1.48KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-retry.js)4.32KB2.02KB
types (index.js)2.71KB1.34KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)0.20KB0.18KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)28.1 KB350 KB
Entry fileindex-4FbG6W_b.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)8.66KB3.13KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)7.57KB2.97KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)22.10KB4.37KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)35.76KB9.11KB
auth (createAuthenticatedFetch.js)4.37KB1.69KB
auth (index.js)2.35KB1.07KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)4.91KB0.87KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)482.64KB106.39KB
core (index.js)3.00KB1.14KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)139.61KB35.99KB
fields (index.js)231.13KB56.80KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.32KB1.77KB
i18n (index.js)2.65KB1.06KB
i18n (pickLocalized.js)1.70KB0.83KB
i18n (provider.js)9.48KB3.27KB
i18n (useObjectLabel.js)27.59KB6.63KB
i18n (useSafeTranslation.js)4.52KB1.96KB
layout (index.js)38.53KB10.71KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)8.75KB3.06KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)3.67KB1.12KB
permissions (evaluator.js)4.41KB1.44KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.55KB0.71KB
plugin-ai (index.js)15.71KB3.79KB
plugin-calendar (index.js)44.98KB12.37KB
plugin-charts (index.js)61.04KB17.31KB
plugin-chatbot (index.js)180.33KB42.79KB
plugin-dashboard (index.js)117.21KB30.27KB
plugin-designer (index.js)210.51KB42.51KB
plugin-detail (index.js)236.63KB59.02KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)112.10KB27.10KB
plugin-gantt (index.js)162.55KB39.57KB
plugin-grid (index.js)187.63KB49.66KB
plugin-kanban (index.js)48.30KB13.28KB
plugin-list (index.js)109.67KB26.55KB
plugin-map (index.js)16.81KB5.24KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)40.58KB10.58KB
plugin-timeline (index.js)25.76KB7.33KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.03KB20.55KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.71KB3.53KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.67KB2.37KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)20.15KB6.72KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.02KB0.55KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)4.09KB1.74KB
sdui-parser (index.js)4.47KB2.03KB
sdui-parser (parse.js)10.04KB2.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)4.69KB1.48KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-retry.js)4.32KB2.02KB
types (index.js)2.71KB1.34KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)0.20KB0.18KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

@yinlianghuiClaude

Copy link
Copy Markdown
CollaboratorAuthor

📌 状态(objectui 分片 PM,session session_01GTRjn8xBqp75dk7kFupVRt):本 PR 内容已实物核验,唯一 CI 红与本 PR 文件面无关 —— Test shard 1/4 两连红(head ba2ed1e06 与 update-branch 后的新 merge ref)同签名:ContextSelectors.persist.test.tsx 的 query 首用例 expected 'billing' to be 'crm_core'

诊断:该用例(objectui#3922 带入)在 optionsReady 后立即点击,与 SelectorControl 的 auto-select-first effect 竞速,高负载 worker 下 effect 后发、以过期闭包把 pick 覆盖回首项。本 PR 新增两个测试文件改变 shard 打包组合,把这条竞态变成该组合下的稳定红。已立 objectstack-ai/objectstack#6979 并派修(测试 settle-then-click 为主修,组件侧竞态根因顺带评估)。

处置:#6979 修入 main 后本 PR update branch 重跑即入队;两连红均非本 PR 缺陷,不改本 PR 内容。


Generated by Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)28.1 KB350 KB
Entry fileindex-BoDf2vR3.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)8.66KB3.13KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)7.57KB2.97KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)22.10KB4.37KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)35.76KB9.11KB
auth (createAuthenticatedFetch.js)4.37KB1.69KB
auth (index.js)2.35KB1.07KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)4.91KB0.87KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)482.64KB106.39KB
core (index.js)3.00KB1.14KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)139.61KB35.99KB
fields (index.js)231.13KB56.80KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.32KB1.77KB
i18n (index.js)2.65KB1.06KB
i18n (pickLocalized.js)1.70KB0.83KB
i18n (provider.js)9.48KB3.27KB
i18n (useObjectLabel.js)27.59KB6.63KB
i18n (useSafeTranslation.js)4.52KB1.96KB
layout (index.js)38.53KB10.71KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)8.75KB3.06KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)3.67KB1.12KB
permissions (evaluator.js)4.41KB1.44KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.55KB0.71KB
plugin-ai (index.js)15.71KB3.79KB
plugin-calendar (index.js)44.98KB12.37KB
plugin-charts (index.js)61.04KB17.31KB
plugin-chatbot (index.js)180.33KB42.79KB
plugin-dashboard (index.js)117.21KB30.27KB
plugin-designer (index.js)210.51KB42.51KB
plugin-detail (index.js)236.63KB59.02KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)112.10KB27.10KB
plugin-gantt (index.js)162.55KB39.57KB
plugin-grid (index.js)187.63KB49.66KB
plugin-kanban (index.js)48.30KB13.28KB
plugin-list (index.js)109.67KB26.55KB
plugin-map (index.js)16.81KB5.24KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)40.58KB10.58KB
plugin-timeline (index.js)25.76KB7.33KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.03KB20.55KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.71KB3.53KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.67KB2.37KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)20.15KB6.72KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.02KB0.55KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)4.09KB1.74KB
sdui-parser (index.js)4.47KB2.03KB
sdui-parser (parse.js)10.04KB2.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)4.69KB1.48KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-retry.js)4.32KB2.02KB
types (index.js)2.71KB1.34KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)0.20KB0.18KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

@yinlianghuiClaude

Copy link
Copy Markdown
CollaboratorAuthor

验收通过(objectui 分片 PM,session session_01GTRjn8xBqp75dk7kFupVRt)objectstack-ai/objectstack#6938(v17 收官单)

实物核验(前序评论已记录):单提交 9 文件,四个 declared-action 渲染器补 bodyShape 转发 + runner buildApiRequestBody wrap 分支(纳入范围的两个前置条件 —— 成本低、语义唯一 —— 论证成立:spec 自述与两个 console 读点三方一致,wrap 只罩收集载荷、bodyExtra 平铺);element:button 不补的论证经双路径核验(运行时 walk + 源码 pick list 均无 bodyShape);ActionSchema.bodyExtra 后追加 bodyShape 同以 spec 派生。反向验证两处方向相反且均与预判吻合;off-spec 降级用例的非判别性自我declared诚实。

CI 亲读终态(update branch 携 #6979 修复后):20 检查全 completed、0 失败,原两连红的 Test shard 1/4 转绿 —— 前两次红已确证为 ContextSelectors persist 测试的 auto-select 竞态(objectstack#6979,PR #3933 已修入 main),与本 PR 文件面无关。

dev 另记的 rc 漂移观察(安装版 spec rc.5 的 InlineActionSchema pick list 尚无 bodyExtra,源码已有 —— spec-first 方向一致,无需动作)与 finding objectstack#6975(转发白名单 vs 运行时实读键集无门禁,三方向待裁)已入档,冻结期不派。


Generated by Claude Code

@yinlianghui
yinlianghui marked this pull request as ready for review August 9, 2026 08:50
@yinlianghui
yinlianghui added this pull request to the merge queueAug 9, 2026
Merged via the queue into main with commit c2fd122Aug 9, 2026
21 checks passed
@yinlianghui
yinlianghui deleted the claude/issue-os6938-bodyshape-forward branch August 9, 2026 08:51
Sign up for freeto 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.

objectui: bodyShape is read by the console apiHandler but forwarded by ZERO action renderers — a declared wrap is silently dropped

2 participants

@yinlianghui@claude