Skip to content

refactor: hand-copied checklists become derivations or gated inventories (#3017) - #3043

Merged
os-zhuang merged 1 commit into
mainfrom
claude/spec-checklist-sync-audit-f5f056
Jul 30, 2026
Merged

refactor: hand-copied checklists become derivations or gated inventories (#3017)#3043
os-zhuang merged 1 commit into
mainfrom
claude/spec-checklist-sync-audit-f5f056

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Closes #3017. 承 framework#3786 / objectstack#4120 的修法模板:能派生就从唯一来源派生;确实无法派生的,加集合覆盖/不相交断言当闸门;闸门必须变异测试证明会红。

Issue 六处中 #1/#2 已由 #3019 落地;本 PR 处理其余四处,并在加闸门过程中捞到三处同种残留(issue 表格之外)。

逐处修法

# 位置 修法
3 object-fields-bridge.ts DESIGNER_TYPES DesignerFieldType 联合改为从新的运行时数组 DESIGNER_FIELD_TYPES(@object-ui/types)派生;bridge 直接 new Set(DESIGNER_FIELD_TYPES)FieldDesignerFIELD_TYPE_META 本就是 Record<DesignerFieldType,…>,词汇增删自动变编译错误;顺手删掉死代码 ALL_FIELD_TYPES
4 RecordMetaFooter AUDIT_FIELDSRecordDetailView AUDIT_FIELD_NAMES 单一来源 AUDIT_FIELD_BY_ROLE / AUDIT_FIELD_NAMES 落在 @object-ui/types(两包公共底座;app-shell 不依赖 plugin-detail,反向也不行)。RecordDetailViewHIDDEN_SYSTEM_FIELD_NAMES 进一步改为 spec FIELD_GROUP_SYSTEM_FIELDS − 审计集 派生 —— framework 明天新注入的 bookkeeping 列默认隐藏,而不是漏进 detail 正文等人补清单
5 ImportWizard BOOLEAN_IMPORT_TOKENS spec 未导出 token 表,无法派生(framework#3786 跟踪)→ 拆成 true/false 两集,闸门:不相交 + trim/lowercase 归一化(查找路径依赖此性质)+ 清单钉扎(改动必须有意识地双处落笔)
6 ImportWizard REFERENCE_IMPORT_TYPES 与服务端同一条派生链:spec REFERENCE_VALUE_TYPES + 'reference'(新模块 importCoercionContract.ts);plugin-grid 新增 @objectstack/spec 运行时依赖
+7 FieldDesigner FIELD_TYPE_CATEGORIES/CATEGORY_ORDER tsc 只保证成员合法,不保证每个类型都落进某个类目(新类型会悄悄从类型下拉里消失)→ 覆盖闸门:摊平后与 DESIGNER_FIELD_TYPES 集合相等、无重复、CATEGORY_ORDER 覆盖全部类目
+8 MetadataFieldsPage KNOWN_FIELD_TYPES 又一份 27 型手抄(变异测试把它炸了出来)→ 派生自 DESIGNER_FIELD_TYPES
+9 multiValueFields.ts 两个 Set 与 spec MULTI_OPTION_TYPES/MULTI_CAPABLE_TYPES 逐项相同 → 直接消费 spec(保留 null 容错包装),锚点断言防词汇缩水复发 #2204 形状腐蚀

变异测试(闸门真的会红)

七处注入漂移(词汇删 slider、审计删 updated_by、hidden 派生偷排 tenant_id、布尔加 'True'/两侧同置 'on'、别名 'reference' 删除、CATEGORY_ORDERdate):

  • 13 个测试失败,分布在全部 5 个闸门文件,逐项可归因;
  • 编译闸门同步引爆:FieldDesigner TS2353/TS2322、MetadataFieldsPage TS2769、RecordMetaFooter TS2339;
  • 回滚后 10 文件 102 断言全绿,5 包 type-check + lint 全绿。

行为不变

每个派生集与被替换清单逐值相同(hidden 集今天恰为原 4 项字面量;spec 词汇未来增长时行为按上表设计演化)。测试内的清单钉扎是有意的第二份陈述(照 #3032 ActionDef inventory / #4120 的登记表模式):它把「静默漂移」换成「红着的、指路的测试」。

沿途观察、动的:ObjectFieldInspectorSUMMARY_NUMERIC_TYPES 是语义选择(可汇总类型)而非清单拷贝;isPlausibleEmail/importJobUndoable 等是算法镜像,不属本 issue 的清单模式。

🤖 Generated with Claude Code

…s become derivations or gated inventories (#3017)

Sites #3-#6 of the audit, plus three more of the same species found while
gating - all previously "keep in sync" comments with zero mechanism:

- DesignerFieldType is now derived from a runtime DESIGNER_FIELD_TYPES
  array in @object-ui/types; app-shell's object-fields-bridge and
  plugin-designer's MetadataFieldsPage derive their 27-type sets from it
  instead of restating the list (FieldDesigner's FIELD_TYPE_META was
  already compile-gated via Record<DesignerFieldType>). The dead
  ALL_FIELD_TYPES const is removed, and the FIELD_TYPE_CATEGORIES /
  CATEGORY_ORDER partition gets a coverage gate - a type added to the
  vocabulary but left uncategorized would silently vanish from the type
  pickers.
- The audit-provenance columns get one source: AUDIT_FIELD_BY_ROLE /
  AUDIT_FIELD_NAMES in @object-ui/types, consumed by RecordMetaFooter and
  RecordDetailView. RecordDetailView's HIDDEN_SYSTEM_FIELD_NAMES is now
  derived as spec FIELD_GROUP_SYSTEM_FIELDS minus the audit set, so a
  newly injected system column defaults to hidden instead of leaking into
  detail bodies until a hand list is edited.
- ImportWizard's REFERENCE_IMPORT_TYPES is derived from the spec's
  REFERENCE_VALUE_TYPES plus the generic 'reference' alias - the same
  derivation the server uses - in a new importCoercionContract module.
- The boolean token table cannot be derived (no spec export yet,
  framework#3786): it is split into true/false sets with disjointness +
  normalization gates and a pinned inventory so edits are deliberate.
- multiValueFields' two sets were member-for-member copies of the spec's
  MULTI_OPTION_TYPES / MULTI_CAPABLE_TYPES - now consumed directly, with
  non-vacuity anchors so a shrinking spec vocabulary fails loudly instead
  of resurrecting the #2204 column-shape corruption.

Mutation-tested: seven injected drifts across five source files produced
13 test failures across all five gate files, plus compile errors in
FieldDesigner (TS2353/TS2322), MetadataFieldsPage (TS2769) and
RecordMetaFooter (TS2339). Zero behavior change - every derived set is
value-identical to the list it replaces.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 30, 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 Jul 30, 2026 1:24pm

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

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

📦 Bundle Size Report

Package Size Gzipped
app-shell (index.js) 8.20KB 2.97KB
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.12KB 3.41KB
auth (LoginForm.js) 17.86KB 5.29KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.43KB 2.09KB
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) 457.97KB 100.09KB
core (index.js) 2.16KB 0.78KB
create-plugin (index.js) 9.28KB 2.98KB
data-objectstack (index.js) 134.67KB 34.24KB
fields (index.js) 222.07KB 54.35KB
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.46KB 0.96KB
i18n (pickLocalized.js) 1.70KB 0.83KB
i18n (provider.js) 5.37KB 1.72KB
i18n (useObjectLabel.js) 25.17KB 5.80KB
i18n (useSafeTranslation.js) 3.26KB 1.44KB
layout (index.js) 38.45KB 10.67KB
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) 6.84KB 2.42KB
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.90KB 12.35KB
plugin-charts (index.js) 60.52KB 17.11KB
plugin-chatbot (index.js) 180.09KB 42.72KB
plugin-dashboard (index.js) 111.59KB 28.74KB
plugin-designer (index.js) 210.51KB 42.50KB
plugin-detail (index.js) 221.42KB 54.12KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 106.54KB 25.88KB
plugin-gantt (index.js) 162.26KB 39.53KB
plugin-grid (index.js) 184.01KB 48.28KB
plugin-kanban (index.js) 47.82KB 13.18KB
plugin-list (index.js) 102.39KB 24.18KB
plugin-map (index.js) 16.80KB 5.24KB
plugin-markdown (index.js) 13.65KB 4.67KB
plugin-report (index.js) 40.32KB 10.53KB
plugin-timeline (index.js) 25.75KB 7.32KB
plugin-tree (index.js) 8.36KB 2.81KB
plugin-view (index.js) 85.91KB 20.99KB
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
sdui-parser (codegen.js) 4.09KB 1.74KB
sdui-parser (index.js) 3.47KB 1.54KB
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 (index.js) 2.07KB 0.99KB
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.04KB 1.93KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 0.20KB 0.18KB
types (ui-action.js) 1.08KB 0.64KB
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

@os-zhuang
os-zhuang merged commit 4e11db8 into main Jul 30, 2026
16 checks passed
@os-zhuang
os-zhuang deleted the claude/spec-checklist-sync-audit-f5f056 branch July 30, 2026 13:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

排查「手抄 spec 清单 + "keep in sync" 注释」模式:objectui 侧六处,目前全部一致但零闸门(framework#3786)

1 participant