test(cli): 钉住三个命令都跑 reference-integrity suite(#4384) - #4402
Merged
Conversation
…ite (#4384) #4394 removed the instance — `validateReadonlyFlowWrites` was hand-wired into `os validate` and `os compile` and never into `os lint`, so an `error`-level gate left `os lint` returning clean for stacks `os compile` refuses. It did not remove the failure MODE. A rule wired into two commands out of three produces no failing assertion anywhere: every command's own tests pass, the rule's unit tests pass, and the only symptom is the three commands disagreeing about the same stack. That is how the last one survived from #3425 until #4394, with the suite's own header naming it "the standing proof" of the drift the suite exists to end — a comment doing a test's job. The invariant worth pinning is `os lint` ⊇ `os compile`'s gate set: lint is the cheap pre-flight, compile is the gate, and a green lint followed by a red compile makes the pre-flight worthless — worse than worthless for an agent, whose remaining options are re-verifying everything or learning to distrust the signal. The guard asserts each command calls `validateReferenceIntegrity` and that none imports a suite member directly — the import is what a second call site starts with, so catching it closes the window between adding the import and adding the call. It scans source rather than spying, for the same reason lazy-deps.test.ts scans src: vitest inlines imports through its transform, so a module-cache probe cannot prove which symbols a command file actually reaches for. A third assertion keeps the other two from passing vacuously if the suite were emptied or its export renamed. Verified to FAIL on a reintroduced direct import in compile.ts, not merely to pass today. Test-only; no runtime or behaviour change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckNo hand-written docs reference the 0 changed package(s). ✅ |
This was referenced Jul 31, 2026
Open
os-zhuang
added a commit
that referenced
this pull request
Jul 31, 2026
…4340 后续) (#4417) * fix(lint,cli): os lint / os compile 不再放行一个 os validate 会拒绝的 react 页面 (#4340 后续) `validateReactPageProps` 只手工接在 `os validate` 上,`os lint` 和 `os compile` 从来没跑过它。在 showcase 的 react 页面植入一处 gating 违规 (`<ListView filters={['no_such_col','=',stage]}>` —— 谓词命中不了任何行, SqlDriver 吞掉 "no such column" 后返回 [],列表回空且与「本来就没数据」无法区分) 实测: os lint os compile os validate 修复前 exit 0 放行 exit 0 放行 exit 1 拒绝 修复后 exit 1 拒绝 exit 1 拒绝 exit 1 拒绝 #4340 之后这条规则已经是整个 react 页面表面唯一的字段解析闸门:<ListView> 的 columns/fields/sort/grouping/userFilters、<ObjectForm> 的 fields/initialValues/sections/subforms、record:* 一族(与元数据表面共用同一张 COMPONENT_FIELD_SPECS)、<ObjectChart> 的 aggregate/axes,以及 searchableFields。 所以漏接不是少几条警告 —— 而是这些绑定在 build 路径上完全没人看,包括其中会 gate 的那些。 现接入 REFERENCE_INTEGRITY_RULES,`os validate` 那处手工接线随之删除,三个命令的 答案由构造保证一致。这正是 suite 设立要终结的漂移(#3583 §5 D5),也是 validateReadonlyFlowWrites 在 #4394 里刚走过的同一条路:那次是「一张 map、 两个检查、两套命令集合」,这次是「一次 JSX parse、七个 rule id、一套命令集合」。 按 charter,react-prop-missing-required / react-prop-typo 是 shape 而非解析问题, 本不属于 suite。它们随行的理由与 validateActionBodyWrites 完全相同(其注释已写明): 落在同一次 parse 的同一份 source 上,拆成第二个 member 就要把每个 react 页面 parse 两遍,而改回手工接线正是 suite 要终结的那种漂移。同时更正了那条注释里 "The ONE member here that emits two rule ids" 的说法 —— 现在不止一个。 规则行为零变化:id、严重级、文案都不动;输入也不变(`os validate` 原本就传 result.data,suite 拿到的是同一个)。#4402 的接线守卫会在下次有人想再手工接一条 规则时直接报错——本次删除 validate.ts 的直接 import 也正是被它逼出来的。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012rK2McPogrTJBKdUsThrGs * docs: validating-metadata 反映 react 页面字段绑定现在三个命令都跑 本 PR 把 react 页面的字段绑定检查从「只在 os validate」变成「suite 成员,三个命令 都跑」,这份文档有三处随之失真 —— 而 docs-drift 的包级扇出恰好没点到它(它按 @objectstack/cli / @objectstack/lint 列了 20 份,漏了语义上唯一真正耦合的这份)。 - "one gate, two entry points" 表补一行 React page block field bindings(两列都 ✓)。 - 表下那句把 "JSX/React page sources" 整体算作 os validate 独有 —— 现在只有 「源码能否 parse」这个 SHAPE 闸门是独有的,里面的字段绑定属于 reference-integrity, suite 跑到哪它就跑到哪(含 os lint)。改写为分开陈述,并记下这里曾经的漂移与 #4384 的接线守卫。 - 示例 os validate 输出里的 `→ Checking React-source page props (ADR-0081)...` 随手工接线一并删除,已按真实 CLI 输出核对:示例里的每一行 step 现在都能在 showcase 上逐字复现(comm 比对为空)。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012rK2McPogrTJBKdUsThrGs --------- Co-authored-by: Claude <noreply@anthropic.com>
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.
Closes #4384
这个 PR 补的是什么
#4394 已经修掉了那一例 ——
validateReadonlyFlowWrites手工接进os validate和os compile,唯独漏了os lint,而它是 error 级,于是os lint长期放行os compile会拒绝的 stack。但它没有修掉失败模式本身:今天仍然没有任何东西能阻止下一条规则被接进三个命令里的两个。
而这类缺陷的特点是不会有任何测试变红 —— 每个命令自己的测试都过,规则的单测也过,唯一症状就是三个命令对同一个 stack 给出不同答案。上一次就是这么从 #3425 一直活到 #4394 的,期间 suite 头注释里把它称作 "the standing proof of the drift the suite exists to end" —— 一条注释在干测试的活。
钉住的不变量
os lint⊇os compile的门禁集。lint 是廉价预检,compile 是门禁。lint 绿、compile 红,预检就没有存在意义;对 agent 更糟 —— 剩下的选择只有"全量重验"(慢)或"学会不信任这个信号"(危险)。
三条断言
validateReferenceIntegrity;validateReadonlyFlowWrites—— 防止前两条在 suite 被清空或导出改名后空转通过。为什么扫源码而不是打桩
vitest 会把 import 内联进 transform,所以对
@objectstack/lint打 spy 证明不了命令文件到底 reach 了哪些符号 —— 和lazy-deps.test.ts扫src/是同一个理由。suite 内容的行为覆盖在
@objectstack/lint的reference-integrity-suite.test.ts;本文件只守 suite 与三个调用点之间那道缝。反向验证
不是"今天能过"就算数。在
compile.ts里加回一行直接 import,它确实失败:范围
纯测试,无运行时/行为变更。
@objectstack/cli65 文件 / 636 测试全绿,typecheck干净。空 changeset。顺带说明为什么只提这一条:我原本按 #4384 的分析做了一版"家族 + 组合层"(把 suite 的成员判据和"哪些命令跑"拆开),做到一半发现 #4394 已经先合入了。实测确认症状已消失(同一 fixture 下
os lint现在 exit 1),所以那版重构的核心价值归零,我 abort 了。剩下一个可以讨论但不在本 PR 范围的点:
validateReadonlyFlowWrites问的是"名字解析得到、但写会不会生效",而 suite 的判据写的是"名字能否解析"。#4394 的理由是"它走的是同一张 map"——这是邻近性论证。要不要为此调整 suite 的判据表述,是维护者的取舍,我没有在这里动它。🤖 Generated with Claude Code