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

@@ -1,9 +1,9 @@
/**
* GSD Tools Tests - docs-update
* MSD Tools Tests - docs-update
*
* Integration tests for the docs-init gsd-tools subcommand.
* Integration tests for the docs-init msd-tools subcommand.
* Covers: JSON output shape, project type detection, existing doc scanning,
* GSD marker detection, and doc tooling detection.
* MSD marker detection, and doc tooling detection.
*
* Requirements: VERF-03
*/
@@ -12,9 +12,9 @@ const { test, describe, beforeEach, afterEach } = require('node:test');
const assert = require('node:assert/strict');
const fs = require('fs');
const path = require('path');
const { runGsdTools, createTempProject, cleanup } = require('./helpers.cjs');
const { runMsdTools, createTempProject, cleanup } = require('./helpers.cjs');
const MODEL_PROFILES = require('../gsd-core/bin/lib/model-profiles.cjs').MODEL_PROFILES;
const MODEL_PROFILES = require('../msd-core/bin/lib/model-profiles.cjs').MODEL_PROFILES;
const EXPECTED_AGENTS = Object.keys(MODEL_PROFILES);
function createCompleteCodexAgents(projectRoot) {
@@ -27,7 +27,7 @@ function createCompleteCodexAgents(projectRoot) {
files[`agents/${name}.md`] = {};
files[`agents/${name}.toml`] = {};
}
fs.writeFileSync(path.join(projectRoot, '.codex', 'gsd-file-manifest.json'), JSON.stringify({ files }));
fs.writeFileSync(path.join(projectRoot, '.codex', 'msd-file-manifest.json'), JSON.stringify({ files }));
}
// ─── JSON output shape ────────────────────────────────────────────────────────
@@ -44,7 +44,7 @@ describe('docs-init command', () => {
});
test('returns expected JSON shape', () => {
const result = runGsdTools(['docs-init'], tmpDir);
const result = runMsdTools(['docs-init'], tmpDir);
assert.ok(result.success, `Command failed: ${result.error}`);
const data = JSON.parse(result.output);
@@ -83,7 +83,7 @@ describe('docs-init command', () => {
});
test('bare project returns all false signals', () => {
const result = runGsdTools(['docs-init'], tmpDir);
const result = runMsdTools(['docs-init'], tmpDir);
assert.ok(result.success, `Command failed: ${result.error}`);
const data = JSON.parse(result.output);
@@ -128,7 +128,7 @@ describe('docs-init Codex project-local agent status', () => {
test('reports a complete local Codex installation instead of a global fixture', () => {
createCompleteCodexAgents(tmpDir);
const result = runGsdTools('docs-init --raw', tmpDir, { CODEX_HOME: globalHome });
const result = runMsdTools('docs-init --raw', tmpDir, { CODEX_HOME: globalHome });
assert.ok(result.success, `docs-init failed: ${result.error}`);
const output = JSON.parse(result.output);
@@ -139,9 +139,9 @@ describe('docs-init Codex project-local agent status', () => {
test('reports an empty local Codex directory as unhealthy even with global agents', () => {
fs.mkdirSync(path.join(tmpDir, '.codex', 'agents'), { recursive: true });
fs.writeFileSync(path.join(tmpDir, '.codex', 'gsd-file-manifest.json'), JSON.stringify({ files: {} }));
fs.writeFileSync(path.join(tmpDir, '.codex', 'msd-file-manifest.json'), JSON.stringify({ files: {} }));
const result = runGsdTools('docs-init --raw', tmpDir, { CODEX_HOME: globalHome });
const result = runMsdTools('docs-init --raw', tmpDir, { CODEX_HOME: globalHome });
assert.ok(result.success, `docs-init failed: ${result.error}`);
const output = JSON.parse(result.output);
@@ -175,7 +175,7 @@ describe('docs-init response_language wiring (#2402)', () => {
JSON.stringify({ response_language: 'Japanese' })
);
const result = runGsdTools(['docs-init'], tmpDir);
const result = runMsdTools(['docs-init'], tmpDir);
assert.ok(result.success, `Command failed: ${result.error}`);
const data = JSON.parse(result.output);
@@ -183,7 +183,7 @@ describe('docs-init response_language wiring (#2402)', () => {
});
test('output omits response_language when not configured', () => {
const result = runGsdTools(['docs-init'], tmpDir);
const result = runMsdTools(['docs-init'], tmpDir);
assert.ok(result.success, `Command failed: ${result.error}`);
const data = JSON.parse(result.output);
@@ -211,7 +211,7 @@ describe('project type detection', () => {
'utf-8'
);
const result = runGsdTools(['docs-init'], tmpDir);
const result = runMsdTools(['docs-init'], tmpDir);
assert.ok(result.success, `Command failed: ${result.error}`);
const data = JSON.parse(result.output);
@@ -222,7 +222,7 @@ describe('project type detection', () => {
test('detects open source from LICENSE file', () => {
fs.writeFileSync(path.join(tmpDir, 'LICENSE'), 'MIT License', 'utf-8');
const result = runGsdTools(['docs-init'], tmpDir);
const result = runMsdTools(['docs-init'], tmpDir);
assert.ok(result.success, `Command failed: ${result.error}`);
const data = JSON.parse(result.output);
@@ -236,7 +236,7 @@ describe('project type detection', () => {
'utf-8'
);
const result = runGsdTools(['docs-init'], tmpDir);
const result = runMsdTools(['docs-init'], tmpDir);
assert.ok(result.success, `Command failed: ${result.error}`);
const data = JSON.parse(result.output);
@@ -247,7 +247,7 @@ describe('project type detection', () => {
test('detects tests from tests directory', () => {
fs.mkdirSync(path.join(tmpDir, 'tests'), { recursive: true });
const result = runGsdTools(['docs-init'], tmpDir);
const result = runMsdTools(['docs-init'], tmpDir);
assert.ok(result.success, `Command failed: ${result.error}`);
const data = JSON.parse(result.output);
@@ -257,7 +257,7 @@ describe('project type detection', () => {
test('detects deploy config from Dockerfile', () => {
fs.writeFileSync(path.join(tmpDir, 'Dockerfile'), 'FROM node:20', 'utf-8');
const result = runGsdTools(['docs-init'], tmpDir);
const result = runMsdTools(['docs-init'], tmpDir);
assert.ok(result.success, `Command failed: ${result.error}`);
const data = JSON.parse(result.output);
@@ -267,7 +267,7 @@ describe('project type detection', () => {
test('detects API routes from src/app/api directory', () => {
fs.mkdirSync(path.join(tmpDir, 'src', 'app', 'api'), { recursive: true });
const result = runGsdTools(['docs-init'], tmpDir);
const result = runMsdTools(['docs-init'], tmpDir);
assert.ok(result.success, `Command failed: ${result.error}`);
const data = JSON.parse(result.output);
@@ -292,7 +292,7 @@ describe('existing doc scanning', () => {
fs.writeFileSync(path.join(tmpDir, 'README.md'), '# README\n', 'utf-8');
fs.writeFileSync(path.join(tmpDir, 'ARCHITECTURE.md'), '# Architecture\n', 'utf-8');
const result = runGsdTools(['docs-init'], tmpDir);
const result = runMsdTools(['docs-init'], tmpDir);
assert.ok(result.success, `Command failed: ${result.error}`);
const data = JSON.parse(result.output);
@@ -303,26 +303,26 @@ describe('existing doc scanning', () => {
assert.ok(paths.includes('ARCHITECTURE.md'), 'existing_docs should contain ARCHITECTURE.md');
});
test('detects GSD marker in existing docs', () => {
test('detects MSD marker in existing docs', () => {
fs.writeFileSync(
path.join(tmpDir, 'README.md'),
'<!-- generated-by: gsd-doc-writer -->\n# README\n',
'<!-- generated-by: msd-doc-writer -->\n# README\n',
'utf-8'
);
fs.writeFileSync(path.join(tmpDir, 'NOTES.md'), '# Notes\n', 'utf-8');
const result = runGsdTools(['docs-init'], tmpDir);
const result = runMsdTools(['docs-init'], tmpDir);
assert.ok(result.success, `Command failed: ${result.error}`);
const data = JSON.parse(result.output);
const readmeEntry = data.existing_docs.find(d => d.path === 'README.md');
assert.ok(readmeEntry, 'README.md should appear in existing_docs');
assert.strictEqual(readmeEntry.has_gsd_marker, true, 'README.md should have GSD marker');
assert.strictEqual(readmeEntry.has_msd_marker, true, 'README.md should have MSD marker');
const notesEntry = data.existing_docs.find(d => d.path === 'NOTES.md');
assert.ok(notesEntry, 'NOTES.md should appear in existing_docs');
assert.strictEqual(notesEntry.has_gsd_marker, false, 'NOTES.md should not have GSD marker');
assert.strictEqual(notesEntry.has_msd_marker, false, 'NOTES.md should not have MSD marker');
});
});
@@ -342,7 +342,7 @@ describe('doc tooling detection', () => {
test('detects Docusaurus config', () => {
fs.writeFileSync(path.join(tmpDir, 'docusaurus.config.js'), 'module.exports = {};', 'utf-8');
const result = runGsdTools(['docs-init'], tmpDir);
const result = runMsdTools(['docs-init'], tmpDir);
assert.ok(result.success, `Command failed: ${result.error}`);
const data = JSON.parse(result.output);
@@ -353,7 +353,7 @@ describe('doc tooling detection', () => {
fs.mkdirSync(path.join(tmpDir, '.vitepress'), { recursive: true });
fs.writeFileSync(path.join(tmpDir, '.vitepress', 'config.ts'), 'export default {};', 'utf-8');
const result = runGsdTools(['docs-init'], tmpDir);
const result = runMsdTools(['docs-init'], tmpDir);
assert.ok(result.success, `Command failed: ${result.error}`);
const data = JSON.parse(result.output);
@@ -363,7 +363,7 @@ describe('doc tooling detection', () => {
test('detects MkDocs config', () => {
fs.writeFileSync(path.join(tmpDir, 'mkdocs.yml'), 'site_name: test', 'utf-8');
const result = runGsdTools(['docs-init'], tmpDir);
const result = runMsdTools(['docs-init'], tmpDir);
assert.ok(result.success, `Command failed: ${result.error}`);
const data = JSON.parse(result.output);
@@ -386,13 +386,13 @@ describe('doc tooling detection', () => {
// Regression tests for bug #3135.
//
// PR #2824 consolidated add-backlog into `gsd-capture --backlog` by creating
// a routing wrapper in commands/gsd/capture.md that delegates to
// PR #2824 consolidated add-backlog into `msd-capture --backlog` by creating
// a routing wrapper in commands/msd/capture.md that delegates to
// workflows/add-backlog.md via execution_context. The workflow file was never
// created. Same gap class as reapply-patches.md (found and fixed in the same PR).
//
// Fix: create gsd-core/workflows/add-backlog.md with the full process
// ported from the deleted commands/gsd/add-backlog.md (git ref 87917131^).
// Fix: create msd-core/workflows/add-backlog.md with the full process
// ported from the deleted commands/msd/add-backlog.md (git ref 87917131^).
const { describe, test } = require('node:test');
const assert = require('node:assert/strict');
@@ -400,24 +400,24 @@ const fs = require('node:fs');
const path = require('node:path');
const ROOT = path.join(__dirname, '..');
const WORKFLOW = path.join(ROOT, 'gsd-core', 'workflows', 'add-backlog.md');
const COMMANDS_DIR = path.join(ROOT, 'commands', 'gsd');
const WORKFLOW = path.join(ROOT, 'msd-core', 'workflows', 'add-backlog.md');
const COMMANDS_DIR = path.join(ROOT, 'commands', 'msd');
// ─── #3135: add-backlog workflow ─────────────────────────────────────────────
describe('#3135: gsd-core/workflows/add-backlog.md', () => {
describe('#3135: msd-core/workflows/add-backlog.md', () => {
test('file exists', () => {
assert.ok(
fs.existsSync(WORKFLOW),
'gsd-core/workflows/add-backlog.md does not exist — capture --backlog has no implementation to load',
'msd-core/workflows/add-backlog.md does not exist — capture --backlog has no implementation to load',
);
});
test('uses gsd-sdk query phase.next-decimal to find next 999.x slot', () => {
test('uses msd-sdk query phase.next-decimal to find next 999.x slot', () => {
const src = fs.readFileSync(WORKFLOW, 'utf8');
assert.ok(
src.includes('phase.next-decimal'),
'add-backlog.md must use gsd-sdk query phase.next-decimal to find the next 999.x number',
'add-backlog.md must use msd-sdk query phase.next-decimal to find the next 999.x number',
);
});
@@ -438,15 +438,15 @@ describe('#3135: gsd-core/workflows/add-backlog.md', () => {
const src = fs.readFileSync(WORKFLOW, 'utf8');
assert.ok(
src.includes('generate-slug'),
'add-backlog.md must use gsd-sdk query generate-slug to build the phase directory slug',
'add-backlog.md must use msd-sdk query generate-slug to build the phase directory slug',
);
});
test('commits via gsd-sdk query commit', () => {
test('commits via msd-sdk query commit', () => {
const src = fs.readFileSync(WORKFLOW, 'utf8');
assert.ok(
src.includes('gsd-sdk query commit') || src.includes('query commit'),
'add-backlog.md must commit via gsd-sdk query commit',
src.includes('msd-sdk query commit') || src.includes('query commit'),
'add-backlog.md must commit via msd-sdk query commit',
);
});
@@ -470,11 +470,11 @@ describe('#3135: gsd-core/workflows/add-backlog.md', () => {
);
});
test('documents /gsd-review-backlog for promotion', () => {
test('documents /msd-review-backlog for promotion', () => {
const src = fs.readFileSync(WORKFLOW, 'utf8');
assert.ok(
src.includes('review-backlog') || src.includes('gsd-review-backlog'),
'add-backlog.md should mention /gsd-review-backlog for promoting items to active milestone',
src.includes('review-backlog') || src.includes('msd-review-backlog'),
'add-backlog.md should mention /msd-review-backlog for promoting items to active milestone',
);
});
});
@@ -491,7 +491,7 @@ describe('#3135: capture.md correctly routes --backlog to add-backlog workflow',
for (const line of blk.split('\n')) {
const t = line.trim();
if (!t.startsWith('@')) continue;
const rel = t.replace(/^@~?\/?(?:\.claude\/)?(?:gsd-core\/)?/, '');
const rel = t.replace(/^@~?\/?(?:\.claude\/)?(?:msd-core\/)?/, '');
targets.push(rel);
}
}