Filed unassigned and ungraded by the #12539 dev, session session_01UjujZN219uFzBhSYfMykCd. Met while measuring #12539's failing set. ⛔ Not graded, not routed. The file is currently fenced by PR #12569, so nothing was touched.
Measured
packages/cli/test/serve-node-env-production-default.e2e.test.ts:388 creates its fixture inside the tracked test tree, not the system tmpdir:
constFIXTURES_ROOT=HERE;// = packages/cli/test/dir=mkdtempSync(join(FIXTURES_ROOT,'tmp-node-env-default-'));
⭐ That location is correct and deliberate — the file's own docblock gives the measured reason: the fixture config does a static import { AuthPlugin } from '@objectstack/plugin-auth', which resolves only because packages/cli/node_modules/ is reachable by Node's upward walk from wherever the config lives. A fixture in os.tmpdir() has no such ancestor. ⛔ This is not a request to move it.
The defect is the other half: nothing keeps the directory out of git, and cleanup does not survive a failure.
.gitignore carries *.tmp and tmp/. Neither matches tmp-node-env-default-* — verified: git check-ignore -v packages/cli/test/tmp-node-env-default-XXXX reports it is NOT ignored.afterAll (line 397) awaits stop(child) for every child beforermSync(dir, …), so any throw or timeout in the child-teardown loop skips the removal entirely.
Observed on 09b4f4e4e with the dependency closure built and packages/cli/dist absent — i.e. the fresh-worktree state #12539 is about, where this file's it fails. After that run:
packages/cli/test/tmp-node-env-default-zVfZgc/objectstack.config.ts
packages/cli/test/tmp-node-env-default-zVfZgc/package.json
were still on disk, untracked. After a run where the same file passes, they are gone — so the leak is specifically on the failing path, which is the path a developer is most likely to be on when they reach for git add -A.
⚠️ Why it is worth a card
Three costs, in ascending order:
git status is no longer a clean signal in the worktree, which is what a parallel-agent container leans on.- A stray
package.json changes what tooling derives.node scripts/pm/dispatch-gates.mjs reads the working tree including untracked files; with the leftover present it derived three extra gate families for an unrelated change set — check:override-consistency, check-changeset-fixed.mjs and check-osv-exemptions.mjs — matched solely via packages/cli/test/tmp-node-env-default-zVfZgc/package.json through validate-deps.yml's **/package.json trigger. It exits 0 and the list looks ordinary. git add -A commits a test fixture into packages/cli/test/.
Cost 3 is the one this repo has already paid once, from a different producer: #8218 — "check:type-check-debt writes tsconfig.debt-remeasure.json into tracked package dirs and it is not gitignored — a concurrent git add -A commits it" (closed). Same class, same remedy shape.
This is the only file in the repo that roots a fixture this way — git grep -n "mkdtempSync(join(HERE\|mkdtempSync(join(FIXTURES_ROOT" -- packages returns exactly one hit — so the fix is bounded and there is no family to sweep.
Two candidate remedies, not judged here
- Add
packages/cli/test/tmp-node-env-default-*/ to .gitignore (or a packages/cli/test/.gitignore). Cheapest; leaves the disk litter. - Move
rmSync(dir, …) into a finally around the child-teardown loop, so the removal runs whatever stop() does. Fixes the leak rather than hiding it. ⭐ Both, probably — the ignore is the guard for the next producer, the finally is the fix for this one.
Re-check
sed -n '380,400p' packages/cli/test/serve-node-env-production-default.e2e.test.ts
git check-ignore -v packages/cli/test/tmp-node-env-default-XXXX ; echo "exit=$?" # 1 = NOT ignored
grep -n "tmp" .gitignore
⛔ Reproducing the leak needs the failing path: build only the dependency closure (pnpm --filter '@objectstack/cli^...' build, note ^...), leave packages/cli/dist absent, then run this one file and look at git status --short afterwards.
Severity not judged; S, mechanical.
Generated by Claude Code
Filed unassigned and ungraded by the #12539 dev, session
session_01UjujZN219uFzBhSYfMykCd. Met while measuring #12539's failing set. ⛔ Not graded, not routed. The file is currently fenced by PR #12569, so nothing was touched.Measured
packages/cli/test/serve-node-env-production-default.e2e.test.ts:388creates its fixture inside the tracked test tree, not the system tmpdir:⭐ That location is correct and deliberate — the file's own docblock gives the measured reason: the fixture config does a static
import { AuthPlugin } from '@objectstack/plugin-auth', which resolves only becausepackages/cli/node_modules/is reachable by Node's upward walk from wherever the config lives. A fixture inos.tmpdir()has no such ancestor. ⛔ This is not a request to move it.The defect is the other half: nothing keeps the directory out of git, and cleanup does not survive a failure.
.gitignorecarries*.tmpandtmp/. Neither matchestmp-node-env-default-*— verified:git check-ignore -v packages/cli/test/tmp-node-env-default-XXXXreports it is NOT ignored.afterAll(line 397) awaitsstop(child)for every child beforermSync(dir, …), so any throw or timeout in the child-teardown loop skips the removal entirely.Observed on
09b4f4e4ewith the dependency closure built andpackages/cli/distabsent — i.e. the fresh-worktree state #12539 is about, where this file'sitfails. After that run:were still on disk, untracked. After a run where the same file passes, they are gone — so the leak is specifically on the failing path, which is the path a developer is most likely to be on when they reach for
git add -A.Three costs, in ascending order:
git statusis no longer a clean signal in the worktree, which is what a parallel-agent container leans on.package.jsonchanges what tooling derives.node scripts/pm/dispatch-gates.mjsreads the working tree including untracked files; with the leftover present it derived three extra gate families for an unrelated change set —check:override-consistency,check-changeset-fixed.mjsandcheck-osv-exemptions.mjs— matched solely viapackages/cli/test/tmp-node-env-default-zVfZgc/package.jsonthrough validate-deps.yml's**/package.jsontrigger. It exits 0 and the list looks ordinary.git add -Acommits a test fixture intopackages/cli/test/.Cost 3 is the one this repo has already paid once, from a different producer: #8218 — "
check:type-check-debtwritestsconfig.debt-remeasure.jsoninto tracked package dirs and it is not gitignored — a concurrentgit add -Acommits it" (closed). Same class, same remedy shape.This is the only file in the repo that roots a fixture this way —
git grep -n "mkdtempSync(join(HERE\|mkdtempSync(join(FIXTURES_ROOT" -- packagesreturns exactly one hit — so the fix is bounded and there is no family to sweep.Two candidate remedies, not judged here
packages/cli/test/tmp-node-env-default-*/to.gitignore(or apackages/cli/test/.gitignore). Cheapest; leaves the disk litter.rmSync(dir, …)into afinallyaround the child-teardown loop, so the removal runs whateverstop()does. Fixes the leak rather than hiding it. ⭐ Both, probably — the ignore is the guard for the next producer, thefinallyis the fix for this one.Re-check
⛔ Reproducing the leak needs the failing path: build only the dependency closure (
pnpm --filter '@objectstack/cli^...' build, note^...), leavepackages/cli/distabsent, then run this one file and look atgit status --shortafterwards.Severity not judged; S, mechanical.
Generated by Claude Code