在 #5545(给 client.meta.getItem 补返回类型注解)里测绘到。写侧的同一问题已由 #5745 修掉(SaveMetaItemResponseSchema 曾是真实 body 的真子集,version/seq/state 被抹);读侧还留着一个没人收的同形缺口。
事实(基线 origin/main @ a6b3ee7a1)
spec 声明(packages/spec/src/api/protocol.zod.ts:234)只有三个键:
export const GetMetaItemResponseSchema = lazySchema(() => z.object({
type: z.string(), name: z.string(), item: z.unknown(),
}));
生产端(packages/metadata-protocol/src/protocol.ts getMetaItem,主 return 在 :3733 附近)发的是超集:
return {
type: request.type,
name: request.name,
item: decorated,
lock: lockState.lock,
...(lockState.lockReason !== undefined ? { lockReason: lockState.lockReason } : {}),
...(lockState.lockSource !== undefined ? { lockSource: lockState.lockSource } : {}),
REST 侧 translateMetaEnvelope(packages/rest/src/rest-server.ts:2714)...envelope 原样铺开,所以这三个键会到线上。而 #5563 收敛后的缓存分支(默认 enableCache: true)重建的信封只有 { type, name } + item,代码注释里写明是有意的:
rest-server.ts:4278 — "The cached read carries no lock — it is the fast published-value path and never consulted the lock resolver; a caller that needs the ADR-0008 OCC carriers reads the uncached path."
为什么这是个缺口
#5563 把文档的形状在两条分支上收敛了,但 OCC 载体没有:lock 是否出现仍由服务端 enableCache 决定,且这件事在 spec 里一个字也没有。于是
处置(建议,待分诊)
在 GetMetaItemResponseSchema 上把三个键声明为 optional,并在 describe 里写清「仅非缓存读路径提供;缓存读路径不解析锁」——这与 #5745 的做法一致(先实测哪些必选、哪些条件出现,再照实声明),且不改任何运行时行为。若认为「配置决定字段有无」本身才是要修的,那是更大的一步,应单独定案。
关联:#5545(测绘出处)、#5563(读路由形状收敛)、#5745(写侧同形缺口,已修)、ADR-0008。
在 #5545(给
client.meta.getItem补返回类型注解)里测绘到。写侧的同一问题已由 #5745 修掉(SaveMetaItemResponseSchema曾是真实 body 的真子集,version/seq/state被抹);读侧还留着一个没人收的同形缺口。事实(基线
origin/main@a6b3ee7a1)spec 声明(
packages/spec/src/api/protocol.zod.ts:234)只有三个键:生产端(
packages/metadata-protocol/src/protocol.tsgetMetaItem,主 return 在 :3733 附近)发的是超集:REST 侧
translateMetaEnvelope(packages/rest/src/rest-server.ts:2714)...envelope原样铺开,所以这三个键会到线上。而 #5563 收敛后的缓存分支(默认enableCache: true)重建的信封只有{ type, name }+item,代码注释里写明是有意的:为什么这是个缺口
#5563 把文档的形状在两条分支上收敛了,但 OCC 载体没有:
lock是否出现仍由服务端enableCache决定,且这件事在 spec 里一个字也没有。于是meta.getItem没有声明返回类型(载荷为unknown),而并排的meta.getItems有 —— 同一表面上相邻两个方法的类型化不对等 #5545 之后meta.getItem标Promise< GetMetaItemResponse >)在类型上看不到lock,要读只能 cast —— 正是本仓一贯反对的消费端宽容;If-Match」这条 ADR-0008 链路,写侧有契约([#5563 附带裁决] SaveMetaItemResponseSchema 补齐实现实际返回的字段(version / seq / state / projectionApplied) #5745 补的version),读侧没有;GET /meta/:type/:nameanswers two different body shapes on the same request — the cached branch (the DEFAULT) returns the bare document, the non-cached branch returns the spec-declared{ type, name, item }envelope #5563 那类「配置决定契约」的残留。处置(建议,待分诊)
在
GetMetaItemResponseSchema上把三个键声明为 optional,并在 describe 里写清「仅非缓存读路径提供;缓存读路径不解析锁」——这与 #5745 的做法一致(先实测哪些必选、哪些条件出现,再照实声明),且不改任何运行时行为。若认为「配置决定字段有无」本身才是要修的,那是更大的一步,应单独定案。关联:#5545(测绘出处)、#5563(读路由形状收敛)、#5745(写侧同形缺口,已修)、ADR-0008。