Found while running the machine-lane baseline for the QA wave (#9296, round #9298). Filed as a finding, not fixed — R0 does not land code.
Summary
On a cold checkout (fresh git worktree + pnpm install, nothing built yet), pnpm objectui:build fails within ~20 s, long before it reaches the objectui console build. The console SPA never gets built, so packages/console/dist is never produced and /_console/ stays 404.
scripts/build-console.sh L136-139 pre-builds @objectstack/client by shelling straight into the package:
if [[ !-f"${CLIENT_PKG}/dist/index.mjs" ]];thenecho"→ @objectstack/client dist missing — building it first..."
(cd "$CLIENT_PKG"&& pnpm build)
fipackages/client's own build is tsup --config ../../tsup.config.ts, which emits declarations. Its dependencies include @objectstack/core and @objectstack/spec, and it imports their subpath exports (@objectstack/spec/data, /api, /contracts, /automation, /identity, @objectstack/core/logger) — all of which resolve to ./dist/** via each package's exports map.
Invoking pnpm build in the package directory bypasses turbo, so turbo's ordering is lost. turbo.json declares:
"build": { "dependsOn": ["^build"], "outputs": ["dist/**", ...] }^build is exactly the guarantee being skipped. On a cold tree packages/spec/dist and packages/core/dist do not exist, the subpaths resolve to nothing, and the DTS pass fails.
Environment
- framework sha:
e4e5c6e3c608b1b807c83a0d5b734f213eb1a1dd (tip of main at the time of the run) .objectui-sha: 665661ab093263f39f2e660a295ea615dbcee35a- node v22.22.2, pnpm 10.31.0, linux x64
- tree: fresh
git worktree add --detach + a single pnpm install (exit 0, 35 s); no pnpm build had been run
Reproduction
git worktree add --detach ../objectstack-cold e4e5c6e3c608b1b807c83a0d5b734f213eb1a1dd
cd ../objectstack-cold && pnpm install
pnpm objectui:build # exit 1 in ~18s
Reproduced twice, both exit 1, both failing at the same step (@objectstack/client DTS build).
Run 1 — fully cold, canonical.packages/spec/dist and packages/core/dist both absent:
→ Using objectui source at /home/user/objectui
→ Pinned commit 665661ab0932 not present locally — fetching from origin...
Preparing worktree (detached HEAD 665661ab0)
HEAD is now at 665661ab0 fix(examples): catalog entries author the keys their renderers read (#4624) (#4630)
→ Building @object-ui/console at 665661ab0932...
→ @objectstack/client dist missing — building it first...
> @objectstack/client@17.0.0 build
> tsup --config ../../tsup.config.ts
CJS ⚡️ Build success in 90ms
ESM ⚡️ Build success in 91ms
DTS Build start
src/index.ts(3,91): error TS2307: Cannot find module '@objectstack/spec/data' or its corresponding type declarations.
src/index.ts(79,8): error TS2307: Cannot find module '@objectstack/spec/api' or its corresponding type declarations.
src/index.ts(85,8): error TS2307: Cannot find module '@objectstack/spec/contracts' or its corresponding type declarations.
src/index.ts(86,38): error TS2307: Cannot find module '@objectstack/spec/automation' or its corresponding type declarations.
src/index.ts(87,39): error TS2307: Cannot find module '@objectstack/spec/identity' or its corresponding type declarations.
src/index.ts(88,38): error TS2307: Cannot find module '@objectstack/core/logger' or its corresponding type declarations.
src/index.ts(4973,41): error TS2731: Implicit conversion of a 'symbol' to a 'string' will fail at runtime. Consider wrapping this expression in 'String(...)'.
src/index.ts(5466,8): error TS2307: Cannot find module '@objectstack/spec/api' or its corresponding type declarations.
src/index.ts(5476,8): error TS2307: Cannot find module '@objectstack/spec/contracts' or its corresponding type declarations.
Error: error occurred in dts build
DTS Build error
ELIFECYCLE Command failed with exit code 1.
Run 2 — after rm -rf packages/client/dist, exit 1 in 9 s. This one happened to run alongside a pnpm typecheck that had already emitted packages/spec/dist/**/*.js but not the .d.ts, so the same defect surfaced as TS7016 instead of TS2307 (Could not find a declaration file for module '@objectstack/spec/data'. '…/packages/spec/dist/data/index.js' implicitly has an 'any' type.). @objectstack/core/logger was TS2307 in both runs, and the DTS build failed in both. Same root cause, different observable depending on how far a concurrent job had populated the dep dists.
Second-order problem: the failure self-heals into a silent pass
The guard is [[ ! -f "${CLIENT_PKG}/dist/index.mjs" ]], but tsup writes the CJS/ESM bundles before the DTS pass. So the failed run still leaves packages/client/dist/index.mjs on disk. A plain re-run of pnpm objectui:build therefore skips the client build entirely and proceeds — shipping a client dist whose declarations were never generated.
The console only consumes the runtime JS via OBJECTSTACK_CLIENT_DIST, so the resulting bundle is probably fine at runtime — but the net effect is that the first invocation fails and the second appears to succeed, which reads as flakiness rather than a deterministic ordering bug. Anyone who hits this and just retries will conclude it was transient.
Pre-existing, not a fresh regression
git log -L 136,141:scripts/build-console.sh returns exactly one commit: b990bc258 (2026-07-02, #2513 — the change that introduced injecting this repo's client into the console bundle). That block has been unchanged for 3549 commits. This is latent, not new.
It only bites on a cold tree, which is why it has stayed invisible: any tree where pnpm build, pnpm typecheck, or a prior console build has already populated packages/spec/dist and packages/core/dist sails past the guard. That makes it a fresh-machine / fresh-CI-runner / fresh-worktree defect specifically.
Note this determines the failure mode by static reading of the script plus the one-commit -L history rather than an executed bisect — the QA wave is under a fixed container disk allowance and a second worktree + install was not available to run b990bc258 directly.
Workaround used by the wave
Build the client's dependency closure through turbo first, which honours ^build:
pnpm exec turbo run build --filter=@objectstack/client...
pnpm objectui:build
Suggested direction (not implemented here)
Replace the bare pnpm build with the turbo-mediated equivalent, so the ordering comes from the task graph that already declares it:
pnpm exec turbo run build --filter=@objectstack/client
and consider making the staleness guard test for a declaration artifact (e.g. dist/index.d.mts) rather than dist/index.mjs, so a half-built client is not mistaken for a complete one.
Found while running the machine-lane baseline for the QA wave (#9296, round #9298). Filed as a finding, not fixed — R0 does not land code.
Summary
On a cold checkout (fresh
git worktree+pnpm install, nothing built yet),pnpm objectui:buildfails within ~20 s, long before it reaches the objectui console build. The console SPA never gets built, sopackages/console/distis never produced and/_console/stays 404.scripts/build-console.shL136-139 pre-builds@objectstack/clientby shelling straight into the package:packages/client's own build istsup --config ../../tsup.config.ts, which emits declarations. Itsdependenciesinclude@objectstack/coreand@objectstack/spec, and it imports their subpath exports (@objectstack/spec/data,/api,/contracts,/automation,/identity,@objectstack/core/logger) — all of which resolve to./dist/**via each package'sexportsmap.Invoking
pnpm buildin the package directory bypasses turbo, so turbo's ordering is lost.turbo.jsondeclares:^buildis exactly the guarantee being skipped. On a cold treepackages/spec/distandpackages/core/distdo not exist, the subpaths resolve to nothing, and the DTS pass fails.Environment
e4e5c6e3c608b1b807c83a0d5b734f213eb1a1dd(tip ofmainat the time of the run).objectui-sha:665661ab093263f39f2e660a295ea615dbcee35agit worktree add --detach+ a singlepnpm install(exit 0, 35 s); nopnpm buildhad been runReproduction
Reproduced twice, both exit 1, both failing at the same step (
@objectstack/clientDTS build).Run 1 — fully cold, canonical.
packages/spec/distandpackages/core/distboth absent:Run 2 — after
rm -rf packages/client/dist, exit 1 in 9 s. This one happened to run alongside apnpm typecheckthat had already emittedpackages/spec/dist/**/*.jsbut not the.d.ts, so the same defect surfaced as TS7016 instead of TS2307 (Could not find a declaration file for module '@objectstack/spec/data'. '…/packages/spec/dist/data/index.js' implicitly has an 'any' type.).@objectstack/core/loggerwas TS2307 in both runs, and the DTS build failed in both. Same root cause, different observable depending on how far a concurrent job had populated the dep dists.Second-order problem: the failure self-heals into a silent pass
The guard is
[[ ! -f "${CLIENT_PKG}/dist/index.mjs" ]], but tsup writes the CJS/ESM bundles before the DTS pass. So the failed run still leavespackages/client/dist/index.mjson disk. A plain re-run ofpnpm objectui:buildtherefore skips the client build entirely and proceeds — shipping a client dist whose declarations were never generated.The console only consumes the runtime JS via
OBJECTSTACK_CLIENT_DIST, so the resulting bundle is probably fine at runtime — but the net effect is that the first invocation fails and the second appears to succeed, which reads as flakiness rather than a deterministic ordering bug. Anyone who hits this and just retries will conclude it was transient.Pre-existing, not a fresh regression
git log -L 136,141:scripts/build-console.shreturns exactly one commit:b990bc258(2026-07-02, #2513 — the change that introduced injecting this repo's client into the console bundle). That block has been unchanged for 3549 commits. This is latent, not new.It only bites on a cold tree, which is why it has stayed invisible: any tree where
pnpm build,pnpm typecheck, or a prior console build has already populatedpackages/spec/distandpackages/core/distsails past the guard. That makes it a fresh-machine / fresh-CI-runner / fresh-worktree defect specifically.Note this determines the failure mode by static reading of the script plus the one-commit
-Lhistory rather than an executed bisect — the QA wave is under a fixed container disk allowance and a second worktree + install was not available to runb990bc258directly.Workaround used by the wave
Build the client's dependency closure through turbo first, which honours
^build:pnpm exec turbo run build --filter=@objectstack/client... pnpm objectui:buildSuggested direction (not implemented here)
Replace the bare
pnpm buildwith the turbo-mediated equivalent, so the ordering comes from the task graph that already declares it:pnpm exec turbo run build --filter=@objectstack/clientand consider making the staleness guard test for a declaration artifact (e.g.
dist/index.d.mts) rather thandist/index.mjs, so a half-built client is not mistaken for a complete one.