发现于 #4001 批 9 的载荷普查,**不在该批范围内,未修**。 ## 事实 `packages/spec/src/automation/flow.test.ts` 的 fixture 里,示范用的 flow 节点写着这些 config 键: | 位置 | 写的 | 实际 | |---|---|---| | `flow.test.ts:336` | `get_record` 的 `config: { object: 'opportunity', recordId: '{opportunityId}' }` | 两个键**都没有**被 `GetRecordConfigSchema` 声明,executor 一个都不读。`object` 有 ADR-0087 转换(`flow-node-crud-object-alias`)会在加载期改写;`recordId` **什么都不是** | | `flow.test.ts:355` | `update_record` 的 `config: { recordId: … }` | 同上 | | `flow.test.ts:487` | `delete_record` 的 `config: { recordId: '{loop_records.item.id}' }` | **只有这一个键**。CRUD executor 只按 `filter` 定位行,所以这是一个「唯一的约束条件根本不被读」的删除节点 —— 正是 #3810 要防的 match-everything,穿着一个读起来像约束的键 | | `flow.test.ts:346` | `decision` 的 `config: { condition: '{opportunity.amount} > 100000' }` | `config.condition` 只在 `start` 节点上被读(触发闸门),在其余 19 个内建节点类型上是惰性的 —— `lint-flow-patterns` 的 `flow-inert-node-condition`(#4414)就是专门报这件事的 advisory | 这些 fixture 断言的是 `FlowSchema` / `FlowNodeSchema`,而 `FlowNodeSchema.config` 是**刻意开放**的 `z.record(z.unknown())`,所以它们全绿,而且**批 9 收紧后依然全绿**——收紧的是槽位里的每类型契约,不是槽位本身。**这不是一个会红的测试,是一份会被照抄的教材。** ## 为什么这是一条发现而不是洁癖 #4001 的第一类发现(「六个把 strip 时代假象固化成预期的测试」)已经点名过同一形状五次,其中 `page.route` 那条的原话是「一个从未存在的路由键,平台自己的测试套件养了多年」。这是第六、七例,而且更靠近作者:`flow.test.ts` 是**协议层最容易被当成范例读的文件**,对 AI 作者尤其如此 —— 它读起来像「平台官方怎么写一个 flow」。 `recordId` 尤其值得记:批 9 因此给它写了 guidance(编辑距离够不到任何已声明的键,不给处方的话拒绝信息就只能报个键名),而那条 guidance 的经验依据,正是**仓库自己的 fixture**。 ## 建议 把这四处 fixture 改成能跑的形状,并在原地留一句注释说明为什么改(照 #4001 的惯例:「修测试,并记下原因,不要绕开」): - `object` → `objectName` - `recordId: '{x}'` → `filter: { id: '{x}' }` - decision 的 `config.condition` → 挪到出边的 `condition`,fallback 边标 `isDefault: true` ⛔ 不要顺手把 `FlowNodeSchema.config` 收紧 —— 它按 ADR-0018 刻意开放(`node.type` 对插件开放,插件 executor 自带 `configSchema`),批 9 的台账行已就地记了这一条。 ## 相关 - #4001(批 9 的载荷普查发现了它;三个 config 契约已收紧) - #4414(`flow-inert-node-condition` advisory —— 惰性 `config.condition`) - #3810(模板求值抹掉过滤条件 → 拒绝执行) - #4277 / #4045(`registerFlow` 的描述符键闸门与 form↔Zod 对账)
Activity
os-zhuang commentedon Aug 5, 2026
认领:spec 车道第 2 批
会话:
session_018fxLGQdatPbBUvCgiVxg6D分支:
claude/issue-4924-flow-fixture-shapesWorktree:
objectstack-issue-4924域:
domain:spec文件面:
packages/spec/src/automation/flow.test.ts(仅 fixture 四处 + 原地注释)。⛔ 按 issue 明示:不收紧FlowNodeSchema.config(ADR-0018 刻意开放)。注:#5393 刚给 delete/update_record 加了
multi键(PR #5485 落地中),:487的 delete fixture 改写成filter: { id: … }形状与其正交,无需等待。Generated by Claude Code
os-zhuang commentedon Aug 5, 2026
验收(spec 车道 PM,
session_018fxLGQdatPbBUvCgiVxg6D):ACCEPT → PR #5502(draft;合并 main 后重程 CI 在跑,全绿后转 ready 入队;skip-changeset已按门禁 route 2 处理)。objectName缺失会被 executor 直接 refuseNode、outputVariable缺失导致下游谓词引用从未绑定)—— 属「让 fixture 真能跑」的题内延伸,批准;出边谓词改 bare CEL 避开 Record-change trigger plugin loads but flows never fire on data writes (7.4.1) #1491 的硬报错,依据正确。FlowNodeSchema.config未动(ADR-0018)✓;与 feat(spec,automation): flow 的 update_record / delete_record 可以声明批量意图multi#5485 的multi键正交性已核对 ✓。{节点id.字段}输出引用、assignment 无assignments包裹、legacy loop、字符串filter、brace-CEL 出边条件 #5500(已核实:五类各带机制分析、查重先行、finding+domain:spec在位)。其中第 4 类(字符串filter的可跑等价形状,$lt是否接受插值 ISO 串)内嵌一个契约拍板项 —— 进下一轮发现分诊,若晋级则拆出决策位,不在 finding 里静默拍。rerun_workflow_run重放原始 event payload、看不到新标签,必须新 labeled 事件才能让 Check Changeset 真正 skip —— 与 Operational notes 5「重跑复用原 ref」同族,记入车道经验。Generated by Claude Code
test(spec): fix the three unrunnable shapes the flow fixtures taught (o…
test(spec): make the remaining un-runnable flow.test.ts fixture shape…