Skip to content

标量 config.timeRelative(如 timeRelative: 'daily')= 引擎解析不出任何 trigger,flow 永不触发且全层零输出 #5647

Description

@os-zhuang

发现于 #5496(time-relative 描述符 authoring 期校验)的实测。属 PD #10 的范围外发现,#5496 内刻意不修(见下「为什么不在 #5496 里修」),交 PM 定级。

事实(实测,非推断)

config.timeRelative 写成非对象标量时,引擎解析不出任何 trigger,flow 绑不上任何东西、永不触发,而且每一层都零输出。

复现的 flow(除描述符外一切合规:对象存在、status: 'active'、runAs: 'system'):

{
  name: 'scalar_time_relative',
  type: 'autolaunched',
  status: 'active',
  runAs: 'system',
  nodes: [
    { id: 'start', type: 'start', config: { timeRelative: 'daily' } },
    { id: 'end', type: 'end' },
  ],
  edges: [{ id: 'e1', source: 'start', target: 'end' }],
}

实测两条 flow lint 的输出:

validateFlowTriggerReadiness = []
lintFlowPatterns             = []

原因链,逐环:

  1. AutomationEngine.resolveTriggerBinding(packages/services/service-automation/src/engine.ts:1517)的路由判据是
    config.timeRelative != null && typeof config.timeRelative === 'object' —— 标量不满足,不路由到 time_relative。
  2. 继续下落:config.schedule != null || flow.type === 'schedule' 不成立(autolaunched、无 schedule),flow.type === 'api' || triggerType === 'api' 不成立 → 函数 return undefined(engine.ts:1554)。
  3. activateFlowTrigger 的 if (!resolved) return;(engine.ts:1564)—— 静默返回,连 warn 都没有。对比:描述符是对象时至少有 TimeRelativeTrigger.start() 的 bind 期 warn。
  4. authoring 期同样沉默:validate-flow-trigger-readiness.ts 的 isTimeRelative 也要求 typeof === 'object'(与引擎一致),所以 §1b 两条规则都不看它;更关键的是 isAutoTriggered 因此为 false,连 flow-draft-status-ambiguous 都不报。lint-flow-patterns.ts:254 的 startCfg.timeRelative != null 倒是命中,但那条规则只在 runAs 未提权时才出诊断,本例 runAs: 'system' 已合规,故也沉默。

所以标量描述符比对象描述符更静默:后者至少有一行服务器日志 warn(这正是 #5496 修掉的 authoring 期缺口),前者连那行都没有。

与 #3481 的同构

这与 validate-flow-trigger-readiness.ts §1d 存在的理由(#3481)完全同构,只是换了一个键:非字符串 triggerType 折叠成「无 trigger」→ flow 被当作 manual → 零输出。该文件的 §1d 注释原话:「a non-string triggerType folds to "no trigger"… so it binds to nothing and never fires, with zero output at any layer」。把 triggerType 换成 timeRelative、把「非字符串」换成「非对象」,就是本条。#3481 当时被判定为值得单开一条规则。

为什么不在 #5496 里修

#5496 落地的规则(PR 见该单)判据刻意与引擎的路由判据逐字一致(!= null && typeof === 'object'),这样规则只为「引擎真正交给 time-relative trigger 的那些 flow」发言。要覆盖标量就得放宽 isTimeRelative,而该变量同时喂 §1b 的 unknown-object 规则和 isAutoTriggered(draft-status 规则)—— 放宽会改变另外两条已发布规则的覆盖面,超出 #5496 的范围。故单开。

建议方向(供 PM 定级,不预设结论)

  1. 在 validate-flow-trigger-readiness.ts 新增一条判据:config.timeRelative != null && typeof !== 'object' → 报「这个槽要求描述符对象,标量不会被路由到任何 trigger,flow 永不触发」。不动 isTimeRelative,新增独立判据,避免波及另两条规则。规则 id 可复用 timeRelative 描述符跑不通时 authoring 期零诊断 —— 两条 flow lint 一条只看非空、一条只看对象名(#4966 建议 2) #5496 的族前缀风格(flow-time-relative-descriptor-invalid,或另起一条点明「不是对象」)。
  2. 同时补 isAutoTriggered:让标量 timeRelative 也算「作者意图自动触发」,这样 draft-status 规则也能覆盖。需评估对现有 flow 的诊断增量。
  3. 什么都不做:标量拼法罕见,且 未知键静默剥离仍是全仓默认:把 #3405 的 strict 收紧从一个 schema 推广到整个可授权面(ADR-0078 完整性闸门) #4001 收紧后描述符对象内部的键已有保护。

倾向 1 的理由在「让 AI 写的元数据难以写错」这一轴上:AI 作者把 cadence 概念和描述符概念混淆时,timeRelative: 'daily' 是一个很自然的错写,而它当前的反馈是绝对静默——比 #5496 修掉的那个缺口还差一档。同时这不引入任何消费端宽容(PD #12):不接受标量、不做 coercion,只是把「引擎解析不出 trigger」这件已经确定的事提前到 authoring 期报出来。

关联:#5496(本条的来源)、#3481(同构先例)、#5482(同族:节点 config 里已能判定、authoring 期无人报警)、ADR-0018(node config 开放槽)。

Blocked-by: #5496


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions