docs(adr),chore(devx): tombstone ADR-0107 — 撤回后退役的编号,附考古证据 (#6676) - #7316
docs(adr),chore(devx): tombstone ADR-0107 — 撤回后退役的编号,附考古证据 (#6676)#7316os-project-manager wants to merge 1 commit into
Conversation
…#6676) docs/adr/ ran 0106-* straight to 0108-*. Archaeology on full history (9,829 commits, clone verified unshallowed) settles which of the three cases it is: the number was DRAFTED AND WITHDRAWN, not lost and not never-assigned. 53d37f1 (#3716) 2026-07-28 00:25 +0800 adds 0107-hook-body-write-set- accepted-static-gap.md, Proposed 3bb382b (#3735) 2026-07-28 09:24 +0800 owner decision deletes it; #3700 closed as not planned Nothing else ever claimed the number: `git log --all --diff-filter=AD -- 'docs/adr/0107*'` returns exactly those two commits, `-S'ADR-0107'` five (both of the above, the two later gate commits, #6634), `-S'0107' -- docs/` the same two. No restoration is wanted — and one would be actively wrong: the withdrawn record's D2 declared "no heuristic source analysis" a PERMANENT posture, and c1d44f7 (#4271, 2026-07-31) reversed exactly that, shipping the parser-based `hook-body-write-unknown-field` lint. Its subject says so: 从 accepted gap 变 为作者时 lint 告警. So: a tombstone, recording the withdrawal, the later reversal, and the archaeology, so the next reader does not redo it. The gate edit is forced by the tombstone, not scope creep. #6634 had grandfathered the bare number onto `UNRESOLVED_ADR_CITATIONS`, which is audited in BOTH directions — a number that gains a record fails the entry as stale. Removing it is the (a) remedy the gate's own dangling-citation message recommends over the allowlist, and it is strictly stronger: the entry would have expired on its own once the withdrawal changeset is consumed by a release (direction B: "nothing cites it any more"), quietly re-freeing the number, whereas a record makes re-use collide in the number-uniqueness audit. Reverse-verified in both directions, predicted before running: - tombstone removed, entry stays removed -> RED, "ADR-0107 is cited by 3 file(s) but names no record", fix (a) named in the message - tombstone kept, entry restored -> RED, "entry for 0107 is stale — docs/adr/ now HAS a record" Gates: check:adr-anchors OK (119 decision numbers, 20916 citations resolve), check:adr-links OK (532 destinations), check:nul-bytes OK, check:doc-authoring OK (375 files), check:empty-changeset OK, eslint clean. No changeset: docs/adr/** and scripts/** ship in no published package, so this releases nothing — the `skip-changeset` label is the documented route and an empty-frontmatter changeset is rejected by check:empty-changeset (#5471). Fixes #6676 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F8q5J1MQyocgtNspb15fSn
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
|
PM 验收:实质 ACCEPT。唯一的红是设计如此的人工门 —— ⛔ 无可修,等维护者。 红的那一项不是缺陷
这正是派单里原文照抄的落地约束的门禁形态 —— 推与开草稿 PR 都合规,只有 merge 被保留。按 drive-to-green 纪律,这类阻塞的正确动作是回帖说明而不是推"修复":任何让它变绿的改动都是在削弱门禁。⛔ 未武装 auto-merge、未入队。其余 23 项中 考古 —— 我独立抽验过,不是采信报告dev 报告尚未送达,下列事实是我自己在
三岔判定正确:这是「撤回」,不是「丢失」,更不是「从未分配」—— 删除是有意的、理由写在撤回提交里。派单里把「把从未分配写成已撤回」定为一票否决,因为那等于在决策日志里伪造历史;这里的方向相反且有据,墓碑写的是事实。 没有复活它,而且给出了不该复活的硬理由:该记录的 D2 宣称"永不用启发式源码分析"是永久立场而非延期,而三天后 #4271 的 范围纪律:碰了
|
|
验收转为无条件:上贴挂起的两项已转绿 —— 我上贴对
|
Fixes #6676
结论先说:是「起草后撤回」,不是丢失,也不是从未分配
卡片列了三种可能,考古结果唯一且无歧义:ADR-0107 曾经真实存在于
main上九个小时,随后被 owner 决定删除。53d37f1ae(#3716)3bb382b67(#3735)c1d44f7dc(#4271)check-adr-anchors的引用 allowlist 上过渡我搜了什么,以及为什么负结果是可信的
先确认克隆不是浅克隆(9,829 commits;#6634 曾被 106 commit 的浅克隆误导过,会把「从未存在」当成事实答出来):
没有第二个东西曾经占用过这个编号——任何分支、任何时间点都没有。所以不存在「两个 ADR-0107 时代」这一停止条件。被撤回的正文也没有丢,
git show 53d37f1ae:docs/adr/0107-hook-body-write-set-accepted-static-gap.md可完整取回;tombstone 里故意不转载它,因为把被撤回的记录重印在自己的墓碑里,读起来就还是一份记录。为什么不恢复——恢复会是错的
不只是「被撤回了」。被撤回记录的 D2 把「不用启发式分析源码」写成了 permanent posture, not a deferral:永远不会用正则或 AST 去猜 Turing-complete body 的写入集。
撤回三天后,#4271(
c1d44f7dc,2026-07-31)做的恰恰就是这件事:validateHookBodyWrites解析body.source,把字面写入解析到目标对象字段上,hook-body-write-unknown-field带 did-you-mean 告警。那个 commit 的标题自己就记着这次反转——「L2 hook body 写不存在字段从 accepted gap 变为作者时 lint 告警」。也就是说,恢复正文等于往决策日志里种一句和已发布代码矛盾的话。今天这块面的真实说法在
content/docs/automation/hook-bodies.mdx「Write-set checking」,tombstone 把读者指过去。改动
1.
docs/adr/0107-withdrawn-hook-body-write-set-static-gap.md(新增)按邻居
0106-*/0108-*的 front-matter 与标题形状写的(粗体**Status**:行组 +---+## TL;DR)。明说编号已退役、不得复用,记下撤回、后续反转、以及上面这段考古,让下一个人不用重做。2.
scripts/check-adr-anchors.mjs(allowlist 收缩一条 + 三处注释)这一处不是顺手扩大范围,而是 tombstone 强制的。#6634 把裸编号 0107 放进了
UNRESOLVED_ADR_CITATIONS,而这张表是双向审计的:编号一旦获得记录,条目就以 stale 失败。所以加了 tombstone 就必须删这条——这正是 gate 自己在悬空引用报错里排第一的补救方式「(a) write the record」。而且它严格更强:allowlist 条目只在还有人引用该编号时存活(方向 B「nothing cites it any more」),而 0107 今天的三个引用里有一个是等待发布消费的 changeset——
.changeset/是设计上就会被changeset version删掉的。等它被消费掉,这条 grandfather clause 会自己过期、被要求删除,编号就悄悄重新空出来了,也就是这张卡担心的那件事。记录不会过期;而且复用现在会撞进编号唯一性审计,红得直白。反向验证(方向是先预测再跑的,两侧都红,但红的理由不同)
两处改动因此是耦合的,任何一边单独存在都是红的;没有一处是死重。
Gates(本地实测输出)
编号数从 118 变 119,
docs/adr/里 0106 → 0107 → 0108 连续。Changeset:走
skip-changeset标签docs/adr/**与scripts/**不在任何已发布包里,本 PR 不发布任何东西。空 frontmatter 的 changeset 已被check:empty-changeset(#5471)明确拒绝——它对changesets/action是真实输入,能触发 #4898 那种静默停发,而标签不会。所以按仓库文档化的路线打skip-changeset标签,不写 changeset。按维护者在 #6015 / #6741 的裁定,本 PR 触及
docs/adr/**,因此只起草和推送:没有开启 auto-merge,也没有进 merge queue。ADR maintainer approval检查在维护者本人 approve 之前会是红的——这是设计如此,不是失败。合并键在维护者手里。顺带测到、但本 PR 不动的事
docs/adr/一共有 4 个洞,而且成因各不相同,这正好是卡片里「gaps 是否合法」那个可选 gate 问题的输入:9da8e3e72)permission-protocol 重写时删除,至今在 allowlist 上;148f4c8f5/617f3f8ae,均git merge-base --is-ancestor判否),即main上从未分配;四个洞四种故事,其中至少两个(0075/0083)是完全正常的编号跳过。所以「给 gaps 加告警」不能是一刀切的,已按卡片要求记为 out-of-scope finding 交分诊判断,本 PR 不实现。
Generated by Claude Code