Skip to content

validate-rule-compilability.ts:239 也有同形的 obj.validations ?? obj.validationRules 别名读法(#5017 全包 grep 的第八处,第三个文件) #5096

Description

@xuyushun441-sys

#5017 的全包 grep 顺带发现的第八处,落在第三个文件,不在 #5017(validate-expressions.ts / validate-security-posture.ts)的处置范围内,按 Prime Directive #10 单独记账。

事实

packages/lint/src/validate-rule-compilability.ts:239:

// `validations` is the spec key; `validationRules` is read for the same
// …
const validations = obj.validations ?? obj.validationRules;

ObjectSchema.shape 只声明 validations,且是 strict —— 实测:

objects[].validationRules parses? false
  ["objects.0: Unrecognized key(s) on this object: `validationRules`. …
    Did you mean `validationRules` → `validations`?"]

validateRuleCompilability 也是 input: 'parsed' 注册的规则,所以在 compile 路径上 obj.validationRules 恒为 undefined。canonical 排首位,别名 limb 不可达 —— 和 #5009 那四条、#5017 前六条完全同形。

与 #5017 的关系

#5017 已在另外两个文件把同族的七条收敛完毕(PR #5046),并落了两层结构性 meta-guard(declared-key ⊆ schema.shape + reachability)。这一条没有一并改,是因为:

  1. 它在第三个文件,validate-expressions / validate-security-posture 也有同形的 spec 不声明键的 ?? 别名读法(#5009 建议 3 的核对结果) #5017 的议题正文和验收条件都没有点名它;
  2. fix(lint): 收敛 validate-expressions / validate-security-posture 的 spec 不声明键 ?? 别名读法 (#5017) #5046 的真实元数据零新红、反向验证、变异测试都是围绕那两个文件做的,顺手带上第三个规则等于把没做过同等验证的改动混进已经绿了的 PR;
  3. 它自己那份 meta-guard 需要单独写(该规则的 finding 形状与两者又不同)。

处置建议

照 #5046 的模式办:

  1. 收敛为 obj.validations;
  2. 补 declared-key guard(该规则从 obj / 规则对象上读的每个键 ⊆ 对应 .shape)+ reachability guard;
  3. 反向验证注意方向:canonical 排首位,所以改动前对非法拼法越权判红,改动后让位给 schema 的具名拒绝 —— 与 fix(lint): 删除 validateOrgAxisRedLines 里 spec 合法 stack 到不了的四条分支 (#5009) #5018 的方向一致;
  4. 现有 fixture validate-rule-compilability.test.ts:295 用的正是 validationRules: 拼法,改动时要一并改成 canonical(否则该用例会静默失去覆盖 —— fix(lint): 收敛 validate-expressions / validate-security-posture 的 spec 不声明键 ?? 别名读法 (#5017) #5046 在 runtime-gate.test.ts 上正好踩到这个:别名拼法让"上下文里有坏规则"的 fixture 实际上一条 finding 都产生不了,断言 toEqual([]) 通过的原因是没有东西可减而不是减法正确)。

理由两条轴,与 #5017 同:

  • 长期正确性:consumer 容忍 producer 明确拒绝的别名,是把一条具名拒绝降级成静默失效的分支;读代码的人(和照着写的 AI)会相信 objects[].validationRules 是真实的 authoring 面。
  • 让 AI 写的元数据难写错:别名容忍属于 producer 的拒绝面,不属于 consumer(Prime Directive Add comprehensive test suite for Zod schema validation #12)。

参考

Activity

  1. xuyushun441-sys commented on Aug 4, 2026

    @xuyushun441-sys
    CollaboratorAuthor

    认领(PM 分派)

    按本单自带的 playbook 执行(#5046 沉淀的),特别是:validate-rule-compilability.test.ts:295 的 validationRules: fixture 必须一并换 canonical —— runtime-gate 刚示范过"绿但空转"的陷阱。


    Generated by Claude Code

  2. xuyushun441-sys commented on Aug 4, 2026

    @xuyushun441-sys
    CollaboratorAuthor

    审核通过 — PR #5121 已取消草稿并挂上 auto-merge(SQUASH);同族第 8 例收官

    :295 fixture 的实测方向与议题预警相反,处置因此更对:不是 runtime-gate 那种 0→N(空转断言终于干活),而是 1→0 —— 该测试主动钉着被删的别名 limb,真的在触发。所以不能换拼写保绿(那会留下一个测试主题已不存在的绿测试),必须替换:新测试钉 schema 的具名拒绝文案 + canonical 1 条 vs 别名 0 条 + 重建 OLD_CHAIN 证明新旧读法只在 schema 已拒的输入类上有差。先测量再动手,这是三种 fixture 处置(re-spell / 补声明 / 替换)里第三种的首个实例,进方法论。

    guard 比 #5046 更严一档且理由讲清了:reachability 用全量 safeParse(#5018 原始 bar)—— 因为 zod 把 regex 当任意字符串、schema 当任意 record,不可编译的产物本身就是 spec 合法的,这条规则存在的理由恰是 zod 看不见这类缺陷,所以永远不需要 zod 拒收的 fixture。与 #5046 在 security-posture 上放宽到 unrecognized_keys 的理由互为镜像 —— 判据跟着规则的性质走,不是模板。另有两处细活:字符串字面量剥离(finding 里的 config path 模板会让朴素 dotted 扫描逼出装饰性豁免)、rule[branch] 计算键的专项断言(dotted 扫描的盲区,恰是本规则最要紧的读法)。

    全文件仅此一条链,无新同族;真实元数据 28 对象 / 17 规则 diff 逐字为空;M1/M2 变异 2/11 红;lint 1172 测试、cli 消费半径 37 测试全绿。落点 3 文件,未碰在飞 #5026 的文件。


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions