Skip to content

feat(flow-designer): the script node's form authors what the executor runs (framework#4278) - #3099

Merged
os-zhuang merged 2 commits into
mainfrom
claude/schemaless-nodes-designer-forms-y1g7q0
Jul 31, 2026
Merged

feat(flow-designer): the script node's form authors what the executor runs (framework#4278)#3099
os-zhuang merged 2 commits into
mainfrom
claude/schemaless-nodes-designer-forms-y1g7q0

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

framework#4278 的 objectui 半边(spec 半边:objectstack-ai/objectstack#4325)。

问题

script 节点的表单只存在于本仓手写的 FLOW_NODE_CONFIG(引擎有意不为它发布 configSchema),且与执行器已经漂移:四个 actionType 选项里 code 是 no-op(内置运行时无服务端 JS 沙箱)、sms/notification 每次运行必然失败(不在内置集合,被当函数名解析);复数「Output variables」无人读;而唯一真正执行逻辑的路径(function + inputs + outputVariable)完全无法授权。

改动

  • actionType 只提供「调用函数(默认)/ Email / Slack」——即执行器的分发集合(SCRIPT_BUILTIN_ACTION_TYPES + invoke_function 标记)。函数路径三字段成为一等公民。
  • 内联 script 正文改为仅存量渲染:新节点不再提供,存量值仍显示并附「不执行,请改用注册函数」提示;死键 outputVariables 删除,存量值落到 Advanced (JSON) 块。
  • 标量 select 的存量未知值渲染为 <value> (deprecated) 选项而非空白——沿用 FlowObjectListField 对 select 单元格的既有规则。
  • 数据选择器(flow-scope)与流程模拟器不再假装 outputVariables[] 会绑定变量——引擎从不绑定这些名字,只绑定单数 outputVariable
  • 新增跨仓对账测试flow-node-config.spec-reconciliation.test.ts:手写的 script/subflow/decision 组与 spec 发布的执行器派生契约做双向键集对账,wait/connector_action/boundary_event 组与 FlowNodeSchema sibling 块对账。retiredKey() 墓碑不计入契约键集——已用 @object-ui/fields deep subpaths resolve only through the repo vitest alias — its exports map publishes none of them #4325 的 spec 构建验证:三个新面板对账全绿,且 wait 面板会在 spec 18 升版时准确点名 waitEventConfig.timeoutMs/.onTimeout(framework#4198 已退役、表单尚未跟进)——这正是 ratchet 的本意,升版 PR 需一并删掉这两个字段。依赖新导出的面板 feature-detect,在当前 rc.0 下跳过、升版后自动激活。

验证

  • 定点 + 全仓测试:771 文件 / 9002 用例全绿;改动文件 eslint 无告警。
  • Preview gallery(?only=flow)浏览器实测:遗留 code 样例的存量正文以「Code (not executed)」渲染并带引导文案;函数路径字段默认展示;actionType 下拉精确等于三个选项;email 节点正常显示模板/收件人/模板变量。
  • changeset:@object-ui/app-shell minor。

🤖 Generated with Claude Code

https://claude.ai/code/session_01Ki9WjmmSY19koz9hNkeL1P


Generated by Claude Code

… runs (framework#4278)
The script flow node's designer form is hand-written here (the engine
publishes no configSchema for it, deliberately) and had drifted from the
executor: of four offered actionType options, `code` was a recognized
no-op, `sms` / `notification` failed every run, the plural
"Output variables" field was read by nothing — and the one path that runs
real logic (function + inputs + outputVariable) could not be authored.
- actionType now offers Call function (default) / Email / Slack — the
executor's dispatch set (SCRIPT_BUILTIN_ACTION_TYPES + the
invoke_function marker). The function-path fields are first-class.
- The inline `script` body becomes render-only: hidden for new nodes,
shown (with a not-executed warning) whenever a stored node carries one.
The dead plural outputVariables field is removed; stored values surface
in the Advanced (JSON) block.
- A scalar select whose stored value was dropped from the options renders
it as "<value> (deprecated)" instead of blanking it — the rule
FlowObjectListField already applied to select cells.
- flow-scope (data picker) and the flow simulator stop pretending the
legacy outputVariables[] list binds variables — the engine never binds
those names; only the singular outputVariable does.
- New reconciliation test compares the hand-written script / subflow /
decision groups bidirectionally against the executor-derived contracts
@objectstack/spec/automation publishes for exactly this purpose, and
the wait / connector_action / boundary_event groups against the
FlowNodeSchema sibling blocks. `retiredKey()` tombstones are excluded
from the contract key set, so a form field for a retired key fails
loudly instead of false-passing — verified against the framework#4278
spec build: script/subflow/decision reconcile green, and the wait
panel correctly fires on `waitEventConfig.timeoutMs` / `.onTimeout`
(retired at spec 18, framework#4198), which the 18 bump must drop from
the wait form. The spec-export panels feature-detect and skip on the
installed rc.0 spec, arming themselves on the next bump.
Verified in the preview gallery (?only=flow): the legacy code sample
renders the stored body under "Code (not executed)", the function-path
fields show by default, and the select offers exactly the three options.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ki9WjmmSY19koz9hNkeL1P
@vercel

vercelBot commented Jul 31, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectuiIgnoredIgnoredJul 31, 2026 6:38am

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests labels Jul 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)27.9 KB350 KB
Entry fileindex-ckr4lebD.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)8.26KB2.99KB
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.12KB3.41KB
auth (LoginForm.js)17.86KB5.29KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.43KB2.09KB
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)18.38KB4.49KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)3.65KB1.42KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.25KB0.53KB
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)473.75KB103.77KB
core (index.js)2.16KB0.78KB
create-plugin (index.js)9.28KB2.98KB
data-objectstack (index.js)136.34KB34.64KB
fields (index.js)222.07KB54.35KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.32KB1.77KB
i18n (index.js)2.46KB0.96KB
i18n (pickLocalized.js)1.70KB0.83KB
i18n (provider.js)5.37KB1.72KB
i18n (useObjectLabel.js)25.17KB5.80KB
i18n (useSafeTranslation.js)3.26KB1.44KB
layout (index.js)38.44KB10.66KB
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.05KB1.53KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)8.76KB3.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 (retry.js)3.48KB1.61KB
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.90KB12.35KB
plugin-charts (index.js)60.52KB17.11KB
plugin-chatbot (index.js)180.09KB42.72KB
plugin-dashboard (index.js)111.59KB28.74KB
plugin-designer (index.js)210.51KB42.50KB
plugin-detail (index.js)221.81KB54.28KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)111.38KB26.93KB
plugin-gantt (index.js)162.26KB39.53KB
plugin-grid (index.js)182.21KB48.24KB
plugin-kanban (index.js)47.82KB13.18KB
plugin-list (index.js)103.85KB24.80KB
plugin-map (index.js)16.80KB5.24KB
plugin-markdown (index.js)13.65KB4.67KB
plugin-report (index.js)40.32KB10.53KB
plugin-timeline (index.js)25.75KB7.32KB
plugin-tree (index.js)8.36KB2.81KB
plugin-view (index.js)83.54KB20.39KB
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)19.28KB6.38KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.02KB0.55KB
sdui-parser (codegen.js)4.09KB1.74KB
sdui-parser (index.js)3.47KB1.54KB
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 (index.js)2.07KB0.99KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)0.20KB0.18KB
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)1.08KB0.64KB
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

@os-zhuang
os-zhuang marked this pull request as ready for review July 31, 2026 06:36
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)28.0 KB350 KB
Entry fileindex-C1sugWkC.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)8.26KB2.99KB
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.12KB3.41KB
auth (LoginForm.js)17.86KB5.29KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.43KB2.09KB
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)18.38KB4.49KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)3.65KB1.42KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.25KB0.53KB
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)473.75KB103.77KB
core (index.js)2.16KB0.78KB
create-plugin (index.js)9.28KB2.98KB
data-objectstack (index.js)136.34KB34.64KB
fields (index.js)222.07KB54.35KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.32KB1.77KB
i18n (index.js)2.46KB0.96KB
i18n (pickLocalized.js)1.70KB0.83KB
i18n (provider.js)5.37KB1.72KB
i18n (useObjectLabel.js)25.17KB5.80KB
i18n (useSafeTranslation.js)3.26KB1.44KB
layout (index.js)38.44KB10.66KB
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.05KB1.53KB
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.90KB12.35KB
plugin-charts (index.js)60.52KB17.11KB
plugin-chatbot (index.js)180.09KB42.72KB
plugin-dashboard (index.js)111.59KB28.74KB
plugin-designer (index.js)210.51KB42.50KB
plugin-detail (index.js)221.81KB54.28KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)111.38KB26.93KB
plugin-gantt (index.js)162.26KB39.53KB
plugin-grid (index.js)182.21KB48.24KB
plugin-kanban (index.js)47.82KB13.18KB
plugin-list (index.js)103.85KB24.80KB
plugin-map (index.js)16.80KB5.24KB
plugin-markdown (index.js)13.65KB4.67KB
plugin-report (index.js)40.32KB10.53KB
plugin-timeline (index.js)25.75KB7.32KB
plugin-tree (index.js)8.36KB2.81KB
plugin-view (index.js)83.54KB20.39KB
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)19.28KB6.38KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.02KB0.55KB
sdui-parser (codegen.js)4.09KB1.74KB
sdui-parser (index.js)3.47KB1.54KB
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.45KB1.21KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)0.20KB0.18KB
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)1.08KB0.64KB
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

@os-zhuang
os-zhuang merged commit c7c5294 into mainJul 31, 2026
16 checks passed
@os-zhuang
os-zhuang deleted the claude/schemaless-nodes-designer-forms-y1g7q0 branch July 31, 2026 06:45
akarma-synetal pushed a commit to akarma-synetal/objectui that referenced this pull request Aug 2, 2026
…thing else (framework#4343) (objectstack-ai#3170)
framework#4343 retired the `script` node's other dispatch branches because none
of them ran: `actionType: 'email' | 'slack'` were logger-backed stubs that wrote
a log line, reported success and delivered nothing under any configuration —
with `template` / `recipients` / `variables` addressing a message no channel
sent — inline `config.script` was recognized and never executed (no server-side
JS sandbox), and any other `actionType` was a second spelling of `function`.
The panel follows: `Function` (required), `Inputs` and `Output variable` are
offered unconditionally, since there is no action type left to gate them behind.
All five retired keys keep a legacy render-only field labelled `(retired)` with
its replacement in the help text, so a stored node still shows everything it
carries — the rule this group already followed for the `code` / `sms` /
`notification` action types objectstack-ai#3099 dropped.
The canvas subtitle leads with the function name (falling back to the retired
keys so an unmigrated node is never blank), and the simulator says what a retired
branch actually did instead of pretending it mocked a notification.
The reconciliation ledger spans the spec bump: on a spec that still publishes the
branches it asserts only that the form offers nothing the executor ignores; on
the spec that retires them — `SCRIPT_BUILTIN_ACTION_TYPES` disappearing is the
discriminator — the full bidirectional comparison arms itself. Verified against a
locally built framework spec: the converged panel reconciles clean both ways.
Claude-Session: https://claude.ai/code/session_01Ct9NXp2JumjKuARtQnrbPf
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationtests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-zhuang@claude