test(spec): 别名一致性闸门收编 44 个 strictUnknownKeyError 直调点 —— probe 撞车维度首测 (#5483) - #5609
Merged
Merged
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
|
Contributor
📓 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:
|
Contributor
Author
|
PM 预记( Generated by Claude Code |
This was referenced Aug 5, 2026
os-zhuang
marked this pull request as ready for review
August 5, 2026 22:15
This was referenced Aug 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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