问题
#3457 将多事件 triggerType 数组列为 deferred——受支持的写法是单 token(record-{before,after}-{create,insert,update,delete} + write 联合,#3427 /#3446 )。但作者若凭直觉写了数组形态(对 code-first 作者、尤其对 AI authoring 来说是最自然的猜测输出):
{
type : 'start' ,
config : {
objectName : 'app_task' ,
triggerType : [ 'record-after-create' , 'record-after-delete' ] , // ← 不受支持的猜测写法
} ,
}
得到的是一个看起来注册成功、永不触发、且每一层都保持沉默 的 flow:
spec — start 节点 config 是 z.record(z.string(), z.unknown())(packages/spec/src/automation/flow.zod.ts:102),数组直接通过 defineFlow 校验。
engine — resolveTriggerBinding 用 typeof config.triggerType === 'string' 收窄(packages/services/service-automation/src/engine.ts:901),数组折叠成 undefined,flow 被归类为 manual/screen 。
binding audit — getTriggerBindingAudit 对未解析出 trigger 的 flow 直接跳过(engine.ts,if (!resolved) continue),CLI 启动摘要里不出现任何条目。
lint — validate-flow-trigger-readiness 用同样的 typeof 收窄(packages/lint/src/validate-flow-trigger-readiness.ts:96)→ isRecordTriggered 为 false,record_change flow start node binds to a single lifecycle event — no create-OR-update in one flow #3427 加的 never-fire 规则(flow-trigger-unknown-event)看不到它。零 finding。
与 2026-07-17 三方评估 / #3427 / #3472 是同一 failure class("看起来武装好了、静默不发射")——数组形态是至今唯一还能绕过全部守卫的 authoring 形态。
修复(纯防御——数组仍不支持,#3457 的 deferral 维持不变)
契约优先(AGENTS.md Prime Directive #12 ):在 authoring 侧响亮拒绝,不在 consumer 侧加容忍别名。
lint (validate-flow-trigger-readiness):triggerType 为数组且含 record-* 字符串元素 → warning(复用 flow-trigger-unknown-event 规则 id)——数组形态不受支持;create-or-update 用 record-after-write;其他组合一事件一 flow(见 flow record trigger: consider multi-event triggerType (array / unions beyond create-or-update) #3457 )。
engine (resolveTriggerBinding):把含 record-* 元素的数组路由到 record_change trigger(event 传字符串化值),而不是折叠成 manual——由 trigger 在绑定时响亮拒绝,与现有 typo-token 路径(如 record-after-updated)可观察行为一致。
trigger (record-change-trigger):拒绝时识别 binding.config.triggerType 的数组形态,给出针对性提示(record-after-write / 一事件一 flow / flow record trigger: consider multi-event triggerType (array / unions beyond create-or-update) #3457 )。
验收
对含数组形态 flow 的 stack 跑 os validate → 输出 warning,指明 flow 名、节点路径与修法。
启动该 stack → 绑定期 warning 指名该 flow(而非全链路沉默)。
每个新测试先对未修复代码证明能红。
Refs: #3457 (deferral + 设计归档)、#3427 / #3446 (record-after-write)、#3472 (同族静默缺陷)。
问题
#3457 将多事件
triggerType数组列为 deferred——受支持的写法是单 token(record-{before,after}-{create,insert,update,delete}+write联合,#3427/#3446)。但作者若凭直觉写了数组形态(对 code-first 作者、尤其对 AI authoring 来说是最自然的猜测输出):得到的是一个看起来注册成功、永不触发、且每一层都保持沉默的 flow:
config是z.record(z.string(), z.unknown())(packages/spec/src/automation/flow.zod.ts:102),数组直接通过defineFlow校验。resolveTriggerBinding用typeof config.triggerType === 'string'收窄(packages/services/service-automation/src/engine.ts:901),数组折叠成undefined,flow 被归类为 manual/screen。getTriggerBindingAudit对未解析出 trigger 的 flow 直接跳过(engine.ts,if (!resolved) continue),CLI 启动摘要里不出现任何条目。validate-flow-trigger-readiness用同样的typeof收窄(packages/lint/src/validate-flow-trigger-readiness.ts:96)→isRecordTriggered为 false,record_change flow start node binds to a single lifecycle event — no create-OR-update in one flow #3427 加的 never-fire 规则(flow-trigger-unknown-event)看不到它。零 finding。与 2026-07-17 三方评估 / #3427 / #3472 是同一 failure class("看起来武装好了、静默不发射")——数组形态是至今唯一还能绕过全部守卫的 authoring 形态。
修复(纯防御——数组仍不支持,#3457 的 deferral 维持不变)
契约优先(AGENTS.md Prime Directive #12):在 authoring 侧响亮拒绝,不在 consumer 侧加容忍别名。
validate-flow-trigger-readiness):triggerType为数组且含record-*字符串元素 → warning(复用flow-trigger-unknown-event规则 id)——数组形态不受支持;create-or-update 用record-after-write;其他组合一事件一 flow(见 flow record trigger: consider multi-eventtriggerType(array / unions beyond create-or-update) #3457)。resolveTriggerBinding):把含record-*元素的数组路由到record_changetrigger(event传字符串化值),而不是折叠成 manual——由 trigger 在绑定时响亮拒绝,与现有 typo-token 路径(如record-after-updated)可观察行为一致。record-change-trigger):拒绝时识别binding.config.triggerType的数组形态,给出针对性提示(record-after-write/ 一事件一 flow / flow record trigger: consider multi-eventtriggerType(array / unions beyond create-or-update) #3457)。验收
os validate→ 输出 warning,指明 flow 名、节点路径与修法。Refs: #3457(deferral + 设计归档)、#3427 / #3446(
record-after-write)、#3472(同族静默缺陷)。