Skip to content

fix(types,detail): derive five spec-named symbols instead of forking them (objectstack#4115) - #3057

Merged
os-zhuang merged 1 commit into
mainfrom
claude/spec-name-debt-types
Jul 30, 2026
Merged

fix(types,detail): derive five spec-named symbols instead of forking them (objectstack#4115)#3057
os-zhuang merged 1 commit into
mainfrom
claude/spec-name-debt-types

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

承上一轮 objectui#3017 的收尾结论:「#4115 的 156 条债务是同一失效类的超集,且 objectui @object-ui/types 占 71 条,是传播根」。本 PR 是分诊 + 第一个增量

分诊结果:不是「离漂移只差一个版本」,是已经漂了

@object-ui/types 全部 73 条碰撞记录(71 个唯一名)逐条两边对读:

判决 数量
FORK_DRIFTED — 本地声明与 spec 已经不一致 55
COINCIDENCE — 真撞名,概念不同 17
FORK_IDENTICAL 1

#4115 描述这批债务是「已漂移离漂移只差一个 spec 版本」。实测偏向前者:四分之三已经漂了,其中若干是活的缺陷而非理论风险。完整分诊表(每条含 spec 侧定义、精确成员 delta、注释是否谎称 canonical、建议修法)见下方「分诊全表」。

本 PR 落地的五条(149 → 144)

只取可证明安全的一档:本地是 spec 的严格子集、或与 spec 逐成员相同。其中两条是活缺陷:

  • PageVariableSchema 漏了 source —— 整个 ADR-0049 写绑定。spec 写法 {name:'selectedProjectId', source:'project_picker'} 在这里解析后变成一个谁也写不了的变量;type 枚举还漏了 record_id,spec 合法的记录选择器变量直接被拒。最扎眼的是:同一文件往下三行的 PageTypeSchema 已经改成 spec 引用了,注释还写着「镜像漏了 list 导致 spec 合法页面校验失败」—— 修了一个,把隔壁那个漏了。
  • FeedItemType 只有 spec 13 个成员里的 7 个。缺的 6 个(file/sharing/note/record_create/record_delete/approval)在 RecordActivityTimeline既没图标也没颜色,服务端一旦发出就是渲染不出来的条目。两张表都是 Record<FeedItemType, …> 全键映射,所以 widen 联合类型直接把缺口变成编译错误 —— 六个条目在本 PR 补齐。
  • PermissionAction 8/11,漏 execute(跑 flow/action 的权限)、manageconfigure
  • ObjectIndexfulltextunique: 'global'(全局唯一域)、partial
  • PageVariable(TS)与 spec 逐成员相同 —— 它唯一的作用就是多一个会漂的地方。有意思的是它的 Zod 对应物漂了、它自己没漂。

闸门与验证

台账用脚本自带的 --ledger 重生成而非手改,并逐条 diff 确认改动恰好是这 5 个名字,没有误抹其他包的债务(149→144,removed 恰为这五个、added 为空)。

变异测试两个方向都验过:

  • PermissionAction 重新 fork 成本地联合 → 守卫按名报红(declares 1 spec-named symbol the spec already owns);
  • 烧掉的名字留在台账里不删 → 守卫按「登记表已腐烂」报红。

全仓 type-check 78/78 绿;@object-ui/types + @object-ui/plugin-detail 共 49 文件 535 断言绿;两包 lint 绿(仅存量 warning)。

未纳入本 PR 的,以及为什么

余下 50 条 drifted 大多需要API 决策,不该和安全派生混在一个 PR 里:

  • 重命名类(约 17 条 COINCIDENCE + 部分 drifted):FilterCondition/FilterOperator/EventHandler/CacheStrategy/MutationEvent/SpanSchema 等都是概念不同的真撞名,正解是改本地名 —— 但它们多数从 barrel 公开导出,改名是 breaking change。
  • 渲染节点 vs 元数据文档(PageSchema/AppSchema/DashboardSchema/ReportSchema,TS + Zod 各一份):spec 的 type 是页面/报表种类,objectui 的 type 是渲染器判别式,两者语义冲突,需要先定命名约定(*NodeSchema?)再动。
  • .passthrough() 静默放行:AppSchema/DashboardSchema/PageSchema 的 Zod 侧继承了 BaseSchema.passthrough(),spec 侧是 .strict()——spec 独有的 22/13/15 个键全部未经校验地穿过去,brading: 这种拼写错误完全隐形。这是 #4120 那个失效形态在 objectui 的等价物,值得单独一轮。
  • 已有良好范式可抄:zod/objectql.zod.tsListViewSchema 是全场最佳实践 —— spec 字段经 SpecListViewFields.shape 按引用流入,配 list-view-spec-parity.test.ts 漂移守卫,注释所述与代码所做一致。其余几处应向它收敛。

我会把完整分诊表(55 条 drifted 的逐条 delta)发到 #4115,作为后续增量的工作清单。

🤖 Generated with Claude Code

…them (objectstack#4115)

Burns the first five names off the spec-symbol DEBT ledger (149 -> 144).
None of these were "one spec release away from drifting" — all five had
already drifted, and two were live defects:

- PageVariableSchema (zod/layout.zod.ts) omitted `source`, the entire
  ADR-0049 write-binding, so a spec-authored master/detail page parsed
  into a variable nothing could ever write; its `type` enum was also
  missing `record_id`, rejecting spec-valid record-picker variables. The
  sibling PageTypeSchema three lines below was already a spec re-export,
  with a comment describing this exact failure — one mirror was fixed and
  its neighbour left broken.
- FeedItemType carried 7 of the spec's 13 members. The six missing kinds
  (file, sharing, note, record_create, record_delete, approval) had no
  icon and no colour in RecordActivityTimeline, so a server emitting any
  of them produced an unrenderable feed item. Both maps are
  `Record<FeedItemType, …>`, so widening the union surfaced the gap as a
  compile error; the six entries are filled in here.
- PermissionAction was 8 of 11, missing `execute`/`manage`/`configure`.
- ObjectIndex lacked `fulltext`, `unique: 'global'` and `partial`.
- PageVariable (TS) was member-for-member identical to spec's — a second
  place to drift from and nothing else. Note its own Zod counterpart had
  drifted while it had not.

The ledger is regenerated with `--ledger`, not hand-edited; the diff is
exactly these five names, so no other package's debt was dropped.

Mutation-tested both directions: re-forking a burned-down name fails the
guard by name, and leaving a burned name in the ledger fails it as stale.

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 2:37pm

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-BAwKLuIu.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) 458.88KB 100.29KB
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) 8.76KB 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 (retry.js) 3.48KB 1.61KB
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.81KB 54.28KB
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) 183.79KB 48.20KB
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.95KB 21.02KB
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 056faa8 into main Jul 30, 2026
16 checks passed
@os-zhuang
os-zhuang deleted the claude/spec-name-debt-types branch July 30, 2026 14:43
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.

1 participant