Skip to content

refactor(spec)!: remove the kernel metadata-loader envelope family — 11 names declared twice with different shapes (#4411) - #4458

Merged
os-zhuang merged 6 commits into
mainfrom
claude/metadata-watch-event-dual-source-v3jw3v
Aug 1, 2026
Merged

refactor(spec)!: remove the kernel metadata-loader envelope family — 11 names declared twice with different shapes (#4411)#4458
os-zhuang merged 6 commits into
mainfrom
claude/metadata-watch-event-dual-source-v3jw3v

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Closes #4411.

@objectstack/spec exported eleven names twice, with a different shape each time, on two subpath entries — so which type a consumer got depended on nothing but the import path:

import type { MetadataWatchEvent } from '@objectstack/spec/kernel';   // one shape
import type { MetadataWatchEvent } from '@objectstack/spec/system';   // another

This removes the kernel/metadata-loader.zod copies of MetadataFormat, MetadataStats, MetadataLoadOptions, MetadataSaveOptions, MetadataExportOptions, MetadataImportOptions, MetadataLoadResult, MetadataSaveResult, MetadataWatchEvent, MetadataCollectionInfo and MetadataLoaderContract (plus each one's …Schema). system/metadata-persistence.zod stays as the single source.

#4411 范围的一处修正

issue 记录的是 MetadataWatchEvent 一个同名双源。核实下来,同一个文件里还有 10 个同类,机制完全相同 —— 所以本 PR 一并退役了 11 个,而不是 1 个。

只删被记录过的那一个,会留下九个一模一样的陷阱,而且恰好把唯一有文档的那个拆掉了。

为什么删 kernel 侧

  • 零消费方。 三仓(本仓 + cloud + objectui)import 语句级扫描:11 个名字的所有消费方都从 ./system 导入(export/import options 走 ./contracts 自有 interface)。只有 kernel/metadata-loader.test.ts 在 parse kernel 版。ADR-0049 enforce-or-remove。
  • 命名直觉是反的,这是它比普通重复更危险的地方。kernel 那份看起来更正统 —— 规范化枚举、字段必填、每个属性都有 .describe() —— 而它是死的;活的是宽松超集,其消费方在自己的注释里管它叫 "legacy"。按名字选、或按"哪个看起来更严谨"选,都选中死的那份;而两份形状大量重叠,所以选错照样编译,只在边缘值(add vs added)或必填性上翻车。

退役路线

这些是运行时信封类型,不是可作者化 metadata —— 没有任何 load path 会解析它们,任何作者写的源码都不可能携带。所以刻意不加 retiredKey() tombstone、不加 ADR-0087 conversion:收不到的处方是噪音,os migrate meta 也没有源码可改写(plugin-runtime.zod.ts / dev-plugin 家族先例,#3950#4149)。

FROM → TO

改 import 路径,名字不变:

-import type { MetadataWatchEvent, MetadataStats } from '@objectstack/spec/kernel';
+import type { MetadataWatchEvent, MetadataStats } from '@objectstack/spec/system';

存活的 system 版是更宽松的一份,所以读取方可能需要新增收窄,生产方不需要任何改动。差异明细见 changeset;要点:MetadataWatchEvent.typeadd/change/unlink,metadataType/name/timestamp 为可选;MetadataStats 全部可选。

没有运行时行为变化 —— 没有东西读过被删的副本。本 PR 不收紧 system 侧任何形状(那是独立的行为变更)。

未受影响

MetadataManagerConfigMetadataFallbackStrategy 不动 —— 它们从未重复(kernel 拥有、system re-export),而这正是保留下来的切分:manager wiring 归 kernel,loader/watch envelope 归 system,没有任何东西声明两遍

MetadataManagerConfig.formats 原本引用被删的 kernel MetadataFormatSchema,改为引 shared/metadata-types.zod 的同名 schema(四个成员完全一致,叶子模块无循环)。没用 system —— 那份含 yml/ts/js 别名,采用它会悄悄放宽这个 config 接受的值。

顺带

生成物

  • json-schema.manifest.json −11 条、authorable-surface.json −65 行,刻意手工删除(gate (a) 的 vanished-key 路径;没有东西能作者化它们,所以没有 [RETIRED] 标记)
  • api-surface.json 重新生成:./kernel 少 22 个导出,0 added / 0 narrowed
  • references/kernel/metadata-persistence.mdxgen:docs 移除
  • v17 release notes 的 dead-clusters 表 + upgrade checklist 已扩充

验证

相关

follow-up #4446(跨 barrel 同名导出检查):本 PR 清掉了一个同名双源家族,产生机制没堵。基线已实测(本 PR 后仍有 83 条跨子路径同名导出)。


Generated by Claude Code

claude added 2 commits August 1, 2026 07:48
…11 names declared twice with different shapes (#4411)

`@objectstack/spec` exported eleven names TWICE, with a different shape each
time, on two subpath entries — so which type a consumer got depended on nothing
but the import path:

    import type { MetadataWatchEvent } from '@objectstack/spec/kernel';   // one shape
    import type { MetadataWatchEvent } from '@objectstack/spec/system';   // another

`MetadataFormat`, `MetadataStats`, `MetadataLoadOptions`, `MetadataSaveOptions`,
`MetadataExportOptions`, `MetadataImportOptions`, `MetadataLoadResult`,
`MetadataSaveResult`, `MetadataWatchEvent`, `MetadataCollectionInfo` and
`MetadataLoaderContract` are removed from `kernel/metadata-loader.zod`. The
`system/metadata-persistence.zod` copies stay as the single source.

Why the kernel side goes, and why this was worth removing rather than living
with:

- Zero consumers. Import-statement scans across this repo, `cloud` and
  `objectui` find every consumer on `./system` (or `./contracts`' own
  interface); only `kernel/metadata-loader.test.ts` ever parsed the kernel
  copies. ADR-0049 enforce-or-remove.
- The naming intuition pointed the wrong way, which is what made this sharper
  than an ordinary duplicate. The kernel copies were the ones that LOOKED
  canonical — normalized enums, required fields, a `.describe()` per property —
  and they were the dead ones; the live copy is the loose superset its own
  consumer calls "legacy". Picking by name, or by which reads as more rigorous,
  picked the dead one, and because the shapes overlap heavily that choice
  compiled and failed later, at an edge value (`add` vs `added`) or on a field
  one copy made required.

No tombstone and no ADR-0087 conversion, deliberately: these are runtime
envelope types, not authorable metadata, so no authored source can carry them
and there is nothing for `os migrate meta` to rewrite (the plugin-runtime /
dev-plugin precedents).

`MetadataManagerConfig` and `MetadataFallbackStrategy` are untouched — they were
never duplicated (kernel owns them, system re-exports them), and that is the
split that survives: manager wiring is kernel's, the loader/watch envelope is
system's, nothing is declared twice. `MetadataManagerConfig.formats` now reads
the `shared` format enum (same four members, leaf module, no cycle) rather than
a fourth local copy.

Also:
- `contracts/metadata-service.ts` drops the "spec carries TWO types named
  MetadataWatchEvent" warning added in #4404 — it no longer does.
- `expression-conformance.ledger.ts` drops the now-absent
  `kernel/metadata-loader.zod.ts:filter` CEL surface (the surviving system
  options never declared a `filter`, so no loader predicate was ever evaluated
  through it).
- Baselines dropped deliberately: `json-schema.manifest.json` −11 entries,
  `authorable-surface.json` −65 lines (nothing can author these, so no
  `[RETIRED]` markers). `api-surface.json` regenerated: 22 exports leave
  `./kernel`. `references/kernel/metadata-persistence.mdx` removed by
  `gen:docs`. v17 release notes + upgrade checklist extended.

No runtime behaviour changes — nothing read the removed copies. The system
shapes are NOT tightened here; narrowing them would be a separate change.

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

vercel Bot commented Aug 1, 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 1, 2026 9:56am

Request Review

@github-actions github-actions Bot added size/xl documentation Improvements or additions to documentation protocol:system tests tooling labels Aug 1, 2026
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/dogfood, @objectstack/spec.

108 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx (via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx (via @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via @objectstack/spec)
  • content/docs/api/environment-routing.mdx (via @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx (via @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/spec)
  • content/docs/automation/approvals.mdx (via @objectstack/spec)
  • content/docs/automation/connectors.mdx (via @objectstack/spec)
  • content/docs/automation/flows.mdx (via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx (via packages/spec)
  • content/docs/automation/hooks.mdx (via @objectstack/spec)
  • content/docs/automation/index.mdx (via @objectstack/spec)
  • content/docs/automation/webhooks.mdx (via @objectstack/spec)
  • content/docs/automation/workflows.mdx (via @objectstack/spec)
  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via packages/spec)
  • content/docs/concepts/north-star.mdx (via packages/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx (via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx (via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx (via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx (via @objectstack/spec)
  • content/docs/data-modeling/index.mdx (via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx (via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx (via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx (via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx (via @objectstack/spec)
  • content/docs/deployment/cli.mdx (via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/deployment/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx (via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx (via packages/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via packages/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/spec)
  • content/docs/kernel/services.mdx (via @objectstack/spec)
  • content/docs/permissions/authorization.mdx (via packages/qa/dogfood, @objectstack/spec)
  • content/docs/permissions/delegated-administration.mdx (via packages/qa/dogfood)
  • content/docs/permissions/permission-sets.mdx (via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/permissions/positions.mdx (via @objectstack/spec)
  • content/docs/permissions/rls.mdx (via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/plugins/development.mdx (via @objectstack/spec)
  • content/docs/plugins/index.mdx (via @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/protocol/diagram.mdx (via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/runtime-capabilities.mdx (via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx (via @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v12.mdx (via @objectstack/spec)
  • content/docs/releases/v13.mdx (via @objectstack/spec)
  • content/docs/releases/v16.mdx (via @objectstack/spec)
  • content/docs/releases/v17.mdx (via @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/spec)
  • content/docs/ui/actions.mdx (via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx (via @objectstack/spec)
  • content/docs/ui/dashboards.mdx (via @objectstack/spec)
  • content/docs/ui/forms.mdx (via @objectstack/spec)
  • content/docs/ui/index.mdx (via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx (via @objectstack/spec)
  • content/docs/ui/setup-app.mdx (via @objectstack/spec)
  • content/docs/ui/translations.mdx (via @objectstack/spec)
  • content/docs/ui/views.mdx (via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

claude added 4 commits August 1, 2026 08:42
…-event-dual-source-v3jw3v

# Conflicts:
#	content/docs/references/kernel/metadata-persistence.mdx
The two baselines this branch edits by hand — `json-schema.manifest.json` and
`authorable-surface.json` — came out with `—` escaped as `—`, because the
edit went through Python's `json.dump`, whose `ensure_ascii` defaults to true.
`build-schemas.ts` writes them with `JSON.stringify`, which emits the character
literally.

No gate catches this: the manifest is only rewritten when the SCHEMA KEY SET
changes, so the escape would have sat in the file until the next PR that adds a
schema, where the generator would silently rewrite it back and hand that author
an unrelated one-line diff to explain.

Re-serialised with `ensure_ascii=False`. Both files now differ from main by
exactly the intended removals and nothing else: 11 manifest keys, 65
authorable-surface lines, zero incidental churn.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M9uWvoEp9CoLzYjNExj9sL
…-event-dual-source-v3jw3v

# Conflicts:
#	content/docs/releases/v17.mdx
@os-zhuang
os-zhuang merged commit cf2c9b7 into main Aug 1, 2026
18 checks passed
@os-zhuang
os-zhuang deleted the claude/metadata-watch-event-dual-source-v3jw3v branch August 1, 2026 10:10
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 protocol:system size/xl tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

spec 同名双源:两个 MetadataWatchEvent 形状不同、分挂两个子路径入口,其中 kernel 版零消费方(ADR-0049 enforce-or-remove)

2 participants