Repository navigation
test(cli): declare measured budgets on the generate-refuses and build spawn files (#23181 slice 11) - #26174
Merged
Conversation
… spawn files Ten packages/cli integration files spawn the source CLI once per single-cause fixture. Each spawn's floor is the source entry loading all 72 commands (about 8.5 s locally, `os --version` included), so no file with a spawn fits the 10 s line, and none spawns twice for one fixture. Each file now carries its ruled `test-budget:` header line (class "spawns the real producer once per single-cause fixture"), sized from the slowest CI reading in shard-timings refresh run 40275747937 x 1.25, rounded up to the next 10 s. Comment-only: no case, assertion, timeout or project changes. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pq8DZ41armkBBdhQUufpjH
Contributor
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
Contributor
Author
席位核对 · ACCEPT ·
|
| item | reading |
|---|---|
| Shape | draft, base main, Part of #23181 (slice 11), skip-changeset, mergeable clean. |
| Files | 10 files, +10/−0: one // test-budget: header each on the generate-refuses-* and build-* spawn files in packages/cli/test/. |
| Finding | The per-case-boot hypothesis does not hold for this family. Every spawn is a separate single-cause case (the generate-refuses-* files already spawn inside one beforeAll), and each tsx run-dev spawn has an 8.2–8.5 s floor. So no file can get under 10 s within the claim. |
| Fix | This is the ruled route for such files: ruling 6181973363 letter B ("spawns the real producer once per single-cause fixture"). Each header is sized at the slowest CI reading in refresh run 40275747937 (#25960) × 1.25, rounded up (60–160 s), and names its spawns. Departure (accepted): 10 files rather than about 8, because each change is one comment line. |
| Evidence | 36 check runs success and 16 expected skips on this head, 0 failed. Shuffled run 10/10 files, 91/91 tests; 55/55 derived gates exit 0; eslint and typecheck clean. |
| Carried | The open question (the 8.5 s spawn floor caused by the missing oclif.manifest.json) is ruled A by this seat and dispatched as slice 14 (amendment 6419075788): a test-only globalSetup writes the manifest per run. A later refresh re-sizes these headers. The duplicate spawns across generate-refuses-* are named in the PR's Acceptance notes and left in place. |
| Landing | 「按照 pm-dispatch 规则复核过的都授权」 (Leehom, 2026-10-25T11:35Z): ready and auto-merge through the relay. |
Generated by Claude Code
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.
Requested by Leehom · project thread
Part of #23181 (slice 11). The card is a series and stays open.
Clause-②: no
Metadata-protocol: none
Test-only, comment-only diff:
skip-changeset(nothing in any package'sfiles[]changes;packages/cli/test/**is not published).Rows this PR addresses
The ten
@objectstack/cliintegration files of the per-case CLI spawn family (test/generate-refuses-*.test.tsand the five namedtest/build-*.test.ts). Reading used: the per-file list of shard-timings refresh run40275747937(PR #25960, the newest refresh with a per-file list; it was not merged, and PR #26089 used the same list for the spec/lint rows). The card's own table (run38340176409) is older and lower.test/build-callable-names.test.ts40200279306)test/generate-refuses-unimportable-alias.test.ts40204927516)test/build-runtime-bundle-bodyless.test.ts40200279306)test/build-strict-body-count.test.ts40204927516)test/generate-refuses-namespace-prefix.test.ts40204927516)test/build-view-container-name.test.ts40204927516)test/generate-refuses-unparseable-name.test.ts40200279306)test/generate-refuses-name-outside-charset.test.ts40204927516)test/generate-refuses-retired-generator.test.ts40204927516)test/build-text-face-advisory-count.test.ts40200279306)Budget = slowest CI reading x 1.25, rounded up to the next 10 s (the grammar
readTestBudgetinscripts/measure-test-shard-timings.mjsenforces; all ten lines parse through it). Pin: the next refresh lists none of these ten in its over-budget table; each appears under "Held to the budget it declares" instead, and is listed again only if a run reads it over its own budget.Why a declared budget, not a cheaper test
The order's hypothesis was a per-case boot that one
beforeAllcould share. Measured, it does not hold here:tsx bin/run-dev.jsspawn costs 8.2 to 8.5 s locally, andos --versionalone costs 8.4 to 8.8 s: the source entry has oclif import all 72 command modules through tsx on every start, because nooclif.manifest.jsonexists. Every file's local wall is its spawn count x 8.5 to 9.5 s (for example 7 spawns, 65 s; 3 spawns, 25 s).generate-refuses-*files already run all their spawns in onebeforeAll. Every spawn in all ten files is a different argv or a different fixture: each one is a single-cause case (a refusal, its dry-run form, the neighbouring layer's verdict, or a control). Cutting one removes a case.// test-budget:header, as eleven other cli spawn files already do.packages/cli/vitest.config.tsrecords for rejectingmaxWorkers: 4.The lever that would make these budgets fall (a decision, not taken here)
Measured on this tree, with an
oclif.manifest.jsonwritten intopackages/clifor the probe and removed afterwards (git statusclean):tsx bin/run-dev.js generate object order_line --dry-rundrops from 8.2 to 8.5 s to 2.0 to 2.3 s, with byte-identical output (1412 bytes) and the same exit code.--versiondrops to 0.4 s. A refusal case (generate object class) still exits 1 in 2.2 s. Applied to this family, local wall would fall from about 520 s to about 130 s. It is reported to the seat as an open decision because it changes the spawn shape these files document.Proof
179c8078a,pnpm exec vitest run --project integration --maxWorkers=2 --sequence.shuffle --sequence.seed=23181+ the 10 files: Test Files 10 passed (10), Tests 91 passed (91), lock VERDICT command-exit 0.os-verify-lock,--project integration --maxWorkers=2, the default reporter's per-file module line (the number CI's per-file timings read). The after wall is the same tree's behaviour (comment-only diff), so it was not re-run three times; the shuffled run above is the after reading.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackat179c8078a: 55 commands, all exit 0 (two first exited 3 on prerequisites:check-plugin-teardown-shape --self-teston a shallow clone, fixed by fetching621a4876;check:dual-build-cjs-loadson eight unbuilt packages, fixed by building them).--ran: "55 derived famil(ies) accounted for, 55 run, 0 NOT-MEASURED".pnpm --filter @objectstack/cli typecheck: exit 0 (check:test-typecheck: OK).pnpm exec eslint --no-inline-config packages/cli: exit 0.Acceptance notes
os g object class(inunimportable-alias,unparseable-name,name-outside-charset),os g object order-line(inunimportable-alias,name-outside-charset) andos g object order_line(inunparseable-name,name-outside-charset). Each file asserts a different layer's wording on its copy, so they are not removed here. Folding them is about 4 spawns (about 35 s per run) and a cross-file reshuffle of the [Decision] Which names shouldos generateACCEPT? — a gate, a sanitiser, or both, and whose charset #16726,os generatehas NO name validation at all —os generate object foo.baremitsconst foo.bar: Data.ServiceObjectand a barrel re-export, both un-parseable TypeScript #16541 andos generate view classemits a barrel line binding a reserved word — it parses, so both the charset gate and the parse check admit it, and no consumer can import it #17410 layer pins.Generated by Claude Code