tests/loop-hooks-verify-post-e2e.test.cjs's runCli stripped ambient GSD_* env vars but never sandboxed HOME, so the spawned gsd-tools CLI subprocess fell through to os.homedir() (capability-loader.cts's overlayRoots and capability-state.cts's resolveCapabilityRuntimeState both thread process.env['GSD_HOME'], which falls back to os.homedir() when unset). Any capability genuinely installed at ~/.gsd/capabilities on the machine running the suite (e.g. beads, markdown-linting) leaked into the verify:post registry and inflated the file's exact-count assertions (3 -> 5 active hooks, 0 -> 2 on the all-off case, etc). Switch runCli to helpers.cjs's installSpawnEnv(), the helper ~370 other test files already use for this: it sandboxes HOME/USERPROFILE to a per-file mkdtemp'd fixture and clears the full config-location env list (GSD_HOME, GSD_RUNTIME, CLAUDE_CONFIG_DIR, etc.), so the CLI subprocess sees only the core registry regardless of what's installed on the host. The pure resolveLoopHooks() tests in the same file were already unaffected — they call the resolver directly with realRegistry, bypassing CLI env resolution entirely. Fixes #4204 Co-authored-by: Test <test@test.com> Co-authored-by: Tom Boucher <trekkie@nomorestars.com>
This commit is contained in:
committed by
GitHub
parent
5869febb16
commit
f9bb489363
@@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
const { describe, test, before, after, afterEach } = require('node:test');
|
||||
const { cleanup } = require('./helpers.cjs');
|
||||
const { cleanup, installSpawnEnv } = require('./helpers.cjs');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const os = require('node:os');
|
||||
@@ -40,20 +40,23 @@ const realRegistry = require('../gsd-core/bin/lib/capability-registry.cjs');
|
||||
// ── CLI path ───────────────────────────────────────────────────────────────────
|
||||
const GSD_TOOLS = path.join(__dirname, '..', 'gsd-core', 'bin', 'gsd-tools.cjs');
|
||||
|
||||
// ── Env hermeticity (strip ambient GSD_ vars that skew planning dir lookups) ──
|
||||
const CLEAN_ENV = Object.fromEntries(
|
||||
Object.entries(process.env).filter(([k]) => !k.startsWith('GSD_')),
|
||||
);
|
||||
|
||||
/**
|
||||
* Invoke gsd-tools CLI with spawnSync and return the parsed result.
|
||||
* Always use CLEAN_ENV to avoid ambient GSD_ env vars redirecting planning paths.
|
||||
*
|
||||
* #4204: uses helpers.cjs's installSpawnEnv() rather than a hand-rolled env,
|
||||
* because it sandboxes HOME (so capability-loader's overlayRoots and
|
||||
* resolveCapabilityRuntimeState's registry load — both of which fall back to
|
||||
* os.homedir() — never reach the real machine) AND clears the full
|
||||
* config-location env list (GSD_HOME, GSD_RUNTIME, CLAUDE_CONFIG_DIR, etc.),
|
||||
* not just a GSD_-prefix strip. Without it, a capability genuinely installed
|
||||
* on the host running the suite (e.g. beads, markdown-linting) leaked into
|
||||
* the verify:post registry and inflated the exact-count assertions below.
|
||||
*/
|
||||
function runCli(args, cwd) {
|
||||
const result = spawnSync(process.execPath, [GSD_TOOLS, ...args], {
|
||||
cwd,
|
||||
encoding: 'utf8',
|
||||
env: CLEAN_ENV,
|
||||
env: installSpawnEnv(),
|
||||
timeout: 60000,
|
||||
});
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user