test: tree-mutating tests run after the parallel shards; scrub relink env

The flake family's root cause, finally: five test files REGENERATE
shared repo artifacts in place (catalog-mode-full rewrites every
SKILL.md in full-catalog mode; spec-sync and idempotency regenerate all
skills; gen-skill-docs and skill-validation rewrite .agents/). Any
concurrent shard reading those files sees a moving target — this one
family produced the exactly-doubled catalog estimate, the golden-file
drift, and the spec-sync mismatch chased earlier today. Full-suite mode
now runs TREE_MUTATING files in one serial shard AFTER the parallel
shards complete; CI's matrix is unaffected (per-runner checkouts).

Also: relink's run() helper spread process.env into its children, so a
sibling file's leaked GSTACK_HOME made the 'fresh install' test see a
neighbor's skill_prefix. GSTACK_HOME is now dropped unless the test
passes it explicitly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-08-15 15:50:30 -07:00
co-authored by Claude Fable 5
parent 710900bd51
commit 1b38e5ad16
2 changed files with 44 additions and 5 deletions
+9 -1
View File
@@ -25,7 +25,15 @@ function run(cmd: string, env: Record<string, string> = {}, expectFail = false):
try {
return execSync(cmd, {
cwd: ROOT,
env: { ...process.env, GSTACK_STATE_DIR: tmpDir, ...env },
// A sibling test file in the same shard PROCESS can leave GSTACK_HOME
// set on process.env; relink/config children must resolve state ONLY
// via the dirs this test passes (observed: 'fresh install' test saw a
// neighbor's skill_prefix and produced prefixed names).
env: (() => {
const child: Record<string, string | undefined> = { ...process.env, GSTACK_STATE_DIR: tmpDir, ...env };
if (!('GSTACK_HOME' in env)) delete child.GSTACK_HOME;
return child;
})(),
encoding: 'utf-8',
timeout: 10000,
stdio: ['pipe', 'pipe', 'pipe'],