Repository navigation
Closed
Labels
domain:cliRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they landRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they landpm: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
观察类(finding):与 #5138 同样的可达性 —— 装了 MetadataPlugin(@objectstack/metadata-protocol,注册 protocol 槽)的部署走 protocol 优先路径,碰不到兜底。记录在案交分诊定级,不自行判轻重。
实现 #5138(PR 见下)时在同一函数里撞见,不在该单范围内(#5138 收敛的是「记录不存在」的答案,这一条是「删除成功」的答案),故另立。
事实
packages/runtime/src/action-execution.ts 的 callData('delete', …) 两条路径回的成功体不是同一个形状:
| 路径 | 返回 | 与 spec |
|---|---|---|
protocol(deleteData,packages/metadata-protocol/src/protocol.ts) |
{ object, id, success: true } |
合规范 |
ObjectQL 兜底(action-execution.ts,delete 分支末行) |
{ object, id, deleted: true } |
success 缺失,deleted 未声明 |
规范只有一个:
packages/spec/src/api/protocol.zod.ts:472
export const DeleteDataResponseSchema = lazySchema(() => z.object({
object: z.string().describe('Object name'),
id: z.string().describe('Deleted record ID'),
success: z.boolean().describe('Whether deletion succeeded'),
}));
实测(#5138 的复现 harness,同一行数据,唯一差别是注不注册 protocol 槽,main @ c11369013):
PROTOCOL del (hit): {"object":"task","id":"r1","success":true}
FALLBACK del (hit): {"object":"task","id":"r1","deleted":true}
还有一处文档面与规范相反
packages/runtime/src/domains/data.ts:102 的路由注释写的是:
// Spec: returns DeleteDataResponse = { object, id, deleted }
DeleteDataResponseSchema 声明的是 success,不是 deleted。所以这条注释把兜底的形状当成了规范 —— 下一个读它的人(或 agent)会照着 deleted 写消费端。同文件 87/94 行的 get/update 注释与各自的 schema 是对上的,只有 delete 这条对不上。
为什么值得记
DELETE /data/:object/:id的成功体因部署是否装 protocol 插件而不同,而调用方无从分辨自己走的是哪条 —— 与 callData 的 ObjectQL 兜底路径对「记录不存在」给三种不同答案(get→200 null / update→500 / delete→200 deleted:true) #5138 是同一个「一个callData、两种答案」的家族,只是落在成功侧而非 not-found 侧;- 按
DeleteDataResponseSchema写的客户端在精简装配上读到success === undefined,即「删除是否成功」读不出来,而 HTTP 状态是 200; - 声明式端点执行器(E5(#5040 执行器):执行目标委派 —— endpoint target 映射到既有 flow / script / proxy 执行管线 #5092 / PR feat(runtime): 端点执行目标委派 —— endpoint-executor 纯模块(#5040 E5) #5136)逐字节复用
/data的委派形状,同样原样继承这个分叉; - 修点在
callData一处(兜底改回success,或规范改成deleted—— 要拍板哪个是规范,spec 现物是success),消费者侧各自兼容两种键正是 contract-first 禁止的形状。
不在 #5138 处置的原因
#5138 的验收面是「记录不存在时三分支给同一个 404 RECORD_NOT_FOUND」,其 PR 已按此收敛并显式保持 deleted: true 原样(有测试钉住成功路径未变)。本条要决定的是「删除成功的规范键是 success 还是 deleted」,是一次独立取舍,且会动到 spec 或所有 deleted 的读取方,不适合搭车。
Metadata
Metadata
Assignees
Labels
domain:cliRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they landRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they landpm: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
发现分诊轮判级:晋级 —— 摘
finding换pm:queue+domain:cli。packages/runtime/src/action-execution.ts的callDatadelete 兜底与 protocol 路径({success:true},合 spec 声明)形状分叉,返回 spec 未声明的{deleted:true};同一操作两种成功体是活体行为分歧,收敛方向明确(向 spec 声明形状对齐 + 两条路径同形 pin)。packages/runtime归 cli 车道。packages/client对 204 空体也自造{deleted: true}(client/src/index.ts:3416等四处,rc.2 变更记录在案)—— 先确认契约权威侧(spec 的{success:true}vs client 的 204 归一)再动手;若牵动 client 公开返回形状,回分诊上报,勿静默扩面。本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
baozhoutao commentedon Aug 5, 2026
认领 + 方向裁定(PM 会话
session_016FNvXhtSdnEGEfLEsMmvxh,cli 车道;#5615 热修已落,action-execution.ts面解锁)裁定(restore-invariant,带 veto window):兜底向 spec 声明形状收敛——
DeleteDataResponseSchema(protocol.zod.ts:472)现物是{object, id, success},protocol 路径已合规,兜底的deleted: true改为success: true;domains/data.ts:102那条与 spec 相反的注释一并改正。两条路径同形以测试钉住(照 #5138/PR #5584 的跨路径同一性断言先例)。claude/issue-5581-delete-success-shape../objectstack-5581(os-dev 自建)packages/runtime/src/action-execution.ts(delete 分支末行)+domains/data.ts注释 + 测试(可扩展 fix(runtime): callData 的 ObjectQL 兜底对「记录不存在」统一答 404 RECORD_NOT_FOUND (#5138) #5584 落的action-execution-calldata-not-found.test.ts同族,注意其 engine double 已接assertEngineDeleteDispatch,勿回退 hotfix(runtime): route #5138 test engine doubles through assertEngineDeleteDispatch #5615)。packages/client对 204 空体自造{deleted: true}(index.ts:3416等四处)——先测绘该归一化与本单的消费关系;若收敛牵动 client 公开返回形状,停手回报,勿静默扩面到 client。deleted键的既有读取方测绘(含声明式端点执行器面)是本单最大回归风险,先测后动。Generated by Claude Code
baozhoutao commentedon Aug 5, 2026
开工(os-dev,session
session_016FNvXhtSdnEGEfLEsMmvxh派发,cli 车道)claude/issue-5581-delete-success-shape../objectstack-5581(基于 origin/main,含 hotfix(runtime): route #5138 test engine doubles through assertEngineDeleteDispatch #5615)deleted: true→success: true,domains/data.ts注释改正,两条路径同形以测试钉住。deleted键读取方全仓测绘 +packages/client204 归一化的消费关系测绘;若收敛牵动 client 公开返回形状则停手回报。Generated by Claude Code
chore: 退回本地 `gen:schema` 顺带重生成的 authorable-surface 锚点 (#5581)
baozhoutao commentedon Aug 5, 2026
draft PR 已开:#5641(等 CI 收敛后交报告)
前提复核成立,且裁定方向额外拿到一条独立佐证:公开 HTTP 文档
content/docs/protocol/kernel/http-protocol.mdx:649一直写的就是success(含{"object","id","success":true}示例体)。spec、protocol 实现、公开文档三者一致,兜底是唯一偏离方。两条警示的结论:
deleted读取方测绘 —— 无回归。全仓(packages//examples//apps//packages/qa含 dogfood 与 http-conformance)没有任何消费方从/datadelete 响应体读.deleted;三个callData('delete')调用点(domains/data.ts/domains/mcp.ts的remove/endpoint-executor.ts:434)全是直通。domains/automation.ts:472那条{name, deleted:true}是 automation flow 注销面,protocol.delete-many.test.ts那条是engine.delete的返回,两者都与本单无关,未动。client 归一化与本单面无交集。五处 204 归一化(
index.ts3416/3467/3536/3590/3799)逐条核过路由 —— shares revoke、sharing rules delete、reports delete、report schedules unschedule、ai conversations delete,没有一条走/data/:object/:id;client.data.delete走 200 + JSON 体,不经过 204 归一化。故未牵动 client 公开返回形状,无需停手扩面。测绘中另发现一条界外缺陷,查重(含 closed)无果后已无标签立单 #5638:
client的DeleteDataResult自称Spec: DeleteDataResponseSchema却声明deleted: boolean,是纯直通类型声明,在装了 protocol 插件的常规部署上此前就已经是错的(TS 写r.deleted编译通过、运行时恒undefined)。属公开导出接口的破坏性重命名,故未搭车。反向验证方向先判后跑,与预判一致:兜底改回
deleted: true→ fallback 侧 6 条断言全红,protocol 侧 parse 保持绿(6 failed | 25 passed)。Generated by Claude Code
baozhoutao commentedon Aug 5, 2026
ACCEPT → PR #5641(PM 会话
session_016FNvXhtSdnEGEfLEsMmvxh,cli 车道)验收依据:
http-protocol.mdx:649的公开文档一直声明success(含示例体)——spec、protocol 实现、公开文档三者一致,兜底是唯一偏离方,「无第二种读法」。safeParse+ 跨路径逐字段相等 + 显式断言不含deleted残留键——第三层是必要的,z.object剥未知键,单靠 parse 抓不到残留;两个消费面(真 dispatcher 的/data+ 声明式端点执行器)都钉了,且区分了body.success(信封 ok)与body.data.success(删除发生)两个事实。DeleteDataResult类型自称对齐 schema 却声明deleted: boolean(常规部署上此前就是错的类型)——以 client SDK 的DeleteDataResult注释写着 "Spec: DeleteDataResponseSchema" 却声明deleted: boolean,而该 schema 声明的是success—— 类型骗过编译器,运行时读到 undefined #5638 独立立单(公开导出接口重命名,blast radius 与 semver 另判),不搭车,正确。转 ready 挂 auto-merge,跟到 MERGED。
Generated by Claude Code
fix(runtime): callData 的 delete 兜底返回 spec 声明的 `{object, id, success}`…
fix(client)!: `DeleteDataResult` 声明它自称的 schema —— `success`,不是 `delet…
feat(devx): ratchet check:engine-double-contract's consumer-seam popu…
feat(devx): ratchet check:engine-double-contract's consumer-seam popu…
docs(mcp): re-anchor the dead tracker citations in packages/mcp/src t…