You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
packages/cli e2e tests that spawn bin/run.js as "the SHIPPED entrypoint" never reach dist/ — oclif's ts-path reroutes them to src/ under NODE_ENV=test|development #11317
Found while diagnosing the CI red on #11268 (issue #11113). Unassigned, filed for triage rather than fixed there — #11268's surface is ruled closed.
The claim three files make, and the measurement that contradicts it
packages/cli/test/serve-mcp-stdio-answers.e2e.test.ts:53, serve-mcp-capability-collision.e2e.test.ts:54 and serve-stdio-stdout-purity.e2e.test.ts:50 each carry the identical comment:
/** `bin/run.js` — the SHIPPED entrypoint, i.e. the one the card's repro names. */constCLI=resolve(HERE,'../bin/run.js');
They do spawn that stub. They do not reach packages/cli/dist.
Two facts compose:
packages/cli/dist is never built for these tests.turbo.json declares "@objectstack/cli#test": { "dependsOn": ["^build"] } — dependencies only, not the package's own build. Measured: pnpm exec turbo run test --filter=@objectstack/cli --dry=json yields 58 tasks, 57 of them #build, and @objectstack/cli#test's resolved dependency list does not contain @objectstack/cli#build. invocation-loudness.e2e.test.ts:34-35 already states this fact in prose.
All three spawns set NODE_ENV: 'development' in the child env (:115, :119, :109 respectively — for the --dev admin seed). @oclif/core@4.13.3's tsPath() skips the TypeScript path lookup only when isProd(), and lib/util/util.js:66 defines that as:
So under development (or vitest's inherited test) oclif rewrites the command target from the declared ./dist/commands to ./src/commands and auto-transpiles. The compiled artifact is never consulted.
Measured directly, packages/cli/dist absent:
$ env -u NODE_ENV node packages/cli/bin/run.js serve …
› Error: command serve not found
$ NODE_ENV=production node packages/cli/bin/run.js serve …
› Error: command serve not found
$ NODE_ENV=test node packages/cli/bin/run.js serve …
(node:22544) [MODULE_NOT_FOUND] Warning: ModuleLoadError
task: findCommand (compile)
message: … import() failed to load …/packages/cli/src/commands/compile.ts …
$ NODE_ENV=development node packages/cli/bin/run.js serve …
(same — resolution proceeds from src/)
The test/development legs get past command resolution and into src/; unset and production do not.
packages/cli/vitest.config.ts's cost header reasons about "swapping the spawns to the built entry" as an unrealised speed lever, and quotes node bin/run.js --version 2.9-3.2s against tsx bin/run-dev.js --version 6.5-6.8s. These files already spell bin/run.js and do not get that 2.9s path — they pay the transpile cost anyway. The header's measurement stands; its framing of these files does not.
Anyone reading these three as the pattern for "test the built CLI" copies a shape that silently does not.
#11267 is the inherited TEST=true making better-auth skip origin checks. This is oclif rerouting command resolution to source. Same family (a spawned child's env quietly changing what is under test), different mechanism, different remedy.
Shape of a fix, not prescribed
Either the three files stop claiming the built entry (spawn bin/run-dev.js like the other ~20 e2e files here, and delete the comment), or they genuinely get one (declare the build dependency and stop forcing a ts-path-enabling NODE_ENV — which means finding another way to reach the --dev admin seed, since that is why they set development). The first is honest and cheap; the second is what the comment currently promises. Whoever takes it should also decide whether packages/cli wants a lint rule making "spawns bin/run.js" and "sets a ts-path-enabling NODE_ENV" mutually exclusive, since the combination is silently self-cancelling.
Found while diagnosing the CI red on #11268 (issue #11113). Unassigned, filed for triage rather than fixed there — #11268's surface is ruled closed.
The claim three files make, and the measurement that contradicts it
packages/cli/test/serve-mcp-stdio-answers.e2e.test.ts:53,serve-mcp-capability-collision.e2e.test.ts:54andserve-stdio-stdout-purity.e2e.test.ts:50each carry the identical comment:They do spawn that stub. They do not reach
packages/cli/dist.Two facts compose:
packages/cli/distis never built for these tests.turbo.jsondeclares"@objectstack/cli#test": { "dependsOn": ["^build"] }— dependencies only, not the package's own build. Measured:pnpm exec turbo run test --filter=@objectstack/cli --dry=jsonyields 58 tasks, 57 of them#build, and@objectstack/cli#test's resolved dependency list does not contain@objectstack/cli#build.invocation-loudness.e2e.test.ts:34-35already states this fact in prose.All three spawns set
NODE_ENV: 'development'in the child env (:115,:119,:109respectively — for the--devadmin seed).@oclif/core@4.13.3'stsPath()skips the TypeScript path lookup only whenisProd(), andlib/util/util.js:66defines that as:So under
development(or vitest's inheritedtest) oclif rewrites the command target from the declared./dist/commandsto./src/commandsand auto-transpiles. The compiled artifact is never consulted.Measured directly,
packages/cli/distabsent:The
test/developmentlegs get past command resolution and intosrc/; unset andproductiondo not.Why it matters
Three flavours of loss, none of them loud:
tscoutput difference (emit,exportsresolution, adist-only path bug of the cli:packages/cli/dist/index.jsinvoked directly exits 0 with zero output, anddev's unknown-flag failure presents as a crashed boot (carved from #10087) #10111 kind) is invisible to them.packages/cli/vitest.config.ts's cost header reasons about "swapping the spawns to the built entry" as an unrealised speed lever, and quotesnode bin/run.js --version 2.9-3.2sagainsttsx bin/run-dev.js --version 6.5-6.8s. These files already spellbin/run.jsand do not get that 2.9s path — they pay the transpile cost anyway. The header's measurement stands; its framing of these files does not.Not the same thing as #11267
#11267 is the inherited
TEST=truemaking better-auth skip origin checks. This is oclif rerouting command resolution to source. Same family (a spawned child's env quietly changing what is under test), different mechanism, different remedy.Shape of a fix, not prescribed
Either the three files stop claiming the built entry (spawn
bin/run-dev.jslike the other ~20 e2e files here, and delete the comment), or they genuinely get one (declare the build dependency and stop forcing a ts-path-enablingNODE_ENV— which means finding another way to reach the--devadmin seed, since that is why they setdevelopment). The first is honest and cheap; the second is what the comment currently promises. Whoever takes it should also decide whetherpackages/cliwants a lint rule making "spawnsbin/run.js" and "sets a ts-path-enablingNODE_ENV" mutually exclusive, since the combination is silently self-cancelling.Related
NODE_ENV !== 'production'still open in a real production deployment that never sets NODE_ENV (os servedoes not force it,os startdoes) #11113 — where this was found. That PR's pin is currently the only file inpackages/clithat genuinely consumesdist/, because it is the only one that spawns withNODE_ENVunset — which is exactly the value that disables the reroute.os serveunder vitest inheritTEST=true, which makes better-auth silently skip origin/CSRF validation regardless ofNODE_ENV#11267 — sibling env-leak false-green in the same suite.packages/cli/dist/index.jsinvoked directly exits 0 with zero output, anddev's unknown-flag failure presents as a crashed boot (carved from #10087) #10111 — the card that addedinvocation-loudness.e2e.test.tsand thedist/index.jsdiagnosability work.Every line and path above was re-derived in a dedicated worktree at
adb1b9ea8c.Generated by Claude Code