fix(form): declare the runtime field metadata slot, ban the spec FormField misimport (#3090 PR3a) - #3097
Merged
Conversation
…Field misimport (#3090) FormField.field — where object-bound paths stash the resolved field-metadata OBJECT for widgets — rode through the index signature, undeclared, readable only via `as any`, while the same key in the spec form-view vocabulary is a STRING. Declaring it (Record<string, any> + load-bearing JSDoc) makes assigning a string a compile error, retires the casts at every read site, and a tripwire test pins the invariant: normalizeSectionField never emits a string field — the authored form ends at that boundary. The one deliberate boundary read in ObjectForm (authored defs, where the string IS legitimate) is commented as such. no-restricted-imports bans FormField/FormFieldSchema imports from @objectstack/spec/ui: the spec type erases to `any` (objectstack#4171), so the misimport silently deletes type safety and tsc says nothing — the lint message is the correction, naming both layers and the chokepoint. The parity drift guard is the one legitimate importer, exempted inline; the rule firing on it was the mutation proof. Ledger: FormField + FormFieldSchema move DEBT → ALLOW with the two-layer rationale (122 → 120, 5 declared dialects). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
…e import of spec/ui now trips the #3090 misimport tripwire Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
Author
|
CI Lint 命中一处漏网: |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
…ters the #3090 tripwire flagged Two guard tests (the objectstack#4171 inverted pin and the re-export parity walk) must import the banned names to do their jobs; index.ts's Spec-prefixed public aliases and the UI namespace export ARE the disambiguation the tripwire exists to force. Block-form disables where the rule reports at the specifier line, out of -next-line reach. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
#3090 的 PR3a(零破坏)。分析阶段的两个"待拍板改名"经评估都以更便宜的机制达成同等防错效果,本 PR 落地。
1.
field元数据槽:声明,不改名槽是三层结构:authored(spec string)→ runtime
FormField.field(对象,此前未声明、靠 index signature 走私、只能as any读)→ widget propfield: FieldMetadata(公共契约)。改名会把槽和它喂的 widget prop 拆成两个名字或破坏第三方 widget 契约;声明则拿到全部牙齿:field?: Record<string, any>+ 承重 JSDoc(写明双关与不变量)。赋 string 即编译错;读取零摩擦(源头是 served object schema,键集比 designer 向的FieldMetadata联合更宽,故不套严格联合)as anycast 退役;ObjectForm 941 的边界读保留并注明「此处读 authored def,string 合法——cast 即边界,不是泄漏」typeof field !== 'string'钉死2. spec
FormField误导入:lint tripwire,不改名修正此前一个错误判断:「误导入会被 tsc 抓」——不会。spec 的
FormField类型在 dist 里是any(objectstack#4171),误导入是静默的类型安全删除,tsc 一声不吭(checker 头注 lie #2 的活例)。改名的真实成本在已发布 API 与文档/语料长尾;no-restricted-imports按importNames禁@objectstack/spec/ui的FormField/FormFieldSchema,报错文案即修正指令(点名两层与枢纽)。Mutation 证明是免费的:规则一落地就命中了全仓唯一的既有导入点——parity 闸门自己(漂移守卫是唯一合法消费者),已加带理由的行内豁免。
3. 台账 122 → 120
FormField/FormFieldSchema从 untriaged DEBT 转 ALLOW,双层论证写死在 ALLOW reason 里(不可派生 + #4171 类型擦除 + 枢纽与闸门指针)。表单簇 6 条至此全部处置:2 烧(SelectOption 对)、4 ALLOW(含本次 2 条)。验证
Closes 部分 #3090(PR3 第一个复选框)。PR3b(
SelectOption.value回程保型)随后。🤖 Generated with Claude Code