Uh oh!
There was an error while loading. Please reload this page.
test(spec): 别名一致性闸门收编 44 个 strictUnknownKeyError 直调点 —— probe 撞车维度首测 (#5483) - #5609
Conversation
…5483) #5013 的闸门判的是 strictObject 建的表(构造期登记 {options, shape}),而 helper 之前的老接线直接调 strictUnknownKeyError、自带一份手抄 knownKeys 数组,没有 shape 可登记,于是这 44 张表在闸门的每一条判据之外。#5481 把判据加到三条之后,其中第三条 (表内 aliasProbe 撞车)只读别名表本身、不依赖 shape —— 也就是说这批表在撞车维度上 一直是「未测量」,而不是 issue 正文说的「已测干净」(那次测量早于 #5481)。 登记放在工厂里而不是调用点上:strictUnknownKeyError 首行把自己的 {surface, knownKeys, aliases, guidance} 记进一张独立的内部登记表 (shared/alias-table-registry.ts,不进 shared/index.ts 桶,与 strict-object.ts / alias-probe.ts 同待遇)。44 个调用点一个都没改,#5593 的迁移因此仍是一次干净可分离 的改动。strictObject 内部那次调用用 withoutDirectAliasTableRegistration 抑制登记 —— 它的表已带 shape 登记在更强的那张里,重复登记会让本表规模取决于此前有没有哪个测试 恰好触发过一次拒绝。 闸门的 forcing walk 现在也用一个合成 unrecognized_keys issue 构建 error map: strictObject 与 data/object.zod.ts 都把 map 延迟到首次拒绝才建,对直调点而言这个 延迟就是「登记了」和「根本看不见」的区别。 首测:44 个源码调用点 → 运行时 52 张表(ui/app.zod.ts 的导航项工厂一个调用点跑九次)。 - aliasProbe 撞车 0 条(参考:已覆盖的 235 张里实测 4 条,PR #5516 清零) - 别名 key 不得是已知键 0 条 - 别名 target 必须是已知键 32 条,同一根因:NAV_ITEM_ALIASES 的四条「默认展开」 别名指向 expanded,而 expanded 只声明在 group 变体上 —— 另外八个变体把作者指向 该变体同样会拒的键。已立 #5555;修法要改面向作者的文案且落在调用点里,本单不动, 这里钉成结构化的只减不增容差(≤32),第五种拼法直接红。 两处显式豁免各带一条陈旧检查:ui/app.zod.ts 六条刻意的散文式 target,以及 children 的 guidance 在 object/group 两个变体上本就合法。≤44 棘轮一字未动。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018fxLGQdatPbBUvCgiVxg6D
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📓 Docs Drift CheckThis PR changes 1 package(s): 109 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
os-zhuang
commented
Aug 5, 2026
PM 预记( Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#5483
按路线 1(过渡看守)落地:让
strictUnknownKeyError自己登记别名表,alias-integrity.test.ts因此把 44 个直调点也判了 —— 一个调用点都没改。为什么需要它
#5013 的闸门判的是
strictObject建的表:那个 helper 在构造期登记{ options, shape },所以闸门能拿到运行时 shape。helper 之前的老接线直接调strictUnknownKeyError,自带一份手抄的knownKeys数组,没有 shape 可登记,于是这 44 张表在闸门的每一条判据之外。#5481 之后判据从两条变成三条,而第三条(表内
aliasProbe撞车)只读别名表本身、不依赖 shape。所以本 issue 正文里那句「实测干净」只覆盖前两条 —— 这批表在撞车维度上是未测量,不是已测净。怎么做的
packages/spec/src/shared/alias-table-registry.ts:一张独立的登记表。刻意不并进strictObject那张,因为两者成色不同,合表等于把弱的那一半悄悄贴上「shape 背书」的标签。strictUnknownKeyError首行登记自己的{ surface, knownKeys, aliases, guidance }。登记放在工厂里而不是调用点上,这是「零调用点改动」的全部机关,也让 把 44 个strictUnknownKeyError直调点批量迁到strictObject,棘轮降到 0(路线 1 消不掉手抄数组与 shape 的漂移) #5593 的迁移仍然是一次干净可分离的改动。strictObject内部那次调用用withoutDirectAliasTableRegistration抑制登记:它的表已经带 shape 登记在更强的那张里,重复登记会让本表的规模取决于「此前有没有哪个测试恰好触发过一次拒绝」。规模随测试顺序漂移的东西不叫测量。unrecognized_keysissue)。两处 error map 是延迟构建的:strictObject(绕开field.zod与suggestions.zod的循环导入)和data/object.zod.ts(绕开 temporal dead zone)。对直调点而言,这个延迟就是「登记了」和「根本看不见」的区别。三条判据在这批表上的成色(闸门自己也这么写)
strictObject的 235 张.shape判.shape判(含墓碑)aliasProbe不得撞车前两条继承手抄数组与 shape 之间的漂移,那是路线 1 消不掉的一半,归 #5593。
首测结果
44 个源码调用点 → 运行时 52 张表(
ui/app.zod.ts的导航项工厂一个调用点跑九次,每个type变体一张;strictObject那 235 张不受影响)。ui/app.zod.ts把四条「默认展开」别名(defaultopen/open/collapsed/isopen指向expanded)放在九个变体共用的NAV_ITEM_ALIASES里,而expanded只声明在group上。于是另外八个变体把作者指向该变体同样会拒的键 —— ledger finding 7 的二次拒绝。已立ui/app.zod.ts导航项:4 条expanded别名在另外 8 个变体上把作者指向该变体同样拒绝的键(二次拒绝) #5555;修法要改面向作者的报错文案且落在调用点里,本单硬约束是不动那 44 个文件,所以这里只把它钉成只减不增的已知债(toBeLessThanOrEqual(32)),判定规则是结构化的:只放过「nav 变体表 + 这四个 key + target 恰为expanded」,第五种拼法直接红。两处显式豁免(都带陈旧检查,不许静默放过)
PROSE_ALIAS_TARGETS——ui/app.zod.ts六条刻意的散文式 target(形如type: 'url' (with url))。它们回答的是「键名对、变体错」,裸键名会误导。逐条枚举、绑定到 nav 那一族 surface;配套一条测试要求每条仍被用到,否则删除。VARIANT_LEGAL_GUIDANCE——children的 guidance 在object/group两个变体上确实不触发,因为那两个变体真的声明了children。一张手写 guidance 被盖了九份,这是判据碰上变体族、不是死条目;同样逐条枚举 + 陈旧检查。反向验证(先定方向再跑)
五次注入,每次先写下预期方向再执行:
expanded拼法broken两处预期没中,都按实测改了说法,没有把结果套回模板:
data/object.zod.ts:962的surface与别名条目都是字面量,AST 看得见,所以覆盖检查会把它报成 unreached。注释已按实测改写:这条按名钉住的断言不是让「触发缺失」可见的东西,而是让它可读 ——「this object不见了」指出机制,「object.zod.ts:962 未触达」只会让下一个人去找一个并不存在的 walk bug。常规测试
棘轮
toBeLessThanOrEqual(44)一个字符没动。它劝阻的事情 —— 新增一个直调点、再抄一份键表 —— 在这批表拿到看守之后与之前一样不受欢迎。注释改了,因为原文说这批「没人看着」,现在不成立。其他
@objectstack/specpatch。helper 里多了一次登记调用,是随包发布的运行时代码(对解析行为无影响),按 AGENTS.md「功能/改进加 changeset」与 ReportSchema 的filter别名指向filters—— 一个 ReportSchema 同样拒绝的键(#4001 战役自己的假处方,第 5 例) #5013 自身闸门 PR 的先例走 patch。check:strictness-ledger数字无变化,故未动gen:strictness-ledger产物(本 PR 没有新增z.object(站点,新文件也不是*.zod.ts)。未新增任何check:/gen:脚本,无需登记 check-generated 台账。shared/index.ts导出,与strict-object.ts/alias-probe.ts同待遇 —— 闸门按相对路径取用的内部接缝。strictUnknownKeyError是发布出去的 API(在api-surface.json的./shared下),消费者完全可以在循环里按租户建 error map;无上限的登记表会变成别人进程里的滞留物。溢出计数由闸门断言为 0,所以「装不下」会是一次响亮的失败,而不是悄悄判一个前缀。跟进
ui/app.zod.ts导航项:4 条expanded别名在另外 8 个变体上把作者指向该变体同样拒绝的键(二次拒绝) #5555 —— 上面那 32 条背后的真实缺陷(修法要改面向作者的文案,需单独决定)。strictUnknownKeyError直调点批量迁到strictObject,棘轮降到 0(路线 1 消不掉手抄数组与 shape 的漂移) #5593 —— 路线 2:44 个调用点分批迁strictObject,棘轮降到 0,本 PR 的登记表随最后一个调用点一起删除。🤖 Generated with Claude Code
https://claude.ai/code/session_018fxLGQdatPbBUvCgiVxg6D
Generated by Claude Code