fix(lint): 收敛 validate-rule-compilability 的 spec 不声明键 ?? 别名读法 (#5096) - #5121
Merged
Merged
Conversation
#4984 → #5009 → #5017/PR #5046 同族第八处,落在第三个文件。 `validate-rule-compilability.ts:239` 读 `obj.validations ?? obj.validationRules`, 而 `ObjectSchema.shape` 只声明 `validations` 且 strict —— `validationRules` 被按名 拒绝("Did you mean `validationRules` → `validations`?",#4001)。该规则以 `input: 'parsed'` 注册,canonical 排首位,别名 limb 对任何能解析的 stack 不可达。 三个 example(crm / showcase / todo,28 个对象、17 条验证规则)上改动前后 findings 逐字相同,两侧均 0 条。代价从来不是漏报而是误导:consumer 里的别名 fallback 等于 向后来的读者和照着写的 AI 宣称 `objects[].validationRules` 是真实 authoring 面。 补两层结构性 meta-guard:declared-key(含 `rule[branch]` 计算属性读法的专项断言) + reachability(判据是 `safeParse` 全绿,比 #5046 严一档 —— 编不过的 regex/schema 在 spec 眼里依然完全合法)。原测试 `reads `validationRules` too` 断言的正是被删掉 的 limb(实测产出 1 条 finding,非空转),故替换而非改拼写。变异测试:别名 limb 加回 → 2 条红;改为纯别名读 → 11 条红。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018iARDqtrhQgz6fVHDeDkbQ
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 3 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
xuyushun441-sys
marked this pull request as ready for review
August 4, 2026 05:27
xuyushun441-sys
enabled auto-merge
August 4, 2026 05:27
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 #5096
#4984 → #5009 → #5017/PR #5046 同族第八处,落在第三个文件。改动限于
packages/lint,未触碰content/docs/releases/。一条读法,实测核实
validate-rule-compilability.ts:239:对着 live
.shape+safeParse实测(与 #5046 那条 414 行是同一份证据):validateRuleCompilability以input: 'parsed'注册(authoring-rules.ts:864),canonical 排首位 —— 别名 limb 对任何能解析的 stack 不可达。收敛为obj.validations。真实元数据:零行为变化
三个 example 的对象面(该规则只读
stack.objects,所以对象 barrel 就是它的完整输入面):合计 28 个对象、17 条验证规则,改动前后 findings 逐字相同。全包 grep
validationRules作对象键:真实元数据里零命中(仅剩validate-expressions.test.ts里 #5017 刻意 pin 住 schema 拒绝的那条 fixture,以及packages/spec/DEVELOPMENT_PLAN.md里FormViewSchema的同名键 —— 另一个 surface,与本单无关)。fixture 陷阱:这次是 1 → 0,不是 0 → N
议题提醒
validate-rule-compilability.test.ts:295的validationRules:拼法可能"绿但空转"(runtime-gate 的先例)。先测量再动手,结果是相反的方向:所以它不是空转 —— 那条
it('reads \validationRules` too …')断言的正是本 PR 要删掉的那条 limb,它真的在跑。因此它被**替换**而不是改拼写:把 key 换成validations只会留下一条主题(「本规则也读别名」)已不复存在的绿测试。替换成的三条断言分别 pin 住:schema 按名拒绝的原文、canonical 读法产出 1 条 / 别名拼法产出 0 条、以及重建的旧链(OLD_CHAIN`)与新读法只在 schema 已拒绝的那一种输入上不同。反向验证的方向(#5018 的教训)
canonical 排首位,所以删掉别名 limb 在任何有效 stack 上都不会丢 finding;它只在一条 schema 已经按名拒绝的 stack 上不再判红 —— 而那里 schema 的具名拒绝本来就是更好的诊断。两边都写进了断言,而不是断言一边、假设另一边。
两层结构性 meta-guard(#4992 模式,#5017 形状)
stack/obj/rule上读的每个键 ⊆ 对应 surface 自己的.shape,expected精确匹配(改名 loop 变量会静默解除扫描),外加 "covers every receiver" 元测试与一条反陈旧断言(被豁免却已不再读任何东西的名字必须删掉 —— 否则豁免表迟早变成装饰)。flattenRules经rule[branch]下降,点号扫描看不见then/otherwise,而那恰是本规则最有意思的读法。所以从源码里把字面量分支表读出来单独核对:漏掉它等于让这两个键坐在本文件所有 guard 之外。findings.push落点都被一条ObjectStackSchema完整 parse 通过的 fixture 触达,且是把 parsed 产物喂给规则(它在 compile 路径上拿到的就是这个)。判据这里用 #5018 的
safeParse全绿,比validate-security-posture只能要求"不报unrecognized_keys"严一档,理由是这条规则判什么:在 spec 眼里regex是任意字符串、schema是任意 record,所以编译不过的产物依然完全 spec 合法。这条 gate 存在的理由正是 zod 看不见该缺陷,因此它永远不需要一条 zod 会拒绝的 fixture。顺带把源码扫描的字面量文本剥掉了:本规则的 message / hint 里全是
objects.< name >.validations.< rule >.regex这类给作者看的配置路径和rule-validator.ts这类文件名,按字面扫会逼着把objects/validations/validator塞进"plumbing"豁免 —— 那正是让豁免表失去意义的那种填充。${…}插值是真读法,保留。变异测试
obj.validations ?? obj.validationRules)reads the canonical key only …、every key read off \obj` is declared by ObjectSchema`)obj.validationRules,#5026 那种形状)全文件同族普查
全文件只有这一条
??,别无同族链或纯别名读。其余 receiver(err/import/process)是 JS/Node 内建,已在NOT_SCHEMA_RECEIVERS里逐条写明理由。无新增 out-of-scope 发现,未新开 issue。消费半径
validation-rule-regex-uncompilable/validation-rule-json-schema-uncompilable/validateRuleCompilability在packages/lint/src/之外零引用。跨包 fixture(#5046 返工的教训)packages/cli/test/authoring-rule-command-parity.test.ts与packages/cli/src/utils/collect-docs.test.ts都已是 canonicalvalidations:拼法(前者正是 #5046 顺手改的),实跑通过。验证
已 merge
origin/main(3 个提交,均未触及packages/lint/packages/spec;pnpm-lock.yaml动过,已pnpm install --frozen-lockfile后重跑全绿)。packages/cli的 parity 测试 import@objectstack/lint,在 lint 尚未 build 的新 worktree 里报的是 import 失败,与本改动无关 ——pnpm --filter @objectstack/lint build后即绿。Generated by Claude Code