docs(gates): measure the changeset LEVEL axis src/** over-read, and pin the proxy as a decision - #17224
Merged
Conversation
… pin the proxy as a decision The LEVEL axis reads "did this PR grow the package's published surface?" from where the changed file lives. That proxy over-reads, and the gap was filed without a rate. Measured over the axis's whole life -- born c3b63f7 (2026-09-06), 449 commits landed, 233 of them introducing a changeset entry and moving a package the axis calls grown: * the over-read is common: 50 of 358 (package, PR) pairs, 14.0% * its cost is zero: not one false refusal, with the declaration forced to `yes` on every PR, and `refusable` is computed before the declaration is read, so the same zero covers the NOT MEASURED lane * the instance the card was filed on no longer refuses either -- it reads `discharged` at exit 0 under the rule that landed after it So neither remedy is bought, and no verdict changes here. The cheaper remedy that was left open -- exempt a file no entry point re-exports -- is separately recorded as measured UNSOUND: it holds only for a bundled build, and packages/cli emits its whole program, so a module nothing imports still ships. An instrument that skipped that distinction reported twelve false refusals for that package which reading the build mode collapsed to zero. Three self-test rows pin the proxy as a decision, with a nonsense control, so that exempting unreachable files costs a deliberate deletion and a fresh rate. Claude-Session: https://claude.ai/code/session_012GKcPZbMoGq7WPzKLfRBTU Co-authored-by: Claude <noreply@anthropic.com>
baozhoutao
marked this pull request as ready for review
September 9, 2026 19:21
baozhoutao
enabled auto-merge
September 9, 2026 19:22
baozhoutao
deleted the
claude/issue-16985-changeset-level-export-face
branch
September 9, 2026 20:12
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #16985 — this delivers the measurement that card asked for, and the remedy that measurement sizes. It deliberately does not close the card; see What is left open at the bottom.
Clause-②: no — comments and self-test rows only, in a repo-root CI script that no package publishes. No exported symbol moves, no verdict changes, no public surface widens.
The headline
The card asked whether
packages/**/src/**is a sound proxy for "the package grew a public face", and it was honest that the rate was not measured. Triage sized the remedy in advance: an exemption list if the false red is rare, an exported-surface reading if it is common.Measured: the over-read is common. Its cost is zero. So neither instrument is bought, and this PR changes no verdict.
The measurement
The LEVEL axis is three days old — born
c3b63f7add(#16264, 2026-09-06 08:57Z). So this is not a sample of the population, it is the population: 449 commits landed to3c5f3c5991, 233 of them introducing a changeset entry and moving a package the axis calls grown.Method: drive this file's own
scan,packagesTouchedandjudgeLevelat each merge commit against its parent — the same replay idiom the DEPTH note (#16713) already used in this file — plus one added reading per package: does this diff ship anything?, answered from the build each package actually runs.yesWhere the 50 over-reads land, which is the whole answer:
minor+, or is not graded.dischargedat exit 0, not a refusal. The@objectstack/client: minorin its own changeset discharges the PR under [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, which landed after it. The one cost the card was filed on is already structurally gone.By shape, the 50 are: 35 moved only
src/**/*.test.ts(a bundled package never emits those), 12 moved only modules no entry point reaches, 3 moved both.The zero is declaration-independent, which is what makes it a bound rather than an accident of who declared what. It is measured with the declaration forced to
yeson every PR — stronger than anything that actually happened — andrefusableis computed before the declaration is consulted, so the same zero covers the NOT MEASURED lane.A finding that kills the card's own cheaper alternative
The card left open "exempt a file no entry point transitively re-exports". Measured unsound, and unsound by the same asymmetry that condemns the packed-set predicate the dispatch warned about:
tsupbuilds fromsrc/index.ts, so for a bundled package a module nothing reaches emits no byte. 68 of 69 public packages.packages/clidoes not bundle. It runstsc -p tsconfig.build.json, which emits the wholeincludeprogram — so asrc/**file nothing imports still ships as its owndistoutput. Its tsconfig already documents this in prose and pays for it with an explicitexcludeline for a review-record module.One package is enough: an entry-graph exemption applied uniformly would switch this axis off for exactly the package where it must not be, printing a green. That is the expensive direction, and the same failure #16692 and #16713 each landed to undo.
This is measured, not reasoned. My first instrument skipped the build mode and reported twelve false refusals for
@objectstack/cli; reading the build mode collapsed them to zero. An exemption written from that same blind spot would have shipped the error as a rule.What actually landed
No behaviour change. Three things, all in
scripts/check-changeset-no-major.mjs:PUBLISHED_SOURCE_ROOT— which already refutes the other wrong narrowing, so the two now sit together where anyone narrowing the proxy will look.Verification
dispatch-gates --ranreconciles clean — 0 NOT-MEASURED, 0 UNRUN. Re-derived after fetching a movedorigin/main(bccf311100): identical set, no new family.09a7d6f9changed tocbb811d0, mutation visible on the predicate line), the self-test went red at exit 1 naming exactly the two new pins, then restore was verified by blob-hash equality againstHEADand an emptygit diff HEAD, with the restored self-test green again. Both legs ran from the committed state.falsecannot be an empty-closure artefact.fromon the same line silently missed every multi-line re-export block, and the build-mode blindness above.skip-changesetis measured, not assumed: the only changed file is a repo-root CI script, in a private root package with nofilesarray. Nothing publishes.What is left open
Part of, notFixes, and deliberately: the proxy is still unsound. What this PR discharges is the card's "not measured" gap and its prescription question. Whether the finding now closes as measured, or stays open for re-measure, is the maintainer's call — the card carries re-grade triggers, and two of them turn on facts I checked:Clause-②: yesfor package A that also moves a package-internal line under package B'ssrc/**, where no exit exists): not hit. The two PRs with that mixed offender shape both declared no at tier, so the axis stood down on both.needs:contract-reviewwas pre-hung at triage again within hours of ruling A landing — 13 carriers on cards with no claim and no PR, and no patrol row reads "carrier without increment" #16995 coupling — a pre-hung carrier reaching the PR side and lighting this axis): not observed. Neither carried the carrier label.⛔ Not claimed: that the proxy is sound. Only that the repair is unbought at today's rate. Re-measure before repairing, not instead of it.
Generated by Claude Code