test(app-shell): 测量 invalid_value 的范畴定性 — 两种定性各有形状受损,不放宽,钉住两个方向 - #3706
Merged
Conversation
…decline the relaxation
objectui#3694 asked whether the nested-union category test counting only
`invalid_type` is the rule's meaning or an implementation detail that leaked
into it. Measured over 51 shapes: re-qualifying `invalid_value` is a TRADE on
one union, not an improvement, so no behaviour changed.
`columns[].summary` (`enum | {type, field}`) is the only union the question
reaches. Counting `invalid_value` as a node-level rejection gains 5 shapes
(an OBJECT summary drops to `…summary.type` plus the option list) and loses 8
(every non-enum SCALAR summary loses the enum's option list and collapses to
`Invalid input`) — the loss includes #3678's own CANARY. A type-aware variant
merely re-cuts the same trade, 6 gained for 6 lost.
Test file is add-only: 14 pins covering both directions of the trade, the
second `invalid_value` site (`sections[].columns`), and the measured fact that
the content rule's reach cannot move at all. Four of the damaged shapes
(`summary: 42 | true | null | ['count']`) were pinned nowhere before, so the
relaxation could have shipped with silent regressions.
Refs #3694
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
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 #3694
结论先说:测量后不放宽,行为零改动
#3694 问的是:范畴判定只认
invalid_type,这是规则的本意,还是实现细节漏进了语义?测量答案:两种定性各有形状受损,不存在「全面改善」的再定性。于是本 PR 不动任何判定逻辑,只把测量钉成回归防线 + 更新注释。判定门、38+ 既有钉子、两条规则的划分全部原样。
测量面:整个
view家族里,这个问题只够得着一个 union先把
ViewMetadataSchema/ViewItemSchema/ViewSchema的 Zod 树走了一遍,21 个无判别式嵌套 union。其中成员在自身相对根上答invalid_value的只有两处:columns[].summaryenum | {type, field}sections[].columnsenum | 1 | 2 | 3 | 4invalid_valuesections[].columns两种定性下都不说话(今天 k=5 落进内容判别的格子、被五成员限制挡下;放宽后 k=0 落进空格子)—— 换了格子,同样沉默,对结论零贡献。已钉。两种定性逐形状对照(51 个探针,只列有变化的)
A = 今天(
invalid_value视作「读过值的候选」);B = 放宽(invalid_value视作类型层拒绝)。summary: {type:'bogus'}…summary/Invalid input…summary.type/ 具名选项summary: {}…summary/Invalid input…summary.type/ 具名选项summary: {type:'bogus', field:'x'}…summary/Invalid input…summary.type/ 具名选项list.…summary: {type:'bogus'}listViews.v1.…summary: {type:'bogus'}summary: 'bogus'…summary/ 具名选项…summary/Invalid inputsummary: 42…summary/ 具名选项Invalid inputsummary: true…summary/ 具名选项Invalid inputsummary: null…summary/ 具名选项Invalid inputsummary: []…summary/ 具名选项Invalid inputsummary: ['count']…summary/ 具名选项Invalid inputsummary: [{type:'count'}]…summary/ 具名选项Invalid inputlistViews.…summary: 'bogus'…summary/ 具名选项Invalid input5 改善 / 8 退化。 带⚠️ 的那行是 PR #3693 自己的 CANARY(
CANARY: a scalar union member left standing names the options it wanted)—— 放宽会把一条已合并的钉子改红,方向是回归而不是验证。派发单第 2 条的逐处核对:新激活处没有误选
放宽让 k 从 2 降到 1 的 5 处,选中的都是
{type, field}成员 —— 作者写的就是对象,这正是作者意图的成员。误选零处。B 的伤害全部来自「去激活」(k 从 1 降到 0),不是来自选错。这一点值得单独记下:它说明放宽的方向不算错,错的是它同时砍掉了枚举成员本来提供的那条好消息。还测了第三种谓词(类型感知),同样不合格
invalid_value只有在没有任何允许字面量与该值typeof相同时才算类型层拒绝(枚举值都是字符串 → 喂对象/数字属于「压根没机会」;喂字符串属于「真读过」)。结果只是把同一笔交易重新切了一刀:6 改善 / 6 退化 —— 它救回了summary: 'bogus',还多赚一个sections[].columns: 'bogus',但42 / true / null / ['count']照样塌陷。内容判别的适用面:测出来动不了
#3694 正文担心「放宽会同时改变两条规则的适用范围」。实测:不会。内容判别要求恰好两个成员且值是非空数组,全家族同时满足这两条又落在
invalid_value站点的形状只有summary: ['count']一个;那里对象成员答的是invalid_type,groups.some(memberRejectedNodeType)今天就已经为真,放宽只会让它更真。整个问题活在唯一候选规则里。已钉。逆向验证(先写预测,后运行;三个扰动)
预测全文落盘于实现之前。注意方向不是常规的「还原实现→新钉子红」 —— 本 PR 不改行为,所以扰动的是被否决的那两个谓词,预测它们红出各自会损坏的形状。
先在加钉之前跑(56 条),验证既有套件能看见多少:
invalid_type || invalid_value)再在加钉之后跑(70 条):
三次预测逐条命中,连红的测试名都一致。
加钉的价值就在这个差值里:加钉前,C 的四个退化形状(
summary: 42 / true / null / ['count'])在整个仓库里一条钉子都没有 —— 类型感知谓词本可以带着四条静默回归合进来,套件不会吭一声。顺带测到的一件事:存在严格改善的谓词,但它不是「再定性
invalid_value」上表的 D 是「证据深度」谓词:先取在值内部报过位置(相对 path 非空)的成员,恰好一个就选它;一个都没有时,回落到今天的普查。
invalid_type,故 D 的候选集是 A 的子集,|tier1|=1 时 A 的 k≥1)。实测 51 形状:5 改善 / 0 退化。invalid_value算不算读过值」。它同时把唯一候选规则的理据从「只有一个成员读过值」悄悄换成「只有一个成员报进了值内部」,两者恰好在 enum-vs-object 上分叉。#3626 / #3677 两次把「不发明偏好」写进代码注释,这一步是否要迈,是维护者的设计裁决,不该由本单的有界授权顺手做掉。因此:测量、记录、不实施,留给 #3694 后续或 objectstack#6391 一并裁。上表 D 那一行也已经把代价说清楚了 —— 若采纳,要红的是 4 条「钉住现状」的钉子,按 fixture 三分诊做整体替换,零回归。
判定奇偶
本 PR 一行判定逻辑都没动,
clientValidation.ts的 diff 是纯注释。奇偶不是「测出来没变」,是 diff 层面不可能变。另加 8 条 parity pin(修前修后都绿 —— 这正是它们的意义)。测试
clientValidation.viewDiagnostics.test.ts只加不改(196 增 / 0 删,git diff --numstat为证),新增 14 条:6 条测量钉 + 8 条 parity。新鲜 worktree 里先
pnpm --filter '@object-ui/app-shell^...' build再 type-check —— 否则报的是缺@object-ui/react之类的假红。不做的事 / 残留
config.columns)的诊断仍塌成「Invalid input」——创建路/编辑路都中 #3626 方向 1)未做。config.columns)的诊断仍塌成「Invalid input」——创建路/编辑路都中 #3626 / metadata-admin:嵌套 union「只剩一个成员接受了值的类型」时仍塌成 Invalid input(config.sort 等) #3678 / metadata-admin:范畴判定只认 invalid_type,enum 成员对非枚举值答 invalid_value,把可判定的 union 留在塌陷态 #3694 三条局部规则一起退休。本 PR 的注释把这句话留在了谓词旁边。Generated by Claude Code