Skip to content

feat(flow-designer)!: the script node authors a function call, and nothing else (framework#4343) - #3170

Merged
os-zhuang merged 1 commit into
mainfrom
claude/script-config-parse-contract-gy035e
Aug 1, 2026
Merged

feat(flow-designer)!: the script node authors a function call, and nothing else (framework#4343)#3170
os-zhuang merged 1 commit into
mainfrom
claude/script-config-parse-contract-gy035e

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

objectstack-ai/objectstack#4343 的 objectui 半边(framework 侧:objectstack-ai/objectstack#4516)。

问题

script 节点的表单提供四种分发形态,而只有一种会运行:

表单曾提供 真实行为
Action type: Email / Slack logger stub——写一行日志、报告成功、任何配置下都不投递任何东西
Template / Recipients / Template variables 喂给上面那个 stub,寻址一条从没被发出的消息
内联 Code 从未执行(内置运行时没有服务端 JS 沙盒)
Call function + Inputs + Output variable 唯一跑真实逻辑的路径

#3099 已经修掉了「表单提供的选项跑起来必然失败」那一层(sms/notification/code),但仍然把两个 stub 当作一等公民授权。framework#4343 把这五个键整体退役,表单跟进。

改动

  • script 组收敛为函数路径:Function(必需)/ Inputs / Output variable,无条件展示——已经没有 action type 可以用来 gate 它们了。
  • 五个退役键保留为 legacy 只读字段(__legacy__ 门,永不匹配 ⇒ 永不被「提供」),标签加 (retired),help 文案各自点名替代机制。存量节点仍然显示它携带的一切——这正是 feat(flow-designer): the script node's form authors what the executor runs (framework#4278) #3099 处理 code/sms/notification 时立下的规矩。
  • 替代是三种不同机制,不是一次改名:邮件 → notify 节点(经 messaging 服务:默认站内收件箱,装了 @objectstack/plugin-email 后走真实邮件);Slack → connector_action(Slack connector)或 http webhook(notify 没有 slack channel);内联逻辑 → 注册函数。存量元数据由 os migrate meta --from 16 改写,简写 actionType 会被搬进 function
  • 画布副标题改为优先显示函数名(退役键作为兜底,未迁移的节点不会变空白);流程模拟器改为如实说明退役分支当初做了什么,而不是假装它 mock 了一条通知。

跨仓对账测试跨越 spec 升版

flow-node-config.spec-reconciliation.test.ts 现在两态都有断言,判别依据是 SCRIPT_BUILTIN_ACTION_TYPES 是否还存在(framework#4343 连同它描述的分支一起删除了这个常量):

  • 仍发布退役分支的 spec(今天装的这个):只断言「表单不提供执行器不读的键」——反方向会要求表单继续授权那些从不投递的分支,那是错的;
  • 退役后的 spec:zodKeys() 本来就过滤 [REMOVED] 墓碑,契约自动收敛为三键,完整双向对账自动激活

验证

  • 全仓:798 文件 / 9317 用例全绿;type-check 29/29;改动文件 eslint 零告警。
  • 定点:inspectors + previews 57 文件 / 660 用例绿。
  • 跨仓实测:把 @objectstack/spec 临时指向本地构建的 framework worktree(即 #4516 的 spec)后重跑对账测试——收敛后的面板双向对账干净,SPEC_PREDATES_SCRIPT_CONVERGENCE 分支正确跳过。这条验证很关键,因为当前安装的 17.0.0-rc.0 早于 framework#4278,该套件今天整体 skip,不实测就等于没验。

同一次实测顺带确认了一条既有债(不在本 PR 范围):wait 面板仍编辑 framework#4158 已退役的 waitEventConfig.timeoutMs / .onTimeout,所以下一次 spec 升版会让它的 ratchet 精准点名这两个字段——这正是 ratchet 的本意,由 #3101 追踪,升版 PR 需一并删掉它们。

Related

🤖 Generated with Claude Code

https://claude.ai/code/session_01Ct9NXp2JumjKuARtQnrbPf


Generated by Claude Code

…thing else (framework#4343)

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 #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.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ct9NXp2JumjKuARtQnrbPf
@vercel

vercel Bot commented Aug 1, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectui Ignored Ignored Aug 1, 2026 3:02pm

Request Review

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Main entry (gzip) 28.1 KB 350 KB
Entry file index-tbNS0l1F.js
Status PASS

📦 Bundle Size Report

Package Size Gzipped
app-shell (index.js) 8.45KB 3.08KB
app-shell (runtime-config.js) 7.42KB 2.32KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 7.57KB 2.97KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 1.17KB 0.53KB
auth (AuthProvider.js) 22.10KB 4.37KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.12KB 3.41KB
auth (LoginForm.js) 17.86KB 5.29KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.43KB 2.09KB
auth (SocialSignInButtons.js) 9.60KB 3.89KB
auth (UserMenu.js) 3.40KB 1.22KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 35.76KB 9.11KB
auth (createAuthenticatedFetch.js) 4.37KB 1.69KB
auth (index.js) 2.35KB 1.07KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 4.91KB 0.87KB
auth (useIsWorkspaceAdmin.js) 1.61KB 0.85KB
collaboration (CommentThread.js) 18.38KB 4.49KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 3.65KB 1.42KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.25KB 0.53KB
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) 475.95KB 104.41KB
core (index.js) 2.25KB 0.80KB
create-plugin (index.js) 9.28KB 2.98KB
data-objectstack (index.js) 136.20KB 34.74KB
fields (index.js) 223.45KB 54.66KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (i18n.js) 4.32KB 1.77KB
i18n (index.js) 2.46KB 0.96KB
i18n (pickLocalized.js) 1.70KB 0.83KB
i18n (provider.js) 5.37KB 1.72KB
i18n (useObjectLabel.js) 26.14KB 6.07KB
i18n (useSafeTranslation.js) 3.26KB 1.44KB
layout (index.js) 38.44KB 10.66KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.74KB
mobile (index.js) 1.50KB 0.62KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.71KB 0.42KB
mobile (useResponsiveConfig.js) 1.36KB 0.63KB
mobile (useSpecGesture.js) 4.05KB 1.53KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 8.75KB 3.06KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 3.67KB 1.12KB
permissions (evaluator.js) 4.41KB 1.44KB
permissions (index.js) 0.91KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.52KB
permissions (usePermissions.js) 1.55KB 0.71KB
plugin-ai (index.js) 15.71KB 3.79KB
plugin-calendar (index.js) 44.90KB 12.35KB
plugin-charts (index.js) 60.53KB 17.12KB
plugin-chatbot (index.js) 180.09KB 42.72KB
plugin-dashboard (index.js) 111.86KB 28.81KB
plugin-designer (index.js) 210.51KB 42.50KB
plugin-detail (index.js) 224.52KB 54.98KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 111.38KB 26.93KB
plugin-gantt (index.js) 162.26KB 39.53KB
plugin-grid (index.js) 184.69KB 48.91KB
plugin-kanban (index.js) 47.82KB 13.18KB
plugin-list (index.js) 104.82KB 25.30KB
plugin-map (index.js) 16.80KB 5.24KB
plugin-markdown (index.js) 13.65KB 4.67KB
plugin-report (index.js) 40.47KB 10.57KB
plugin-timeline (index.js) 25.75KB 7.32KB
plugin-tree (index.js) 8.34KB 2.82KB
plugin-view (index.js) 83.54KB 20.39KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.71KB 3.53KB
providers (index.js) 0.44KB 0.22KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.67KB 2.37KB
react (LazyPluginLoader.js) 3.77KB 1.33KB
react (SchemaRenderer.js) 19.28KB 6.38KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 1.02KB 0.55KB
sdui-parser (codegen.js) 4.09KB 1.74KB
sdui-parser (index.js) 4.47KB 2.03KB
sdui-parser (parse.js) 10.04KB 2.82KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 4.69KB 1.48KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 0.99KB
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) 1.87KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-retry.js) 4.32KB 2.02KB
types (index.js) 2.46KB 1.21KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 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 (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (spec-report.js) 5.05KB 1.93KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 0.20KB 0.18KB
types (ui-action.js) 3.40KB 1.71KB
types (views.js) 0.20KB 0.18KB
types (widget.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
os-zhuang marked this pull request as ready for review August 1, 2026 15:30
@os-zhuang
os-zhuang added this pull request to the merge queue Aug 1, 2026
Merged via the queue into main with commit b67be19 Aug 1, 2026
16 checks passed
@os-zhuang
os-zhuang deleted the claude/script-config-parse-contract-gy035e branch August 1, 2026 15:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants