范围外发现,记录于 #6751 的实现过程中(PR #7075)。观察类:今天没有用户路径命中,门禁红绿不受影响,单纯记录同一文件里同一类的两处剩余缺口。
#6751 修的是 aggregateCategoryShards:它把分片的数组字段 as string[] 一转就喂给 categoryOfDefKey,非字符串条目于是死在 helper 里。修法是在遍历处加一次 typeof 校验(报文件名 + 条目下标 + 锚点)。
同一文件 packages/spec/scripts/lib/sharded-artifacts.ts 里还有两个读取器做了同样的转换、但走不到那次校验,所以 #6751 的落点覆盖不到它们:
1. readShardedKeysAtRev —— 历史基线读取
两条分支(sharded / legacy)都是:
const list = doc[field];
if (!Array.isArray(list)) return { error: `… has no "${field}" array` };
entries.push(...(list as string[]));
Array.isArray 只回答「是数组」,不回答「里面是什么」。非字符串条目会原样流进基线集合。它不调用 categoryOfDefKey,所以 #6751 加的那格分支永远碰不到它。
后果不是绕过:删除门禁拿基线与当前集合做差,一个数字条目会被算成「消失的 key」并索要 tombstone —— 响亮但指错人的失败,而不是静默通过。
2. aggregateApiSurfaceShards —— 第四个分片产物
if (!Array.isArray(shard.doc.exports)) {
throw new Error(`… has no "exports" array (#5837).`);
}
surface[shard.doc.entry] = shard.doc.exports;
同样只校验容器不校验条目。api-surface/ 是第四个分片产物,#6751 明确不覆盖它 —— 因为它不经 categoryOfDefKey 路由,所以那单的实测表格里也没有它。
为什么归为观察类
建议修法(窄)
与 #6751 已落地的形状同族:在两处的 Array.isArray 之后各加一次逐条 typeof 校验,复用同样的消息骨架(文件名 + 字段名 + 条目下标 + #5837 锚点)。aggregateCategoryShards 里现成的 jsonTypeLabel 可直接复用。历史基线那处要注意它的返回形状是 { error } 而非 throw,消息得走同一骨架但换承载方式。
关联:#6751(同类,已修,PR #7075)、#5837(分片重做)。
Generated by Claude Code
范围外发现,记录于 #6751 的实现过程中(PR #7075)。观察类:今天没有用户路径命中,门禁红绿不受影响,单纯记录同一文件里同一类的两处剩余缺口。
#6751 修的是
aggregateCategoryShards:它把分片的数组字段as string[]一转就喂给categoryOfDefKey,非字符串条目于是死在 helper 里。修法是在遍历处加一次typeof校验(报文件名 + 条目下标 + 锚点)。同一文件
packages/spec/scripts/lib/sharded-artifacts.ts里还有两个读取器做了同样的转换、但走不到那次校验,所以 #6751 的落点覆盖不到它们:1.
readShardedKeysAtRev—— 历史基线读取两条分支(sharded / legacy)都是:
Array.isArray只回答「是数组」,不回答「里面是什么」。非字符串条目会原样流进基线集合。它不调用categoryOfDefKey,所以 #6751 加的那格分支永远碰不到它。后果不是绕过:删除门禁拿基线与当前集合做差,一个数字条目会被算成「消失的 key」并索要 tombstone —— 响亮但指错人的失败,而不是静默通过。
2.
aggregateApiSurfaceShards—— 第四个分片产物同样只校验容器不校验条目。
api-surface/是第四个分片产物,#6751 明确不覆盖它 —— 因为它不经categoryOfDefKey路由,所以那单的实测表格里也没有它。为什么归为观察类
建议修法(窄)
与 #6751 已落地的形状同族:在两处的
Array.isArray之后各加一次逐条typeof校验,复用同样的消息骨架(文件名 + 字段名 + 条目下标 +#5837锚点)。aggregateCategoryShards里现成的jsonTypeLabel可直接复用。历史基线那处要注意它的返回形状是{ error }而非 throw,消息得走同一骨架但换承载方式。关联:#6751(同类,已修,PR #7075)、#5837(分片重做)。
Generated by Claude Code