feat(spec)!: 双源 C2 收敛 — MetadataEvent / MetadataBulkRegisterRequest 归 ./api,./kernel 侧死删 (#4587) - #4603
Merged
Conversation
…al source — ./kernel copies removed, ./api keeps the bare names (#4587) The three #4535-C2 baseline rows were the #4411 trap on the kernel metadata family: MetadataEvent(Schema) and MetadataBulkRegisterRequestSchema each had a second, different declaration in ./kernel, and which shape a consumer got depended only on the import path. Import-statement-level scan across framework, cloud and objectui: - ./kernel copies: zero importers outside their own unit test in all three repos. The kernel MetadataEvent lifecycle vocabulary (metadata.registered/.../exported) has NO producer anywhere; the kernel bulk-register per-item `namespace` field matches no enforced write path (IMetadataService.bulkRegister and MetadataManager.bulkRegister both take {type,name,data} items only). - ./api MetadataEvent is the live realtime contract: MetadataManager publishes metadata.{type}.{created|deleted} events and @objectstack/client / client-react subscribe against the type. - ./api MetadataBulkRegisterRequestSchema is the POST /api/meta/bulk/register contract whose item shape matches the runtime. Disposal (route 1, dead-side delete, v17 major window): both kernel copies removed; ./api is the sole owner of the bare names. Name continuity for the kernel-only type alias: `MetadataBulkRegisterRequest` (z.input) is now exported from ./api beside its schema, per the family convention and the #4570 docs-import concern. Compile-time pin (typeof import conditional type, #4581 pattern) keeps the bare names out of ./kernel; new events.test.ts covers the surviving ./api declarations. dual-source-exports.baseline.json: exactly the 3 named rows removed (31 -> 28). json-schema.manifest: kernel/MetadataEvent and kernel/MetadataBulkRegisterRequest retired deliberately; their 11 authorable-surface rows hand-deleted per the #4458/#4568/#4581 precedent (plugin TS types, schema bodies deleted — no silent-strip path, misuse fails at the import site at compile time). Changeset: @objectstack/spec major with FROM -> TO migration lines. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M9uWvoEp9CoLzYjNExj9sL
…:generated --fix, 2 proved stale) api-surface.json: ./kernel loses MetadataEvent(type)/MetadataEventSchema and MetadataBulkRegisterRequest(type)/MetadataBulkRegisterRequestSchema; ./api gains the MetadataBulkRegisterRequest type alias beside its schema. Reference docs: the api/metadata-plugin.mdx page (which documented the removed kernel pair under the api section and advertised a then-nonexistent ./api type import) is no longer emitted; api/events.mdx now documents MetadataEvent, api/metadata.mdx documents MetadataBulkRegisterRequest, and kernel/metadata-plugin.mdx drops the removed schemas. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M9uWvoEp9CoLzYjNExj9sL
…adata-event-dual-source
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
…rface gate (#4595) The merge brought in build-docs' new import-surface ratchet. This PR's MetadataBulkRegisterRequest type alias on ./api closes the gap the fresh baseline had accepted, so its line is deleted (shrink-only ratchet).
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 107 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
os-zhuang
marked this pull request as ready for review
August 2, 2026 10:02
os-zhuang
enabled auto-merge
August 2, 2026 10:03
This was referenced Aug 2, 2026
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Aug 3, 2026
…ai#4610) (objectstack-ai#4638) * feat(spec)!: resolve the notification-vocabulary dual sources — ./ui Notification(Config) removed, ./system NotificationConfig removed, ./api keeps the bare names (objectstack-ai#4610) The four objectstack-ai#4535-C3 baseline rows were the objectstack-ai#4411 trap on the notification vocabulary: Notification(Schema) had a second declaration in ./ui diverging from ./api, and NotificationConfig(Schema) had two declarations (./system vs ./ui) that shared nothing but the name. Import-statement-level scan across framework, cloud and objectui: - ./api Notification(Schema) is the live REST inbox-row contract: embedded in ListNotificationsResponseSchema, part of NotificationProtocol, implemented by @objectstack/client, served by the runtime notifications domain, and mirrored by contracts' InboxNotification (ADR-0030: the bell reads this shape). - ./ui Notification(Schema) — a toast/banner instance shape — had zero importers outside its own unit test; objectui pins only the presentation enums (NotificationType/Position/ActionSchema), which stay. - ./system NotificationConfig(Schema) — a channel+template+recipients+ schedule+retryPolicy+tracking wrapper — had zero importers, is wired into no parent schema, predates ADR-0030's accepted delivery model (NotificationService.emit / NotifyConfigSchema / sys_* objects), and advertised unenforced capability (objectstack-ai#3197 dead-letter channels). - ./ui NotificationConfig(Schema) — a toaster global config — had zero importers. Disposal (route 1, dead-side delete, v17 major window): the ./ui pair and BOTH NotificationConfig declarations removed; ./api is the sole owner of the bare Notification(Schema) names and NotificationConfig left the export surface entirely. Compile-time pins (typeof import conditional type, objectstack-ai#4581 pattern) keep the bare names out of ./ui and ./system; the surviving ./api declaration is already covered by api/protocol.test.ts. dual-source-exports.baseline.json: exactly the 4 named rows removed (28 -> 24). json-schema.manifest: system/NotificationConfig, ui/Notification and ui/NotificationConfig retired deliberately; their 25 authorable-surface rows hand-deleted per the objectstack-ai#4458/objectstack-ai#4568/objectstack-ai#4581/objectstack-ai#4603 precedent. api-surface + reference docs regenerated via check:generated --fix (2 proved stale; the api/notification.mdx page folds into api/protocol.mdx where the declaration lives). docs-import-surface baseline (objectstack-ai#4595): untouched. Changeset: @objectstack/spec major with FROM -> TO migration lines. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M9uWvoEp9CoLzYjNExj9sL * docs(audits): 严格性台账跟随 objectstack-ai#4610 —— ui/notification.zod.ts 站点 3 → 1 删除 ./ui 的 Notification / NotificationConfig 两个形状后,台账里 `notification.zod.ts` 那行声明的站点数过期(gate 点名 ledger:454: declares 3 site(s), found 1)。把它从「3 ea」的合并行拆出单列为 1, 并写明为何掉了两个站点;`ui/` 章节总计 200 → 198 相应收敛。 check:strictness-ledger 恢复绿(67 文件 / 5 目录,站点数与章节总计均衡); 同 job 的其余源码审计(liveness / empty-state / variant-docs / exported-any / react-declaration-parity / skill-examples)一并复跑通过。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M9uWvoEp9CoLzYjNExj9sL --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #4587
#4535 C2:基线 31 条中的 3 条 ——
MetadataEvent(Schema)/MetadataBulkRegisterRequestSchema在./api与./kernel各有一份不同声明,消费者拿到哪个形状只取决于 import 路径(#4411 陷阱)。issue 的「kernel 侧可能是 #4411 家族残留」线索,已按手册以 import 语句级扫描重新判定,未照抄前科。判真源:三仓 import 语句级扫描
framework(本仓)、
/workspace/cloud(HEADbce2bec)、objectui(浅克隆,HEADd3584c6):ResourceHistoryPage.tsx一行注释提及MetadataEvent[],指的是 metadata-core 的第三个同名概念,非消费)。./kernel侧三个名字:三仓唯一 importer 是自己的单测(metadata-plugin.test.ts)。packages/metadata从@objectstack/spec/kernelimport 了一串名字(MetadataQuery/MetadataBulkResult/…),不含这三个。./apiMetadataEvent(type):packages/client/src/realtime-api.ts与packages/client-react/src/realtime-hooks.tsx都import type { MetadataEvent } from '@objectstack/spec/api'—— 活的 SDK 合同。metadata.{type}.{created|updated|deleted}有真实生产者 ——MetadataManager的 register/unregister 路径向 realtime service 发布`metadata.${type}.created`/`.deleted`,client 的subscribeMetadata按同词表过滤。kernel 词表(metadata.registered/…/exported)在三仓零生产者、零消费者。@objectstack/metadata-core的MetadataEvent(ADR-0008 仓库变更日志事件)不在 spec 入口、不归本 gate 管,未触碰;handwritten docs(concepts/metadata-lifecycle.mdx、ADR-0008)引用的都是它,无需改。逐字段 diff(判定依据)
MetadataEvent(Schema)—— 同名两个信封,kernel 侧已死:./api(events.zod.ts)./kernel(metadata-plugin.zod.ts,已删)type: enummetadata.{13 类型}.{created|updated|deleted}(39 值)event: enummetadata.registered/updated/unregistered/validated/deployed/overlay.applied/overlay.removed/imported/exported(9 值)id(uuid,必填)、definition?、userId?namespace?、actor?、payload?(record)metadataType(z.string)、name、packageId?、timestampmetadataType为MetadataTypeSchema(枚举),其余同名MetadataBulkRegisterRequestSchema—— 同概念近重复,kernel 侧已死且偏离强制路径:./api./kernel(已删){type, name, data}{type, name, data, namespace?}continueOnError=false、validate=true完全一致MetadataBulkRegisterRequest = z.input(kernel 独有,不在基线)IMetadataService.bulkRegister与MetadataManager.bulkRegister的 item 形状都是{type, name, data},无 namespace —— 与 api 侧一致;namespace平台级弃用(军规 #6)处置(手册路线 1:死侧删除,v17 major 窗口)
./kernelMetadataEventSchema/MetadataEvent→ 死删。零消费方、词表零生产者。运行时 watch 事件另有MetadataWatchEvent(./system),不受影响。./kernelMetadataBulkRegisterRequestSchema/MetadataBulkRegisterRequest→ 死删。MetadataBulkResultSchema(活,packages/metadata消费)原地保留。./api两族原样不动,成为裸名唯一属主。唯一新增:./api补导出MetadataBulkRegisterRequest = z.input<…>类型别名 —— 名字延续到真源;该文件族本就每个 Schema 配推断类型(bulk 对是仅有的例外),且 build-docs 剥Schema后缀生成 import 示例(build-docs.ts 用「剥掉 Schema 后缀」推导 import type 示例,类型别名不存在时生成的文档引用无法编译 #4570),api/metadata 文档此前宣传的这个 import 现在真实存在。z.input保留 kernel 侧原语义(authoring 形状,continueOnError/validate可省略)。./api消费者零变化;从./kernel迁来的消费者(三仓实测为零)是形状变化:event/actor/payload/namespace字段不复存在、bulk item 不再接受namespace—— changeset FROM → TO 各带一行修法与形状差说明。typeof import('./metadata-plugin.zod')条件类型,feat(spec)!: 双源 C1 收敛 — WebhookConfig / WebhookEvent 归 ./integration,./api 侧死删 + 改名 OpenApiWebhookEvent (#4572) #4581 先例,不吃 vitest 超时)钉死 kernel 模块不再声明这两个裸名;./api幸存声明补了此前缺失的单测(events.test.ts:词表模式、client 订阅的三个事件名、kernel 退休词表不再 parse;metadata.test.ts:z.input 形状 + item 无namespace的类型级断言)。kernel/MetadataEvent、kernel/MetadataBulkRegisterRequest两键蓄意退休删行(gate 点名后删,非静默下架);authorable-surface 的 11 行按 refactor(spec)!: remove the kernel metadata-loader envelope family — 11 names declared twice with different shapes (#4411) #4458/feat(spec)!: contracts 手写 interface 与域内 zod 推导类型收敛(3 簇 11 名,#4535·A3) #4568/feat(spec)!: 双源 C1 收敛 — WebhookConfig / WebhookEvent 归 ./integration,./api 侧死删 + 改名 OpenApiWebhookEvent (#4572) #4581 先例手工删除(插件 TS 类型,schema 本体已删,不存在「父 schema 静默剥离」路径 —— 不适用 tombstone / D2 conversion,误用者在 import 处编译期即失败)。基线
dual-source-exports.baseline.json恰好删除 gate 点名的 3 行(31 → 28,不多删不漏删):MetadataBulkRegisterRequestSchema — [./api (const)] ≠ [./kernel (const)]MetadataEvent — [./api (type)] ≠ [./kernel (type)]MetadataEventSchema — [./api (const)] ≠ [./kernel (const)]验证
pnpm --filter @objectstack/spec build✅check:dual-source-exports✅(self-test 通过;4308 名字 / 16 入口,基线 28)check:generated8/8 up to date ✅(api-surface + reference docs 经--fix定向再生,单独 commit;api-surface 净变化:kernel −4、api +1)typecheck✅;spectest288 文件 / 7274 用例全过 ✅pnpm build71/71 ✅、pnpm typecheck122/122 ✅、pnpm test132/132 ✅(首轮 service-datasource 的 sqlite-wasm 文件回环用例在并行负载下超时一次 ——/tmpmkdir ENOENT,环境性;单跑 197/197 全过,复跑全仓 132/132 绿,与本改动无关)origin/main(b3235b5,来向不触 spec)后按 §10 范围复验:spec build +check:generated8/8 + 基线 28 复确认 ✅Changeset
@objectstack/specmajor:两条 FROM → TO 迁移(kernelMetadataEvent→ api,含形状差与MetadataWatchEvent/metadata-core 的指路;kernelMetadataBulkRegisterRequest(Schema)→ api,含namespace不再 parse 与 z.input 语义说明)。不改content/docs/releases/。范围外发现
subscribeMetadata把RealtimeEventPayload信封as any as MetadataEvent硬铸交给订阅者,声明的顶层name/metadataType/definition运行时嵌在payload里、id/userId从不生成。本 PR 只消歧命名归属,不改 realtime 行为;该单给出生产者履约 vs 合同如实两个方向待裁决。🤖 Generated with Claude Code
https://claude.ai/code/session_01M9uWvoEp9CoLzYjNExj9sL
Generated by Claude Code