Uh oh!
There was an error while loading. Please reload this page.
fix(types): 把 objectstack#4171 三处反向 pin 对准真正的触发条件 (#3177) - #3194
Merged
Conversation
… trigger (#3177) Spec 17.0.0-rc.1 typed NavigationItem, FormField and ConditionalValidation.then/.otherwise, so the IsAny / IsUnknown pins fired. Firing was supposed to mean the burn-down was due. Per-symbol triage found it was not: `any` was never the only blocker for any of the three, so "no longer any" was never the right admission question. No symbol is bound. Each probe now asks the condition that actually governs it, asserts today's state (green now), and stops compiling the day that blocker lifts: - NavigationItem: flat shape vs the spec's nine-variant union, plus three semantics absent at BOTH spec tiers (visible: boolean, pinned, defaultOpen) and a labelled separator. Four probes, one per blocker. - FormField: two layers, not two dialects — disjoint required keys (local `name` vs spec `field`), and `field` itself is a string on one side and the resolved metadata object on the other. - ConditionalValidation: the branches became BaseValidationRuleShape, `{ type: string; …; [key: string]: unknown }` — no literal discriminant and an index signature that absorbs anything. The spec says so itself and names objectstack#4075 as the remaining work; the probe now pins that condition. What did become derivable is derived: NavigationItemType comes off the spec's nav-item discriminant instead of a hand-written nine-member copy, and recordMode / filters / badge / target / params / actionDef each come off the spec branch that owns them, extending the badgeVariant precedent. No member changes today. Also corrects the stale premise in check-spec-symbol-derivation.mjs, which still named these three as "the spec export resolves to any" — the guard's own warning about a wrong canonical-claim being a planted premise for the next session. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012C2cd7tL8QDoZ2QKN3djJ5
The latest updates on your projects. Learn more about Vercel for GitHub. |
os-zhuang
marked this pull request as ready for review
August 2, 2026 10:26
Uh oh!
There was an error while loading. Please reload this page.
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 freeto 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#3177
前提被修正了:pin 触发 ≠ burn-down 到期
spec 17.0.0-rc.1 给
NavigationItem/FormField/ConditionalValidation.then·.otherwise都定了型,三处IsAny/IsUnknown反向 pin 按设计触发。按 issue 计划第 1 步逐符号 triage 之后,结论是:触发它们的谓词问错了问题。any从来不是这三个符号里唯一的阻碍,所以「不再是 any」从来就不是正确的准入条件。三个符号今天都不该绑定,一个都没绑。改的是探针:每条现在问那个真正说了算的条件,并且断言当下的事实 —— 今天绿,而各自的阻碍被解除的那天就编译失败,那时才是 burn-down 真正到期。维护者决定见 #3177 的决策评论(Q1 B+C / Q2 B / Q3 B / Q4 B)。
逐符号
NavigationItem—— 阻碍有三个,没有一个是any造成的spec 把导航建模成九个
$strict变体的判别联合 +superRefine互斥规则;objectui 是一个扁平全可选形状。除此之外,下面这些 spec 在两个 tier 上都没有:visible: booleanNavigationRenderer的evalVis;menuItemToNavigationItem把 legacyMenuItem.hidden取反生产出布尔值pinneduseNavPins+FavoritesProviderdefaultOpennavigation-spec-parity.test.ts有用例labelmenuItemToNavigationItem会发一个四条探针,一个阻碍一条。另有一条伞形判定
[NavigationItem] extends [SpecNavigationItem]记录总体结论。注意不能用结构化
extends当探针:它对多余属性是放行的,所以看不见「spec 根本没声明pinned」。这里用的是逐键、逐 tier 的KeysOfUnion探测。FormField—— 两个层,不是一个概念的两种方言决定性的、机械化的形式是:两边的必填键不相交。objectui 必填⚠️ 标了这个双关。
name(表单数据路径),spec 必填field(对象字段引用),而且 spec 两个 tier 都没有name。同名的field一边是字符串、一边是解析后的元数据对象 ——form.ts早就用仓库自己已经有判词,
select-option-spec-parity.test.ts开头:而且
index.ts是单独导出SpecFormField的,那正是 #3090 tripwire 要强制的消歧;绑定会让FormField === SpecFormField,消歧一起塌掉。顺带还会把 framework#4074 的dependsOn放宽原地退回去。ConditionalValidation—— 从unknown变成了「弱一档」分支现在是
BaseValidationRuleShape:比
unknown强,但仍然不能派生:type不是字面量联合,分支无法按判别式收窄;then.condition读回来是unknown;索引签名放行任何成员 —— 包括拼错的type: 'formatt'。spec 自己在ValidationRuleSchema上就写了:所以整体派生等于用一个带索引签名的 bag 换掉 9 成员判别联合 —— 正是当初立 pin 要防的那类倒退,只是弱了一档。探针改为钉「字面量判别式 / 无索引签名」,objectstack#4075 落地那天自动到期。
为什么这一处的代价比看上去大:渲染器读裸对象、从不 parse,所以 spec 真正拒绝畸形规则的那道 parse 期联合根本不在客户端路径上。作者端(含 AI 生成)的判别式检查是这些规则运行前唯一的关。
真正能派生的,已经派生了
按决策 Q1 的 C 子集,扩展现有的
badgeVariant先例:NavigationItemType← spec 导航联合的判别式。原来是手写的九成员副本,正是 objectstack#4115 那一类(ChartType19 个里只有 7 个、ActionType漏了form)。派生还让未来 spec 新增变体在穷举消费者处编译失败(plugin-designer的NAV_TYPE_META是Record< NavigationItemType, … >),而不是掉进死的default:。recordMode/filters/badge/target/params/actionDef← 各自所属的 spec 分支。actionDef是结构化载荷,恰恰是最容易悄悄走样的那种 —— 它当初被objectui validate整个吃掉就是这么来的。成员今天一个没变,所以没有消费者受影响。
visible/pinned/defaultOpen保持本地,声明处都写清了「为什么不派生」以及对应探针在哪。顺带
scripts/check-spec-symbol-derivation.mjs的注释还写着这三个符号「the SPEC export resolves toany」—— 这已经是错的(JoinNode随 framework#4286 退役,另两个 rc.1 已定型)。这个 guard 自己就警告过「a wrong canonical-claim is not stale documentation — it is a planted premise for the next session」,所以一并修正,并新增 case 2c:spec 侧已定型但不够精确,any和unknown两个探针都报干净。验证
pnpm type-check(全仓 turbo,即spec-symbol-parity.test.ts的「编译期」断言从未被编译 —— 整个 tripwire 是哑的 #3181 的 typetests lane ——packages/types/tsconfig.test.json由该包type-check串联):78 successful, 78 totalvitest run packages/types packages/layout:26 files / 399 tests passedvitest run packages/plugin-designer packages/plugin-form:33 files / 332 tests passedvitest run packages/core/src/validation:4 files / 62 tests passedpnpm --filter @object-ui/types lint:0 errorsnode scripts/check-spec-symbol-derivation.mjs:✅;node scripts/check-changeset-fixed.mjs:✅Revert-proof(改动探针的期望值必须让 typetests lane 红):
changeset:patch(无用户可见形状变化)。
🤖 Generated with Claude Code
Generated by Claude Code