Skip to content

spec 缺一条「跨 barrel 同名导出」检查:api-surface.json 里同名跨入口目前可见但不报警(#4411 遗留裁决 2) #4446

Description

@os-zhuang

#4411 的第二条待裁决。那条 issue 由一次同名双源引发(MetadataWatchEvent 在 ./kernel 与 ./system 各一份、形状不同、kernel 版零消费方),已在 #4411 的 PR 里连同同文件另外 10 个同类一并退役。但产生这类问题的机制没有被堵上 —— api-surface.json 里同名跨入口是可见但不报警的,下一个同名双源仍会静默落地。

为什么这类缺陷特别值得机器来抓

它是只在 import 路径上分叉的缺陷:两份声明共用一个名字,靠 from '@objectstack/spec/<entry>' 区分。

一次 code review 很难看见它 —— 两个文件各自都是合理的。

当前实测基线(#4411 PR 合入后)

从 packages/spec/api-surface.json 直接算:

指标 #4411 前 #4411 后
跨子路径同名导出(name (kind) 出现在 >1 个非 . 入口) 103 83
其中在 >1 个源文件里各自声明的(真·多源,非 re-export) 70 待重算

复算脚本:

const s = require('./packages/spec/api-surface.json');
const map = new Map();
for (const [ep, list] of Object.entries(s).filter(([, v]) => Array.isArray(v)))
  for (const n of list) (map.get(n) ?? map.set(n, []).get(n)).push(ep);
console.log([...map].filter(([, eps]) => eps.filter(e => e !== '.').length > 1).length);

.(根入口)+ 子路径的组合要排除 —— 那是有意的 re-export,同一个符号。

设计要点(裁决时值得先看的几条)

  1. 按符号 identity 判定,不能只按名字。 83 条里绝大多数是同一个声明从两个入口可达(合法),真正的缺陷是两个不同声明共用一个名字。scripts/build-api-surface.ts 已经用 TS checker 解析 module symbol,拿到 declaration 位置来做同一性判断是可行的 —— 这也是这条检查唯一有价值的形态,只比名字会淹没在误报里。
  2. 需要 allowlist 基线。 剩余的真·多源不可能在一个 PR 里清完,得按 ratchet 模式落地(新增即失败,存量记账),形态参照 authorable-surface.json / check-type-check-coverage.mjs。
  3. 挂载点。 跟着 check:api-surface 走(同一个 TypeScript Type Check job,读 built dist/*.d.ts);注意 AGENTS.md 记的 stale-dist 陷阱同样适用。

已知的存量条目(建档,便于起基线)

  • MetadataFormat —— system/metadata-persistence.zod.ts(7 个成员,含 yml/ts/js 别名)与 shared/metadata-types.zod.ts(4 个成员)枚举分歧,两者都在导出面上。spec 同名双源:两个 MetadataWatchEvent 形状不同、分挂两个子路径入口,其中 kernel 版零消费方(ADR-0049 enforce-or-remove) #4411 只把 kernel 的第三份删掉了,这一对仍在。
  • contracts/metadata-service.ts 自有的 MetadataExportOptions / MetadataImportOptions interface —— 与 system/metadata-persistence.zod.ts 的同名 schema 第三形状,且有消费方,不是删得掉的死副本,需要单独判定哪边是真源。
  • system ↔ integration(ConsumerConfig、DatabaseProvider、MessageQueueProvider、MultipartUploadConfig)、system ↔ cloud(EnvironmentArtifact、TenantPlan)、kernel ↔ api(*PackageRequest/Response 一族)、ui ↔ shared(HttpRequest、HttpMethodSchema)等成组条目 —— 需逐组判定 re-export vs 真分歧。

待裁决

这条检查是否值得做、按什么优先级做,由维护者定(#4411 里已明确记为「值不值当由维护者定」)。开这条 issue 是为了不让那次裁决连同实测基线一起丢失。


关联:#4411(触发路径 + 已退役的 11 个同名双源)、#4404、#4251、#4393、ADR-0049

Activity

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions