Skip to content

Commit bd2fb98

Browse files
committed
fix(spec): manifest 删行相对 merge-base 自证 —— 整 schema 消失不再只是纪律 (#4725)
`json-schema.manifest.json` 的 #2978 ratchet 对删行的全部要求是一句注释 ("remove a key ONLY for a deliberate retirement"),没有任何机器校验。它的 `missing` 集合是「manifest − 本次产出」,而 manifest 是同一个 commit 里可以随手 改的文件:把导出、manifest 行、基线行一起删掉,`missing` 恒空;检查 (c) 又以 「def 已不再产出」为由放行它名下的每一行(那一条出口原话就写着交给 manifest 裁 判);`check:api-surface` 只是新鲜度门。三个门,一句话都不说。 实测(修复前):删掉 src/data/index.ts 一行 `export * from './validation.zod';` —— ObjectSchema 直接从该模块导入 ValidationRuleSchema,所以 7 个 def 依旧从 `object` 元数据根可达 —— gen:schema 与 check:authorable-surface 双双 exit 0, 116 个 authorable key 静默离开契约。 - 新增 manifest deletion gate:相对 merge-base(HEAD, origin/main) 的 manifest 计算「离开已发布集合」的 def,跑在检查 (c) 之前。 - 新增导出 RETIRED_DEFS_BY_MAJOR(per-DEF,精确集合判定,#4659 先例)+ 镜像检查 (登记了一个仍在发布的 def 直接失败)。RENAMED_DEFS 前置豁免。 - 不复用 #4650 的可达性:reachableVia() 从 zodByDefKey 取实例,该表只装本次构建 产出的 def,刚被删的 def 必然答 null(「不可达 ⇒ 放行」)。 - 离线沿用 #5235 姿态:镜像照跑,比较打印说明并跳过。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01559M8FVm6W6vDLABL3jvdW
1 parent 72bd873 commit bd2fb98

7 files changed

Lines changed: 789 additions & 21 deletions

File tree

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
"@objectstack/spec": patch
3+
---
4+
5+
fix(spec): manifest 删行不再是纪律 —— 整 schema 消失必须相对 merge-base 自证 (#4725)
6+
7+
#4650 堵住了 `authorable-surface.json` 的手编删行捷径:被删的基线行现在必须在门禁
8+
内自证。但它把「整 def 消失」这条路交给了 `json-schema.manifest.json`#2978
9+
ratchet —— 检查 (c) 的第 3 条出口至今原话写着「whole-schema removals are
10+
adjudicated by json-schema.manifest.json」。**那个 ratchet 什么也没裁判。** 它的
11+
`missing` 集合是「manifest − 本次产出」,而 manifest 是**同一个 commit 里可以随手
12+
改的文件**:把导出、manifest 行、基线行一起删掉,`missing` 恒空,检查 (c) 又以
13+
「def 已不再产出」为由放行它名下的每一行,`check:api-surface` 只是新鲜度门(重新
14+
生成即绿)。三个门,一句话都不说 —— 和 #4650 修复前的形状同构,只是上移了一层。
15+
16+
实测(修复前,在测试沙箱里跑真源码):删掉 `src/data/index.ts`**一行**
17+
`export * from './validation.zod';` —— `ObjectSchema` 是直接从 `./validation.zod`
18+
导入 `ValidationRuleSchema` 的,所以这 7 个 def 依旧从 `object` 元数据根**可达**
19+
它们的 116 个 key 依旧被作者书写、依旧被解析 —— `gen:schema`
20+
`check:authorable-surface` **双双 exit 0**,消失的只是它们的 JSON Schema、
21+
manifest 行,以及 ratchet 对它们的全部记录。
22+
23+
现在按 #4650 的同一结构重新锚定:
24+
25+
- **新增门禁「manifest deletion gate」**(`scripts/build-schemas.ts`):相对
26+
**merge-base(HEAD, origin/main) 的 manifest** —— 本次 commit 改不动的那一份 ——
27+
计算「离开已发布集合」的 def,每一个都必须有登记,否则红。它跑在检查 (c) **之前**,
28+
所以 (c) 那句「交给 manifest 裁判」从此指向一个真的会出裁决的地方。
29+
- **新增导出 `RETIRED_DEFS_BY_MAJOR`**(`@objectstack/spec`,
30+
`src/migrations/registry.ts`):`RETIRED_KEYS_BY_MAJOR` 的上一层同胞,值是确切的
31+
`` `${category}/${SchemaName}` `` —— manifest 里怎么写就怎么写。沿用 #4659
32+
精确集合判定:不取叶名、不按前缀、不从相邻条目辐射。门禁失败时直接打印要粘贴的
33+
那几行和它们该进哪个 major。
34+
- **镜像检查**:表里登记了一个本次构建**仍在发布**的 def —— 一次没有任何东西消费的
35+
登记 —— 直接失败,否则真正的删除可以在几个月后的别人的 PR 里落地,而门禁早已被
36+
满足、当时没有任何人写下任何东西。
37+
- 改名不是退休:`RENAMED_DEFS`(`scripts/lib/renamed-defs.ts`)在这张表之前被查,
38+
一次改名不需要、也不允许写进这里 —— 那是在谎称契约收缩了。
39+
40+
**为什么是「声明」而不是「可达性」。** issue 建议复用 #4650 的可达性 BFS(「该 def
41+
从元数据根不可达」)。这条在本层用不了,而且是**静默地**用不了:`reachableVia()`
42+
`zodByDefKey` 取实例,而那张表只装**本次构建产出**的 def —— 一个刚刚不再产出的 def
43+
必然答 `null`,也就是「不可达 ⇒ 放行」,正对着这道门要拦的那一类删除。加宽 BFS 也救
44+
不了:def 已经从源码里没了,没有图可以走。所以本层唯一诚实的证据是声明,沿用 #5902
45+
为 key 层定下的先例。
46+
47+
**离线沿用 #5235 的既有姿态,不新造第三种**:镜像检查不需要 git,任何环境都跑;
48+
比较本身在解析不到 origin/main 时打印说明并跳过 —— 那些环境是已合并的不可变树
49+
(镜像构建阶段、离网、fork、历史 tag 重放),「这个 PR 相对 main 删了什么」在那里
50+
不是一个存在的问题,跳过不会让任何构建失败,因此不需要为它再加一个 in-tree 锚点。
51+
52+
`json-schema.manifest.json` 自己的描述同时更新了(并纳入陈旧判定,不会再漂移):
53+
它此前写的「remove a key ONLY for a deliberate retirement」正是 issue 引用的那句
54+
「唯一的要求,且没有任何机器校验」;现在它指向这道门和这张表。

packages/spec/api-surface.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
"PredicateInput (type)",
9292
"PredicateInputSchema (const)",
9393
"PredicateSchema (const)",
94+
"RETIRED_DEFS_BY_MAJOR (const)",
9495
"RETIRED_KEYS_BY_MAJOR (const)",
9596
"STACK_KEY_GUIDANCE (const)",
9697
"STACK_RUNTIME_MEMBERS (const)",

packages/spec/json-schema.manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"description": "Ratchet manifest of every JSON Schema emitted by scripts/build-schemas.ts. Auto-appended when new schemas are added (commit the change). A listed schema that a build no longer emits fails gen:schema — remove a key ONLY for a deliberate retirement. See #2978.",
2+
"description": "Ratchet manifest of every JSON Schema emitted by scripts/build-schemas.ts. Auto-appended when new schemas are added (commit the change). A listed schema that a build no longer emits fails gen:schema. DELETING a key is gated too (#4725): the removal is measured against this file at the merge base with origin/main — which the commit under test cannot rewrite — and every def that leaves the published set must be declared in RETIRED_DEFS_BY_MAJOR (src/migrations/registry.ts), or in RENAMED_DEFS (scripts/lib/renamed-defs.ts) when it is a rename rather than a removal. See #2978, #4725.",
33
"schemas": [
44
"ai/AIModelConfig",
55
"ai/AIUsageRecord",

0 commit comments

Comments
 (0)