Skip to content

test(dogfood): the cold-boot catalog file takes its database roots under tmpdir() and removes them itself - #22416

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-22400-cold-boot-dogfood-tmpdir
Oct 9, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-22400-cold-boot-dogfood-tmpdir

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #22400
Clause-②: no

What this changes

One test file, packages/qa/dogfood/test/security-catalog-cold-boot-environment-holder.dogfood.test.ts, in the private @objectstack/dogfood package:

  • databaseFile() takes its mkdtempSync base from join(tmpdir(), 'catalog-cold-boot-'). Before, the base was join(process.cwd(), 'catalog-cold-boot-').
  • The per-file cwd sweep no longer covers these directories, so the file records every root databaseFile() creates and removes them in a new afterAll. That hook runs after afterEach has stopped the last kernel. A refused boot leaves no kernel to stop, but its directory is still removed. This follows the harness's own BootOptions.databaseFile contract: "Callers own the file's lifetime (create it under a temp dir, delete it after)".
  • The header comment now describes the new placement and why the base is spelled tmpdir(). The old text ("the files live in this test file's own working directory, which the dogfood run removes at its end") is no longer true.

Why: scripts/pm/dispatch-gates.mjs's scratch-directory scan must be able to read every mkdtempSync base. process.cwd() is not a base it reads, so the site came back UNRESOLVED and the pm dispatch-gates self-test case failed on main. This uses the same remedy as PR #21935, which fixed the same mechanism on per-file-cwd.setup.ts: the base is made readable at the site. Per triage, dispatch-gates.mjs is not touched (the guard is not loosened, and process.cwd() is not taught to the scan), and per-file-cwd.setup.ts is not touched.

Evidence

pnpm check:pm-dispatch-gates (run detached, followed with tail --pid)

tree final line
main 83e7ae93a (unfixed, in a separate worktree pinned there) ✗ dispatch-gates self-test: 1 of 2011 case(s) failed. (the failing case: ✗ no mkdtempSync site in this tree takes a base the scan cannot read — UNRESOLVED: packages/qa/dogfood/test/security-catalog-cold-boot-environment-holder.dogfood.test.ts:108 (a base this scan cannot read: process.cwd()))
this branch d8eee2191 ✓ dispatch-gates self-test: 2011 cases pass.

On this branch the case itself reads ✓ no mkdtempSync site in this tree takes a base the scan cannot read (log line 1533 in both runs). The wrapper's own battery reads ✓ check:pm-dispatch-gates --self-test: the exit contract holds in all three directions. on both trees. The unfixed run ends ELIFECYCLE Command failed with exit code 1., and the fixed run prints no such line. Battery time on this shared box: 781.7s before and 774.7s after.

The same scan, read directly through exposedScratchDirs() on both trees: sites=1625 inTree=63 exposed=0, with unresolved(mkdtempSync) going from 1 to 0 and unresolved(all) from 289 to 288. Site and in-tree counts are unchanged, so the one site moved to "outside", not out of the scan.

The dogfood file itself (through scripts/pm/os-verify-lock.sh, on d8eee2191)

pnpm --filter @objectstack/dogfood exec vitest run --maxWorkers=2 test/security-catalog-cold-boot-environment-holder.dogfood.test.ts

 Test Files  1 passed (1)
      Tests  4 passed (4)
os-verify-lock: VERDICT command-exit 0

A catalog-cold-boot-* listing under tmpdir() (/tmp here), taken before and after the run, with a poller sampling /tmp every 100 ms during it:

before (2026-10-09T04:02:10Z): count=0
seen during the run:
  2026-10-09T04:02:32.669Z /tmp/catalog-cold-boot-6eM9D3
  2026-10-09T04:02:36.183Z /tmp/catalog-cold-boot-KGxFei
  2026-10-09T04:02:37.484Z /tmp/catalog-cold-boot-eGpgIr
  2026-10-09T04:02:39.290Z /tmp/catalog-cold-boot-PzYAkQ
  (distinct seen=4, one per case)
after (2026-10-09T04:02:41Z): count=0

So the four roots really are created under tmpdir() and none survives the file. Nothing else removes them: the dogfood globalSetup teardown only sweeps its own os-dogfood-run-TAG-file- prefix.

pnpm --filter @objectstack/dogfood typecheck gives VERDICT command-exit 0. The package's tsconfig.json includes test/**/*, and tsc --noEmit --listFiles names this file once.

Derived gates

node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 53 commands from this diff (1 path vs merge base 83e7ae93a). Each was run on d8eee2191 with its exit code recorded, then reconciled with --ran:

Run reconciliation — 53 derived, 53 run, 0 NOT-MEASURED, 0 UNRUN.
✓ dispatch-gates --ran: 53 derived famil(ies) accounted for — 53 run, 0 NOT-MEASURED (a DERIVED zero — all 53 recorded an exit code and none of them is 3).

On its first pass, pnpm check:dual-build-cjs-loads exited 3 (PREREQUISITE NOT MET): eight packages outside the dogfood closure had no dist/. They were built through the lock (44 of 44 turbo tasks, all cache hits), and the re-run exited 0: ✓ check:dual-build-cjs-loads — 107 published require entry point(s) across 66 package(s) load. The record above carries that re-run's code. The other 52 exited 0 on the first pass.

ESLint, narrowed to the one changed file: eslint --no-inline-config --format json gives 1 file, 0 errors, 0 warnings, and the file is not ignored. The resolved config sets neither parserOptions.project nor projectService, so linting is not type-aware and this diff cannot change the verdict on any file it does not touch. The repo-wide pnpm lint is CI's.

Acceptance notes

  • No changeset: @objectstack/dogfood is private: true and the diff is one test file.
  • The full dogfood suite is not run locally. CI's Dogfood Regression Gate runs it. Locally this file ran on its own, as above.
  • The workflow-valued families the derivation names as NOT MEASURED (check-shard-attestation --emit …, check-test-completeness "$RUNNER_TEMP/…", check-issue-citations --census) take a value that exists only in a CI run. They are CI's.

Generated by Claude Code

…der tmpdir() and removes them itself

The scratch-directory scan in scripts/pm/dispatch-gates.mjs must be able to
read every mkdtempSync base. process.cwd() is not one it reads, so the site
came back UNRESOLVED and the pm dispatch-gates self-test failed on main.

The base is now join(tmpdir(), 'catalog-cold-boot-'). The per-file cwd sweep
no longer covers these directories, so the file records each root it creates
and removes them in afterAll, after afterEach has stopped the last kernel.

Claude-Session: https://claude.ai/code/session_01WYYhVJ78u7PhwFViWo1EmQ
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs.

What this run could not see

Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json abd254508b861da8ed1e96c2a813541b3274fb40 → packageMentionDocs.

@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 9, 2026
@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 9, 2026 04:50
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 9, 2026 04:50
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 9, 2026
Merged via the queue into main with commit 27a8b33 Oct 9, 2026
40 of 41 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-22400-cold-boot-dogfood-tmpdir branch October 9, 2026 05:20
os-tesla pushed a commit that referenced this pull request Oct 9, 2026
…der tmpdir() and removes them itself (ported from PR #22416)

Ported verbatim from PR #22416 (branch claude/issue-22400-cold-boot-dogfood-tmpdir,
head d8eee21): its one-file diff against its merge base 83e7ae9, applied
with git apply. The resulting blob equals that head's blob byte for byte
(ac01935). Main carries the same file blob as that merge base, so the
hunks are identical and a later merge of main that brings PR #22416 is a
no-op here. It moves the mkdtempSync base from process.cwd() to
join(tmpdir(), ...), which the dispatch-gates scratch-directory scan reads,
and removes the created roots in an afterAll.

Claude-Session: https://claude.ai/code/session_01VZqqwTj2wsihZEbfT6yyYN
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

2 participants