Skip to content

fix(flow-designer): the default path is the edge marker, not the branch (framework#4414) - #3148

Merged
os-zhuang merged 1 commit into
mainfrom
claude/decision-inert-condition-help
Aug 1, 2026
Merged

fix(flow-designer): the default path is the edge marker, not the branch (framework#4414)#3148
os-zhuang merged 1 commit into
mainfrom
claude/decision-inert-condition-help

Conversation

@os-zhuang

@os-zhuang os-zhuang commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Decision 检查器上两处 help 文案描述了引擎并不具备的机制。纯文案,本侧无行为变更。

配套框架侧:objectstack-ai/objectstack#4414 / #4440(isDefault 落地)、#4439 / #4474(表达式账本)。

① Branches 编辑器:把「分支」和「边上的标记」混为一谈

原文写「expression"true" 的分支就是 default/else 路径」。实际它是申请一条:FlowEdgeInspector.applyBranch() 会把这种分支接成出边上的 isDefault: true,真正路由的是那条边上的标记

这个混淆正是 framework#4414 里「守卫不守」得以出厂的读法,而且现在特别值得说准 —— isDefault 在引擎里此前是零读者。也就是说这个 designer 一直在写一个没人认领的标记,每一条 Studio 画出来的「default/else」边实际上都是无条件执行的,和真正命中的分支并行跑。框架侧 enforcement 落地后它们才开始只走一条。

顺带补上两点原本没说的:分支是按顺序试、第一个命中的赢;expression裸 CEL —— 带花括号的谓词自 framework#4439 起是构建失败,不再是「另一种方言」。

② Legacy 单数 Condition:不是「次一等」,是根本不生效

原文写「Prefer Branches above」,读起来像「这个能用,只是那个更好」。它完全不工作:decision 执行器从不读 config.condition。引擎只在 Start 节点上认这个键(作为触发门),framework#4414 为此新增了 flow-inert-node-condition,os validate 现在会报。

字段本身保持 render-only(__legacy__ 控制器永不匹配,所以不对新建开放)—— 存量节点的值不该在界面上凭空消失 —— 但 help 现在如实说它是惰性的,以及谓词该搬去哪里。

验证

pnpm exec vitest run --project unit flow-node-config → 40 passed / 5 skipped;flow-node-config.spec-reconciliation.test.ts 一并通过(它对账的是 key 集合,文案不影响);ESLint 干净。

🤖 Generated with Claude Code

https://claude.ai/code/session_01Q8as8yR67v41xEdomiTba9

…ch (framework#4414)

Two help strings on the Decision inspector that described mechanisms the
engine does not have.

The Branches editor said a branch whose expression is "true" IS the
default/else path. It is how you ASK for one: FlowEdgeInspector.applyBranch()
turns such a branch into `isDefault: true` on the out-edge it wires, and the
marker on that edge is what routes. Conflating the two is the reading that
let framework#4414 ship a decision whose guard did not guard — worth being
exact about now that `isDefault` is actually enforced (the key had zero
readers until then, so this designer was writing a marker nothing honoured).
Also states that branches are tried in order and that the expression is bare
CEL, since a braced predicate is now a build failure (framework#4439).

The legacy single `Condition` field said "Prefer Branches above", which reads
as "this works, but the other is better". It does not work at all: the
decision executor never reads `config.condition`. The engine only honours
that key on a Start node, as the trigger gate; framework#4414 added
`flow-inert-node-condition` to `os validate` for exactly this. The field stays
render-only (`__legacy__` never matches) so a stored value is not invisible,
but the help now says it is inert and where to move the predicate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q8as8yR67v41xEdomiTba9
@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 11:03am

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-sLwunqsA.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.52KB 17.11KB
plugin-chatbot (index.js) 180.09KB 42.72KB
plugin-dashboard (index.js) 111.59KB 28.74KB
plugin-designer (index.js) 210.51KB 42.50KB
plugin-detail (index.js) 222.45KB 54.50KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 111.35KB 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.62KB 25.18KB
plugin-map (index.js) 16.80KB 5.24KB
plugin-markdown (index.js) 13.65KB 4.67KB
plugin-report (index.js) 40.32KB 10.53KB
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 merged commit efd7767 into main Aug 1, 2026
16 checks passed
@os-zhuang
os-zhuang deleted the claude/decision-inert-condition-help branch August 1, 2026 12:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants