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

@@ -8,7 +8,7 @@ const test = require('node:test');
const helpers = require('./helpers.cjs');
const hooksSurface = require('../gsd-core/bin/lib/runtime-hooks-surface.cjs');
const hooksSurface = require('../msd-core/bin/lib/runtime-hooks-surface.cjs');
const { install, installAllRuntimes, finishInstall } = require('../bin/install.js');
/**
@@ -93,21 +93,21 @@ test('a hook already registered under a stale command is still tracked for valid
// installer versions) and still shaped as the modern runtime-resolving
// chain (rewriteLegacyManagedNodeHookCommands deliberately never touches
// an already-current-format entry — #3662), but baked with a node path
// this install would never produce. `hasGsdUpdateHook` still finds it and
// this install would never produce. `hasMsdUpdateHook` still finds it and
// applySettingsJsonHooks takes its register-only-if-absent branch on the
// next install (never rewriting it).
const onDisk = JSON.parse(fs.readFileSync(first.settingsPath, 'utf8'));
const staleEntry = (onDisk.hooks.SessionStart || []).find(entry =>
entry.hooks && entry.hooks.some(h => h.command && h.command.includes('gsd-check-update.js'))
entry.hooks && entry.hooks.some(h => h.command && h.command.includes('msd-check-update.js'))
);
assert.ok(staleEntry, 'a fresh install must register the check-update hook');
const staleCommand = hooksSurface.buildHookCommand(first.configDir, 'gsd-check-update.js', {
const staleCommand = hooksSurface.buildHookCommand(first.configDir, 'msd-check-update.js', {
execPath: '/old/nvm/pinned/node',
platform: process.platform,
runtime: 'claude',
});
for (const h of staleEntry.hooks) {
if (h.command && h.command.includes('gsd-check-update.js')) {
if (h.command && h.command.includes('msd-check-update.js')) {
h.command = staleCommand;
}
}
@@ -116,7 +116,7 @@ test('a hook already registered under a stale command is still tracked for valid
const second = install(true, 'claude');
const trackedNames = (second.configuredEntrypoints || []).map(entry => path.basename(entry.scriptPath));
assert.ok(
trackedNames.includes('gsd-check-update.js'),
trackedNames.includes('msd-check-update.js'),
`a hook already registered under a stale command must still be tracked for validation, got: ${trackedNames.join(', ')}`,
);
});
@@ -297,7 +297,7 @@ test('a win32 selfExecutable entry (Codex .cmd shim) skips the execute-bit check
// a spurious 'not-executable' for a .cmd shim that was never chmod'd +x.
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'configured-entrypoint-win32-cmd-'));
t.after(() => helpers.cleanup(root));
const cmdPath = path.join(root, 'gsd-check-update.cmd');
const cmdPath = path.join(root, 'msd-check-update.cmd');
fs.writeFileSync(cmdPath, '@echo off\r\n');
const result = hooksSurface.validateConfiguredEntrypoints([
@@ -329,7 +329,7 @@ test('runtime config writers expose the exact configured entrypoints they emit',
const codexRoot = path.join(root, 'codex');
// On win32, ensureCodexHooksJsonSessionStart writes a .cmd shim under
// <codexRoot>/hooks/; the real installer only calls this once that dir
// (and gsd-check-update.js) already exist, so create it here too.
// (and msd-check-update.js) already exist, so create it here too.
fs.mkdirSync(path.join(codexRoot, 'hooks'), { recursive: true });
const codex = hooksSurface.ensureCodexHooksJsonSessionStart(codexRoot, {
absoluteRunner: JSON.stringify(process.execPath),
@@ -342,7 +342,7 @@ test('runtime config writers expose the exact configured entrypoints they emit',
&& entry.configPath === path.join(codexRoot, 'hooks.json')
&& entry.platform === process.platform));
assert.ok(codex.configuredEntrypoints.some(
entry => path.basename(entry.scriptPath) === 'gsd-check-update.js'
entry => path.basename(entry.scriptPath) === 'msd-check-update.js'
&& Array.isArray(entry.interpreterCandidates)
&& entry.interpreterCandidates.length === 1,
));
@@ -353,7 +353,7 @@ test('runtime config writers expose the exact configured entrypoints they emit',
});
assert.deepEqual(
cursor.configuredEntrypoints.map(entry => path.basename(entry.scriptPath)),
['gsd-cursor-session-start.js'],
['msd-cursor-session-start.js'],
);
assert.ok(cursor.configuredEntrypoints.every(entry => entry.configPath === cursor.hooksJsonPath));
@@ -361,7 +361,7 @@ test('runtime config writers expose the exact configured entrypoints they emit',
const windsurf = hooksSurface.writeWindsurfHooksJson(windsurfRoot, sourceRoot);
assert.deepEqual(
windsurf.configuredEntrypoints.map(entry => path.basename(entry.scriptPath)).sort(),
['gsd-windsurf-pre-command.js', 'gsd-windsurf-pre-write.js'],
['msd-windsurf-pre-command.js', 'msd-windsurf-pre-write.js'],
);
const kimiRoot = path.join(root, 'kimi');
@@ -381,13 +381,13 @@ test('runtime config writers expose the exact configured entrypoints they emit',
);
// #4249 (CodeRabbit): Cline's `#!/usr/bin/env node` hook is a hybrid —
// self-executable (needs its own execute bit checked) AND PATH-dependent
// on `node` (needs an interpreter candidate resolved), unlike GSD's other
// on `node` (needs an interpreter candidate resolved), unlike MSD's other
// JS hooks which bake an absolute node path specifically to avoid this.
assert.equal(cline.configuredEntrypoints[0].selfExecutable, true);
assert.deepEqual(cline.configuredEntrypoints[0].interpreterCandidates, ['node']);
const portable = [];
assert.ok(hooksSurface.buildHookCommand(root, 'gsd-context-monitor.js', {
assert.ok(hooksSurface.buildHookCommand(root, 'msd-context-monitor.js', {
runtime: 'claude',
portableHooks: true,
configPath: path.join(root, 'settings.json'),
@@ -395,7 +395,7 @@ test('runtime config writers expose the exact configured entrypoints they emit',
}));
assert.deepEqual(
portable.map(entry => path.basename(entry.scriptPath)),
['gsd-node-runner.sh', 'gsd-context-monitor.js'],
['msd-node-runner.sh', 'msd-context-monitor.js'],
);
});
@@ -406,15 +406,15 @@ test('a minimal Codex rollback restores skills from the alternate skills home (#
// skills-kind `home` override) — the surface #3245's own snapshot owns and
// the manifest-driven pass deliberately leaves to it.
const skillsRoot = path.join(root, '.agents', 'skills');
const skillDir = fs.readdirSync(skillsRoot).find(name => name.startsWith('gsd-'));
assert.ok(skillDir, `a Codex install must write gsd-* skills under ${skillsRoot}`);
const skillDir = fs.readdirSync(skillsRoot).find(name => name.startsWith('msd-'));
assert.ok(skillDir, `a Codex install must write msd-* skills under ${skillsRoot}`);
const skillFile = path.join(skillsRoot, skillDir, 'SKILL.md');
const priorBytes = '# bytes only this test wrote\n';
fs.writeFileSync(skillFile, priorBytes);
// Marker-driven core profile — the `gsd update` path into minimal mode.
fs.writeFileSync(path.join(first.configDir, '.gsd-profile'), 'core\n');
// Marker-driven core profile — the `msd update` path into minimal mode.
fs.writeFileSync(path.join(first.configDir, '.msd-profile'), 'core\n');
const second = install(true, 'codex');
second.rollbackPreInstallSnapshot();
@@ -471,7 +471,7 @@ test('an aggregate entrypoint validation failure leaves Cline\'s own config file
// Cline is one of the four runtimes (Cursor/Windsurf/Kimi/Cline) that
// write their config file inside install(), ahead of the validation
// gate, with no snapshot/restore path — see the rollback-matrix
// paragraph in the update-gsd how-to. Unlike the Codex companion test above,
// paragraph in the update-msd how-to. Unlike the Codex companion test above,
// this asserts the POSITIVE case that same paragraph discloses in
// prose but no prior test proved: the file the failing runtime itself
// just wrote is still there afterward, broken and unreverted.
@@ -514,7 +514,7 @@ test('a NON-entrypoint finalize failure leaves an already-successful Codex insta
// Kilo is the smallest real non-Codex runtime whose finishInstall still
// writes: plan.finishPermissionWriter === 'kilo' makes it call
// configureKiloPermissions unconditionally (that writer, unlike OpenCode's,
// is NOT GSD_TEST_MODE-gated), ending in an unguarded
// is NOT MSD_TEST_MODE-gated), ending in an unguarded
// fs.writeFileSync(<configDir>/kilo.json). Cline can't stand in here — its
// plan is writesSharedSettings:false + finishPermissionWriter:null, so its
// finishInstall performs no write at all and has no non-entrypoint failure
@@ -545,7 +545,7 @@ test('a NON-entrypoint finalize failure leaves an already-successful Codex insta
// Kilo's throws, so the reversed rollback loop does reach Codex's entry —
// but with a non-entrypoint error it must take the installer-migrations-only
// closure, not restoreCodexSnapshot. A configured-entrypoint validation
// failure is the only trigger docs/how-to/update-gsd.md documents for
// failure is the only trigger docs/how-to/update-msd.md documents for
// reverting a runtime install that otherwise succeeded; un-installing (on
// update, downgrading) Codex because an unrelated runtime hit EACCES would
// contradict the "Done!" the user has already been shown.