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:
@@ -2,18 +2,18 @@
|
||||
// allow-test-rule: source-text-is-the-product (see #1990)
|
||||
// Command/workflow markdown is deployed runtime product; source-text assertions
|
||||
// below verify the installed command contract. CLI assertions exercise real
|
||||
// gsd-tools behavior through the public command boundary.
|
||||
// msd-tools behavior through the public command boundary.
|
||||
|
||||
const { describe, test, beforeEach, afterEach } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { runGsdTools, cleanup, absPlanningPath } = require('./helpers.cjs');
|
||||
const { runMsdTools, cleanup, absPlanningPath } = require('./helpers.cjs');
|
||||
const { createFixture } = require('./fixtures/index.cjs');
|
||||
|
||||
const ROOT = path.join(__dirname, '..');
|
||||
const CMD_PATH = path.join(ROOT, 'commands', 'gsd', 'onboard.md');
|
||||
const WF_PATH = path.join(ROOT, 'gsd-core', 'workflows', 'onboard.md');
|
||||
const CMD_PATH = path.join(ROOT, 'commands', 'msd', 'onboard.md');
|
||||
const WF_PATH = path.join(ROOT, 'msd-core', 'workflows', 'onboard.md');
|
||||
|
||||
describe('init onboard public CLI projection', () => {
|
||||
let tmpDir;
|
||||
@@ -37,7 +37,7 @@ describe('init onboard public CLI projection', () => {
|
||||
fs.mkdirSync(path.join(tmpDir, 'docs', 'adr'), { recursive: true });
|
||||
fs.writeFileSync(path.join(tmpDir, 'docs', 'adr', '0001-runtime.md'), '# ADR: Runtime\n');
|
||||
|
||||
const result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
const result = runMsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `init onboard should succeed: ${result.error}`);
|
||||
|
||||
const parsed = JSON.parse(result.output);
|
||||
@@ -64,7 +64,7 @@ describe('init onboard public CLI projection', () => {
|
||||
fs.mkdirSync(path.join(tmpDir, 'rfc'), { recursive: true });
|
||||
fs.writeFileSync(path.join(tmpDir, 'rfc', 'proposal.md'), '# Request for Comments\n');
|
||||
|
||||
const result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
const result = runMsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `init onboard should succeed: ${result.error}`);
|
||||
|
||||
const parsed = JSON.parse(result.output);
|
||||
@@ -87,7 +87,7 @@ describe('init onboard public CLI projection', () => {
|
||||
fs.mkdirSync(path.join(tmpDir, 'src'), { recursive: true });
|
||||
fs.writeFileSync(path.join(tmpDir, 'src', 'PRD.md'), '# Nested Product Requirements\n');
|
||||
|
||||
const result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
const result = runMsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `init onboard should succeed: ${result.error}`);
|
||||
|
||||
const parsed = JSON.parse(result.output);
|
||||
@@ -104,7 +104,7 @@ describe('init onboard public CLI projection', () => {
|
||||
});
|
||||
|
||||
test('forwards the --text flag into the public projection', () => {
|
||||
const result = runGsdTools(['init', 'onboard', '--text', '--raw'], tmpDir, { HOME: tmpDir });
|
||||
const result = runMsdTools(['init', 'onboard', '--text', '--raw'], tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `init onboard should succeed: ${result.error}`);
|
||||
|
||||
const parsed = JSON.parse(result.output);
|
||||
@@ -132,7 +132,7 @@ describe('init onboard public CLI projection', () => {
|
||||
];
|
||||
const before = new Map(trackedFiles.map(file => [file, fs.readFileSync(file, 'utf8')]));
|
||||
|
||||
const result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
const result = runMsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `init onboard should succeed: ${result.error}`);
|
||||
|
||||
for (const file of trackedFiles) {
|
||||
@@ -159,7 +159,7 @@ describe('init onboard public CLI projection', () => {
|
||||
}
|
||||
fs.writeFileSync(path.join(tmpDir, 'package.json'), '{"name":"fixture"}\n');
|
||||
|
||||
const result = runGsdTools(['init', 'onboard', '--fast', '--raw'], tmpDir, { HOME: tmpDir });
|
||||
const result = runMsdTools(['init', 'onboard', '--fast', '--raw'], tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `init onboard should succeed: ${result.error}`);
|
||||
|
||||
const parsed = JSON.parse(result.output);
|
||||
@@ -169,7 +169,7 @@ describe('init onboard public CLI projection', () => {
|
||||
assert.strictEqual(parsed.needs_codebase_map, true);
|
||||
assert.strictEqual(parsed.needs_fast_codebase_map, false);
|
||||
assert.strictEqual(parsed.next_action.kind, 'complete-map-before-new-project');
|
||||
assert.strictEqual(parsed.next_action.command, '/gsd-map-codebase');
|
||||
assert.strictEqual(parsed.next_action.command, '/msd-map-codebase');
|
||||
assert.match(parsed.next_action.reason, /complete codebase map/i);
|
||||
assert.deepStrictEqual(parsed.fast_codebase_map_files_required, [
|
||||
'STACK.md',
|
||||
@@ -189,12 +189,12 @@ describe('init onboard public CLI projection', () => {
|
||||
fs.mkdirSync(path.join(tmpDir, 'docs', 'adr'), { recursive: true });
|
||||
fs.writeFileSync(path.join(tmpDir, 'docs', 'adr', '0001-runtime.md'), '# ADR: Runtime\n');
|
||||
|
||||
const result = runGsdTools(['init', 'onboard', '--fast', '--raw'], tmpDir, { HOME: tmpDir });
|
||||
const result = runMsdTools(['init', 'onboard', '--fast', '--raw'], tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `init onboard should succeed: ${result.error}`);
|
||||
|
||||
const parsed = JSON.parse(result.output);
|
||||
assert.strictEqual(parsed.next_action.kind, 'complete-map-before-new-project');
|
||||
assert.strictEqual(parsed.next_action.command, '/gsd-map-codebase');
|
||||
assert.strictEqual(parsed.next_action.command, '/msd-map-codebase');
|
||||
});
|
||||
|
||||
test('routes planning artifacts without PROJECT.md to partial planning', () => {
|
||||
@@ -203,7 +203,7 @@ describe('init onboard public CLI projection', () => {
|
||||
fs.writeFileSync(path.join(tmpDir, '.planning', 'ROADMAP.md'), '# Roadmap\n');
|
||||
fs.writeFileSync(path.join(tmpDir, '.planning', 'STATE.md'), '# State\n');
|
||||
|
||||
const result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
const result = runMsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `init onboard should succeed: ${result.error}`);
|
||||
|
||||
const parsed = JSON.parse(result.output);
|
||||
@@ -221,7 +221,7 @@ describe('init onboard public CLI projection', () => {
|
||||
fs.writeFileSync(path.join(tmpDir, '.planning', `${name}.md`), `# ${name}\n`);
|
||||
}
|
||||
|
||||
const result = runGsdTools(['init', 'onboard', '--fast', '--raw'], tmpDir, { HOME: tmpDir });
|
||||
const result = runMsdTools(['init', 'onboard', '--fast', '--raw'], tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `init onboard should succeed: ${result.error}`);
|
||||
|
||||
const parsed = JSON.parse(result.output);
|
||||
@@ -243,7 +243,7 @@ describe('init onboard public CLI projection', () => {
|
||||
fs.writeFileSync(path.join(tmpDir, '.planning', 'ROADMAP.md'), '# Roadmap\n');
|
||||
fs.writeFileSync(path.join(tmpDir, '.planning', 'STATE.md'), '# State\n');
|
||||
|
||||
const result = runGsdTools(['init', 'onboard', '--fast', '--raw'], tmpDir, { HOME: tmpDir });
|
||||
const result = runMsdTools(['init', 'onboard', '--fast', '--raw'], tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `init onboard should succeed: ${result.error}`);
|
||||
|
||||
const parsed = JSON.parse(result.output);
|
||||
@@ -256,11 +256,11 @@ describe('init onboard public CLI projection', () => {
|
||||
test('projects the next action for code, docs, greenfield, partial planning, and summary states', () => {
|
||||
fs.mkdirSync(path.join(tmpDir, 'src'), { recursive: true });
|
||||
fs.writeFileSync(path.join(tmpDir, 'src', 'server.ts'), 'export const server = true;\n');
|
||||
let result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
let result = runMsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `init onboard should succeed: ${result.error}`);
|
||||
assert.deepStrictEqual(JSON.parse(result.output).next_action, {
|
||||
kind: 'map-codebase',
|
||||
command: '/gsd-map-codebase',
|
||||
command: '/msd-map-codebase',
|
||||
reason: 'Existing code was detected, but the required .planning/codebase/ map is missing.',
|
||||
});
|
||||
|
||||
@@ -269,22 +269,22 @@ describe('init onboard public CLI projection', () => {
|
||||
tmpDir = fs.realpathSync(createFixture({ planning: false, projectDoc: false }));
|
||||
fs.mkdirSync(path.join(tmpDir, 'docs', 'adr'), { recursive: true });
|
||||
fs.writeFileSync(path.join(tmpDir, 'docs', 'adr', '0001-runtime.md'), '# ADR: Runtime\n');
|
||||
result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
result = runMsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `init onboard should succeed: ${result.error}`);
|
||||
assert.deepStrictEqual(JSON.parse(result.output).next_action, {
|
||||
kind: 'ingest-docs',
|
||||
command: '/gsd-ingest-docs',
|
||||
command: '/msd-ingest-docs',
|
||||
reason: 'Detected existing ADR/PRD/SPEC/RFC document(s) before project setup.',
|
||||
});
|
||||
|
||||
cleanup(tmpDir);
|
||||
// #2376 macOS fix: see beforeEach above.
|
||||
tmpDir = fs.realpathSync(createFixture({ planning: false, projectDoc: false }));
|
||||
result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
result = runMsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `init onboard should succeed: ${result.error}`);
|
||||
assert.deepStrictEqual(JSON.parse(result.output).next_action, {
|
||||
kind: 'new-project',
|
||||
command: '/gsd-new-project',
|
||||
command: '/msd-new-project',
|
||||
reason: 'No existing code or planning docs were detected.',
|
||||
});
|
||||
|
||||
@@ -295,7 +295,7 @@ describe('init onboard public CLI projection', () => {
|
||||
fs.writeFileSync(path.join(tmpDir, '.planning', 'PROJECT.md'), '# Project\n');
|
||||
fs.writeFileSync(path.join(tmpDir, '.planning', 'ROADMAP.md'), '# Roadmap\n');
|
||||
fs.writeFileSync(path.join(tmpDir, '.planning', 'STATE.md'), '# State\n');
|
||||
result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
result = runMsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `init onboard should succeed: ${result.error}`);
|
||||
const partial = JSON.parse(result.output);
|
||||
assert.strictEqual(partial.next_action.kind, 'partial-planning');
|
||||
@@ -306,7 +306,7 @@ describe('init onboard public CLI projection', () => {
|
||||
fs.writeFileSync(path.join(tmpDir, '.planning', 'codebase', `${name}.md`), `# ${name}\n`);
|
||||
}
|
||||
fs.writeFileSync(path.join(tmpDir, '.planning', 'REQUIREMENTS.md'), '# Requirements\n');
|
||||
result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
result = runMsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `init onboard should succeed: ${result.error}`);
|
||||
assert.deepStrictEqual(JSON.parse(result.output).next_action, {
|
||||
kind: 'write-summary',
|
||||
@@ -316,7 +316,7 @@ describe('init onboard public CLI projection', () => {
|
||||
|
||||
fs.mkdirSync(path.join(tmpDir, '.planning', 'onboarding'), { recursive: true });
|
||||
fs.writeFileSync(path.join(tmpDir, '.planning', 'onboarding', 'SUMMARY.md'), '# Onboarding Summary\n');
|
||||
result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
result = runMsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `init onboard should succeed: ${result.error}`);
|
||||
assert.deepStrictEqual(JSON.parse(result.output).next_action, {
|
||||
kind: 'ready',
|
||||
@@ -330,7 +330,7 @@ describe('init onboard public CLI projection', () => {
|
||||
fs.writeFileSync(path.join(tmpDir, '.planning', 'ROADMAP.md'), '# Roadmap\n');
|
||||
fs.writeFileSync(path.join(tmpDir, '.planning', 'STATE.md'), '# State\n');
|
||||
|
||||
const result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
const result = runMsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `init onboard should succeed: ${result.error}`);
|
||||
|
||||
const parsed = JSON.parse(result.output);
|
||||
@@ -346,7 +346,7 @@ describe('init onboard public CLI projection', () => {
|
||||
fs.mkdirSync(path.join(tmpDir, 'dist'), { recursive: true });
|
||||
fs.writeFileSync(path.join(tmpDir, 'dist', 'bundle.js'), 'console.log("ignored");\n');
|
||||
|
||||
const result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
const result = runMsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `init onboard should succeed: ${result.error}`);
|
||||
|
||||
const parsed = JSON.parse(result.output);
|
||||
@@ -359,7 +359,7 @@ describe('init onboard public CLI projection', () => {
|
||||
test('treats package manifests as brownfield even without source files', () => {
|
||||
fs.writeFileSync(path.join(tmpDir, 'package.json'), '{"name":"fixture"}\n');
|
||||
|
||||
const result = runGsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
const result = runMsdTools('init onboard --raw', tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `init onboard should succeed: ${result.error}`);
|
||||
|
||||
const parsed = JSON.parse(result.output);
|
||||
@@ -373,30 +373,30 @@ describe('init onboard public CLI projection', () => {
|
||||
test('formats onboard handoff commands for the resolved runtime', () => {
|
||||
fs.writeFileSync(path.join(tmpDir, 'package.json'), '{"name":"fixture"}\n');
|
||||
|
||||
const result = runGsdTools(['init', 'onboard', '--raw'], tmpDir, {
|
||||
const result = runMsdTools(['init', 'onboard', '--raw'], tmpDir, {
|
||||
HOME: tmpDir,
|
||||
GSD_RUNTIME: 'codex',
|
||||
MSD_RUNTIME: 'codex',
|
||||
});
|
||||
assert.ok(result.success, `init onboard should succeed: ${result.error}`);
|
||||
|
||||
const parsed = JSON.parse(result.output);
|
||||
assert.strictEqual(parsed.next_action.kind, 'map-codebase');
|
||||
assert.strictEqual(parsed.next_action.command, '$gsd-map-codebase');
|
||||
assert.strictEqual(parsed.next_action.command, '$msd-map-codebase');
|
||||
assert.deepStrictEqual(parsed.handoff_commands, {
|
||||
map_codebase: '$gsd-map-codebase',
|
||||
map_codebase_fast: '$gsd-map-codebase --fast',
|
||||
ingest_docs: '$gsd-ingest-docs',
|
||||
manager: '$gsd-manager',
|
||||
new_project: '$gsd-new-project',
|
||||
onboard: '$gsd-onboard',
|
||||
map_codebase: '$msd-map-codebase',
|
||||
map_codebase_fast: '$msd-map-codebase --fast',
|
||||
ingest_docs: '$msd-ingest-docs',
|
||||
manager: '$msd-manager',
|
||||
new_project: '$msd-new-project',
|
||||
onboard: '$msd-onboard',
|
||||
});
|
||||
});
|
||||
|
||||
test('dotted query init.onboard matches direct init onboard', () => {
|
||||
fs.writeFileSync(path.join(tmpDir, 'package.json'), '{"name":"fixture"}\n');
|
||||
|
||||
const direct = runGsdTools(['init', 'onboard', '--raw'], tmpDir, { HOME: tmpDir });
|
||||
const query = runGsdTools(['query', 'init.onboard', '--raw'], tmpDir, { HOME: tmpDir });
|
||||
const direct = runMsdTools(['init', 'onboard', '--raw'], tmpDir, { HOME: tmpDir });
|
||||
const query = runMsdTools(['query', 'init.onboard', '--raw'], tmpDir, { HOME: tmpDir });
|
||||
assert.equal(direct.success, true, direct.error || direct.output);
|
||||
assert.equal(query.success, true, query.error || query.output);
|
||||
assert.deepStrictEqual(JSON.parse(query.output), JSON.parse(direct.output));
|
||||
@@ -404,24 +404,24 @@ describe('init onboard public CLI projection', () => {
|
||||
|
||||
});
|
||||
|
||||
describe('/gsd:onboard command contract', () => {
|
||||
describe('/msd:onboard command contract', () => {
|
||||
test('command file declares the onboard command and loads its workflow', () => {
|
||||
const content = fs.readFileSync(CMD_PATH, 'utf8');
|
||||
assert.match(content, /^name:\s*gsd:onboard$/m);
|
||||
assert.match(content, /^name:\s*msd:onboard$/m);
|
||||
assert.match(content, /^description:\s*.*(?:existing codebase|brownfield|onboard).*$/mi);
|
||||
assert.match(content, /^\s*- AskUserQuestion$/m);
|
||||
assert.match(content, /^\s*- Agent$/m);
|
||||
assert.ok(content.includes('@~/.claude/gsd-core/workflows/onboard.md'));
|
||||
assert.ok(content.includes('@~/.claude/gsd-core/references/ui-brand.md'));
|
||||
assert.ok(content.includes('@~/.claude/gsd-core/references/gate-prompts.md'));
|
||||
assert.ok(content.includes('@~/.claude/msd-core/workflows/onboard.md'));
|
||||
assert.ok(content.includes('@~/.claude/msd-core/references/ui-brand.md'));
|
||||
assert.ok(content.includes('@~/.claude/msd-core/references/gate-prompts.md'));
|
||||
});
|
||||
|
||||
test('workflow renders the init projection without owning the route state machine', () => {
|
||||
const content = fs.readFileSync(WF_PATH, 'utf8');
|
||||
|
||||
assert.ok(content.includes('@~/.claude/gsd-core/references/gsd-run-resolver.md'));
|
||||
assert.ok(content.includes('@~/.claude/msd-core/references/msd-run-resolver.md'));
|
||||
assert.ok(
|
||||
!content.includes('_GSD_SHIM_NAME="gsd-tools.cjs"'),
|
||||
!content.includes('_MSD_SHIM_NAME="msd-tools.cjs"'),
|
||||
'workflow must reference the shared resolver instead of inlining it',
|
||||
);
|
||||
assert.match(content, /init onboard --fast --raw/);
|
||||
@@ -429,7 +429,7 @@ describe('/gsd:onboard command contract', () => {
|
||||
assert.match(content, /next_action\.kind/);
|
||||
assert.match(content, /map_readiness/);
|
||||
assert.match(content, /codebase_map_summary_status/);
|
||||
assert.match(content, /ONBOARDING_ROOT=\{git_worktree_root \|\| _GSD_RUNTIME_ROOT\}/);
|
||||
assert.match(content, /ONBOARDING_ROOT=\{git_worktree_root \|\| _MSD_RUNTIME_ROOT\}/);
|
||||
|
||||
for (const action of [
|
||||
'map-codebase',
|
||||
@@ -484,9 +484,9 @@ describe('/gsd:onboard command contract', () => {
|
||||
assert.match(content, /do not overwrite/i, 'workflow must protect existing summary/planning');
|
||||
assert.match(content, /query commit "docs: create onboarding summary" --files \.planning\/onboarding\/SUMMARY\.md/);
|
||||
assert.ok(!content.includes('execute-phase'), 'onboarding must not execute implementation phases');
|
||||
assert.ok(!content.includes('gsd:ship'), 'onboarding must not ship work');
|
||||
assert.ok(!content.includes('msd:ship'), 'onboarding must not ship work');
|
||||
assert.ok(content.includes('Next recommended command: {handoff_commands.manager}'));
|
||||
assert.ok(!content.includes('/gsd:ingest-docs'), 'skip handoffs must not hard-code legacy ingest command');
|
||||
assert.ok(!content.includes('/gsd:new-project'), 'skip handoffs must not hard-code legacy new-project command');
|
||||
assert.ok(!content.includes('/msd:ingest-docs'), 'skip handoffs must not hard-code legacy ingest command');
|
||||
assert.ok(!content.includes('/msd:new-project'), 'skip handoffs must not hard-code legacy new-project command');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user