Uh oh!
There was an error while loading. Please reload this page.
fix(ci): ADR-0087 迁移说明探测器读得懂「无箭头的改写表」(#6497) - #6558
Conversation
`not-required (no-migration-prescription)` 这条豁免的唯一守门人是 `findMigrationPrescription()`:正文带改写指令 ⇒ 拒绝该豁免。它此前的两条分支 (#6148 的 FROM/TO 标签、#6419 的框架锚定改写)**都要求出现箭头**,而本仓相当 一批 changeset 把改写指令写成 `## Migration` 标题下的两列表格,一个箭头都没有。 探测器判它「无迁移说明」,于是这条自相矛盾的豁免被门禁批准。 新增第三条分支 `framed-table`:**迁移框架标题所辖区域内**、markdown 表格的 数据行、**两个及以上不同单元格各带一个 OPERAND**。表格里由单元格边界承担箭头 的职责,所以这条分支对两侧的要求与箭头分支完全一致(代码形操作数),只是读 `|` 而不读 `→`。 **先量误报面,再放宽**(#6419 的打法):该分支在 1384 条存量上只命中 7 条, 7 条全部声明为 breaking,且逐条人工核对全部是真改写处方 —— 误报 0 条。 门禁口径 129/97 → 133/101,**+4 / −0**;超集性质在此是**结构性**的而非测量出来 的:箭头两支先判并当场 return,表格命中被扣到循环结束才返回,整个函数就是 `arrowBranches(body) ?? tableArm(body)`。 四条同形存量按预期从 `exempt-no-prescription` 移入残差面(`--audit-stock` 残差 92 → 96,恰好 +4、无一移出):`runtime-httpserver-wrapper-retired.md`、 `etl-author-shape-aliases.md`、`retire-three-deprecated-aliases.md`、 `unknown-key-strictness-ui-batch15.md`。这只是**工作清单**,不是判决。 同时重写脚本自述里那段「残余盲区」—— 它此前只说**未加框架**的改写表读不到, 而这 4 条恰恰是**加了框架**的,那句自述本身就是 #6497 的成因。现在按剩余形状 分项给数,并记下两条经测量后**拒绝**的更宽规则(无框架锚的表格 +114/33; 用表头取框架:只买到 1 条无判决影响的真阳性,却带来 1 条真实误报)。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AZgRyPVwi1jLb1mNNuUQ9o
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
os-project-manager
commented
Aug 8, 2026
PM 验收:通过,转 ready 并开启自动合并。( 验收时点的诚实边界: 独立复核的五点
另两项细节做对了: #6559 已由本 dev 按 PD#10 独立立单(未认领、未打标,留给分诊),数字口径与本 PR 一致。本座位此前承诺「若 dev 未立则由我补立」,据此解除,不重复立单 —— 那是与 #6497 同类、今天仍有 11 条声明 breaking 的 changeset 在用的活口子,不能只留在源码注释里。 Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#6497
缺陷
not-required (no-migration-prescription)这条豁免的唯一守门人是findMigrationPrescription():正文带改写指令 ⇒ 拒绝该豁免。它此前的两条分支 —— #6148 的FROM/TO标签约定、#6419 的框架锚定改写 —— 都要求出现箭头(REWRITE_RE是OPERAND ARROW OPERAND,循环里if (!REWRITE_RE.test(line)) continue)。而本仓相当一批 changeset 把改写指令写成迁移框架标题下的两列 markdown 表,一个箭头都没有。探测器判它「无迁移说明」,于是这条自相矛盾的豁免被门禁批准 —— 这是 #6419 那个形状的第三种拼写,它的教训逐字适用:作者写得越认真,探测器越看不见。一张写清了「原来怎么写 / 改成怎么写」的表,比一行箭头信息量更大,却恰恰是探测器唯一读不到的形状。
改法
新增第三条分支
framed-table:迁移框架标题所辖区域内、markdown 表格的数据行、两个及以上不同单元格各带一个OPERAND。表格里由单元格边界承担箭头的职责,所以这条分支对两侧的要求与箭头分支完全一致(代码形操作数:反引号代码段,或点/斜线标识符路径),只是读
|而不读→。三处收窄都是刻意的,方向都是「宁可漏,不可误」:| --- | --- |)才算表 —— 正文里带竖线的散文不是表,分隔行同时保证表头行永远不会被当成证据(扫到表头时分隔行还没出现);a | b,但认它就等于把每一行带竖线的散文读成表格行;| \getPort?()` | the real bound port |`),不是处方。先量误报面,再放宽(#6419 的打法,本单照抄)
误报没有诚实的出口:作者被错误拒掉一条他有权使用的豁免,封闭词表里没有别的选项给他。所以放宽之前先在整个存量上量,而不是在触发本单的那 4 条上量。
超集性质在此是结构性的而非测量出来的:箭头两支先判并当场
return,表格命中被扣到循环结束才返回,整个函数就是arrowBranches(body) ?? tableArm(body)—— 改前命中的每一条,仍以同一分支、同一条证据行命中。将来只动表格分支的编辑无法破坏它。经测量后拒绝的两条更宽规则
MIGRATION_FRAMING_RE,能正确读出| 原写法 | 改写为 |)—— 很诱人,不需要新词表。实测:只买到 1 条无判决影响的真阳性(filter-icontains-and-regex-retirement.md,不声明 breaking,门禁从不judge它),却带来 1 条真实误报 ——rate-limit-config-dual-source-c9.md,它那张表是两个类型的对照矩阵,只因表头单元格里有(renamed)一词被命中,而那个词在给列命名,不在框改写。在被判决的人群上一无所得、却多一种判错的方式 ⇒ 拒绝。4 条存量按名核对(
--audit-stock)残差面 92 → 96,恰好 +4,无一移出;
exempt-no-prescription桶 143 → 139。runtime-httpserver-wrapper-retired.mdexempt-no-prescription!(framed-table)etl-author-shape-aliases.mdexempt-no-prescription!(framed-table)retire-three-deprecated-aliases.mdexempt-no-prescription~(framed-table)unknown-key-strictness-ui-batch15.mdexempt-no-prescription!(framed-table)一并改写的自述
脚本正文那段「残余盲区」此前只说未加框架的改写表读不到 —— 而本单这 4 条恰恰是加了框架的。那句自述本身就是 #6497 的成因:它读起来像「凡是作者框起来的都看得见」,于是下一个读者信了它而不去测。现在给的是分支 3 之后剩下的形状,分项带数:
old → new清单/表:132 条 / 21 条 breaking —— 锚定框架的诚实残差,故意保留;**Migration.**独占一行,紧跟表格):4 条 / 2 条 breaking;| Wrote | Write instead |、| Removed | Live replacement |、| you wrote | write instead |、| Was | Now |):14 条 / 11 条 breaking —— 这是一条真实的房规(4 种拼法),读它需要一套新的老/新列词表,那是它自己的测量任务和自己的误报面,本单刻意不做,已另行归档为 finding。自测与反向验证
--self-test从 73 条断言增至 85 条(CI 的 Check Changeset 步骤跑它)。新增:P22-P27(表格分支的能力与三条边界)、R12(#6497 形状走完整scan()路径被拒,证据分支为framed-table)、G8(同一框架下的能力表保持 GREEN)、S7(--audit-stock分类器把它归入residue)。反向验证 —— 红集在运行前就预测好了:删掉表格分支,预测
R12(1 条「expected RED, got green」+ 3 条消息断言)、P22、P23、P24、S7转红,共 8 条;实跑 8 条,与预测逐条一致,既有断言无一移动。诚实标注方向:
P25/P26/P27/G8是误报地板,删掉分支后仍然是绿的。删一条分支只会让探测器匹配得更少,所以任何误报地板在反向验证下都不可能转红 —— 它们钉的是分支停在哪里,不是分支的能力。把它们写进红集预测才是编造证据。为什么没有 changeset
本 PR 只改
scripts/下的 CI 脚本,不属于任何已发布包,不发布任何东西 ⇒ 按 AGENTS.md「纯 bug 修复不需要 changeset」走不写 changeset这一支,并给 PR 打skip-changeset标签。本地门禁
node scripts/check-adr-0087-registration.mjs --self-test✅ 85 assertionsnode scripts/check-adr-0087-registration.mjs(门禁本体)✅pnpm lint(全仓 ESLint)✅;lint.yml里的全部check:*家族门禁 ✅pnpm check:nul-bytes✅;并对改动文件做了超出门禁的控制字符自扫(0 命中)🤖 Generated with Claude Code
https://claude.ai/code/session_01AZgRyPVwi1jLb1mNNuUQ9o
Generated by Claude Code