fix(spec): shared/http.zod.ts 的两个不同 enum 不再发布成同一个 def key —— 7 值 HttpMethod 拿回裸名,5 值子集改名 HttpMethodSubset,build-schemas 补硬报错守卫 - #5976
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 111 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
This was referenced Aug 6, 2026
qq9340100
marked this pull request as ready for review
August 6, 2026 13:58
This was referenced Aug 6, 2026
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 #5832
前提复现(动手前先对 origin/main 实测)
issue 三条复现命令逐条跑过,前提成立,行号与代码形状也与 issue 一致:
顺带把碰撞面量全了(按
build-schemas.ts同样的枚举顺序遍历 15 个命名空间):全仓 15 个 def key 被写第二次,其中 14 个是
export const X = XSchema自别名(两次写的是同一个对象,发布物逐字节相同),只有shared/HttpMethod是两个真正不同的 schema。这条量测直接决定了守卫的判据(见下)。
改了什么
1. 5 值受限子集改名(裁 1,照 #4684
RateLimitConfig先例)HttpMethodSchemaHttpMethodSubsetSchemaHttpMethodTypeHttpMethodSubsetshared/HttpMethod(覆盖了 7 值那份)shared/HttpMethodSubsetui/HttpMethodui/HttpMethodSubset7 值的
HttpMethod一字未动,拿回它本来的裸名。实测发布物:content/docs/references/shared/http现在同时有HttpMethod(7 值,含HEAD/OPTIONS)与HttpMethodSubset(5 值)两节,各带一句.describe()说明谁用在哪 —— 这是本单要修的用户可见面。为什么类型别名也跟着改。 裁定里提到「其类型别名已是
HttpMethodType」,我本来只想改 const。实测拦住了:scripts/lib/docs-import-surface.ts要求每个发布名N在自己的入口点有一个同名类型导出,否则记一条no type exportgap,而docs-import-surface.baseline.json是只减不增的 ratchet —— 只改 const 而发布名叫HttpMethodSubset会新增两条 gap,check:docs直接红。所以按裁定里「沿仓内命名惯例定名」执行:发布名 / schema const / 类型别名三者对齐成一个名字(ADR-0112 D9「一个名字只指一件事」)。HttpMethodType当年(#4691)只是因为HttpMethod被占用才起的名字,不是一个自带含义的名字;#4691 那条 pin 的论证一字未改,只换了拼写。2. 选项 3 守卫:同一个 def key 被第二次写 = 硬报错
新增
packages/spec/scripts/lib/def-key-collisions.ts,在build-schemas.ts的生成循环之后、两个 ratchet 之前跑(它们都以 def key 计量,碰撞只产生一个 key,谁也看不见)。判据是实例同一性,不是当天的字节相等:
这正好放行上面量到的 14 处
export const X = XSchema自别名(第二次写的是同一个对象,不可能改变发布出去的内容),而拦住两份独立声明 —— 哪怕它们今天序列化结果相同,下一次改动其中任何一份都会让发布物重新取决于导出枚举顺序,而那正是本单的失效模式。为什么没有收口到 #4696 的同一个工具函数(裁定要求说明):#4696 的
scripts/lib/schema-index.ts判的是源码文本 —— 正则扫.zod.ts,按「文件/页面 slug」决定归属;它的冲突判据是「同一 category 内两个文件声明同名」。HttpMethod与HttpMethodSchema在同一个文件里,对它就是同一条目,天然看不见。而build-schemas.ts拿到的是运行期的值(命名空间对象里的z.ZodType实例),判据只能是实例同一性。两者输入类型不同、判据不同,没有可收口的公共函数。能收口的那一半已经收口了:def key 的拼法(schemaNameFromExportKey)两边共用同一个scripts/lib/schema-name.ts(#4592 定下的单一来源),所以两个生成器对「什么是一个 def key」永远不会漂开。错误文案里也互相点名。3.
RENAMED_DEFS登记只登记
ui/HttpMethod -> ui/HttpMethodSubset:./ui只 re-export 了子集,所以ui/HttpMethod确实离场了(0 key 结转,枚举 def 没有 authorable 属性)。shared/HttpMethod故意不登记 —— 它仍在发出,只是内容从 5 值变回源码一直声明的 7 值;checkRenameTable会把它判成「这是复制不是改名」而拒绝,判得对。反向验证(方向在跑之前就写死了:红)
把删掉的肢体接回去 —— 在
HttpMethodSubsetSchema旁边重新声明HttpMethodSchema(而不是把新名字改回去:那样ui/view.zod.ts的 import 会断,脚本在模块加载期就死,红得毫无意义),然后跑真gen:schema:要点两条:恰好 1 条(14 处自别名全绿,守卫可用),而且它停在 ratchet 之前(输出里没有任何
json-schema.manifest.json字样)。恢复后gen:schema/gen:openapi/check:generated全绿。这段反向验证还被固化成了常驻测试(scripts/def-key-collisions.test.ts最后一例,在沙箱里 copy 一份src/改完真跑子进程)—— 理由同 #5168:一个从未被观测到红过的门禁,不能算门禁。跨包消费者(裁定要求如实列出)
本仓
packages/spec之外没有任何HttpMethodSchema/HttpMethodType的消费点(只有 CHANGELOG、content/docs/references/**生成物与 release notes 提到)。兄弟仓
objectui有两处,本 PR 不跨仓改,已另开 issue 跟踪(不改跨包语义,只跟名):packages/types/src/zod/objectql.zod.ts:26,41—import { HttpMethodSchema as SpecHttpMethodSchema }packages/types/src/objectql.ts:44—export type { HttpMethodType as HttpMethod }两处都只在 objectui 升到下一个
@objectstack/spec发布版时才需要跟名。验证
pnpm --filter @objectstack/spec test— 324 files / 8275 tests passedpnpm --filter @objectstack/spec typecheck—tsc --noEmit+check:test-typecheck全绿pnpm --filter @objectstack/spec check:generated— 10/10 绿(merge origin/main 之后重跑仍 10/10)check:dual-source-exports(4218 names / 0 new)、check:exported-any、check:generated --reconcile-only、check:adr-anchors、check:nul-bytes全绿docs-import-surface.baseline.json少了一行(ui/HttpMethod — no type export)—— ratchet 只减不增的减方向,由--update-import-baseline生成;该文件仓内是 ASCII 转义编码而生成器写原始字符,为了让 diff 只剩这一行真实变化,内容取生成器输出后按仓内既有编码惯例重新序列化(内容 100% 来自生成器,门禁读的是JSON.parse后的条目,与编码无关)。对兄弟单的影响(必答)
build-openapi.ts摘段)—— 完全无影响。build-openapi.ts里HttpMethod、schemaNameFromExportKey、json-schema/def key 三个都 grep 不到,它与本单改动零交集。HierarchyScopeContext未声明organizationId/tenantId哪个权威 —— producer 只填一个、consumer 只读另一个,两边都「符合契约」 #5858(HierarchyScopeContext契约 doc)—— 完全无影响。 它在packages/spec/src/contracts/sharing-service.ts:396,是纯 TS interface,不产生 def key,与 HTTP 方法词表无关。两单都不因本 PR 变简单、变难或变得不必要。
Generated by Claude Code