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

@@ -23,9 +23,9 @@ const fs = require('node:fs');
const path = require('node:path');
const fc = require('fast-check');
const roadmapParser = require('../gsd-core/bin/lib/roadmap-parser.cjs');
const { SCOPE } = require('../gsd-core/bin/lib/planning-scope.cjs');
const { createTempProject, cleanup, runGsdTools } = require('./helpers.cjs');
const roadmapParser = require('../msd-core/bin/lib/roadmap-parser.cjs');
const { SCOPE } = require('../msd-core/bin/lib/planning-scope.cjs');
const { createTempProject, cleanup, runMsdTools } = require('./helpers.cjs');
const {
stripShippedMilestones,
@@ -391,7 +391,7 @@ describe('roadmap-parser: extractCurrentMilestone', () => {
});
test('#2947 — roadmap.analyze on the issue fixture reports phase_count 2 (end-to-end)', () => {
writeState(tmpDir, { milestone: 'v9.0', gsd_state_version: '1.0' });
writeState(tmpDir, { milestone: 'v9.0', msd_state_version: '1.0' });
const content = [
'# ROADMAP',
'',
@@ -420,7 +420,7 @@ describe('roadmap-parser: extractCurrentMilestone', () => {
].join('\n');
writeRoadmap(tmpDir, content);
const result = runGsdTools(['query', 'roadmap.analyze', '--raw'], tmpDir);
const result = runMsdTools(['query', 'roadmap.analyze', '--raw'], tmpDir);
assert.ok(result.success, `roadmap.analyze should succeed; got: ${result.error}`);
const payload = JSON.parse(result.output);
assert.strictEqual(payload.phase_count, 2, `expected phase_count 2, got ${payload.phase_count} (phases dropped — #2947)`);
@@ -874,7 +874,7 @@ describe('roadmap-parser: getMilestoneInfo #2135 — milestone_name clobber', ()
afterEach(() => { cleanup(tmpDir); });
test('case A: 🚧 bullet quoting a nameless ## heading in backticks', () => {
writeState(tmpDir, { gsd_state_version: '1.0', milestone: 'v1.8' });
writeState(tmpDir, { msd_state_version: '1.0', milestone: 'v1.8' });
writeRoadmap(tmpDir, [
'# Roadmap',
'',
@@ -893,7 +893,7 @@ describe('roadmap-parser: getMilestoneInfo #2135 — milestone_name clobber', ()
});
test('case B: nameless ## heading + 🚧 marker carries the real name', () => {
writeState(tmpDir, { gsd_state_version: '1.0', milestone: 'v1.9' });
writeState(tmpDir, { msd_state_version: '1.0', milestone: 'v1.9' });
writeRoadmap(tmpDir, [
'## v1.9 — Active Milestone',
'',
@@ -908,7 +908,7 @@ describe('roadmap-parser: getMilestoneInfo #2135 — milestone_name clobber', ()
});
test('case C: canonical ## vX.Y: Name (no regression)', () => {
writeState(tmpDir, { gsd_state_version: '1.0', milestone: 'v2.0' });
writeState(tmpDir, { msd_state_version: '1.0', milestone: 'v2.0' });
writeRoadmap(tmpDir, '## v2.0: The Big Launch\n### Phase 1: Setup\n');
const info = getMilestoneInfo(tmpDir);
assert.strictEqual(info.scope, SCOPE.COMPLETE);
@@ -917,7 +917,7 @@ describe('roadmap-parser: getMilestoneInfo #2135 — milestone_name clobber', ()
});
test('case D: canonical ## vX.Y — Name (em-dash delimiter stripped)', () => {
writeState(tmpDir, { gsd_state_version: '1.0', milestone: 'v2.5' });
writeState(tmpDir, { msd_state_version: '1.0', milestone: 'v2.5' });
writeRoadmap(tmpDir, '## v2.5 — Galaxy Release\n### Phase 1: Start\n');
const info = getMilestoneInfo(tmpDir);
assert.strictEqual(info.scope, SCOPE.COMPLETE);
@@ -926,7 +926,7 @@ describe('roadmap-parser: getMilestoneInfo #2135 — milestone_name clobber', ()
});
test('case E: 🚧 bullet only, no ## heading (no regression)', () => {
writeState(tmpDir, { gsd_state_version: '1.0', milestone: 'v1.5' });
writeState(tmpDir, { msd_state_version: '1.0', milestone: 'v1.5' });
writeRoadmap(tmpDir, 'Some intro text.\n\n- 🚧 **v1.5 Quick Fix** — minor\n');
const info = getMilestoneInfo(tmpDir);
assert.strictEqual(info.scope, SCOPE.COMPLETE);
@@ -935,7 +935,7 @@ describe('roadmap-parser: getMilestoneInfo #2135 — milestone_name clobber', ()
});
test('anchored regex never matches a ## heading quoted inside backticks mid-line', () => {
writeState(tmpDir, { gsd_state_version: '1.0', milestone: 'v3.0' });
writeState(tmpDir, { msd_state_version: '1.0', milestone: 'v3.0' });
writeRoadmap(tmpDir, [
'# Roadmap',
'',
@@ -968,7 +968,7 @@ describe('roadmap-parser: getMilestoneInfo #4134 — name-then-version heading',
test('#4134 — name-then-version H1 never yields a punctuation-fragment name (rule 6: TRUNCATED, name null)', () => {
writeState(tmpDir, { milestone: 'v1.13' });
writeRoadmap(tmpDir, [
'# Roadmap: GSD Core — Native OMP Runtime Support (v1.13)',
'# Roadmap: MSD Core — Native OMP Runtime Support (v1.13)',
'',
'### Phase 1: Runtime Adapter Interface',
].join('\n'));
@@ -981,7 +981,7 @@ describe('roadmap-parser: getMilestoneInfo #4134 — name-then-version heading',
test('#4134 — ROADMAP-only fallback path also refuses the ")" fragment', () => {
// No STATE.md: the first open milestone heading supplies the version.
writeRoadmap(tmpDir, [
'# Roadmap: GSD Core — Native OMP Runtime Support (v1.13)',
'# Roadmap: MSD Core — Native OMP Runtime Support (v1.13)',
'',
'### Phase 1: Runtime Adapter Interface',
].join('\n'));
@@ -1232,7 +1232,7 @@ describe('roadmap-parser: getMilestonePhaseFilter', () => {
// #2562 added a trailing optional `ws` param. Every pre-existing call site in
// the codebase passes 1–3 args, so what has to hold is that omitting the 4th
// is INDISTINGUISHABLE from the prior resolution — including its
// `GSD_WORKSTREAM` env fallback. Characterises the legacy call surface
// `MSD_WORKSTREAM` env fallback. Characterises the legacy call surface
// directly; it does not stand in for coverage of the individual callers.
test('#2562: omitting the ws param preserves the prior path resolution exactly', () => {
const ROADMAP = ['## v1.0: Launch', '### Phase 1: Setup', '**Goal:** setup'].join('\n');
@@ -1250,22 +1250,22 @@ describe('roadmap-parser: getMilestonePhaseFilter', () => {
}
});
test('#2562: the GSD_WORKSTREAM env fallback still resolves when ws is omitted', () => {
test('#2562: the MSD_WORKSTREAM env fallback still resolves when ws is omitted', () => {
const wsRoadmap = ['## v1.0: WS', '### Phase 7: Only', '**Goal:** only'].join('\n');
const wsDir = path.join(tmpDir, '.planning', 'workstreams', 'alpha');
fs.mkdirSync(wsDir, { recursive: true });
fs.writeFileSync(path.join(wsDir, 'ROADMAP.md'), wsRoadmap);
writeRoadmap(tmpDir, ['## v1.0: Root', '### Phase 1: Setup', '**Goal:** setup'].join('\n'));
const previous = process.env.GSD_WORKSTREAM;
process.env.GSD_WORKSTREAM = 'alpha';
const previous = process.env.MSD_WORKSTREAM;
process.env.MSD_WORKSTREAM = 'alpha';
try {
const filter = getMilestonePhaseFilter(tmpDir);
assert.strictEqual(filter('07-only'), true, 'env fallback must still reach the workstream roadmap');
assert.strictEqual(filter('01-setup'), false, 'and must not read the root roadmap');
} finally {
if (previous === undefined) delete process.env.GSD_WORKSTREAM;
else process.env.GSD_WORKSTREAM = previous;
if (previous === undefined) delete process.env.MSD_WORKSTREAM;
else process.env.MSD_WORKSTREAM = previous;
}
});
@@ -1521,12 +1521,12 @@ describe('roadmap-parser: getMilestonePhaseFilter', () => {
assert.strictEqual(filter('01-setup'), true, 'phase 1 dir matches');
});
test('adversarial: bracket-prefixed phase heading ### [GSD] Phase 2-01:', () => {
test('adversarial: bracket-prefixed phase heading ### [MSD] Phase 2-01:', () => {
writeState(tmpDir, { milestone: 'v2.0' });
writeRoadmap(tmpDir, [
'## v2.0: Bracket',
'### [GSD] Phase 2-01: Setup',
'### [GSD] Phase 2-02: Build',
'### [MSD] Phase 2-01: Setup',
'### [MSD] Phase 2-02: Build',
].join('\n'));
const filter = getMilestonePhaseFilter(tmpDir);
@@ -1538,7 +1538,7 @@ describe('roadmap-parser: getMilestonePhaseFilter', () => {
// `^([A-Za-z][A-Za-z0-9]*(?:-[A-Za-z0-9]+)*)` that swallowed the whole
// hyphenated directory name (A-tool-output-contract → captured
// "A-tool-output-contract", not "A"). Every letter-named phase directory
// (GSD's own Phase A:..Phase L: convention; ADR-612 first-class non-numeric
// (MSD's own Phase A:..Phase L: convention; ADR-612 first-class non-numeric
// IDs) was silently excluded and milestone counts were fabricated over
// whatever numeric dir survived. The fix is a segment-boundary membership
// test: a dir belongs if it equals a declared phase ID or begins with id + "-".
@@ -1757,7 +1757,7 @@ const assert = require('node:assert/strict');
const fs = require('fs');
const path = require('path');
const { createTempProject, cleanup } = require('./helpers.cjs');
const { getMilestonePhaseFilter } = require('../gsd-core/bin/lib/roadmap-parser.cjs');
const { getMilestonePhaseFilter } = require('../msd-core/bin/lib/roadmap-parser.cjs');
describe('bug #2554 — getMilestonePhaseFilter decimal phase dirs', () => {
let tmpDir;
@@ -1847,7 +1847,7 @@ const assert = require('node:assert/strict');
const fs = require('fs');
const path = require('path');
const os = require('os');
const { runGsdTools, cleanup, absPlanningPath } = require('./helpers.cjs');
const { runMsdTools, cleanup, absPlanningPath } = require('./helpers.cjs');
// ---------------------------------------------------------------------------
// Shared fixture content
@@ -1889,7 +1889,7 @@ function createBareProject() {
// process.cwd()-anchored output — macOS's tmpdir is a symlink
// (/var/... -> /private/var/...) that a spawned child resolves via
// realpath but a bare mkdtempSync() does not. No-op on Linux (no symlink).
const tmpDir = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-test-730-')));
const tmpDir = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'msd-test-730-')));
fs.mkdirSync(path.join(tmpDir, '.planning'), { recursive: true });
return tmpDir;
}
@@ -1916,7 +1916,7 @@ describe('bug #730 — milestone (Phase Details) section scope resolution', () =
// per-milestone "(Phase Details)" section
// -------------------------------------------------------------------------
test('init phase-op resolves a current-milestone phase defined only under its (Phase Details) section', () => {
const r = runGsdTools('init phase-op 2', dir);
const r = runMsdTools('init phase-op 2', dir);
assert.ok(r.success, `init phase-op 2 failed: ${r.error}`);
const out = JSON.parse(r.output);
@@ -1931,7 +1931,7 @@ describe('bug #730 — milestone (Phase Details) section scope resolution', () =
// "## Phase Details" section — no regression
// -------------------------------------------------------------------------
test('init phase-op still resolves a first-milestone phase (no regression on flat Phase Details)', () => {
const r = runGsdTools('init phase-op 1', dir);
const r = runMsdTools('init phase-op 1', dir);
assert.ok(r.success, `init phase-op 1 failed: ${r.error}`);
const out = JSON.parse(r.output);
@@ -1944,7 +1944,7 @@ describe('bug #730 — milestone (Phase Details) section scope resolution', () =
// directly before any phases/ dir exists
// -------------------------------------------------------------------------
test('getRoadmapPhaseInternal resolves the current-milestone phase directly before any dir exists', () => {
const { getRoadmapPhaseInternal } = require('../gsd-core/bin/lib/roadmap-parser.cjs');
const { getRoadmapPhaseInternal } = require('../msd-core/bin/lib/roadmap-parser.cjs');
const res = getRoadmapPhaseInternal(dir, '2');
assert.ok(res !== null && res !== undefined, `getRoadmapPhaseInternal returned null/undefined for phase 2`);
@@ -1965,7 +1965,7 @@ describe('bug #730 — milestone (Phase Details) section scope resolution', () =
// disturb the shared beforeEach/afterEach fixture used by tests 1–3.
// -------------------------------------------------------------------------
test('validate health raises W006 for a started current-milestone phase defined under (Phase Details) with no directory', () => {
const localDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-test-730-t4-'));
const localDir = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-test-730-t4-'));
try {
const planning = path.join(localDir, '.planning');
fs.mkdirSync(planning, { recursive: true });
@@ -1990,7 +1990,7 @@ describe('bug #730 — milestone (Phase Details) section scope resolution', () =
// Phase 2 has NO directory — that's the missing-dir condition under test.
fs.mkdirSync(path.join(planning, 'phases', '01-setup'), { recursive: true });
const result = runGsdTools(['validate', 'health'], localDir);
const result = runMsdTools(['validate', 'health'], localDir);
const payload = JSON.parse(result.output);
const warnings = payload.warnings || [];
@@ -2017,7 +2017,7 @@ describe('bug #730 — milestone (Phase Details) section scope resolution', () =
// -------------------------------------------------------------------------
test('init phase-op resolves the latest milestone phase in a 3-milestone roadmap', () => {
// #2376 macOS fix: see createBareProject() above.
const localDir = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-test-730-t5-')));
const localDir = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'msd-test-730-t5-')));
try {
const planning = path.join(localDir, '.planning');
fs.mkdirSync(planning, { recursive: true });
@@ -2034,7 +2034,7 @@ describe('bug #730 — milestone (Phase Details) section scope resolution', () =
'utf-8',
);
const r = runGsdTools('init phase-op 3', localDir);
const r = runMsdTools('init phase-op 3', localDir);
assert.ok(r.success, `init phase-op 3 failed: ${r.error}`);
const out = JSON.parse(r.output);
@@ -2053,7 +2053,7 @@ describe('bug #730 — milestone (Phase Details) section scope resolution', () =
// -------------------------------------------------------------------------
test('init phase-op anchors Phase Details to the selected sub-milestone, not a closed same-prefix sibling', () => {
// #2376 macOS fix: see createBareProject() above.
const localDir = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-test-730-t6-')));
const localDir = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'msd-test-730-t6-')));
try {
const planning = path.join(localDir, '.planning');
fs.mkdirSync(planning, { recursive: true });
@@ -2100,7 +2100,7 @@ describe('bug #730 — milestone (Phase Details) section scope resolution', () =
'utf-8',
);
const r = runGsdTools('init phase-op 2', localDir);
const r = runMsdTools('init phase-op 2', localDir);
assert.ok(r.success, `init phase-op 2 failed: ${r.error}`);
const out = JSON.parse(r.output);
@@ -2131,7 +2131,7 @@ describe('bug #730 — milestone (Phase Details) section scope resolution', () =
//
// roadmap.cjs countPhasePlansAndSummaries() used to filter plan files with:
// f.endsWith('-PLAN.md') || f === 'PLAN.md'
// This misses the {N}-PLAN-{NN}-{slug}.md layout that gsd-plan-phase
// This misses the {N}-PLAN-{NN}-{slug}.md layout that msd-plan-phase
// actually writes (e.g. 5-PLAN-01-setup-database.md), ending in -database.md.
// Result: init manager returned plan_count=0 and disk_status='discussed' for
// fully-planned phases, triggering unnecessary background planner agents.
@@ -2149,7 +2149,7 @@ const { createTempDir, cleanup } = require('./helpers.cjs');
const ROOT = path.join(__dirname, '..');
// Require the module under test directly
const planScanLib = path.join(ROOT, 'gsd-core', 'bin', 'lib', 'plan-scan.cjs');
const planScanLib = path.join(ROOT, 'msd-core', 'bin', 'lib', 'plan-scan.cjs');
// We test countPhasePlansAndSummaries indirectly via getManagerInfo since
// it is not exported. We build a real phaseDir on disk and call the full
@@ -2249,8 +2249,8 @@ 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 planScan = require('../gsd-core/bin/lib/plan-scan.cjs');
const { runMsdTools, createTempProject, cleanup } = require('./helpers.cjs');
const planScan = require('../msd-core/bin/lib/plan-scan.cjs');
const { isRootPlanFile, scanPhasePlans } = planScan;
describe('isRootPlanFile does not count legacy summaries as plans (#500 RC2)', () => {
@@ -2293,7 +2293,7 @@ describe('state planned-phase preserves curated milestone progress.* (#500 RC1)'
// would derive (disk has only one near-empty phase dir). The bug rebuilds
// progress.* from that disk snapshot, trampling these values.
const STATE = `---
gsd_state_version: 1.0
msd_state_version: 1.0
milestone: v3.0
milestone_name: Active
status: in_progress
@@ -2357,7 +2357,7 @@ Last activity: TBD
}
test('planned-phase updates per-phase body fields but leaves milestone progress.* untouched', () => {
const result = runGsdTools(['state', 'planned-phase', '--phase', '2', '--plans', '3'], tmpDir);
const result = runMsdTools(['state', 'planned-phase', '--phase', '2', '--plans', '3'], tmpDir);
assert.equal(result.success, true, result.error || result.output);
// The command did its real job: per-phase "Total Plans in Phase" was set.
@@ -2408,7 +2408,7 @@ const os = require('os');
const { cleanup } = require('./helpers.cjs');
// Helper under test — must exist at this path (GREEN phase wires it up)
const scanPhasePlans = require('../gsd-core/bin/lib/plan-scan.cjs');
const scanPhasePlans = require('../msd-core/bin/lib/plan-scan.cjs');
// ---------------------------------------------------------------------------
// Fixture helpers
@@ -2429,7 +2429,7 @@ function touch(dir, ...filenames) {
}
beforeEach(() => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-plan-scan-'));
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-plan-scan-'));
});
afterEach(() => {
@@ -2499,7 +2499,7 @@ describe('scanPhasePlans — flat layout', () => {
test('extended-layout root file (5-PLAN-01-setup.md style)', () => {
// roadmap.cjs isPlanFile explicitly matches any .md with PLAN in name at root
// (not just ending with -PLAN.md). The canonical helper must too.
// e.g. gsd-plan-phase writes "5-PLAN-01-setup.md".
// e.g. msd-plan-phase writes "5-PLAN-01-setup.md".
const dir = phaseDir();
// The summary for this file follows the canonical *-SUMMARY.md suffix convention.
touch(dir, '3-PLAN-01-setup.md', '3-01-SUMMARY.md');
@@ -2850,7 +2850,7 @@ describe('scanPhasePlans — superseded plans (#2349)', () => {
const fc = require('fast-check');
fc.assert(
fc.property(fc.integer({ min: 1, max: 8 }), fc.integer({ min: 0, max: 5 }), (n, k) => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-plan-scan-prop-'));
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-plan-scan-prop-'));
try {
for (let i = 1; i <= n; i++) {
const idx = String(i).padStart(2, '0');
@@ -2885,7 +2885,7 @@ describe('scanPhasePlans — superseded plans (#2349)', () => {
*
* Loads each fixture in `tests/fixtures/adversarial/roadmap/` as the
* project's `.planning/ROADMAP.md` and pins invariants on the public
* `gsd-tools roadmap get-phase <N>` surface — which routes through the
* `msd-tools roadmap get-phase <N>` surface — which routes through the
* SDK bridge when available and the CJS handler otherwise.
*
* Per CONTRIBUTING.md §"Testing Standards / Parser and project-file
@@ -2934,7 +2934,7 @@ function projectWithFixture(t, fixtureName) {
}
/**
* Run `gsd-tools roadmap get-phase <N>` and parse the JSON payload.
* Run `msd-tools roadmap get-phase <N>` and parse the JSON payload.
* Returns `{ ok, exit, parsed, raw }` so tests can assert on either
* the exit code or the structured payload.
*/
@@ -2987,7 +2987,7 @@ describe('feat-3594: roadmap parser and fenced-code-block headings (#2787)', ()
path.join(projectDir, '.planning', 'STATE.md'),
[
'---',
'gsd_state_version: 1.0',
'msd_state_version: 1.0',
'milestone: v1.1',
'status: planning',
'---',
@@ -3163,14 +3163,14 @@ describe('feat-3594: roadmap parser does not crash on ANY corpus fixture', () =>
// only within the active milestone so they cannot touch a backticked prose
// literal, a Backlog entry, or a same-numbered phase in a shipped milestone.
// This tests the scoping helper the fix rests on (the mutators' command path is
// covered by the existing phase-complete suite; gsd-test confirms no regression).
// covered by the existing phase-complete suite; msd-test confirms no regression).
{
const { describe: d3, test: t3 } = require('node:test');
const a3 = require('node:assert/strict');
const fs3 = require('node:fs');
const path3 = require('node:path');
const { createTempProject: ctp3, cleanup: cu3 } = require('./helpers.cjs');
const rp3 = require('../gsd-core/bin/lib/roadmap-parser.cjs');
const rp3 = require('../msd-core/bin/lib/roadmap-parser.cjs');
d3('#2200 currentMilestoneRawRanges — scopes writes to the active milestone', () => {
t3('the active window contains the active phase bullet, excludes Backlog + prose + shipped', () => {
@@ -3223,7 +3223,7 @@ describe('feat-3594: roadmap parser does not crash on ANY corpus fixture', () =>
const fs2 = require('node:fs');
const path2 = require('node:path');
const { createTempProject: ctp2, cleanup: cu2 } = require('./helpers.cjs');
const rp2 = require('../gsd-core/bin/lib/roadmap-parser.cjs');
const rp2 = require('../msd-core/bin/lib/roadmap-parser.cjs');
const writeRoadmap2 = (d, c) => fs2.writeFileSync(path2.join(d, '.planning', 'ROADMAP.md'), c);
d2('#2199 roadmap bullet/em-dash phase resolution', () => {
@@ -3344,12 +3344,12 @@ describe('feat-3594: roadmap parser does not crash on ANY corpus fixture', () =>
// silently pass with zero coverage in root Docker/CI.
describe('#1881 unreadable ROADMAP vs absent ROADMAP', () => {
const scp = require('../gsd-core/bin/lib/shell-command-projection.cjs');
const scp = require('../msd-core/bin/lib/shell-command-projection.cjs');
const {
UNUSABLE_REASON,
_resetUnusableInputWarningsForTests,
_unusableInputEmissionCountForTests,
} = require('../gsd-core/bin/lib/unusable-input.cjs');
} = require('../msd-core/bin/lib/unusable-input.cjs');
const HEALTHY = [
'# Roadmap',
@@ -3363,7 +3363,7 @@ describe('#1881 unreadable ROADMAP vs absent ROADMAP', () => {
/** Write a project with the given ROADMAP content (or none when null). */
function project(t, roadmap) {
const dir = createTempProject('gsd-1881-');
const dir = createTempProject('msd-1881-');
t.after(() => cleanup(dir));
const planning = path.join(dir, '.planning');
fs.mkdirSync(planning, { recursive: true });
@@ -3598,19 +3598,19 @@ describe('#1881 unreadable ROADMAP vs absent ROADMAP', () => {
test('neither lookup throws when the planning path itself cannot be resolved', (t) => {
// The regression this pair exists to catch. planningDir throws a plain Error for an
// invalid GSD_WORKSTREAM segment. Resolving it OUTSIDE the try -- which is what naming
// invalid MSD_WORKSTREAM segment. Resolving it OUTSIDE the try -- which is what naming
// the file for the diagnostic naively required -- let that escape uncaught, crashing
// every caller of getMilestoneInfo for a workstream name containing a slash, and
// breaking the invariant #2245 relies on. The earlier 'does not throw' cases inject
// only through platformReadSync and so could never have caught it.
_resetUnusableInputWarningsForTests();
const dir = project(t, HEALTHY);
const previous = process.env.GSD_WORKSTREAM;
const previous = process.env.MSD_WORKSTREAM;
t.after(() => {
if (previous === undefined) delete process.env.GSD_WORKSTREAM;
else process.env.GSD_WORKSTREAM = previous;
if (previous === undefined) delete process.env.MSD_WORKSTREAM;
else process.env.MSD_WORKSTREAM = previous;
});
process.env.GSD_WORKSTREAM = 'evil/../thing';
process.env.MSD_WORKSTREAM = 'evil/../thing';
let info, phase;
const emitted = emissionsDuring(() => {
assert.doesNotThrow(() => { info = getMilestoneInfo(dir); });
@@ -3645,8 +3645,8 @@ describe('#1881 unreadable ROADMAP vs absent ROADMAP', () => {
const a3 = require('node:assert/strict');
const fs3 = require('node:fs');
const path3 = require('node:path');
const { createTempProject: ctp3, cleanup: cu3, runGsdTools: rgt3 } = require('./helpers.cjs');
const rp3 = require('../gsd-core/bin/lib/roadmap-parser.cjs');
const { createTempProject: ctp3, cleanup: cu3, runMsdTools: rgt3 } = require('./helpers.cjs');
const rp3 = require('../msd-core/bin/lib/roadmap-parser.cjs');
const writeRoadmap3 = (d, c) => fs3.writeFileSync(path3.join(d, '.planning', 'ROADMAP.md'), c);
const TABLE_ROADMAP = [