Skip to content

表达式 ledger 只认 descriptor configSchema,所以「刻意 schemaless」的节点上声明的 CEL 槽位没有任何 build-time 校验器 #4439

Description

@os-zhuang

#4414 时发现的相邻缺口,独立于那三条路由机制,所以单独开。

现状

FLOW_NODE_EXPRESSION_PATHS(packages/spec/src/automation/flow-node-expression-paths.ts)是 #4027 立的账本:一个节点 config 里声明的表达式槽位必须登记在这里,registerFlowobjectstack validate 才会去走它。棘轮由 config-expression-ledger.test.ts 双向咬死:

问题在于账本的唯一真值来源是 descriptor 的 configSchema。而 decision / script / subflow / wait / connector_action 这一类是刻意不发 configSchema 的 —— schemaless-node-config.zod.ts 的模块注释写得很明确:这些类型的 config 契约发布在那个文件里,"must NOT grow into descriptor configSchemas"(表单在 objectui 手写)。

两条规则一叠,结果是:凡是 schemaless 类的节点,它声明的表达式槽位在结构上无法进账本,因此永远没有 build-time 校验器。

具体的一个

DecisionConditionSchema.expression(schemaless-node-config.zod.ts:193)自己写着 'Bare CEL predicate deciding this branch',注释也点名 {…}#1491 的陷阱。但:

  • 它不在 FLOW_NODE_EXPRESSION_PATHS 里 —— 也加不进去,加了 config-expression-ledger.test.ts 的「无 stale 条目」那条会红;
  • 所以 registerFlow 不校验它,objectstack validate 也不校验它。

对比 edge.condition:那条是结构性槽位(每条边都有),两个校验器都硬编码走它,所以 {lead_record.status} == 'converted' 写在边上会在注册时就炸,并带修正提示。写在 decision 的 conditions[].expression 里则一路绿灯到运行时。

#4414 已经把运行时那半补上了 —— 执行器现在按声明的 bare CEL 求值({ dialect: 'cel', source }),所以带花括号的谓词会响亮地失败而不是静默判 false。但作者是在跑起来才知道,不是在 os build 时知道,这正是 #4027 建账本要消除的那段延迟。

建议

账本的「反向」棘轮应该按槽位的声明处分档,而不是一律要求 descriptor 声明:

  • configSchema 的节点 → 维持现状(双向咬死 xExpression);
  • schemaless 类节点 → 允许账本条目由 schemaless-node-config.zod.ts 里的 Zod schema 认领。棘轮改成「每条账本条目要么对应一个 descriptor 的 xExpression,要么对应一个 schemaless config schema 里标注过的字段」,两边都不许有孤儿。

落地之后把 decision.conditions[].expression 登记为 role: 'predicate',两个校验器就自动覆盖它了。顺带该扫一遍 script / subflow / wait / connector_action 的 config 契约,看还有几个同样形状的槽位 —— 我没有逐个数。

相关: #4027(账本本身)、#3528(它要防的那个缺陷)、#4414(decision 路由,运行时那半已修)、#4336

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions