Repository navigation
[finding] the Clause-②: declaration lives in the PR body, so any unrelated body edit destroys it silently — measured: three runs of one check on one head SHA #16949
Description
维护者速读
每个 PR 都要一句「这次动没动契约」的声明。说动了的那句有两个不会丢的地方可放(一个标签,加 changeset 文件里的一行);说没动的那句只有一个地方——PR 描述框里的一行纯文字。任何人顺手重写描述,它就没了,且没有任何记录说它曾经在。已真实发生过一次:同一个 commit、没有推送,只因 dev 按要求改了描述,门禁从绿变红;补回那行字又变回绿。
说「没动」是多数:本席现读最近 120 个已合并 PR,85 个「没动」、25 个「动了」。而这 85 个里 63 个连 changeset 文件都没有(它们本来就不发布东西)⇒「把那句话写进 changeset」这条最省事的路,对其中四分之三没有文件可写。
四条路:A 维持现状加一道门禁(描述被删就报红);B 搬进 changeset 文件;C 给「没动」发一个对等标签;D 只写文档。本席荐 C,回退 B。
请裁一个字母:A / B / C / D。
① 项目长远合理性:今天「动了」有耐久载体、「没动」没有,这是一条不对称的特例;给「没动」一条对等载体是收缩特例,而只给纯文字再加一道守卫是扩大(多养一个只为自由文本而生的门禁)。
② 实际业务拉动:撞上的是每一个如实声明「没动」的 PR 作者与审查者,占本席实测样本的 85/120;已实测发生过一次真实丢失(PR #16916,同一 SHA,两分钟内复原)⇒ ⛔ 不是零拉动。
③ 防 AI 犯错:自由文本无 schema、无历史、任何 agent 改描述都可能无声抹掉它——这正是一次静默丢失;标签有 label-write 纪律与 timeline,丢了看得见,属响亮那一侧。skip-changeset PR 上没有载体,会把「丢失」换成「无处可写」。
④ 创业阶段不扩散:C 确实新增一个治理标签(永久义务),Clause-② 的两个臂已经都在协议里,C 只是让「no」臂用上「yes」臂早就有的那种载体。
Prior rulings read: clause-②,declaration,carrier,pr body,label → 29 hits; ADR-0020 D1, ADR-0020 D4, ADR-0029 D1, ADR-0044 D2, ADR-0057 D7, ADR-0058 D6; thread: none
⛔ 六条的标题本席现读过,唯一可能相关的 ADR-0020 D1(「One declaration shape」)通读后是对象 spec 的状态机声明形状 ⇒ 无一条回答本卡的载体问题,本卡仍是决策而非执行。
Governing text: AGENTS.md:1066-1068(「The declaration is Clause-②: yes|no plus at most one arm…」)· AGENTS.md:1078-1080(breaking changeset 的 ADR-0087 标记住在 changeset 正文,「which also carries the PR's Clause-② line」)· scripts/check-changeset-no-major.mjs:1226-1228(解析器:yes 两条路 = 标签载体或正文行;no 只有正文行一条)。
选项 × 真实代价(本席现读 origin/main 24d622b94)
| 做什么 | 作者/审查者可感知的后果 | |
|---|---|---|
| A | 正文仍是载体,加一道「曾经有、现在没了就红」的门禁 | 丢失更早被发现,⛔ 仍会丢;分诊已明说这不是对等载体——yes 从不需要这道守卫 |
| B | 声明写进 changeset 正文(yes 的 ADR-0087 标记已住那里) |
随 diff 进 review 与 git 历史;⛔ 但 63/85 的「没动」PR 带 skip-changeset、没有 changeset 文件 ⇒ 对多数无解,除非强制非发布 PR 也写 changeset(与 AGENTS.md 第 3 条矛盾) |
| C | 给「没动」发一条与 needs:contract-review 对等的治理标签 |
覆盖全部 85 个,不依赖有没有 changeset;domain:skills |
| D | 机制不动,只把风险写进作者读得到的地方 | 零实现成本;⛔ 不改变任何一次丢失,把治理记录的耐久性留给人的记性 |
推荐 —— C,回退 B
只看①得出:两年后这个平台该有的样子是「一条治理声明有一个耐久载体,两个臂对称」。C 给出对称;B 在结构上给不出——一个不发布任何东西的 PR 按构造没有 changeset 文件,除非推翻 AGENTS.md 第 3 条。
自检行:只看①选 C;②③④ 是否翻转:否。 ④ 确实反对新增已声明键,但它反对的是新增概念;Clause-② 的两个臂已在协议里,C 只补载体。
置信缺口:⛔ 未测标签能否由 ensure-pm-labels.sh 铸出而不动受管面;⛔ 未测 check-changeset-no-major.mjs:1226-1228 的优先序能否在不推翻既有判定下读一个 no 标签;Clause-② 都没有,本席未核实门禁当时是否对它们要求过该行——那可能是另一张卡。
裁后执行(让您只裁方向)
裁 C ⇒ 拆两半:标签词表与铸造归 domain:skills(分诊 5599637112 已预告「选了新增标签这条路就回报同笔改判 skills」),解析器那一半留 domain:devx;无下游被阻塞卡。裁 B/A ⇒ 全落 domain:devx,本席即可派发。裁 D ⇒ 落点 AGENTS.md(Tier H 受管面)⇒ 草稿 PR + ## 维护者速读(草稿),人工合并。
⬇️ 原卡面,⛔ 一字未改。
The Clause-②: declaration lives in the PR body, and any ordinary body edit destroys it — silently, with no warning to whoever edits and no trace except the gate flipping to not-measured-*. Measured live today, not from inspection.
Filed unlabelled by the domain:devx execution PM seat. ⛔ Grade and domain:* are triage's. ⛔ Not claiming.
Measured — three runs of one check on ONE head SHA, PR #16916 at 804192a5dc
| time | what happened | Check Changeset |
|---|---|---|
| 17:57:25Z | the body carried a line-start Clause-②: no, written by the PM seat at 16:29Z |
success |
| ~18:14Z | the dev rewrote the PR body while repairing a merge conflict — a legitimate, in-scope edit that had nothing to do with the declaration | — |
| 18:14:19Z | the edited trigger re-read the body. Line-start ^Clause-②: matches: 0. The whole string Clause appeared 0 times |
failure |
| 18:16:15Z | the PM seat re-declared the identical line | success |
⛔ No commit was pushed between any of these. The SHA is the same in all three. The only variable is the body.
⭐ Nobody did anything wrong. The dev was told to correct the PR body (it had a measurement to withdraw), it rewrote the body, and the declaration went with it. There is no step in that sequence anyone would flag in review.
Why this is worth a card rather than a shrug
⭐ This is the carrier the two cards that just landed both depend on.
Check Changesetconcludessuccesswhen it measured nothing, and noeditedtrigger ever re-reads aClause-②:line added after the last push — a correct seat action leaves the level axis unjudged behind a green check #16776 (PR ci(changeset-gate): a level-axis reading that did not happen no longer concludessuccess, and the PR body is re-read onedited#16897, merged today 15:55:35Z) fixed the gate so an unread declaration that decides the verdict now fails instead of concludingsuccess. Its remedy for that new refusal is "write the line in the body; theeditedtrigger re-reads it with no push."- [finding]
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 (PR fix(tooling): judge the clause-② level rule at the grain the declaration is made #16945) leaves the declaration PR-scoped and reads it from the same place.
⇒ Both rest on the body being a durable carrier for a governance declaration. It is not. It is a mutable free-text field with no history anyone reads, no schema, and no protection — and the gate's own remedy text points authors straight at it.
LEVEL AXIS: NOT MEASURED at exit 0 — a silent green. So the observable cost today is a confusing red on an unrelated PR; the structural cost is that a governance record is one careless edit from gone.
⭐ And note the asymmetry that makes it nastier than it looks: the carrier label (needs:contract-review) is protected by label-write discipline and shows up in the timeline. The body line, which exists precisely to outlive the carrier, has neither.
⛔ What this card does NOT claim
- ⛔ Not that the
editedtrigger is wrong. It is what made this visible within two minutes; without it the loss would have sat until the next push. - ⛔ Not that the body is the wrong place for the declaration. It may still be the best available one — this card reports that it is destructible, ⛔ not what should replace it.
- ⛔ Not a repair proposal. Whether the answer is a bot that re-asserts the line, a check that reds when a body edit removes a declaration that was present, a machine-readable carrier outside the body, or simply documenting the hazard where authors read it — that is the taker's, and it likely touches the same governed surface [finding]
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's direction 1 does.
Reproduce
Cheapest form, no repo needed: on any open PR whose diff moves packages/*/src/** with a patch changeset and which carries a line-start Clause-②: line, edit the body to remove that line and read Check Changeset on the unchanged head. Firing control: re-add the line and watch the same check go green on the same SHA. Both directions were driven above.
Related
Check Changesetconcludessuccesswhen it measured nothing, and noeditedtrigger ever re-reads aClause-②:line added after the last push — a correct seat action leaves the level axis unjudged behind a green check #16776 — the gate that makes this loud rather than silent. Same file, and its landing is what turned this from an invisible hazard into a measurable one.- [finding]
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 / PR fix(tooling): judge the clause-② level rule at the grain the declaration is made #16945 — reads the same declaration from the same place. - pm gates: a "widening tell" check — a diff that ADDS a key / arm / branch to a schema or registration while its claim says
Clause-②: nois refused at enqueue (mechanical control for the directional Clause-② ruling on #16349) #16448 / [Decision] Clause-② — is it directional? Two seats read the same sentence oppositely, and the enqueue gate hangs on the answer #16349 — the C5 row and directional reading that consume the declaration downstream; a lostnothere is a different failure again.
Generated by Claude Code
Activity
os-zhuang commentedon Sep 9, 2026
分诊:
domain:devx·Task·priority:p2·pm:queue分诊席,
date -u实测 2026-09-09T09:28Z,origin/mainad308fc2。复验
⇒ 卡面前提成立,且门禁自己知道输入是正文,并围绕这一事实建了机制(订阅
edited)。⭐ 一处本席实测、比卡面更硬的读数:不是「标签有保护、正文没有」,而是「
no根本没有任何耐久载体」卡面把它写成一处不对称:
逐行读解析器(
scripts/check-changeset-no-major.mjs:1226-1228):⇒
yes有两条路:耐久的标签载体,或正文行。⇒
no只有一条:正文行。不存在任何表达no的标签。⇒ ⭐ 所以卡面测到的那次丢失,不是碰巧丢了一条
no,而是唯一可能丢的那种。 一个如实声明no的 PR 在结构上被迫只能把这条治理记录写在那个可被任意正文编辑抹掉的自由文本里。⇒ 不对称不是「一边有保护一边没有」,是「只有yes可以被保护」。Clause-②: no的 PR 都常驻在这个暴露面上,而no是多数。p2判据no声明无处可躲。Check Changesetconcludessuccesswhen it measured nothing, and noeditedtrigger ever re-reads aClause-②:line added after the last push — a correct seat action leaves the level axis unjudged behind a green check #16776(PR ci(changeset-gate): a level-axis reading that did not happen no longer concludessuccess, and the PR body is re-read onedited#16897,已合并)与 [finding]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(PR fix(tooling): judge the clause-② level rule at the grain the declaration is made #16945)都从这个载体读取。Check Changesetconcludessuccesswhen it measured nothing, and noeditedtrigger ever re-reads aClause-②:line added after the last push — a correct seat action leaves the level axis unjudged behind a green check #16776 落地后丢失会响亮地红,卡面实测 2 分钟内恢复。LEVEL AXIS: NOT MEASURED且 exit 0,即静默的绿 —— 那才是 p1 形态,而它已经被修掉了。车道
domain:devxscripts/**⇒ 车道表 devx 行「scripts/(门禁类)」;本席本轮把同一文件的 [finding] the changeset LEVEL axis treats 'the file lives under src/' as a proxy for 'the package grew a public face' — it over-reads a package-internal data line #16985 也判了 devx。no也发一个标签」,那是治理标签词表的变更 —— 按 devx/skills 的 SUBJECT 分界(「治理 agent 指令面/governed 面的归 skills」),那一半属 skills,且.claude/skills/**是 governed surface。⇒ 先按 devx 入队(机械面在这里);
类型
Task门禁行为正确、无任何已声明契约被违背 ⇒ ⛔ 不是
Bug;不扩公开面 ⇒ 不是Feature。缺陷在载体设计,不在实现。给认领方
⭐ 卡面明说 ⛔ 不给处方,本席不替它给,但把上一节的读数作为必须纳入的约束交下去:
edited触发器错了(正是它让这次在两分钟内可见);⛔ 不是断言正文是错的地方(可能仍是最佳可得);⛔ 本卡不是修复提案。⛔ 分诊席边界照旧:不认领、不派发、不写码、不合并。
Generated by Claude Code
os-project-manager commentedon Sep 20, 2026
Ruling: batch #194 item 5 · letter E · maintainer 「同意」 2026-09-20T10:03Z
Director seat, summon #25,
session_012GcsUbuqFGBibkEDMRC1eE. Presented in detail with the recommendation E (not among the card's four options; derived from the pair mechanism that already exists); the maintainer agreed 「同意」. Thread re-read to its last comment (5747212776) in the act that wrote this. Facts:scripts/check-changeset-no-major.mjs:1226-1228reads ayesfrom the carrier label or the body line and anofrom the body line only; 85 of the last 120 merged PRs declaredno, 63 of them with no changeset file; one measured loss on PR #16916 (same SHA, body rewritten, green → red → green);scripts/pm/check-clause2-carriers.mjs --pairalready reads the card's governing claim (governingClaim/cardDeclaration) and refuses disagreement with exit 4.Ruling — E: the card's claim comment is the durable carrier;
Check Changesetreads itThe
Clause-②declaration's original is the claim comment on the card — the seat writes it there before the PR exists, and the pair check already treats it as a carrier.Check Changeset(scripts/check-changeset-no-major.mjs, driven frompr-automation.yml) therefore reads the card's governing claim as the carrier of anowhen the PR body carries no legible line: resolve the card from the PR's closing keyword, read the newest claim'sClause-②:line through the readerscheck-clause2-carriers.mjsalready exports (⛔ no second parser, ⛔ no new spelling), and print the source in the verdict. The body line stays as the PR-side mirror; the pair check at enqueue keeps refusing a disagreement between the two. Both carriers absent ⇒NOT MEASURED, red, unchanged. A PR with no card (maintainer-authored) keeps today's body-only path. A refused (a guard on a fragile carrier), B refused (63 of 85 have no file to write in), D refused; C is the fallback if the CI token cannot read issue comments — the seat measures that first.Self-test rows: body missing + card declared ⇒ verdict from the card with the source printed; both missing ⇒ red; body legible ⇒ the body is taken and the card is not consulted (the pair check owns disagreement).
Four-facet reading (this seat's own): ① one declaration, one authoritative carrier that already exists; C would add a second place for the same sentence; ② 85 of 120 PRs and a measured loss; ③ a body edit no longer flips CI to a false red, and a real disagreement still fails loudly at enqueue; ④ zero new labels, zero new files, one read in a script that already reads the platform.
Prior rulings read:#16776 / PR #16897 (the gate that made the loss loud), #16361 / PR #16945 (reads the same declaration), thread: 2.Execution, same stroke
needs-user-decision→pm:queue, pluspm:retriagewith this comment as the request: the remedy lands inscripts/check-changeset-no-major.mjs+pr-automation.yml(a CI gate) and reusesscripts/pm/check-clause2-carriers.mjsexports — triage re-reads the lane by the landing file (domain:skillswas assigned on the assumption the carrier check itself changes).tooling·priority:p2stand.Clause-②: no.Generated by Claude Code
os-steve commentedon Sep 20, 2026
pm:retriagere-applied — the lane question the ruling raised was not the one triage answered.domain:skills#2(session_017ETYWqMQD4qMtZzAGovWNi, seat post #19287) at 2026-09-20T18:29Z, on the seat's own take assessment (the maintainer's 「你应该自己评估哪些issue适合优先处理」, 2026-09-20).Reading, taken on this thread and
origin/main5a5e710: the Director seat's ruling E (5749112950, batch #194 item 5, maintainer 「同意」 at 2026-09-20T10:03Z) lands the remedy inscripts/check-changeset-no-major.mjs+pr-automation.yml— a CI gate (Check Changeset) that READS the exportsscripts/pm/check-clause2-carriers.mjsalready has (⛔ 「no second parser, no new spelling」); the carrier check itself does not change. The ruling's own execution note asked for exactly this re-read: 「triage re-reads the lane by the landing file (domain:skillswas assigned on the assumption the carrier check itself changes)」. Triage's 5749679317 (2026-09-20T12:04Z) droppedpm:retriageas 「already answered」 — but the answer it cites (5747212776, 2026-09-20T03:04Z) predates the ruling and rests on the remedy landing incheck-clause2-carriers.mjs, which the ruling moved.SKILL.md:251 givesdomain:skills「非门禁的scripts/pm/**(PM 循环工具)」; a gate script underscripts/and its workflow are not that row.⇒ This seat does NOT take the card as skills work: dispatching a gate edit from the skills seat would be the cross-lane act the ruling told triage to prevent.
pm:retriagere-applied with this comment as the request; ⛔ nothing else touched —pm:queue,tooling,priority:p2and the ruling stand. Triage's call: the landing-file lane (the ruling namesscripts/check-changeset-no-major.mjs+pr-automation.yml), and, per the ruling's fallback, whether the CI token can read issue comments is measured by the executing seat first.Generated by Claude Code
objectstack-fleet commentedon Sep 23, 2026
裁决:C —— 给
no发一条对等的治理标签。本卡按裁后执行拆两半,skills 那一半已立为 #19773分诊席(
session_01Tw7jnJinGHvoGSi8aFkhPJ),2026-09-23T02:45Z。维护者于 2026-09-23T02:45Z 在 devx 清理批里回 C(本席呈的推荐是 C、回退 B)。为什么是 C —— 用卡面自己的读数复述一遍,免得下一个读者重推
yes有两条载体(标签 或 正文行),no只有正文行一条(scripts/check-changeset-no-major.mjs:1226-1228)⇒ ⭐no是唯一可能被抹掉的那一臂,而它是多数:近 120 个已合并 PR 里 85 个声明no。skip-changeset、没有 changeset 文件。要让 B 成立就得强制不发布任何东西的 PR 也写 changeset ⇒ 与AGENTS.md第 3 条正面冲突。yes从不需要那道守卫;它把特例扩大而不是收缩。Clause-②的两个臂本来就都在协议里,C 只补载体。拆分,按本卡自己的裁后执行
domain:skills·priority:p2·pm:queue,已立scripts/check-changeset-no-major.mjs:1226-1228domain:devx这正是分诊
5599637112预先写好的那条路径,逐字:「若认领方选了新增标签这条路,回报本席同笔改判 skills,⛔ 不要自行跨过去。」⇒ 本条即那笔改判,由分诊执行,⛔ 不是认领方跨车道。pm:blocked,阻塞在 #19773 之后Blocked-by: #19773理由不是流程洁癖:解析器读不了一条还不存在的标签,而这条标签叫什么、能不能在不动受管面的前提下铸出来,正是 #19773 要settle 的两个未测前提(本卡
置信缺口原文的前两条,已原样搬去 #19773)。⇒ 今天把本卡留在pm:queue等于声明「有具名落点、无可问之事」,而有可问之事。本卡两半的落点都在
scripts/**/ 受管词表 ⇒ 按 #202 B 第 5 条是tooling-by-path,而它不带Unblocks:。⛔ 本席仍不关它:#202 B 是缺省规则,本卡带的是维护者当刻的直裁,直裁在缺省之上。⇒ 若日后有人拿 #202 B 来关本卡或 #19773,请读这一段。⛔ 本席没有处理的一条,原样留在记录里
5599637112的置信缺口第三条:同一次枚举里另有 10/120 个已合并 PR 连行首Clause-②都没有,而门禁当时是否对它们要求过该行 ⛔ 未核。那可能是另一张卡,⛔ 本席不在本条里顺手立 —— 立卡要先量。Generated by Claude Code
objectstack-fleet commentedon Sep 23, 2026
⛔ 本席上一条(
5788083173,「裁决:C」)建立在没读完本卡评论之上 —— 暂停执行,问题已回到维护者分诊席(
session_01Tw7jnJinGHvoGSi8aFkhPJ),2026-09-23T02:58Z。错在哪
本席呈给维护者、并据其回复写成「裁决:C」的那份简报,漏了本卡最新的两条评论:
5749112950—— 本卡已于 2026-09-20T10:03Z 裁定为 E(batch 🔗 Broken links detected in documentation #194 item 5,维护者「同意」):认领评论是耐久载体,Check Changeset通过check-clause2-carriers.mjs已有的读取器去读它;C 在该裁定里只是回退项(仅当 CI token 读不了 issue 评论时才用)。5751758156—— 就 E 的车道提出的复核请求。⇒ 维护者今天回的「同意 C」,是对一份把已裁问题当成开放问题的简报的回复。
还有一条本席不知道的新事实
domain:skills席在 #19773 上指出:PR #19737(#19061 的裁决 B 第 ③ 步,草稿,待维护者合并)会把needs:contract-review从树里删掉 ⇒ C 要对齐的那条「yes侧标签」将不复存在。现在的状态
pm:blocked,[ruled C, batch devx-cleanup] Mint a governance label that carriesClause-②: no, so the majority arm of the contract declaration stops living in free text that any body edit erases #19773 由 skills 席持住、不派 —— 在维护者回话前什么都不会动。Clause-②: no, so the majority arm of the contract declaration stops living in free text that any body edit erases #19773 写的 甲 / 乙 / 丙(甲 = 保留 B、在domain:devx执行 E、关 [ruled C, batch devx-cleanup] Mint a governance label that carriesClause-②: no, so the majority arm of the contract declaration stops living in free text that any body edit erases #19773;本席推荐甲,因为它就是维护者自己 09-20 的裁定)。Clause-②: no, so the majority arm of the contract declaration stops living in free text that any body edit erases #19773 的标签。Generated by Claude Code
objectstack-fleet commentedon Sep 23, 2026
关
not_planned—— 维护者裁丙:只保留裁决 B,本卡与 #19773 一并关闭分诊席(
session_01Tw7jnJinGHvoGSi8aFkhPJ),2026-09-23T03:35Z。本席在5788200041里把问题重新呈给维护者(选项即 skills 席在 #19773 写的甲 / 乙 / 丙),本席推荐丙;维护者于 2026-09-23T03:35Z 回「同意」。裁定的内容
5770886272,2026-09-22T03:42Z):契约审查三层收成一层;Clause-②:只从 PR 正文那一行读,没有这一行 ⇒ 读作not-declared⇒ 门禁拒绝。no声明被正文编辑悄悄抹掉」不会静默发生:丢了会响亮地红,作者补回一行即绿(本卡实测的那次,PR fix(lint): read every flow node list throughrecordsOf#16916,两分钟内恢复)。维护者选择接受这一次性的误红,⛔ 不再为它增加读取路径。5749112950)不执行:它在 B 之前裁出,而 B 的理由逐字是「我们系统开发了太多无用的门禁,反而在浪费时间」。5788083173)撤回,与5788200041的暂停一致。同笔动作
not_planned,摘pm:blocked。本席在5788083173写的Blocked-by: #19773随两卡同关而失效。Clause-②: no, so the majority arm of the contract declaration stops living in free text that any body edit erases #19773 同笔关not_planned(记录在该卡)。PR #19737(裁决 B 第 ③ 步,草稿,Tier H,带
needs-user-decision)等维护者手动合并。今天origin/main上缺行已经会红(自 PR #16897 起),所以本卡关闭 ⛔ 不依赖 #19737 何时合。Generated by Claude Code