Repository navigation
Closed
Labels
bugSomething isn't workingSomething isn't workingdomain:specDomain lane — seat card indexed by label:pm:seatDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatchDispatched to a dev agent by /pm-dispatchpm:queueReady for the PM dispatch loopReady for the PM dispatch loop
Description
Part of #5225(showcase 清扫流从未删过记录 —— 该单的根因,按跨车道协议转 spec 车道;发现与全部实测证据来自其 os-dev 的 needs_decision 报告,PM 转录)。
事实(真实 boot + built spec 的 safeParse 实测,origin/main @ ccba1bb)
DeleteRecordConfigSchema(packages/spec/src/automation/builtin-node-config.zod.ts:242)是strictObject,只声明objectName与filter两键;multi/options.multi/bulk/all逐一实测被unrecognized_keys拒绝。- CRUD 执行器(service-automation)调用引擎时从不传
options.multi。引擎契约(packages/objectql/src/engine-delete-dispatch.ts):标量where.id→ 按 id;否则options.multi为真 → deleteMany;否则抛Delete requires an ID or options.multi=true。 - 于是谓词批量删除从任何 app 的任何 flow 都不可达,而节点描述符写着
name: 'Delete Records'/description: 'Delete records matching a filter.';writtenRowCount的文档与 Flow node filters silently blank date macros: the template engine consumes{…}before the query engine sees it #3810 擦除防护的前提都以「谓词 delete_record 会到达 deleteMany」为设计意图 —— declared ≠ enforced。 update_record同病(engine.ts:5403同款抛错,UpdateRecordConfigSchema同样无批量键);showcase 三处update_record全用filter: { id: … }所以被掩盖。- 单元测试全程绿的原因已另记:service-automation 的
run-summary.test.ts:405内联 fake 接受真引擎拒绝的谓词删除,且不在 engine-double 基线内(已评论至 os-dev 派发词/定义可加一行:测试假引擎的 delete() 必须路由 assertEngineDeleteDispatch —— 同一门禁一日两红(#5173、#5192) #5197,检测器盲点)。
PM 裁定(两轴分析由 #5225 的 dev 给出,PM 附议;留否决窗口 —— 维护者可否决,不等批准)
取 A:在 spec 给两个节点 config 声明批量意图键(一次命名,两节点共用),CRUD 执行器在作者声明后传 options.multi;B 与 C 否决。
- 长远轴:A 是唯一契约先行的形态 —— 破坏性批量写的安全要求在 authoring 时可见,而不是在旗舰示例上以运行时失败浮现;B 在 flow 层伪造「作者声明过批量」,把引擎刻意竖起的护栏溶解掉,并分叉出第二份事实契约。
- 防 AI 轴:A 最强 —— 破坏性批量删除需要一个显式、可 grep 的声明,AI 只写 filter 会得到点名拒绝而非静默 no-op;B 是该轴上最坏选项:AI 元数据最常见错误就是 filter 字段名拼错,B 把它从「引擎拒绝」升级成「全表删除」(Flow node filters silently blank date macros: the template engine consumes
{…}before the query engine sees it #3810 只防模板插值失败的条件擦除,不防语法合法、语义错误的字面字段名);C(示例改 get→loop→逐 id 删)是 PD [WIP] Fix error in step four of the action run #5 的 workaround、PD chore: version packages #10 的反面,且撞上 flow lint rules never descend into aloopbody — the whole family is blind to nested nodes (8 real inert conditions shipped pastflow-inert-node-condition) #5383(flow lint 不进 loop 体),等于教 AI 一个 lint 盲区里的 N+1 删除惯用法。 - 两节点必须同改:拆开必然让同一个概念在两个 CRUD 写入器上长出两个名字与语义(PD Add comprehensive test suite for Zod schema validation #12 的「N 方言」结局),且生成面翻倍。
- 时序注:这是恢复宣称能力的加性键,非 breaking,不占 v17 硬窗口;spec 车道按自身节奏排(authorable-surface / docs / api-surface 生成物随行)。
完成判据
- 两个 config schema 声明同名批量意图键(surface/history/guidance 随 未知键静默剥离仍是全仓默认:把 #3405 的 strict 收紧从一个 schema 推广到整个可授权面(ADR-0078 完整性闸门) #4001 纪律);执行器接线
options.multi; - 引擎抛错路径对「未声明批量的谓词写」保持现状(拒绝即契约);
- showcase 的
showcase_inquiry_purge清扫流从来没删掉过任何记录 —— delete_record 节点每次都失败(Delete requires an ID or options.multi=true) #5225(showcase 示例)在此单落地后以声明批量意图收尾(该单挂 Blocked-by 本单); - service-automation 侧补真实契约测试(os-dev 派发词/定义可加一行:测试假引擎的 delete() 必须路由 assertEngineDeleteDispatch —— 同一门禁一日两红(#5173、#5192) #5197 记录的 fake 盲点不再掩盖)。
关联:#5225(现场与验收锚)、#5197(检测器盲点)、#5383(loop lint 盲区)、#3810、PD #5/#10/#12。
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workingdomain:specDomain lane — seat card indexed by label:pm:seatDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatchDispatched to a dev agent by /pm-dispatchpm:queueReady for the PM dispatch loopReady for the PM dispatch loop
Activity
os-zhuang commentedon Aug 5, 2026
认领:spec 车道第 1 轮⚠️ 跨入
会话:
session_018fxLGQdatPbBUvCgiVxg6D分支:
claude/issue-5393-flow-bulk-intentWorktree:
objectstack-issue-5393域:
domain:spec文件面:
packages/spec/src/automation/builtin-node-config.zod.ts(+生成物)、packages/services/service-automation/**(执行器接线options.multi+ 真实契约测试)。domain:services文件面,按跨域单一认领协议整单声明 —— engine/services 车道如有异议请在此回执;引擎拒绝路径保持现状(拒绝即契约),packages/objectql零改动。按 issue 在册裁定 A 执行(维护者 2026-08-05 已核准本单进 P0 批,否决窗口视为已过)。#5225 挂 Blocked-by 本单,落地后由其收尾。
Generated by Claude Code
os-zhuang commentedon Aug 5, 2026
验收(spec 车道 PM,
session_018fxLGQdatPbBUvCgiVxg6D):ACCEPT → PR #5485(draft;短程 12 checks 已绿,长程在跑,全绿后转 ready 入队)。裁定 A 落地完整,四条完成判据全部满足:
multi(boolean,默认 false)在两个 config schema 同名同语义声明,拼写处方(bulk/all/multiple+options.multi的错层答案)双门齐备,descriptorconfigSchema同步 → Studio 可作者化;multi: cfg.multi === true,packages/objectql零改动(拒绝即契约保持);assertEngineDeleteDispatch,门禁判 pinned —— 不是又一份手抄判定;update 侧结构性做不到的原因如实立单(objectql 的 UPDATE dispatch 没有共享判定函数 —— delete 有resolveEngineDeleteDispatch,update 的同款三分支只是 engine.ts 里的一个内联 throw #5480);消费半径按规则的调用方扫(cli/lint/metadata-protocol/objectql 全绿),生成物全套整体重生成零手改。两张范围外单已核实并代分诊:#5480(engine 队列:update dispatch 判定抽取)、#5482(devx 队列:
multi:true空 filter 的 authoring 告警,定级方案 1,待本 PR 落地后派)。#5225(showcase 清扫流)在本 PR MERGED 后解锁收尾,届时我在该单留解锁评论。
Generated by Claude Code
feat(spec,automation): declare bulk intent on update_record / delete_…
fix(showcase): declare `multi: true` on the inquiry purge flow's dele…
docs(pm-dispatch,os-dev): 假引擎的 delete() 一律路由 assertEngineDeleteDispat…
feat(lint): `multi: true` 且无 filter 的 delete/update 在 authoring 期告警(o…
refactor(objectql): update 的三分支派发抽成生产者侧唯一判定 + 门禁 update 切片 (objectsta…