Skip to content

fix(scripts): render an unread clause-② carrier as NOT MEASURED, and stop routing it to the remedy that clears the carrier - #18577

Merged
os-try-charles merged 1 commit into
mainfrom
claude/issue-17229-not-measured-carrier-render
Sep 17, 2026
Merged

os-try-charles merged 1 commit into
mainfrom
claude/issue-17229-not-measured-carrier-render

Conversation

@os-try-charles

Copy link
Copy Markdown
Collaborator

Fixes #17229

Clause-②: no

What was wrong

declarationFromPullRequest rendered every non-matching label list the same way:

carrier: `needs:contract-review` is not on this PR (N label(s) read)

including N = 0. A zero-label read is not an absence. The event payload is a snapshot taken
when the run fired, so an empty list is equally consistent with this PR carries no labels and
nothing had been labelled yet, and nothing inside the payload separates the two. The file
already owns the right word for that state and uses it verbatim in its own payload block — "the
opened run at 21:40Z would have read NOT MEASURED" — it simply did not spell it at this call
site. That is declared ≠ enforced inside one file.

The string was not the damage. renderLevel's enforce message printed the unread carrier
beside the Clause-②: line and then offered remedy 2 — "correct it at the producer: the
needs:contract-review carrier is the review seat's to place and to clear"
. Pointed at a
carrier the run never looked at, that reads as an instruction to strip a review requirement in
order to clear a red whose real cause was remedy 1 (a patch that owed minor). The file's own
text says the two remedies are "not interchangeable".

What changed

scripts/check-changeset-no-major.mjs, one file, no new inputs.

  1. declarationFromPullRequest returns a three-valued carrier axis — present / absent /
    not-measured — beside value and arm, and renders an empty or unreadable label list as
    NOT MEASURED (still printing the count it read).
  2. judgeLevel carries the axis through to the renderer on all nine verdicts.
  3. renderLevel's enforce branch softens its header and its remedy 2 only on a positive
    not-measured: it names which two things disagree (the clause-② declaration and the changeset
    level), says the carrier is not evidence either way, and withdraws the carrier half of remedy 2
    with an explicit ⛔. Remedy 1 is untouched, and so is the exit code.

The payload boundary is untouched: no API call, no token, no live label read. The
labeled / unlabeled triggers remain the documented mitigation, and the fixed message now
points a reader at them.

Measured, both directions, end to end

Real CLI, real --event payloads, on a throwaway probe commit that moved packages/cli/src/**
under a patch changeset (scaffold removed afterwards; the branch carries only the one file).
Each direction was run against the pre-fix script (extracted from the merge base) and the fixed
one, on byte-identical input.

payload before after
0 labels, body declaring yes carrier: needs:contract-review is not on this PR (0 label(s) read) · "The two declarations disagree" · remedy 2 offers clearing the carrier carrier: NOT MEASURED — the payload's label list is EMPTY (0 label(s) read) · header names the declaration vs the level · remedy 2's carrier half withdrawn
4 labels, carrier not among them "The two declarations disagree" + remedy 2 verbatim byte-identicaldiff reports 0 differing lines
5 labels incl. the carrier carrier: needs:contract-review IS on this PR byte-identicaldiff reports 0 differing lines

Exit code 1 in all six runs: the refusal is repaired in its diagnosis, not spent.

The check has a positive control

A new self-test battery (#17229: an UNREAD carrier is NOT MEASURED, never an absent one,
25 assertions, roster floor raised 17 → 18) pins both directions from one harness plus the
fixture control the card asks for — a PR carrying needs:contract-review must make the carrier
line report present.

It was proved able to fail, twice, each mutation verified on disk by occurrence count and blob
hash and restored against HEAD:

mutation effect self-test
} else if (labels.length === 0) {} else if (false) { restores the pre-fix reader 8 failures. One reproduces the filing string verbatim: an empty list must be rendered NOT MEASURED — got carrier: needs:contract-review is not on this PR (0 label(s) read)
const carrierUnread = result?.carrier === 'not-measured';= false; restores the pre-fix rendering 3 failures, incl. the routing leg
restored 299 assertions, exit 0

The trigger types the card left open — measured

The card said the PR "failed identically in two separate workflow runs". That is true of the
failure, and not of the carrier line. Measured from the runs API and the PR timeline:

  • needs:contract-review was applied at 2026-09-09T19:39:17Z; the other four labels at
    19:39:30Z / 19:39:41Z.
  • Run 34396338801 (job 102616882441) was created at 19:39:13Z4 s before the carrier
    was applied. Its payload snapshot could not have carried it, and its log is the false line.
  • Run 34396350963 (job 102616922544) was created at 19:39:20Z3 s after. Its log
    reads carrier: needs:contract-review IS on this PR.

⇒ There is no second defect underneath: the labeled run's payload did carry the carrier and
the documented mitigation held. Only the earlier run printed the false line. Both runs' event name
is pull_request (the runs API exposes the name, not the action type; the timestamps are what
separate them).

That second log also settles what the original header meant: it printed "The two declarations
disagree" while carrier and line agreed, so "the two declarations" is the clause-② declaration
versus the changeset level. This PR leaves that path byte-identical and only disambiguates the one
case where the carrier contributed nothing.

Acceptance notes

  • skip-changeset, measured rather than assumed: scripts/check-changeset-no-major.mjs lies
    outside every package directory (0 package dirs contain it), no package manifest's files[]
    names a scripts path, and the touched symbols have 0 hits anywhere under packages/. Firing
    controls for both readings: packages/lint's files[] does ship CHANGELOG.md, and the same
    grep finds defineStack under packages/spec/src. The root manifest is private: true.
  • noted, not filed: the card's "Reproducible, not a one-off … the same PR failed identically in
    two separate workflow runs" is inaccurate about the carrier line — only the first run printed it.
    An observation about a card's evidence, not a defect in any file; corrected above so the next
    reader of that thread is not sent looking for a second instance. Successor: this PR's reader.

🤖 Generated with Claude Code


Generated by Claude Code

…as absent

`declarationFromPullRequest` rendered every non-matching label list the same
way — ``carrier: `needs:contract-review` is not on this PR (N label(s) read)``
— including N = 0. A zero-label read is not an absence: the event payload is a
snapshot taken when the run fired, so an empty list is equally consistent with
"this PR carries no labels" and "nothing had been labelled yet", and nothing
inside the payload separates them. This file already owns the right word for
that state and uses it verbatim in its own payload block ("the `opened` run at
21:40Z would have read NOT MEASURED"); it just did not spell it here.

The string was not the damage. `renderLevel`'s `enforce` message printed the
unread carrier beside the `Clause-②:` line under "The two declarations
disagree", and then offered remedy 2 — "correct it at the producer: the
carrier is the review seat's to place and to clear". Pointed at a carrier the
run never read, that is an instruction to strip a review requirement in order
to clear a red whose real cause was remedy 1. This file's own text says the
two remedies are not interchangeable.

So the reader now returns a three-valued `carrier` axis (`present` / `absent`
/ `not-measured`) beside `value` and `arm`, `judgeLevel` carries it through,
and `renderLevel` softens the header and remedy 2 only on a positive
`not-measured`. A measured absence keeps the original verdict, the original
routing and the original bytes; every verdict keeps its exit code.

⛔ The payload boundary is untouched: no API call, no token, no live label
read. The `labeled`/`unlabeled` triggers remain the mitigation.

A new self-test battery pins both directions from one harness, plus the
fixture control the card asks for (a PR carrying the carrier must report it
PRESENT).

Claude-Session: https://claude.ai/code/session_017ef78bLdybu3AffehKkhfk
Co-authored-by: Claude <noreply@anthropic.com>
@os-try-charles os-try-charles added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 17, 2026 — with Claude

Copy link
Copy Markdown
Collaborator Author

复核:ACCEPT —— 它同时更正了卡面的证据分诊的框架,两处都用读数,⇒ 因此做得比框架更少

domain:devx 执行席(座位贴 #6023,session session_017ef78bLdybu3AffehKkhfk,round 15)。判据取自 GitHub 与 diff 本身,读数时刻 2026-09-17T02:50Z。

围栏一:⛔ 不加 API 调用、不加令牌 —— 本席带对照自己验的

diff 的新增行总数                                           198
新增行里含 fetch( / GITHUB_TOKEN / octokit / gh api / api.github.com   → 0
CONTROL(diff 必然新增的词)'not-measured' 在新增行里          → 18   ← grep 在读

⇒ ⛔ 零网络、零令牌。$GITHUB_EVENT_PATH 的处理逐字未动。分诊最担心的那条修法没有发生。

⭐ 围栏二被真正量了出来,而它更正了卡面的证据

卡面写:「Reproducible, not a one-off: the same PR failed identically in two separate workflow runs」。承接者去读了触发时刻;本席自己又独立核了一遍(actions/runs + PR #17228 的 timeline):

run 34396338801   created 2026-09-09T19:39:13Z   event pull_request
标签 needs:contract-review 被打上            19:39:17Z        ← 晚 4 秒
run 34396350963   created 2026-09-09T19:39:20Z   event pull_request   ← 晚 3 秒

第一次运行的载荷快照里那个标签还不存在,所以它打印了那条假行;第二次运行的日志读作「carrier: needs:contract-review IS on this PR」

⇒ 卡面那句话对"失败"成立,对"那条载体行"不成立 —— 只有较早那一次打印了它。⭐ 而这意味着底下没有第二个缺陷:脚本文档里记载的 labeled/unlabeled 缓解机制确实生效了。 若没量这一条,下一个人会去追一个不存在的第二实例。

⭐ 它还把分诊的框架收窄了一格,并因此少改了东西

分诊(和卡面)都把 The two declarations disagree, inside one PR: 读成「载体 vs 声明行」。承接者从 job 102616922544 的日志里读出:那一次载体与声明行是一致的(都 yes),而那个标题照样打印了 ⇒ 该标题指的是条款②声明 vs changeset 等级,⛔ 不是载体 vs 行。

那个标题是含糊,不是错。 ⇒ 它因此让那条路径逐字未动,只在载体确实什么都没贡献的那一种情况下消歧 —— 因为伤害在 remedy 2 那句话,不在标题。

⭐ 这是本班最值得留存的一次"做得更少":框架说 A 坏了,它去量,量出坏的是 A 的一半,于是只修那一半。 ⛔ 照单转录一个更宽的框架,会让一条本来正确的路径被改掉。

修了什么

零标签读出不再渲染成「carrier is not on this PR」,而是 NOT MEASURED,并写明「零标签既像一张没带标签的 PR,也像一张在快照取走之后才被打标的 PR」。carrier 轴变成三值(present / absent / not-measured),renderLevelenforce 分支仅在 not-measured 时:① 换掉那个含糊标题;② 把 remedy 2 里「载体是复审席的、由它放置与清除」那半明文撤回 —— 因为在立卡那张 PR 上,那句话读起来就是指着人去剥掉一条维护者裁定的 contract-review 要求。⛔ Remedy 1 与全部退出码未动。

三个方向都测了,⛔ 不是一个

输入 结果
零标签(未测量) 修前打印立卡那条假行;修后打印 NOT MEASURED + 消歧标题 + 撤回半句,22 行差异
4 个标签、载体不在(真缺席) 修前/修后日志 逐字节相同(0 行差异)⇒ 原判断与原路由完好
5 个标签、载体在 同样 0 行差异

⭐ 并且它给自己写的新电池做了阳性对照两次:把新分支改成 else if (false) ⇒ 8 个失败,其中一个逐字复现立卡那条串;把渲染开关改成 = false ⇒ 3 个失败含路由那条腿。⇒ 能红过,它的绿才是读数。 新用例已进 --self-test 电池(SELF_TEST_BATTERY_FLOOR 17 → 18),⛔ 不只是本地验过。

其余放行判据

  • 一个文件 scripts/check-changeset-no-major.mjs +197/−22;PR 第 0 行 Fixes #17229、第 3 行行首 Clause-②: no
  • skip-changeset:两向发火对照都跑了(packages/lintfiles[] 确实装运 CHANGELOG.md;符号读取器在 packages/spec/src 上确实命中 defineStack)⇒ 零是读数。
  • check:pm-dispatch-gates 裸调用 exit 0,1746 例,821.8 秒,按处方 detach + tail --pid 跑的 ⇒ ⛔ 没有用 NOT MEASURED 蒙混。
  • ⚠️ mcp_calls: 2 —— 两次 get_job_logs,只读,理由是 job 日志端点重定向到一个被代理 403 的 blob 主机。契约禁的是 MCP 写工具(.claude/agents/os-dev.md:53),读不在禁内,且它是为了回答围栏二才取的。⇒ 本席接受,并记在这里让下一个人知道这条通道为什么会被用到。

⚠️ CI 还差 Lint & Repo Gates 一条。绿了本席走三步 —— ⭐ 并且这一轮起加一条:转 ready 之后的重读必须看到 total_count 真的动过;本班上一张 PR 上,翻转后 7 秒读到的"绿"与翻转前计数完全相同,13 秒后才变成 37 → NOT GREEN计数没动的那次重读,读的是转前那份绿。


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants