test(#2665): reversion guards for all three round-4 fixes

None of the round-4 fixes had a test that fails on reversion: re-shipping
the test-instrumentation chain passes #2858 (everything ships, so every
require resolves), dropping the strict env from test.yml demotes the guard
to report-only with nothing red, and the skillsHome derivation tests are
enumeration-relative over declarations that are all empty today. One
guard each, every one negative-controlled against its reverted fix (fails
pre-fix, passes post-fix):

- packaging-shipped-scripts-require-only-shipped.test.cjs asserts the four
  chain files are absent from the npm pack file list (reuses the tarball
  set the #2858 gate already resolves — no second npm pack).
- live-config-guard.test.cjs asserts all three test jobs wire
  GSD_STRICT_LIVE_CONFIG_GUARD, matching the WHOLE expression anchored —
  a prefix match accepted both a Windows-silently-strict tail and a
  malformed one.
- helpers-process-isolation.test.cjs cold-requires helpers.cjs in a child
  with sentinel skillsHome env vars injected into both enumerations, so
  the walk itself is under test rather than today's empty declarations.
This commit is contained in:
0xdhx
2026-08-03 03:09:17 -05:00
parent 7b8c36f904
commit 652b99b71b
3 changed files with 112 additions and 0 deletions

View File

@@ -235,3 +235,57 @@ describe('#2665: TEST_ENV_BASE config-location coverage', () => {
});
});
});
describe('#2665 round 4: the skillsHome walk is reversion-sensitive', () => {
// The coverage tests above are enumeration-relative, and skillsHome.env is
// empty everywhere today — so reverting the skillsHome rungs from the
// derivation leaves every one of them green (measured by this round's
// pre-push adversarial review). This test closes that: it cold-requires
// helpers.cjs in a child process after injecting sentinel skillsHome env
// vars into BOTH enumerations (registry and non-registry), so the walk
// itself is what is under test, not today's empty declarations.
test('sentinel skillsHome vars flow into TEST_ENV_BASE on both rungs', () => {
const { execFileSync } = require('node:child_process');
const regPath = require.resolve('../gsd-core/bin/lib/capability-registry.cjs');
const rhPath = require.resolve('../gsd-core/bin/lib/runtime-homes.cjs');
const helpersPath = require.resolve('./helpers.cjs');
const script = `
'use strict';
const reg = require(${JSON.stringify(regPath)});
const rh = require(${JSON.stringify(rhPath)});
// Rung 1 (registry): give one runtime a skillsHome env var. kilo already
// declares skillsHome (env: []); push a sentinel into whichever runtime
// declares it, or graft one onto the first runtime if none does.
const declaring = Object.values(reg.runtimes).find(
(r) => r?.runtime?.configHome?.skillsHome,
) ?? Object.values(reg.runtimes)[0];
if (!declaring.runtime.configHome.skillsHome) {
declaring.runtime.configHome.skillsHome = { kind: 'dot-home', name: '.x', env: [] };
}
declaring.runtime.configHome.skillsHome.env = ['GSD_TEST_SENTINEL_REGISTRY_SKILLS'];
// Rung 2 (non-registry): graft a skillsHome onto the first descriptor.
rh.NON_REGISTRY_CONFIG_HOME_DESCRIPTORS[0].skillsHome = {
kind: 'dot-home', name: '.x', env: ['GSD_TEST_SENTINEL_NONREG_SKILLS'],
};
const { TEST_ENV_BASE } = require(${JSON.stringify(helpersPath)});
const missing = [
'GSD_TEST_SENTINEL_REGISTRY_SKILLS',
'GSD_TEST_SENTINEL_NONREG_SKILLS',
].filter((k) => TEST_ENV_BASE[k] !== '');
if (missing.length > 0) {
console.error('skillsHome walk missed: ' + missing.join(', '));
process.exit(1);
}
process.exit(0);
`;
const out = execFileSync(process.execPath, ['-e', script], {
cwd: __dirname,
encoding: 'utf-8',
stdio: ['pipe', 'pipe', 'pipe'],
timeout: 30_000,
});
void out; // exit 0 is the assertion; execFileSync throws on nonzero
});
});

View File

@@ -410,3 +410,40 @@ describe('#2665: scan-budget truncation', () => {
}
});
});
describe('#2665 round 4: CI wires the guard to strict mode', () => {
// The reversion this guards: dropping GSD_STRICT_LIVE_CONFIG_GUARD from
// test.yml silently demotes the guard back to report-only, and a future
// leak of exactly the class #2665 closes prints a warning and CI stays
// green. Windows lanes are deliberately report-only until the documented
// pre-existing USERPROFILE leak class is swept (SEVERITY note in
// scripts/live-config-guard.cjs) — so the assertion is per-OS, not global.
test('all three test jobs set GSD_STRICT_LIVE_CONFIG_GUARD (Windows carved out)', () => {
const yaml = require('js-yaml');
const wf = yaml.load(
fs.readFileSync(
path.join(__dirname, '..', '.github', 'workflows', 'test.yml'),
'utf8',
),
);
for (const job of ['test', 'test-full']) {
const v = String(wf.jobs?.[job]?.env?.GSD_STRICT_LIVE_CONFIG_GUARD ?? '');
assert.match(
v,
// The WHOLE expression, anchored — a prefix match accepted both
// `&& '1' || '1'` (Windows silently strict) and a malformed tail
// (found by this round's pre-push adversarial review).
/^\$\{\{\s*matrix\.os\s*!=\s*'windows-latest'\s*&&\s*'1'\s*\|\|\s*''\s*\}\}$/,
`jobs.${job}.env.GSD_STRICT_LIVE_CONFIG_GUARD must be strict on ` +
`non-Windows lanes and empty on windows-latest; got: ${JSON.stringify(v)}`,
);
}
assert.strictEqual(
String(wf.jobs?.['test-inert']?.env?.GSD_STRICT_LIVE_CONFIG_GUARD ?? ''),
'1',
'jobs.test-inert (ubuntu-only) must set GSD_STRICT_LIVE_CONFIG_GUARD: 1',
);
});
});

View File

@@ -135,6 +135,27 @@ describe('#2858 — shipped scripts require only shipped paths', () => {
.sort();
});
test('#2665: the test-instrumentation chain does not ship', () => {
// These four are one closed require chain of test instrumentation
// (run-tests -> live-config-guard, affected-tests-lib -> run-tests,
// run-affected-tests -> affected-tests-lib). Excluding a strict subset
// re-trips the shipped-requires-only-shipped gate above on whichever links
// still ship, so the exclusion set and this assertion cover the chain.
const TEST_INSTRUMENTATION = [
'scripts/live-config-guard.cjs',
'scripts/run-tests.cjs',
'scripts/affected-tests-lib.cjs',
'scripts/run-affected-tests.cjs',
];
for (const f of TEST_INSTRUMENTATION) {
assert.ok(
!shippedFiles.has(f),
`${f} is test instrumentation and must not ship — restore its ` +
"package.json files[] '!'-exclusion (and keep the whole chain excluded)",
);
}
});
test('every shipped scripts/*.{cjs,js} is require-able from a shipped-only tree', () => {
assert.ok(shippedScripts.length > 0, 'expected at least one shipped script');