Repository navigation
Commit a14f3e6
test(floors, ui): one shared floor per ui package population, one catalog entry floor, all at about two thirds (#26576)
<!-- claude-projects-attribution: {"github_login":"os-steve"} -->
_Requested by **Steve** · [project
thread](https://claude.ai/code/project/chan_01FdL1XeUyvVNxLreh3F4Qi9?thread=cmsg_01FdL1XeUyvVNxLreh3F4Qi98CkpE4eCgM4NDygyDXH8Pt)_
Fixes #26521
Clause-②: no
Metadata-protocol: none
The ui half of #26444 (the parent stays open for its CLI and baseline
halves). No changeset: every edit is to a test, a test helper, a
repo-internal gate script under `ui/scripts/` or
`ui/QUICK_REFERENCE.md`, none of which any package ships; the PR carries
`skip-changeset`.
## 维护者速读
- 改了什么:ui 包数量的防空值底线原先在约 8 处各写一遍、都贴着今天的实测值;现在每个包总体只在
`ui/scripts/__tests__/helpers/ui-package-population.mjs`
写一次,取实测值约三分之二,两个门禁脚本的 `MIN_PACKAGES` 和全部测试点都读它;schema-catalog 的条目底线收成
`catalog-entry-floor.ts` 一处(原来 8 处三个值)。`ui/QUICK_REFERENCE.md` 删掉手写的「35
published packages」,测试改为拒绝手写数字。
- 为什么改:#26444 的规则:底线只防空扫描,不是普查;删一个包、一个目录条目不该让任何底线变红(#26343 删一个包改了五处底线)。
- 风险与回滚:只改测试、测试辅助、仓内门禁脚本和一行文档,不发布任何东西。底线变松但每条仍在清空总体时变红(下方 31 条断言实测)。回滚 =
revert 本 PR。
-
先看:`ui/scripts/__tests__/helpers/ui-package-population.mjs`(实测表与五个底线)、`ui/examples/schema-catalog/test/catalog-entry-floor.ts`、`ui/scripts/__tests__/quick-reference-commands-4149.test.ts`(改写的那条测试)。
- 两分钟验证:`cd ui && pnpm exec vitest run
scripts/__tests__/package-files-exist.test.ts
scripts/__tests__/quick-reference-commands-4149.test.ts`,预期两文件全绿。
- 需要你做的:无,席位落地。
## Why
#26444's rule: an anti-vacuity floor refuses an empty scan; it is not a
census. Floors set at today's measured value red on every legitimate
deletion, and #26343 edited five floors to delete one ui package. Each
floor now sits at about two thirds of its measurement and is written
once per population.
## What changes
**One floor per ui package population, written once.** New
`ui/scripts/__tests__/helpers/ui-package-population.mjs` holds the
anti-vacuity floors with the table they were measured from. It is an
`.mjs` module rather than a `.ts` helper like its neighbours because the
two gate scripts import it under plain `node`. Each floor is about two
thirds of the value measured on `origin/main` `6a7c0fe3` (right after
#26483 made `@object-ui/app-shell` private), the
`vite-dts-wiring-ratchet` precedent:
| floor | population | measured @ 6a7c0fe | floor | margin |
|:---|:---|---:|---:|---:|
| `UI_PUBLISHED_PACKAGE_FLOOR` | published packages (release group) | 36
| 24 | 12 |
| `UI_WORKSPACE_MEMBER_FLOOR` | manifests under `packages/*`, `apps/*`,
`examples/*` | 43 | 28 | 15 |
| `UI_SIDE_EFFECTS_FALSE_FLOOR` | packages declaring `sideEffects:
false` | 11 | 7 | 4 |
| `UI_SIDE_EFFECTS_ARRAY_FLOOR` | packages declaring a `sideEffects`
array | 17 | 11 | 6 |
| `UI_TSC_BUILT_PACKAGE_FLOOR` | tsc-built packages | 11 | 7 | 4 |
The card asked for one shared constant; the published-package floor is
that constant and every site whose population is the published set or a
superset of it reads it. Four sites count genuinely smaller or larger
populations (the two `sideEffects` groups, the tsc-built packages, all
workspace members); a 24 there would either red today (11, 17) or sit
far under two thirds (43), so each of those has its own floor in the
same module, still written once. See open question 1 in the report.
Every site, its measured value and its margin:
| site | was | measured | now | margin |
|:---|---:|---:|---:|---:|
| `check-node-esm-load.mjs` `MIN_PACKAGES` | 30 | 36 | published floor
24 | 12 |
| `check-published-dist-tooling.mjs` `MIN_PACKAGES` | 30 | 36 |
published floor 24 | 12 |
| `package-files-exist` packages declaring `files` | 38 | 39 | published
floor 24 | 15 |
| `package-files-exist` `files` entries | 150 | 153 | 100 | 53 |
| `package-files-exist` packages owing license text | 36 | 36 |
published floor 24 | 12 |
| `package-files-exist` packages declaring `exports` | 36 | 38 |
published floor 24 | 14 |
| `package-files-exist` `exports` targets | 130 | 150 | 100 | 50 |
| `side-effects-declaration-consistency` declaring | 28 | 28 | false +
array floors = 18 | 10 |
| `side-effects-declaration-consistency` `false` | 11 | 11 | 7 | 4 |
| `side-effects-declaration-consistency` array | 17 | 17 | 11 | 6 |
| `check-dist-completeness` tsc-built packages | 11 | 11 | 7 | 4 |
| `zero-test-member-exclusion-9106` members | 40 | 43 | member floor 28
| 15 |
| `zero-test-member-exclusion-9106` members with a test script and files
| 40 | 41 | member floor 28 | 13 |
| `check-doc-links` `examples` READMEs | 3 | 3 | 2 | 1 |
| `check-doc-links` `packages/*/README.md` | 35 | 39 | published floor
24 | 15 |
| `quick-reference-commands-4149` published under `packages/` | exact
prose | 35 | published floor 24 (anti-vacuity) | 11 |
The two entry-count floors (`files` entries, `exports` targets) and the
example-README floor count entries, not packages, so they stay local at
two thirds of their own measurement.
**`ui/QUICK_REFERENCE.md` drops its hand-written count.** The
`packages/*` row now reads "The published `@object-ui/*` packages, plus
the private ..." and still names the four private packages. Its test no
longer requires the row to state `N published`; it refuses any `N
published` / `N packages` figure in the row, keeps the anti-vacuity
floor under the derived population, and keeps the private-package check
(its failure text reworded for a row without a number).
**One schema-catalog entry floor, in one place.** New
`ui/examples/schema-catalog/test/catalog-entry-floor.ts` exports
`CATALOG_ENTRY_FLOOR = 288` (432 entries measured, margin 144). It
replaces the card's four sites (431 ×3, 423 ×1) and four more spellings
of the same population the card did not list
(`component-fixture-declared-keys.test.ts`, `allExamples().length > 400`
×3 and `entries.length > 400` ×1). The helper lives in the catalog
package's own `test/` because a test there importing from `ui/scripts/`
would read outside its package.
**Per-type catalog floors in the same four files, fixed in place.** The
same tests pin per-type censuses at exactly today's count, so deleting
one badge or card demo would red them. Same defect class, same files,
mechanical two-thirds edit, so they moved in place:
| site | measured | now | margin |
|:---|---:|---:|---:|
| `catalog-authored-key-6805-6806` `scroll-area` nodes (`minNodes`) | 7
| 5 | 2 |
| `catalog-authored-key-6805-6806` `badge` nodes (`minNodes`) | 40 | 27
| 13 |
| `card-demo-content-6788` cards | 93 | 62 | 31 |
| `card-demo-content-6788` card categories | 19 | 13 | 6 |
| `badge-demo-label-6829` badges | 40 | 27 | 13 |
| `badge-demo-label-6829` badge categories | 12 | 8 | 4 |
| `component-fixture-declared-keys` select options | 66 | 44 | 22 |
| `component-fixture-declared-keys` option categories | 7 | 5 | 2 |
| `catalog-gallery-render` plugin categories | 13 | 9 | 4 |
The plugin-category floor counts ui plugin packages with catalog
entries, so retiring one plugin package would have redded it.
### Forced test edits
- `ui/scripts/__tests__/check-node-esm-load.test.ts` "keeps a floor
under both legs": it pinned `MIN_PACKAGES >= 30`, a ninth spelling of
the population. It now pins `MIN_PACKAGES` to the shared floor and keeps
`> 0`.
- `ui/scripts/__tests__/quick-reference-commands-4149.test.ts`:
rewritten as described above, because the card deletes the prose number
it asserted.
## Tests
At head `0c64d31a`, all under `scripts/pm/os-verify-lock.sh`:
- The 14 touched or reading test files (the six `ui/scripts/__tests__`
sites, `check-node-esm-load`, `check-published-dist-tooling`,
`check-published-tsconfig-tooling-exclude`, and the five schema-catalog
files): Test Files 14 passed (14), Tests 1143 passed (1143). VERDICT
command-exit 0.
- `pnpm --dir ui exec vitest run scripts/ --maxWorkers=2`: Test Files
178 passed, 2 skipped (180); Tests 5057 passed, 2 skipped. VERDICT
command-exit 0.
- `pnpm --dir ui type-check:scripts` (the program holding the new `.mjs`
and every `ui/scripts` test): VERDICT command-exit 0.
<details><summary>Emptied population: every floor still goes red (31
assertions)</summary>
A one-shot mutation, restored from `HEAD` by a trap and confirmed by an
empty `git diff HEAD` afterwards: at each of the 30 floor sites in the
eleven test files the measured population was replaced by `0`
(`expect.soft(0, "EMPTIED ...")`), so every floor is read against an
empty population in one run. Result: Test Files 11 failed (11), and 31
assertions red, one per floor (the `minNodes` loop yields two). Examples
from the log:
- `EMPTIED packagesWithFiles.length: expected 0 to be greater than or
equal to 24`
- `EMPTIED members.length: expected 0 to be greater than or equal to 28`
- `EMPTIED published.length: expected 0 to be greater than or equal to
24` (QUICK_REFERENCE)
- `EMPTIED entries.length: expected 0 to be greater than or equal to
288` (×5) and `EMPTIED allExamples().length: ... 288` (×3)
- `no plugin categories were derived, so this case would be vacuous:
expected 0 to be greater than or equal to 9`
The two gate scripts' own collapse refusal (fewer than `MIN_PACKAGES`
published packages found) is covered by the existing
`check-published-tsconfig-tooling-exclude` case that pads a fixture
below `MIN_PACKAGES` and asserts the `scan-collapsed` finding naming the
number; it is green at the new value.
</details>
<details><summary>Measurement method</summary>
The measured values were read on `6a7c0fe3` by a throwaway mutation that
turned each floor into `expect.soft(population).toBe(-1)` and read the
actual values from the failures, restored from `HEAD` afterwards.
`MIN_PACKAGES`' population was read by calling each script's own
discovery (`discoverPackages(...).filter(not private)` and
`discoverPublishedPackages`): 36 each.
</details>
## Acceptance notes
- **Deleting one ui package or one catalog entry reds no floor** above:
every margin is at least 1 (the example-README floor, 3 → 2) and the
package floors' margins are at least 4.
- **Left as they are, deliberately.**
`layout-props-conversion.test.tsx`: layout nodes 430 (447 measured) has
a margin; `withClassName` 175 (182 measured) says in its own comment it
is deliberately tighter after a ruled sweep; the 153 stack-node count is
the census of a ruled `spacing` → `gap` rename, a transcription pin
rather than an anti-vacuity floor (the class #26431 owns).
`badge-demo-label-6829` `CONTAINER_CHILDREN_FLOOR` 600 (660 measured)
and `catalog-authored-key-6805-6806` text-content 600 (659 measured)
have margins. Exact `toHaveLength` pins on fixed demos are not floors.
- `#26365` (plugin-ai retirement) edits the QUICK_REFERENCE count and
`package-files-exist` floors too; whichever lands second merges main.
After this PR it needs to touch neither.
- The new helper sits under `ui/scripts/__tests__/helpers/` as the
claim's file surface names; the two gate scripts importing from there is
the one oddity, and the alternative (a sibling of `workspace-root.mjs`
in `ui/scripts/`) is open question 2 in the report.
## Verification
<details><summary>dispatch-gates: 20 derived, 20 run, 0 NOT
MEASURED</summary>
`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` at `0c64d31a` derived 20 families; each was
run after the last commit with its exit code captured before any pipe:
- exit 0: `check-closing-keyword-parity` (and `--self-test`),
`check-comment-mask-corpus` (18349 files, 0 disagree),
`check:cross-package-test-inputs`, `check:dispatcher-error-vocabulary`,
`check:driver-memory-census`, `check:engine-double-contract`,
`check:gitlink-declared`, `check:nul-bytes`, `check:published-files`,
`check:query-options-erasure`, `check:refd-timer-probe`,
`check:test-source-alias`, `check:tier-file-adoption`,
`check:type-check-coverage`, `check:type-check-debt`,
`check:undeclared-dep-imports`, `check:watch-hint-literal`,
`check:where-matcher`, and `pnpm --dir ui exec vitest run scripts/`
(above).
- `--ran`: `20 derived famil(ies) accounted for — 20 run, 0 NOT-MEASURED
(a DERIVED zero — all 20 recorded an exit code and none of them is 3)`.
</details>
- NOT MEASURED: `@object-ui/example-schema-catalog` `type-check` on
built dependencies. A local `tsc -p tsconfig.test.json` without the
`@object-ui/*` builds prints 171 errors, all unresolved-module noise
from unbuilt packages (81 TS2307, 62 TS2882 and their implicit-any
fallout); none names `catalog-entry-floor.ts` or an edited line. CI
`Type Check UI` is the reading.
- Every family CI runs is read from this PR's check runs; none was
re-run locally to stand in for them.
## Human Minimum
- [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic.
(not touched)
- [x] 2. Every name I added uses the casing for its kind.
- [x] 3. No formatter ran; `pnpm lint` passes. (lint is CI's run)
- [x] 4. One issue, one branch off an up-to-date `main`, one pull
request.
- [x] 5. A change that publishes carries a changeset, and both
declaration lines are filled in here and in the changeset. (publishes
nothing: `skip-changeset`)
- [x] 6. `packages/spec` touched: n/a.
- [x] 7. No hand edits to `content/docs/references/`,
`packages/*/CHANGELOG.md` or `content/docs/releases/`.
- [x] 8. Title, body and comments are in English.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01ADHkmTNh6kDC6Lu2Yr7s5v
---
_Generated by [Claude
Code](https://claude.ai/code/session_01ADHkmTNh6kDC6Lu2Yr7s5v)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 8e9abd9 commit a14f3e6
17 files changed
Lines changed: 220 additions & 98 deletions
File tree
- ui
- examples/schema-catalog/test
- scripts
- __tests__
- helpers
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
82 | 82 | | |
83 | 83 | | |
84 | 84 | | |
85 | | - | |
| 85 | + | |
86 | 86 | | |
87 | 87 | | |
88 | 88 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
119 | 119 | | |
120 | 120 | | |
121 | 121 | | |
| 122 | + | |
122 | 123 | | |
123 | 124 | | |
124 | 125 | | |
| |||
245 | 246 | | |
246 | 247 | | |
247 | 248 | | |
248 | | - | |
249 | | - | |
250 | | - | |
251 | | - | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
252 | 255 | | |
253 | 256 | | |
254 | 257 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
124 | 124 | | |
125 | 125 | | |
126 | 126 | | |
| 127 | + | |
127 | 128 | | |
128 | 129 | | |
129 | 130 | | |
| |||
213 | 214 | | |
214 | 215 | | |
215 | 216 | | |
216 | | - | |
217 | | - | |
218 | | - | |
219 | | - | |
220 | | - | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
221 | 224 | | |
222 | 225 | | |
223 | 226 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
117 | 117 | | |
118 | 118 | | |
119 | 119 | | |
| 120 | + | |
120 | 121 | | |
121 | 122 | | |
122 | 123 | | |
| |||
150 | 151 | | |
151 | 152 | | |
152 | 153 | | |
153 | | - | |
| 154 | + | |
| 155 | + | |
154 | 156 | | |
155 | 157 | | |
156 | 158 | | |
| |||
161 | 163 | | |
162 | 164 | | |
163 | 165 | | |
164 | | - | |
| 166 | + | |
| 167 | + | |
165 | 168 | | |
166 | 169 | | |
167 | 170 | | |
| |||
256 | 259 | | |
257 | 260 | | |
258 | 261 | | |
259 | | - | |
260 | | - | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
261 | 265 | | |
262 | 266 | | |
263 | 267 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
149 | 149 | | |
150 | 150 | | |
151 | 151 | | |
| 152 | + | |
152 | 153 | | |
153 | 154 | | |
154 | 155 | | |
| |||
646 | 647 | | |
647 | 648 | | |
648 | 649 | | |
649 | | - | |
| 650 | + | |
650 | 651 | | |
651 | 652 | | |
652 | 653 | | |
| |||
1345 | 1346 | | |
1346 | 1347 | | |
1347 | 1348 | | |
1348 | | - | |
| 1349 | + | |
| 1350 | + | |
| 1351 | + | |
1349 | 1352 | | |
1350 | 1353 | | |
1351 | 1354 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
87 | 87 | | |
88 | 88 | | |
89 | 89 | | |
| 90 | + | |
90 | 91 | | |
91 | 92 | | |
92 | 93 | | |
| |||
280 | 281 | | |
281 | 282 | | |
282 | 283 | | |
283 | | - | |
| 284 | + | |
284 | 285 | | |
285 | 286 | | |
286 | 287 | | |
| |||
565 | 566 | | |
566 | 567 | | |
567 | 568 | | |
568 | | - | |
| 569 | + | |
569 | 570 | | |
570 | 571 | | |
571 | 572 | | |
| |||
773 | 774 | | |
774 | 775 | | |
775 | 776 | | |
776 | | - | |
| 777 | + | |
777 | 778 | | |
778 | 779 | | |
779 | 780 | | |
| |||
935 | 936 | | |
936 | 937 | | |
937 | 938 | | |
938 | | - | |
939 | | - | |
940 | | - | |
941 | | - | |
942 | | - | |
| 939 | + | |
| 940 | + | |
| 941 | + | |
| 942 | + | |
| 943 | + | |
| 944 | + | |
943 | 945 | | |
944 | 946 | | |
945 | 947 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
3 | 4 | | |
4 | 5 | | |
5 | 6 | | |
| |||
269 | 270 | | |
270 | 271 | | |
271 | 272 | | |
272 | | - | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
273 | 276 | | |
274 | 277 | | |
275 | 278 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
| 25 | + | |
25 | 26 | | |
26 | 27 | | |
27 | 28 | | |
| |||
514 | 515 | | |
515 | 516 | | |
516 | 517 | | |
517 | | - | |
518 | | - | |
519 | | - | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
520 | 522 | | |
521 | 523 | | |
522 | | - | |
523 | | - | |
524 | | - | |
525 | | - | |
526 | | - | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
527 | 530 | | |
528 | 531 | | |
529 | 532 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| 6 | + | |
6 | 7 | | |
7 | 8 | | |
8 | 9 | | |
| |||
448 | 449 | | |
449 | 450 | | |
450 | 451 | | |
451 | | - | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
452 | 456 | | |
453 | 457 | | |
454 | 458 | | |
| |||
0 commit comments