fix(plugin-detail): record:details 的 sections 说明改为 spec 的对象形,不再教已退役的 Section IDs (#3807) - #3820
Merged
Conversation
…Section IDs (#3807) `inputs` 是发布出去的编写契约(gen-manifest.ts → sdui.manifest.json 保存门 + sdui-intrinsics.d.ts),而 record:details.sections 的说明写的是 `Section IDs to show (required when layout is "custom")` —— 17.x 以前的形状。 pin 版 @objectstack/spec@17.0.0-rc.5 的 RecordDetailsProps.sections 是对象数组 `{ name?, label?, columns?, fields }`;objectstack#5611 把 z.array(z.string()) 那条拼法删掉而不是 union 进来(既无 producer 也无 consumer)。 照旧说明写 `sections: ['contact_info','address']` 的作者四层都拿不到诊断: manifest 门只看顶层键名 + 粗类型(字符串数组是合法 array),上游 validateComponentProps 是 advisory 级,spec 只在真走 parse 的路径上才拒,而 RecordDetailsRenderer 对每个条目读 s.name / s.label / s.fields —— 字符串上三者 全 undefined,该 section 一个字段都不渲染。layout: 'custom' 时 sections 是正文 唯一来源,结果就是一张没有报错的空白详情页。 新说明逐键派生自 spec 各成员的 .describe() 与渲染器实读:fields 必填按序; label 是标题(省略即无标题无边框);name 是 snake_case 稳定标识与 i18n 锚点 (sectionLabel → objects.{object}._sections.{name}.label,useObjectLabel.ts:419); columns(1-4)是本 section 的字段栅格宽度(DetailSection 的 applyDetailAutoLayout(visibleFields, section.columns)),省略则由渲染器推导; 并明确写出字符串条目不被接受。渲染器另外还认的 title / showBorder / hideEmpty 故意不写进说明:spec 的 section 对象没声明它们,parse 时静默剥掉,发布它们等于 教作者写契约丢弃的键(与本文件下方"顶层 readonly 不声明"同一条理由)。 recordDetailsInputs.spec-parity.test.ts 是 PR #3795(record:highlights)那条 sibling,两个方向都在运行时从 spec schema 派生:每个 spec 成员键都能从说明里 发现;本 block 不声明 spec 不接受的顶层 input。另外三条把这次的判断钉住 —— 退役拼法真的被 spec 按值拒(safeParse 红)、对象形保留、渲染器独有的三个 section 键确实会被 parse 剥掉且不得出现在说明里(词边界匹配,因为 untitled 内含 title)。 围栏内核对结论:同处 fields 的说明与 spec 的 "Explicit field list to display (optional, overrides highlightFields)" 语义一致, 元素是纯字符串、没有成员形状可发布,故不改;渲染器对 {name}/{field} 条目的容忍 不是第二套契约(spec 按值拒),测试里也钉了这一点。hideFields 未声明属 #3808。 仅说明文本变化,无运行时行为改动。 Co-authored-by: Claude <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
Collaborator
Author
|
✅ 验收通过(objectui 分片 PM,session_01GTRjn8xBqp75dk7kFupVRt)—— undraft + auto-merge。 核验:净 diff 3 文件;description 逐键派生自实装 spec(含 string 元素被拒的实跑证据),渲染器独有键(title/showBorder/hideEmpty)故意不发布并被测试钉住 —— 与 #3795 同一契约优先姿态,且 衍生:#3818( Generated by Claude Code |
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 #3807
record:details的sectionsinput description 教的是 spec 已经退役的「Section IDs」形状。inputs不是文档而是发布出去的编写契约(gen-manifest.ts→sdui.manifest.json保存门 + parser 白名单 +sdui-intrinsics.d.ts),而 pin 版@objectstack/spec@17.0.0-rc.5的RecordDetailsProps.sections是对象数组 —— objectstack#5611 把z.array(z.string())那条拼法删掉而不是 union 进来(既无 producer 也无 consumer,一种形状而不是两套事实契约)。照旧说明写sections: ['contact_info','address']的作者,四层都拿不到诊断,最后得到一张没有报错的空白详情页(layout: 'custom'时 sections 是正文的唯一来源)。做法沿用 #3407 / PR #3795 在
record:highlights.fields上确立的范式:description 从 spec 形状派生着写,并配一条两方向都在运行时从 spec schema 取期望值的 parity 测试。三方对照:spec 成员键 ↔ 新 description ↔ 渲染器实读
spec 侧全部实读自装好的
node_modules/@objectstack/spec@17.0.0-rc.5(不是 objectstack 仓库的 HEAD),渲染器侧实读自origin/main5147d93 的packages/plugin-detail/src/renderers/record-details.tsx。sections[]成员name?string,snake_case,「resolves objects.{object}._sections.{name}.label」objects.{object}._sections.{name}.label,没写 name 的 section 在所有 locale 下都显示 authored label」sectionLabel(objectName, s.name, rawTitle ?? s.name);键约定在packages/i18n/src/useObjectLabel.ts:419label?I18nLabel,「omit for an untitled, borderless section」s.title ?? s.label→pickLocalized→showBorder: s.showBorder ?? (translatedTitle ? true : false)columns?int 1-4,「Omitted → the renderer derives the width」...s透传进 synthesized section →DetailSection.tsx:190applyDetailAutoLayout(visibleFields, section.columns)fieldsstring[],必填,「in order」dropHidden(normaliseList(filterList(s.fields)))s.name/s.label/s.fields全undefined→ 该 section 零字段顶层 parity:spec 顶层键 =
columns/layout/sections/fields/hideFields/aria;本 block 声明 4 个,全部在 spec 内,所以反方向(声明 spec 不接受的顶层键)本来就绿,PR #3806 的全仓门实跑仍绿。hideFields未声明属 #3808 的范围,本单不夹带;aria的省略是既有决定(无障碍逃生口,不是布局选择),同文件下方已有说明。故意不写进 description 的三个键:渲染器另外还认
s.title/s.showBorder/s.hideEmpty,但 spec 的 section 对象没有声明它们 ——safeParse({ sections: [{ label:'Contact', fields:['phone'], title:'T', showBorder:true, hideEmpty:false }] })成功但条目只剩{ label, fields }(实跑,测试里钉住了)。发布它们等于教作者写契约会丢弃的键,与同文件下方「顶层readonly不声明」是同一条理由;渲染器容忍不等于可以教。围栏内核对:同处的
fields(:250)没有同漂,故不改fields的 describe 是Explicit field list to display (optional, overrides highlightFields),input 写的是Explicit field list (overrides highlightFields)—— 同一件事,没有退役形状、也没有漏掉的成员键。z.array(z.string()),元素是纯字符串(测试里用arrayElement(...)的shapeKeys为空钉住)。normaliseField容忍{name}/{field}条目,但 spec 按值拒(safeParse({ fields: [{ name:'phone' }] }).success === false,实跑)。按契约优先,这种容忍不写进说明,否则就是发布第二套事实契约;测试里把「fields说明不出现成员形状」也钉住了。测试
新增
packages/plugin-detail/src/__tests__/recordDetailsInputs.spec-parity.test.ts(PR #3795 那条的 sibling,7 条):前提守卫(spec 真的只收对象形、退役拼法真的被按值拒)、每个 spec 成员键都能从说明里发现、说明不再教 section-id 拼法、渲染器独有的三个键被 parse 剥掉且不得出现在说明里、不声明 spec 不接受的顶层 input、fields不发布成员形状。期望值全部运行时从 spec schema 派生。一处值得写下来的细节:「不得出现」这个方向用的是词边界而不是子串 —— 第一次实跑就红在
title,因为说明里的untitled内含title。判 key 是否被「教」要用\b;正方向(每个 spec 键都能被发现)保留子串匹配(与 PR #3795 一致,那边的假阳性只会放过一个确实提到了该键的说明)。反向验证(方向先判后跑)
先判:把 description 退回
'Section IDs to show (required when layout is "custom")',应当恰好两条红 —— 派生的「成员键可发现」(四个键全部 undocumented)和显式的「不再教 section-id 拼法」;其余五条绿,因为它们的判据(spec 前提、parse 剥键行为、顶层 parity、fields)与这段文本无关。实跑一致:
恢复后
7 passed (7)。其他实跑
pnpm vitest run packages/plugin-detail --maxWorkers=2→Test Files 57 passed (57)/Tests 475 passed (475)(输出里的ECONNREFUSED 127.0.0.1:3000是既有 fixture 噪声,非本改动)pnpm --filter @object-ui/plugin-detail type-check→tsc --noEmit && tsc -p tsconfig.typetests.json无输出即通过pnpm vitest run apps/console/src/__tests__/registry-inputs-spec-parity.test.ts→21 passed(PR test(console): registry inputs 与 spec ComponentPropsMap 的 parity 门推到全仓,4 个 OFF-SPEC block 逐块判定 (#3797) #3806 的全仓 inputs × spec 门,消费半径内)manifestFromConfigs+generateDts,即scripts/gen-manifest.ts/dev/manifest-dump.tsx用的同一对,不落盘):record:details在 public tier,新说明整段出现在components['record:details'].inputs[sections].description。附一句诚实的边界:generateDts只发sections?: unknown[]、不带 JSDoc,所以这段说明的落点是 manifest(以及读 manifest 的作者/AI),不是 intrinsics 的类型注释。node scripts/check-control-bytes.mjs→OK (scanned 3737 tracked text file(s));另对三个改动文件grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f]'零命中pnpm --filter @object-ui/plugin-detail lint→0 errors(707 条既有 warning,新测试文件零 warning,index.tsx的 4 条 warning 都在 26/42/46/52 行,与本改动无关)Changeset:
.changeset/record-details-sections-description-3807.md(@object-ui/plugin-detailpatch,与 PR #3795 同档位;authoring 面 description 修正,无运行时行为改动)。顺带发现(未夹带,已另开 unassigned issue)
record:details的layout发布了auto|custom语义,渲染器唯一的读点只认 spec 已退役的inline|compact—— auto/custom 从未被实装 #3818 ——record:details.layout发布了auto|custom语义,但渲染器唯一的schema.layout读点只认 spec 已退役的inline|compact(record-details.tsx:104),两个值都落到'vertical',正文选谁只由 sections 在不在决定。同族失效但换键,且修法有三条互斥路线(实装语义 / 承认 inert 走 enforce-or-remove / 上游先定),需要决定,所以不夹带。record:details.sections块设计器没有name输入位 —— Studio 搭出来的 section 结构上无法翻译,且必然挂着上游translation-section-name-missing#3819 —— metadata-admin 的record:details.sections块设计器itemFields只有label/columns/fields,没有name,于是 Studio 里搭出来的 section 结构上无法翻译,且必然挂着上游translation-section-name-missing。Generated by Claude Code