* fix(#4220): terminate the temp-sweep ancestor walk with a fixed-point check
scripts/run-tests.cjs's sweepProtectSet block walked each selected test
file's ancestor directories, stopping on `cur !== runTempRoot &&
cur.length > 1` — a POSIX-only sentinel. path.posix.dirname('/') === '/'
(length 1) correctly stops, but path.win32.dirname('C:\\') === 'C:\\'
(length 3) never satisfies the length check, so the walk spun forever on
Windows whenever a selected file lived outside runTempRoot (the common
case). This has hung every Windows CI shard since #4207.
Extract the walk into a pure, exported computeSweepProtectSet(selected,
runTempRoot, dirnameImpl) helper and replace the length sentinel with a
fixed-point check (stop when dirnameImpl(cur) === cur), which terminates
correctly on POSIX, Windows drive roots, and UNC roots alike with no
platform branch.
* fix(#4220): repoint TEMP/TMP alongside TMPDIR in run-tests-temp-root test child env
Node's os.tmpdir() on Windows never reads TMPDIR, only TEMP/TMP. The
test's runNode child-process env override only set TMPDIR, so on a
real Windows runner nested inside a run-tests invocation the child
inherited the outer process's already-repointed TEMP/TMP and its
mkdtempSync(os.tmpdir()) landed under the outer run's temp root
instead of the test's intended `outer` directory. This was masked on
gsd-test's benches and locally because Windows CI always died in the
#4220 infinite loop before reaching this test.
* fix(#4220): stop the ancestor walk from protecting the filesystem root itself
computeSweepProtectSet added `cur` to the protect set before checking
whether dirname(cur) === cur, so on the terminating iteration it
protected the filesystem root (posix `/`, and analogously a win32
drive root) instead of stopping before adding it. Caught by the
existing posix-parity regression assertion
(`!protectSet.has('/')`) on the linux-node24 gsd-test bench. Reorder
to compute the parent and check the fixed point before adding.
* fix(#4220): backfill changeset pr number to 4245
---------
Co-authored-by: sim <sim@local>
* test(#4020): the runner must bound and sweep a run-scoped temp root
* fix(#4020): bound the run's temp footprint with a swept run-scoped root
* test(#4020): isolate the env-mutating rows in child processes
* fix(#4020): gate root removal on ownership so nested runners spare the outer root
* test(#4020): pass the probe file via --files, the runner's explicit-file flag
* test(#4020): resolve the probe by basename, as --files matching requires
* test(#4020): assert root survival, not content survival, in the nested-row
* chore(#4020): changeset for the run-scoped temp root
* chore(#4020): backfill changeset pr number
* fix(#4020): the sweep spares ancestors of the runner's own selected files
* fix(#4020): TMPDIR precedence — an operator redirect beats inherited TEMP/TMP
* fix(#4020): only the root's owner sweeps — a nested runner spares live sibling fixtures
---------
Co-authored-by: sim <sim@local>