Skip to content

docs(pr-automation): the "WHICH LEVEL" prose says the level axis exists - #17205

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-16946-which-level-prose
Sep 9, 2026
Merged

docs(pr-automation): the "WHICH LEVEL" prose says the level axis exists#17205
baozhoutao merged 1 commit into
mainfrom
claude/issue-16946-which-level-prose

Conversation

@claude

@claude claude Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Fixes #16946

Clause-②: no — this PR is prose in a workflow comment/message block. It puts no new key on any published payload, touches no packages/**/src/**, and publishes nothing (skip-changeset).

What was wrong

The closing sentence of the "WHICH LEVEL" prose in the Check Changeset step said:

This is prose, not a gate -- no
check computes it; `check-changeset-no-major.mjs` refuses `major` and
says why in its header, and the two remaining levels are yours.

Both halves stopped being true when #16055 landed the LEVEL axis in scripts/check-changeset-no-major.mjs. On a PR that declares clause ②, grading every moved package patch exits 1.

The gate builds a pointer to this exact paragraph from four sites — :80, :773, :1457, :1518 — so the reader most likely to arrive here is the author the gate has just refused, sent by the gate to a paragraph denying the gate exists.

The wording is copied, not invented

Every load-bearing clause in the replacement is quoted from the gate itself. Verified verbatim by normalising both texts (unwrapping line breaks and comment/string prefixes) and asserting containment:

quoted text copied from
"a PR that DECLARES clause ② (a new key on a published payload) must grade AT LEAST ONE package whose published source it moves minor or above" check-changeset-no-major.mjs:7-9 (file header)
"for exactly the PRs where the widening is already DECLARED, and for no others" check-changeset-no-major.mjs:776-777 (the LEVEL axis block)
not-declared, "the declaration reads no" → exit 0 judgeLevel verdict table, :1240
enforce, "declared yes, moved packages graded patch and NONE of them graded minor or above" → exit 1 judgeLevel verdict table, :1244-1245
"WHICH of the packages above received that widening is NOT something this gate can read, and it does not claim to. Clause ② is declared ONCE, FOR THE PR" check-changeset-no-major.mjs:1521-1523 (the enforce refusal message)

The gate's self-declared boundary is written in, deliberately

The correction would be a second false sentence if it only said "a gate computes this" — it would read as though the gate judges the act. So the replacement carries a second paragraph, headed WHAT THE AXIS DOES NOT JUDGE, in its own words, which quotes :1521-1523 and then states the consequence in plain terms: the axis cross-checks a declaration against the levels, it never reads the diff to find the act, judging the act is still the author's, and this paragraph is still where the rule lives.

This is also what keeps the change clear of #16361 (the grain the predicate is applied at, landed via PR #16945) and #16713 (the same predicate's blindness to nested packages, landed via PR #16969): the prose states the boundary the gate already declares, and asserts nothing about grain or path depth.

My own sweep for other carriers

The dispatch flagged that the PM's sweep read no check computes it as 0 hits — not because there is no other carrier, but because the sentence wraps: :725 ended with no and check computes it began :726. A literal transliteration of the claim missed even the primary site.

So: short fragments only, none able to straddle a newline, and every zero paired with a positive control on the same corpus (git grep over all tracked files, at d61139f1ba).

fragment hits where
check computes 1 pr-automation.yml:726 (the primary site the PM's whole-sentence probe missed)
prose, not a gate 1 pr-automation.yml:725
levels are yours 1 pr-automation.yml:727
remaining levels 1 pr-automation.yml:727
yours to keep 1 check-changeset-no-major.mjs:1453 — the gate's own text, correct as it stands
nothing computes 0
no check computes it 0 the wrapped-sentence trap, reproduced

Positive controls on the same corpus, proving the sweep reaches these files: WHICH LEVEL = 7 hits, 2026-09-04 = 269, decision batch #35 = 13, check-changeset-no-major = 142.

AGENTS.md was swept separately, because the card recorded it as not measured: clause ②, Clause-②, WHICH LEVEL, no check, not a gate, levels are yours all read 0, with controls changeset = 16 and level = 8 firing in the same file. Its only changeset-level statement is the patch floor at :1035-1036 ("a bug fix in a released package takes a patch changeset — never none"), which is a floor, not a claim about whether a gate computes the level — not a carrier, and outside this PR's boundary in any case.

The rest of the Check Changeset step's prose (routes 2 and 3, the empty-changeset step, the allow-major read) was read directly and carries no pre-#16055 claim.

Result: no other carrier found. The correction is exactly one paragraph, in one file.

Scope

Prose and comments only, inside the step's quoted heredoc message block. No step logic, no if: condition, no env:, no permissions, no uses:, no run: line is in the diff (asserted by grepping the diff for those tokens: none). scripts/check-changeset-no-major.mjs is not modified — the gate is correct, the prose was wrong. The workflow still parses (yaml.safe_load, top-level keys intact).

Verification

  • node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 33 families from the committed change set at 39b64933d6. All 33 ran; all exit 0.
  • --ran reconciliation: 33 derived famil(ies) accounted for — 33 run, 0 NOT-MEASURED, 0 UNRUN.
  • The derivation flagged roster families whose roster sits under .github/workflows ("silence is not evidence in either direction"), so those were run too: check-platform-checklist-watchdog.mjs, check-ci-filter-parity.mjs, pr-labels.mjs --self-test, ci/scheduled-full-run.mjs --self-test, ci/select-shard-timings-run.mjs --self-test, measure-test-shard-timings.mjs --self-test — all exit 0.
  • check-single-claim-paths.mjs: NOT MEASURED, by its own words — it exits 2 with "NOT WIRED — PR_NUMBER is not set … This is a wiring or usage failure, NOT a verdict". It needs CI's PR context; not a red.
  • Lint: the full union was run, not a narrowing. npx eslint . --no-inline-config --format json at 39b64933d6: 6439 files in the population, 0 errors, 0 warnings. Of those, 0 are YAML and this PR's path is absent from the population — eslint's own verdict when the file is passed explicitly is File ignored because no matching configuration was supplied. So the changed file is outside the lint surface entirely, and the union confirms nothing else moved.

Changeset

skip-changeset. Measured, not assumed: the one changed path is .github/workflows/pr-automation.yml, and no package manifest's files[] array in the repo contains .github — with the positive control that the same scan fires on dist for packages/cli, packages/apps/studio and others. .github/ is also named explicitly under route 2 of the very message this PR edits.

验收备注

Found but not filed, with reasons:

  • The Check Changeset step's message block is now ~46 lines of prose before route 2 begins. That is a readability observation about a block this PR made longer by 27 lines, not a defect: no instruction in it is wrong and nothing an author follows fails. Filing rule (a)/(b)/(c) does not reach it. Carrier: no PR or person is queued on this file. noted, not filed.
  • AGENTS.md:1035-1036 states the patch floor without mentioning the level axis. It is not false and it is not a carrier of the retracted claim, so it is neither an error nor a contract breach; AGENTS.md is a governed surface and out of this PR's boundary regardless. noted, not filed.

🤖 Generated with Claude Code

https://claude.ai/code/session_012GKcPZbMoGq7WPzKLfRBTU

Generated by Claude Code


Generated by Claude Code

The closing sentence of the "WHICH LEVEL" block said "This is prose, not a
gate -- no check computes it" and "the two remaining levels are yours". Both
halves stopped being true when #16055 landed the LEVEL axis in
check-changeset-no-major.mjs: on a PR that declares clause ②, grading every
moved package `patch` exits 1.

The gate builds a pointer to this exact paragraph from four sites (:80, :773,
:1457, :1518), so the reader most likely to arrive here is the author the gate
has just refused -- sent by the gate to a paragraph denying the gate exists.

The correction states the scope in the gate's own words (its header, the
`judgeLevel` verdict table) and, in the same breath, the boundary the gate
declares for itself at :1521 -- WHICH package received the widening is not
something it can read, and it does not claim to. Without that half the prose
would flip from "the gate does not exist" to "the gate is omniscient".

Prose only: no step logic, condition or permission is touched, and
check-changeset-no-major.mjs is not modified -- the gate is correct.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012GKcPZbMoGq7WPzKLfRBTU
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

2 participants