Skip to content

test(cli): spawn the source entry under node, not the tsx binary, in 34 test files - #28625

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-5d91ie
Nov 1, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-5d91ie

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

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、参数、超时都不变。
  • 为什么改:卡 test budget (domain:cli): 119 test file(s) over 10 s of wall in the hourly full battery (Part of #23151) #23181 的测试提速职责。tsx 包装只多出一个进程和一次自身的转译,每次子进程白付几秒;slice 27 实测同一条命令 tsx 9.5–11.8 s、node 5.3–5.4 s,stdout 字节相同。
  • 风险与回滚:只改测试文件,不发布任何东西(cli 的 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/cli test files that still name tsx on origin/main outside slices 24–28 and test/helpers/**. I sorted each one first.

(a) The switch applies: 34 files. Each spawned bin/run-dev.js through the tsx binary, and none of them is about that entry. Each now spawns process.execPath with bin/run-dev.js as the first argument, slice 12's way. The child env, cwd, argv, stdin, maxBuffer and timeouts are unchanged. The local const TSX (or the TSX import from the shared helper) goes, a runner named runTsx whose every call spawns the CLI is renamed runCli, and the prose that said "through tsx" now says node.

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-name

  • generate-skill.e2e is the one mixed file. Its two CLI spawns move to node. Its parse probe imports a generated bare .ts module with an extensionless specifier, which plain node cannot load, so the probe stays on the tsx binary through a two-argument runChild(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.integration and serve-host-config-metadata-door.integration imported TSX from test/helpers/serve-process.ts but spawn in their own code, so only the import changes; the helper is untouched.
  • The tier is unchanged: vitest-tiers.ts still reads every file as a spawner through its run-dev.js entry name.

(b) Already on node, or tsx in prose only: 6 files, nothing to do.

file why
src/commands/child-env-source-loader.pin spawns nothing; tsx appears in prose and in a specimen string
src/commands/migrate/plan.declared-default-datasource.integration slice 12 moved it to process.execPath; prose only
src/commands/migrate/plan.telemetry-sibling.integration same
src/commands/dev-database-directory already process.execPath; --import tsx loads an inline -e script that imports src/ (.js specifiers onto .ts files), not the CLI entry, and plain node cannot resolve those
src/utils/make-directory same shape as dev-database-directory
test/serve-built-cli-prerequisite spawns nothing; tsx in prose only

(c) The test pins the tsx or run-dev.js entry itself: 5 files, keep tsx.

file why
test/run-dev-cwd-tsconfig-redirect.e2e its subject is tsx honouring the cwd tsconfig and the shim's re-exec with TSX_TSCONFIG_PATH
test/start-signal-forwarding.e2e already process.execPath, with the tsx loader as --import on purpose: the tsx CLI would put a relay process between the test and the pid it signals
test/invocation-loudness.e2e pins what a shell sees when the package barrel src/index.ts is run as if it were the CLI (only tsx runs a bare .ts file), plus the shims' own success path
test/released-port-production-spawn.pin a source census; spawns nothing; TSX appears only in specimen sources and in its own vocabulary
test/unbuilt-workspace-lead.test spawns nothing; pins the remedy text, which names tsx

Not 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 from HEAD after it, checked by blob hash, so both legs ran in the same tier slot. .e2e files ran with OS_TEST_TIERS=nightly, the rest with queue (the queue tier writes the oclif test manifest once per run, as in CI). Whole process wall per run, in seconds:

    file command base head mean change
    build-strict-body-count os build 36.2, 31.5, 32.7 26.6, 26.6, 26.0 33.5 → 26.4 −21.0%
    generate-refuses-unparseable-name os generate 20.3, 20.9, 20.6 18.1, 18.6, 18.4 20.6 → 18.4 −10.9%
    validate-view-container-name os validate 32.3, 31.6, 31.6 28.9, 28.2, 28.8 31.8 → 28.6 −10.0%
    qa-requires-skip-run os qa 14.7, 13.3, 14.6 13.5, 13.2, 14.1 14.2 → 13.6 −4.2%
    dev-no-watch.pin os dev 53.2, 49.7, 50.4 41.4, 42.6, 41.0 51.1 → 41.6 −18.5%
    migrate-exit-code.e2e os migrate 40.2, 37.7, 39.3 23.8, 23.1, 23.2 39.1 → 23.4 −40.1%
    create-refuses-invalid-project-name.e2e os create 43.8, 42.2, 46.1 28.6, 28.9, 30.1 44.0 → 29.2 −33.7%

    Every 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 .e2e files, 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 --version and tsx bin/run-dev.js --version give byte-identical stdout and stderr on this tree.

  • pnpm --filter @objectstack/cli typecheck (tsc plus check:test-typecheck) exit 0.

  • No ablation: test-only, no tested behaviour changed.

Acceptance notes

Verification

All readings on head b2400351 (git rev-parse --short HEAD), the merge of origin/main after slices 25, 26 and 27 landed (#28601, #28599, #28592). None of them touched these 34 files; the merge had no conflict.

  • Derived gate families: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack gives 52 families. Each ran with its exit code captured before any pipe, after a full pnpm exec turbo run build --concurrency=2 (118/118 tasks) on the merged tree. --ran reconciliation: ✓ dispatch-gates --ran: 52 derived famil(ies) accounted for — 52 run, 0 NOT-MEASURED. On the pre-merge head 01d2b0d5 the same set (51 families) was green too; there check:i18n-coverage first exited 3 (an unbuilt @objectstack/connector-slack) and read 0 after the full build, and check-plugin-teardown-shape.mjs --self-test needed its positive-control commit fetched on the shallow clone.
  • The 34 switched files on the merged head: queue tier 17/17 files, 125/125 tests; nightly tier 17/17 files, 113/113 tests.
  • Hand gates: pnpm --filter @objectstack/cli typecheck exit 0. pnpm exec eslint --no-inline-config over the 34 files exit 0 (@objectstack/cli has no lint script; the repo-wide pnpm lint runs in CI). node scripts/check-commit-card-trailers.mjs --range origin/main..HEAD exit 0.
  • CI families (Test Core with both cli tiers, the nightly .e2e tier on main, the lint farm, the type-check lanes) are read off this PR's check-runs by the seat.
  • Evidence (gate lists with exit codes for both heads, every A/B row, the A/B script): pm-orders/server/evidence/23181-s29/ in the project files.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FEkQ5pFGjmwfPzsnkVqJPu

…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
@github-actions github-actions Bot added the tests label Nov 1, 2026
@github-actions

github-actions Bot commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing 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): node scripts/docs-audit/affected-docs.mjs --json 28ef35e0e3799e1305e82c2d12f0515ca6bf519c → packageMentionDocs.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:server#1 · os-project-manager · session_01R1q2xdtYgU6FKrZ7LgjPCC

席位核对 · ACCEPT · domain:server seat 1 · os-project-manager · session_01R1q2xdtYgU6FKrZ7LgjPCC · 2026-11-01T09:16Z

Head b2400351, report 6555836120 (on #23181), claim 6555841491 (slice 29). No contract review is owed: test-only, no packages/spec/** path, no governed path, no narrowing and no Clause-②: yes.

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

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 1, 2026 09:19
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge November 1, 2026 09:19
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Nov 1, 2026
@github-actions github-actions Bot added the size/m label Nov 1, 2026
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 1, 2026
Merged via the queue into main with commit 49d60d3 Nov 1, 2026
48 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-5d91ie branch November 1, 2026 11:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant