refactor: hard-fork GSD -> MSD (Make Software Done)
Mechanical rename produced by scripts/msd-rename.cjs: gsd/Gsd/GSD -> msd/Msd/MSD across contents and paths, upstream package/repo coordinates -> @golem15/msd-core and golem15com/msd-core. Deep links into upstream history, sibling upstream packages, the GSD-2 import feature, CHANGELOG.md and .changeset/ are kept as-is. Hand edits on top: MSD block-letter banner and logos, LICENSE copyright line, package/plugin identity, regenerated lockfile, install-tree fixtures, derived registries and benchmark baseline; migration checksum baseline re-locked (MSD keeps its own install state, so no install had applied the old sums); sort-order and regex-escaped expectations in tests adjusted.
This commit is contained in:
@@ -5,17 +5,17 @@
|
||||
*
|
||||
* Coverage gaps closed here (tests/install-minimal-hooks.test.cjs already
|
||||
* covers the installed-tree rows — pi local+global: no `hooks/`, bundle at
|
||||
* `gsd-hooks/`, manifest keys — and is not duplicated):
|
||||
* `msd-hooks/`, manifest keys — and is not duplicated):
|
||||
*
|
||||
* GROUP A bin/install.js `resolveSharedHooksDirName(runtime)` — the
|
||||
* descriptor-driven sanitizer that rejects anything that is not a
|
||||
* plain, non-empty, separator-free, non-dot, non-absolute,
|
||||
* NUL-free single path segment.
|
||||
* GROUP B pi/gsd.cjs `_internals.resolveSharedHooksDir(engineRoot)` — the
|
||||
* GROUP B pi/msd.cjs `_internals.resolveSharedHooksDir(engineRoot)` — the
|
||||
* adapter-side probe over `SHARED_HOOKS_DIR_CANDIDATES`.
|
||||
* GROUP C the two latent bundle-directory-NAME dependencies:
|
||||
* hooks/gsd-check-update-worker.js (stale-hook scan) and
|
||||
* hooks/gsd-read-injection-scanner.js (own-bundle exclusion).
|
||||
* hooks/msd-check-update-worker.js (stale-hook scan) and
|
||||
* hooks/msd-read-injection-scanner.js (own-bundle exclusion).
|
||||
*
|
||||
* GROUP A malformed-value cases (empty/whitespace/non-string/traversal/NUL):
|
||||
* `resolveSharedHooksDirName` sources its raw descriptor value from the
|
||||
@@ -31,7 +31,7 @@
|
||||
* GROUP A's real-registry assertions above it.
|
||||
*/
|
||||
|
||||
process.env.GSD_TEST_MODE = process.env.GSD_TEST_MODE || '1';
|
||||
process.env.MSD_TEST_MODE = process.env.MSD_TEST_MODE || '1';
|
||||
|
||||
const { test, describe, before, after } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
@@ -55,7 +55,7 @@ const PROPERTY_DRIVER_TIMEOUT_MS = 60000;
|
||||
// Requiring the installer (not as main) never runs the CLI — matches the
|
||||
// existing tests/claude-imperative-reference.test.cjs convention.
|
||||
const installMod = require('../bin/install.js');
|
||||
const piExtension = require('../pi/gsd.cjs');
|
||||
const piExtension = require('../pi/msd.cjs');
|
||||
const { resolveSharedHooksDir, SHARED_HOOKS_DIR_CANDIDATES } = piExtension._internals;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -73,8 +73,8 @@ describe('GROUP A.1: resolveSharedHooksDirName — real registry, real runtimes'
|
||||
}
|
||||
});
|
||||
|
||||
test('the real pi descriptor resolves to "gsd-hooks" (#3023)', () => {
|
||||
assert.equal(installMod.resolveSharedHooksDirName('pi'), 'gsd-hooks');
|
||||
test('the real pi descriptor resolves to "msd-hooks" (#3023)', () => {
|
||||
assert.equal(installMod.resolveSharedHooksDirName('pi'), 'msd-hooks');
|
||||
});
|
||||
|
||||
test('an unknown runtime id, and an empty-string runtime id, both degrade to the default and never throw', () => {
|
||||
@@ -128,10 +128,10 @@ const HOSTILE_CASES = [
|
||||
// Trailing dot — Windows silently strips this at creation time, splitting
|
||||
// the created dir name from the probed-for name. (A trailing ASCII SPACE is
|
||||
// not exercised here: `raw.trim()` at the top of the function already
|
||||
// strips it before any guard runs, so 'gsd-hooks ' correctly normalizes to
|
||||
// the intended 'gsd-hooks' — see the ACCEPTED_CASES entry below, which
|
||||
// strips it before any guard runs, so 'msd-hooks ' correctly normalizes to
|
||||
// the intended 'msd-hooks' — see the ACCEPTED_CASES entry below, which
|
||||
// pins down that verified, non-regressive behavior instead.)
|
||||
{ label: 'trailing dot', raw: 'gsd-hooks.' },
|
||||
{ label: 'trailing dot', raw: 'msd-hooks.' },
|
||||
{ label: 'single-char trailing dot', raw: 'a.' },
|
||||
// Windows reserved device names — cannot exist as directories on Windows.
|
||||
{ label: 'reserved CON uppercase', raw: 'CON' },
|
||||
@@ -146,8 +146,8 @@ const HOSTILE_CASES = [
|
||||
// default). An over-broad guard would silently retarget a legitimate
|
||||
// descriptor, which is worse than under-rejecting a hostile one.
|
||||
const ACCEPTED_CASES = [
|
||||
{ label: 'ordinary name', raw: 'gsd-hooks', expect: 'gsd-hooks' },
|
||||
{ label: 'leading-dot hidden dir', raw: '.gsd-hooks', expect: '.gsd-hooks' },
|
||||
{ label: 'ordinary name', raw: 'msd-hooks', expect: 'msd-hooks' },
|
||||
{ label: 'leading-dot hidden dir', raw: '.msd-hooks', expect: '.msd-hooks' },
|
||||
{ label: 'plain word', raw: 'hooks2', expect: 'hooks2' },
|
||||
{ label: 'CONSOLE (not a reserved device)', raw: 'CONSOLE', expect: 'CONSOLE' },
|
||||
{ label: 'COM10 (not a reserved device)', raw: 'COM10', expect: 'COM10' },
|
||||
@@ -157,7 +157,7 @@ const ACCEPTED_CASES = [
|
||||
// any guard runs, so the descriptor's clearly-intended name survives
|
||||
// unharmed — rejecting this to the default would be the actual regression
|
||||
// (see the comment on HOSTILE_CASES above).
|
||||
{ label: 'trailing space (normalized by existing trim)', raw: 'gsd-hooks ', expect: 'gsd-hooks' },
|
||||
{ label: 'trailing space (normalized by existing trim)', raw: 'msd-hooks ', expect: 'msd-hooks' },
|
||||
];
|
||||
|
||||
const ALL_SINGLE_CASES = [...MALFORMED_CASES, ...HOSTILE_CASES, ...ACCEPTED_CASES];
|
||||
@@ -276,7 +276,7 @@ describe('GROUP A.2: resolveSharedHooksDirName — malformed/hostile values + pr
|
||||
const driverPath = path.join(driverDir, 'driver.cjs');
|
||||
fs.writeFileSync(driverPath, buildDriverSource());
|
||||
|
||||
const registryPath = path.join(REPO_ROOT, 'gsd-core', 'bin', 'lib', 'capability-registry.cjs');
|
||||
const registryPath = path.join(REPO_ROOT, 'msd-core', 'bin', 'lib', 'capability-registry.cjs');
|
||||
const installPath = path.join(REPO_ROOT, 'bin', 'install.js');
|
||||
const fastcheckPath = require.resolve('fast-check');
|
||||
|
||||
@@ -359,28 +359,28 @@ describe('GROUP A.2: resolveSharedHooksDirName — malformed/hostile values + pr
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// GROUP B — pi/gsd.cjs _internals.resolveSharedHooksDir(engineRoot)
|
||||
// GROUP B — pi/msd.cjs _internals.resolveSharedHooksDir(engineRoot)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe('GROUP B: pi adapter resolveSharedHooksDir (pi/gsd.cjs)', () => {
|
||||
describe('GROUP B: pi adapter resolveSharedHooksDir (pi/msd.cjs)', () => {
|
||||
// A real staged bundle always has at least one hook file in it; these tests
|
||||
// populate every "should qualify" candidate with a placeholder file so they
|
||||
// exercise the same non-empty invariant defect 2's fix enforces, rather than
|
||||
// relying on an literally-empty directory that no real install ever produces.
|
||||
function populate(dirPath) {
|
||||
fs.mkdirSync(dirPath, { recursive: true });
|
||||
fs.writeFileSync(path.join(dirPath, 'gsd-placeholder-hook.js'), '// placeholder\n');
|
||||
fs.writeFileSync(path.join(dirPath, 'msd-placeholder-hook.js'), '// placeholder\n');
|
||||
}
|
||||
|
||||
test('candidate order is exactly ["gsd-hooks", "hooks"] (a reordering that silently prefers the stale dir must fail loudly)', () => {
|
||||
assert.deepEqual(SHARED_HOOKS_DIR_CANDIDATES, ['gsd-hooks', 'hooks']);
|
||||
test('candidate order is exactly ["msd-hooks", "hooks"] (a reordering that silently prefers the stale dir must fail loudly)', () => {
|
||||
assert.deepEqual(SHARED_HOOKS_DIR_CANDIDATES, ['msd-hooks', 'hooks']);
|
||||
});
|
||||
|
||||
test('only gsd-hooks/ exists (populated) -> returns that path', (t) => {
|
||||
test('only msd-hooks/ exists (populated) -> returns that path', (t) => {
|
||||
const root = createTempDir('fix-3023-adapter-');
|
||||
t.after(() => cleanup(root));
|
||||
populate(path.join(root, 'gsd-hooks'));
|
||||
assert.equal(resolveSharedHooksDir(root), path.join(root, 'gsd-hooks'));
|
||||
populate(path.join(root, 'msd-hooks'));
|
||||
assert.equal(resolveSharedHooksDir(root), path.join(root, 'msd-hooks'));
|
||||
});
|
||||
|
||||
test('only hooks/ exists (dev-tree back-compat, populated) -> returns that path', (t) => {
|
||||
@@ -390,12 +390,12 @@ describe('GROUP B: pi adapter resolveSharedHooksDir (pi/gsd.cjs)', () => {
|
||||
assert.equal(resolveSharedHooksDir(root), path.join(root, 'hooks'));
|
||||
});
|
||||
|
||||
test('both exist and both populated (half-upgraded tree) -> gsd-hooks wins deterministically', (t) => {
|
||||
test('both exist and both populated (half-upgraded tree) -> msd-hooks wins deterministically', (t) => {
|
||||
const root = createTempDir('fix-3023-adapter-');
|
||||
t.after(() => cleanup(root));
|
||||
populate(path.join(root, 'gsd-hooks'));
|
||||
populate(path.join(root, 'msd-hooks'));
|
||||
populate(path.join(root, 'hooks'));
|
||||
assert.equal(resolveSharedHooksDir(root), path.join(root, 'gsd-hooks'));
|
||||
assert.equal(resolveSharedHooksDir(root), path.join(root, 'msd-hooks'));
|
||||
});
|
||||
|
||||
test('neither exists -> null, does not throw', (t) => {
|
||||
@@ -405,60 +405,60 @@ describe('GROUP B: pi adapter resolveSharedHooksDir (pi/gsd.cjs)', () => {
|
||||
assert.equal(resolveSharedHooksDir(root), null);
|
||||
});
|
||||
|
||||
test('gsd-hooks exists as a FILE, not a directory -> skipped; falls through to a populated hooks/ when present', (t) => {
|
||||
test('msd-hooks exists as a FILE, not a directory -> skipped; falls through to a populated hooks/ when present', (t) => {
|
||||
const root = createTempDir('fix-3023-adapter-');
|
||||
t.after(() => cleanup(root));
|
||||
fs.writeFileSync(path.join(root, 'gsd-hooks'), 'not a directory');
|
||||
fs.writeFileSync(path.join(root, 'msd-hooks'), 'not a directory');
|
||||
populate(path.join(root, 'hooks'));
|
||||
assert.equal(resolveSharedHooksDir(root), path.join(root, 'hooks'));
|
||||
});
|
||||
|
||||
test('gsd-hooks exists as a FILE and hooks/ is absent -> null', (t) => {
|
||||
test('msd-hooks exists as a FILE and hooks/ is absent -> null', (t) => {
|
||||
const root = createTempDir('fix-3023-adapter-');
|
||||
t.after(() => cleanup(root));
|
||||
fs.writeFileSync(path.join(root, 'gsd-hooks'), 'not a directory');
|
||||
fs.writeFileSync(path.join(root, 'msd-hooks'), 'not a directory');
|
||||
assert.equal(resolveSharedHooksDir(root), null);
|
||||
});
|
||||
|
||||
// ── Defect 2 (adversarial review): empty-bundle qualification ────────────
|
||||
// An install interrupted between mkdirSync(gsd-hooks) and the file copy
|
||||
// leaves a directory that EXISTS but is EMPTY. Since gsd-hooks is probed
|
||||
// FIRST, an empty gsd-hooks/ must lose to a fully-staged legacy hooks/ —
|
||||
// An install interrupted between mkdirSync(msd-hooks) and the file copy
|
||||
// leaves a directory that EXISTS but is EMPTY. Since msd-hooks is probed
|
||||
// FIRST, an empty msd-hooks/ must lose to a fully-staged legacy hooks/ —
|
||||
// otherwise every hook silently no-ops (runHook's fs.existsSync guard
|
||||
// degrades per-file, producing no error at all).
|
||||
|
||||
test('regression: gsd-hooks/ exists but is EMPTY, hooks/ is populated -> resolves hooks/ (fails before the fix)', (t) => {
|
||||
test('regression: msd-hooks/ exists but is EMPTY, hooks/ is populated -> resolves hooks/ (fails before the fix)', (t) => {
|
||||
const root = createTempDir('fix-3023-adapter-');
|
||||
t.after(() => cleanup(root));
|
||||
fs.mkdirSync(path.join(root, 'gsd-hooks'), { recursive: true }); // empty — no files written
|
||||
fs.mkdirSync(path.join(root, 'msd-hooks'), { recursive: true }); // empty — no files written
|
||||
populate(path.join(root, 'hooks'));
|
||||
assert.equal(
|
||||
resolveSharedHooksDir(root),
|
||||
path.join(root, 'hooks'),
|
||||
'an empty gsd-hooks/ must not win over a fully-staged legacy hooks/',
|
||||
'an empty msd-hooks/ must not win over a fully-staged legacy hooks/',
|
||||
);
|
||||
});
|
||||
|
||||
test('gsd-hooks/ populated, hooks/ populated -> resolves gsd-hooks/', (t) => {
|
||||
test('msd-hooks/ populated, hooks/ populated -> resolves msd-hooks/', (t) => {
|
||||
const root = createTempDir('fix-3023-adapter-');
|
||||
t.after(() => cleanup(root));
|
||||
populate(path.join(root, 'gsd-hooks'));
|
||||
populate(path.join(root, 'msd-hooks'));
|
||||
populate(path.join(root, 'hooks'));
|
||||
assert.equal(resolveSharedHooksDir(root), path.join(root, 'gsd-hooks'));
|
||||
assert.equal(resolveSharedHooksDir(root), path.join(root, 'msd-hooks'));
|
||||
});
|
||||
|
||||
test('both gsd-hooks/ and hooks/ exist but are BOTH empty -> null', (t) => {
|
||||
test('both msd-hooks/ and hooks/ exist but are BOTH empty -> null', (t) => {
|
||||
const root = createTempDir('fix-3023-adapter-');
|
||||
t.after(() => cleanup(root));
|
||||
fs.mkdirSync(path.join(root, 'gsd-hooks'), { recursive: true });
|
||||
fs.mkdirSync(path.join(root, 'msd-hooks'), { recursive: true });
|
||||
fs.mkdirSync(path.join(root, 'hooks'), { recursive: true });
|
||||
assert.equal(resolveSharedHooksDir(root), null);
|
||||
});
|
||||
|
||||
test('gsd-hooks/ is empty, hooks/ does not exist -> null', (t) => {
|
||||
test('msd-hooks/ is empty, hooks/ does not exist -> null', (t) => {
|
||||
const root = createTempDir('fix-3023-adapter-');
|
||||
t.after(() => cleanup(root));
|
||||
fs.mkdirSync(path.join(root, 'gsd-hooks'), { recursive: true });
|
||||
fs.mkdirSync(path.join(root, 'msd-hooks'), { recursive: true });
|
||||
assert.equal(resolveSharedHooksDir(root), null);
|
||||
});
|
||||
});
|
||||
@@ -468,25 +468,25 @@ describe('GROUP B: pi adapter resolveSharedHooksDir (pi/gsd.cjs)', () => {
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// bin/install.js derives the shared-hooks directory NAME for a runtime from
|
||||
// the capability registry (resolveSharedHooksDirName). pi/gsd.cjs cannot read
|
||||
// the capability registry (resolveSharedHooksDirName). pi/msd.cjs cannot read
|
||||
// that registry at runtime — it must resolve correctly in a dev checkout AND
|
||||
// in a half-upgraded tree, where the registry's CURRENT answer would be the
|
||||
// wrong one to probe for (see the SHARED_HOOKS_DIR_CANDIDATES doc comment in
|
||||
// pi/gsd.cjs) — so it keeps its own hardcoded probe list instead. That is two
|
||||
// pi/msd.cjs) — so it keeps its own hardcoded probe list instead. That is two
|
||||
// independent sources of truth for the same name: exactly the "Generative Fix
|
||||
// Divergence" anti-pattern (CLAUDE.md -> KNOWN DEFECTS: "When sharing
|
||||
// constants/arrays/parsers between parallel surfaces, add a parity assertion
|
||||
// test that fails if they diverge."). If a future descriptor rename is not
|
||||
// mirrored into pi/gsd.cjs, this is the guard that fails loudly instead of
|
||||
// mirrored into pi/msd.cjs, this is the guard that fails loudly instead of
|
||||
// every pi hook going quiet with no error.
|
||||
describe('GROUP D: parity — installer descriptor vs pi/gsd.cjs SHARED_HOOKS_DIR_CANDIDATES', () => {
|
||||
const REMEDY = 'if the descriptor changes, update SHARED_HOOKS_DIR_CANDIDATES in pi/gsd.cjs to match';
|
||||
describe('GROUP D: parity — installer descriptor vs pi/msd.cjs SHARED_HOOKS_DIR_CANDIDATES', () => {
|
||||
const REMEDY = 'if the descriptor changes, update SHARED_HOOKS_DIR_CANDIDATES in pi/msd.cjs to match';
|
||||
|
||||
test('the installer-resolved pi descriptor name is a member of the adapter probe list', () => {
|
||||
const descriptorName = installMod.resolveSharedHooksDirName('pi');
|
||||
assert.ok(
|
||||
SHARED_HOOKS_DIR_CANDIDATES.includes(descriptorName),
|
||||
`pi's capability descriptor resolves to "${descriptorName}", which is NOT in pi/gsd.cjs's ` +
|
||||
`pi's capability descriptor resolves to "${descriptorName}", which is NOT in pi/msd.cjs's ` +
|
||||
`SHARED_HOOKS_DIR_CANDIDATES (${JSON.stringify(SHARED_HOOKS_DIR_CANDIDATES)}) — ${REMEDY}.`,
|
||||
);
|
||||
});
|
||||
@@ -496,7 +496,7 @@ describe('GROUP D: parity — installer descriptor vs pi/gsd.cjs SHARED_HOOKS_DI
|
||||
assert.equal(
|
||||
SHARED_HOOKS_DIR_CANDIDATES[0],
|
||||
descriptorName,
|
||||
`pi/gsd.cjs's SHARED_HOOKS_DIR_CANDIDATES probes "${SHARED_HOOKS_DIR_CANDIDATES[0]}" first, but the ` +
|
||||
`pi/msd.cjs's SHARED_HOOKS_DIR_CANDIDATES probes "${SHARED_HOOKS_DIR_CANDIDATES[0]}" first, but the ` +
|
||||
`installer's current descriptor for pi resolves to "${descriptorName}" — a half-upgraded tree (both dirs ` +
|
||||
`present) would bind to the stale bundle first. ${REMEDY}, with the descriptor's current name listed first.`,
|
||||
);
|
||||
@@ -505,7 +505,7 @@ describe('GROUP D: parity — installer descriptor vs pi/gsd.cjs SHARED_HOOKS_DI
|
||||
test('the back-compat default ("hooks") is present in the adapter probe list', () => {
|
||||
assert.ok(
|
||||
SHARED_HOOKS_DIR_CANDIDATES.includes(installMod.SHARED_HOOKS_DIR_DEFAULT),
|
||||
`pi/gsd.cjs's SHARED_HOOKS_DIR_CANDIDATES (${JSON.stringify(SHARED_HOOKS_DIR_CANDIDATES)}) no longer ` +
|
||||
`pi/msd.cjs's SHARED_HOOKS_DIR_CANDIDATES (${JSON.stringify(SHARED_HOOKS_DIR_CANDIDATES)}) no longer ` +
|
||||
`contains the installer's back-compat default ("${installMod.SHARED_HOOKS_DIR_DEFAULT}") — dropping it ` +
|
||||
`breaks the dev-checkout/back-compat path (a checkout with only a legacy hooks/ dir would resolve to null). ${REMEDY}.`,
|
||||
);
|
||||
@@ -520,33 +520,33 @@ const { MANAGED_HOOKS } = require('../hooks/managed-hooks-registry.cjs');
|
||||
const FIXTURE_HOOK_NAME = MANAGED_HOOKS.find((f) => f.endsWith('.js'));
|
||||
|
||||
describe('GROUP C: bundle-directory-name-agnostic hook scripts', () => {
|
||||
test('gsd-check-update-worker.js detects a stale hook when staged under a non-"hooks"-named bundle directory', (t) => {
|
||||
test('msd-check-update-worker.js detects a stale hook when staged under a non-"hooks"-named bundle directory', (t) => {
|
||||
assert.ok(FIXTURE_HOOK_NAME, 'expected at least one .js entry in MANAGED_HOOKS');
|
||||
|
||||
const tmpRoot = createTempDir('fix-3023-worker-');
|
||||
t.after(() => cleanup(tmpRoot));
|
||||
|
||||
const bundleDir = path.join(tmpRoot, 'gsd-hooks');
|
||||
const bundleDir = path.join(tmpRoot, 'msd-hooks');
|
||||
fs.mkdirSync(bundleDir, { recursive: true });
|
||||
|
||||
fs.copyFileSync(
|
||||
path.join(REPO_ROOT, 'hooks', 'gsd-check-update-worker.js'),
|
||||
path.join(bundleDir, 'gsd-check-update-worker.js'),
|
||||
path.join(REPO_ROOT, 'hooks', 'msd-check-update-worker.js'),
|
||||
path.join(bundleDir, 'msd-check-update-worker.js'),
|
||||
);
|
||||
fs.copyFileSync(
|
||||
path.join(REPO_ROOT, 'hooks', 'managed-hooks-registry.cjs'),
|
||||
path.join(bundleDir, 'managed-hooks-registry.cjs'),
|
||||
);
|
||||
// The worker's own require()s of ../gsd-core/... are relative to
|
||||
// __dirname (wherever it is physically staged), so a real gsd-core tree
|
||||
// The worker's own require()s of ../msd-core/... are relative to
|
||||
// __dirname (wherever it is physically staged), so a real msd-core tree
|
||||
// must exist one level up from the bundle directory, exactly like the
|
||||
// real install layout (<configDir>/gsd-hooks + <configDir>/gsd-core would
|
||||
// real install layout (<configDir>/msd-hooks + <configDir>/msd-core would
|
||||
// NOT match — but this worker's actual production layout is the shared
|
||||
// engine tree, one level above the bundle, which this symlink mirrors).
|
||||
fs.symlinkSync(path.join(REPO_ROOT, 'gsd-core'), path.join(tmpRoot, 'gsd-core'), 'dir');
|
||||
fs.symlinkSync(path.join(REPO_ROOT, 'msd-core'), path.join(tmpRoot, 'msd-core'), 'dir');
|
||||
|
||||
const fixtureHookLines = [
|
||||
'// gsd-hook-version: 1.0.0',
|
||||
'// msd-hook-version: 1.0.0',
|
||||
'// fixture managed hook staged for the #3023 bundle-name-agnostic staleness test',
|
||||
'module.exports = {};',
|
||||
'',
|
||||
@@ -561,7 +561,7 @@ describe('GROUP C: bundle-directory-name-agnostic hook scripts', () => {
|
||||
const cacheFile = path.join(tmpRoot, 'cache.json');
|
||||
|
||||
const result = runNode(
|
||||
[path.join(bundleDir, 'gsd-check-update-worker.js')],
|
||||
[path.join(bundleDir, 'msd-check-update-worker.js')],
|
||||
{
|
||||
cwd: tmpRoot,
|
||||
// PATH is cleared so the worker's own npm-registry lookup
|
||||
@@ -571,9 +571,9 @@ describe('GROUP C: bundle-directory-name-agnostic hook scripts', () => {
|
||||
env: {
|
||||
...process.env,
|
||||
PATH: '',
|
||||
GSD_PROJECT_VERSION_FILE: versionFile,
|
||||
GSD_GLOBAL_VERSION_FILE: '',
|
||||
GSD_CACHE_FILE: cacheFile,
|
||||
MSD_PROJECT_VERSION_FILE: versionFile,
|
||||
MSD_GLOBAL_VERSION_FILE: '',
|
||||
MSD_CACHE_FILE: cacheFile,
|
||||
},
|
||||
timeoutMs: STAGED_HOOK_SCRIPT_TIMEOUT_MS,
|
||||
},
|
||||
@@ -590,14 +590,14 @@ describe('GROUP C: bundle-directory-name-agnostic hook scripts', () => {
|
||||
assert.equal(staleEntry.installedVersion, '2.0.0');
|
||||
});
|
||||
|
||||
test('gsd-read-injection-scanner.js excludes a path inside its own (non-"hooks"-named) bundle directory', (t) => {
|
||||
test('msd-read-injection-scanner.js excludes a path inside its own (non-"hooks"-named) bundle directory', (t) => {
|
||||
const tmpRoot = createTempDir('fix-3023-scanner-');
|
||||
t.after(() => cleanup(tmpRoot));
|
||||
|
||||
const bundleDir = path.join(tmpRoot, 'gsd-hooks');
|
||||
const bundleDir = path.join(tmpRoot, 'msd-hooks');
|
||||
// Stage via copyScriptWithDeps (walks the real require graph — see its doc
|
||||
// comment / CLAUDE.md "no new copyFileSync line") into a throwaway staging
|
||||
// root, then relocate the staged hooks/ subtree onto `gsd-hooks` — a
|
||||
// root, then relocate the staged hooks/ subtree onto `msd-hooks` — a
|
||||
// NON-"hooks"-named directory is exactly the condition this test exists to
|
||||
// exercise (#3023), so the staged tree cannot simply be used at its
|
||||
// repo-relative `hooks/` location. A hand-copied dependency list is what
|
||||
@@ -607,9 +607,9 @@ describe('GROUP C: bundle-directory-name-agnostic hook scripts', () => {
|
||||
// to the scanner (or any of its deps) cannot be silently omitted here again.
|
||||
const stageRoot = createTempDir('fix-3023-scanner-stage-');
|
||||
t.after(() => cleanup(stageRoot));
|
||||
copyScriptWithDeps(REPO_ROOT, stageRoot, 'hooks/gsd-read-injection-scanner.js');
|
||||
copyScriptWithDeps(REPO_ROOT, stageRoot, 'hooks/msd-read-injection-scanner.js');
|
||||
fs.cpSync(path.join(stageRoot, 'hooks'), bundleDir, { recursive: true });
|
||||
const scannerPath = path.join(bundleDir, 'gsd-read-injection-scanner.js');
|
||||
const scannerPath = path.join(bundleDir, 'msd-read-injection-scanner.js');
|
||||
|
||||
// Node canonicalizes a module's __dirname via the REAL (symlink-resolved)
|
||||
// path, so a payload path must be built from the same realpath — on macOS
|
||||
|
||||
Reference in New Issue
Block a user