fix(spec): authorable-surface 被删基线行必须自证合法 — merge-base 锚定 + 可达性窄例外 (#4650) - #4726
Merged
Merged
Conversation
…elves (#4650) Check (a) reads authorable-surface.json from the commit under check, so hand-deleting a baseline line deleted the evidence it runs on (#4638, #4643 landed exactly that way; #4662 proved the file was hand-edited). gen:schema / check:authorable-surface now add check (c): every key present at the merge base with origin/main but absent from this build must carry one of three in-gate proofs — 1. aged-out tombstone: base entry [RETIRED] + an ADR-0087 conversion/migration registered >= 2 majors ago; 2. def not reachable from the metadata-type roots (2026-08-02 ruling): BFS over the build's in-memory Zod graph from BUILTIN_METADATA_TYPE_SCHEMAS + EXTRA_METADATA_TYPE_SCHEMAS, with derived-clone bridging so .refine()/.extend() copies keep their originals protected; waives ONLY this file's tombstone requirement; 3. whole def no longer emitted (manifest ratchet / api-surface jurisdiction). Anchoring on the merge base (not HEAD) keeps the check alive in CI, where HEAD is the PR's own commit and a HEAD-relative diff is always empty. --check further rejects any byte of the file that is not the generator's output (#4662 description drift class); write mode regenerates it. Checks (a0)/(a)/(b) unchanged and pinned by tests. Fixes #4650 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0176qgxgCXTJCUv4YFLtusP9
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckNo hand-written docs reference the 0 changed package(s). ✅ |
os-zhuang
marked this pull request as ready for review
August 2, 2026 23:52
os-zhuang
enabled auto-merge
August 2, 2026 23:52
This was referenced Aug 3, 2026
Closed
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 #4650
改动仅三个文件:
packages/spec/scripts/build-schemas.ts(门禁本体)、packages/spec/scripts/build-schemas-check-mode.test.ts(单测)、一个 changeset。零生成物改动、零src/改动(只读 importkernel/metadata-type-schemas的两个公开访问器),与 A 道 #4691 文件互斥。写模式与--check在本分支上跑完后git status --porcelain只剩这两个脚本文件——生成器输出与已提交工件逐字节一致。一、检查语义边界表
--check红 / 写模式重写(c) 的判定集合是「merge-base 基线有、本次构建不再发出」的 key(先经 RENAMED_DEFS 携带,rename 不会被误读为删除)。每个这样的 key 必须命中三条证明之一,全部门禁内实算:
[RETIRED],且其 surface 在CONVERSIONS_BY_MAJOR/MIGRATIONS_BY_MAJOR的登记 major 距当前 ≥ 2(取最早登记;子句匹配沿用检查 (b) 的/拆分 + 叶名后缀规则,build-schemas.ts 检查 (b) 用叶名匹配 conversion surface —— 无关簇的.type就能让一个 tombstone 冒充「已登记迁移」 #4659 记录的共同弱点不在本单扩大);json-schema.manifest.jsonratchet(gen:schema silently drops PageTabsProps since #2967 — references regen would delete real docs #2978)与check:api-surface管辖,本门禁放行并逐 def 打印提示。二、CI 基准选择(为何不空转)
issue 草案的
git show HEAD:在 CI 里恒等自比(HEAD 就是 PR commit)。本实现:merge-base(HEAD, origin/main)。origin/main缺失时脚本自行git fetch --quiet --depth=1 origin +refs/heads/main:refs/remotes/origin/main——lint.yml 的 typecheck job 是默认浅检出(无分支 ref),不必改 workflow;浅历史走不到公共祖先时回退 origin/main tip(PR 合成 merge commit 的 parent1 即该 tip,语义等价);三、Sabotage 证据(均为真实命令输出)
1. 修复前复现(worktree:临时删掉
src/data/object.zod.ts的iconprop + 手删基线行data/Object:icon,均已还原):2. 修复后同一 sabotage 红,错误指向 #4650;已提交后再跑同样红:
3/5. 不可达 def 删行绿(打印判定来源)、aged-out tombstone 删行绿、整 def 消失绿(沙箱:把待删行注入 base commit、PR commit 删除——与真实攻击集合等价;
data/Object:compactLayout登记于 major 11,历史真实的 aged-out 案例):4. 可达且无 tombstone 的行 → 红:见上
data/Object:icon;单测另覆盖「retired 但未登记」「retired 已登记但未满 2 majors(动态取 major 17 的skill.triggerPhrases,fixture 老化会响亮失败提示换选)」两个红分支。6. 检查 (a) 原语义仍在:单测「a key the BUILD stops emitting while still recorded is fatal before (c) ever runs」——文件仍记录、构建不再发出 → (a) 红,(c) 不吞。
7.
--check零写入:8. 单测:12 passed(5 存量 + 7 新增,新增覆盖上述全部分支);全量 spec suite:
沙箱本身就是真 git 仓库 + 伪造的
refs/remotes/origin/main——不加任何 test-only env 缝,门禁跑的就是 CI 跑的 git 解析路径。四、可达性 BFS:根集合与图来源
listMetadataTypeSchemaTypes()+getMetadataTypeSchema()=BUILTIN_METADATA_TYPE_SCHEMAS(当前 24 个)∪EXTRA_METADATA_TYPE_SCHEMASoverlay,门禁内每次实算,禁 PR 描述人工论证;gen:schema发出每个 def 时同步记录其 Zod 实例)。遍历对 def 做泛型深走(shape/options/in/out/element/innerType/keyType/valueType/数组/Map),另加两条 def 走不到的边:z.lazy的getter()、check-clone 的_zod.parent;.refine()/.extend()/.strip()克隆与原 def 无 identity(extend/strip 连 parent 链都没有),但共享逐属性 schema 实例。任一「(属性名, 实例) 对」出现在已访问对象节点的 shape 里 ⇒ 该 def 记为可达。ui/View正是实证:ViewMetadataSchema内嵌的是ViewSchema.refine(…)克隆,纯 identity BFS 会把ui/View误判不可达并放走它的删行——桥接后受保护。误差方向 fail closed(顶多多要一个 tombstone,绝不静默放行);shared/RateLimitConfig、shared/FieldMapping、automation/DataSyncConfig、integration/DataSyncConfig均不可达(评论 1 的静态近似认为 RateLimitConfig / FieldMapping 可达)。原因:import 边不等于 Zod 引用边(24 根里没有 endpoint/connector/manifest 类型,api/endpoint.rateLimit不在根图上)。门禁按裁决用真图并逐条打印判定;若维护者认为某簇应受保护,加根或加显式 Zod 引用即可,门禁自动跟进。五、残余风险(诚实声明)
.type就能让一个 tombstone 冒充「已登记迁移」 #4659,本单不扩大。六、changeset 定级:patch
纯构建期门禁收紧:无运行时 export、无 schema 形状、无生成物变化,npm 消费者唯一可见的是 CHANGELOG 条目。issue 的
protocol:breaking标签是问题域标注(本门禁保护的是 protocol-breaking 类删除),不使本 PR 本身成为 breaking。七、评论 2 扩展项(非新增的 description/格式改动):已做
--check现在比对整个文件字节与生成器规范输出:keys 相同但字节不同(description 手改、缩进、重排)→ 红,信息指向 #4662/#4650;写模式自动重写为规范形。已提交工件与规范形逐字节一致(实测),因此本 PR 落地时该检查零噪声。范围仅 authorable-surface.json(manifest 的同类问题归 #4725 评估)。🤖 Generated with Claude Code
https://claude.ai/code/session_0176qgxgCXTJCUv4YFLtusP9
Generated by Claude Code