Skip to content

fix(fields): grid columns 收敛到声明拼写 name,spec 合规元数据不再渲染空单元格 (#3951) - #4909

Merged
yinlianghui merged 3 commits into
mainfrom
claude/issue-3951-grid-column-name
Aug 17, 2026
Merged

fix(fields): grid columns 收敛到声明拼写 name,spec 合规元数据不再渲染空单元格 (#3951)#4909
yinlianghui merged 3 commits into
mainfrom
claude/issue-3951-grid-column-name

Conversation

@yinlianghui

@yinlianghui yinlianghui commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

Fixes #3951

按 2026-08-10 维护者裁定实施:已发布的声明拼写胜出,修 readerGridField 对齐 GridColumnDefinition(@object-ui/types)读 name,master-detail 派生侧(deriveColumns / hydrateColumns / pickAmountField)随迁。没有 col.field ?? col.name 别名 —— 一套拼写落在生产者侧,AGENTS.md #0.1。

前提复核(改前先验)

卡面写于 2026-08-09,行号已随文件增长漂移(正文的 :558/:590/:620 现为 :659/:689/…),但前提完全成立:

  • packages/types/src/field-types.ts:677 GridColumnDefinition.nameGridFieldMetadata.columns 的声明类型 —— 现状未变。
  • packages/fields/src/widgets/GridField.tsx 本地 GridColumn 声明 field: string,31 处 c.field 读点,无任何 normalize —— 现状未变。
  • content/docs/fields/grid.mdx:散文、ColumnDefinition interface、三组 pattern 示例全部name 侧;页内唯一 field 键的代码块是 object-grid(plugin-grid 的 ListColumn,另一份契约,已在原文注明)。核实无误,未反向改动。
  • examples/schema-catalog/src/schemas/fields-grid/ 三例 9 个列条目全部 name 侧。核实无误,未反向改动。

存量 field 拼写普查(仅 grid-field 列,即 GridColumnDefinition / GridColumn)

甄别口径:list view / object-gridListColumn、record picker 的 LookupColumnDefsort / filter 子句、form section 的 field 都是另外的契约,合法保留 field,不计入、不改动。

field 拼写 说明
stored / example metadata(objectstackexamples/app-crmapp-showcaseapp-todoinlineColumns) 0 例应用的 inline grid 全部走自动派生,无显式 columns;relatedListColumns 是裸字符串数组,lookupColumns 是 record picker 契约
examples/schema-catalog fields-grid 三例(9 条) 0 本就 name
content/docs/fields/grid.mdx 0 本就 name
apps/** 7 处 / 2 文件 均为 dev harness(DevLookup / DevMasterDetail),已逐处改拼写
仓内源码 + fixture + ADR 示例 143 处 / 16 文件 见下迁移清单

结论:授权侧(stored/example metadata)存量为 0,无需数据迁移;转换面全部落在仓内代码、dev harness 与 ADR 示例,已逐处显式改写,无兼容层。

迁移清单

Reader / producer(行为改动)

Fixture / harness / 文档示例(拼写对齐)

GridField.test.tsxdate-locale-channel.test.tsxcomplex-widgets.test.tsxderiveMasterDetail.test.tsLineItemsPanel.test.tsxLineItemsPanel.elementDataSource.test.tsxMasterDetailForm.test.tsxMasterDetailForm.elementDataSource.test.tsxObjectForm.test.tsxsubformHosts.test.tsxMetadataProvider.merge.test.ts(subform columns 那一条;同文件的 list view columns 保持 field 不动)、apps/console/src/dev/DevLookup.tsxDevMasterDetail.tsxdocs/adr/0001-master-detail-subform.md(两处授权示例,ADR 原文自称「reuses the existing GridColumnDefinition shape」却写着 field,正是本卡记录的分歧本身)。

消费半径按规则被谁读扫,不按被改包扫:GridColumn 的 TS 消费者只有 plugin-form(LineItemsPanel / MasterDetailForm / deriveMasterDetail);plugin-grid 的 VirtualGridColumn / ObjectGridColumnState 是另一套类型,未涉及。

新增钉(pin,纪律同 #4041)

  • packages/fields/src/widgets/GridField.declaredSpelling.test.tsx —— fixture GridColumnDefinition[] 显式标注类型(钉在声明契约上,而不是 widget 自己的理解上),断言单元格逐格非空、只读面有值、空行按声明列名开、编辑按声明列名回写。
  • packages/fields/src/widgets/GridField.keyWarning.test.tsx —— React missing-key 警告那一半,单独成文件。原因见下。
  • packages/plugin-form/src/deriveMasterDetail.declaredSpelling.test.tsx —— master-detail 路径的钉:产出/消费均为 namefield 键列不被容忍性复活、以及一条端到端(派生列直接喂进真 GridField,渲染出非空单元格)—— 生产者与消费者再也不能各说各话而两边单测都绿。

一处必须讲清的测试设计

key 警告最初和「单元格非空」放在同一文件的第二个用例里,反向验证时它没有变红。查因:React 的 missing-key 警告对同一 owner 组件只发一次,第一个用例的渲染已经把它消费掉,第二个用例观察到的是「什么都没有」—— 断言绿是因为没东西可看,不是因为逻辑对。这正是「空绿」陷阱,故拆成独立文件(dom project 是 isolate: true,按文件隔离,能保证它拥有首次渲染),并加了一个阳性对照:先渲染一个故意不带 key 的列表,断言 spy 确实抓得到警告,再断言 grid 自己的渲染没有新增警告。这样绿是被证明过的绿。

反向验证(先预判、后执行;变异前已 commit,还原用 git checkout HEAD --,未用 stash)

预判方向:Red(常规向) —— reader 读的键是 fixture 不拼写的那个,还原退役读法会同时抽掉「值」和「诊断」,不是只动诊断。

变异一:reader 还原成读 c.field(git checkout 97da1b0d6 -- GridField.tsx),fixture 保持 name:

FAIL  keyWarning       · 无 unique key 警告      → expected 2 to be 1  (对照 1 条 + grid 新增 1 条)
FAIL  declaredSpelling · 单元格逐格非空          → expected '' to be 'Widget A'
FAIL  declaredSpelling · 只读面有值              → Unable to find an element with the text: Widget A
FAIL  declaredSpelling · 空行按声明列名开        → expected [ { product: null, …(2) } ]
FAIL  declaredSpelling · 编辑按声明列名回写      → expected [ { product: 'Widget A', … } ]
FAIL  deriveMasterDetail · 端到端渲染非空        → expected '' to be 'Taxi to airport'
PASS  deriveMasterDetail · 纯派生 4 例保持绿(变异未触及生产者)
   Tests  6 failed | 4 passed (10)

与预判一致:值与诊断同时变红,派生侧不受影响的 4 例如期保持绿。

变异二:生产者还原成产出 field: namehydrateColumnscol.field(reader 保持已修):

FAIL  deriveColumns 产出 name  → expected [ undefined, undefined, undefined ] to deeply equal [ 'description', 'quantity', 'amount' ]
FAIL  hydrateColumns 认 name   → expected { name: 'amount' } to match object { name: 'amount', …(2) }
FAIL  field 键不被容忍性复活   → expected { field: 'amount', …(3) } to deeply equal { field: 'amount' }
FAIL  amountField 按 name 选   → expected undefined to be 'amount'
FAIL  端到端渲染非空           → expected '' to be 'Taxi to airport'
   Tests  5 failed (5)

第三条按预期反向变红:旧生产者读 col.field,{ field: 'amount' } 反而被补全了 type/label —— 恰好把「容忍性双读会长回来」这件事钉住。

两次变异后均 git checkout HEAD -- 还原,复跑全绿。

验证

pnpm exec vitest run packages/fields/src/widgets/ packages/plugin-form/ --maxWorkers=2
   Test Files  101 passed (101)
        Tests  1001 passed (1001)
     Duration  238.88s

pnpm exec turbo run type-check --concurrency=2
   Tasks:    81 successful, 81 total

node scripts/check-control-bytes.mjs
   check-control-bytes: OK (scanned 4389 tracked text file(s); skipped 85 binary)

(全部重验证经 flock /tmp/os-heavy-verify.lock 串行,NODE_OPTIONS=--max-old-space-size=4096,--maxWorkers=2。)

Breaking change 与 changeset

.changeset/grid-column-declared-name-spelling.md(patch,@object-ui/fields + @object-ui/plugin-form)已写明:作者显式提供的 grid / line-items / master-detail subform 列必须由 { field: 'amount' } 改写为 { name: 'amount' };自动派生列(未写 columns)无需改动;list view 与 object-gridListColumn 是另一份契约,保留自己的 field 键。

顺带发现(未在本 PR 修)

  • objectstack#9227 —— Field.inlineColumns 在 spec 里是 z.array(z.any()),任何拼错的列键都能发布通过、只在浏览器里表现为空单元格。本 PR 修好了 renderer,但授权面仍然没有守卫;例应用中该键用量为 0,故对本仓无影响,已另立卡(未指派)。

claude added 2 commits August 17, 2026 03:14
`GridField` declared a local `GridColumn` interface keyed by `field` and read
`c.field` everywhere, while the published `GridColumnDefinition`, the grid docs
page and the `fields-grid` catalog examples all declare the key as `name`.
Metadata authored against the published type rendered the right row count with
every cell empty, plus a React "unique key" warning per column.

Align the reader to the declared spelling and migrate the master-detail
producer (`deriveColumns` / `hydrateColumns` / `pickAmountField`) with it. No
`col.field ?? col.name` alias — one spelling at the producer (AGENTS.md #0.1).

Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added documentation Improvements or additions to documentation plugin apps tests labels Aug 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

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

📦 Bundle Size Report

Package Size Gzipped
app-shell (index.js) 9.56KB 3.59KB
app-shell (runtime-config.js) 7.42KB 2.32KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 8.92KB 3.41KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 1.17KB 0.53KB
auth (AuthProvider.js) 25.13KB 5.40KB
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) 38.46KB 10.17KB
auth (createAuthenticatedFetch.js) 6.34KB 2.43KB
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) 5.02KB 0.88KB
auth (useIsWorkspaceAdmin.js) 1.61KB 0.85KB
collaboration (CommentThread.js) 26.07KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.65KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
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) 498.37KB 111.05KB
core (index.js) 3.79KB 1.52KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 157.05KB 43.28KB
fields (index.js) 231.70KB 57.59KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (i18n.js) 4.28KB 1.75KB
i18n (index.js) 3.35KB 1.38KB
i18n (pickLocalized.js) 3.69KB 1.73KB
i18n (provider.js) 23.12KB 7.62KB
i18n (useDisplayLocale.js) 2.84KB 1.45KB
i18n (useObjectLabel.js) 27.59KB 6.63KB
i18n (useSafeTranslation.js) 7.77KB 3.13KB
layout (index.js) 38.86KB 10.83KB
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.32KB 1.64KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 9.35KB 3.31KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 4.42KB 1.42KB
permissions (evaluator.js) 5.12KB 1.74KB
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.81KB 0.83KB
plugin-ai (index.js) 15.75KB 3.80KB
plugin-calendar (index.js) 46.62KB 12.83KB
plugin-charts (index.js) 64.75KB 18.37KB
plugin-chatbot (index.js) 181.21KB 43.14KB
plugin-dashboard (index.js) 130.85KB 33.44KB
plugin-designer (index.js) 212.39KB 42.83KB
plugin-detail (index.js) 239.81KB 59.97KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 120.42KB 29.03KB
plugin-gantt (index.js) 164.10KB 39.87KB
plugin-grid (index.js) 197.59KB 53.01KB
plugin-kanban (index.js) 52.72KB 14.54KB
plugin-list (index.js) 111.23KB 26.97KB
plugin-map (index.js) 17.91KB 5.72KB
plugin-markdown (index.js) 13.72KB 4.69KB
plugin-report (index.js) 41.70KB 11.19KB
plugin-timeline (index.js) 26.68KB 7.66KB
plugin-tree (index.js) 8.50KB 2.88KB
plugin-view (index.js) 83.81KB 20.49KB
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.66KB 3.50KB
providers (index.js) 0.44KB 0.22KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 3.77KB 1.33KB
react (SchemaRenderer.js) 27.53KB 9.41KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 1.28KB 0.68KB
react (schema-input.js) 1.45KB 0.83KB
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 (dashboard-filter-alias.js) 6.23KB 2.74KB
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) 3.05KB 1.52KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 2.59KB 1.31KB
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

…ding it as a dual read

The comment on `GridColumn.name` stated the rule by spelling out the
alternation it forbids. `column-identity.ratchet.test.ts` scans package
sources line by line and cannot tell prose from code, so that sentence
registered as a new dual read and failed the gate — on the very commit that
removed the second spelling.

Restate the rule in words and leave a note telling the next editor not to
write it as an expression again. The file is deliberately NOT added to the
ratchet inventory: there is no dual read here to record, and listing one
would corrupt the inventory it exists to keep honest.

Second instance of the text-level-gate blind spot tracked in objectui#4902.

Co-authored-by: Claude <noreply@anthropic.com>

Copy link
Copy Markdown
Collaborator Author

返工:07881e07e —— 改注释措辞,让 #3104 双读棘轮不再把它当成双读

CI 终态 19/20 绿,唯一红是 Test (shard 2/4) 的 column-identity.ratchet.test.ts > finds no dual read in a file the inventory does not list:

+ "fields/src/widgets/GridField.tsx:51 :: * There is deliberately NO `col.field ?? col.name` alias: one spelling, at"

行为零缺陷。 该棘轮(packages/core/src/utils/__tests__/column-identity.ratchet.test.ts:194-215)是逐行文本启发式 —— 一行里同时出现 || / ?? 和两个以上不同的身份键属性访问就记一处双读,判据不剥注释、分不清散文与代码。我那句注释的内容恰恰是声明「这里故意没有这个别名」,却因为把该形状照字面写了出来而被判成新增双读:棘轮读数 11 → 12。修掉双拼写的那次提交,因为写下「这里没有双读」而被双读门拦住。

处置

只改措辞,GridField.tsx 加进棘轮 inventory —— 这里没有双读可登记,往「双读清单」上记一处不存在的双读,污染的正是这份清单赖以存在的可信度。改后的注释用散文陈述规则(no tolerant alias bridging the retired spelling to this one),并留了一行给下一个编辑者:不要把这条规则重新写成两个键名之间的 alternation 表达式,本仓的棘轮逐行扫描且分不清散文与代码。

本地读数

pnpm exec vitest run packages/core/src/utils/__tests__/column-identity.ratchet.test.ts --maxWorkers=2
   ✓ scans a plausible number of package source files (guards a broken scan path)
   ✓ finds no dual read in a file the inventory does not list      ← CI 红的那条
   ✓ matches the recorded count in every listed file
   ✓ holds the family at zero
   ✓ records a precedence for every read left in the family
   ✓ routes every converged surface through the one reader
   ✓ keeps the table-adapter key ahead of metadata identity in RelatedList
   Test Files  1 passed (1)   Tests  7 passed (7)

pnpm exec vitest run packages/core/src/utils/__tests__/column-identity.ratchet.test.ts packages/fields/src/widgets/ --maxWorkers=2
   Test Files  55 passed (55)   Tests  530 passed (530)

node scripts/check-control-bytes.mjs → OK (4389 tracked text files)

复刻棘轮扫描逻辑单独核对:全仓命中数由 12 回到基线 11,且 11 处中没有一处来自本 PR 触及的文件。

顺带

这是 #4902(文本级门把注释当代码)的第二实例,已在该卡追加评论记录:盲区从单个门扩大为「文本级门家族」,且误报系统性地集中在正确修法上 —— 讲解某个被禁形状的注释,最可能出现在刚刚修掉它的那个 PR 里。这改变了该 finding 的修法作用域(建议至少覆盖 scripts-type-check.test.ts 与本棘轮两个门)。


Generated by Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

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

📦 Bundle Size Report

Package Size Gzipped
app-shell (index.js) 9.56KB 3.59KB
app-shell (runtime-config.js) 7.42KB 2.32KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 8.92KB 3.41KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 1.17KB 0.53KB
auth (AuthProvider.js) 25.13KB 5.40KB
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) 38.46KB 10.17KB
auth (createAuthenticatedFetch.js) 6.34KB 2.43KB
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) 5.02KB 0.88KB
auth (useIsWorkspaceAdmin.js) 1.61KB 0.85KB
collaboration (CommentThread.js) 26.07KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.65KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
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) 498.37KB 111.05KB
core (index.js) 4.06KB 1.61KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 157.05KB 43.28KB
fields (index.js) 231.70KB 57.59KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (i18n.js) 4.28KB 1.75KB
i18n (index.js) 3.35KB 1.38KB
i18n (pickLocalized.js) 3.69KB 1.73KB
i18n (provider.js) 23.12KB 7.62KB
i18n (useDisplayLocale.js) 2.84KB 1.45KB
i18n (useObjectLabel.js) 27.59KB 6.63KB
i18n (useSafeTranslation.js) 7.77KB 3.13KB
layout (index.js) 38.86KB 10.83KB
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.32KB 1.64KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 9.35KB 3.31KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 4.42KB 1.42KB
permissions (evaluator.js) 5.12KB 1.74KB
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.81KB 0.83KB
plugin-ai (index.js) 15.75KB 3.80KB
plugin-calendar (index.js) 46.62KB 12.83KB
plugin-charts (index.js) 64.75KB 18.37KB
plugin-chatbot (index.js) 181.21KB 43.14KB
plugin-dashboard (index.js) 127.85KB 32.73KB
plugin-designer (index.js) 212.39KB 42.83KB
plugin-detail (index.js) 239.81KB 59.97KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 120.42KB 29.03KB
plugin-gantt (index.js) 164.10KB 39.87KB
plugin-grid (index.js) 197.59KB 53.01KB
plugin-kanban (index.js) 52.72KB 14.54KB
plugin-list (index.js) 111.23KB 26.97KB
plugin-map (index.js) 17.91KB 5.72KB
plugin-markdown (index.js) 13.72KB 4.69KB
plugin-report (index.js) 41.97KB 11.33KB
plugin-timeline (index.js) 26.68KB 7.66KB
plugin-tree (index.js) 8.50KB 2.88KB
plugin-view (index.js) 83.81KB 20.49KB
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.66KB 3.50KB
providers (index.js) 0.44KB 0.22KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 3.77KB 1.33KB
react (SchemaRenderer.js) 27.53KB 9.41KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 1.28KB 0.68KB
react (schema-input.js) 1.45KB 0.83KB
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 (dashboard-filter-alias.js) 6.23KB 2.74KB
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) 3.05KB 1.52KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 2.59KB 1.31KB
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

Copy link
Copy Markdown
Collaborator Author

PM 验收:ACCEPT(1 轮返工后)(#3951,批次 16→17,PM 会话 session_01GTRjn8xBqp75dk7kFupVRt)

裁定执行:声明拼写 name 胜出、reader 修正(GridField 31 读点 + deriveMasterDetail 家族 13 处),全仓 ⛔ 零容忍别名(PM 独立扫描:唯一命中是禁令注释本身,实读判假阳)。普查结果:本契约下按 field 授权的存量元数据为 0(catalog 三例与 grid.mdx 本就在 name 侧,核实未反改)—— 裁定预设的迁移成本实测为零;7 处 dev harness + 143 处仓内 fixture/ADR 显式转换,无双读桥。

反向验证:双向变异各自预判逐例命中(reader 回翻 → 6 红空单元格;producer 回翻 → 5 红含双读守卫反转);React key 警告钉的一次性消费陷阱(once-per-owner,断言空过)由 dev 自查抓出 —— 移独立文件 + 正查对照后重跑转红,假绿不采信纪律执行到位。git checkout -- 从 index 还原的坑也当场自纠(改用 HEAD --),变异代码零入库(实测计数验证)。

返工记账(1 轮,非行为缺陷):首轮 CI 唯一红是 column-identity.ratchet.test.ts(#3104)把 GridField.tsx:51 的禁令注释当双读 —— 文本级门分不清 prose 与代码,#4902 盲区家族第二实例(已由 dev 在该卡追加,扩展其修法作用域)。返工为纯注释措辞(+7/−2,含防再踩说明),⛔ 未加白名单(inventory 保持诚实);dev 本地复刻棘轮扫描 12→11 命中、0 来自本 PR。返工头 CI:20 项全 completed,18 success + 2 skipped,零失败。

附带产出:os#9227(spec 侧 inlineColumns: z.array(z.any()) authoring 面缺口,跨仓卡)。

→ undraft + auto-merge (SQUASH)。


Generated by Claude Code

@yinlianghui
yinlianghui marked this pull request as ready for review August 17, 2026 05:35
@yinlianghui
yinlianghui added this pull request to the merge queue Aug 17, 2026
Merged via the queue into main with commit 800f455 Aug 17, 2026
21 checks passed
@yinlianghui
yinlianghui deleted the claude/issue-3951-grid-column-name branch August 17, 2026 05:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

apps documentation Improvements or additions to documentation plugin tests

Projects

None yet

2 participants