维护者速读
我们有一条纪律:每个自检脚本都要声明「我至少应该跑多少条断言」,这样一整批断言被误删时会变红,而不是安静地变绿。三个脚本已经按这条纪律加了声明 —— 但它们的声明只覆盖表格驱动的那些行,而这三个文件里另外还有 24 条一条一条手写在循环下面的断言,不在声明覆盖范围内:今天删掉其中任何一条,整个跑测仍然全绿,判决行一个字都不变。
更要紧的是测这件事的那支仪器看不见这个缺口:它按文件读,而这三个文件现在都报「已声明」⇒ 从它的输出看是干净的。⇒ 这是「门禁报出来的判决面,比它实际检查的面更宽」,而不是哪一条断言写错了(24 条今天全过)。
两条路:给这三处各写一份字面清单,把它们也纳入声明(A);还是裁定「这条纪律到表格行为止,不延伸到手写断言」并把话写明(B)?要一个字母。
① 项目长远合理性:A 扩大 —— 三份手写清单是三处永久义务,而卡面自己测到 js-comment-mask 的 extra 那一组只能写字面清单(derived 的清单会随生成它的那次调用一起被删掉,正是这条纪律要防的形状);B 缩小 —— 把契约边界一次说清,不新增载体。
② 实际业务拉动:今天没有人被伤害(24 条全过,且都不是本批改动碰过的);拉动来自 over-claim 本身 —— 一个读判决行的人会以为整份自检都被兜住了。
③ 防 AI 犯错:偏 A —— 字面清单是闭合枚举,抓得住「整组被删」;B 之后删掉一条手写断言仍然是静默的,而这正是本纪律要关掉的那一类。
④ 创业阶段不扩散:偏 B —— remove 优于 declare-and-maintain,每一份已声明的清单都是永久义务,而这里要三份。
Prior rulings read: recipe,floors,table,rows,inline,assertions,three,now-roster,self-tests,register,nothing,green → 87 hits; ADR-0020 D1, ADR-0029 D9.7, ADR-0056 D10, ADR-0076 D11, ADR-0119 D3, ADR-0120 D2, ADR-0131 D1, ADR-0131 D13, ADR-0131 D3, ADR-0131 D7; thread: 2
⚠️ 那十条 ADR 裁决本席查过,没有一条管这个问题。 check-prior-rulings.mjs 的告警由术语重叠触发(命中的是 floor / roster 这类通用词,落在通知平台、助手绑定、权限模型等无关域)。判据:docs/adr 139 个文件里,「自检断言底线」意义上的 floor / recipe A / roster 无一命中,而同一次 grep 的必中对照(Decision)命中 130 ⇒ 这是真空不是坏 grep(2026-09-19T04:24:37Z 现读)。⇒ 本卡不是被既有 ADR 答过的执行卡。
推荐:B。自检「只看①选 B;②③④ 是否翻转:②不翻转(无人被伤害,拉动是把 over-claim 说清);③ 会翻转 —— 它偏 A,因为 B 之后删一条手写断言仍然静默;④不翻转(三份永久义务对三个文件)」。⇒ ⭐ 四棱不同向(①④ 偏 B,③ 偏 A),所以本席不代裁,按置信门①呈你。
置信缺口:①④ 与 ③ 的权重之比就是这张卡的全部 —— 若你认为「静默删除一条断言」的代价高于「三份永久清单」的义务,答案是 A 而不是 B。本席没有独立复现「derived 清单会自删其 floor」那条(证据在卡面正文,针对 js-comment-mask 的 extra);若该条不成立,A 的成本下降,①也会松动。
📅 排期提示(⛔ 不是依赖声明):#13799 是这条纪律的主卡(117 条评论),也在等你一封信。两者可能适合一起答。⛔ 本席不主张 #13799 那封信已经覆盖本卡的问题 —— 本席读过 #13799 的正文,它谈的是「把 3 个没有入口函数的 inline 自检块改造成形」,与本卡「已声明文件内部的手写断言算不算在覆盖内」不是同一个问题。此前本席在轮次报告与座位贴里把两者说成同一个裁定,那是过度主张,已更正。
Governing text: #13799 正文(这条纪律的来源与 Tier 划分)· PR #15271(字面清单的既定形状)· scripts/measure-self-test-floor.mjs(按文件读的那支仪器)· 分诊席 5570109892(「a gate that runs and reports a verdict broader than what it checked is in class」与「Task —— the deliverable carries a decision」)
Measured while landing #13799 batch 7b (PR #15286) on 4dd5041bd. Filed unassigned, as a finding only.
The reading
Recipe A floors a table-driven self-test at its table rows. Three of the four files in that batch also carry assertions that are not rows — written inline, one at a time, below the driving loop:
| file |
rows floored |
assertions carrying no floor |
scripts/check-agent-model-declared.mjs |
18 |
4 (the discovery block: *.md only, a missing .claude/agents/, a directory holding no .md, real-tree discovery) |
scripts/check-startup-registry-verdict.mjs |
18 |
8 (expectRoot(...), the dead-root reverse proof) |
scripts/js-comment-mask.mjs |
23 |
12 (the interpolation view, pushed onto extra by the x(...) helper) |
That is 24 assertions whose disappearance is still indistinguishable from their passing: each writes into the shared failure sink only when it FAILS, so deleting one leaves the run green and the verdict line unchanged.
Why this needs a card rather than a note
The census (node scripts/measure-self-test-floor.mjs) reads per file. All three files now report ROSTER, so the residue above is invisible to the instrument that produced #13799's worklist — the exact shape of "a green run registers nothing", one level down, and now under a floored file's name.
⚠️ Note what the fix is NOT. For js-comment-mask's extra the rows exist only because an x(...) call pushed them at runtime, so a roster derived from that loop would delete its own floor with the call — the defect recipe A exists to prevent. Each of these three blocks needs a literal roster of its own, in the shape the pilot PR #15271 settled, or a decision that reach-only floors do not extend to inline assertions.
Not a defect in any gate's judgement: every one of these 24 assertions passes today, and none of them was touched by batch 7b.
Generated by Claude Code
维护者速读
我们有一条纪律:每个自检脚本都要声明「我至少应该跑多少条断言」,这样一整批断言被误删时会变红,而不是安静地变绿。三个脚本已经按这条纪律加了声明 —— 但它们的声明只覆盖表格驱动的那些行,而这三个文件里另外还有 24 条一条一条手写在循环下面的断言,不在声明覆盖范围内:今天删掉其中任何一条,整个跑测仍然全绿,判决行一个字都不变。
更要紧的是测这件事的那支仪器看不见这个缺口:它按文件读,而这三个文件现在都报「已声明」⇒ 从它的输出看是干净的。⇒ 这是「门禁报出来的判决面,比它实际检查的面更宽」,而不是哪一条断言写错了(24 条今天全过)。
两条路:给这三处各写一份字面清单,把它们也纳入声明(A);还是裁定「这条纪律到表格行为止,不延伸到手写断言」并把话写明(B)?要一个字母。
① 项目长远合理性:A 扩大 —— 三份手写清单是三处永久义务,而卡面自己测到
js-comment-mask的extra那一组只能写字面清单(derived 的清单会随生成它的那次调用一起被删掉,正是这条纪律要防的形状);B 缩小 —— 把契约边界一次说清,不新增载体。② 实际业务拉动:今天没有人被伤害(24 条全过,且都不是本批改动碰过的);拉动来自 over-claim 本身 —— 一个读判决行的人会以为整份自检都被兜住了。
③ 防 AI 犯错:偏 A —— 字面清单是闭合枚举,抓得住「整组被删」;B 之后删掉一条手写断言仍然是静默的,而这正是本纪律要关掉的那一类。
④ 创业阶段不扩散:偏 B —— remove 优于 declare-and-maintain,每一份已声明的清单都是永久义务,而这里要三份。
Prior rulings read: recipe,floors,table,rows,inline,assertions,three,now-roster,self-tests,register,nothing,green → 87 hits; ADR-0020 D1, ADR-0029 D9.7, ADR-0056 D10, ADR-0076 D11, ADR-0119 D3, ADR-0120 D2, ADR-0131 D1, ADR-0131 D13, ADR-0131 D3, ADR-0131 D7; thread: 2
check-prior-rulings.mjs的告警由术语重叠触发(命中的是floor/roster这类通用词,落在通知平台、助手绑定、权限模型等无关域)。判据:docs/adr139 个文件里,「自检断言底线」意义上的 floor / recipe A / roster 无一命中,而同一次 grep 的必中对照(Decision)命中 130 ⇒ 这是真空不是坏 grep(2026-09-19T04:24:37Z 现读)。⇒ 本卡不是被既有 ADR 答过的执行卡。推荐:B。自检「只看①选 B;②③④ 是否翻转:②不翻转(无人被伤害,拉动是把 over-claim 说清);③ 会翻转 —— 它偏 A,因为 B 之后删一条手写断言仍然静默;④不翻转(三份永久义务对三个文件)」。⇒ ⭐ 四棱不同向(①④ 偏 B,③ 偏 A),所以本席不代裁,按置信门①呈你。
置信缺口:①④ 与 ③ 的权重之比就是这张卡的全部 —— 若你认为「静默删除一条断言」的代价高于「三份永久清单」的义务,答案是 A 而不是 B。本席没有独立复现「derived 清单会自删其 floor」那条(证据在卡面正文,针对
js-comment-mask的extra);若该条不成立,A 的成本下降,①也会松动。📅 排期提示(⛔ 不是依赖声明):#13799 是这条纪律的主卡(117 条评论),也在等你一封信。两者可能适合一起答。⛔ 本席不主张 #13799 那封信已经覆盖本卡的问题 —— 本席读过 #13799 的正文,它谈的是「把 3 个没有入口函数的 inline 自检块改造成形」,与本卡「已声明文件内部的手写断言算不算在覆盖内」不是同一个问题。此前本席在轮次报告与座位贴里把两者说成同一个裁定,那是过度主张,已更正。
Governing text:#13799 正文(这条纪律的来源与 Tier 划分)· PR #15271(字面清单的既定形状)·scripts/measure-self-test-floor.mjs(按文件读的那支仪器)· 分诊席5570109892(「a gate that runs and reports a verdict broader than what it checked is in class」与「Task—— the deliverable carries a decision」)Measured while landing #13799 batch 7b (PR #15286) on
4dd5041bd. Filed unassigned, as a finding only.The reading
Recipe A floors a table-driven self-test at its table rows. Three of the four files in that batch also carry assertions that are not rows — written inline, one at a time, below the driving loop:
scripts/check-agent-model-declared.mjs*.mdonly, a missing.claude/agents/, a directory holding no.md, real-tree discovery)scripts/check-startup-registry-verdict.mjsexpectRoot(...), the dead-root reverse proof)scripts/js-comment-mask.mjsinterpolationview, pushed ontoextraby thex(...)helper)That is 24 assertions whose disappearance is still indistinguishable from their passing: each writes into the shared failure sink only when it FAILS, so deleting one leaves the run green and the verdict line unchanged.
Why this needs a card rather than a note
The census (
node scripts/measure-self-test-floor.mjs) reads per file. All three files now reportROSTER, so the residue above is invisible to the instrument that produced #13799's worklist — the exact shape of "a green run registers nothing", one level down, and now under a floored file's name.js-comment-mask'sextrathe rows exist only because anx(...)call pushed them at runtime, so a roster derived from that loop would delete its own floor with the call — the defect recipe A exists to prevent. Each of these three blocks needs a literal roster of its own, in the shape the pilot PR #15271 settled, or a decision that reach-only floors do not extend to inline assertions.Not a defect in any gate's judgement: every one of these 24 assertions passes today, and none of them was touched by batch 7b.
Generated by Claude Code