Repository navigation
test(cli): spawn the source entry under node, not the tsx binary, in 34 test files - #28625
Merged
Merged
Conversation
…34 test files The source entry bin/run-dev.js runs the same under this process's own node: the entry, its src/ and its pinned NODE_ENV=development do not change, and the tsx wrapper only adds a second process and its own transform to every spawn. Slice 12 moved the migrate files this way; these 34 files outside the other live slices follow. generate-skill keeps tsx for its parse probe, a bare .ts file, and spawns the CLI under node. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5pFGjmwfPzsnkVqJPu
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. 34 of slice 29's 45 listed packages/cli test files (6 needed nothing, 5 keep tsx with a named reason), labels tests + skip-changeset. Clause-②: no, Metadata-protocol: none. |
| Diff check (seat) | Read per file: every removed TSX spawn of bin/run-dev.js became process.execPath with the same [CLI, …] argv, cwd, env and stdio; the only TSX kept in a switched file is generate-skill's probe of a .ts file, which node cannot load. Removed lines are otherwise the now-unused TSX constants and imports and prose that named the tsx wrapper. No numeric timeout changed, no assertion changed, no helper touched. |
| Evidence | CI green on head b2400351 (23 success, 18 skipped, 0 failed; the CI and Lint & Type Check workflow runs both success). Governed check: NOT governed, 294 changed lines. The report gives 34/34 switched files passing (238 tests) on the merged head, 52 of 52 derived gates exit 0 with --ran reconciled, and A/B N=3 on 7 files of −4 % to −40 %. |
| 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 29, the tsx wrapper lever across the cli test files outside slices 24–28). The card stays open for later slices.
Clause-②: no
Metadata-protocol: none
维护者速读
packages/cli里 34 个测试文件起 CLI 子进程时,不再经node_modules/.bin/tsx包一层,改为用当前进程自己的node(process.execPath)直接跑bin/run-dev.js,与 slice 12 对 migrate 文件的做法一致。入口、src/、NODE_ENV=development、子进程的 env、cwd、参数、超时都不变。files[]只有 dist、README、CHANGELOG);没有改任何断言、用例名、超时、分层或// test-budget:头;回滚即 revert。packages/cli/test/generate-skill.e2e.test.ts(唯一手改:CLI 走 node,解析探针是裸.ts文件,仍走 tsx);packages/cli/test/package-install-local-handlers.integration.test.ts(os start启动走 node);其余 32 个文件只是TSX→process.execPath并删掉常量。pnpm --filter @objectstack/cli exec vitest run test/build-strict-body-count.test.ts→ 6/6 通过,墙钟约 26 s(改前约 33 s)。What changes
The order lists 45
packages/clitest files that still nametsxonorigin/mainoutside slices 24–28 andtest/helpers/**. I sorted each one first.(a) The switch applies: 34 files. Each spawned
bin/run-dev.jsthrough the tsx binary, and none of them is about that entry. Each now spawnsprocess.execPathwithbin/run-dev.jsas the first argument, slice 12's way. The child env, cwd, argv, stdin,maxBufferand timeouts are unchanged. The localconst TSX(or theTSXimport from the shared helper) goes, a runner namedrunTsxwhose every call spawns the CLI is renamedrunCli, and the prose that said "through tsx" now saysnode.src/commands/validate-json-strict-exit.e2e·test/build-callable-names·build-connector-spec-file-artifact.e2e·build-demo-staff-artifact·build-docs-step-count.e2e·build-runtime-bundle-bodyless·build-seed-files-artifact.e2e·build-strict-body-count·build-view-container-name·create-refuses-invalid-project-name.e2e·dev-no-watch.pin·generate-agent-retired.e2e·generate-object-namespace-prefix.e2e·generate-refuses-name-outside-charset·generate-refuses-unimportable-alias·generate-refuses-unparseable-name·generate-skill.e2e·hook-body-build-reach.e2e·migrate-apply-refuses-before-ddl.e2e·migrate-exit-code.e2e·migrate-unloadable-host-config-exit.e2e·package-install-local-handlers.integration·qa-names-and-tags-run·qa-requires-skip-run·refusal-renders-once.e2e·retry-policy-key-validate-door·rule-line-explain-pointer.e2e·scaffold-emission-policy.e2e·serve-host-config-metadata-door.integration·stack-datasource-default-validate-door·validate-field-predicate-traversal·validate-json-warning-parity.e2e·validate-top-level-strict.e2e·validate-view-container-namegenerate-skill.e2eis the one mixed file. Its two CLI spawns move to node. Its parse probe imports a generated bare.tsmodule with an extensionless specifier, which plain node cannot load, so the probe stays on the tsx binary through a two-argumentrunChild(bin, args, cwd).migrate-apply-refuses-before-ddl.e2e,migrate-unloadable-host-config-exit.e2e,qa-names-and-tags-run,qa-requires-skip-run,package-install-local-handlers.integrationandserve-host-config-metadata-door.integrationimportedTSXfromtest/helpers/serve-process.tsbut spawn in their own code, so only the import changes; the helper is untouched.vitest-tiers.tsstill reads every file as a spawner through itsrun-dev.jsentry name.(b) Already on node, or tsx in prose only: 6 files, nothing to do.
src/commands/child-env-source-loader.pinsrc/commands/migrate/plan.declared-default-datasource.integrationprocess.execPath; prose onlysrc/commands/migrate/plan.telemetry-sibling.integrationsrc/commands/dev-database-directoryprocess.execPath;--import tsxloads an inline-escript that importssrc/(.jsspecifiers onto.tsfiles), not the CLI entry, and plain node cannot resolve thosesrc/utils/make-directorydev-database-directorytest/serve-built-cli-prerequisite(c) The test pins the tsx or
run-dev.jsentry itself: 5 files, keep tsx.test/run-dev-cwd-tsconfig-redirect.e2eTSX_TSCONFIG_PATHtest/start-signal-forwarding.e2eprocess.execPath, with the tsx loader as--importon purpose: the tsx CLI would put a relay process between the test and the pid it signalstest/invocation-loudness.e2esrc/index.tsis run as if it were the CLI (only tsx runs a bare.tsfile), plus the shims' own success pathtest/released-port-production-spawn.pinTSXappears only in specimen sources and in its own vocabularytest/unbuilt-workspace-lead.testNot changed: no assertion, expected output, case name, timeout, tier, project,
// test-budget:header or test helper. No source file.Tests
A/B (one box, one lock hold, N=3,
--maxWorkers=1, base and head interleaved, base first in rounds 1 and 3, head first in round 2): for each base leg the base file's bytes were written into the same path and restored fromHEADafter it, checked by blob hash, so both legs ran in the same tier slot..e2efiles ran withOS_TEST_TIERS=nightly, the rest withqueue(the queue tier writes the oclif test manifest once per run, as in CI). Whole process wall per run, in seconds:build-strict-body-countos buildgenerate-refuses-unparseable-nameos generatevalidate-view-container-nameos validateqa-requires-skip-runos qadev-no-watch.pinos devmigrate-exit-code.e2eos migratecreate-refuses-invalid-project-name.e2eos createEvery leg exit 0, with the same test count on both sides (6, 13, 5, 7, 8, 5, 6). The saving is larger on the nightly
.e2efiles, which run without the queue tier's oclif manifest, so each tsx spawn there also paid the full command import twice over.All 34 switched files on head
01d2b0d5(and again on the merged head, below): queue tier 17/17 files, 125/125 tests; nightly tier 17/17 files, 113/113 tests.Same output through both binaries:
node bin/run-dev.js --versionandtsx bin/run-dev.js --versiongive byte-identical stdout and stderr on this tree.pnpm --filter @objectstack/cli typecheck(tsc pluscheck:test-typecheck) exit 0.No ablation: test-only, no tested behaviour changed.
Acceptance notes
test/helpers/serve-process.tsexportsTSX, andrunServe()spawnsservethrough it; 20 cli test files callrunServe(. The order keepstest/helpers/**out of this slice because slices 24–28 run on top of it. Carrier: test budget (domain:cli): 119 test file(s) over 10 s of wall in the hourly full battery (Part of #23151) #23181.invocation-loudness.e2ecould move half. Its twobin/run-dev.jsspawns (dev --no-ui,--version) share one runner with the barrel spawns. Kept on tsx as the order names the file, which pins the shims. Carrier: test budget (domain:cli): 119 test file(s) over 10 s of wall in the hourly full battery (Part of #23151) #23181.package-install-local-handlers.integration's line-2 header still says "the tsx source entry". The order forbids touching// test-budget:headers in this slice; the next shard-timings refresh resizes and can reword it.skip-changeset. Test-only.@objectstack/cli'sfiles[]isdist,README.md,CHANGELOG.md;test/andsrc/**/*.test.tsdo not build intodist/, so nofiles[]content changes.Verification
All readings on head
b2400351(git rev-parse --short HEAD), the merge oforigin/mainafter slices 25, 26 and 27 landed (#28601, #28599, #28592). None of them touched these 34 files; the merge had no conflict.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackgives 52 families. Each ran with its exit code captured before any pipe, after a fullpnpm exec turbo run build --concurrency=2(118/118 tasks) on the merged tree.--ranreconciliation:✓ dispatch-gates --ran: 52 derived famil(ies) accounted for — 52 run, 0 NOT-MEASURED. On the pre-merge head01d2b0d5the same set (51 families) was green too; therecheck:i18n-coveragefirst exited 3 (an unbuilt@objectstack/connector-slack) and read 0 after the full build, andcheck-plugin-teardown-shape.mjs --self-testneeded its positive-control commit fetched on the shallow clone.pnpm --filter @objectstack/cli typecheckexit 0.pnpm exec eslint --no-inline-configover the 34 files exit 0 (@objectstack/clihas nolintscript; the repo-widepnpm lintruns in CI).node scripts/check-commit-card-trailers.mjs --range origin/main..HEADexit 0..e2etier onmain, the lint farm, the type-check lanes) are read off this PR's check-runs by the seat.pm-orders/server/evidence/23181-s29/in the project files.🤖 Generated with Claude Code
https://claude.ai/code/session_01FEkQ5pFGjmwfPzsnkVqJPu