Repository navigation
test(cli): compile each scaffold sandbox in process, one spawn per distinct lint-eval run, budget the generate/i18n spawn files - #28592
Merged
Conversation
…headers for the generate/i18n spawn files Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5oeaQtmg5DUi2ojVqs
…eclaration files Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5oeaQtmg5DUi2ojVqs
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5oeaQtmg5DUi2ojVqs
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5oeaQtmg5DUi2ojVqs
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
|
domain:server#1 · os-project-manager · session_01R1q2xdtYgU6FKrZ7LgjPCC 席位核对 · ACCEPT ·
|
| item | reading |
|---|---|
| Shape | Draft, base main, Part of #23181. Exactly slice 27's six files in packages/cli/test, labels tests + skip-changeset. Clause-②: no, Metadata-protocol: none. |
| Diff check (seat) | lint-eval-generator-refusal-separator: the four distinct runs spawn once in beforeAll, and the same-door case reads the two machine-face runs instead of re-spawning them; every assertion is kept (6 spawns → 4). scaffold-emission-typechecks: each sandbox is still compiled as its own Program from its own tsconfig.json with tsc --noEmit -p diagnostics; only the read-only lib.*.d.ts and @objectstack/spec declarations are parsed once and shared. typescript is already a cli dependency, and the report shows the verdicts match the tsc child on all 12 sandboxes. Line-2 // test-budget: headers on all six files (50/50/40/40/30/30). No helper outside the six files is touched; no timeout is raised. |
| Evidence | CI green on head cc5ee375 (35 success, 23 skipped, 0 failed). Governed check: NOT governed, 180 changed lines. Mergeable state clean. The report gives 48 of 48 derived gates exit 0, --ran reconciled, and A/B of −25 % (lint-eval) and −39 % (scaffold-emission). |
| Landing | 「按照 pm-dispatch 规则复核过的都授权」 (Leehom, 2026-10-25T11:35Z): ready and auto-merge through the relay, once every check on this head is green or an expected skip. |
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 27, the generate / scaffold / i18n family in
packages/cli/test). The card stays open for later slices.Clause-②: no
Metadata-protocol: none
维护者速读
packages/cli/test里 6 个超过 10 s 的测试文件。lint-eval-generator-refusal-separator去掉两次与前面完全相同的 CLI 子进程(6 次变 4 次);scaffold-emission-typechecks不再每个用例起一个tsc子进程,改为进程内每个脚手架一个独立的 TypeScript Program,共享已解析的 lib 与 spec 声明文件;另外 4 个文件每次子进程都是不同的工作,只加第 2 行// test-budget:头。files[]只有 dist、README、CHANGELOG);没有删改任何断言、用例名、超时或分层;回滚即 revert。packages/cli/test/scaffold-emission-typechecks.test.ts的typecheckProject(进程内编译与声明文件缓存);packages/cli/test/lint-eval-generator-refusal-separator.test.ts的beforeAll;其余 4 个文件只有第 2 行。pnpm --filter @objectstack/cli exec vitest run test/scaffold-emission-typechecks.test.ts→ 13/13 通过,canary 仍以 TS2694 变红。What changes
Slice 23's offender table (the default reporter's per-file line in every Test Core shard log of the five scheduled
ci.ymlruns41199450735,41217827347,41237094739,41255489006,41271604267) names these six files over 10 s with no header.Cause, per file. I counted child processes against distinct (command, flags, fixture) triples:
lint-eval-generator-refusal-separator--jsonruns the cases above it already ranbeforeAll; every case reads them. Header 50scaffold-emission-typecheckstscchildren (canary, 3os inittemplates, 8os ggenerators)lib.*.d.tsand@objectstack/specdeclarations againtsconfig.json, with one shared cache of the parsed declaration files outside the sandboxes. Header 50generate-stack-reachbeforeAlldependency-range-doorsi18n-extract-check-jsoni18n-extract-check-dry-runlint-eval-generator-refusal-separator. The same-door case compared--json --generator ""with--json --generator MISSING_PATH, two runs with the same command, flags and fixture as the first and third cases. It now reads those runs. The pair it compares and every assertion are unchanged. ThebeforeAlltimeout is the old per-case allowance times four.scaffold-emission-typechecks. Each sandbox still compiles as its own Program, from its owntsconfig.json(the onerenderScaffoldTsconfigwrites), so no scaffold can lean on another's declarations. The verdict istsc --noEmit's:getPreEmitDiagnostics(config, options, global, syntactic, semantic, declaration) plus the emit diagnostics, exit 0 exactly when none is an error, and the output is those diagnostics in--pretty falseform. Only files outside the sandbox are cached, keyed by path and parse options. All sandboxes compile under the sameSCAFFOLD_TSCONFIG_COMPILER_OPTIONS; they differ only inrootDirandinclude, which change no parse. This is the compiler's own reuse model: the language service shares source files across programs the same way. The compiler is the sametypescriptpackagetypescript/bin/tscresolved to. The docblock says all this in a new "One compiler, one Program per sandbox" section.Headers (ruling 6181973363 letter B): N = the slowest of the five CI readings × 1.25, rounded up to 10 s. Classes:
spawns the real producer once per single-cause fixturefor the five spawn files,compiles the package type graph onceforscaffold-emission-typechecks. The two fixed files keep their pre-fix CI reading. All six parse withreadTestBudget(scripts/measure-test-shard-timings.mjs).Not changed: no assertion, case name, per-case timeout, tier, project or test helper. No source file.
Tests
A/B (one box, one lock hold, N=3,
--maxWorkers=1, base and head interleaved): the base file's bytes were written into the same path for each base leg and restored fromHEADafter it, checked by blob hash, so both legs ran in the same tier and the sameDECLARATION_READER_FILESslot (azzbase.*copy beside it would not). Vitest'sDurationline, with no per-file line in single-file runs:scaffold-emission-typecheckslint-eval-generator-refusal-separatorEvery leg exit 0, 13/13 and 5/5 tests on both sides.
The in-process verdict matches
tsc(one-time probe, not committed): a copy of the head file ran both the in-process compile and the oldtscchild on every sandbox. Same verdict on all 12, the same error codes (canaryTS2694on both, none elsewhere). A second canary run after all the others, with the cache warm, still answersTS2694.tsc --noEmitexits 2 on an error under TypeScript 6.0.3, so the in-process verdict answers 2 too.All six files on head, in one run: 6/6 files, 41/41 tests.
pnpm --filter @objectstack/cli typecheck(tsc +check:test-typecheck) exit 0.No ablation: test-only, no tested behaviour changed.
Acceptance notes
bin/run-dev.jsthroughnode_modules/.bin/tsx. The migrate files moved toprocess.execPathin slice 12. Oneos lint --eval --json --generator ""spawn here, without the queue-tier manifest: 9.5 to 11.8 s through tsx, 5.3 to 5.4 s through node, with byte-identical stdout. Not taken: the order rules the fix set (sharedbeforeAll, in-process read, header). Carrier: test budget (domain:cli): 119 test file(s) over 10 s of wall in the hourly full battery (Part of #23151) #23181.--checkcontrol over an empty--out. Sharing it would need a helper beyond these files or a file merge, so it was not done.skip-changeset. Test-only.@objectstack/cli'sfiles[]isdist,README.md,CHANGELOG.md, andtest/is not built intodist/, so nofiles[]content changes.Verification
All readings on head
cc5ee375(git rev-parse --short HEAD).node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackgives 48 families. Each ran with its exit code captured before any pipe. Two first reads were container prerequisites and were re-read after meeting them:check-plugin-teardown-shape.mjs --self-testexited 3 on the shallow clone, then 0 aftergit fetch --depth=1of its positive-control commit;check:dual-build-cjs-loadsexited 3 with no full build, then 0 afterpnpm exec turbo run build --concurrency=2(118/118 tasks).--ranreconciliation:✓ dispatch-gates --ran: 48 derived famil(ies) accounted for — 48 run, 0 NOT-MEASURED.pnpm exec eslint --no-inline-configover the six files exit 0 (@objectstack/clihas nolintscript; the repo-widepnpm lintruns in CI).node scripts/check-commit-card-trailers.mjs --range origin/main..HEADexit 0.pm-orders/server/evidence/23181-s27/in the project files.🤖 Generated with Claude Code
https://claude.ai/code/session_01FEkQ5oeaQtmg5DUi2ojVqs