Skip to content

Commit 5fdc1a8

Browse files
fix(changeset-gate): the level axis sees @objectstack/console when a diff moves the manifest its dist ships (#22816)
Part of #15204 Clause-②: no This is stage 5-pre of #15204 (claim amendment 6107473261). It repairs a blind spot in `Check Changeset`'s level axis that blocks stage 5 (#22812). #15204 remains open for its other stages, #22812 among them. ## The blind spot, measured on `origin/main` at `23419bafb` - `scripts/check-changeset-no-major.mjs` counts a package as grown when the diff moves its `packages/**/src/**` (leg 1) or a `bin` target its manifest names (leg 2). - `@objectstack/console` has neither. Its tracked files are `package.json`, `README.md`, `CHANGELOG.md` and `.gitignore`, and it publishes `dist/` (`files: ["dist","README.md","CHANGELOG.md"]`). - One file in that `dist` comes from this repository: `scripts/build-console.sh:398`–`:405` copies the repo-root `sdui.manifest.json` to `packages/console/dist/sdui.manifest.json`. `@objectstack/cli` reads it at runtime for the JSX gate and for the html-page save gate. - So a diff that widens what those gates accept moves only that file. On #22812 the axis saw `{packages: [@objectstack/spec]}` and refused a true `Clause-②: yes (widening)`, and it told the author to grade `minor` a package that did not grow. - No open PR or branch repairs it: the open PRs that name the gate (#22794, #22808, #22812) touch neither `scripts/check-changeset-no-major.mjs` nor `scripts/build-console.sh`. ## The fix: leg 3, read from the build script `packagesTouched` gains a third leg. A changed path that a build script copies into a package's packed output names that package. - **The mapping is read, not written down.** `packedCopiesIn` reads `scripts/build-console.sh` at the head under judgement. It evaluates its `NAME="value"` assignments in order and its `cp SRC DEST` lines. The repo root is the variable whose value is the script's own parent directory. `packedCopyOwner` then takes the nearest manifest above the destination and checks that its `files` packs it. The gate names one path, `PACKED_COPY_BUILD_SCRIPTS = ['scripts/build-console.sh']`, and never the file being copied. If the build ships a second tracked file, the leg sees it with no edit to the gate. If the build stops copying the manifest, the leg stops claiming it. - **`scripts/sdui-manifest.record.json` is measured out.** The build reads it only for a warning line and does not copy it, so it is not part of the shipped artefact. - **`.objectui-sha` is not added.** The pin decides which tree the console `dist` is built from, but nothing copies it. A pin bump that moves an accept set moves the manifest too, and that is what this leg reads. - **Unreadable stays unreadable (#4690).** If the build script is present but yields no copy, its path goes in `unreadable`, and the verdict prints it. If the destination package's manifest will not parse, that directory goes in `unreadable`. A path this leg matches lands in `packages` or in `unreadable`, never in neither. The leg is a union with legs 1 and 2, so nothing that was "grown" before stops being "grown". - **No gate and no tolerance are added.** The predicate, the verdicts and the inputs are unchanged. The axis now sees the package that carries the widening. - **One bounded in-place fix.** The verdict lines said "a package whose `packages/**/src/**` it moves". That was already false for leg 2, and with this leg it would be false for the console on #22812's green line. They now say "published source (`src/**`, a packed `bin` target, or a repo file its build copies in)". The self-test pins none of these strings. ## Evidence - **#22812's real inputs** (head `ecd4ed7458`, merge base `680a86b4c`, `--event` built from #22812's live body): - `main`'s gate: `node scripts/check-changeset-no-major.mjs --base origin/main --event EVENT` **exit 1**. "clause-② declares yes (widening) while no moved package is graded minor or above". This reproduces CI job 114433350057. #22812's copy of the gate is byte-identical to `main`'s. - This branch's gate, same command, same tree: **exit 0**. "✓ LEVEL AXIS: this PR declares clause-② `yes (widening)`, and it grades a package whose published source … it moves at `minor` or above", naming `@objectstack/console: minor (.changeset/console-0df67f237c5a.md)`. - `packagesTouched` on that diff: `{"packages":["@objectstack/console","@objectstack/spec"],"unreadable":[]}`. - **Self-test**: `node scripts/check-changeset-no-major.mjs --self-test` exits 0 with 401 assertions (378 on `main`). The new battery, `THE COPY` (floor 23, its measured count), pins: - #22812's shape (manifest moved, console `minor`, spec `patch`, `yes (widening)`) is `discharged`, exit 0, and the console line is what discharges it. The firing control: the same diff with the build script gone is refused, exit 1. - The manifest moved with the console at `patch`, or with no console changeset, stays `enforce`, exit 1. A manifest-only diff at `patch` is refused on the console alone. - The manifest moved under `Clause-②: no` is `not-declared`, exit 0. - The record alone moves nothing. A build script that yields no copy is reported and printed. An unparseable console manifest lands in `unreadable`. - The leg is pinned on this repository's real `scripts/build-console.sh`: it must copy `sdui.manifest.json` into `packages/console/dist/` as this reader sees it, and must not ship the record. So if the copy is respelled where the reader cannot see it, lint goes red instead of the leg retiring quietly. - **Ablation**, from the committed fix. `node scripts/ablation-replace.mjs` replaced the leg-3 loop's iterable with `[]` (anchor 1 → 0, blob `036d4b043ac9` → `a44dc90ff99c`). The self-test exited 1 with 5 failures, the first being "THE CARD: the manifest move names @objectstack/console beside the spec — got {"packages":["@objectstack/spec"],"unreadable":[]}". The restore was verified with blob == HEAD and an empty `git diff HEAD`. Floor probe: pinning the battery at 24 reds with "registered 23 case(s), below its pinned floor of 24". - **Derived gates.** `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 32 commands at `87d0ed9`, and all 32 exit 0. `--ran` reads "32 derived famil(ies) accounted for — 32 run, 0 NOT-MEASURED". This includes `check:changeset-gate-self-tests`, `check:nul-bytes` and `check:pm-dispatch-gates` ("1828 cases pass"). - **Lint, narrowed.** ESLint with `--no-inline-config` over the one changed file gives 0 errors and 0 warnings, 1 file by the `--format json` count. The config enables no type-aware linting (`parserOptions.project` is unset for it), so this diff cannot move the verdict on any untouched file. The repo-wide `pnpm lint` is CI's run. - **Governance.** `node scripts/pm/check-governed-merges.mjs --branch claude/issue-15204-s5pre-changeset-level-console` reads "NOT governed", 346 changed lines. ## Release `skip-changeset`: `scripts/` is the repo root's, and no package's `files` ships it. ## Landing On green, before #22812. #22812 then re-runs `Check Changeset` on its next push or on a body edit, with no change to its own files. ## Acceptance notes - `.objectui-sha` is not a leg (see above). A pin bump that ships new console bytes but moves no accept set still shows no console in the touched set. That is the right answer for this axis, which asks about a declared widening, and it is noted so nobody reads it as an omission. Carrier: none. - The leg understands plain `NAME="value"` / `$NAME` / `${NAME}` / `cp [flags] SRC DEST` shell, and nothing else. That is enough for the script it reads, and the real-script pin is what catches a respelling. Carrier: none. --- _Generated by [Claude Code](https://claude.ai/code/session_01Cw7JSJKE4EqGJ1uKPJZnSu)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 67b669e commit 5fdc1a8

1 file changed

Lines changed: 335 additions & 11 deletions

File tree

0 commit comments

Comments
 (0)