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,7 +1,7 @@
/**
* Execute-phase wave filter tests
*
* Validates the /gsd-execute-phase --wave feature contract:
* Validates the /msd-execute-phase --wave feature contract:
* - Command frontmatter advertises --wave
* - Workflow parses WAVE_FILTER
* - Workflow enforces lower-wave safety
@@ -12,13 +12,13 @@ const { test, describe } = 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 COMMAND_PATH = path.join(__dirname, '..', 'commands', 'gsd', 'execute-phase.md');
const WORKFLOW_PATH = path.join(__dirname, '..', 'gsd-core', 'workflows', 'execute-phase.md');
const COMMAND_PATH = path.join(__dirname, '..', 'commands', 'msd', 'execute-phase.md');
const WORKFLOW_PATH = path.join(__dirname, '..', 'msd-core', 'workflows', 'execute-phase.md');
const COMMANDS_DOC_PATH = path.join(__dirname, '..', 'docs', 'COMMANDS.md');
// After #3039, the comprehensive command reference moved to help/modes/full.md.
const HELP_PATH = path.join(__dirname, '..', 'gsd-core', 'workflows', 'help', 'modes', 'full.md');
const HELP_PATH = path.join(__dirname, '..', 'msd-core', 'workflows', 'help', 'modes', 'full.md');
// allow-test-rule: source-text-is-the-product
// The workflow and command .md files are the installed AI instructions — their text content
@@ -26,7 +26,7 @@ const HELP_PATH = path.join(__dirname, '..', 'gsd-core', 'workflows', 'help', 'm
// See #2692 for the missing behavioral test for --wave N argument parsing.
describe('execute-phase command: --wave flag', () => {
test('command file exists', () => {
assert.ok(fs.existsSync(COMMAND_PATH), 'commands/gsd/execute-phase.md should exist');
assert.ok(fs.existsSync(COMMAND_PATH), 'commands/msd/execute-phase.md should exist');
});
test('argument-hint includes --wave, --gaps-only, and --interactive', () => {
@@ -77,16 +77,16 @@ describe('execute-phase workflow: wave filtering', () => {
test('workflow has partial-wave completion guardrail', () => {
const content = fs.readFileSync(WORKFLOW_PATH, 'utf-8');
// handle_partial_wave_execution was extracted to
// gsd-core/workflows/execute-phase/steps/partial-wave.md. The parent now only
// references it via a <gsd:section> pointer, so assert the pointer is present here
// msd-core/workflows/execute-phase/steps/partial-wave.md. The parent now only
// references it via a <msd:section> pointer, so assert the pointer is present here
// and then read the actual step body from the extracted file below.
assert.ok(
content.includes('gsd-core/workflows/execute-phase/steps/partial-wave.md'),
content.includes('msd-core/workflows/execute-phase/steps/partial-wave.md'),
'workflow should reference the extracted partial-wave step file'
);
const PARTIAL_WAVE_STEP_PATH = path.join(
__dirname, '..', 'gsd-core', 'workflows', 'execute-phase', 'steps', 'partial-wave.md'
__dirname, '..', 'msd-core', 'workflows', 'execute-phase', 'steps', 'partial-wave.md'
);
assert.ok(fs.existsSync(PARTIAL_WAVE_STEP_PATH), 'partial-wave step file should exist');
const stepContent = fs.readFileSync(PARTIAL_WAVE_STEP_PATH, 'utf-8');
@@ -233,7 +233,7 @@ describe('execute-phase docs: user-facing wave flag', () => {
const content = fs.readFileSync(COMMANDS_DOC_PATH, 'utf-8');
assert.ok(content.includes('`--wave N`'), 'COMMANDS.md should mention --wave N');
assert.ok(
content.includes('/gsd-execute-phase 1 --wave 2'),
content.includes('/msd-execute-phase 1 --wave 2'),
'COMMANDS.md should include a wave-filter example'
);
});
@@ -245,7 +245,7 @@ describe('execute-phase docs: user-facing wave flag', () => {
'help.md should describe wave-specific execution'
);
assert.ok(
content.includes('Usage: `/gsd:execute-phase 5 --wave 2`') || content.includes('Usage: `/gsd-execute-phase 5 --wave 2`'),
content.includes('Usage: `/msd:execute-phase 5 --wave 2`') || content.includes('Usage: `/msd-execute-phase 5 --wave 2`'),
'help.md should include wave-filter usage'
);
});
@@ -309,7 +309,7 @@ describe('phase-plan-index: wave grouping behavior', () => {
'<task>Do the other thing</task>',
].join('\n'));
const result = runGsdTools(['phase-plan-index', '1', '--raw'], tmpDir);
const result = runMsdTools(['phase-plan-index', '1', '--raw'], tmpDir);
assert.ok(result.success, `phase-plan-index should succeed: ${result.error}`);
const data = JSON.parse(result.output);
@@ -353,7 +353,7 @@ describe('phase-plan-index: wave grouping behavior', () => {
'<task>Some work</task>',
].join('\n'));
const result = runGsdTools(['phase-plan-index', '1', '--raw'], tmpDir);
const result = runMsdTools(['phase-plan-index', '1', '--raw'], tmpDir);
assert.ok(result.success, `phase-plan-index should succeed: ${result.error}`);
const data = JSON.parse(result.output);
@@ -368,10 +368,10 @@ describe('phase-plan-index: wave grouping behavior', () => {
});
describe('use_worktrees config: cross-workflow structural coverage', () => {
const QUICK_PATH = path.join(__dirname, '..', 'gsd-core', 'workflows', 'quick.md');
const DIAGNOSE_PATH = path.join(__dirname, '..', 'gsd-core', 'workflows', 'diagnose-issues.md');
const EXECUTE_PLAN_PATH = path.join(__dirname, '..', 'gsd-core', 'workflows', 'execute-plan.md');
const PLANNING_CONFIG_PATH = path.join(__dirname, '..', 'gsd-core', 'references', 'planning-config.md');
const QUICK_PATH = path.join(__dirname, '..', 'msd-core', 'workflows', 'quick.md');
const DIAGNOSE_PATH = path.join(__dirname, '..', 'msd-core', 'workflows', 'diagnose-issues.md');
const EXECUTE_PLAN_PATH = path.join(__dirname, '..', 'msd-core', 'workflows', 'execute-plan.md');
const PLANNING_CONFIG_PATH = path.join(__dirname, '..', 'msd-core', 'references', 'planning-config.md');
test('quick workflow reads USE_WORKTREES from config', () => {
const content = fs.readFileSync(QUICK_PATH, 'utf-8');
@@ -420,7 +420,7 @@ describe('use_worktrees config: cross-workflow structural coverage', () => {
test('config-set accepts workflow.use_worktrees', () => {
const tmpDir = createTempProject();
try {
const result = runGsdTools('config-set workflow.use_worktrees true', tmpDir);
const result = runMsdTools('config-set workflow.use_worktrees true', tmpDir);
assert.ok(result.success, `config-set should accept workflow.use_worktrees: ${result.error}`);
} finally {
cleanup(tmpDir);
@@ -441,7 +441,7 @@ describe('use_worktrees config: cross-workflow structural coverage', () => {
// Per CONTRIBUTING.md exception matrix.
/**
* Bug #2410 — /gsd:manager background execute-phase Task fails with
* Bug #2410 — /msd:manager background execute-phase Task fails with
* "Stream idle timeout" on multi-plan phases.
*
* Fix: execute-phase.md instructs the orchestrator to emit `[checkpoint]`
@@ -458,7 +458,7 @@ const path = require('path');
const WORKFLOW_PATH = path.join(
__dirname,
'..',
'gsd-core',
'msd-core',
'workflows',
'execute-phase.md'
);
@@ -604,13 +604,13 @@ describe('bug #2410: execute-phase emits checkpoint heartbeats', () => {
describe('bug #2410: checkpoint heartbeat format is user-documented', () => {
const commandsDoc = fs.readFileSync(COMMANDS_DOC_PATH, 'utf-8');
test('COMMANDS.md documents the [checkpoint] format under /gsd-manager', () => {
const managerIdx = commandsDoc.indexOf('### `/gsd-manager`');
assert.ok(managerIdx !== -1, '/gsd-manager section should exist');
test('COMMANDS.md documents the [checkpoint] format under /msd-manager', () => {
const managerIdx = commandsDoc.indexOf('### `/msd-manager`');
assert.ok(managerIdx !== -1, '/msd-manager section should exist');
const section = commandsDoc.slice(managerIdx, managerIdx + 4000);
assert.ok(
/\[checkpoint\]/.test(section),
'COMMANDS.md /gsd-manager section should document [checkpoint] heartbeat markers'
'COMMANDS.md /msd-manager section should document [checkpoint] heartbeat markers'
);
assert.ok(
/Stream idle timeout/i.test(section),
@@ -649,9 +649,9 @@ const assert = require('node:assert/strict');
const fs = require('fs');
const path = require('path');
const WORKFLOW_PATH = path.join(__dirname, '..', 'gsd-core', 'workflows', 'execute-phase.md');
const WAVE_GUARD_PATH = path.join(__dirname, '..', 'gsd-core', 'references', 'execute-phase-wave-guard.md');
const BETWEEN_WAVE_PATH = path.join(__dirname, '..', 'gsd-core', 'references', 'execute-phase-between-wave-reset.md');
const WORKFLOW_PATH = path.join(__dirname, '..', 'msd-core', 'workflows', 'execute-phase.md');
const WAVE_GUARD_PATH = path.join(__dirname, '..', 'msd-core', 'references', 'execute-phase-wave-guard.md');
const BETWEEN_WAVE_PATH = path.join(__dirname, '..', 'msd-core', 'references', 'execute-phase-between-wave-reset.md');
describe('execute-phase: inter-wave worktree base re-check (#1369)', () => {
test('workflow file exists', () => {
@@ -847,10 +847,10 @@ describe('execute-phase: between-wave manifest reset (#1369, #3384)', () => {
// Regression guard for bug #3096.
//
// ai-integration-phase.md listed Steps 7+8 (gsd-ai-researcher +
// gsd-domain-researcher) without an explicit sequential ordering constraint.
// ai-integration-phase.md listed Steps 7+8 (msd-ai-researcher +
// msd-domain-researcher) without an explicit sequential ordering constraint.
// An orchestrator optimizing for speed could reasonably parallelize them
// since the sections appeared disjoint. When parallelized, gsd-domain-researcher's
// since the sections appeared disjoint. When parallelized, msd-domain-researcher's
// Write call at finalization replaced the whole AI-SPEC.md file with its
// in-memory copy (pre-researcher state), silently overwriting Sections 3/4.
//
@@ -868,7 +868,7 @@ const path = require('node:path');
const ROOT = path.join(__dirname, '..');
const src = fs.readFileSync(
path.join(ROOT, 'gsd-core', 'workflows', 'ai-integration-phase.md'),
path.join(ROOT, 'msd-core', 'workflows', 'ai-integration-phase.md'),
'utf8',
);
@@ -880,10 +880,10 @@ describe('bug #3096: ai-integration-phase sequential ordering and Edit-only disc
);
});
test('Step 7 gsd-ai-researcher prompt includes Edit-only tool discipline', () => {
// The discipline block must appear before </objective> for gsd-ai-researcher
const step7Idx = src.indexOf('## 7. Spawn gsd-ai-researcher');
const step8Idx = src.indexOf('## 8. Spawn gsd-domain-researcher');
test('Step 7 msd-ai-researcher prompt includes Edit-only tool discipline', () => {
// The discipline block must appear before </objective> for msd-ai-researcher
const step7Idx = src.indexOf('## 7. Spawn msd-ai-researcher');
const step8Idx = src.indexOf('## 8. Spawn msd-domain-researcher');
assert.ok(step7Idx !== -1, 'Step 7 not found');
assert.ok(step8Idx !== -1, 'Step 8 not found');
const step7Block = src.slice(step7Idx, step8Idx);
@@ -893,9 +893,9 @@ describe('bug #3096: ai-integration-phase sequential ordering and Edit-only disc
);
});
test('Step 8 gsd-domain-researcher prompt includes Edit-only tool discipline', () => {
const step8Idx = src.indexOf('## 8. Spawn gsd-domain-researcher');
const step9Idx = src.indexOf('## 9. Spawn gsd-eval-planner');
test('Step 8 msd-domain-researcher prompt includes Edit-only tool discipline', () => {
const step8Idx = src.indexOf('## 8. Spawn msd-domain-researcher');
const step9Idx = src.indexOf('## 9. Spawn msd-eval-planner');
assert.ok(step8Idx !== -1, 'Step 8 not found');
assert.ok(step9Idx !== -1, 'Step 9 not found');
const step8Block = src.slice(step8Idx, step9Idx);
@@ -906,8 +906,8 @@ describe('bug #3096: ai-integration-phase sequential ordering and Edit-only disc
});
test('Step 8 references the wait instruction', () => {
const step8Idx = src.indexOf('## 8. Spawn gsd-domain-researcher');
const step9Idx = src.indexOf('## 9. Spawn gsd-eval-planner');
const step8Idx = src.indexOf('## 8. Spawn msd-domain-researcher');
const step9Idx = src.indexOf('## 9. Spawn msd-eval-planner');
const step8Block = src.slice(step8Idx, step9Idx);
assert.ok(
step8Block.includes('Wait') || step8Block.includes('wait') || step8Block.includes('complete'),
@@ -933,7 +933,7 @@ describe('issue #3210: execute-phase auto-mode carve-out exempts precondition-un
assert.ok(open !== -1, 'checkpoint_handling step not found');
const close = content.indexOf('</step>', open);
const step = content.slice(open, close);
const splitLines = require('../gsd-core/bin/lib/text-lines.cjs').splitLines;
const splitLines = require('../msd-core/bin/lib/text-lines.cjs').splitLines;
const carveOut = splitLines(step).find((l) => l.includes('Carve-out'));
assert.ok(carveOut, 'checkpoint_handling must keep the blocking-human carve-out');
assert.match(
@@ -977,7 +977,7 @@ describe('execute-phase workflow: #3684 verified-unmarked resume', () => {
);
// Report fields may be NAMED in the prohibition prose — what is
// forbidden is reading them as the signal (a command/jq consumption).
const branchBash = step.split('\n').filter((l) => /jq|gsd_run|pick/.test(l)).join('\n');
const branchBash = step.split('\n').filter((l) => /jq|msd_run|pick/.test(l)).join('\n');
assert.ok(
!/roadmap_updated|state_updated/.test(branchBash),
'completion report fields must never be READ as the already-complete signal (#3685)',
@@ -1018,7 +1018,7 @@ describe('execute-phase workflow: #3684 verified-unmarked resume', () => {
});
function buildStrandedFixture(t, { ticked }) {
const proj = createTempProject('gsd-3684-');
const proj = createTempProject('msd-3684-');
t.after(() => cleanup(proj));
const phaseDir = path.join(proj, '.planning', 'phases', '01-alpha');
fs.mkdirSync(phaseDir, { recursive: true });
@@ -1043,8 +1043,8 @@ describe('execute-phase workflow: #3684 verified-unmarked resume', () => {
test('routing queries yield passed + unmarked on the stranded fixture', (t) => {
const { proj } = buildStrandedFixture(t, { ticked: false });
const verify = runGsdTools(`verification status ${path.join(proj, '.planning', 'phases', '01-alpha')} --pick status`, proj);
const analyze = runGsdTools(['roadmap.analyze', '--json'], proj);
const verify = runMsdTools(`verification status ${path.join(proj, '.planning', 'phases', '01-alpha')} --pick status`, proj);
const analyze = runMsdTools(['roadmap.analyze', '--json'], proj);
assert.ok(analyze.success, `roadmap.analyze should succeed: ${analyze.error}`);
const phases = JSON.parse(analyze.output).phases || [];
const p1 = phases.find((p) => String(p.number) === '1');
@@ -1058,7 +1058,7 @@ describe('execute-phase workflow: #3684 verified-unmarked resume', () => {
test('routing queries yield marked after completion', (t) => {
const { proj } = buildStrandedFixture(t, { ticked: true });
const analyze = runGsdTools(['roadmap.analyze', '--json'], proj);
const analyze = runMsdTools(['roadmap.analyze', '--json'], proj);
const phases = JSON.parse(analyze.output).phases || [];
const p1 = phases.find((p) => String(p.number) === '1');
assert.ok(p1, 'phase 1 should appear');
@@ -1067,11 +1067,11 @@ describe('execute-phase workflow: #3684 verified-unmarked resume', () => {
test('phase.complete is idempotent on the already-complete fixture', (t) => {
const { proj } = buildStrandedFixture(t, { ticked: false });
const first = runGsdTools('phase complete 1', proj);
const first = runMsdTools('phase complete 1', proj);
assert.ok(first.success, `first completion should succeed: ${first.error}`);
const roadmapAfterFirst = fs.readFileSync(path.join(proj, '.planning', 'ROADMAP.md'), 'utf-8');
assert.ok(/\[x\]/.test(roadmapAfterFirst), 'first completion ticks the checkbox');
const second = runGsdTools('phase complete 1', proj);
const second = runMsdTools('phase complete 1', proj);
assert.ok(second.success, 'second completion should succeed (no-op)');
const roadmapAfterSecond = fs.readFileSync(path.join(proj, '.planning', 'ROADMAP.md'), 'utf-8');
assert.equal(roadmapAfterSecond, roadmapAfterFirst, 'second run must leave ROADMAP byte-identical (criterion 3)');
@@ -1100,7 +1100,7 @@ describe('execute-phase workflow: #3684 review findings — join normalization',
`the jq must strip leading zeros on both sides: ${jqFilter}`,
);
const proj = createTempProject('gsd-3684-pad-');
const proj = createTempProject('msd-3684-pad-');
t.after(() => cleanup(proj));
const phaseDir = path.join(proj, '.planning', 'phases', '01-alpha');
fs.mkdirSync(phaseDir, { recursive: true });
@@ -1112,7 +1112,7 @@ describe('execute-phase workflow: #3684 review findings — join normalization',
'- [x] **Phase 1: Alpha** - done', '',
].join('\n'));
const analyze = runGsdTools('roadmap.analyze --json', proj);
const analyze = runMsdTools('roadmap.analyze --json', proj);
assert.ok(analyze.success, `roadmap.analyze should succeed: ${analyze.error}`);
// Evaluate the extracted filter's join semantics via a node mirror of
// `sub("^0+(?=[0-9])";"")` — the bench hosts no jq binary, so the
@@ -1136,7 +1136,7 @@ describe('execute-phase workflow: #3684 review findings — join normalization',
// state". The ROADMAP half is byte-identity; the STATE half legitimately
// touches only last_updated (the transition runs unconditionally — the
// triage's own empirical finding). Assert both halves explicitly.
const proj = createTempProject('gsd-3684-state-');
const proj = createTempProject('msd-3684-state-');
t.after(() => cleanup(proj));
const phaseDir = path.join(proj, '.planning', 'phases', '01-alpha');
fs.mkdirSync(phaseDir, { recursive: true });
@@ -1156,13 +1156,13 @@ describe('execute-phase workflow: #3684 review findings — join normalization',
'last_updated: 2026-01-01', '---', '', '# STATE', '',
].join('\n'));
const first = runGsdTools('phase complete 1', proj);
const first = runMsdTools('phase complete 1', proj);
assert.ok(first.success, `first completion should succeed: ${first.error}`);
const roadmap1 = fs.readFileSync(path.join(proj, '.planning', 'ROADMAP.md'), 'utf-8');
const state1 = fs.readFileSync(path.join(proj, '.planning', 'STATE.md'), 'utf-8');
assert.ok(/\[x\]/.test(roadmap1), 'first completion ticks the checkbox');
const second = runGsdTools('phase complete 1', proj);
const second = runMsdTools('phase complete 1', proj);
assert.ok(second.success, 'second completion should succeed');
const roadmap2 = fs.readFileSync(path.join(proj, '.planning', 'ROADMAP.md'), 'utf-8');
const state2 = fs.readFileSync(path.join(proj, '.planning', 'STATE.md'), 'utf-8');
@@ -1201,7 +1201,7 @@ describe('execute-phase workflow: #3684 review findings — join normalization',
describe('execute-phase: stall surveillance must not steer a working executor (#4218)', () => {
const workflow = fs.readFileSync(WORKFLOW_PATH, 'utf-8');
const FRAGMENT_PATH = path.join(
__dirname, '..', 'gsd-core', 'workflows', 'execute-phase', 'steps', 'executor-progress-policy.md');
__dirname, '..', 'msd-core', 'workflows', 'execute-phase', 'steps', 'executor-progress-policy.md');
const fragment = fs.existsSync(FRAGMENT_PATH) ? fs.readFileSync(FRAGMENT_PATH, 'utf-8') : '';
test('the host routes to the policy before treating an executor as stalled', () => {