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:
@@ -27,7 +27,7 @@ const LONG_KEY_CLI_TIMEOUT_MS = 8000;
|
||||
// In-process invocation, not execFileSync: cmdConfigGet is a pure CJS
|
||||
// function reachable without spawning `node` as a child. The prior
|
||||
// execFileSync(..., { timeout: 5000 }) raced a real subprocess's startup
|
||||
// (full node boot + gsd-tools.cjs's large eager require graph — capability
|
||||
// (full node boot + msd-tools.cjs's large eager require graph — capability
|
||||
// registry, phase/roadmap/agent/check/task routers, verify.cjs,
|
||||
// cli-skew-check, findProjectRoot, etc.) against a fixed 5s wall clock, with
|
||||
// no retry. Under Docker host contention that wall clock loses
|
||||
@@ -35,20 +35,20 @@ const LONG_KEY_CLI_TIMEOUT_MS = 8000;
|
||||
// defect. bin/lib/config.cjs requires none of that dispatcher machinery, so
|
||||
// calling cmdConfigGet directly removes the subprocess-spawn cost and the
|
||||
// wall-clock race entirely: no timeout of any size can flake this.
|
||||
const config = require(path.join(__dirname, '..', 'gsd-core', 'bin', 'lib', 'config.cjs'));
|
||||
const config = require(path.join(__dirname, '..', 'msd-core', 'bin', 'lib', 'config.cjs'));
|
||||
// io.cjs owns error()/output() and the JSON-error-mode toggle. cmdConfigGet's `error`
|
||||
// is bound to io.error at load, so we drive io directly to (a) get structured stderr
|
||||
// we can assert a typed `reason` on, and (b) restore the mode after each error probe.
|
||||
const io = require(path.join(__dirname, '..', 'gsd-core', 'bin', 'lib', 'io.cjs'));
|
||||
const io = require(path.join(__dirname, '..', 'msd-core', 'bin', 'lib', 'io.cjs'));
|
||||
// ADR-3889: error() throws ExitError instead of calling process.exit()
|
||||
// directly. The `runExpectError`/`runInProcessAt`/`runScopedExpectError`
|
||||
// harnesses below now catch ExitError directly rather than mocking
|
||||
// process.exit with a throwable sentinel — mocking process.exit no longer
|
||||
// observes anything, since error() never calls it.
|
||||
const { ExitError } = require(path.join(__dirname, '..', 'gsd-core', 'bin', 'lib', 'cli-exit.cjs'));
|
||||
const { ExitError } = require(path.join(__dirname, '..', 'msd-core', 'bin', 'lib', 'cli-exit.cjs'));
|
||||
|
||||
/**
|
||||
* cmdConfigGet's error() path (gsd-core/bin/lib/io.cjs) now throws ExitError
|
||||
* cmdConfigGet's error() path (msd-core/bin/lib/io.cjs) now throws ExitError
|
||||
* directly (ADR-3889) instead of calling process.exit(1). The harnesses below
|
||||
* catch that ExitError directly — no process.exit mock / throwable sentinel
|
||||
* is needed anymore.
|
||||
@@ -77,7 +77,7 @@ function captureFdWrite(fd, fn) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a CLI-style config-get argv (mirrors gsd-core/bin/gsd-tools.cjs's
|
||||
* Parse a CLI-style config-get argv (mirrors msd-core/bin/msd-tools.cjs's
|
||||
* 'config-get' case: key is args[1], optional --default <value>, optional
|
||||
* --raw) into cmdConfigGet's positional params. Keeps the test bodies below
|
||||
* expressed in the same CLI-args vocabulary they always were.
|
||||
@@ -100,7 +100,7 @@ describe('config-get --default flag (#1893)', () => {
|
||||
let planningDir;
|
||||
|
||||
beforeEach(() => {
|
||||
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-config-default-'));
|
||||
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-config-default-'));
|
||||
planningDir = path.join(tmpDir, '.planning');
|
||||
fs.mkdirSync(planningDir, { recursive: true });
|
||||
});
|
||||
@@ -234,7 +234,7 @@ describe('config-get --default flag (#1893)', () => {
|
||||
// erroring.
|
||||
// ────────────────────────────────────────────────────────────────────────
|
||||
{
|
||||
const configSchemaMod = require(path.join(__dirname, '..', 'gsd-core', 'bin', 'lib', 'config-schema.cjs'));
|
||||
const configSchemaMod = require(path.join(__dirname, '..', 'msd-core', 'bin', 'lib', 'config-schema.cjs'));
|
||||
// Repo idiom for property tests (matches config-schema.property.test.cjs):
|
||||
// require the shared seeded/bounded wrapper, not bare 'fast-check', so this
|
||||
// property run is deterministic across CI (seed 42) rather than fuzzing with
|
||||
@@ -246,7 +246,7 @@ describe('config-get --default flag (#1893)', () => {
|
||||
let planningDir;
|
||||
|
||||
beforeEach(() => {
|
||||
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-config-2256-'));
|
||||
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-config-2256-'));
|
||||
planningDir = path.join(tmpDir, '.planning');
|
||||
});
|
||||
|
||||
@@ -551,7 +551,7 @@ describe('config-get --default flag (#1893)', () => {
|
||||
leafValueArb,
|
||||
fc.object({ maxDepth: 3 }),
|
||||
(keyPath, plant, leafValue, backgroundObj) => {
|
||||
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-proto-prop-'));
|
||||
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-proto-prop-'));
|
||||
try {
|
||||
fs.mkdirSync(path.join(dir, '.planning'), { recursive: true });
|
||||
|
||||
@@ -644,7 +644,7 @@ describe('config-get --default flag (#1893)', () => {
|
||||
/**
|
||||
* Regression test for bug #2798
|
||||
*
|
||||
* `gsd-sdk query config-set context_window <n>` was rejected with
|
||||
* `msd-sdk query config-set context_window <n>` was rejected with
|
||||
* "Unknown config key: context_window" because context_window was missing
|
||||
* from VALID_CONFIG_KEYS in sdk/src/query/config-schema.ts.
|
||||
*
|
||||
@@ -668,7 +668,7 @@ const SDK_CLI = path.join(REPO_ROOT, 'sdk', 'dist', 'cli.js');
|
||||
function runConfigSet(key, value, projectDir) {
|
||||
const argv = ['query', 'config-set', key, String(value), '--project-dir', projectDir];
|
||||
const result = runNode([SDK_CLI, ...argv], {
|
||||
env: { ...process.env, GSD_SESSION_KEY: '' },
|
||||
env: { ...process.env, MSD_SESSION_KEY: '' },
|
||||
timeoutMs: PROBE_TIMEOUT_MS,
|
||||
});
|
||||
let json = null;
|
||||
@@ -680,7 +680,7 @@ describe('bug-2798: context_window is a valid config key', () => {
|
||||
let tmpDir;
|
||||
|
||||
beforeEach(() => {
|
||||
tmpDir = createTempProject('gsd-test-2798-');
|
||||
tmpDir = createTempProject('msd-test-2798-');
|
||||
fs.writeFileSync(
|
||||
path.join(tmpDir, '.planning', 'config.json'),
|
||||
JSON.stringify({ mode: 'balanced' })
|
||||
@@ -722,7 +722,7 @@ describe('bug-2798: context_window is a valid config key', () => {
|
||||
t.skip('sdk/dist/query/config-schema.js not built — run `cd sdk && npm run build` to enable this integration test');
|
||||
return;
|
||||
}
|
||||
const cjsSchema = require(path.join(REPO_ROOT, 'gsd-core', 'bin', 'lib', 'config-schema.cjs'));
|
||||
const cjsSchema = require(path.join(REPO_ROOT, 'msd-core', 'bin', 'lib', 'config-schema.cjs'));
|
||||
const sdkSchema = require(path.join(REPO_ROOT, 'sdk', 'dist', 'query', 'config-schema.js'));
|
||||
|
||||
assert.ok(
|
||||
@@ -748,7 +748,7 @@ describe('bug-2798: context_window is a valid config key', () => {
|
||||
/**
|
||||
* Regression test for bug #2943
|
||||
*
|
||||
* `gsd-tools.cjs config-get context_window` (and the SDK equivalent) threw
|
||||
* `msd-tools.cjs config-get context_window` (and the SDK equivalent) threw
|
||||
* "Key not found: context_window" when the key was absent from config.json,
|
||||
* even though context_window has a documented schema default of 200000.
|
||||
*
|
||||
@@ -760,7 +760,7 @@ describe('bug-2798: context_window is a valid config key', () => {
|
||||
'use strict';
|
||||
|
||||
// Migrated to typed-IR (#2974): the previous shape grepped stderr/stdout for
|
||||
// "Key not found"; now the test passes `--json-errors` to gsd-tools and
|
||||
// "Key not found"; now the test passes `--json-errors` to msd-tools and
|
||||
// asserts on the structured `reason` code (a frozen-enum value from
|
||||
// `core.cjs::ERROR_REASON`). Exit code is also a typed signal — together
|
||||
// they fully discriminate the failure class.
|
||||
@@ -772,8 +772,8 @@ const path = require('node:path');
|
||||
const os = require('node:os');
|
||||
const { execFileSync } = require('node:child_process');
|
||||
|
||||
const GSD_TOOLS = path.join(__dirname, '..', 'gsd-core', 'bin', 'gsd-tools.cjs');
|
||||
const { ERROR_REASON } = require(path.join(__dirname, '..', 'gsd-core', 'bin', 'lib', 'io.cjs'));
|
||||
const MSD_TOOLS = path.join(__dirname, '..', 'msd-core', 'bin', 'msd-tools.cjs');
|
||||
const { ERROR_REASON } = require(path.join(__dirname, '..', 'msd-core', 'bin', 'lib', 'io.cjs'));
|
||||
const { cleanup } = require('./helpers.cjs');
|
||||
const { PROBE_TIMEOUT_MS } = require('./helpers/timeouts.cjs');
|
||||
|
||||
@@ -782,7 +782,7 @@ describe('bug-2943: config-get returns schema default for context_window', () =>
|
||||
let planningDir;
|
||||
|
||||
beforeEach(() => {
|
||||
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-test-2943-'));
|
||||
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-test-2943-'));
|
||||
planningDir = path.join(tmpDir, '.planning');
|
||||
fs.mkdirSync(planningDir, { recursive: true });
|
||||
});
|
||||
@@ -796,7 +796,7 @@ describe('bug-2943: config-get returns schema default for context_window', () =>
|
||||
* Uses --raw so we get the plain scalar value, not JSON-wrapped.
|
||||
*/
|
||||
function runConfigGet(keyPath, extraArgs = []) {
|
||||
const args = [GSD_TOOLS, 'config-get', keyPath, '--raw', '--cwd', tmpDir, ...extraArgs];
|
||||
const args = [MSD_TOOLS, 'config-get', keyPath, '--raw', '--cwd', tmpDir, ...extraArgs];
|
||||
let stdout = '';
|
||||
let stderr = '';
|
||||
let exitCode = 0;
|
||||
@@ -1194,7 +1194,7 @@ test('--cwd pointing at a non-existent path fails with a typed usage reason', (_
|
||||
const result = runCli(['--cwd', nonExistent, 'config-get', 'model_profile'], { cwd: process.cwd() });
|
||||
assert.notEqual(result.status, 0);
|
||||
assert.equal(result.hasStackTrace, false);
|
||||
// gsd-tools validates --cwd up-front and emits ERROR_REASON.USAGE.
|
||||
// msd-tools validates --cwd up-front and emits ERROR_REASON.USAGE.
|
||||
assert.equal(result.reason, 'usage', `expected reason=usage for invalid --cwd, got: ${result.reason}`);
|
||||
});
|
||||
|
||||
@@ -1253,7 +1253,7 @@ test('runCli rejects missing cwd with TypeError', () => {
|
||||
test('runCli surfaces typed reason from a known failure path', (t) => {
|
||||
const projectDir = createTempProject('cli-neg-harness-');
|
||||
t.after(() => cleanup(projectDir));
|
||||
// Unknown command — gsd-tools emits ERROR_REASON.SDK_UNKNOWN_COMMAND or
|
||||
// Unknown command — msd-tools emits ERROR_REASON.SDK_UNKNOWN_COMMAND or
|
||||
// USAGE depending on dispatch depth. Either is a real reason string;
|
||||
// the contract we pin here is just "the IR carries a reason from the
|
||||
// ERROR_REASON enum, never null".
|
||||
@@ -1357,7 +1357,7 @@ test('runCli treats jsonErrors=false as an explicit human-formatter path', (t) =
|
||||
|
||||
// ─── #2702: workstream-scoped config-get inherits from root config ──────────
|
||||
//
|
||||
// When GSD_WORKSTREAM is set, planningDir(cwd) points at .planning/workstreams/<ws>/.
|
||||
// When MSD_WORKSTREAM is set, planningDir(cwd) points at .planning/workstreams/<ws>/.
|
||||
// cmdConfigGet used to read ONLY that file, so a key configured at the project root
|
||||
// (.planning/config.json) but absent from the workstream's own config was reported
|
||||
// "Key not found" — silently inverting boolean workflow guards. The fix adds a
|
||||
@@ -1369,7 +1369,7 @@ describe('#2702: workstream config-get inherits from root config', () => {
|
||||
let wsPlanningDir;
|
||||
|
||||
beforeEach(() => {
|
||||
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-config-ws-2702-'));
|
||||
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-config-ws-2702-'));
|
||||
rootPlanningDir = path.join(tmpDir, '.planning');
|
||||
wsPlanningDir = path.join(rootPlanningDir, 'workstreams', 'alpha');
|
||||
fs.mkdirSync(wsPlanningDir, { recursive: true });
|
||||
@@ -1379,27 +1379,27 @@ describe('#2702: workstream config-get inherits from root config', () => {
|
||||
cleanup(tmpDir);
|
||||
});
|
||||
|
||||
// Run cmdConfigGet with GSD_WORKSTREAM scoped to 'alpha' (so planningDir → ws dir).
|
||||
// Run cmdConfigGet with MSD_WORKSTREAM scoped to 'alpha' (so planningDir → ws dir).
|
||||
function runScoped(...args) {
|
||||
const { keyPath, raw, defaultValue } = parseConfigGetArgs(args);
|
||||
const saved = process.env.GSD_WORKSTREAM;
|
||||
process.env.GSD_WORKSTREAM = 'alpha';
|
||||
const saved = process.env.MSD_WORKSTREAM;
|
||||
process.env.MSD_WORKSTREAM = 'alpha';
|
||||
let out;
|
||||
try {
|
||||
out = captureFdWrite(1, () => {
|
||||
config.cmdConfigGet(tmpDir, keyPath, raw, defaultValue);
|
||||
});
|
||||
} finally {
|
||||
if (saved === undefined) delete process.env.GSD_WORKSTREAM;
|
||||
else process.env.GSD_WORKSTREAM = saved;
|
||||
if (saved === undefined) delete process.env.MSD_WORKSTREAM;
|
||||
else process.env.MSD_WORKSTREAM = saved;
|
||||
}
|
||||
return out.trim();
|
||||
}
|
||||
|
||||
function runScopedExpectError(...args) {
|
||||
const { keyPath, raw, defaultValue } = parseConfigGetArgs(args);
|
||||
const saved = process.env.GSD_WORKSTREAM;
|
||||
process.env.GSD_WORKSTREAM = 'alpha';
|
||||
const saved = process.env.MSD_WORKSTREAM;
|
||||
process.env.MSD_WORKSTREAM = 'alpha';
|
||||
const origWriteSync = fs.writeSync;
|
||||
io.setJsonErrorMode(true);
|
||||
let stderr = '';
|
||||
@@ -1420,8 +1420,8 @@ describe('#2702: workstream config-get inherits from root config', () => {
|
||||
} finally {
|
||||
fs.writeSync = origWriteSync;
|
||||
io.setJsonErrorMode(false);
|
||||
if (saved === undefined) delete process.env.GSD_WORKSTREAM;
|
||||
else process.env.GSD_WORKSTREAM = saved;
|
||||
if (saved === undefined) delete process.env.MSD_WORKSTREAM;
|
||||
else process.env.MSD_WORKSTREAM = saved;
|
||||
}
|
||||
const parts = stderr.split('\n').filter(Boolean);
|
||||
let payload = {};
|
||||
@@ -1488,7 +1488,7 @@ describe('#2702: workstream config-get inherits from root config', () => {
|
||||
writeRoot({ workflow: { use_worktrees: true } });
|
||||
writeWs({ workflow: {} });
|
||||
const scoped = runScoped('config-get', 'workflow.use_worktrees', '--raw');
|
||||
// Unscoped read: no GSD_WORKSTREAM — reads root directly.
|
||||
// Unscoped read: no MSD_WORKSTREAM — reads root directly.
|
||||
const unscoped = captureFdWrite(1, () => {
|
||||
config.cmdConfigGet(tmpDir, 'workflow.use_worktrees', true, undefined);
|
||||
}).trim();
|
||||
@@ -1510,27 +1510,27 @@ describe('#2702: workstream config-get inherits from root config', () => {
|
||||
assert.equal(runScoped('config-get', 'workflow.use_worktrees', '--raw'), 'true');
|
||||
});
|
||||
|
||||
test('GSD_PROJECT alone (no workstream) does not trigger root inheritance — matches loadConfigResolved', () => {
|
||||
// GSD_PROJECT scopes planningDir to .planning/<project>/ but loadConfigResolved
|
||||
test('MSD_PROJECT alone (no workstream) does not trigger root inheritance — matches loadConfigResolved', () => {
|
||||
// MSD_PROJECT scopes planningDir to .planning/<project>/ but loadConfigResolved
|
||||
// gates root-reading on `if (ws)`, so a project-only read must NOT inherit root.
|
||||
// The fix gates on GSD_WORKSTREAM presence (not path inequality) to match.
|
||||
// The fix gates on MSD_WORKSTREAM presence (not path inequality) to match.
|
||||
// A --default is supplied so a non-inheriting read returns a clean sentinel
|
||||
// ('not-inherited') rather than hitting the error/exit path.
|
||||
const projectPlanningDir = path.join(rootPlanningDir, 'myproj');
|
||||
fs.mkdirSync(projectPlanningDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(projectPlanningDir, 'config.json'), JSON.stringify({ workflow: {} }));
|
||||
writeRoot({ workflow: { use_worktrees: true } });
|
||||
const saved = process.env.GSD_PROJECT;
|
||||
process.env.GSD_PROJECT = 'myproj';
|
||||
const saved = process.env.MSD_PROJECT;
|
||||
process.env.MSD_PROJECT = 'myproj';
|
||||
try {
|
||||
const out = captureFdWrite(1, () => {
|
||||
config.cmdConfigGet(tmpDir, 'workflow.use_worktrees', true, 'not-inherited');
|
||||
}).trim();
|
||||
// No workstream → no root inheritance → returns the --default sentinel, NOT root 'true'.
|
||||
assert.equal(out, 'not-inherited', 'GSD_PROJECT-only must not inherit root (matches loadConfigResolved)');
|
||||
assert.equal(out, 'not-inherited', 'MSD_PROJECT-only must not inherit root (matches loadConfigResolved)');
|
||||
} finally {
|
||||
if (saved === undefined) delete process.env.GSD_PROJECT;
|
||||
else process.env.GSD_PROJECT = saved;
|
||||
if (saved === undefined) delete process.env.MSD_PROJECT;
|
||||
else process.env.MSD_PROJECT = saved;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user