Skip to content

spec 双源 C2:MetadataEvent / MetadataBulkRegisterRequestSchema —— ./api ≠ ./kernel(3 条,#4535 C 组) #4587

Description

@os-zhuang

父单:#4535(C 组第 2 簇)。packages/spec/dual-source-exports.baseline.json 现存 31 条中的 3 条:

MetadataBulkRegisterRequestSchema — [./api (const)] ≠ [./kernel (const)]
MetadataEvent — [./api (type)] ≠ [./kernel (type)]
MetadataEventSchema — [./api (const)] ≠ [./kernel (const)]

同名 schema + 推断类型在 ./api 与 ./kernel 各有一份不同声明 —— 消费者拿到哪个形状只取决于 import 路径(#4411 陷阱)。

背景提示(判定时核实,不要照抄):./kernel 的 metadata 家族有死副本前科 —— #4411/PR #4458 已删过 11 个零消费的 kernel metadata-loader schema,A1(#4536)也证伪过 kernel 侧枚举的虚胖成员。本簇的 kernel 侧很可能同属该家族残留,但必须按 import 语句级扫描重新判定,不得凭前科直接下结论。

任务

  1. 先判真源(contract-first):import 语句级扫描三仓(本仓 + cloud(/workspace/cloud 若在)+ objectui 浅克隆),不要用名字出现次数。两份声明逐字段 diff:形状差异、语义差异、各自消费方,判定结果写进 PR 正文。
  2. 处置三选一(按 ✅ spec 双源清账主单:基线 52 → 0(2026-08-03 收官)—— #4446 gate 落地后的偿还 worklist #4535 手册):死侧零消费方 ⇒ 直接删(v17 rc 是 major 窗口);两侧都活且同概念 ⇒ 收敛到真源 + 另一侧 re-export(re-export 不会被 gate 报);真是两个概念 ⇒ 改名一侧(先例:[#4535·B] 跨形态同名三条:ShareRecipientType(type≠const)、TransformType(const≠type)、suggestFieldType(双实现 function) #4539 → PR feat(spec)!: 跨形态同名三条收敛 — ShareRecipientType / TransformType / suggestFieldType (#4539) #4571、spec 双源 C1:WebhookConfig / WebhookEvent —— ./api ≠ ./integration(4 条,#4535 C 组) #4572 → PR feat(spec)!: 双源 C1 收敛 — WebhookConfig / WebhookEvent 归 ./integration,./api 侧死删 + 改名 OpenApiWebhookEvent (#4572) #4581 的 OpenApiWebhookEvent)。
  3. 收敛 ≠ 无行为变化:若存活形状比被删侧窄/宽,消费方类型会变 —— 逐字段核实并写进 changeset;拿不准的分歧用编译期 pin(typeof import 条件类型,PR feat(spec)!: 双源 C1 收敛 — WebhookConfig / WebhookEvent 归 ./integration,./api 侧死删 + 改名 OpenApiWebhookEvent (#4572) #4581 先例 —— 优先于运行时动态 import pin,不吃 vitest 超时)。

验收

  • 基线恰好 −3(31 → 28):check:dual-source-exports stale 分支点名的即这 3 行,不多删不漏删
  • check:generated 8/8 up to date(api-surface 等经 --fix 定向再生,单独 commit)
  • spec build / typecheck / test 全绿;全仓 pnpm build / pnpm typecheck / pnpm test 全绿
  • changeset:@objectstack/spec major,FROM → TO 迁移行;不改 content/docs/releases/(releases-freeze,见 CLAUDE.md);手写文档若引用被改名/删除的导出,一并修正
  • 若触及可作者化 metadata key 的形状,回 spec-property-retirement skill 走完整流程
  • 范围外发现按第十条军规立 unassigned issue,不夹带进本 PR

工作方式

专用 worktree(git worktree add ../objectstack-issue-<本单号> -b claude/issue-<本单号>-metadata-event-dual-source main)→ 实现 → 推分支 → draft PR(正文含逐条判定 + 验证清单)→ 向 PM 返回 JSON 报告。

Activity

  1. self-assigned this
    on Aug 2, 2026
  2. os-zhuang commented on Aug 2, 2026

    @os-zhuang
    ContributorAuthor

    PM 审阅:ACCEPT — PR #4603 已转正式并进入合并流程(squash)。

    逐项核验结果:

    1. MetadataEvent(Schema) kernel 侧死删:我在 main 上独立复核 —— packages/client/src/realtime-api.ts:11 确认 api 侧是活的 SDK 合同;kernel 词表(metadata.registered/…)全仓 grep 仅命中其自身声明文件,零生产者。逐字段 diff(9 值 event 信封 vs 39 值 type 信封)证实是两个不同信封共名,api 侧为唯一真源。
    2. MetadataBulkRegisterRequestSchema kernel 侧死删 + 类型别名归位:kernel 侧多出的 per-item namespace 不在任何强制写路径(IMetadataService.bulkRegister / MetadataManager.bulkRegister 均为 {type, name, data}),且 namespace 平台级弃用;./api 补 z.input 别名延续名字,文档 import 示例此前宣传的导出现在真实存在。
    3. 手写文档零涉及(metadata-lifecycle.mdx 等引用的是 metadata-core 的第三概念,不归本 gate 管,未触碰,判定正确);releases 页零涉及;编译期 pin 沿用 feat(spec)!: 双源 C1 收敛 — WebhookConfig / WebhookEvent 归 ./integration,./api 侧死删 + 改名 OpenApiWebhookEvent (#4572) #4581 模式;新增 events.test.ts 补上幸存声明此前缺失的词表测试。
    4. 合并冲突已由 PM 处理:开 PR 后 main 合入 fix(#4570): reference 页的 import 示例改由真实导出面生成,并加只减不增的棘轮兜底 #4595(恰是本流水线 B 组立案的 build-docs.ts 用「剥掉 Schema 后缀」推导 import type 示例,类型别名不存在时生成的文档引用无法编译 #4570 的修复 —— build-docs 新增 import-surface ratchet 并重生成全部 reference docs)。按生成物冲突手册取 main 版本后用修复过的生成器重跑:本 PR 新增的类型别名恰好关掉了新基线里 api/MetadataBulkRegisterRequest — no type export 这条 gap,按 shrink-only 规则删除该行(154 → 153)。复验:check:generated 8/8、双源 gate 基线 28、spec typecheck 全绿。

    基线恰好 −3(31 → 28);范围外立案 #4602(client realtime declared ≠ enforced,subscribeMetadata 的 as any 硬铸 —— 我复核时在 realtime-api.ts:72 直接看到了该铸型,立案有据)。

    两个流水线自产的成果在本轮闭环:#4570(B 组立案)→ #4595(修复)→ 本 PR 吃到它的 ratchet 并让基线再 −1。


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions