Skip to content

fix(showcase): 注册 ContactViews —— 文档引用的「create form ≠ edit form」参考实现终于真的进栈 (#5420) - #5438

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-5420-showcase-register-contact-views
Aug 5, 2026
Merged

fix(showcase): 注册 ContactViews —— 文档引用的「create form ≠ edit form」参考实现终于真的进栈 (#5420)#5438
baozhoutao merged 1 commit into
mainfrom
claude/issue-5420-showcase-register-contact-views

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

Fixes #5420

前提复核(先证伪,再实现)

origin/main 123067ce7(即 #5416 / #5422 合并之后)上实证,issue 的前提仍然成立 —— #5416#5422 都没有做注册:

git show origin/main:examples/app-showcase/objectstack.config.ts | grep -n Views
23:  import { TaskViews, ProjectViews, InquiryViews, BusinessUnitViews } from './src/ui/views/index.js';
196: views: [TaskViews, ProjectViews, InquiryViews, BusinessUnitViews],

barrel src/ui/views/index.ts 导出 5 个容器,config 的具名 import 只取了 4 个。views: 背后没有目录扫描,CLI 读的就是这个数组,所以这份元数据编译通过、类型通过、lint 干净,却既进不了运行栈,也进不了任何静态门:nav_contacts 渲染的是派生默认表单而不是作者写的那份,addRecord.formView: 'create' 从未绑定,而 content/docs/ui/create-vs-edit-form.mdx 一直把这个文件当作活的参考实现引用。这也解释了 #5405i18n/missing-section 为什么在 showcase 上采到 10 条却没有一条属于 showcase_contact

改了什么

  1. examples/app-showcase/objectstack.config.ts —— 第 23 行 import + 第 196 行 views: 各补一个 ContactViews
  2. examples/app-showcase/src/system/translations/index.ts —— 为注册后新可见的 5 个 zh-CN 覆盖键补译文。
  3. examples/app-showcase/test/seed.test.ts —— 两条 pin(见下)。
  4. 空 frontmatter changeset —— 示例应用为 private 包,不发布任何包(仓规里「本 PR 不发布任何东西」的正规声明方式)。

⛔ 未动 packages/**,未动棘轮基线 scripts/i18n-coverage-baseline.json,未缩 supportedLocales

新增键是实测的,不是预测的

node packages/cli/bin/run.js lint examples/app-showcase/objectstack.config.ts

  483 warning(s)   ← 注册前(= origin/main)
  488 warning(s)   ← 只注册、未补译文
  484 warning(s)   ← 本 PR 最终态

注册引入的 5 条,逐条 diff 出来的:

+ i18n/missing-view     translations.zh-CN.objects.showcase_contact._views.list.label
+ i18n/missing-section  translations.zh-CN.objects.showcase_contact._sections.contact.label
+ i18n/missing-section  translations.zh-CN.objects.showcase_contact._sections.work.label
+ i18n/missing-section  translations.zh-CN.objects.showcase_contact._sections.status.label
+ i18n/missing-section  translations.zh-CN.objects.showcase_contact._sections.notes.label

formViews.create 的那个段落没有 name,按渲染器的约定天生不可翻译,所以不在集合内 —— 这不是遗漏。

译文体例对齐 PR #5416 的返工 commit e3d1e855c:zh-CN 从本 bundle 既有词汇表取词(状态/备注 就是它自己 stage 族与 notes 的用词),en 不加条目(默认语言由内联 label 满足,复述源串只会伪造覆盖率)。两处需要解释的取词写在代码注释里:contact 取「联系方式」而不是在联系人记录里再套一个循环的「联系人」;_views.list 的源串是光秃秃的 "Contacts",所以用对象自己的 pluralLabel,而 task/project 列表的「全部…」属于那些真的写了 "All …" 的 label。

两条 pin

test/seed.test.ts:

反向验证(方向是事先预判的:红)

把 config 那一处 hunk stash 掉重跑,两条 pin 按预期变红,且第一条精确点名:

AssertionError: exported but absent from `views:` → ContactViews:
  expected [ 'ContactViews' ] to deeply equal []
 Tests  2 failed | 4 passed (6)

只点名 ContactViews、不误伤其余四个,说明按目标对象比对的那版 helper 是对的。

验证

pnpm build (turbo, --concurrency=2)      Tasks: 71 successful, 71 total
npx tsc --noEmit (examples/app-showcase) 通过
npx vitest run  (examples/app-showcase)  Test Files 12 passed / Tests 126 passed
npx objectstack validate                 ✓ Validation passed (1367ms),exit 0
pnpm check:i18n-coverage                 OK (12 config(s), 660 baselined
                                         untranslated string(s), none new)
node scripts/check-nul-bytes.mjs         OK (5436 files, no raw NUL bytes)

仓库级 check:i18n-coverage 是先 turbo run build 再跑的(门 shell 到构建产物)—— #5416 用一次 CI 红换来的教训,这次没有重付。

已知遗留:_views.list 上那条 translation-target-unknown

_views.list 译文之后,translation-target-unknown 多出一条 —— 但这不是本 PR 引入的新类:showcase_project / showcase_task / showcase_inquiry / showcase_business_unit 在 main 上已经各有一条一模一样的。根因是 #5164 记录的那件事:i18n 覆盖 walker 把容器默认列表按 primary.name || 'list' 推导出 _views.list.label要求它,而引用校验器认为没有任何视图叫 list —— 同一次 os lint 里两条规则互相打架。validate-translation-references.ts 的注释也明写了这归 #5164。本 PR 只能二选一,选了不让覆盖率棘轮变红的那一边,并把第 5 个实例作为数据点评论回 #5164


Generated by Claude Code

`src/ui/views/contact.view.ts` declares the whole "create form != edit form"
reference implementation — a default grouped `form` with four named sections,
a sparse `formViews.create`, and the list's
`addRecord: { mode: 'form', formView: 'create' }` binding — and
`src/ui/views/index.ts` exports it. `objectstack.config.ts` named the other
four containers on line 23 and line 196 and never named this one.

There is no directory scan behind `views:`; the CLI reads exactly that array.
So the metadata compiled, type-checked and linted clean while reaching
nothing: `nav_contacts` rendered a derived default form instead of the
authored one, `addRecord.formView` never bound, and no static pass
(`os validate` / `os lint` / `os i18n extract` / the coverage ratchet) could
see it either — which is also why #5405's new `i18n/missing-section` gate
found 10 headings in the showcase and zero of them under `showcase_contact`.
`content/docs/ui/create-vs-edit-form.mdx` cites this file as the live
reference implementation the whole time.

Registration makes exactly five zh-CN coverage keys newly reachable, measured
on the real config rather than predicted:

  os lint examples/app-showcase/objectstack.config.ts
    483 warnings (before) -> 488 (registered, untranslated) -> 484 (translated)
    + i18n/missing-view     objects.showcase_contact._views.list.label
    + i18n/missing-section  objects.showcase_contact._sections.{contact,work,status,notes}.label

All five are translated in this commit, following PR #5416's rework: zh-CN
takes its words from the vocabulary this bundle already uses, and `en` gains
nothing (the default locale is satisfied by the inline labels; echoing the
source string only fakes coverage). The ratchet baseline
`scripts/i18n-coverage-baseline.json` and `i18n.supportedLocales` are
untouched — `check-i18n-coverage: OK (12 config(s), 660 baselined
untranslated string(s), none new)`, showcase back to exactly 451.

Two guards in `test/seed.test.ts`:

  * every container the barrel exports reaches `stack.views`, matched by
    target object (`defineStack` parses the config, so a registered container
    is a structural copy and never `===` the export). Reverting the config
    hunk fails it naming `ContactViews`.
  * the four section names and their zh-CN `_sections` keys are asserted as
    set EQUALITY, because the two i18n gates read that set in opposite
    directions — `i18n/missing-section` fails on a declared section with no
    entry, `translation-target-unknown` on an entry no section declares.
    With #5422 on main this is the first time the relationship is testable on
    the real config: the four correctly-translated sections are NOT reported
    as orphans.

The remaining `translation-target-unknown` on `_views.list` is #5164's
open contradiction between the three `_views` producers, not new here — the
showcase already carried four identical instances (project / task / inquiry /
business_unit) before this change.

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 11:51am

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 11:57
@baozhoutao
baozhoutao added this pull request to the merge queue Aug 5, 2026
Merged via the queue into main with commit ed0d2aa Aug 5, 2026
23 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-5420-showcase-register-contact-views branch August 5, 2026 12:05
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