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:
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user