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:
Jakub Zych
2026-10-06 01:47:40 +02:00
parent fe069b2a56
commit a9a7a328e6
2763 changed files with 78465 additions and 78434 deletions

View File

@@ -6,8 +6,8 @@
* #2874 (epic #2866 Phase 5), governed by ADR-58
* (docs/adr/58-runtime-install-policy-module.md).
*
* Design: .gsd/phase/feat-2874-executed-plan-return/40-design.md
* Test matrix: .gsd/phase/feat-2874-executed-plan-return/50-test-matrix.md
* Design: .msd/phase/feat-2874-executed-plan-return/40-design.md
* Test matrix: .msd/phase/feat-2874-executed-plan-return/50-test-matrix.md
*
* This file implements the Red-first order's rows 1-3 from 50-test-matrix.md:
* - E3 (section E, "Executed-plan return shape"): the opencode-family
@@ -24,7 +24,7 @@
* — this package is tests only.
*/
process.env.GSD_TEST_MODE = '1';
process.env.MSD_TEST_MODE = '1';
const { test, describe } = require('node:test');
const assert = require('node:assert/strict');
@@ -37,16 +37,16 @@ const fc = require('fast-check');
const { createTempDir, cleanup } = require('./helpers.cjs');
const { installRuntimeArtifacts, hasExistingSymlinkBetween } = require('../gsd-core/bin/lib/install-engine.cjs');
const registry = require('../gsd-core/bin/lib/capability-registry.cjs');
const { loadSkillsManifest, resolveProfile } = require('../gsd-core/bin/lib/install-profiles.cjs');
const runtimeArtifactLayout = require('../gsd-core/bin/lib/runtime-artifact-layout.cjs');
const runtimeArtifactInstallPlan = require('../gsd-core/bin/lib/runtime-artifact-install-plan.cjs');
const { withInstallFs } = require('../gsd-core/bin/lib/install-fs-adapter.cjs');
const commandRoster = require('../gsd-core/bin/lib/command-roster.cjs');
const { installRuntimeArtifacts, hasExistingSymlinkBetween } = require('../msd-core/bin/lib/install-engine.cjs');
const registry = require('../msd-core/bin/lib/capability-registry.cjs');
const { loadSkillsManifest, resolveProfile } = require('../msd-core/bin/lib/install-profiles.cjs');
const runtimeArtifactLayout = require('../msd-core/bin/lib/runtime-artifact-layout.cjs');
const runtimeArtifactInstallPlan = require('../msd-core/bin/lib/runtime-artifact-install-plan.cjs');
const { withInstallFs } = require('../msd-core/bin/lib/install-fs-adapter.cjs');
const commandRoster = require('../msd-core/bin/lib/command-roster.cjs');
const slashCommandTransformer = require('../scripts/fix-slash-commands.cjs');
const REAL_COMMANDS_DIR = path.join(__dirname, '..', 'commands', 'gsd');
const REAL_COMMANDS_DIR = path.join(__dirname, '..', 'commands', 'msd');
const REAL_PACKAGE_ROOT = path.resolve(__dirname, '..');
const MANIFEST = loadSkillsManifest(REAL_COMMANDS_DIR);
const RESOLVED_CORE = resolveProfile({ modes: ['core'], manifest: MANIFEST });
@@ -68,7 +68,7 @@ const { sandboxHome } = require('./helpers.cjs');
describe('installRuntimeArtifacts — E3: opencode-family early return', () => {
test('family install still returns a plan', (t) => {
const configDir = createTempDir('gsd-e3-opencode-');
const configDir = createTempDir('msd-e3-opencode-');
t.after(() => cleanup(configDir));
sandboxHome(t, configDir);
@@ -95,7 +95,7 @@ describe('installRuntimeArtifacts — E13: no runtime returns undefined', () =>
for (const runtime of RUNTIMES) {
test(`${runtime}: installRuntimeArtifacts does not return undefined`, (t) => {
const configDir = createTempDir(`gsd-e13-${runtime}-`);
const configDir = createTempDir(`msd-e13-${runtime}-`);
t.after(() => cleanup(configDir));
sandboxHome(t, configDir);
@@ -117,7 +117,7 @@ describe('installRuntimeArtifacts — E13: no runtime returns undefined', () =>
// The full write+read surface installRuntimeArtifacts's call tree is known to
// reach once every gap named in the #2874 follow-up round is closed: the
// direct mkdirSync/existsSync/rmSync calls, _copyStaged's readdirSync/cpSync/
// copyFileSync/mkdirSync, _removeGsdEntries's directory scan+delete,
// copyFileSync/mkdirSync, _removeMsdEntries's directory scan+delete,
// _snapshotDir/_restoreDir's read/write of preserved skill dirs, the
// symlink-escape guard's lstatSync/realpathSync probes, commonjs-marker.cts's
// lstatSync/writeFileSync/unlinkSync, and installer-migrations.cts's
@@ -136,8 +136,8 @@ describe('installRuntimeArtifacts — E13: no runtime returns undefined', () =>
// never reaches this poison. If this ever fires, `current`'s identity check
// broke, not a documented gap.
//
// One exception this poison list does NOT cover: readGsdCommandNames
// (command-roster.cts) reads the PACKAGE'S OWN commands/gsd/ source tree via
// One exception this poison list does NOT cover: readMsdCommandNames
// (command-roster.cts) reads the PACKAGE'S OWN commands/msd/ source tree via
// real fs.readdirSync — deliberately unrouted (see install-fs-adapter.cts's
// module doc, "DELIBERATELY NOT ROUTED"). `poisonRealFsAgainstDestination`
// below allows real calls scoped to that known package-source root and
@@ -151,7 +151,7 @@ const REAL_FS_WRITE_SURFACE = [
];
// The provider resolver probes upward through the executing package before it
// reaches commands/gsd and agents. All read-only package-tree probes are valid
// reaches commands/msd and agents. All read-only package-tree probes are valid
// real IO while a fake DESTINATION adapter is active; destination paths remain
// poisoned below.
const PACKAGE_SOURCE_ROOTS = [path.resolve(__dirname, '..')];
@@ -167,9 +167,9 @@ function isPackageSourcePath(resolvedPath) {
* limits"/install-fs-adapter.cts's module doc) rather than aligned with it by
* coincidence: a real fs call against the install DESTINATION is a failure —
* the seam exists precisely so a fake adapter can intercept those — but a
* real call against the package's OWN source tree (commands/gsd/, agents/)
* real call against the package's OWN source tree (commands/msd/, agents/)
* is expected and allowed, because that read is deliberately unrouted
* (readGsdCommandNames et al.). Poisoning every real fs method wholesale,
* (readMsdCommandNames et al.). Poisoning every real fs method wholesale,
* regardless of path, makes a correct install fail for the wrong reason.
*
* Returns a Map<method, count> of package-source hits, so a caller can
@@ -358,7 +358,7 @@ function createFakeInstallFs(seed = []) {
// itself rather than assuming it.
describe('createFakeInstallFs — wx exclusive-create emulation', () => {
test('refuses an exclusive create against an existing path (EEXIST)', () => {
const target = path.join(os.tmpdir(), 'gsd-fake-wx-existing.txt');
const target = path.join(os.tmpdir(), 'msd-fake-wx-existing.txt');
const fakeFs = createFakeInstallFs([[target, { type: 'file', content: 'original' }]]);
assert.throws(
@@ -374,7 +374,7 @@ describe('createFakeInstallFs — wx exclusive-create emulation', () => {
});
test('allows an exclusive create against an absent path', () => {
const target = path.join(os.tmpdir(), 'gsd-fake-wx-absent.txt');
const target = path.join(os.tmpdir(), 'msd-fake-wx-absent.txt');
const fakeFs = createFakeInstallFs();
fakeFs.writeFileSync(target, 'created', { flag: 'wx' });
@@ -390,16 +390,16 @@ function sha256Hex(content) {
}
function fakeInstalledCorpusSeed(configDir) {
const coreDir = path.join(configDir, 'gsd-core');
const coreDir = path.join(configDir, 'msd-core');
const commandsDir = path.join(coreDir, 'commands');
const commandsGsdDir = path.join(commandsDir, 'gsd');
const commandsMsdDir = path.join(commandsDir, 'msd');
const agentsDir = path.join(coreDir, 'agents');
return [
[configDir, { type: 'dir' }],
[coreDir, { type: 'dir' }],
[commandsDir, { type: 'dir' }],
[commandsGsdDir, { type: 'dir' }],
[path.join(commandsGsdDir, 'fixture.md'), { type: 'file', content: '# Fixture command\n' }],
[commandsMsdDir, { type: 'dir' }],
[path.join(commandsMsdDir, 'fixture.md'), { type: 'file', content: '# Fixture command\n' }],
[agentsDir, { type: 'dir' }],
[path.join(agentsDir, 'fixture-agent.md'), { type: 'file', content: '# Fixture agent\n' }],
];
@@ -407,8 +407,8 @@ function fakeInstalledCorpusSeed(configDir) {
function fakeInstalledCorpusManifestFiles() {
return {
'gsd-core/commands/gsd/fixture.md': sha256Hex('# Fixture command\n'),
'gsd-core/agents/fixture-agent.md': sha256Hex('# Fixture agent\n'),
'msd-core/commands/msd/fixture.md': sha256Hex('# Fixture command\n'),
'msd-core/agents/fixture-agent.md': sha256Hex('# Fixture agent\n'),
};
}
@@ -421,7 +421,7 @@ describe('installRuntimeArtifacts — F2: fake-adapter install touches no real f
// try/finally inside test bodies").
const packageSourceHits = poisonRealFsAgainstDestination(t, '');
const configDir = path.join(os.tmpdir(), `gsd-f2-must-not-exist-${crypto.randomUUID()}`);
const configDir = path.join(os.tmpdir(), `msd-f2-must-not-exist-${crypto.randomUUID()}`);
const fakeFs = createFakeInstallFs(fakeInstalledCorpusSeed(configDir));
// configDir exists only in the fake store — F2 asserts nothing real ever
@@ -446,7 +446,7 @@ describe('installRuntimeArtifacts — F2: fake-adapter install touches no real f
// touch the poisoned surface.
assert.ok(
(packageSourceHits.get('readdirSync') ?? 0) > 0,
'F2: readGsdCommandNames must have read the real, unrouted commands/gsd/ package-source ' +
'F2: readMsdCommandNames must have read the real, unrouted commands/msd/ package-source ' +
'tree at least once — proving the poison boundary was exercised, not merely tolerated',
);
});
@@ -454,14 +454,14 @@ describe('installRuntimeArtifacts — F2: fake-adapter install touches no real f
test('fake-adapter install touches no real filesystem (opencode-family legacy command/ dir migration)', (t) => {
poisonRealFsAgainstDestination(t, ' (opencode legacy migration)');
const configDir = path.join(os.tmpdir(), `gsd-f2-opencode-legacy-${crypto.randomUUID()}`);
const configDir = path.join(os.tmpdir(), `msd-f2-opencode-legacy-${crypto.randomUUID()}`);
const legacyDir = path.join(configDir, 'command');
const legacyFile = path.join(legacyDir, 'gsd-old-cmd.md');
const legacyFile = path.join(legacyDir, 'msd-old-cmd.md');
const content = '# stale legacy command\n';
const manifestPath = path.join(configDir, 'gsd-file-manifest.json');
const manifestPath = path.join(configDir, 'msd-file-manifest.json');
const manifestJson = JSON.stringify({ files: {
...fakeInstalledCorpusManifestFiles(),
'command/gsd-old-cmd.md': sha256Hex(content),
'command/msd-old-cmd.md': sha256Hex(content),
} });
const fakeFs = createFakeInstallFs([
@@ -502,13 +502,13 @@ describe('installRuntimeArtifacts — F2: fake-adapter install touches no real f
// the poisoned list (see install-fs-adapter.cts's module doc — it is
// deliberately unrouted, real-fs-only, package-source introspection), so
// resolving this here is safe even after poisoning existsSync et al.
const commandsGsdDir = REAL_COMMANDS_DIR;
const repoRoot = path.dirname(path.dirname(commandsGsdDir));
const commandsMsdDir = REAL_COMMANDS_DIR;
const repoRoot = path.dirname(path.dirname(commandsMsdDir));
const nativePlugin = registry.runtimes.pi.runtime.hostBehaviors.nativePlugin;
assert.ok(nativePlugin && nativePlugin.source, 'pi must declare hostBehaviors.nativePlugin.source (registry drifted)');
const pluginSrc = path.join(repoRoot, nativePlugin.source);
const configDir = path.join(os.tmpdir(), `gsd-f2-pi-nativeplugin-${crypto.randomUUID()}`);
const configDir = path.join(os.tmpdir(), `msd-f2-pi-nativeplugin-${crypto.randomUUID()}`);
const fakeFs = createFakeInstallFs([
[pluginSrc, { type: 'file', content: '// fake plugin adapter\n' }],
]);
@@ -541,13 +541,13 @@ describe('installRuntimeArtifacts — F2: fake-adapter install touches no real f
assert.ok(Array.isArray(retired) && retired.length > 0, 'cursor must declare hostBehaviors.retiredArtifacts (registry drifted)');
const { destSubpath, prefix, suffix } = retired[0];
const configDir = path.join(os.tmpdir(), `gsd-f2-cursor-retired-${crypto.randomUUID()}`);
const configDir = path.join(os.tmpdir(), `msd-f2-cursor-retired-${crypto.randomUUID()}`);
const destDir = path.resolve(configDir, destSubpath);
const staleName = `${prefix}retired-probe${suffix}`;
const staleFile = path.join(destDir, staleName);
const content = '# stale retired artifact\n';
const relPath = `${destSubpath.replace(/\\/g, '/')}/${staleName}`;
const manifestPath = path.join(configDir, 'gsd-file-manifest.json');
const manifestPath = path.join(configDir, 'msd-file-manifest.json');
const manifestJson = JSON.stringify({ files: {
...fakeInstalledCorpusManifestFiles(),
[relPath]: sha256Hex(content),
@@ -576,7 +576,7 @@ describe('installRuntimeArtifacts — F2: fake-adapter install touches no real f
);
assert.ok(
(packageSourceHits.get('readdirSync') ?? 0) > 0,
'F2 (retiredArtifacts): readGsdCommandNames must have read the real, unrouted commands/gsd/ ' +
'F2 (retiredArtifacts): readMsdCommandNames must have read the real, unrouted commands/msd/ ' +
'package-source tree at least once — proving the poison boundary was exercised, not merely tolerated',
);
});
@@ -592,7 +592,7 @@ describe('installRuntimeArtifacts — F2: fake-adapter install touches no real f
describe('installRuntimeArtifacts — E1: claude global, normal install', () => {
test('returns an executed plan for a normal install', (t) => {
const configDir = createTempDir('gsd-e1-claude-global-');
const configDir = createTempDir('msd-e1-claude-global-');
t.after(() => cleanup(configDir));
sandboxHome(t, configDir);
@@ -609,7 +609,7 @@ describe('installRuntimeArtifacts — E1: claude global, normal install', () =>
describe('installRuntimeArtifacts — E2: claude local', () => {
test('executed plan records the scope', (t) => {
const configDir = createTempDir('gsd-e2-claude-local-');
const configDir = createTempDir('msd-e2-claude-local-');
t.after(() => cleanup(configDir));
sandboxHome(t, configDir);
@@ -621,7 +621,7 @@ describe('installRuntimeArtifacts — E2: claude local', () => {
describe('installRuntimeArtifacts — E4: kilo (second family member)', () => {
test('kilo family install still returns a plan', (t) => {
const configDir = createTempDir('gsd-e4-kilo-');
const configDir = createTempDir('msd-e4-kilo-');
t.after(() => cleanup(configDir));
sandboxHome(t, configDir);
@@ -647,7 +647,7 @@ describe('installRuntimeArtifacts — E4: kilo (second family member)', () => {
describe('installRuntimeArtifacts — E5/E7: empty layout + nativePlugin post-step (pi)', () => {
test('empty layout returns an empty plan', (t) => {
const configDir = createTempDir('gsd-e5-pi-');
const configDir = createTempDir('msd-e5-pi-');
t.after(() => cleanup(configDir));
sandboxHome(t, configDir);
@@ -658,7 +658,7 @@ describe('installRuntimeArtifacts — E5/E7: empty layout + nativePlugin post-st
});
test('native plugin post-step is recorded', (t) => {
const configDir = createTempDir('gsd-e7-pi-');
const configDir = createTempDir('msd-e7-pi-');
t.after(() => cleanup(configDir));
sandboxHome(t, configDir);
@@ -673,7 +673,7 @@ describe('installRuntimeArtifacts — E5/E7: empty layout + nativePlugin post-st
describe('installRuntimeArtifacts — E6: hermes post-step is recorded', () => {
test('hermes post-step is recorded', (t) => {
const configDir = createTempDir('gsd-e6-hermes-');
const configDir = createTempDir('msd-e6-hermes-');
t.after(() => cleanup(configDir));
sandboxHome(t, configDir);
@@ -688,10 +688,10 @@ describe('installRuntimeArtifacts — E6: hermes post-step is recorded', () => {
describe('installRuntimeArtifacts — E8: preserved user skill dirs are recorded', () => {
test('preserved user skill dirs are recorded', (t) => {
const configDir = createTempDir('gsd-e8-claude-');
const configDir = createTempDir('msd-e8-claude-');
t.after(() => cleanup(configDir));
sandboxHome(t, configDir);
const preservedSkillDir = path.join(configDir, 'skills', 'gsd-dev-preferences');
const preservedSkillDir = path.join(configDir, 'skills', 'msd-dev-preferences');
fs.mkdirSync(preservedSkillDir, { recursive: true });
fs.writeFileSync(path.join(preservedSkillDir, 'SKILL.md'), '# my custom prefs\n');
@@ -700,8 +700,8 @@ describe('installRuntimeArtifacts — E8: preserved user skill dirs are recorded
const skillsKind = result.kinds.find((k) => k.kind === 'skills');
assert.ok(skillsKind, 'E8 precondition: claude global must write a skills kind');
assert.deepStrictEqual(
skillsKind.preserved, ['gsd-dev-preferences'],
'E8: the plan must record gsd-dev-preferences as preserved',
skillsKind.preserved, ['msd-dev-preferences'],
'E8: the plan must record msd-dev-preferences as preserved',
);
assert.strictEqual(
fs.readFileSync(path.join(preservedSkillDir, 'SKILL.md'), 'utf8'),
@@ -713,7 +713,7 @@ describe('installRuntimeArtifacts — E8: preserved user skill dirs are recorded
describe('installRuntimeArtifacts — E9: non-skills kind records its writes', () => {
test('non-skills kind records its writes', (t) => {
const configDir = createTempDir('gsd-e9-claude-local-');
const configDir = createTempDir('msd-e9-claude-local-');
t.after(() => cleanup(configDir));
sandboxHome(t, configDir);
@@ -731,7 +731,7 @@ describe('installRuntimeArtifacts — E9: non-skills kind records its writes', (
describe('installRuntimeArtifacts — E10: plan item naming a kind absent from layout.kinds', () => {
test('unknown kind still throws', (t) => {
const configDir = createTempDir('gsd-e10-claude-');
const configDir = createTempDir('msd-e10-claude-');
t.after(() => cleanup(configDir));
sandboxHome(t, configDir);
@@ -763,7 +763,7 @@ describe('installRuntimeArtifacts — E10: plan item naming a kind absent from l
describe('installRuntimeArtifacts — E11: plan is not shared across calls', () => {
test('plan is not shared across calls', (t) => {
const configDir = createTempDir('gsd-e11-claude-');
const configDir = createTempDir('msd-e11-claude-');
t.after(() => cleanup(configDir));
sandboxHome(t, configDir);
@@ -788,7 +788,7 @@ describe('installRuntimeArtifacts — E11: plan is not shared across calls', ()
describe('installRuntimeArtifacts — E12: executed plan key set is locked', () => {
test('executed plan key set is locked', (t) => {
const configDir = createTempDir('gsd-e12-claude-');
const configDir = createTempDir('msd-e12-claude-');
t.after(() => cleanup(configDir));
sandboxHome(t, configDir);
@@ -846,14 +846,14 @@ function createRealDelegatingFs(overrides = {}) {
describe('installRuntimeArtifacts — F4: adapter errors propagate, cleanup still runs', () => {
test('adapter errors propagate, cleanup still runs', (t) => {
const configDir = createTempDir('gsd-f4-augment-');
const configDir = createTempDir('msd-f4-augment-');
t.after(() => cleanup(configDir));
sandboxHome(t, configDir);
let capturedCleanupDir;
const fakeFs = createRealDelegatingFs({
writeFileSync: (p, data, opts) => {
if (String(p).includes('gsd-cmd-rewrites-') && capturedCleanupDir === undefined) {
if (String(p).includes('msd-cmd-rewrites-') && capturedCleanupDir === undefined) {
capturedCleanupDir = path.dirname(p);
}
fs.writeFileSync(p, data, opts);
@@ -880,7 +880,7 @@ describe('installRuntimeArtifacts — F4: adapter errors propagate, cleanup stil
describe('installRuntimeArtifacts — F5: fake existsSync drives the same branch', () => {
test('fake existsSync drives the same branch', () => {
const configDir = path.join(os.tmpdir(), `gsd-f5-must-not-exist-${crypto.randomUUID()}`);
const configDir = path.join(os.tmpdir(), `msd-f5-must-not-exist-${crypto.randomUUID()}`);
const skillsDest = path.join(configDir, 'skills');
// Seed ONLY the skills destDir as a pre-existing (empty) directory in the
// fake store — configDir is never created for real, so existsSync(dest)
@@ -912,13 +912,13 @@ describe('installRuntimeArtifacts — F6: incomplete adapter fails loudly, never
// user-artifact-staging.cts's `stageUserArtifacts` calling
// `installFs().rmSync(entryDir)` unconditionally, where a test fake
// missing `rmSync` would silently delete the real
// `<configDir>/.gsd-staging/<key>` on disk. Falling through to real fs is
// `<configDir>/.msd-staging/<key>` on disk. Falling through to real fs is
// exactly how a fake-adapter test can end up performing real, uncontrolled
// IO — the bug, not a feature. The guarded contract instead throws
// immediately, naming the missing method, the moment the exercised path
// reaches it: never a silent no-op AND never a silent real-fs write.
test('incomplete adapter fails loudly (never silently skips the write)', () => {
const configDir = path.join(os.tmpdir(), `gsd-f6-must-not-exist-${crypto.randomUUID()}`);
const configDir = path.join(os.tmpdir(), `msd-f6-must-not-exist-${crypto.randomUUID()}`);
// Deliberately incomplete: only mkdirSync is implemented, to prove the
// FIRST other method the call path reaches throws immediately instead of
@@ -941,7 +941,7 @@ describe('installRuntimeArtifacts — F6: incomplete adapter fails loudly, never
describe('installRuntimeArtifacts — G2: bin/install.js production call site unchanged', () => {
test('installer call site unchanged', (t) => {
const binInstall = require('../bin/install.js');
const tmpDir = createTempDir('gsd-g2-');
const tmpDir = createTempDir('msd-g2-');
const previousCwd = process.cwd();
process.chdir(tmpDir);
t.after(() => { process.chdir(previousCwd); cleanup(tmpDir); });
@@ -966,8 +966,8 @@ describe('installRuntimeArtifacts — G2: bin/install.js production call site un
describe('installRuntimeArtifacts — H1: symlink escape still refuses', () => {
test('symlink escape still refuses', (t) => {
const configDir = createTempDir('gsd-h1-');
const outsideDir = createTempDir('gsd-h1-outside-');
const configDir = createTempDir('msd-h1-');
const outsideDir = createTempDir('msd-h1-outside-');
t.after(() => { cleanup(configDir); cleanup(outsideDir); });
sandboxHome(t, configDir);
// Pre-create the skills destDir AS a symlink pointing outside configDir —
@@ -976,7 +976,7 @@ describe('installRuntimeArtifacts — H1: symlink escape still refuses', () => {
assert.throws(
() => installRuntimeArtifacts('claude', configDir, 'global', RESOLVED_CORE),
/GSD_ALLOW_SYMLINKED_DEST/,
/MSD_ALLOW_SYMLINKED_DEST/,
'H1: a destDir that is itself a symlink pointing outside the install root must be refused',
);
});
@@ -984,17 +984,17 @@ describe('installRuntimeArtifacts — H1: symlink escape still refuses', () => {
describe('installRuntimeArtifacts — H2: opt-in still follows', () => {
test('opt-in still follows', (t) => {
const configDir = createTempDir('gsd-h2-');
const outsideDir = createTempDir('gsd-h2-outside-');
const configDir = createTempDir('msd-h2-');
const outsideDir = createTempDir('msd-h2-outside-');
t.after(() => { cleanup(configDir); cleanup(outsideDir); });
sandboxHome(t, configDir);
fs.symlinkSync(outsideDir, path.join(configDir, 'skills'), 'dir');
const savedOptIn = process.env.GSD_ALLOW_SYMLINKED_DEST;
process.env.GSD_ALLOW_SYMLINKED_DEST = '1';
const savedOptIn = process.env.MSD_ALLOW_SYMLINKED_DEST;
process.env.MSD_ALLOW_SYMLINKED_DEST = '1';
t.after(() => {
if (savedOptIn === undefined) delete process.env.GSD_ALLOW_SYMLINKED_DEST;
else process.env.GSD_ALLOW_SYMLINKED_DEST = savedOptIn;
if (savedOptIn === undefined) delete process.env.MSD_ALLOW_SYMLINKED_DEST;
else process.env.MSD_ALLOW_SYMLINKED_DEST = savedOptIn;
});
const result = installRuntimeArtifacts('claude', configDir, 'global', RESOLVED_CORE);
@@ -1018,7 +1018,7 @@ describe('installRuntimeArtifacts — H3: fake adapter cannot bypass the symlink
// invariant directly: even a fake adapter that lies "nothing exists,
// nothing is a symlink" everywhere cannot make this refusal pass for an
// escaping path, because this branch never asks the adapter anything.
const root = path.join(os.tmpdir(), 'gsd-h3-fake-root');
const root = path.join(os.tmpdir(), 'msd-h3-fake-root');
const escapingPath = path.join(root, '..', '..', 'etc', 'passwd');
const lyingFs = {
existsSync: () => false,
@@ -1063,7 +1063,7 @@ describe('installRuntimeArtifacts — H5: nul byte in dest is rejected', () => {
describe('installRuntimeArtifacts — I1: successful cleanup is recorded', () => {
test('successful cleanup is recorded', (t) => {
const configDir = createTempDir('gsd-i1-augment-');
const configDir = createTempDir('msd-i1-augment-');
t.after(() => cleanup(configDir));
sandboxHome(t, configDir);
@@ -1080,13 +1080,13 @@ describe('installRuntimeArtifacts — I1: successful cleanup is recorded', () =>
describe('installRuntimeArtifacts — I2: failed cleanup is visible, not silent', () => {
test('failed cleanup is visible, not silent', (t) => {
const configDir = createTempDir('gsd-i2-augment-');
const configDir = createTempDir('msd-i2-augment-');
t.after(() => cleanup(configDir));
sandboxHome(t, configDir);
const fakeFs = createRealDelegatingFs({
rmSync: (p, opts) => {
if (String(p).includes('gsd-cmd-rewrites-')) {
if (String(p).includes('msd-cmd-rewrites-')) {
throw new Error('I2: simulated cleanup failure');
}
// eslint-disable-next-line local/no-raw-rmsync-in-tests -- delegate, not test cleanup
@@ -1107,7 +1107,7 @@ describe('installRuntimeArtifacts — I2: failed cleanup is visible, not silent'
describe('installRuntimeArtifacts — I3: no cleanup dirs is an empty array', () => {
test('no cleanup dirs is an empty array', (t) => {
const configDir = createTempDir('gsd-i3-claude-');
const configDir = createTempDir('msd-i3-claude-');
t.after(() => cleanup(configDir));
sandboxHome(t, configDir);
@@ -1123,7 +1123,7 @@ describe('installRuntimeArtifacts — I3: no cleanup dirs is an empty array', ()
describe('installRuntimeArtifacts — I4: stage failure before any item cleans up and throws', () => {
test('stage failure cleans up and throws', (t) => {
const configDir = createTempDir('gsd-i4-');
const configDir = createTempDir('msd-i4-');
t.after(() => cleanup(configDir));
sandboxHome(t, configDir);
@@ -1138,21 +1138,21 @@ describe('installRuntimeArtifacts — I4: stage failure before any item cleans u
describe('installRuntimeArtifacts — I5: rewrite failure mid-plan cleans up and throws', () => {
test('rewrite failure cleans up and throws', (t) => {
const configDir = createTempDir('gsd-i5-augment-');
const configDir = createTempDir('msd-i5-augment-');
t.after(() => cleanup(configDir));
sandboxHome(t, configDir);
let capturedCleanupDir;
const fakeFs = createRealDelegatingFs({
mkdirSync: (p, opts) => {
if (String(p).includes('gsd-profile-runtime-skills-')) {
if (String(p).includes('msd-profile-runtime-skills-')) {
throw new Error('I5: simulated skills-stage failure AFTER commands already rewrote+registered a cleanup dir');
}
fs.mkdirSync(p, opts);
return undefined;
},
writeFileSync: (p, data, opts) => {
if (String(p).includes('gsd-cmd-rewrites-') && capturedCleanupDir === undefined) {
if (String(p).includes('msd-cmd-rewrites-') && capturedCleanupDir === undefined) {
capturedCleanupDir = path.dirname(p);
}
fs.writeFileSync(p, data, opts);
@@ -1192,29 +1192,29 @@ function walkFilesRecursively(root) {
describe('installRuntimeArtifacts — K3: real install before/after, full recursive diff', () => {
test('writes are byte-identical', (t) => {
for (const runtime of ['claude', 'qwen']) {
const dirA = createTempDir(`gsd-k3-${runtime}-a-`);
const dirB = createTempDir(`gsd-k3-${runtime}-b-`);
const dirA = createTempDir(`msd-k3-${runtime}-a-`);
const dirB = createTempDir(`msd-k3-${runtime}-b-`);
// Two SEQUENTIAL sandboxes for one test: sandboxHome()'s per-call
// t.after hooks each save the env as they found it, so the second call
// saves the FIRST sandbox as its "original" — hook ordering then leaves
// HOME pointing at dirA after the test, leaking into later tests in the
// shard (observed on the windows matrix: a leaked gsd-k3-qwen-* home
// shard (observed on the windows matrix: a leaked msd-k3-qwen-* home
// made the L2 property's antigravity/global run refuse via the
// #3712 real-home guard). Manage the env directly with ONE restore.
const savedHome = process.env.HOME;
const savedUserProfile = process.env.USERPROFILE;
const savedMarker = process.env.GSD_TEST_HOME_SANDBOX;
const savedMarker = process.env.MSD_TEST_HOME_SANDBOX;
t.after(() => {
if (savedHome === undefined) delete process.env.HOME; else process.env.HOME = savedHome;
if (savedUserProfile === undefined) delete process.env.USERPROFILE; else process.env.USERPROFILE = savedUserProfile;
if (savedMarker === undefined) delete process.env.GSD_TEST_HOME_SANDBOX; else process.env.GSD_TEST_HOME_SANDBOX = savedMarker;
if (savedMarker === undefined) delete process.env.MSD_TEST_HOME_SANDBOX; else process.env.MSD_TEST_HOME_SANDBOX = savedMarker;
cleanup(dirA); cleanup(dirB);
});
for (const dir of [dirA, dirB]) {
process.env.HOME = dir;
process.env.USERPROFILE = dir;
process.env.GSD_TEST_HOME_SANDBOX = dir;
process.env.MSD_TEST_HOME_SANDBOX = dir;
installRuntimeArtifacts(runtime, dir, 'global', RESOLVED_FULL);
}
@@ -1225,15 +1225,15 @@ describe('installRuntimeArtifacts — K3: real install before/after, full recurs
`K3 (${runtime}): the file sets written by two independent installs must match`,
);
for (const [relPath, contentA] of filesA) {
if (relPath === '.gsd-source') {
if (relPath === '.msd-source') {
assert.strictEqual(
contentA.toString('utf8'),
`${path.join(dirA, 'gsd-core', 'commands', 'gsd')}\n`,
`${path.join(dirA, 'msd-core', 'commands', 'msd')}\n`,
`K3 (${runtime}): first marker must target its own installed corpus`,
);
assert.strictEqual(
filesB.get(relPath).toString('utf8'),
`${path.join(dirB, 'gsd-core', 'commands', 'gsd')}\n`,
`${path.join(dirB, 'msd-core', 'commands', 'msd')}\n`,
`K3 (${runtime}): second marker must target its own installed corpus`,
);
continue;
@@ -1268,7 +1268,7 @@ describe('installRuntimeArtifacts — L1: plan kinds mirror layout kinds (proper
// the failing/shrunk (runtime, scope) pair fast-check found).
fc.assert(
fc.property(RUNTIME_ARB, SCOPE_ARB, (runtime, scope) => {
const configDir = createTempDir(`gsd-l1-${runtime}-`);
const configDir = createTempDir(`msd-l1-${runtime}-`);
createdDirs.push(configDir);
process.env.HOME = configDir;
process.env.USERPROFILE = configDir;
@@ -1335,7 +1335,7 @@ describe('installRuntimeArtifacts — L2: plan is deterministic (property)', ()
fc.property(RUNTIME_ARB, SCOPE_ARB, (runtime, scope) => {
// configDir is never created for real — both calls run against fresh,
// independent fake adapters, so no real fs cleanup is needed here.
const configDir = path.join(os.tmpdir(), `gsd-l2-${runtime}-${crypto.randomUUID()}`);
const configDir = path.join(os.tmpdir(), `msd-l2-${runtime}-${crypto.randomUUID()}`);
fs.mkdirSync(configDir, { recursive: true });
createdL2Dirs.push(configDir);
// #3738: a home-override runtime (antigravity → <HOME>/.gemini/config)
@@ -1371,31 +1371,31 @@ describe('installRuntimeArtifacts — L2: plan is deterministic (property)', ()
});
});
// ─── readGsdCommandNames — single-source parity ──────────────────────────────
// ─── readMsdCommandNames — single-source parity ──────────────────────────────
//
// command-roster.cts's readGsdCommandNames reimplements
// command-roster.cts's readMsdCommandNames reimplements
// scripts/fix-slash-commands.cjs's readCmdNames' directory-scan rule against
// the injectable install-fs seam instead of delegating to it — see
// command-roster.cts's module comment for why (readCmdNames is deliberately
// a zero-dependency standalone CLI/library with no build-order dependency on
// gsd-core/bin/lib, so it cannot itself require the compiled
// msd-core/bin/lib, so it cannot itself require the compiled
// install-fs-adapter.cjs). Two implementations of one filtering rule is this
// repo's recorded Generative Fix Divergence class; this test is the
// enforcement the coordinator required in exchange for keeping the
// reimplementation: it fails the moment the two disagree about which stems
// commands/gsd/ contains.
// commands/msd/ contains.
describe('readGsdCommandNames — single-source parity (command-roster.cts vs scripts/fix-slash-commands.cjs)', () => {
test('both implementations report the identical stem set for commands/gsd/', () => {
const fromCommandRoster = [...commandRoster.readGsdCommandNames()].sort();
describe('readMsdCommandNames — single-source parity (command-roster.cts vs scripts/fix-slash-commands.cjs)', () => {
test('both implementations report the identical stem set for commands/msd/', () => {
const fromCommandRoster = [...commandRoster.readMsdCommandNames()].sort();
const fromSlashCommandTransformer = [...slashCommandTransformer.readCmdNames()].sort();
assert.deepStrictEqual(
fromCommandRoster,
fromSlashCommandTransformer,
'command-roster.cts readGsdCommandNames() and scripts/fix-slash-commands.cjs readCmdNames() ' +
'command-roster.cts readMsdCommandNames() and scripts/fix-slash-commands.cjs readCmdNames() ' +
'diverged — these are two implementations of the SAME directory-scan rule (Generative Fix ' +
'Divergence); fix the one that is wrong, do not just silence this test',
);
assert.ok(fromCommandRoster.length > 0, 'sanity: commands/gsd/ must contain at least one command');
assert.ok(fromCommandRoster.length > 0, 'sanity: commands/msd/ must contain at least one command');
});
});