Skip to content

test(app-shell): 给 viewEnvelope 产出补 ViewItem spec 一致性 pin;MetadataProvider docblock 撤掉 "Legacy" 措辞 (#3375) - #3420

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-3375-view-persistence-pin
Aug 6, 2026
Merged

test(app-shell): 给 viewEnvelope 产出补 ViewItem spec 一致性 pin;MetadataProvider docblock 撤掉 "Legacy" 措辞 (#3375)#3420
yinlianghui merged 1 commit into
mainfrom
claude/issue-3375-view-persistence-pin

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes #3375

#3312 / objectstack#4959 的两条本仓侧尾巴,清理级,非缺陷。无任何运行时行为改动

1. viewEnvelope 产出补 spec 一致性 pin

packages/app-shell/src/views/runtime-metadata-persistence.tsviewEnvelope 是 app-shell 的第二个 ViewItem 生产者;第一个(metadata-admin 的 createBuildBody)早有 view-create-body.test.ts 守着,这里没有。新增同型 pin:

packages/app-shell/src/views/runtime-metadata-persistence.viewItemSpec.test.ts

  • 两个真实调用点的 payload做夹具,不是自造形状:ObjectView.handleViewCreate(CreateViewDialog 的 { type, label, name, [type]: subConfig },加上该调用点对 kanban/gallery 的 column 补全)与 ObjectDataPage.handleSaveAsView
  • 覆盖 grid / kanban / gallery / calendar / 已折叠的 filter rules / config.data 保留 / CJK label 的 type_base36 兜底 key。
  • 与既有 runtime-metadata-persistence.test.ts 的分工:那边断言信封的字面形状(哪个键落在哪),spec 收紧时依然绿;这边断言产出能过记录门(ADR-0017 ViewItem),所以 spec 一动会在这里报出来,而不是拖到 publish 时。

pin 方向按要求先预测后运行:这是 ratchet 不是 bug 复现,预期今天的代码上全绿 —— 实测即全绿。

反向验证做了两次(改完即还原,工作树干净):

临时改动 viewEnvelope 结果
限定名退化成裸 key(name: key) 7 个正向用例全红,ViewItemNameSchema 报 "View item name must be a dotted snake_case qualified name"
去掉 config.data 上的 provider: 'object' 7 个正向用例全红,报 data provider 判别式失配

即 pin 的两半(name 与 config)都是承重的,不是空绿。

补充一条 negative 用例钉住边界:没有 object 绑定时信封拿不到限定名,记录门必然拒绝 —— 两个调用点都在进 seam 前解析出了 object,这条把「为什么该前置条件是承重的」写下来。它在上面两次反向验证里保持绿(因为它断言的就是"无效"),属预期。

2. MetadataProvider.tsx docblock 撤掉 "Legacy"

objectstack#4959 端到端裁定:container 是刻意的栈级打包形状,不是遗留物。docblock 改为并列两个门 —— 记录门(ADR-0017 ViewItem,defineViewItem / 运行时 /meta seam)与栈门(container,defineView 产出、defineStack({ views: [...] }) 携带),并写明该分支不是死代码

措辞前先核过 spec 而非直接采信 issue 正文:@objectstack/spec/ui 把 container 当一等公民(导出 isAggregatedViewContainer / expandViewContainer,且 defineViewdefineViewItem 是两个并列工厂),MetadataProvider.merge.test.ts 也确有 container 形状的用例在跑 —— 所以"不是死代码"这句有测试兜底,不是纯断言。同时把分支上方两处仍写 "Legacy"/"New protocol" 的行内注释一并对齐(否则准备删这个分支的读者正好读到那两行)。

该文件 diff 每一行都是注释文字,已机械核验(过滤掉注释前缀后无剩余变更行)。

测试

仓根跑 vitest(按 #3288 / #3378,不用包级过滤),已确认新文件名出现在 verbose 输出里:

✓ packages/app-shell/src/views/runtime-metadata-persistence.viewItemSpec.test.ts  (8 tests)
Test Files  3 passed (3)   Tests  41 passed (41)

app-shell 全量(仓根发起):

Test Files  280 passed (280)
Tests  2434 passed | 1 skipped (2435)

pnpm --filter @object-ui/app-shell type-check(tsc --noEmit && tsc -p tsconfig.typetests.json)通过。

Changeset

未加。纯测试 + 注释,非用户可见;对照近期纯测试提交(0c9983fcd,只动 sectionLabelI18n.test.tsx)也未带 changeset,符合 AGENTS.md §9「功能改进才写 changeset」。

顺带发现(未在本 PR 修)

已另开 #3419:ObjectDataPage.handleSaveAsView 把 URL 下钻的 FilterTriple[](三元组数组)原样写进 config.filter,而记录门要的是 { field, operator, value } 对象数组 —— 带条件点「Save as view」写出的是 off-spec ViewItem。修它属运行时行为改动,不在本 PR 范围,故本 PR 的 filter 用例走的是 viewFilterFold 那条符合 spec 的产出。


Generated by Claude Code

…te; drop "Legacy" from the container docblock (#3375)

Two cleanup tails from #3312 / objectstack#4959.

1. `viewEnvelope` (runtime-metadata-persistence.ts) is app-shell's second
   ViewItem producer; only `createBuildBody` had a spec-conformance pin.
   Adds the same-shaped ratchet: the envelope produced from each real call
   site payload must pass `ViewItemSchema.safeParse`.

2. MetadataProvider's docblock called the aggregated container "Legacy".
   objectstack#4959 ruled it a deliberate stack-level packaging shape, so
   the wording now names both gates (record vs stack) and states the branch
   is not dead code. Comment prose only, zero runtime-code changes.

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

vercel Bot commented Aug 6, 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)
objectui Ignored Ignored Aug 6, 2026 2:20am

Request Review

@github-actions github-actions Bot added the tests label Aug 6, 2026
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Main entry (gzip) 28.1 KB 350 KB
Entry file index-By8_fQDz.js
Status PASS

📦 Bundle Size Report

Package Size Gzipped
app-shell (index.js) 8.47KB 3.09KB
app-shell (runtime-config.js) 7.42KB 2.32KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 7.57KB 2.97KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 1.17KB 0.53KB
auth (AuthProvider.js) 22.10KB 4.37KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.13KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.64KB 2.21KB
auth (SocialSignInButtons.js) 9.60KB 3.89KB
auth (UserMenu.js) 3.40KB 1.22KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 35.76KB 9.11KB
auth (createAuthenticatedFetch.js) 4.37KB 1.69KB
auth (index.js) 2.35KB 1.07KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 4.91KB 0.87KB
auth (useIsWorkspaceAdmin.js) 1.61KB 0.85KB
collaboration (CommentThread.js) 18.38KB 4.49KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 3.65KB 1.42KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.25KB 0.53KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 478.45KB 105.05KB
core (index.js) 2.47KB 0.91KB
create-plugin (index.js) 9.28KB 2.98KB
data-objectstack (index.js) 136.23KB 34.75KB
fields (index.js) 228.98KB 56.22KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (i18n.js) 4.32KB 1.77KB
i18n (index.js) 2.65KB 1.06KB
i18n (pickLocalized.js) 1.70KB 0.83KB
i18n (provider.js) 9.48KB 3.27KB
i18n (useObjectLabel.js) 26.14KB 6.07KB
i18n (useSafeTranslation.js) 3.26KB 1.44KB
layout (index.js) 38.53KB 10.71KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.74KB
mobile (index.js) 1.50KB 0.62KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.71KB 0.42KB
mobile (useResponsiveConfig.js) 1.36KB 0.63KB
mobile (useSpecGesture.js) 4.05KB 1.53KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 8.75KB 3.06KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 3.67KB 1.12KB
permissions (evaluator.js) 4.41KB 1.44KB
permissions (index.js) 0.91KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.52KB
permissions (usePermissions.js) 1.55KB 0.71KB
plugin-ai (index.js) 15.71KB 3.79KB
plugin-calendar (index.js) 44.98KB 12.37KB
plugin-charts (index.js) 61.04KB 17.31KB
plugin-chatbot (index.js) 180.09KB 42.72KB
plugin-dashboard (index.js) 112.03KB 28.88KB
plugin-designer (index.js) 210.51KB 42.51KB
plugin-detail (index.js) 232.48KB 57.34KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 111.54KB 26.97KB
plugin-gantt (index.js) 162.55KB 39.57KB
plugin-grid (index.js) 185.08KB 49.04KB
plugin-kanban (index.js) 47.89KB 13.18KB
plugin-list (index.js) 105.02KB 25.36KB
plugin-map (index.js) 16.81KB 5.24KB
plugin-markdown (index.js) 13.72KB 4.69KB
plugin-report (index.js) 40.58KB 10.58KB
plugin-timeline (index.js) 25.76KB 7.33KB
plugin-tree (index.js) 8.34KB 2.82KB
plugin-view (index.js) 83.67KB 20.43KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.71KB 3.53KB
providers (index.js) 0.44KB 0.22KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.67KB 2.37KB
react (LazyPluginLoader.js) 3.77KB 1.33KB
react (SchemaRenderer.js) 19.28KB 6.38KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 1.02KB 0.55KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 4.09KB 1.74KB
sdui-parser (index.js) 4.47KB 2.03KB
sdui-parser (parse.js) 10.04KB 2.82KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 4.69KB 1.48KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 0.99KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 0.20KB 0.18KB
types (crud.js) 0.20KB 0.18KB
types (data-display.js) 0.20KB 0.18KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.87KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-retry.js) 4.32KB 2.02KB
types (index.js) 2.46KB 1.21KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 0.20KB 0.18KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (spec-report.js) 5.05KB 1.93KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 0.20KB 0.18KB
types (ui-action.js) 3.40KB 1.71KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

收尾 #3312/objectstack#4959:runtime-metadata-persistence 的 ViewItem 产出补 spec 一致性 pin;MetadataProvider docblock 撤掉 "Legacy" 措辞

2 participants