⛔ Recorded for triage; no severity asserted, no domain:*, no type — routing and grading are triage's. Filed by the domain:cli execution PM seat (#6024) after hitting the same shape twice in one session on two different gates.
The shape
A seat writes a declaration the machine is supposed to read. It reads correctly to a human. The predicate that consumes it does not match, so the declaration is not there as far as the tooling is concerned — and nothing says so at the time it is written. The failure surfaces later, at landing, or not at all.
Both instances were found by an at-tier contract reviewer running the predicate, not by the seat writing the declaration and not by any gate output the author saw.
Instance 1 — Clause ②: vs Clause-②: (a space where a hyphen is required)
Measured on PR #16298 at head 83edbc55f3e. CLAUSE2_KEY_LINE requires the machine spelling Clause-②:; that PR's body writes Clause ②:. The gate says so in as many words:
· declaration line: a near miss, not a declaration — Clause ②: **yes** …
⇒ the body carries no readable declaration, and the level axis reads yes off the needs:contract-review carrier alone. Measured both ways by the implementer: with the carrier the axis reads yes; with today's four real labels and no carrier, the same event reports NOT MEASURED.
⚠️ Not harmful on that PR — the card's claim comment carries the correct spelling, so the machine path is satisfied by the card side. But a PR whose body looks declared and is not is a trap for the next reader, and the distance between correct and near-miss is one character.
Instance 2 — a Branch: named in prose instead of on its own line
Measured on PR #15675 (the lane's only priority:p1) by its contract review. The card's claim comment named its branch in prose, so governingClaim never matched it and cardDeclaration read {state: missing} — meaning the --pair predicate saw no clause-② declaration on the card at all, on a card whose clause-② grade had been yes and public for two days.
The claiming seat fixed it by posting a claim with Claim: / Branch: / Clause-②: as lines, and verified mechanically rather than by eye: {state: missing} → {state: declared, value: yes}.
⭐ Why the two together are a class rather than two typos
- Both are near misses, not omissions. Nobody forgot to declare. Both authors wrote the declaration, believed it was written, and were right in every sense except the one that counts.
- Neither author got any signal. The gate that would have told them was, in both cases, one that this seat cannot run —
check-clause2-carriers returns PREREQUISITE NOT MET / HTTP 403 here, every time. ⇒ the seat that writes the declaration is systematically the one that cannot check it.
- Both were caught by a reviewer executing the predicate, which is luck rather than process: a reviewer is briefed on the diff, not on the declaration plumbing.
- The failure is silent and asymmetric. A missing declaration is loud at landing. A near-miss reads as present to every human who looks and absent to every machine that matters.
What a fix might look like — ⛔ costs only, not a recommendation
- Have the gate name near misses as errors where it currently reports them as context. The
Clause ②: case IS already detected and printed — it is called "a near miss" in the output. ⛔ Cost: it would red PRs that are substantively fine, including on the card-side-satisfied path, unless the check knows about both carriers.
- Accept both spellings. ⛔ Cost: widening a machine format to match prose is how the format stops being machine-readable.
- Emit the declaration from a template rather than by hand, so the spelling cannot drift. ⛔ Cost: templates for claim comments and PR bodies are a tooling surface nobody owns today.
- Leave it and rely on review. ⛔ Cost: this is the status quo, and the status quo produced two instances in one session, one of them on a p1.
⚠️ A decision here should probably also say which carrier is authoritative — card claim comment, PR body, or either. Instance 1 is harmless only because the card side happened to be right; if the rule is "either satisfies", that should be written down, and if it is "both must", instance 1 is a live defect rather than a trap.
Provenance
Instance 1: PR #16298, head 83edbc55f3e, driven with check-changeset-no-major.mjs --base origin/main --event <live label set> and two controls. Instance 2: PR #15675, verified by importing the real cardDeclaration / governingClaim and probing before and after.
Refs: #15675 · #16298 · scripts/pm/check-clause2-carriers.mjs · CLAUSE2_KEY_LINE.
⬇ Appended by the domain:devx execution seat (#6023) when this card was filed into the decision inbox, 2026-09-18T18:08Z. ⛔ Nothing above this rule was edited — the filing seat's text stands as written. The full analysis, and the measurement that reframes the card, are in the comment that accompanies this edit.
维护者速读
一个 PR 要声明「这次改动有没有放宽接受集」。声明是给机器读的一行字。作者写对了意思、写错了排版,机器就当这行不存在 —— 没人当场被告知,问题要么在 CI 里晚一步爆出来,要么根本不爆(卡面那一侧就是这样,有一张 p1 的声明凭空消失了两天)。十天里至少八次,横跨六个 PR、三个不同的席位。
本轮实测把病因从「拼写太挑剔」改写成了另一回事:这条规则其实很干净,只有一句话 —— 装饰随便加,理由随便写,但不能又用反引号把整句包起来、又在包外继续说话。 别的写法(裸写加理由、只给键名加反引号或加粗、项目符号、引用块、缩进)全都读得出来。问题是这句话今天只存在于检查器的源码和一份已合并的 PR 正文里;作者能看到的文档只说「单独一行、行首、就这两种拼法」—— 这句是对的,但它没说清楚「我想多写一句理由」时哪些写法还活着。
⇒ 所以这不是机器太严,是契约没有发表。选项:
- A 把所有近似写法判红,两个载体都判(会红掉一批实质没问题的 PR)
- B 把接受集再放宽,把「整句包起来还继续说话」也收进来(每放宽一次,这个格式就离机器可读远一步)
- C 声明改由工具产出,作者不再手写这一行(彻底消灭这个问题,但多一个今天没人负责的工具面)
- D 只把那一句规则写进作者会看的地方,机械面一个字不改(零成本;本席推荐)
- E 维持现状
⚠️ A、B、C 三项都踩「人工地板」(门禁增删/放宽、新增必须维护的工具面),所以本席不代裁。
请裁一个字母:A / B / C / D / E。
os-decision-facets
① 项目长远合理性:D 既不扩大也不缩小特例 —— 接受集一个字不动,只是把它发表出来;契约先行,把已经存在且自洽的规则写下来,比再造一台绕开它的机器更符合 no-workarounds。B 会让被容忍的拼法集合永久增生,是唯一明确扩大特例的选项。
② 实际业务拉动:非零且已实测 —— 十天内八次,六个 PR、三个席位,其中一次让本车道唯一的 priority:p1 卡在两天里对机器「没有声明」。⛔ 这是实例数不是速率,一轮读不出速率。
③ 防 AI 犯错:今天的失败是静默的(卡面那一侧)与迟到的响亮(PR 正文那一侧要等 CI 红)。D 把作者写之前就该知道的那句话交到他手上,是唯一在「出错之前」起作用的选项;C 更强(闭合枚举,作者根本不组装这行),A 只是把已有的迟到响亮加大音量。
④ 创业阶段不扩散:D 零新增面 —— 不新增门禁、不新增 hook、不新增工具。C 要新增一个今天没有归属的模板面,那是一份永久义务;卡面自己就把这条列为 C 的代价。
Prior rulings read: declarations,read,correctly,human,gate,near-miss,spellings,measured,session,silently,costing,reading (+2 more) → 128 hits; ADR-0076 D11, ADR-0125 D3, ADR-0056 D1, ADR-0058 D6, ADR-0062 D4, ADR-0067 D4, ADR-0069 D3, ADR-0076 D12, ADR-0090 D7
推荐:D。自检行「只看①选 D;②③④ 是否翻转:否」—— ③ 单独看更偏 C(闭合枚举优于自由结构),④ 单独看反对 C 的新增面;两者相消,都不改字母,只把 C 排成「D 发表之后仍复发才付的下一步」。回退项:C。
置信缺口:⛔ 本席没有实测卡面载体(governingClaim / cardDeclaration)那条路径 —— 上面七组读数全是正文形状经 readClause2Line,卡面那一侧是另一个谓词,卡上 instance 2 不被以上任何读数触及。⛔ 也没有数 2026-09-12 之后到今天有多少 PR 撞上这一形状:有三个被别的席位点名,那是实例不是速率。
Generated by Claude Code
⛔ Recorded for triage; no severity asserted, no
domain:*, no type — routing and grading are triage's. Filed by thedomain:cliexecution PM seat (#6024) after hitting the same shape twice in one session on two different gates.The shape
A seat writes a declaration the machine is supposed to read. It reads correctly to a human. The predicate that consumes it does not match, so the declaration is not there as far as the tooling is concerned — and nothing says so at the time it is written. The failure surfaces later, at landing, or not at all.
Both instances were found by an at-tier contract reviewer running the predicate, not by the seat writing the declaration and not by any gate output the author saw.
Instance 1 —
Clause ②:vsClause-②:(a space where a hyphen is required)Measured on PR #16298 at head
83edbc55f3e.CLAUSE2_KEY_LINErequires the machine spellingClause-②:; that PR's body writesClause ②:. The gate says so in as many words:⇒ the body carries no readable declaration, and the level axis reads
yesoff theneeds:contract-reviewcarrier alone. Measured both ways by the implementer: with the carrier the axis readsyes; with today's four real labels and no carrier, the same event reportsNOT MEASURED.Instance 2 — a
Branch:named in prose instead of on its own lineMeasured on PR #15675 (the lane's only
priority:p1) by its contract review. The card's claim comment named its branch in prose, sogoverningClaimnever matched it andcardDeclarationread{state: missing}— meaning the--pairpredicate saw no clause-② declaration on the card at all, on a card whose clause-② grade had beenyesand public for two days.The claiming seat fixed it by posting a claim with
Claim:/Branch:/Clause-②:as lines, and verified mechanically rather than by eye:{state: missing}→{state: declared, value: yes}.⭐ Why the two together are a class rather than two typos
check-clause2-carriersreturnsPREREQUISITE NOT MET / HTTP 403here, every time. ⇒ the seat that writes the declaration is systematically the one that cannot check it.What a fix might look like — ⛔ costs only, not a recommendation
Clause ②:case IS already detected and printed — it is called "a near miss" in the output. ⛔ Cost: it would red PRs that are substantively fine, including on the card-side-satisfied path, unless the check knows about both carriers.Provenance
Instance 1: PR #16298, head
83edbc55f3e, driven withcheck-changeset-no-major.mjs --base origin/main --event <live label set>and two controls. Instance 2: PR #15675, verified by importing the realcardDeclaration/governingClaimand probing before and after.Refs: #15675 · #16298 ·
scripts/pm/check-clause2-carriers.mjs·CLAUSE2_KEY_LINE.⬇ Appended by the
domain:devxexecution seat (#6023) when this card was filed into the decision inbox, 2026-09-18T18:08Z. ⛔ Nothing above this rule was edited — the filing seat's text stands as written. The full analysis, and the measurement that reframes the card, are in the comment that accompanies this edit.维护者速读
一个 PR 要声明「这次改动有没有放宽接受集」。声明是给机器读的一行字。作者写对了意思、写错了排版,机器就当这行不存在 —— 没人当场被告知,问题要么在 CI 里晚一步爆出来,要么根本不爆(卡面那一侧就是这样,有一张 p1 的声明凭空消失了两天)。十天里至少八次,横跨六个 PR、三个不同的席位。
本轮实测把病因从「拼写太挑剔」改写成了另一回事:这条规则其实很干净,只有一句话 —— 装饰随便加,理由随便写,但不能又用反引号把整句包起来、又在包外继续说话。 别的写法(裸写加理由、只给键名加反引号或加粗、项目符号、引用块、缩进)全都读得出来。问题是这句话今天只存在于检查器的源码和一份已合并的 PR 正文里;作者能看到的文档只说「单独一行、行首、就这两种拼法」—— 这句是对的,但它没说清楚「我想多写一句理由」时哪些写法还活着。
⇒ 所以这不是机器太严,是契约没有发表。选项:
请裁一个字母:A / B / C / D / E。
os-decision-facets
① 项目长远合理性:D 既不扩大也不缩小特例 —— 接受集一个字不动,只是把它发表出来;契约先行,把已经存在且自洽的规则写下来,比再造一台绕开它的机器更符合 no-workarounds。B 会让被容忍的拼法集合永久增生,是唯一明确扩大特例的选项。
② 实际业务拉动:非零且已实测 —— 十天内八次,六个 PR、三个席位,其中一次让本车道唯一的
priority:p1卡在两天里对机器「没有声明」。⛔ 这是实例数不是速率,一轮读不出速率。③ 防 AI 犯错:今天的失败是静默的(卡面那一侧)与迟到的响亮(PR 正文那一侧要等 CI 红)。D 把作者写之前就该知道的那句话交到他手上,是唯一在「出错之前」起作用的选项;C 更强(闭合枚举,作者根本不组装这行),A 只是把已有的迟到响亮加大音量。
④ 创业阶段不扩散:D 零新增面 —— 不新增门禁、不新增 hook、不新增工具。C 要新增一个今天没有归属的模板面,那是一份永久义务;卡面自己就把这条列为 C 的代价。
Prior rulings read: declarations,read,correctly,human,gate,near-miss,spellings,measured,session,silently,costing,reading (+2 more) → 128 hits; ADR-0076 D11, ADR-0125 D3, ADR-0056 D1, ADR-0058 D6, ADR-0062 D4, ADR-0067 D4, ADR-0069 D3, ADR-0076 D12, ADR-0090 D7
推荐:D。自检行「只看①选 D;②③④ 是否翻转:否」—— ③ 单独看更偏 C(闭合枚举优于自由结构),④ 单独看反对 C 的新增面;两者相消,都不改字母,只把 C 排成「D 发表之后仍复发才付的下一步」。回退项:C。
置信缺口:⛔ 本席没有实测卡面载体(
governingClaim/cardDeclaration)那条路径 —— 上面七组读数全是正文形状经readClause2Line,卡面那一侧是另一个谓词,卡上 instance 2 不被以上任何读数触及。⛔ 也没有数 2026-09-12 之后到今天有多少 PR 撞上这一形状:有三个被别的席位点名,那是实例不是速率。Generated by Claude Code