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

@@ -4,7 +4,7 @@
/**
* Regression coverage for #2329: OpenCode install target writes slash
* commands to `command/` (singular); OpenCode discovers them from
* `commands/` (plural), so none of the ~71 `/gsd-*` commands appear in the
* `commands/` (plural), so none of the ~71 `/msd-*` commands appear in the
* OpenCode TUI.
*
* Per OpenCode's own docs (opencode.ai/docs/commands/), the documented
@@ -12,9 +12,9 @@
* `~/.config/opencode/commands/`, per-project `.opencode/commands/`).
* OpenCode ALSO accepts singular names for backwards compatibility per its
* config docs, but the reporter empirically confirmed on OpenCode 1.17.13
* that `command/` (what GSD currently writes) is NOT discovered and that
* `mv command commands` fixes it. These tests assert only what GSD
* controls: where GSD writes its command files.
* that `command/` (what MSD currently writes) is NOT discovered and that
* `mv command commands` fixes it. These tests assert only what MSD
* controls: where MSD writes its command files.
*
* Four sites must agree (Generative Fix Divergence guard, repo rule):
* - capabilities/opencode/capability.json:28 (global artifactLayout commands.destSubpath)
@@ -46,7 +46,7 @@ const { INSTALL_TIMEOUT_MS } = require('./helpers/timeouts.cjs');
const { cleanup } = require('./helpers.cjs');
const {
resolveRuntimeArtifactLayout,
} = require('../gsd-core/bin/lib/runtime-artifact-layout.cjs');
} = require('../msd-core/bin/lib/runtime-artifact-layout.cjs');
const CAPABILITY_PATH = path.join(__dirname, '..', 'capabilities', 'opencode', 'capability.json');
const EXPECTED_COMMAND_DIR = 'commands';
@@ -76,9 +76,9 @@ function reinstallOpencode(root, configDir = null, scope = 'global') {
return { status: r.exitCode, stdout: r.stdout, stderr: r.stderr };
}
function gsdMdFiles(dir) {
function msdMdFiles(dir) {
if (!fs.existsSync(dir)) return [];
return fs.readdirSync(dir).filter((f) => f.startsWith('gsd-') && f.endsWith('.md'));
return fs.readdirSync(dir).filter((f) => f.startsWith('msd-') && f.endsWith('.md'));
}
/**
@@ -95,7 +95,7 @@ function gsdMdFiles(dir) {
*
* The migration under test (_migrateLegacyOpencodeCommandDir in
* src/install-engine.cts) only deletes a command/<file> entry when
* classifyArtifact() proves it GSD-managed via gsd-file-manifest.json (key
* classifyArtifact() proves it MSD-managed via msd-file-manifest.json (key
* `command/<file>` present, hash matches or was locally modified — see
* installerMigrations.classifyArtifact). A legacyDir populated with files but
* no matching manifest entries would classify as 'unknown' and never be
@@ -104,7 +104,7 @@ function gsdMdFiles(dir) {
* (matching the OLD writeManifest's opencodeCommandDir-prefix behavior)
* alongside physically moving the files, so the fabricated state is exactly
* what a pre-fix install would have left: files AND a manifest that proves
* GSD manages them at the legacy path.
* MSD manages them at the legacy path.
*
* @param {string} configDir
* @param {object} [opts]
@@ -118,13 +118,13 @@ function fabricateLegacyOpencodeCommandDir(configDir, opts = {}) {
const { keepPluralDir = false } = opts;
const legacyDir = path.join(configDir, 'command');
const pluralDir = path.join(configDir, 'commands');
const manifestPath = path.join(configDir, 'gsd-file-manifest.json');
const manifestPath = path.join(configDir, 'msd-file-manifest.json');
const movedFiles = gsdMdFiles(pluralDir);
const movedFiles = msdMdFiles(pluralDir);
assert.ok(
movedFiles.length >= 60,
`fabricateLegacyOpencodeCommandDir: expected a fresh install to have ` +
`populated >=60 gsd-*.md files under ${pluralDir} before fabrication, got ${movedFiles.length}`
`populated >=60 msd-*.md files under ${pluralDir} before fabrication, got ${movedFiles.length}`
);
fs.mkdirSync(legacyDir, { recursive: true });
@@ -166,15 +166,15 @@ describe('#2329: opencode install writes commands to commands/ (plural), not com
const pluralDir = path.join(configDir, 'commands');
const singularDir = path.join(configDir, 'command');
const pluralFiles = gsdMdFiles(pluralDir);
const pluralFiles = msdMdFiles(pluralDir);
assert.ok(
pluralFiles.length >= 60,
`expected >=60 gsd-*.md command files under ${pluralDir}, got ${pluralFiles.length}. ` +
`expected >=60 msd-*.md command files under ${pluralDir}, got ${pluralFiles.length}. ` +
`OpenCode discovers commands from commands/ (plural) per opencode.ai/docs/commands/.`
);
assert.ok(
pluralFiles.includes('gsd-help.md'),
`gsd-help.md must exist under ${pluralDir}`
pluralFiles.includes('msd-help.md'),
`msd-help.md must exist under ${pluralDir}`
);
assert.ok(
@@ -288,11 +288,11 @@ describe('#2329: opencode command-dir declarations are a single source of truth'
// ---------------------------------------------------------------------------
describe('#2329: upgrading an install with an orphaned command/ dir migrates it to commands/ safely', () => {
test('reinstall relocates all gsd-owned files from command/ into commands/ and removes the now-empty orphan', (t) => {
test('reinstall relocates all msd-owned files from command/ into commands/ and removes the now-empty orphan', (t) => {
// Under the FIXED source, a first install writes straight into commands/
// (plural) — that's the fix working. To exercise the upgrade/migration
// path, fabricate the pre-fix "legacy" starting state a real upgrading
// user has (populated command/ dir + a manifest that proves GSD manages
// user has (populated command/ dir + a manifest that proves MSD manages
// those files at the legacy path) by hand-rewriting a fresh install's
// output — see fabricateLegacyOpencodeCommandDir's doc comment.
const { configDir, root } = runMinimalInstall({ runtime: 'opencode', scope: 'global' });
@@ -303,11 +303,11 @@ describe('#2329: upgrading an install with an orphaned command/ dir migrates it
const { movedFiles } = fabricateLegacyOpencodeCommandDir(configDir);
const filesBefore = new Set(movedFiles);
assert.ok(filesBefore.size >= 60, `sanity: expected >=60 gsd command files from the first install, got ${filesBefore.size}`);
assert.ok(filesBefore.size >= 60, `sanity: expected >=60 msd command files from the first install, got ${filesBefore.size}`);
// Sanity: the migration must genuinely FIRE against this fixture, not
// no-op — confirm the legacy dir is populated and commands/ is gone
// before the reinstall runs.
assert.ok(gsdMdFiles(legacyDir).length >= 60, 'sanity: legacyDir must be populated before reinstall');
assert.ok(msdMdFiles(legacyDir).length >= 60, 'sanity: legacyDir must be populated before reinstall');
assert.ok(!fs.existsSync(pluralDir), 'sanity: pluralDir must not exist before reinstall (fabricated pre-fix state)');
const result = reinstallOpencode(root, configDir, 'global');
@@ -316,16 +316,16 @@ describe('#2329: upgrading an install with an orphaned command/ dir migrates it
`reinstall (upgrade) must exit 0\nstdout: ${result.stdout}\nstderr: ${result.stderr}`
);
const filesAfter = new Set(gsdMdFiles(pluralDir));
const filesAfter = new Set(msdMdFiles(pluralDir));
assert.deepStrictEqual(
[...filesAfter].sort(), [...filesBefore].sort(),
'after the upgrade reinstall, commands/ must contain the exact same gsd-* command file set ' +
'after the upgrade reinstall, commands/ must contain the exact same msd-* command file set ' +
'that was previously under command/'
);
assert.ok(
!fs.existsSync(legacyDir),
'the orphaned command/ dir must be removed once fully migrated — it held only GSD-owned files ' +
'the orphaned command/ dir must be removed once fully migrated — it held only MSD-owned files ' +
'(all present, unmodified, in the manifest), so removing it is safe and expected'
);
});
@@ -339,10 +339,10 @@ describe('#2329: upgrading an install with an orphaned command/ dir migrates it
fabricateLegacyOpencodeCommandDir(configDir);
// Sanity: the migration must genuinely fire against this fixture.
assert.ok(gsdMdFiles(legacyDir).length >= 60, 'sanity: legacyDir must be populated before reinstall');
assert.ok(msdMdFiles(legacyDir).length >= 60, 'sanity: legacyDir must be populated before reinstall');
assert.ok(!fs.existsSync(pluralDir), 'sanity: pluralDir must not exist before reinstall (fabricated pre-fix state)');
const userContent = 'precious user notes — not a GSD-managed file\n';
const userContent = 'precious user notes — not a MSD-managed file\n';
const userFileLegacy = path.join(legacyDir, 'my-notes.md');
fs.writeFileSync(userFileLegacy, userContent, 'utf8');
@@ -355,15 +355,15 @@ describe('#2329: upgrading an install with an orphaned command/ dir migrates it
// The migration must actually have happened (commands/ now populated) —
// otherwise "the user file is still where it was" would be a vacuous pass.
assert.ok(
gsdMdFiles(pluralDir).length >= 60,
`commands/ must contain the migrated gsd-* command set after the upgrade, got ` +
`${gsdMdFiles(pluralDir).length}`
msdMdFiles(pluralDir).length >= 60,
`commands/ must contain the migrated msd-* command set after the upgrade, got ` +
`${msdMdFiles(pluralDir).length}`
);
// The unrelated file is not a GSD-managed artifact (no manifest entry —
// it never matched the "gsd-*.md" filter GSD tracks), so it must never
// The unrelated file is not a MSD-managed artifact (no manifest entry —
// it never matched the "msd-*.md" filter MSD tracks), so it must never
// be silently deleted. It may legitimately end up EITHER left in place
// in the (now GSD-file-free) command/ dir, OR carried over into
// in the (now MSD-file-free) command/ dir, OR carried over into
// commands/ alongside the migrated files — either is safe; deletion is
// not.
const userFilePlural = path.join(pluralDir, 'my-notes.md');
@@ -392,19 +392,19 @@ describe('#2329: upgrading an install with an orphaned command/ dir migrates it
// Simulate a commands/ dir that already independently exists (e.g. the
// user manually created it while working around #2329, or a partial
// prior migration attempt left it behind) with content GSD does not own.
// prior migration attempt left it behind) with content MSD does not own.
fs.mkdirSync(pluralDir, { recursive: true });
const preexistingPath = path.join(pluralDir, 'unrelated-project-doc.md');
const preexistingContent = 'unrelated content that already lived in commands/\n';
fs.writeFileSync(preexistingPath, preexistingContent, 'utf8');
const filesBefore = new Set(gsdMdFiles(legacyDir));
assert.ok(filesBefore.size >= 60, `sanity: expected >=60 gsd command files in command/, got ${filesBefore.size}`);
const filesBefore = new Set(msdMdFiles(legacyDir));
assert.ok(filesBefore.size >= 60, `sanity: expected >=60 msd command files in command/, got ${filesBefore.size}`);
// Sanity: the migration must genuinely fire against this fixture — the
// manifest must actually prove ownership of the legacy files (not just
// their physical presence), otherwise classifyArtifact would treat them
// as 'unknown' and the migration would silently no-op.
const manifestBefore = JSON.parse(fs.readFileSync(path.join(configDir, 'gsd-file-manifest.json'), 'utf8'));
const manifestBefore = JSON.parse(fs.readFileSync(path.join(configDir, 'msd-file-manifest.json'), 'utf8'));
const legacyManifestKeys = Object.keys(manifestBefore.files).filter((k) => k.startsWith('command/'));
assert.ok(
legacyManifestKeys.length >= 60,
@@ -427,8 +427,8 @@ describe('#2329: upgrading an install with an orphaned command/ dir migrates it
'pre-existing unrelated file content in commands/ must be untouched'
);
// All gsd command files must now be present in commands/ too.
const filesAfter = new Set(gsdMdFiles(pluralDir));
// All msd command files must now be present in commands/ too.
const filesAfter = new Set(msdMdFiles(pluralDir));
for (const f of filesBefore) {
assert.ok(filesAfter.has(f), `${f} must be present in commands/ after the upgrade (was in command/ before)`);
}
@@ -454,9 +454,9 @@ describe('#2329: the fix must not affect other runtimes\' command output directo
const pluralDir = path.join(configDir, 'commands');
assert.ok(
gsdMdFiles(singularDir).length >= 60,
msdMdFiles(singularDir).length >= 60,
`kilo must still write its command files to the singular command/ dir, got ` +
`${gsdMdFiles(singularDir).length} files under ${singularDir}`
`${msdMdFiles(singularDir).length} files under ${singularDir}`
);
assert.ok(
!fs.existsSync(pluralDir),