Skip to content

test(dogfood): each file's temporary cwd is created from a base the scratch-dir scan can read - #21935

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-21924-per-file-cwd-readable-base
Oct 6, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-21924-per-file-cwd-readable-base

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #21924
Clause-②: no

What changes

main's hourly Lint & Type Check run is red on one dispatch-gates self-test case (run 37394652870 at be97cf3c93, Lint & Repo Gates, step PM dispatch-gates self-test):

✗ no mkdtempSync site in this tree takes a base the scan cannot read — UNRESOLVED: packages/qa/dogfood/test/per-file-cwd.setup.ts:60 (a base this scan cannot read: inject('dogfoodCwdRoot'))

PR #21919 added that site for #21914. The guard is right: a mkdtempSync base handed over through inject() is an expression the tree's scratch-directory scan cannot read. So the fix is at the site, and nothing in the guard or the scan changes.

  • packages/qa/dogfood/test/per-file-cwd.setup.ts: each file's directory is now mkdtempSync(join(tmpdir(), perFileDirPrefix(runTag))). The base is tmpdir(), outside the tree by construction, and the scan reads it as such.
    • Only the run's TAG crosses inject() (key renamed dogfoodCwdRoot to dogfoodRunTag), and only as a name component.
    • A tag carrying a path separator or .. is refused.
  • packages/qa/dogfood/test/per-file-cwd.global-setup.ts:
    • At start it clears a stale .objectstack (unchanged). It reserves the run's tag as mkdtempSync(join(tmpdir(), 'os-dogfood-run-')) (unchanged expression) and provides its basename.
    • At END it removes every system-temp entry named with this run's prefix (perFileDirPrefix, exported here and imported by the setup module, so the prefix has one spelling), then the reservation.
    • The removal stays run-level, so the memoized shared-showcase boot keeps its handles until the run ends. A concurrent run carries another tag and is never touched.
    • The teardown still judges nothing.
  • packages/qa/dogfood/vitest.config.ts: one comment line ("removes the run's per-file directories at the end").

Unchanged from #21914: every file still runs in its own temporary cwd; the cwd is restored in afterAll; and the throwing afterAll guard on packages/qa/dogfood/.objectstack/data is untouched.

Out of scope here: the rule, the case and scripts/pm/dispatch-gates.mjs are untouched. Nothing is skipped or recorded as an exception.

Evidence

  • Reproduced first, on origin/main faf8dce4 with no change: pnpm check:pm-dispatch-gates gave ✗ dispatch-gates self-test: 1 of 1976 case(s) failed.. The one red case is the line quoted above, at per-file-cwd.setup.ts:60. The battery took 821.9s.
  • At head 2edc5d59: pnpm check:pm-dispatch-gates gave ✓ no mkdtempSync site in this tree takes a base the scan cannot read and ✓ dispatch-gates self-test: 1976 cases pass. (780.2s).
  • The case still fails on a planted unreadable base. A second worktree was checked out at 2edc5d59, and scripts/ablation-replace.mjs (wrap mode) replaced the site with process.chdir(mkdtempSync(join(inject('dogfoodRunTag'), 'file-')));. The anchor went from 1 to 0, and the blob from dc1d3de3 to 51346b9f.
    • Result: ✗ dispatch-gates self-test: 1 of 1976 case(s) failed., and the red case was exactly ... UNRESOLVED: packages/qa/dogfood/test/per-file-cwd.setup.ts:73 (a base this scan cannot read: inject('dogfoodRunTag')).
    • Restore was proven: blob after restore equals HEAD (dc1d3de3), git diff HEAD is empty, and git status --porcelain is empty. The second worktree was then removed.
  • dogfood: five files boot the showcase in the package directory and leave its federated fixture database behind, so a later showcase boot's federated state depends on shard order #21914's behaviour, re-proven at 2edc5d59:
    • Whole dogfood suite, pnpm --filter @objectstack/dogfood test: Test Files 208 passed | 1 skipped (209), Tests 1606 passed | 9 skipped (1615). Afterwards packages/qa/dogfood/.objectstack does not exist. Zero /tmp/os-dogfood-run-* entries before the run and zero after it.
    • H4 ablation through scripts/ablation-replace.mjs: the central process.chdir(...) was dropped (blob dc1d3de3 to ad6684f2) and two files were run, showcase-external-autoconnect and showcase-search. Result: Test Files 2 failed (2). Both failed in the guard: .../packages/qa/dogfood/.objectstack/data exists after this test file ran. Entries: showcase_external.db (plus -shm / -wal on the shared-showcase file).
    • The restore was proven (blob equals HEAD, git diff HEAD empty). The restored leg gave 2 passed, exit 0, and left nothing in the package dir. Zero temp entries were left after each leg, the red one included.
  • Gates: dispatch-gates --commands over the 3 changed paths derived 47 families. All 47 ran at 2edc5d59, and dispatch-gates --ran reported 47 derived famil(ies) accounted for — 47 run, 0 NOT-MEASURED.
    • check:dual-build-cjs-loads first exited 3 (prerequisite: packages/apps/studio/dist missing), then exited 0 after building it.
    • pnpm lint exits 0, and pnpm --filter @objectstack/dogfood typecheck is green.
    • check:pm-dispatch-gates is path-scoped, so this PR's CI may not schedule it, which is how the red reached main. It was run here in full at the head, as above.

Acceptance notes


Generated by Claude Code

…cratch-dir scan can read

The dispatch-gates self-test refuses a mkdtempSync whose base it cannot
read, and the per-file cwd took its base from inject(): a path handed over
from the globalSetup. Each file's directory is now made as
mkdtempSync(join(tmpdir(), TAG-file-)), where TAG is the run's reserved
name (only a name crosses inject(), and a separator in it is refused). The
globalSetup sweeps that prefix at run end, then removes the reservation,
so the shared boot's handles still live until the run ends and a
concurrent run's directories are never touched. Isolation, the leftover
guard and the stale-dir clearing are unchanged.

Claude-Session: https://claude.ai/code/session_01RWZbGvPFcRKvUqASZtunCU
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added the size/s label Oct 6, 2026
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 6, 2026
@github-actions github-actions Bot added the tests label Oct 6, 2026
@github-actions

github-actions Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️ 1 changed file(s) yielded no anchor (packages/qa/dogfood/vitest.config.ts), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)).

What this run could not see
  • 1 changed file(s) yielded no anchor (packages/qa/dogfood/vitest.config.ts) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 2 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 9dce635337c2cc42a4149aa49289ad77d172363d → packageMentionDocs.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 6, 2026 02:19
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 6, 2026 02:19
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 6, 2026
Merged via the queue into main with commit 9e33ee7 Oct 6, 2026
41 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-21924-per-file-cwd-readable-base branch October 6, 2026 02:54
This was referenced Oct 6, 2026
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

Development

Successfully merging this pull request may close these issues.

hourly full run: red on main (Lint & Type Check)

2 participants