在 #5273(PR #5668)核对 HookContext.input 契约表时发现,PD #10 单独记录。观察类(finding):今天没有用户会撞上,它是一条永不命中的兜底分支。
事实(对 origin/main 核实)
packages/triggers/trigger-record-change/src/record-change-trigger.ts:295-300:
const inputDoc =
input.data && typeof input.data === 'object'
? input.data
: input.doc && typeof input.doc === 'object'
? input.doc
: undefined;
input.doc 这条分支在任何引擎路径上都不可达:
该文件自己的注释其实已经写明了真值:
objectql lifecycle hooks carry the written row under input.data (insert / update payload); id is on update. (doc kept only as a defensive alias.)
packages/spec 的契约表当时确实把 insert 写成 { doc: Record, options } —— 那是假的,已由 PR #5668 改成 { data, options } 并加 pin。所以这条 alias 现在连「文档这么说」的依据也没有了。
分级说明
标 finding:纯休眠代码,行为上零影响。但它是 AGENTS.md PD #12 点名的那类消费端 ?? 兜底——「a tolerant fallback fossilizes the wrong convention into a second de-facto contract」——而且是为一个从来不存在的生产者留的。严重程度请分诊轮判。
建议
删掉 input.doc 分支与类型里的 doc?: 声明,只读 input.data;真值已被 packages/objectql/src/hook-input-shape-contract.test.ts(PR #5668 新增,断言 insert 上下文有 data、无 doc)钉住。
顺带:packages/spec/src/data/hook.test.ts:422 与 packages/services/service-storage/src/attachment-lifecycle.test.ts:159 的 fixture 也拼的是 input: { doc: … }。两处都只喂开放形状的 z.record,不会因此变红,但它们是照旧契约表写的,清理时应一并按引擎真值重拼(fixture 三分法里的「re-spell」)。
关联
在 #5273(PR #5668)核对
HookContext.input契约表时发现,PD #10 单独记录。观察类(finding):今天没有用户会撞上,它是一条永不命中的兜底分支。事实(对
origin/main核实)packages/triggers/trigger-record-change/src/record-change-trigger.ts:295-300:input.doc这条分支在任何引擎路径上都不可达:HookContext生产点恰好 5 处,全在packages/objectql/src/engine.ts,加上 [17.x] 批量写按行语义实现:hook 按行触发 + record-change trigger 按行绑定 previous/record(#4800/#4862 拍板 A) #5038 的buildPerRowAfterContexts。写事件构造的键是data(insert4879、update5243),没有一处写doc。beforeInsert/beforeUpdate上input.data恒为对象,所以三元第一支恒真;beforeDelete/afterDelete根本不带data也不带doc,落到previous兜底。两种情况都轮不到input.doc。该文件自己的注释其实已经写明了真值:
packages/spec的契约表当时确实把 insert 写成{ doc: Record, options }—— 那是假的,已由 PR #5668 改成{ data, options }并加 pin。所以这条 alias 现在连「文档这么说」的依据也没有了。分级说明
标
finding:纯休眠代码,行为上零影响。但它是 AGENTS.md PD #12 点名的那类消费端??兜底——「a tolerant fallback fossilizes the wrong convention into a second de-facto contract」——而且是为一个从来不存在的生产者留的。严重程度请分诊轮判。建议
删掉
input.doc分支与类型里的doc?:声明,只读input.data;真值已被packages/objectql/src/hook-input-shape-contract.test.ts(PR #5668 新增,断言 insert 上下文有data、无doc)钉住。顺带:
packages/spec/src/data/hook.test.ts:422与packages/services/service-storage/src/attachment-lifecycle.test.ts:159的 fixture 也拼的是input: { doc: … }。两处都只喂开放形状的z.record,不会因此变红,但它们是照旧契约表写的,清理时应一并按引擎真值重拼(fixture 三分法里的「re-spell」)。关联
HookContext.input的契约注释声明批量写携带input.ast,引擎从不设置它(AST 只在 opCtx 上);同一张表也未描述 #5038 后 after 事件的按行形状 #5273 / PR docs(spec): HookContext.input 契约表改成引擎真正构造的形状 (#5273) #5668ctx.input.ast」——与 #5273 同一句假话,只是另外三个面 #5670(同源的技能/文档面)