Skip to content

Flow 模拟器把 { dialect, source } 信封形式的边守卫当成「没有条件」 #3216

Description

@os-zhuang

#3202(收紧设计器边类型)时越界发现,未在该 PR 里顺手改 —— 它是行为变更,不是类型收紧。

缺陷

packages/app-shell/src/views/metadata-admin/previews/simulator/ 里有两个读边守卫的地方,都只认裸字符串,信封形式一律返回 undefined:

// flow-simulator.ts:46
const condStr = (c: SimEdge['condition']): string | undefined => (typeof c === 'string' ? c : undefined);

// flow-sim-validate.ts:18
const edgeCondString = (c: SimEdge['condition']): string | undefined =>
  typeof c === 'string' ? c : undefined;

于是 flow-simulator.ts:281 处,一条守卫写成 { dialect: 'cel', source: 'amount > 10' } 的决策出边,在模拟时间线上报的是 Branch has no condition.,并被跳过 —— 模拟结果会走到 default 分支或直接停住,而引擎在真实运行时会正常求值这条守卫。flow-sim-validate.ts:154 的诊断也会因此少判一类。

为什么是真 bug 而不是设计

仓内其它每一个读同一个字段的地方都接受两种拼写:

  • previews/flow-canvas-layout.tsconditionText —— 字符串或 { source } 都读(画布标签、FlowEdgeInspector 输入框、flow-decision-edges 的分支匹配都走它);
  • inspectors/expression-validate.tsvalidateExpressionClient —— 注释就写着「Accept a bare string or an Expression envelope」;
  • inspectors/flow-decision-edges.test.ts 里已有一条用例把 { dialect: 'cel', source } 的边条件当作正常存量形状匹配。

@objectstack/specExpressionInputSchema 是一个 ZodPipe:裸字符串在 parse 时就被规范化成 { dialect: 'cel', source } 信封,信封才是 spec 眼里的规范持久化形式(FlowEdgeSchema.condition 用的正是它)。也就是说,模拟器读不了的那种拼写,恰恰是平台自己产出的那种。

所以这不是「模拟器故意只支持简写」,而是两个读函数漏了一条分支 —— 与 #3202 同一族:一个过窄/过宽的本地读法与 spec 不一致

建议修法

两处都改为走同一个读法(conditionText 已经是仓内的既有实现,或抽一个共享的 expressionSource(c)),不要各自再写第三、第四份 typeof c === 'string'

顺带:flow-sim-types.ts:30SimEdge.condition 仍写作 string | { source?: string } —— 那是 #3202 收紧掉的、spec 会拒绝(缺 dialect)的形状的最后一份复制。修这条时一并镜像 spec 的 ExpressionInput(import type 即可,别再重述一遍)。

验证建议

一条决策节点的出边,守卫存成 { dialect: 'cel', source: 'amount > 10' },变量给 amount = 20:期望模拟器选中该分支;当前会得到 Branch has no condition.

相关

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions