Skip to content

fix(showcase): showcase_contact 声明 fieldGroups,让视图注释承诺的自动分组成真 (#5443) - #5463

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-5443-contact-fieldgroups
Aug 5, 2026
Merged

fix(showcase): showcase_contact 声明 fieldGroups,让视图注释承诺的自动分组成真 (#5443)#5463
baozhoutao merged 1 commit into
mainfrom
claude/issue-5443-contact-fieldgroups

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

Fixes #5443

问题

examples/app-showcase/src/data/objects/contact.object.ts 的九个字段都写了 group(contact/work/status/notes),对象却没有声明 fieldGroups。按 ADR-0085 §5,deriveFieldGroupLayout(渲染器与 i18n walker 共用的唯一派生实现)只把 group 命中已声明 fieldGroups[].key 的字段归入分组;一个都没声明时它直接 return null,分组根本不适用。所以这九个 group 与完全不写 group 渲染结果相同 —— os lint 为此报了九条 field-group-undeclared

src/ui/views/contact.view.ts 的头注释(content/docs/ui/create-vs-edit-form.mdx 引用的那份参考实现)写的恰恰相反:手写的 form「镜像平台自动派生的结果」,「省掉它就能免费得到等价的分组表单」。那张分组表单当时并不存在:照抄示例、真把 form 省掉的读者拿到的是一张平铺表单。这是 Prime Directive #10 推论(不要宣传运行时并不提供的能力),只不过做广告的是示例自己的注释。#5420 落地后 nav_contacts 真的会渲染这一族视图,潜伏的谎言变成现役。

改动

按 12:01Z 分诊裁定走方向 1 + 注释校准,三个文件:

  1. contact.object.ts 补四组 fieldGroups 声明,label 与视图四个段落一致;字段表头注释点明「group 还必须在 fieldGroups 里声明,那份声明才是派生的授权来源」。
  2. contact.view.ts 只改头注释:保留原有叙事,把错误的承诺改真 —— 派生以 fieldGroups 声明为授权来源,未声明的 group 等同于没写。并如实写出省掉 form 后与手写版的两处差异(实测所得,不是推定):
    • 派生结果会在末尾多一个无标题段落,装平台注入的 owner_id(审计列与 organization_idFIELD_GROUP_SYSTEM_FIELDS / hidden 排除,所有权列两者都不属于);
    • columns: 2 这类段落排版是表单视图的旋钮,分组声明不携带。
  3. test/seed.test.ts 新增用例,钉住的是承诺本身而不是声明:派生段落必须与视图手写的 form.sections顺序与成员上相等。

三态实测(实测不推定)

指标 ① 改前 ② 只补 fieldGroups ③ 全量
field-group-undeclared 9 0 0
os lint 总计 484 warnings / 22 suggestions 475 / 22 475 / 22
新增其它规则 无(逐规则计数只少了这 9 条)
派生 _sections 键总数 14 14 14
showcase_contact._sections contact/work/status/notes 同上,增删均为空集 同上
pnpm check:i18n-coverage OK,660 baselined,none new

_sections 键集合不变的机制已核实:声明派生(walker 路径 a)与视图手写段落(路径 b)产出同名四键,addSection 首次写入即去重 —— 与 #5438 已译的四键完全同名,所以既没有第 5 个新键,也没有计数变动。棘轮基线 scripts/i18n-coverage-baseline.jsonsupportedLocales 未动;packages/** 未动。

「省掉 form」这半句的实测依据

直接跑 deriveFieldGroupLayout(不起浏览器),对同一对象取两态:

  • 仅 config 解析后的对象 → 恰好四段:contact[name,email,phone] / work[company,title,account] / status[stage,lead_score] / notes[notes],与视图手写段落逐段同序同成员。
  • applySystemFields(注册时形态)→ 同样四段,外加一个无 key 的末尾段 [owner_id]

所以「省掉 form 得到等价分组表单」现在成立,注释按上面这两处差异如实收口。

反向验证(方向先判后跑)

预判:删掉 fieldGroupsderiveFieldGroupLayout 返回 null,新用例应在第一条断言就红,而不是因为「什么都没产出」而空跑变绿。实跑一致:

× derives the contact form sections from `fieldGroups` exactly as the view authors them
AssertionError: showcase_contact must declare fieldGroups (#5443): expected null not to be null
 Test Files  1 failed | 11 passed (12)
      Tests  1 failed | 126 passed (127)

恢复后 127/127 全绿。

测试

  • pnpm --filter @objectstack/example-showcase testTest Files 12 passed (12) / Tests 127 passed (127)
  • pnpm --filter @objectstack/example-showcase typechecktsc --noEmit 无输出
  • pnpm check:i18n-coverage(先 turbo run build,72/72 successful)→ OK (12 config(s), 660 baselined untranslated string(s), none new).
  • os validate / os lint 见上表
  • 消费半径外扩:pnpm --filter @objectstack/dogfood test503 passed | 6 skipped,另有 1 个 suite 失败且与本改动无关 —— showcase-declarative-endpoints/openapi.json 返 503,原因是 packages/spec/json-schema/(.gitignore 第 61 行)在新工作树里没有 openapi.json,而 gen:openapi 是 AGENTS.md 明确记载的两个无门禁生成器之一;共享检出里同样缺这个文件。跑一次 pnpm --filter @objectstack/spec gen:openapi 后该文件 14 passed (14) 全绿。

顺带发现(未在本 PR 修)

已另立 #5458(未认领):content/docs/ui/create-vs-edit-form.mdx §2 与 content/docs/ui/field-grouping-and-order.mdx 的语义分组小节及其代码样例,同样把「表单分组派生自 field.group」讲成 field.group 自己就够,两篇全文均不出现 fieldGroups —— 与本单同一个谎言的文档层,按分诊给定的文件面不在本 PR 范围内。


🤖 Generated with Claude Code

https://claude.ai/code/session_016FNvXhtSdnEGEfLEsMmvxh


Generated by Claude Code

…erivation promise is true (#5443)

Nine `showcase_contact` fields carry `group: 'contact' | 'work' | 'status' |
'notes'` while the object declared no `fieldGroups`. Per ADR-0085 §5,
`deriveFieldGroupLayout` buckets a field only when its `group` matches a
declared `fieldGroups[].key` — with none declared it returns `null` outright, so
those nine `group` values rendered exactly like no `group` at all. `os lint`
said so, nine times, as `field-group-undeclared`.

Meanwhile the header comment of `src/ui/views/contact.view.ts` — the reference
implementation `content/docs/ui/create-vs-edit-form.mdx` cites — promised that
the hand-written `form` "mirrors what the platform auto-derives from
`field.group`" and that you may "OMIT it and get an equivalent grouped form for
free". That grouped form did not exist: a reader copying the example and
dropping `form` got a flat one. Prime Directive #10's corollary, with the
example's own comment doing the advertising.

- `contact.object.ts` declares the four groups (labels matching the view's four
  sections).
- The view comment is calibrated rather than rewritten: it now names
  `fieldGroups` as the authority for the derivation, and states the two honest
  differences the derived form has — the platform-injected `owner_id` lands in
  a trailing untitled section (audit/system columns are excluded, ownership is
  not), and `columns: 2` is form-view presentation the group declaration does
  not carry. Both verified against `deriveFieldGroupLayout` over the object
  before and after `applySystemFields`.
- `test/seed.test.ts` pins the promise itself: the derived sections must equal
  the authored `form.sections` in order and membership. Removing `fieldGroups`
  turns it red on `derived !== null` rather than passing vacuously.

Three-state measurement, not presumption — before / `fieldGroups` only / full:
`field-group-undeclared` 9 → 0 → 0 (total warnings 484 → 475 → 475, no new
rule); the derived `_sections` key set is unchanged at 14 (`showcase_contact`
stays contact/work/status/notes — the walker dedupes the declaration-derived
keys against the view-authored ones #5438 already translated); repo-level
`check:i18n-coverage` reports 660 baselined, "none new", in all three states.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016FNvXhtSdnEGEfLEsMmvxh
@vercel

vercel Bot commented Aug 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 5, 2026 1:03pm

Request Review

@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tests tooling labels Aug 5, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review August 5, 2026 13:04
@baozhoutao
baozhoutao enabled auto-merge August 5, 2026 13:05
@baozhoutao
baozhoutao added this pull request to the merge queue Aug 5, 2026
Merged via the queue into main with commit ef19b94 Aug 5, 2026
23 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-5443-contact-fieldgroups branch August 5, 2026 13:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

2 participants