Uh oh!
There was an error while loading. Please reload this page.
test(cli): one built-CLI prerequisite for all four bin/run.js spawners, each refusing in its own terms - #12617
Conversation
…ilt-cli-prerequisite-coverage
… spawner
`serve-node-env-production-default.e2e.test.ts` is the one spawner of the built
entrypoint that had no `requireBuiltCli()` preflight. It gets one -- with its
OWN mechanism string rather than the siblings' `RUN_JS_RESOLVES_FROM_DIST`.
Only this file's unset-NODE_ENV leg resolves from `dist/`; its other two legs
hand the child `development`/`test`, which flips oclif's `isProd()` and reroutes
them to `src/commands`. The siblings' sentence ("every boot below times out")
is therefore false here, and a true refusal carrying a false explanation is the
defect class #12498 / #12561 / #12563 were filed for.
The guard is file-scoped deliberately: measured on a closure-only tree, this
file reported `3 tests | 1 failed` -- the unset pin failing while the two
rerouted legs PASSED from `src/`, reporting green for a program the file's own
header says it does not measure.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjujZN219uFzBhSYfMykCd📓 Docs Drift Check4 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run. What this run could not see
Coarse fallback — 23 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 114baa35577136b9d1dc00544f7ffb7c81eb5c04 && git checkout 114baa35577136b9d1dc00544f7ffb7c81eb5c04
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 527e0505d8729ae022121a992b62326035953a82 764847a35d575eec075ced57e90ac852366a4bec && git checkout -B drift-repro 527e0505d8729ae022121a992b62326035953a82 && git merge --no-ff 764847a35d575eec075ced57e90ac852366a4bec
node scripts/docs-audit/affected-docs.mjs --json 527e0505d8729ae022121a992b62326035953a82 |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#12539
What the measurement says, before what the diff does
The card claims 4 failing files on a closure-only build. ⭐ The number is right; the attribution in the dispatch order was not. Three independent derivations agree on the same four files:
The repo's own CI detector.
scripts/check-cli-test-child-env.mjsexportsbuiltEntrypointSpawns(), which is what thecheck:cli-test-child-envgate uses to find spawns ofbin/run.js. Run over all 99 files underpackages/cli/test/**it names exactly four, one spawn each:requireBuiltCli()onorigin/mainserve-mcp-capability-collision.e2e.test.tsserve-mcp-stdio-answers.e2e.test.tsserve-stdio-stdout-purity.e2e.test.tsserve-node-env-production-default.e2e.test.tsThe gate's own summary line prints the same count independently:
all 4 spawn(s) of the built CLI keep their child out of development/test.The throw sites.
serve exited N before "Server is ready"is produced by each of those four files' own inline boot helper. ⛔ It is not produced byhelpers/serve-process.ts— that helper'srunServe()path spawnsbin/run-dev.jsthrough tsx, readssrc/, and needs nopackages/cli/distat all.The empirical run, below.
run-dev.js+ tsx family is falsified: the failing set is exactly thebin/run.jsfamily, andrequireBuiltCli()is the right instrument for all four.invocation-loudness.e2e.test.tsresolvesbin/run.jsbut only ever asserts on the string, and is correctly outside the population (the gate pins that distinction with its own case).What changed
The three private copies are hoisted, not copied a fourth time. They were byte-identical — all three hash to⚠️ not 21, as the claim comment said). They now live once in
56b0e32ead67917a296d342d2eab6be9b8b3f363— and 19 lines each (test/helpers/serve-process.tsasrequireBuiltCli(mechanism).The reason is a required parameter, and that is the load-bearing part. The copied sentence "This file spawns
bin/run.jswithNODE_ENVunset … and every boot below times out" is true of those three and of nothing else. It ships as the exported constantRUN_JS_RESOLVES_FROM_DIST, which those three pass; a caller reaching the CLI a different way must supply its own. ⛔ Nothing defaults it.The fourth file is now covered, with its own mechanism string. ⭐ This is where the parameter earns itself.
serve-node-env-production-default.e2e.test.tshas three legs, and only the unset-NODE_ENVone resolves fromdist/; the other two hand the childdevelopment/test, which flips@oclif/core'sisProd()and reroutes them tosrc/commands(the file's own header says so, andcheck-cli-test-child-env.mjspins both asDELIBERATE_REROUTE). PassingRUN_JS_RESOLVES_FROM_DISTthere would have been a true refusal with a false explanation — the class Threepackages/cli/testspawner comments carry a DEAD counterfactual —detectModestopped readingVITESTin #11448, so the reason they give for supplyingOS_SECRET_KEYis false (the conclusion is right) #12498,serve-node-env-production-default.e2e.test.ts's header says only the builtdist/entrypoint reaches the gate — two of its own three legs executesrc/commands#12561 and The flow-shadowing operator sentence is written three times with nothing holding the copies equal — and the two pre-existing copies already disagree on quoting AND on absent-id handling #12563 were filed for. It getsUNSET_LEG_MEASURES_THE_BUILT_DISTinstead.The guard runs for the whole file, deliberately — and the measurement below is why, not a comment.
serve-built-cli-prerequisite.test.tspins the wording, which nothing else can: the message is only ever produced on an unbuilt tree, and no test can produce one without breaking every neighbouring file in the same run.The premise, measured — with controls
Closure-only tree:
pnpm --filter '@objectstack/cli^...' build(note^...— dependencies excluding@objectstack/cli), thenpackages/cli/distremoved and its absence verified on disk.Before this PR:
The two that passed are the controls —
serve-app-runtime-hooks.e2e.test.tsandserve-no-artifact.e2e.test.ts, bothrunServe()/tsx files. ⇒ the failing set is thebin/run.jsfamily and nothing else.The mechanism, reproduced directly on the same tree:
⭐ And the fourth file's failure was a partial green — which is the whole reason its guard is file-scoped.
3 tests | 1 failed: the unset pin failed, and the two rerouted legs passed fromsrc/, reporting green for a program the file's own header says it does not measure.Both directions
Same tree, both legs in one run, the restore proven on disk between them.
Positive — the guard fires, on all four, each in its own words:
serve-node-env-production-default.e2e.test.tsnow reports(3 tests | 3 skipped)— ⭐ all three legs refused, where before the guard it was3 tests | 1 failed. The partial green is gone. Its refusal carries its own sentence:…while the three siblings still carry
RUN_JS_RESOLVES_FROM_DISTverbatim. ⇒ ⛔ thebin/run.jssentence did not travel outward, and both refusals name the build command.Negative — the guard is silent on a correctly built tree.⚠️ The expensive half: a guard that fired here would make every green in this directory a coin flip.
dist/commands/serve.jsabsent, verified)1pnpm --filter @objectstack/cli build00Scope — what is covered and what is left
⭐ Coverage is complete for the population, not partial. The
bin/run.jsfamily has exactly four members and all four are now guarded.packages/cli/test/**(git diff --name-onlyvs each branch's merge base) and none of them touches a single file there. #12561, named as a live holder onserve-node-env-production-default.e2e.test.tsat dispatch time, is closed (PR #12569, merged); PR #12565 merged too. So nothing was left out for fencing reasons.Deliberately not changed:
turbo.json,.github/workflows/**, and everypackage.jsonscript. The@objectstack/cli#test dependsOn builddeclaration (fix(cli): os serve defaults NODE_ENV to production when unset #11268) is what makes CI immune and is correct; this card is about the directvitestrun in a fresh worktree.serve-built-cli-prerequisite.test.tspins it byte-for-byte so a future rewording has to be a deliberate edit.exit; it does not time out. Fixing it here would destroy the reviewable "moved, not reworded" property, so it is filed separately as [finding] the built-CLI refusal says "every boot below times out"; measured, the child exits 2 immediately and the boot rejects onexit#12618.Changeset
None —
skip-changeset, applied as a label and read back after the size-labeler settled (size/m,tests,skip-changeset). Every file in this diff is underpackages/cli/test/**: nosrc/, no public surface, nothing published. AGENTS.md's rule is "add a changeset for feature work … pure bug fixes do not require a changeset", andpr-automation.ymldefines the label as "this PR declares no release of its own".pnpm --filter @objectstack/cli typecheckexits 0, and that is NOT MEASURED for this diff:packages/cli/tsconfig.jsonisinclude: ["src"], sotsc --listFilesreads 0 of 1279 files underpackages/cli/test/(reverse-checked —src/commands/serve.tsscores 1 in the same output). Every file here lives intest/.pnpm check:type-check-coverageexits 0, so this is a ledgered, pre-existing state this PR does not move — but the green typecheck should not be read as covering these files.Verdict on the inherited
wip:commit (3c84e9fc5)Adopted as-is, and extended. Judged adversarially rather than rewritten:
wip:label meant — is the premise measurement. That is supplied above.Generated by Claude Code