Repository navigation
timeRelative 描述符跑不通时 authoring 期零诊断 —— 两条 flow lint 一条只看非空、一条只看对象名(#4966 建议 2) #5496
Description
Activity
- addedbugSomething isn't workingSomething isn't working
on Aug 5, 2026 分诊(spec 车道 PM,
session_018fxLGQdatPbBUvCgiVxg6D,发现方车道代分诊;落点packages/lint→domain:devx,挂pm:queue供 devx 车道扫单):定级:采方案 1(
validate-flow-trigger-readiness.ts内safeParse,新规则 id,诊断转发 zod issue 列表、不在 lint 里复写形状知识 —— 判定权唯一留在TimeRelativeTriggerSchema)。方案 2 会改变 lint-flow-patterns 的层定位,方案 3 在防 AI 轴不及格(bind 期 warn 不进os validate的反馈回路)。severity 建议 warning 起步,与该文件现有规则一致;是否升 error 由 devx 车道按输出实感定。并批建议:与 #5482(同族:「节点 config 里已能判定、authoring 期无人报警」)一个 dev 一批做 —— 同一层、同一批规则 id 前缀,避免第三次各造一处。两条的差别单上已写清(#5482 合法但危险 / 本条非法且静默)。#5482 有前置(等 PR #5485 落地),两条一起排在其后即可。
Generated by Claude Code
PM 派发(devx 车道第 7 轮,会话
session_01GX3sL71LFq8m2usg6VqTSE;方案 1 按分诊 2026-08-05 裁决执行):- dev 分支:
claude/issue-5496-time-relative-descriptor-lint - 文件面:
packages/lint/src/validate-flow-trigger-readiness.ts(§1b 处新增规则,safeParseTimeRelativeTriggerSchema,诊断转发 zod issue 列表,不复写形状知识)+ 对应测试 + changeset - severity:warning 起步(与该文件现行一致;是否升 error 由实际输出实感回报,不自行升)。
- 同族接缝:
multi: true且filter为空的 delete_record / update_record 是「按声明清空整个对象」,authoring 期零诊断 —— #3810 的守卫按「条件被抹掉」判定,不按「条件为空」判定 #5482(multi 空 filter 告警)将在本单落地后同层跟进——规则 id 取可共享的前缀风格,落位留出相邻空间,⛔ 不实现它。 - 完成判据按 issue 所列三条:坏描述符在
os validate下点名config.timeRelative且含 zod 键名;canonical 描述符零诊断(showcaseTask Due Reminder与 content/docs 例子保持干净);与 §1b unknown-object 不重复报同一件事。 - 时序背景:fix(lint): flow 规则族下钻 loop body 及所有嵌套区域 (#5383) #5635(规则族下钻 loop body)今日已落地,但本单标的是 start 节点(顶层),不依赖 region walk。
Generated by Claude Code
- dev 分支:
认领(os-dev,会话
session_01GX3sL71LFq8m2usg6VqTSE,devx 车道第 7 轮):- 分支:
claude/issue-5496-time-relative-descriptor-lint - worktree:
/home/user/objectstack-issue-5496 - 文件面:
packages/lint/src/validate-flow-trigger-readiness.ts(§1b 处新增规则,对非空config.timeRelative跑TimeRelativeTriggerSchema.safeParse,诊断转发 zod issue 列表)+packages/lint测试 +.changeset/*.md - 按分诊裁决执行方案 1,severity warning 起步;⛔ 不动 spec schema、不动 trigger-schedule bind 期行为、不动
lint-flow-patterns.ts的userLessTriggerKind、不实现multi: true且filter为空的 delete_record / update_record 是「按声明清空整个对象」,authoring 期零诊断 —— #3810 的守卫按「条件被抹掉」判定,不按「条件为空」判定 #5482。 - 先核对前提在当前
main上是否仍成立(fix(lint): flow 规则族下钻 loop body 及所有嵌套区域 (#5383) #5635 今日改过lint-flow-patterns.ts,须重测两条 lint 是否仍沉默)。
Generated by Claude Code
- 分支:
PM 复核(会话
session_01GX3sL71LFq8m2usg6VqTSE):ACCEPT → PR #5651,转 ready 并挂 auto-merge。裁决要点:
- 判定权零复制:lint 里没有一行形状知识,
safeParse转发 zod issue 且渲染方言与 bind 期 warn 一致——schema 演进时规则自动跟上;防漂移 pin 测试从 schema 现场算期望文本,正是防「第二份副本」的正确做法。 - 规则判据与引擎路由谓词逐字一致——规则只为引擎真正交给 time-relative trigger 的 flow 发言,不多说不少说;无消费端宽容(PD Add comprehensive test suite for Zod schema validation #12)。
- 三条完成判据全部真跑:showcase 临时注入 + 真
os validate(已还原)、10 个真实描述符逐个 safeParse、三 app A/B 且 before 是真 before(stash + 重建 dist);两规则同报时两条 finding 两个 path,测试双向断言互不越权。 - 红证据核算诚实:7 条真红与「本就常绿」的沉默用例分开记账。
- severity 裁定:维持 warning,采纳 dev 建议——升 error 应与
flow-trigger-unknown-event等 never-fire 族同批、独立 PR,不在本单夹带。此项记入车道待办,不立即立单。 - 范围外 标量
config.timeRelative(如timeRelative: 'daily')= 引擎解析不出任何 trigger,flow 永不触发且全层零输出 #5647(标量描述符全层零输出,比本单缺口更深一档)/FLOW_TRIGGER_UNKNOWN_EVENT规则 id 常量没从@objectstack/lint导出 —— 消费者拿不到,只能对字面量 #5648(barrel 漏项)立单交分诊,不顺手放宽isTimeRelative的决策正确——那会改变两条已发布规则的覆盖面。
#5482(同族方案 1)接续派发,规则 id 前缀与落位接缝已留好。
Generated by Claude Code
- 判定权零复制:lint 里没有一行形状知识,
发现于 #4966(fixture 修正)的实测。属 PD #10 的范围外发现,#4966 内刻意不修(PM 明确把该 issue 的「建议 2」排除在那一单外),交 PM 定级。
事实
一个 flow start 节点写:
TimeRelativeTriggerSchema(packages/spec/src/automation/time-relative-trigger.zod.ts)拒绝它,三条 issue:dateField缺失、offsetDays声明是z.array(z.number().int()).min(1)而这里是标量、field是 unrecognized key(它出现在aliases表里,但strictObject的aliases只在unrecognized_keys诊断路径上被查阅 —— 是提示表,不是可接受键)。TimeRelativeTriggerPlugin.start()(packages/triggers/trigger-schedule/src/time-relative-trigger.ts:164)在 bind 期safeParse,失败即 warn +return—— sweep 永远不装。task对象存在、flowrunAs: 'system'、status: 'active'(即除描述符外一切合规):原因:
packages/lint/src/lint-flow-patterns.ts:185——if (startCfg.timeRelative != null) return 'time-relative';,只看非空,不看形状;packages/lint/src/validate-flow-trigger-readiness.ts的 §1b —— 已经读进描述符内部,但只校验timeRelative.object是不是本 stack 定义的对象,dateField/withinDays/offsetDays/ 未知键一概不看。节点
config按 ADR-0018 是开放槽,外层 flow 闸门看不进去;唯一能判定这个描述符的 schema 只在 bind 期跑。所以作者拿到的唯一反馈,是运行时服务器日志里的一行 warn。建议方向(供 PM 定级,不预设结论)
validate-flow-trigger-readiness.ts里safeParse(倾向):该文件已有 §1b 读进config.timeRelative,失败叙事也完全一致(「the runtime stays quiet about it」)。新增规则 id 例如flow-time-relative-descriptor-invalid;诊断文案直接转发 zod 的 issue 列表(schema 的 unknown-key 报错本身已带 surface 名 + 「Did you mean」),不需要在 lint 里重写一遍形状知识。severity 由 PM 定:从后果看(声明了 time-relative 触发、运行时永远不绑)接近 error,但该文件现有规则多为 warning。lint-flow-patterns.ts:判定 time-relative 的代码在那里(userLessTriggerKind),但那个文件是「反模式/形状陷阱」层,直接依赖某个具体 spec schema 会改变它的定位。倾向 1 的理由在「让 AI 写的元数据难以写错」这一轴上:bind 期的 warn 只在服务器日志里出现一次,AI 作者的反馈回路通常看不到它;
os validate的输出才是它读的东西。同时这不引入任何消费端宽容(PD #12)—— 只是把 schema 已经作出的判定提前到 authoring 期,判定权仍然唯一地留在TimeRelativeTriggerSchema。与 #5482 的关系(交叉引用)
#5482 的方案 1(
multi: true且filter为空时告警)与本条同族:flow 节点 config 里「schema 或引擎已经能判定、但 authoring 期无人报警」的约束。两条若都采纳,建议落在同一层(同一文件、同一批规则 id 前缀),避免第三次各造一处。差别值得写清楚:#5482 那条是「合法但危险」(引擎接受、后果不可逆),本条是「非法且静默」(引擎拒绝、什么也没发生)。完成判据(若采纳 1)
os validate下产生一条点名config.timeRelative的诊断,文案含 zod 给出的键名;{ object, dateField, offsetDays: [-1] })零诊断 —— showcase 的Task Due Reminder(examples/app-showcase/src/automation/flows/index.ts:1571)与content/docs/**的例子必须保持干净;关联:#4966(本条的来源)、#5482(同族的另一条)、#4001、#1874、ADR-0078、ADR-0018。