Filed unassigned and ungraded by the #12539 dev, session session_01UjujZN219uFzBhSYfMykCd, while hoisting requireBuiltCli() into packages/cli/test/helpers/serve-process.ts. ⛔ Not graded, not routed. ⛔ Deliberately not folded into PR #12617 — see Why it was left below.
Measured
RUN_JS_RESOLVES_FROM_DIST (packages/cli/test/helpers/serve-process.ts) ends:
"… so on an unbuilt tree the child answers "command serve not found" and every boot below times out."
The first clause is exactly right. The second is not what happens. On a closure-only tree (pnpm --filter '@objectstack/cli^...' build, then no packages/cli/dist):
$ env -u NODE_ENV node packages/cli/bin/run.js serve --help
› Error: Command serve not found.
EXIT=2
The child exits, with status 2, immediately. Every one of the four spawners resolves its boot promise from the exit handler, not from the timer:
| file |
rejects at |
serve-mcp-capability-collision.e2e.test.ts:250 |
child.on('exit', …) |
serve-mcp-stdio-answers.e2e.test.ts:247 |
child.on('exit', …) |
serve-stdio-stdout-purity.e2e.test.ts:244 |
child.on('exit', …) |
serve-node-env-production-default.e2e.test.ts:345 |
child.on('exit', …) |
Each of those files also has a timeout (serve never printed … / serve never reached …), and it is a different message. The timeout is not the path an unbuilt tree takes. Measured end-to-end: the failing leg took 178 ms, against a 150 s timer.
⭐ Why it is worth a card
This is the class #12498, #12561 and #12563 were filed for this round — a true refusal carrying a false explanation — arriving inside the very message that exists to end a false red. A reader who follows it looks for a hang, and there is no hang: there is an immediate exit 2 with the real reason already printed on the child's stderr.
⚠️ It is also the most load-bearing place for this defect to sit: this is the sentence a developer on a fresh worktree reads instead of debugging. Severity not judged; observation-class, S — one clause.
Suggested repair, one clause: "… and every boot below fails immediately" (or "… and the spawn below exits 2 before it is ready").
Why it was left out of PR #12617
That PR moved this message out of three byte-identical private copies into one helper, and packages/cli/test/serve-built-cli-prerequisite.test.ts pins it byte-for-byte precisely so a rewording has to be a deliberate edit rather than a side effect of the move. Rewording it in the same PR would destroy the reviewable "moved, not reworded" property that makes the hoist checkable. ⇒ a one-clause follow-up, on top of that PR.
Dedup
Searched open issues for this wording and for the refusal message generally; no open card covers it. ⚠️ Raw REST is 403 from this seat, so the search was the MCP search_issues path plus local git grep — declared, not implied. Nearest neighbours, all distinct: #12498 (three other files, dead stated mechanism), #12561 (a file's header misclassifying its own legs — closed, PR #12569), #12563.
Re-check
git grep -n "times out" -- packages/cli/test/helpers/serve-process.ts
git grep -n "on('exit'" -- packages/cli/test/serve-*.e2e.test.ts
pnpm --filter '@objectstack/cli^...' build && rm -rf packages/cli/dist
env -u NODE_ENV node packages/cli/bin/run.js serve --help ; echo "EXIT=$?"
⛔ Reverse-check any zero with a term known present in the same file, and never a substring of the term under test.
Refs
Filed unassigned and ungraded by the #12539 dev, session
session_01UjujZN219uFzBhSYfMykCd, while hoistingrequireBuiltCli()intopackages/cli/test/helpers/serve-process.ts. ⛔ Not graded, not routed. ⛔ Deliberately not folded into PR #12617 — see Why it was left below.Measured
RUN_JS_RESOLVES_FROM_DIST(packages/cli/test/helpers/serve-process.ts) ends:The first clause is exactly right. The second is not what happens. On a closure-only tree (
pnpm --filter '@objectstack/cli^...' build, then nopackages/cli/dist):The child exits, with status 2, immediately. Every one of the four spawners resolves its boot promise from the
exithandler, not from the timer:serve-mcp-capability-collision.e2e.test.ts:250child.on('exit', …)serve-mcp-stdio-answers.e2e.test.ts:247child.on('exit', …)serve-stdio-stdout-purity.e2e.test.ts:244child.on('exit', …)serve-node-env-production-default.e2e.test.ts:345child.on('exit', …)Each of those files also has a timeout (
serve never printed …/serve never reached …), and it is a different message. The timeout is not the path an unbuilt tree takes. Measured end-to-end: the failing leg took 178 ms, against a 150 s timer.⭐ Why it is worth a card
This is the class #12498, #12561 and #12563 were filed for this round — a true refusal carrying a false explanation — arriving inside the very message that exists to end a false red. A reader who follows it looks for a hang, and there is no hang: there is an immediate
exit 2with the real reason already printed on the child's stderr.Suggested repair, one clause: "… and every boot below fails immediately" (or "… and the spawn below exits 2 before it is ready").
Why it was left out of PR #12617
That PR moved this message out of three byte-identical private copies into one helper, and
packages/cli/test/serve-built-cli-prerequisite.test.tspins it byte-for-byte precisely so a rewording has to be a deliberate edit rather than a side effect of the move. Rewording it in the same PR would destroy the reviewable "moved, not reworded" property that makes the hoist checkable. ⇒ a one-clause follow-up, on top of that PR.Dedup
Searched open issues for this wording and for the refusal message generally; no open card covers it.⚠️ Raw REST is 403 from this seat, so the search was the MCP
search_issuespath plus localgit grep— declared, not implied. Nearest neighbours, all distinct: #12498 (three other files, dead stated mechanism), #12561 (a file's header misclassifying its own legs — closed, PR #12569), #12563.Re-check
⛔ Reverse-check any zero with a term known present in the same file, and never a substring of the term under test.
Refs
packages/cli's e2e spawners silently requirepackages/cli/dist— an unbuilt worktree fails withserve exited 2, indistinguishable from a regression #12539 / PR #12617 — where the message now lives, and why it was not reworded therepackages/clie2e spawners are now honest but 2× slower than the shape that would make them honest AND fast — and nothing stops the self-cancelling pair from being re-introduced #11707 / PR test(cli): reach the built CLI in the three serve e2e spawners #12459 — the three private copies this wording came frompackages/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, 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 — the same defect class, other files