You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[finding] Clause ② is read from two different documents by two gates with nothing joining them — a card declaring no and a PR body declaring yes passes both, and --pair's green line says 「both carriers agree」 about the LABELS, not the declarations #16770
Filed by the domain:cli execution PM seat (seat post #6024), from a live pair in this round rather than from inspection. ⛔ No severity asserted, no domain:*, no type — routing and grading are triage's.
⚠️ The live instance below has already been corrected, at the card, by the seat that wrote it (me). The card is filed anyway because the correction had to be made by hand, in place, after landing-time review, on a pair that both gates called green — and nothing in the tooling would have said so at any earlier moment.
One fact, two documents, two readers, no join
Clause ② is a single fact about a PR's contract increment. Two gates consume it, and each reads a different document:
consumer
reads
code
check-clause2-carriers --pair (the enqueue/legibility gate)
⭐ Neither module contains a function that receives both. Grepped both ways: check-clause2-carriers.mjs never mentions declarationFromPullRequest; check-changeset-no-major.mjs mentions cardDeclaration exactly once, at line 790, inside a comment, never as a call.
The PR-side boundary is deliberate and documented, and this card does not contest it (scripts/check-changeset-no-major.mjs:785-789):
That is a deliberate boundary, not a shortcut: the sibling reading — the card's claim comment — needs a credentialled network read inside a required gate, and MEASURED ON THE ACCEPTANCE CASE it would have answered nothing anyway.
What is nowhere written down is the consequence when both documents carry a readable declaration and they say opposite things.
The measurement
Card #16568 / PR #16761, as the pair actually stood before I corrected it — the card's governing claim declared Clause-②: no, the PR body declared Clause-②: yes:
A. the two readers, same pair, pre-correction
card side cardDeclaration() -> {"state":"declared","value":"no","detail":"Clause-②: no"}
PR side declarationFromPullRequest -> {"value":"yes","readings":[
"carrier: `needs:contract-review` is not on this PR (0 label(s) read)",
"declaration line: `Clause-②: yes`"]}
B. POSITIVE CONTROL — the readers are not broken: fed the SAME document they agree
cardDeclaration([yes]) -> {"state":"declared","value":"yes",...}
declarationFromPullRequest(yes body) -> {"value":"yes",...}
C. and the precedence rules are not the same rule either
PR side: carrier label + body `no` -> {"value":"yes","readings":[
"carrier: `needs:contract-review` IS on this PR",
"declaration line: `Clause-②: no`"]}
card side has no label input at all: cardDeclaration.length === 1
⇒ B is the control: on one document the two readers return the same value, so A's split is a fact about the documents, not about a broken reader. C is a second, separable reading: on the PR side a hung carrier overrides a body no into yes; the card-side reader takes no label argument at all, so the two consumers do not merely read different documents, they resolve conflicts by different rules.
Both self-tests were green at the same commit (8b37a0973d): check-changeset-no-major --self-test 157 assertions, check-clause2-carriers --self-test 251 cases.
⚠️ The green line reads as a denial of exactly this
✓ check-clause2-carriers: PR #N / card #M — the clause-② declaration is readable in the fixed spelling and both carriers agree.
「both carriers」 there means the two label carriers — the maintainer's 2026-08-22 ruling that needs:contract-review hangs on card and PR alike (「两边都挂好」), imported from H31 rather than restated; the file's own docblock says so at :52-53. The sentence is true about labels.
⭐ But it is one clause away from 「the clause-② declaration」, and the word it uses for the labels — carriers — is the same word this tree uses for the documents that carry the declaration. I read that line on this pair, in this round, as covering the declaration. It does not, and it cannot: nothing compared the two declarations, so on a pair where they contradict, the gate prints a sentence a careful reader takes as a denial of the contradiction.
Why the split is not cosmetic — it selects the branch
scripts/pm/ensure-pm-labels.sh:283 states the gate's content limb as 「judged from the card」, and SKILL.md:648 ties the act to the same document:
Clause-②: yes 认领同笔在卡上挂标;PR 开出即读 check-clause2-carriers --pair N 为 0 再请审。
So the card's value decides whether the carrier is hung and the at-tier review is requested. On this pair the card said no, so no carrier was ever hung and no review was requested by the declaration; --pair took the no branch and ran the widening-tell scan (#16448) instead. Meanwhile the PR body'syes did its own job correctly and forced the changeset level patch → minor.
⇒ The same PR was simultaneously given the strict treatment on the level axis and the weaker treatment on the review axis, from two declarations of one fact, with both gates green.
⛔ This is not a complaint that the tell scan is weak — #16448's ruling accepted its false negatives deliberately and named in-seat contract review as the compensating control. The complaint is that which branch runs is decided by a document the other gate never reads, so a declaration split silently picks the branch, and no instrument reports the split.
⛔ It is also not a defect in PR #16761. Its PR-body declaration was right, the level red was a correct fire, and the clause-② status was established by content review. The card's no was my error; the point is that the tooling had no way to say so.
What this does NOT claim
⛔ Not that the PR side should read the card. That boundary is measured and argued at :785-789 and the cost (a credentialled network read inside a required gate) is real.
⛔ No count of how many open pairs are split today. I measured one pair, and stating a rate from one instance is the inference this repo keeps paying for. ⚠️ A sweep is cheap on the card side and impossible on the PR side without the same credentialled read, which may be why nobody has one.
Have --pair read the PR body too and refuse on a disagreement. It already fetches the PR. ⛔ Cost: a new refusal that will fire on pairs whose PR body was written before the card was corrected, and --pair is a legibility instrument whose value is that its rows are trustworthy — a noisy row costs more here than elsewhere.
Fix the sentence only. Change :1889 to say which carriers agreed (「both label carriers」) and state plainly that the PR body was not read. ⛔ Cost: one line, no detection — but it removes a green line that currently reads as a denial.
Leave it. ⛔ Cost: the status quo produced one split this session, found at landing by content review, and repaired by hand-editing an existing comment.
Reproduction
git checkout --detach 8b37a0973d
node scripts/check-changeset-no-major.mjs --self-test # 157 assertions
node scripts/pm/check-clause2-carriers.mjs --self-test # 251 cases# then, importing both readers, feed the pre-correction pair:# cardDeclaration([{created_at, body:'Claim: …\nBranch: `…`\nClause-②: no\n'}])# declarationFromPullRequest({labels: [], body: 'Clause-②: yes\n'})# control: feed both the SAME `yes` document — they agree.
Dedup — the four nearest were read in full, none owns this
Search provenance: semantic issue search over the repo, 458 results; the five above are the only ones touching the clause-② carrier plumbing. Firing control on the local greps: the cardDeclaration grep over check-changeset-no-major.mjs returned exactly one hit (line 790, a comment), against zero for declarationFromPullRequest over check-clause2-carriers.mjs — a zero read next to a one from the same command.
Filed by the
domain:cliexecution PM seat (seat post #6024), from a live pair in this round rather than from inspection. ⛔ No severity asserted, nodomain:*, no type — routing and grading are triage's.One fact, two documents, two readers, no join
Clause ② is a single fact about a PR's contract increment. Two gates consume it, and each reads a different document:
check-clause2-carriers --pair(the enqueue/legibility gate)Claim:commentcardDeclaration()—scripts/pm/check-clause2-carriers.mjs:539-550Check Changeset→check-changeset-no-major(the level axis)declarationFromPullRequest()—scripts/check-changeset-no-major.mjs:883⭐ Neither module contains a function that receives both. Grepped both ways:
check-clause2-carriers.mjsnever mentionsdeclarationFromPullRequest;check-changeset-no-major.mjsmentionscardDeclarationexactly once, at line 790, inside a comment, never as a call.The PR-side boundary is deliberate and documented, and this card does not contest it (
scripts/check-changeset-no-major.mjs:785-789):What is nowhere written down is the consequence when both documents carry a readable declaration and they say opposite things.
The measurement
Card #16568 / PR #16761, as the pair actually stood before I corrected it — the card's governing claim declared
Clause-②: no, the PR body declaredClause-②: yes:⇒ B is the control: on one document the two readers return the same value, so A's split is a fact about the documents, not about a broken reader. C is a second, separable reading: on the PR side a hung carrier overrides a body
nointoyes; the card-side reader takes no label argument at all, so the two consumers do not merely read different documents, they resolve conflicts by different rules.Both self-tests were green at the same commit (
8b37a0973d):check-changeset-no-major --self-test157 assertions,check-clause2-carriers --self-test251 cases.--pair's exit-0 sentence (scripts/pm/check-clause2-carriers.mjs:1889):「both carriers」 there means the two label carriers — the maintainer's 2026-08-22 ruling that
needs:contract-reviewhangs on card and PR alike (「两边都挂好」), imported from H31 rather than restated; the file's own docblock says so at:52-53. The sentence is true about labels.⭐ But it is one clause away from 「the clause-② declaration」, and the word it uses for the labels — carriers — is the same word this tree uses for the documents that carry the declaration. I read that line on this pair, in this round, as covering the declaration. It does not, and it cannot: nothing compared the two declarations, so on a pair where they contradict, the gate prints a sentence a careful reader takes as a denial of the contradiction.
Why the split is not cosmetic — it selects the branch
scripts/pm/ensure-pm-labels.sh:283states the gate's content limb as 「judged from the card」, andSKILL.md:648ties the act to the same document:So the card's value decides whether the carrier is hung and the at-tier review is requested. On this pair the card said
no, so no carrier was ever hung and no review was requested by the declaration;--pairtook thenobranch and ran the widening-tell scan (#16448) instead. Meanwhile the PR body'syesdid its own job correctly and forced the changeset levelpatch→minor.⇒ The same PR was simultaneously given the strict treatment on the level axis and the weaker treatment on the review axis, from two declarations of one fact, with both gates green.
⛔ This is not a complaint that the tell scan is weak — #16448's ruling accepted its false negatives deliberately and named in-seat contract review as the compensating control. The complaint is that which branch runs is decided by a document the other gate never reads, so a declaration split silently picks the branch, and no instrument reports the split.
⛔ It is also not a defect in PR #16761. Its PR-body declaration was right, the level red was a correct fire, and the clause-② status was established by content review. The card's
nowas my error; the point is that the tooling had no way to say so.What this does NOT claim
:785-789and the cost (a credentialled network read inside a required gate) is real.Directions, ⛔ none chosen — costs only
nocard with ayesbody still enqueues on the weak branch.--pairread the PR body too and refuse on a disagreement. It already fetches the PR. ⛔ Cost: a new refusal that will fire on pairs whose PR body was written before the card was corrected, and--pairis a legibility instrument whose value is that its rows are trustworthy — a noisy row costs more here than elsewhere.:1889to say which carriers agreed (「both label carriers」) and state plainly that the PR body was not read. ⛔ Cost: one line, no detection — but it removes a green line that currently reads as a denial.Reproduction
Dedup — the four nearest were read in full, none owns this
check-clause2-carriers --pairdemands aClaim:comment on EVERY card a PR delivers — including a card that by its own ruling is never separately dispatched, so exit 4 is unreachable-by-construction #16304 (open) — which card--pairasks when one PR delivers several. Same gate, different axis: that is card-selection, this is document-divergence.Check Changeset's clause-② level rule is PR-scoped but the fact it judges is package-scoped — a PR that widens package A is refused for grading package Bpatch, where B only received a comment #16361 (open) — the level rule's PR-scope vs package-scope. Its second observation is that the declaration vanishes when the carrier is stripped from a PR with no body line; here nothing vanishes — both readings are present and opposite.## Claim — …is invisible to CLAIM_COMMENT_MARKER, so itsClause-②declaration reads as never made #15693 (closed, PR tooling(pm): split the clause-② declaration limb's NO READING into two readings #15735) — a## Claim —heading invisible toCLAIM_COMMENT_MARKER, i.e.NO READING. Fixed, and orthogonal: the split needs both readings to succeed.Clause-②: nois refused at enqueue (mechanical control for the directional Clause-② ruling on #16349) #16448 (closed, PR skills(pm-dispatch): name the widening-tell gate in the landing pre-check #16605) — the widening-tell gate. It is the compensating control on thenobranch, referenced above; this card is about how that branch gets selected, not about how well it performs.Search provenance: semantic issue search over the repo, 458 results; the five above are the only ones touching the clause-② carrier plumbing. Firing control on the local greps: the
cardDeclarationgrep overcheck-changeset-no-major.mjsreturned exactly one hit (line 790, a comment), against zero fordeclarationFromPullRequestovercheck-clause2-carriers.mjs— a zero read next to a one from the same command.Refs: #16568 · #16761 · #16303 · #16304 · #16361 · #16448 ·
scripts/pm/check-clause2-carriers.mjs·scripts/check-changeset-no-major.mjs·scripts/pm/ensure-pm-labels.shGenerated by Claude Code