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

@@ -23,7 +23,7 @@ const { INSTALL_TIMEOUT_MS } = require('./helpers/timeouts.cjs');
const COLD_REQUIRE_PROBE_TIMEOUT_MS = 30000;
describe('#2665: the built-lib require is deferred', () => {
// The scrub set derives from gsd-core/bin/lib, which is BUILT. Requiring it at
// The scrub set derives from msd-core/bin/lib, which is BUILT. Requiring it at
// module scope made an unbuilt tree throw inside `require('./helpers.cjs')` —
// before any test() registered — so one missing `npm run build:lib` became a
// whole-suite crash in the file ~370 test files import. A cold child is the only
@@ -33,7 +33,7 @@ describe('#2665: the built-lib require is deferred', () => {
"const path = require('node:path');",
`require(${JSON.stringify(path.join(__dirname, 'helpers.cjs'))});`,
touch,
"const needle = path.join('gsd-core', 'bin', 'lib', 'capability-registry.cjs');",
"const needle = path.join('msd-core', 'bin', 'lib', 'capability-registry.cjs');",
'process.stdout.write(String(Object.keys(require.cache).some((m) => m.endsWith(needle))));',
].join('\n');
// Bounded per local/no-unbounded-spawn (#3143): a cold require is sub-second, so
@@ -57,19 +57,19 @@ describe('withIsolatedProcessState', () => {
test('restores env, cwd, and exitCode after callback', () => {
const originalCwd = process.cwd();
const originalExitCode = process.exitCode;
const originalMarker = process.env.GSD_TEST_ISOLATION_MARKER;
const originalMarker = process.env.MSD_TEST_ISOLATION_MARKER;
const tempCwd = path.dirname(originalCwd);
withIsolatedProcessState(() => {
process.env.GSD_TEST_ISOLATION_MARKER = 'changed';
process.env.MSD_TEST_ISOLATION_MARKER = 'changed';
process.exitCode = 73;
process.chdir(tempCwd);
});
assert.strictEqual(process.cwd(), originalCwd);
assert.strictEqual(process.exitCode, originalExitCode);
assert.strictEqual(process.env.GSD_TEST_ISOLATION_MARKER, originalMarker);
assert.strictEqual(process.env.MSD_TEST_ISOLATION_MARKER, originalMarker);
});
test('restores state even when callback throws', () => {
@@ -99,15 +99,15 @@ describe('withIsolatedProcessState', () => {
// SCOPE BOUNDARY — read this before trusting a green run here.
//
// Every test below asserts that TEST_ENV_BASE covers some ENUMERATION (the
// capability registry, the non-registry descriptor set, GSD's own location
// capability registry, the non-registry descriptor set, MSD's own location
// keys). Each therefore proves only that the scrub set is not narrower than the
// enumeration it derives from. NONE of them can prove the enumeration is itself
// complete: a config-location var that no enumeration carries is invisible to
// all of them, and they stay green.
//
// That is not hypothetical — it is how round 2 found GSD_HOME and
// KIMI_SHARE_DIR while this block was fully green. GSD_HOME belonged to no
// enumeration at all (it is GSD's own store root, not a runtime configHome);
// That is not hypothetical — it is how round 2 found MSD_HOME and
// KIMI_SHARE_DIR while this block was fully green. MSD_HOME belonged to no
// enumeration at all (it is MSD's own store root, not a runtime configHome);
// KIMI_SHARE_DIR sat inside a function body where nothing could enumerate it.
// Round 3's fix was to make both enumerable rather than to add two assertions,
// precisely because an assertion added per reviewer-named var is the
@@ -120,7 +120,7 @@ describe('withIsolatedProcessState', () => {
// here, and this block should not be read as standing in for them.
describe('#2665: TEST_ENV_BASE config-location coverage', () => {
test('every runtime configHome env var in the registry is scrubbed', () => {
const { runtimes } = require('../gsd-core/bin/lib/capability-registry.cjs');
const { runtimes } = require('../msd-core/bin/lib/capability-registry.cjs');
const declared = [
...new Set(
@@ -159,11 +159,11 @@ describe('#2665: TEST_ENV_BASE config-location coverage', () => {
test('the non-registry config-location vars are covered too', () => {
// These have no capability descriptor, so the registry derivation alone
// cannot reach them: GROK_AGENTS_HOME is a hardcoded branch of
// getGlobalConfigDir, GSD_RUNTIME selects which runtime home resolves, and
// GSD_PROJECT / GSD_WORKSTREAM move a child's .planning root
// getGlobalConfigDir, MSD_RUNTIME selects which runtime home resolves, and
// MSD_PROJECT / MSD_WORKSTREAM move a child's .planning root
// (src/planning-workspace.cts). Named explicitly so deleting one from the
// helper is a test failure rather than a silent narrowing.
for (const key of ['GROK_AGENTS_HOME', 'GSD_RUNTIME', 'GSD_PROJECT', 'GSD_WORKSTREAM']) {
for (const key of ['GROK_AGENTS_HOME', 'MSD_RUNTIME', 'MSD_PROJECT', 'MSD_WORKSTREAM']) {
assert.strictEqual(TEST_ENV_BASE[key], '', `${key} must be scrubbed`);
}
});
@@ -171,11 +171,11 @@ describe('#2665: TEST_ENV_BASE config-location coverage', () => {
test('descriptor-shaped config homes OUTSIDE the registry are derived, not listed', () => {
const {
NON_REGISTRY_CONFIG_HOME_DESCRIPTORS,
} = require('../gsd-core/bin/lib/runtime-homes.cjs');
} = require('../msd-core/bin/lib/runtime-homes.cjs');
// Round 3. kimi owns TWO config homes: KIMI_CONFIG_DIR (registry-visible) and
// KIMI_SHARE_DIR (a hardcoded descriptor inside resolveKimiHooksTomlDir, which
// decides where its native config.toml — carrying GSD's [[hooks]] block — is
// decides where its native config.toml — carrying MSD's [[hooks]] block — is
// written). The registry-only derivation reached the first and not the second,
// so it looked structurally complete while missing a live write surface.
const declared = [
@@ -207,10 +207,10 @@ describe('#2665: TEST_ENV_BASE config-location coverage', () => {
// env: [] — so this asserts the DERIVATION reaches the field, not that any
// var currently flows from it: every skillsHome-declared var (registry and
// non-registry alike) must land in TEST_ENV_BASE the moment one exists.
const { runtimes } = require('../gsd-core/bin/lib/capability-registry.cjs');
const { runtimes } = require('../msd-core/bin/lib/capability-registry.cjs');
const {
NON_REGISTRY_CONFIG_HOME_DESCRIPTORS,
} = require('../gsd-core/bin/lib/runtime-homes.cjs');
} = require('../msd-core/bin/lib/runtime-homes.cjs');
const declared = [
...new Set([
@@ -242,25 +242,25 @@ describe('#2665: TEST_ENV_BASE config-location coverage', () => {
);
});
test("GSD's OWN location vars are scrubbed (a second family, not a registry gap)", () => {
const { GSD_LOCATION_ENV_KEYS } = require('../gsd-core/bin/lib/runtime-homes.cjs');
test("MSD's OWN location vars are scrubbed (a second family, not a registry gap)", () => {
const { MSD_LOCATION_ENV_KEYS } = require('../msd-core/bin/lib/runtime-homes.cjs');
// GSD_HOME decides where GSD keeps user-owned state ($GSD_HOME/.gsd/ —
// MSD_HOME decides where MSD keeps user-owned state ($MSD_HOME/.msd/ —
// consent.json, defaults.json, capability overlays) and is read env-FIRST,
// ahead of os.homedir(), across capability-loader / capability-consent /
// capability-state / capability-writer / config-loader / install-profiles /
// bin/install.js. GSD_AGENTS_DIR is priority 1 in getAgentsDir. Neither is a
// bin/install.js. MSD_AGENTS_DIR is priority 1 in getAgentsDir. Neither is a
// runtime configHome, so no amount of registry derivation reaches them.
assert.ok(GSD_LOCATION_ENV_KEYS.includes('GSD_HOME'));
for (const key of GSD_LOCATION_ENV_KEYS) {
assert.ok(MSD_LOCATION_ENV_KEYS.includes('MSD_HOME'));
for (const key of MSD_LOCATION_ENV_KEYS) {
assert.strictEqual(TEST_ENV_BASE[key], '', `${key} must be scrubbed`);
}
});
test('write-escape PERMISSIONS are scrubbed (a fifth family — not a location var)', () => {
// #2665 round 5. GSD_ALLOW_SYMLINKED_DEST names no path, so every rung of the
// #2665 round 5. MSD_ALLOW_SYMLINKED_DEST names no path, so every rung of the
// derivation above is structurally incapable of reaching it — it is not a
// registry configHome, not descriptor-shaped, not one of GSD's own location
// registry configHome, not descriptor-shaped, not one of MSD's own location
// vars. It is still a #2665 leak vector: install-engine.cts reads it env-first
// and threads it into the symlink-escape guard that stops a write leaving the
// install root, so an ambient `=1` disarms that guard for the whole suite.
@@ -271,13 +271,13 @@ describe('#2665: TEST_ENV_BASE config-location coverage', () => {
// failure this suite already documents, and the one that let the kimi-code
// descriptor go unwatched. Naming it is what makes removal fail loudly.
assert.strictEqual(
TEST_ENV_BASE.GSD_ALLOW_SYMLINKED_DEST,
TEST_ENV_BASE.MSD_ALLOW_SYMLINKED_DEST,
'',
'GSD_ALLOW_SYMLINKED_DEST must be blanked: ambient =1 disarms the symlink-escape guard',
'MSD_ALLOW_SYMLINKED_DEST must be blanked: ambient =1 disarms the symlink-escape guard',
);
// Blanking must be fail-SAFE — '' is neither '1' nor 'true', so the guard gets
// stricter, never looser. This is what licenses scrubbing it wholesale.
assert.ok(!['1', 'true'].includes(TEST_ENV_BASE.GSD_ALLOW_SYMLINKED_DEST));
assert.ok(!['1', 'true'].includes(TEST_ENV_BASE.MSD_ALLOW_SYMLINKED_DEST));
});
test('scrubConfigLocationEnv clears and restores the parent process env', () => {
@@ -313,8 +313,8 @@ describe('#2665 round 4: the skillsHome walk is reversion-sensitive', () => {
// 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 regPath = require.resolve('../msd-core/bin/lib/capability-registry.cjs');
const rhPath = require.resolve('../msd-core/bin/lib/runtime-homes.cjs');
const helpersPath = require.resolve('./helpers.cjs');
const script = `
@@ -330,15 +330,15 @@ describe('#2665 round 4: the skillsHome walk is reversion-sensitive', () => {
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'];
declaring.runtime.configHome.skillsHome.env = ['MSD_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'],
kind: 'dot-home', name: '.x', env: ['MSD_TEST_SENTINEL_NONREG_SKILLS'],
};
const { TEST_ENV_BASE } = require(${JSON.stringify(helpersPath)});
const missing = [
'GSD_TEST_SENTINEL_REGISTRY_SKILLS',
'GSD_TEST_SENTINEL_NONREG_SKILLS',
'MSD_TEST_SENTINEL_REGISTRY_SKILLS',
'MSD_TEST_SENTINEL_NONREG_SKILLS',
].filter((k) => TEST_ENV_BASE[k] !== '');
if (missing.length > 0) {
console.error('skillsHome walk missed: ' + missing.join(', '));
@@ -381,13 +381,13 @@ describe('#3156: a raw installer spawn cannot write into the ambient HOME', () =
// default home while HOME was the caller's, and on a passwd-less host the
// test-home guard compares the two and refuses a legitimately sandboxed
// spawn. Asserting HOME alone did not catch it — the marker has to move too.
assert.strictEqual(build().GSD_TEST_HOME_SANDBOX, build().HOME,
assert.strictEqual(build().MSD_TEST_HOME_SANDBOX, build().HOME,
'the marker must name the default sandbox home');
const overridden = build({ HOME: '/explicit', USERPROFILE: '/explicit' });
assert.strictEqual(overridden.GSD_TEST_HOME_SANDBOX, '/explicit',
assert.strictEqual(overridden.MSD_TEST_HOME_SANDBOX, '/explicit',
'the marker must follow an overridden HOME, not keep naming the default one');
assert.strictEqual(
build({ HOME: '/explicit', GSD_TEST_HOME_SANDBOX: '/caller-chosen' }).GSD_TEST_HOME_SANDBOX,
build({ HOME: '/explicit', MSD_TEST_HOME_SANDBOX: '/caller-chosen' }).MSD_TEST_HOME_SANDBOX,
'/caller-chosen',
'an explicitly supplied marker still wins over the derived one');
}
@@ -396,16 +396,16 @@ describe('#3156: a raw installer spawn cannot write into the ambient HOME', () =
// Behavioural half — the one that actually fails pre-fix.
//
// bin/install.js writeNonClaudeDefaults() (#2834) writes
// <os.homedir()>/.gsd/defaults.json for every NON-Claude runtime, reading no
// GSD variable at all. So this is deliberately driven through the real
// <os.homedir()>/.msd/defaults.json for every NON-Claude runtime, reading no
// MSD variable at all. So this is deliberately driven through the real
// installer against a real ambient HOME: no assertion about the scrub set can
// stand in for it, because no scrub set can reach os.homedir().
//
// Negative control: revert installerEnv() to `{ ...process.env, ...overrides }`
// and the canary gains .gsd/defaults.json.
// and the canary gains .msd/defaults.json.
test('installing a non-Claude runtime leaves the ambient HOME untouched', () => {
const canaryHome = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-3156-canary-home-'));
const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-3156-project-'));
const canaryHome = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-3156-canary-home-'));
const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-3156-project-'));
const realHome = process.env.HOME;
const realUserProfile = process.env.USERPROFILE;
try {
@@ -422,10 +422,10 @@ describe('#3156: a raw installer spawn cannot write into the ambient HOME', () =
timeout: INSTALL_TIMEOUT_MS,
});
assert.ok(!fs.existsSync(path.join(canaryHome, '.gsd')),
`the installer wrote GSD's user store into the ambient HOME: ${
fs.existsSync(path.join(canaryHome, '.gsd'))
? fs.readdirSync(path.join(canaryHome, '.gsd')).join(', ')
assert.ok(!fs.existsSync(path.join(canaryHome, '.msd')),
`the installer wrote MSD's user store into the ambient HOME: ${
fs.existsSync(path.join(canaryHome, '.msd'))
? fs.readdirSync(path.join(canaryHome, '.msd')).join(', ')
: ''
}`);
} finally {
@@ -454,37 +454,37 @@ describe('#3712: a raw installer spawn cannot reach the ambient HOME\'s shared s
*/
const INSTALL_GLOBAL_TIMEOUT_MS = INSTALL_TIMEOUT_MS * 2.5;
// #3156's canary asserts on <canaryHome>/.gsd. That is not the only ambient-HOME
// #3156's canary asserts on <canaryHome>/.msd. That is not the only ambient-HOME
// surface: a kind may declare a global `home` override resolved from os.homedir()
// — codex's skills kind (`.agents`) — and the installer PRUNES gsd-* entries under
// it. A 71-skill deletion there passed the .gsd-only canary unnoticed (#3712).
// — codex's skills kind (`.agents`) — and the installer PRUNES msd-* entries under
// it. A 71-skill deletion there passed the .msd-only canary unnoticed (#3712).
//
// The runtime choice is load-bearing, not incidental. The .gsd row spawns
// The runtime choice is load-bearing, not incidental. The .msd row spawns
// `--cursor --local`, and cursor declares no home override, so an `.agents`
// assertion on THAT spawn passes even with all confinement removed. Only a
// runtime that actually carries the override can discriminate — today that is
// codex at global scope, asserted below so a descriptor change fails here loudly.
test('installing codex globally leaves the ambient HOME\'s .agents/skills sampled inventory unchanged', () => {
const { runtimes } = require('../gsd-core/bin/lib/capability-registry.cjs');
const { runtimes } = require('../msd-core/bin/lib/capability-registry.cjs');
const codexGlobalSkills = (runtimes?.codex?.runtime?.artifactLayout?.global ?? [])
.find((e) => e.kind === 'skills' && e.home);
assert.ok(codexGlobalSkills,
'codex global skills must still declare a `home` override — without it this row '
+ 'is non-discriminating and must be re-pointed at whichever runtime carries one');
const canaryHome = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-3712-canary-home-'));
const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-3712-project-'));
const canaryHome = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-3712-canary-home-'));
const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-3712-project-'));
const realHome = process.env.HOME;
const realUserProfile = process.env.USERPROFILE;
const skillsRoot = path.join(canaryHome, '.agents', 'skills');
fs.mkdirSync(skillsRoot, { recursive: true });
for (const name of ['gsd-plan-phase', 'gsd-dev-preferences', 'cloudflare']) {
for (const name of ['msd-plan-phase', 'msd-dev-preferences', 'cloudflare']) {
fs.mkdirSync(path.join(skillsRoot, name), { recursive: true });
fs.writeFileSync(path.join(skillsRoot, name, 'SKILL.md'), `# ${name}\n`);
}
// A SAMPLE, not a byte-for-byte tree compare: immediate dir names plus each
// dir's SKILL.md. It catches the demonstrated regression (whole gsd-* dirs
// dir's SKILL.md. It catches the demonstrated regression (whole msd-* dirs
// pruned) and would miss nested-file, mode, or metadata mutations.
const inventory = () => fs.readdirSync(skillsRoot).sort()
.map((d) => `${d}:${fs.readFileSync(path.join(skillsRoot, d, 'SKILL.md'), 'utf-8')}`)
@@ -505,7 +505,7 @@ describe('#3712: a raw installer spawn cannot reach the ambient HOME\'s shared s
});
assert.strictEqual(inventory(), before,
'the installer pruned or wrote GSD skills in the ambient HOME instead of its own sandbox');
'the installer pruned or wrote MSD skills in the ambient HOME instead of its own sandbox');
} finally {
if (realHome === undefined) delete process.env.HOME; else process.env.HOME = realHome;
if (realUserProfile === undefined) delete process.env.USERPROFILE;