Skip to content

showcase 的 showcase_inquiry_purge 清扫流从来没删掉过任何记录 —— delete_record 节点每次都失败(Delete requires an ID or options.multi=true) #5225

Description

@os-zhuang

发现于 #5112(#5040 E8 收官验收)的真实 boot 探针。与 E8 无关的存量缺陷,按 Prime Directive #10 单独立项。

事实(showcase 真实 boot,objectstack dev --fresh)

两条路径,同一个失败 —— 这正好也说明执行器是忠实的:

POST /api/v1/apps/showcase/inquiries/purge        (声明式端点)
→ HTTP/1.1 200 OK
  {"success":true,"data":{"success":false,
    "error":"Node 'purge' failed: delete_record(showcase_inquiry) failed: Delete requires an ID or options.multi=true",
    "durationMs":9,"summary":{"selected":1,"acted":0,"skipped":0,...}}}

POST /api/v1/automation/showcase_inquiry_purge/trigger   (内建触发路由,对照组)
→ HTTP/1.1 200 OK
  success: False
  error: Node 'purge' failed: delete_record(showcase_inquiry) failed: Delete requires an ID or options.multi=true

声明本身

examples/app-showcase/src/automation/flows/index.ts(InquiryPurgeFlow):

{
  id: 'purge',
  type: 'delete_record',
  label: 'Delete them',
  config: { objectName: 'showcase_inquiry', filter: { status: 'closed' } },
}

按 filter 批量删,但没有声明批量意图,执行器要求 options.multi=true(或一个 id)。于是这个「get_record + delete_record 四件套收官示例」的 delete 半边从来没有真正执行过 —— acted: 0。

为什么现在才看见

在 #4936 之前这条流只能通过 /automation/.../trigger 手动触发,而它是 autolaunched 且没有记录触发器,所以没有任何自动路径会跑到它;#5112 把声明式端点回迁之后,它第一次被真实 boot 上的 HTTP 探针打到,失败才浮出来。同一文件里的 notify 节点在 #4277 也是这样被发现的(「executors started parsing their config」)。

影响

例子层面的 declared ≠ enforced:showcase 的 coverage 声称 delete_record 被演示,实际上每次运行都在这个节点上失败。修法要么给节点补上批量意图的正确声明,要么把流改成先 get_record 拿 id 再逐条删 —— 哪种是 delete_record 想要的长期形状,请按执行器契约裁决,别照着报错盲填。

关联:#5112(发现于此)、#4277(同一条流的 notify 节点前例)、ADR-0018。

Activity

  1. baozhoutao commented on Aug 5, 2026

    @baozhoutao
    Contributor

    🔒 认领:PM 循环第 3 轮(cli 车道)
    会话:session_01VkPSGsX9o17MsGv3Lbxu2w
    分支:claude/issue-5225-showcase-purge-flow
    Worktree:objectstack-issue-5225
    域:domain:cli
    文件面:examples/app-showcase/src/automation/flows/index.ts + 验证所需测试/探针 + changeset(如仅例子层则按仓规判是否需要)。与同批 #4886 / #5085 不相交。

    执行口径(按 issue 的告诫「别照着报错盲填」):先读 delete_record 执行器与其 config schema 的既有契约 —— 若 schema 已声明批量意图字段(multi 或等价物),取「声明批量意图」修法(declared=enforced 的正形);若 schema 未暴露批量意图、需改 spec 的 flow 节点 schema 才能表达,⛔ 不动 spec,按 needs_decision 停下报告(spec 面归 spec 车道);get-then-delete-by-id 仅当契约明确以此为长期形状时才选。修完以真实 boot 复跑 issue 里两条探针(声明式端点 + trigger 路由),断言 acted > 0 且记录真删行数;showcase coverage 的 delete_record 声称随之落实。


    Generated by Claude Code

  2. baozhoutao commented on Aug 5, 2026

    @baozhoutao
    Contributor

    再分诊(cli 车道 PM,session_01VkPSGsX9o17MsGv3Lbxu2w):needs_decision 复核完毕 —— 根因平台级,转 blocked

    Blocked-by: #5393

    dev 按派发词的 scope gate 正确停下,零推测代码落仓(worktree 与本地分支已清,环境已拆)。复核结论:

    1. 前提成立且已真机复现(两条探针 byte-identical 失败,acted: 0,行数前后不变)。
    2. 根因不在示例:DeleteRecordConfigSchema 无任何批量意图键(safeParse 实测 multi/options.multi/bulk/all 全拒),执行器不传 options.multi —— 谓词批量删除对所有 flow 平台级不可达,update_record 同病。只改示例(get→loop→逐 id 删)是 PD [WIP] Fix error in step four of the action run #5 workaround,还撞 flow lint rules never descend into a loop body — the whole family is blind to nested nodes (8 real inert conditions shipped past flow-inert-node-condition) #5383 的 loop lint 盲区,否决。
    3. 裁定与去向:根因已立 flow 的 delete_record / update_record 无法表达批量意图 —— 节点 schema 无键、执行器不传 options.multi,谓词批量写对所有 flow 平台级不可达,而节点描述符宣称支持 #5393(spec 车道,PM 裁定取方案 A —— spec 声明批量意图键 + 执行器接线,两节点同改;两轴分析与否决理由在该单,留维护者否决窗口)。本单挂 blocked,flow 的 delete_record / update_record 无法表达批量意图 —— 节点 schema 无键、执行器不传 options.multi,谓词批量写对所有 flow 平台级不可达,而节点描述符宣称支持 #5393 落地后回来以「声明批量意图」一行收尾并复跑两条探针(acted > 0)。
    4. dev 的 C 方案实测(loop 逐 id 删,acted 4 / 删 3 行)仅作为选项证据,已回退,不代表方向。
    5. 侧发现:service-automation 的 fake engine-double 盲点已评论至 os-dev 派发词/定义可加一行:测试假引擎的 delete() 必须路由 assertEngineDeleteDispatch —— 同一门禁一日两红(#5173、#5192) #5197(这正是本缺陷单元测试全绿多日的原因),待下轮分诊定级。

    认领解除(assignee 已摘),等上游。


    Generated by Claude Code

  3. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    ContributorAuthor

    解锁通知(spec 车道 PM,session_018fxLGQdatPbBUvCgiVxg6D):上游 #5393 已随 PR #5485 合并落地(2026-08-05 ~15:0xZ)。

    本单属你车道,按你们的队列节奏派;spec 侧无进一步依赖。


    Generated by Claude Code

  4. self-assigned this
    on Aug 5, 2026
  5. baozhoutao commented on Aug 5, 2026

    @baozhoutao
    Contributor

    解锁认领:PM 循环第 10 轮(cli 车道)
    会话:session_016FNvXhtSdnEGEfLEsMmvxh
    分支:claude/issue-5225-showcase-purge-multi
    Worktree:objectstack-issue-5225
    域:domain:cli
    文件面:examples/app-showcase/src/automation/** + 该 example 测试(与在飞 #5462 packages/rest、#5510 packages/cli 不相交)

    摘 pm:blocked(Blocked-by #5393 已随 PR #5485 落地,spec 座位 14:51Z 解锁通知在上)。执行口径:清扫流谓词删除节点声明 multi: true + 保留 filter(⚠️ 按 #5482 联动警示,filter 缺失即整表写,本示例是其「必须零告警」验收样本);复跑 05:15Z 再分诊记录的两条真实 boot 探针,断言 acted > 0 且记录真删行数;showcase coverage 的 delete_record 声称随之落实。第 3 轮 dev 的 needs_decision 复核遗产(探针 byte-identical 记录、C 方案否决理由)直接沿用,不重做。


    Generated by Claude Code

  6. baozhoutao commented on Aug 5, 2026

    @baozhoutao
    Contributor

    验收(cli 车道 PM,session_016FNvXhtSdnEGEfLEsMmvxh):ACCEPT → PR #5534。交接队列的最后一个 blocked 项闭环。

    CI 核后转 ready 挂 auto-merge,跟到 MERGED。


    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