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

@@ -7,7 +7,7 @@
* stateReplaceField / stateExtractField / stateReplaceFieldWithFallback
* (issue #2880, ADR-2143 §3/§4). These lock byte-identical behaviour across
* the migration of the table branch off a hand-rolled whole-document regex
* onto a line-scan + byte-range splice (see gsd-core/bin/lib/state-document.cjs
* onto a line-scan + byte-range splice (see msd-core/bin/lib/state-document.cjs
* locateFieldRow). Any future re-implementation of the table branch must keep
* every assertion below true.
*/
@@ -21,7 +21,7 @@ const {
stateReplaceField,
stateExtractField,
stateReplaceFieldWithFallback,
} = require('../gsd-core/bin/lib/state-document.cjs');
} = require('../msd-core/bin/lib/state-document.cjs');
describe('stateReplaceField — table branch (characterization, #2880)', () => {
test('replaces a two-cell row in place', () => {
@@ -184,7 +184,7 @@ describe('stateReplaceField — empty field preserves the following line (#4010)
});
test('E2E: transitionCore update of an empty field preserves the next line (ADR-3180 Decision 4(c))', () => {
const { transitionCore } = require('../gsd-core/bin/lib/state-transition.cjs');
const { transitionCore } = require('../msd-core/bin/lib/state-transition.cjs');
const content = '## Current Position\n\n**Status:**\n**Current Plan:** 2 of 5';
const result = transitionCore(content, { kind: 'update', field: 'Status', value: 'Executing Phase 5' });
assert.equal(result.content, '## Current Position\n\n**Status:** Executing Phase 5\n**Current Plan:** 2 of 5');
@@ -660,13 +660,13 @@ 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');
describe('#2828 — total_phases uses the roadmap count on a flat unmilestoned roadmap', () => {
let tmpDir;
beforeEach(() => {
tmpDir = createTempProject('gsd-2828-');
tmpDir = createTempProject('msd-2828-');
const planningDir = path.join(tmpDir, '.planning');
// Flat unmilestoned roadmap with 6 phases (no versioned milestone heading).
fs.writeFileSync(
@@ -712,7 +712,7 @@ describe('#2828 — total_phases uses the roadmap count on a flat unmilestoned r
test('state sync writes progress.total_phases === 6 (roadmap count), not 1 (phase-dir count) (#2828)', () => {
// `state sync` derives progress.total_phases from the disk-scan cache (the read path
// #2828 fixes) and writes it to STATE.md frontmatter. Pre-fix this wrote 1.
const result = runGsdTools(['state', 'sync'], tmpDir);
const result = runMsdTools(['state', 'sync'], tmpDir);
assert.ok(result.success, `state sync failed: ${result.error}`);
const stateMd = fs.readFileSync(path.join(tmpDir, '.planning', 'STATE.md'), 'utf8');
@@ -774,7 +774,7 @@ describe('#2828 — total_phases uses the roadmap count on a flat unmilestoned r
* behavior verified to already hold today (see phase-log for the manual CLI
* probes that established each expected value before this file was written).
*
* Rows and naming follow `.gsd/phase/fix-3185-state-writer-phase-count/50-test-matrix.md`
* Rows and naming follow `.msd/phase/fix-3185-state-writer-phase-count/50-test-matrix.md`
* verbatim (row numbers refer to that matrix, not the 8-row table in
* `40-design.md`).
*
@@ -793,7 +793,7 @@ 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');
// ─────────────────────────────────────────────────────────────────────────────
// Fixture builders
@@ -830,7 +830,7 @@ function seedNamedPhaseDir(tmpDir, dirName, planBase) {
function buildStateMd({ milestone = 'v1.0', milestoneName = 'Test', totalPhases, currentPhase = '01', eol = '\n' }) {
const lines = [
'---',
'gsd_state_version: 1.0',
'msd_state_version: 1.0',
`milestone: ${milestone}`,
`milestone_name: ${milestoneName}`,
`current_phase: "${currentPhase}"`,
@@ -843,7 +843,7 @@ function buildStateMd({ milestone = 'v1.0', milestoneName = 'Test', totalPhases,
' percent: 0',
'---',
'',
'# GSD State',
'# MSD State',
'',
'## Current Position',
'',
@@ -856,13 +856,13 @@ function buildStateMd({ milestone = 'v1.0', milestoneName = 'Test', totalPhases,
/** Invoke `state record-session` (the #3204 entry point) then read back `state json --raw`. */
function recordSessionAndReadTotalPhases(tmpDir) {
const recordResult = runGsdTools(
const recordResult = runMsdTools(
['state', 'record-session', '--stopped-at', 'Phase 1, Plan 1', '--resume-file', 'none'],
tmpDir,
);
assert.ok(recordResult.success, `state record-session failed: ${recordResult.error}`);
const jsonResult = runGsdTools(['state', 'json', '--raw'], tmpDir);
const jsonResult = runMsdTools(['state', 'json', '--raw'], tmpDir);
assert.ok(jsonResult.success, `state json --raw failed: ${jsonResult.error}`);
return JSON.parse(jsonResult.output);
}
@@ -1095,7 +1095,7 @@ describe('#3204 buildStateFrontmatter total_phases — negative space / boundari
`#3642: a single non-matching section must not leak its phases into the asserted milestone's total; stored 99 expected, got ${out.progress && out.progress.total_phases}`,
);
// The clobber must also be SURFACED, not silent: drive the seam directly
// (runGsdTools discards stderr on success) and require the #3642 warning
// (runMsdTools discards stderr on success) and require the #3642 warning
// naming the asserted milestone.
const { runNode } = require('./helpers/process-seam.cjs');
const { TOOLS_PATH, TEST_ENV_BASE } = require('./helpers.cjs');
@@ -1525,7 +1525,7 @@ describe('#3185 buildStateFrontmatter total_phases — directory-enumeration ind
const roadmap = ['# Roadmap', '', '## Phase 1: One', '## Phase 2: Two', '## Phase 3: Three', ''].join('\n');
fs.writeFileSync(path.join(tmpDir, '.planning', 'ROADMAP.md'), roadmap);
const sessionState = [
'# GSD State',
'# MSD State',
'',
'## Session',
'',
@@ -1543,14 +1543,14 @@ describe('#3185 buildStateFrontmatter total_phases — directory-enumeration ind
seedPhaseDirs(tmpDir, [1, 2, 3]);
const statePath = path.join(tmpDir, '.planning', 'STATE.md');
const pinnedEnv = { GSD_TEST_MODE: '1', GSD_NOW_MS: '1600000000000' };
const pinnedEnv = { MSD_TEST_MODE: '1', MSD_NOW_MS: '1600000000000' };
const args = ['state', 'record-session', '--stopped-at', 'Phase 1, Plan 1', '--resume-file', 'none'];
const first = runGsdTools(args, tmpDir, pinnedEnv);
const first = runMsdTools(args, tmpDir, pinnedEnv);
assert.ok(first.success, `first record-session failed: ${first.error}`);
const afterFirst = fs.readFileSync(statePath, 'utf8');
const second = runGsdTools(args, tmpDir, pinnedEnv);
const second = runMsdTools(args, tmpDir, pinnedEnv);
assert.ok(second.success, `second record-session failed: ${second.error}`);
const afterSecond = fs.readFileSync(statePath, 'utf8');
@@ -1586,7 +1586,7 @@ describe('#3355 phase-dir dedup — collision tie-break must not consult mtime',
let tmpDir;
beforeEach(() => {
tmpDir = createTempProject('gsd-3355-');
tmpDir = createTempProject('msd-3355-');
});
afterEach(() => {
@@ -1619,7 +1619,7 @@ describe('#3355 phase-dir dedup — collision tie-break must not consult mtime',
}
function readProgress() {
const result = runGsdTools(['state', 'json', '--raw'], tmpDir);
const result = runMsdTools(['state', 'json', '--raw'], tmpDir);
assert.ok(result.success, `state json --raw failed: ${result.error}`);
return JSON.parse(result.output).progress;
}
@@ -1632,7 +1632,7 @@ describe('#3355 phase-dir dedup — collision tie-break must not consult mtime',
// utimes to whole ms), so the flip uses a margin guaranteed to register
// everywhere — pre-fix, the mtime-newer duplicate then won the dedup
// regardless of repository content. `_diskScanCache` is process-local
// and runGsdTools spawns a fresh node per call, so each read below is a
// and runMsdTools spawns a fresh node per call, so each read below is a
// cold scan exactly like a fresh checkout.
const base = new Date('2026-01-01T00:00:00.000Z');
const margin = new Date(base.getTime() + 1500);
@@ -1656,7 +1656,7 @@ describe('#3355 phase-dir dedup — collision tie-break must not consult mtime',
);
// The collision must be surfaced: stderr warning naming BOTH dirs
// (runGsdTools discards stderr on success, so drive the seam directly).
// (runMsdTools discards stderr on success, so drive the seam directly).
const rec = runNode(
[TOOLS_PATH, 'state', 'json', '--raw'],
{ cwd: tmpDir, env: { ...process.env, ...TEST_ENV_BASE }, timeoutMs: LOOP_HOOK_POINT_CLI_TIMEOUT_MS },
@@ -1723,7 +1723,7 @@ describe('#3354 buildStateFrontmatter total_phases — milestoned-but-unbounded
);
seedPhaseDirs(tmpDir, [1, 2, 3, 4]);
// Drive the mutating command with stderr captured (runGsdTools discards
// Drive the mutating command with stderr captured (runMsdTools discards
// stderr on success). The warning is asserted on THIS invocation.
const rec = runNode(
[TOOLS_PATH, 'state', 'record-session', '--stopped-at', 'Phase 1, Plan 1', '--resume-file', 'none'],
@@ -1736,7 +1736,7 @@ describe('#3354 buildStateFrontmatter total_phases — milestoned-but-unbounded
`#3354: expected a stderr warning naming the unbounded milestone token 'v1.0', got stderr=${JSON.stringify(rec.stderr)}`,
);
const jsonResult = runGsdTools(['state', 'json', '--raw'], tmpDir);
const jsonResult = runMsdTools(['state', 'json', '--raw'], tmpDir);
assert.ok(jsonResult.success, `state json --raw failed: ${jsonResult.error}`);
const out = JSON.parse(jsonResult.output);
@@ -1759,14 +1759,14 @@ describe('#3354 buildStateFrontmatter total_phases — milestoned-but-unbounded
path.join(tmpDir, '.planning', 'STATE.md'),
[
'---',
'gsd_state_version: 1.0',
'msd_state_version: 1.0',
'milestone: v1.0',
'milestone_name: Unbounded',
'current_phase: "01"',
'status: executing',
'---',
'',
'# GSD State',
'# MSD State',
'',
'## Current Position',
'',
@@ -1777,13 +1777,13 @@ describe('#3354 buildStateFrontmatter total_phases — milestoned-but-unbounded
);
seedPhaseDirs(tmpDir, [1, 2, 3, 4]);
const recordResult = runGsdTools(
const recordResult = runMsdTools(
['state', 'record-session', '--stopped-at', 'Phase 1, Plan 1', '--resume-file', 'none'],
tmpDir,
);
assert.ok(recordResult.success, `state record-session failed: ${recordResult.error}`);
const jsonResult = runGsdTools(['state', 'json', '--raw'], tmpDir);
const jsonResult = runMsdTools(['state', 'json', '--raw'], tmpDir);
assert.ok(jsonResult.success, `state json --raw failed: ${jsonResult.error}`);
const out = JSON.parse(jsonResult.output);
@@ -1909,7 +1909,7 @@ describe('#3573 total_phases — roadmap absent with an asserted milestone', ()
const rec = recordSession(tmpDir);
assert.ok(rec.exitCode === 0, `state record-session failed: ${rec.stderr}`);
const jsonResult = runGsdTools(['state', 'json', '--raw'], tmpDir);
const jsonResult = runMsdTools(['state', 'json', '--raw'], tmpDir);
assert.ok(jsonResult.success, `state json --raw failed: ${jsonResult.error}`);
const out = JSON.parse(jsonResult.output);
assert.strictEqual(
@@ -1977,7 +1977,7 @@ describe('#3573 total_phases — roadmap absent with an asserted milestone', ()
// resyncing write, silently clobbering stored values under the exact
// condition #3354 established the scan is untrustworthy for. Extend the
// withhold-then-fall-back-to-stored pattern to all three siblings.
// Matrix: .gsd/bug/fix-4094-milestone-withhold-all-counters/50-test-matrix.md
// Matrix: .msd/bug/fix-4094-milestone-withhold-all-counters/50-test-matrix.md
// ─────────────────────────────────────────────────────────────────────────────
describe('#4094 milestone-unbounded withhold — all four progress counters', () => {
@@ -1988,10 +1988,10 @@ describe('#4094 milestone-unbounded withhold — all four progress counters', ()
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 { runNode } = require('./helpers/process-seam.cjs');
const { TOOLS_PATH, TEST_ENV_BASE } = require('./helpers.cjs');
const { splitLines } = require('../gsd-core/bin/lib/text-lines.cjs');
const { splitLines } = require('../msd-core/bin/lib/text-lines.cjs');
/** Seed `.planning/phases/<padded>-phase-<n>` — local copy (the block-scoped seeder at the top of this file is not reachable from here). */
function seedPhaseDirs(dir, nums) {
@@ -2034,7 +2034,7 @@ describe('#4094 milestone-unbounded withhold — all four progress counters', ()
const { totalPhases, completedPhases, totalPlans, completedPlans } = counters;
const fm = [
'---',
'gsd_state_version: 1.0',
'msd_state_version: 1.0',
`milestone: ${milestone}`,
'milestone_name: Unbounded',
'current_phase: "01"',
@@ -2050,7 +2050,7 @@ describe('#4094 milestone-unbounded withhold — all four progress counters', ()
fm.push('progress:');
for (const [k, v] of rows) fm.push(` ${k}: ${v}`);
}
fm.push('---', '', '# GSD State', '', '## Current Position', '', '**Current Phase:** 01', '**Status:** Executing', '');
fm.push('---', '', '# MSD State', '', '## Current Position', '', '**Current Phase:** 01', '**Status:** Executing', '');
return fm.join('\n');
}
@@ -2078,7 +2078,7 @@ describe('#4094 milestone-unbounded withhold — all four progress counters', ()
}
function stateJson(dir) {
const jsonResult = runGsdTools(['state', 'json', '--raw'], dir);
const jsonResult = runMsdTools(['state', 'json', '--raw'], dir);
assert.ok(jsonResult.success, `state json --raw failed: ${jsonResult.error}`);
return JSON.parse(jsonResult.output);
}
@@ -2308,7 +2308,7 @@ describe('#4094 milestone-unbounded withhold — all four progress counters', ()
// unbounded branch's flat test, so the single-section shape takes the #3354
// withhold (stored value preserved + warning) instead of substituting the
// whole-document count. Controls pin what must NOT change.
// Matrix: .gsd/bug/fix-3642-milestone-sectioning-leak/50-test-matrix.md
// Matrix: .msd/bug/fix-3642-milestone-sectioning-leak/50-test-matrix.md
// ─────────────────────────────────────────────────────────────────────────────
describe('#3642 — single-section leak controls and seam pins', () => {
@@ -2316,7 +2316,7 @@ describe('#3642 — single-section leak controls and seam pins', () => {
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');
// Compact local builders (this file's sections are deliberately
// self-contained; the #3204 suite's identical builders live in its own
@@ -2333,7 +2333,7 @@ describe('#3642 — single-section leak controls and seam pins', () => {
function stateMd({ milestone, totalPhases }) {
return [
'---',
'gsd_state_version: 1.0',
'msd_state_version: 1.0',
`milestone: ${milestone}`,
'milestone_name: M',
'current_phase: "01"',
@@ -2346,7 +2346,7 @@ describe('#3642 — single-section leak controls and seam pins', () => {
' percent: 0',
'---',
'',
'# GSD State',
'# MSD State',
'',
'## Current Position',
'',
@@ -2357,12 +2357,12 @@ describe('#3642 — single-section leak controls and seam pins', () => {
}
function writeTotalAfterRecord(tmpDir) {
const recordResult = runGsdTools(
const recordResult = runMsdTools(
['state', 'record-session', '--stopped-at', 'Phase 1, Plan 1', '--resume-file', 'none'],
tmpDir,
);
assert.ok(recordResult.success, `state record-session failed: ${recordResult.error}`);
const jsonResult = runGsdTools(['state', 'json', '--raw'], tmpDir);
const jsonResult = runMsdTools(['state', 'json', '--raw'], tmpDir);
assert.ok(jsonResult.success, `state json --raw failed: ${jsonResult.error}`);
return Number(JSON.parse(jsonResult.output).progress.total_phases);
}
@@ -2370,7 +2370,7 @@ describe('#3642 — single-section leak controls and seam pins', () => {
let tmpDir;
beforeEach(() => {
tmpDir = createTempProject('gsd-3642-');
tmpDir = createTempProject('msd-3642-');
});
afterEach(() => {
@@ -2405,7 +2405,7 @@ describe('#3642 — single-section leak controls and seam pins', () => {
});
test('seam pins: hasAnyMilestoneSection counts >=1; hasMilestoneSectioning stays >=2', () => {
const roadmapParser = require(path.join(__dirname, '..', 'gsd-core', 'bin', 'lib', 'roadmap-parser.cjs'));
const roadmapParser = require(path.join(__dirname, '..', 'msd-core', 'bin', 'lib', 'roadmap-parser.cjs'));
assert.strictEqual(typeof roadmapParser.hasAnyMilestoneSection, 'function',
'hasAnyMilestoneSection must be exported for buildStateFrontmatter (#3642)');
const one = ['# Roadmap', '', '## v2.0', '## Phase 1: One'].join('\n');
@@ -2431,7 +2431,7 @@ describe('#3642 — single-section leak controls and seam pins', () => {
// ─────────────────────────────────────────────────────────────────────────────
describe('#4186: normalizeStateStatus anchored status vocabulary — substring traps', () => {
const { normalizeStateStatus } = require('../gsd-core/bin/lib/state-document.cjs');
const { normalizeStateStatus } = require('../msd-core/bin/lib/state-document.cjs');
// Row 1 — the failing-first regression: a `.planning/` path inside Italian
// prose must NOT land on `planning` (the trigger word lives in the
@@ -2494,7 +2494,7 @@ describe('#4186: normalizeStateStatus anchored status vocabulary — substring t
});
describe('#4186: normalizeStateStatus anchored status vocabulary — documented vocabulary still normalizes', () => {
const { normalizeStateStatus } = require('../gsd-core/bin/lib/state-document.cjs');
const { normalizeStateStatus } = require('../msd-core/bin/lib/state-document.cjs');
test('rows 13-15: variable handler-written phase statuses (case/whitespace variants)', () => {
assert.strictEqual(normalizeStateStatus('Executing Phase 5', null), 'executing');