Repository navigation
Description
发现于 #4001 批 11 的载荷普查,不在该批范围内,未修。与 #4924 同类不同处(那条是 packages/spec 自己的 flow.test.ts,这条在 packages/lint)。
事实
packages/lint/src/lint-flow-patterns.test.ts:343:
scheduledDataFlow({ flowType: 'autolaunched', startConfig: { timeRelative: { object: 'task', field: 'due_at', offsetDays: -1 } } })对照 TimeRelativeTriggerSchema(packages/spec/src/automation/time-relative-trigger.zod.ts),这个描述符有两处跑不通:
field—— 声明的键是dateField。field不是别名、不是转换项,就是不存在;offsetDays: -1—— 声明是z.array(z.number().int()).min(1),要的是数组([-1])。单个数字不是「负偏移」的写法,是类型错误。
TimeRelativeTriggerPlugin.start() 对 binding.config.timeRelative 做 safeParse,任一处都会让它 不绑定并 warn。所以这个 fixture 描述的是一个 flow:lint 认为它是 time-relative 触发的,而运行时永远不会为它装上 sweep。
为什么绿
lintFlowPatterns 判定「这是不是 time-relative flow」的依据是 lint-flow-patterns.ts:185:
if (startCfg.timeRelative != null) return 'time-relative';—— 只看非空,不看形状。于是 lint 正确地对这个 flow 报了 FLOW_RUNAS_UNSCOPED,测试正确地断言了它,而描述符本身有没有可能生效,两边都没人问。
这不是 lint 的 bug(它的职责是 runAs,不是描述符校验),而是本战役反复记录的那个形状:两道守卫各守一扇门,谁也不知道对方在守什么,中间那条「lint 说它是 time-relative,运行时说它不是」的缝隙没有任何东西站着。
值得单独记的一点
#4001 批 11 把 TimeRelativeTriggerSchema 收紧了,而这个 fixture 不会因此变红 —— 它根本不经过那个 schema(config 槽位按 ADR-0018 刻意开放,lint 只做 != null)。也就是说:这是一份收紧之后仍然全绿的错误教材,和 #4924 的四处 fixture 是同一句话。flow.test.ts 之外,packages/lint 的 fixture 同样会被当成「平台官方怎么写」来读。
建议
- fixture 改成能绑的形状:
{ object: 'task', dateField: 'due_at', offsetDays: [-1] },并就地留一句注释说明为什么(照 未知键静默剥离仍是全仓默认:把 #3405 的 strict 收紧从一个 schema 推广到整个可授权面(ADR-0078 完整性闸门) #4001 惯例:修测试并记原因,不要绕开); - 可选、更有价值的一步:让
lint-flow-patterns在认出timeRelative之后顺手safeParse一次描述符,把「声明了但永远不会绑定」报成一条 advisory。今天这个缺口只有 boot 时的一行warn兜着,而作者在os validate阶段是看不到它的 —— 正是 ADR-0078 说的「声明了却惰性」的元数据。第 2 步若要做,建议单独立单评估规则归属。
相关
- spec 自己的 flow fixture 教了三种跑不通的形状:CRUD 的
recordId、decision 的condition、object(#4001 第一类发现的第七例) #4924(packages/spec自己的 flow fixture 教三种跑不通的形状 —— 同类第七例) - 未知键静默剥离仍是全仓默认:把 #3405 的 strict 收紧从一个 schema 推广到整个可授权面(ADR-0078 完整性闸门) #4001(第一类发现:「把 strip 时代假象固化成预期的测试」)
- [P2] Provide a declarative time-relative trigger (avoid fragile date-equality on record-change) #1874(
timeRelative描述符的引入) - ADR-0078(no-silently-inert-metadata)
Activity
os-zhuang commentedon Aug 5, 2026
认领:spec 车道第 2 批⚠️ 修复落点在
会话:
session_018fxLGQdatPbBUvCgiVxg6D分支:
claude/issue-4966-timerelative-fixtureWorktree:
objectstack-issue-4966域:
domain:spec(标签沿用分诊;packages/lint,按跨域单一认领协议声明文件面)文件面:仅
packages/lint/src/lint-flow-patterns.test.ts(fixture 一处 + 原地注释)。与在飞 #5417(lint 翻译规则,另一账号)文件不相交;若实测相交,让行并回报。范围:仅建议 1(fixture 改成可绑形状)。建议 2(lint 顺手 safeParse 报 advisory)按 issue 原文单独立单评估,不在本单。
Generated by Claude Code
os-zhuang commentedon Aug 5, 2026
验收(spec 车道 PM,
session_018fxLGQdatPbBUvCgiVxg6D):ACCEPT → PR #5497(draft;短程 checks 绿、Check Changeset 经skip-changeset标签转 skipped,重程分片在跑,全绿后转 ready 入队)。safeParsepin —— 这一步略超「fixture + 注释」的字面范围,批准:反向验证证明单改 fixture 不翻转任何测试颜色(规则只看非空),没有 pin 这个 fixture 明天就能再次静默腐化。可检测性来自 pin 这一事实按报告纪律如实写明,没有包装成「由红转绿」,加分。timeRelative描述符均已 canonical,无第二处。field在 aliases 表里,但那是 unrecognized_keys 诊断路径的提示表、不是可接受键 —— issue 结论语义成立。timeRelative描述符跑不通时 authoring 期零诊断 —— 两条 flow lint 一条只看非空、一条只看对象名(#4966 建议 2) #5496(实测两条 lint 全部沉默的证据链完整),已核实、分诊入 devx 队列并建议与multi: true且filter为空的 delete_record / update_record 是「按声明清空整个对象」,authoring 期零诊断 —— #3810 的守卫按「条件被抹掉」判定,不按「条件为空」判定 #5482 并批。Generated by Claude Code
test(lint): the #5633 loop fixtures spell the DECLARED item key, and …
test(lint): pin the time-relative fixture to a descriptor the runtime…
fix(lint): `flow-runas-unscoped` 跨区域搜索它的数据节点证据 (objectstack-ai#5633) (o…