#4278 与 #4277 在同一天落地,两者交界处留下一个明确的后续,记在这里以免被当成「忘了接」。
现状
#4277(#4332)让 12 个「有契约」的内置节点在执行前 parse() 自己的
node.config(service-automation/builtin/parse-config.ts),并让 registerFlow()
拒绝 descriptor configSchema 未声明的键。
#4278(#4325)给另外三个 descriptor-schemaless 节点补上了执行器派生的契约
(spec/automation/schemaless-node-config.zod.ts:ScriptConfigSchema /
SubflowConfigSchema / DecisionConfigSchema),但刻意没有接入 parse,也没有发布
descriptor configSchema——两件事是同一个理由。
为什么不能直接接上去
它们的键集不等于契约。
script —— 合法键随 actionType 变:内置副作用分支读
template / recipients / variables;函数分支读
function / inputs / outputVariable;内联 script 是被识别但不执行的第三种。
平铺 parse 只能取这些键的并集,于是
{ actionType: 'email', function: 'x' } 这种自相矛盾的配置照样通过——检了个寂寞;
若反过来收紧成任一分支,就会拒绝另一半合法元数据。
decision —— 完全可以不带 conditions,只靠出边的 edge.condition 分支
(这是遗留但合法的形态)。
subflow —— 这个其实最接近可接入:键集扁平,flowName 执行期必需,
执行器已经用 refuseNode() 拒绝缺失的情况。
建议做法
subflow 可以先接——低风险,把现有的 refuseNode 换成统一的 parse guard,
与其它 12 个节点的失败形态一致(guard refusal,不走 fault 边)。
script 需要先改造成判别式:按 actionType 拆成
z.discriminatedUnion(或等价的 superRefine),分支分别声明各自的键。
这同时会让「自相矛盾的配置」在作者时就被拒,而不是运行到一半才发现
——actionType: 'email' 却写了 function 是当前唯一还能悄悄通过的形态。
decision 大概率维持现状:它的真实契约一半在边上,不在 config 里;
接 parse 的收益仅限于「conditions[] 元素的类型」,可以等 2 做完再评估。
一个附带好处:script 一旦有了判别式形态,objectui 的
flow-node-config.spec-reconciliation.test.ts(objectui#3099)可以从「键集并集比对」
升级为「按 actionType 分支比对表单的 showWhen 分组」——那才是表单实际的形状,
也能挡住「某个分支少提供了一个字段」这类 #4278 没覆盖到的漂移。
Related
#4278 与 #4277 在同一天落地,两者交界处留下一个明确的后续,记在这里以免被当成「忘了接」。
现状
#4277(#4332)让 12 个「有契约」的内置节点在执行前
parse()自己的node.config(service-automation/builtin/parse-config.ts),并让registerFlow()拒绝 descriptor
configSchema未声明的键。#4278(#4325)给另外三个 descriptor-schemaless 节点补上了执行器派生的契约
(
spec/automation/schemaless-node-config.zod.ts:ScriptConfigSchema/SubflowConfigSchema/DecisionConfigSchema),但刻意没有接入 parse,也没有发布descriptor
configSchema——两件事是同一个理由。为什么不能直接接上去
它们的键集不等于契约。
script—— 合法键随actionType变:内置副作用分支读template/recipients/variables;函数分支读function/inputs/outputVariable;内联script是被识别但不执行的第三种。平铺 parse 只能取这些键的并集,于是
{ actionType: 'email', function: 'x' }这种自相矛盾的配置照样通过——检了个寂寞;若反过来收紧成任一分支,就会拒绝另一半合法元数据。
decision—— 完全可以不带conditions,只靠出边的edge.condition分支(这是遗留但合法的形态)。
subflow—— 这个其实最接近可接入:键集扁平,flowName执行期必需,执行器已经用
refuseNode()拒绝缺失的情况。建议做法
subflow可以先接——低风险,把现有的refuseNode换成统一的 parse guard,与其它 12 个节点的失败形态一致(guard refusal,不走 fault 边)。
script需要先改造成判别式:按actionType拆成z.discriminatedUnion(或等价的superRefine),分支分别声明各自的键。这同时会让「自相矛盾的配置」在作者时就被拒,而不是运行到一半才发现
——
actionType: 'email'却写了function是当前唯一还能悄悄通过的形态。decision大概率维持现状:它的真实契约一半在边上,不在 config 里;接 parse 的收益仅限于「
conditions[]元素的类型」,可以等 2 做完再评估。一个附带好处:
script一旦有了判别式形态,objectui 的flow-node-config.spec-reconciliation.test.ts(objectui#3099)可以从「键集并集比对」升级为「按
actionType分支比对表单的showWhen分组」——那才是表单实际的形状,也能挡住「某个分支少提供了一个字段」这类 #4278 没覆盖到的漂移。
Related
scriptoffers three broken options and cannot author the one that works #4278 —— schemaless 节点的表单无人对账(已关闭)parse()their config, and tighten the undeclared-key warning into an error #4277 / feat(automation,spec): 流程执行器 parse() 自己的 config,未声明键在注册时报错 (#4277) #4332 —— 执行器 parse config + registerFlow 拒绝未声明键config.function作为 canonical 调用引用的来源