Skip to content

trigger-record-change 的 input.doc 防御性 alias 读的是一个没有生产者的键(引擎只建 input.data) #5671

Description

@os-zhuang

在 #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」)。

关联

Activity

  1. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    ContributorAuthor

    发现分诊(#4949 纪律):持有,保留 finding,补 domain:services(落点 packages/triggers/trigger-record-change,triggers 族归 services 车道——域表)。

    一行理由:纯休眠代码零行为影响(input.doc 分支在任何引擎路径上不可达,已核作者对 origin/main 的生产点盘点),但 PD #12 的化石化论据成立,值得清。重启条件:PR #5668(#5273)合入 main 后晋级——届时 hook-input-shape-contract.test.ts 的 pin 在 main 上,删 alias + 两处 fixture re-spell 成为纯机械活;在其之前动手会对着还在飞的真值源。

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  2. os-zhuang commented on Aug 6, 2026

    @os-zhuang
    ContributorAuthor

    发现分诊(#4949 纪律):重启条件已触发,晋级 —— 摘 finding 换 pm:queue,domain:services 已在。

    依据:前次持有评论的重启条件 = PR #5668(#5273)合入 main,已于 2026-08-06 落地(28ce594),pin packages/objectql/src/hook-input-shape-contract.test.ts 已在 origin/main;record-change-trigger.ts:298-299 的 input.doc alias 仍在,该包自 #5635 后无相关改动 —— 按预记计划,删 alias + fixture re-spell(含 record-change-trigger.test.ts:303 那个「falls back to input.doc」用例的整条替换)现在是纯机械活。

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  3. self-assigned this
    on Aug 6, 2026
  4. hotlong commented on Aug 6, 2026

    @hotlong
    Contributor

    认领:PM 循环第 1 轮(services 车道)
    会话:session_015a5qkLzpGXhLL2F5gvJ7dD
    分支:claude/issue-5671-drop-input-doc-alias
    Worktree:objectstack-issue-5671
    域:domain:services
    文件面:packages/triggers/trigger-record-change/src/record-change-trigger.ts + 同包测试(含 record-change-trigger.test.ts:303「falls back to input.doc」用例整条替换)+ packages/services/service-storage/src/attachment-lifecycle.test.ts(fixture re-spell);⛔ 不触 packages/spec —— hook.test.ts:422 的 fixture 半边已转席 #5886(spec 座位)
    串行约束已清:今日 2a607d2(#5806)迁移了该包 7 条集成测试到 sqlite :memory:,基于合并后 origin/main


    Generated by Claude Code

  5. hotlong commented on Aug 6, 2026

    @hotlong
    Contributor

    验收:ACCEPT → PR #5908(CI 23/23 绿,随后转 ready 入队,本座位跟到 MERGED)。

    经办:services 座位,会话 session_015a5qkLzpGXhLL2F5gvJ7dD(第 1 轮)。


    Generated by Claude Code

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