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

@@ -29,13 +29,13 @@ const {
resolveActiveWorkstream,
applyResolvedWorkstreamEnv,
_resetControllingTtyCacheForTests,
} = require('../gsd-core/bin/lib/active-workstream-store.cjs');
} = require('../msd-core/bin/lib/active-workstream-store.cjs');
// ── Helpers ───────────────────────────────────────────────────────────────────
//
// saveSessionEnv/restoreSessionEnv/clearSessionEnv now live in tests/helpers.cjs
// (single source of truth — #2850 code review finding: this file's local copy
// had already silently diverged from tests/gsd-statusline.test.cjs's copy).
// had already silently diverged from tests/msd-statusline.test.cjs's copy).
function makePlanningDir(base, ...workstreams) {
const wsDir = path.join(base, '.planning', 'workstreams');
@@ -139,7 +139,7 @@ describe('createMemoryPointerAdapter', () => {
describe('createSharedPointerAdapter', () => {
let tmpDir;
beforeEach(() => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-unit-shared-'));
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-unit-shared-'));
fs.mkdirSync(path.join(tmpDir, '.planning'), { recursive: true });
});
afterEach(() => cleanup(tmpDir));
@@ -198,7 +198,7 @@ describe('createSessionScopedPointerAdapter', () => {
let tmpDir;
let saved;
beforeEach(() => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-unit-session-'));
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-unit-session-'));
saved = saveSessionEnv();
clearSessionEnv();
});
@@ -255,7 +255,7 @@ describe('createSessionScopedPointerAdapter', () => {
});
test('uses env session key when no fixed key provided', () => {
process.env.GSD_SESSION_KEY = 'env-session';
process.env.MSD_SESSION_KEY = 'env-session';
const adapter = createSessionScopedPointerAdapter(tmpDir);
assert.notEqual(adapter, null);
adapter.write('env-ws');
@@ -280,7 +280,7 @@ describe('pickActiveWorkstreamAdapter', () => {
});
test('returns session adapter from adapters when session key exists', () => {
process.env.GSD_SESSION_KEY = 'some-session';
process.env.MSD_SESSION_KEY = 'some-session';
const session = createMemoryPointerAdapter('session-ws');
const shared = createMemoryPointerAdapter('shared-ws');
const picked = pickActiveWorkstreamAdapter('/fake', {
@@ -298,7 +298,7 @@ describe('pickActiveWorkstreamAdapter', () => {
});
test('creates shared pointer adapter when no opts and no session', () => {
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-pick-'));
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-pick-'));
try {
fs.mkdirSync(path.join(tmpDir, '.planning'), { recursive: true });
const picked = pickActiveWorkstreamAdapter(tmpDir, {});
@@ -310,8 +310,8 @@ describe('pickActiveWorkstreamAdapter', () => {
});
test('creates session scoped adapter when session key exists and no adapters given', () => {
process.env.GSD_SESSION_KEY = 'my-session';
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-pick-sess-'));
process.env.MSD_SESSION_KEY = 'my-session';
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-pick-sess-'));
try {
const picked = pickActiveWorkstreamAdapter(tmpDir, {});
// session scoped adapter exists since session key is set
@@ -319,7 +319,7 @@ describe('pickActiveWorkstreamAdapter', () => {
assert.equal(typeof picked.read, 'function');
} finally {
cleanup(tmpDir);
delete process.env.GSD_SESSION_KEY;
delete process.env.MSD_SESSION_KEY;
}
});
@@ -363,7 +363,7 @@ describe('pickActiveWorkstreamAdapterChain', () => {
test('returns [session, shared] chain (length 2, in order) when session key present', () => {
// Kills: `return session ? [session, shared] : []` → `: []`. A mutant
// there collapses the chain to empty even though session key is set.
process.env.GSD_SESSION_KEY = 'chain-session';
process.env.MSD_SESSION_KEY = 'chain-session';
const shared = createMemoryPointerAdapter('shared-ws');
const session = createMemoryPointerAdapter('session-ws');
const chain = pickActiveWorkstreamAdapterChain('/fake', {
@@ -390,7 +390,7 @@ describe('pickActiveWorkstreamAdapterChain', () => {
test('session key present, only session injected: shared half is inert memory adapter', () => {
// Kills: `injected.shared ?? createMemoryPointerAdapter(null)` → `&&` on
// the sessionKey-truthy branch (the shared fallback site).
process.env.GSD_SESSION_KEY = 'chain-partial-shared';
process.env.MSD_SESSION_KEY = 'chain-partial-shared';
const session = createMemoryPointerAdapter('session-ws');
const chain = pickActiveWorkstreamAdapterChain('/fake', {
activeWorkstreamAdapters: { session },
@@ -407,7 +407,7 @@ describe('pickActiveWorkstreamAdapterChain', () => {
test('session key present, only shared injected: session half is inert memory adapter', () => {
// Kills: `injected.session ?? createMemoryPointerAdapter(null)` → `&&`.
process.env.GSD_SESSION_KEY = 'chain-partial-session';
process.env.MSD_SESSION_KEY = 'chain-partial-session';
const shared = createMemoryPointerAdapter('shared-ws');
const chain = pickActiveWorkstreamAdapterChain('/fake', {
activeWorkstreamAdapters: { shared },
@@ -457,10 +457,10 @@ describe('getWorkstreamSessionKey', () => {
}
});
test('returns gsd-session-key prefixed key for GSD_SESSION_KEY', () => {
process.env.GSD_SESSION_KEY = 'mysession';
test('returns msd-session-key prefixed key for MSD_SESSION_KEY', () => {
process.env.MSD_SESSION_KEY = 'mysession';
const key = getWorkstreamSessionKey();
assert.equal(key, 'gsd-session-key-mysession');
assert.equal(key, 'msd-session-key-mysession');
});
test('returns codex-thread-id prefixed key for CODEX_THREAD_ID', () => {
@@ -530,11 +530,11 @@ describe('getWorkstreamSessionKey', () => {
assert.equal(key, 'zellij-session-name-my-zellij');
});
test('GSD_SESSION_KEY takes priority over CODEX_THREAD_ID', () => {
process.env.GSD_SESSION_KEY = 'first';
test('MSD_SESSION_KEY takes priority over CODEX_THREAD_ID', () => {
process.env.MSD_SESSION_KEY = 'first';
process.env.CODEX_THREAD_ID = 'second';
const key = getWorkstreamSessionKey();
assert.equal(key, 'gsd-session-key-first');
assert.equal(key, 'msd-session-key-first');
});
test('returns tty- prefixed key for TTY env var', () => {
@@ -563,15 +563,15 @@ describe('getWorkstreamSessionKey', () => {
assert.equal(key, 'tty-pts_1');
});
test('empty GSD_SESSION_KEY falls through', () => {
process.env.GSD_SESSION_KEY = '';
test('empty MSD_SESSION_KEY falls through', () => {
process.env.MSD_SESSION_KEY = '';
process.env.CODEX_THREAD_ID = 'fallback';
const key = getWorkstreamSessionKey();
assert.equal(key, 'codex-thread-id-fallback');
});
test('whitespace-only GSD_SESSION_KEY falls through', () => {
process.env.GSD_SESSION_KEY = ' ';
test('whitespace-only MSD_SESSION_KEY falls through', () => {
process.env.MSD_SESSION_KEY = ' ';
process.env.CODEX_THREAD_ID = 'fallback2';
const key = getWorkstreamSessionKey();
assert.equal(key, 'codex-thread-id-fallback2');
@@ -584,7 +584,7 @@ describe('getActiveWorkstream', () => {
let tmpDir;
let saved;
beforeEach(() => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-unit-get-'));
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-unit-get-'));
saved = saveSessionEnv();
clearSessionEnv();
});
@@ -655,7 +655,7 @@ describe('resolvesToExistingWorkstream — name-check short-circuit (#3579)', ()
let tmpDir;
let saved;
beforeEach(() => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-unit-resolves-'));
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-unit-resolves-'));
saved = saveSessionEnv();
clearSessionEnv();
});
@@ -669,7 +669,7 @@ describe('resolvesToExistingWorkstream — name-check short-circuit (#3579)', ()
// mutant checks fs.existsSync(join(root, 'workstreams', '')), which
// collapses to the 'workstreams' dir itself — which DOES exist here.
makePlanningDir(tmpDir); // creates .planning/workstreams with no children
process.env.GSD_SESSION_KEY = 'resolves-empty-name';
process.env.MSD_SESSION_KEY = 'resolves-empty-name';
const session = createMemoryPointerAdapter(''); // owned: falls through
const shared = createMemoryPointerAdapter(''); // fallback: also empty
const result = getActiveWorkstream(tmpDir, {
@@ -698,7 +698,7 @@ describe('resolveFromChain — owned/fallback/selfHeal discrimination (#3579)',
let tmpDir;
let saved;
beforeEach(() => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-unit-fromchain-'));
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-unit-fromchain-'));
saved = saveSessionEnv();
clearSessionEnv();
});
@@ -715,7 +715,7 @@ describe('resolveFromChain — owned/fallback/selfHeal discrimination (#3579)',
// BlockStatement removal (an emptied loop body would likewise never find
// the match and fall through to `return null`).
makePlanningDir(tmpDir, 'fallback-ws');
process.env.GSD_SESSION_KEY = 'owned-empty-1';
process.env.MSD_SESSION_KEY = 'owned-empty-1';
const session = createMemoryPointerAdapter(null);
const shared = createMemoryPointerAdapter('fallback-ws');
const result = getActiveWorkstream(tmpDir, {
@@ -729,7 +729,7 @@ describe('resolveFromChain — owned/fallback/selfHeal discrimination (#3579)',
// `if (true)`: the mutant would return the bogus fallback name
// unconditionally instead of continuing to null.
makePlanningDir(tmpDir); // workstreams root exists, 'ghost-fallback' does not
process.env.GSD_SESSION_KEY = 'owned-empty-2';
process.env.MSD_SESSION_KEY = 'owned-empty-2';
const session = createMemoryPointerAdapter(null);
const shared = createMemoryPointerAdapter('ghost-fallback');
const result = getActiveWorkstream(tmpDir, {
@@ -761,7 +761,7 @@ describe('diagnoseUnresolvedActiveWorkstream — full-object assertions (#3579)'
let tmpDir;
let saved;
beforeEach(() => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-unit-diagnose-'));
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-unit-diagnose-'));
saved = saveSessionEnv();
clearSessionEnv();
});
@@ -815,7 +815,7 @@ describe('setActiveWorkstream', () => {
let tmpDir;
let saved;
beforeEach(() => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-unit-set-'));
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-unit-set-'));
saved = saveSessionEnv();
clearSessionEnv();
});
@@ -910,14 +910,14 @@ describe('clearActiveWorkstream', () => {
});
test('uses session adapter branch when session key present', () => {
process.env.GSD_SESSION_KEY = 'clear-session';
process.env.MSD_SESSION_KEY = 'clear-session';
const session = createMemoryPointerAdapter('session-ws');
const shared = createMemoryPointerAdapter('shared-ws');
clearActiveWorkstream('/fake', { activeWorkstreamAdapters: { session, shared } });
assert.equal(session.read(), null);
// shared not cleared
assert.equal(shared.read(), 'shared-ws');
delete process.env.GSD_SESSION_KEY;
delete process.env.MSD_SESSION_KEY;
});
});
@@ -1008,26 +1008,26 @@ describe('parseCliWorkstream', () => {
describe('resolveActiveWorkstream', () => {
test('cli source overrides env and store', () => {
const r = resolveActiveWorkstream('/repo', ['--ws', 'cli-ws'], { GSD_WORKSTREAM: 'env-ws' }, { getStored: () => 'store-ws' });
const r = resolveActiveWorkstream('/repo', ['--ws', 'cli-ws'], { MSD_WORKSTREAM: 'env-ws' }, { getStored: () => 'store-ws' });
assert.equal(r.ws, 'cli-ws');
assert.equal(r.source, 'cli');
assert.deepEqual(r.args, []);
});
test('env source overrides store', () => {
const r = resolveActiveWorkstream('/repo', [], { GSD_WORKSTREAM: 'env-ws' }, { getStored: () => 'store-ws' });
const r = resolveActiveWorkstream('/repo', [], { MSD_WORKSTREAM: 'env-ws' }, { getStored: () => 'store-ws' });
assert.equal(r.ws, 'env-ws');
assert.equal(r.source, 'env');
});
test('env with whitespace is trimmed', () => {
const r = resolveActiveWorkstream('/repo', [], { GSD_WORKSTREAM: ' trimmed ' }, { getStored: () => null });
const r = resolveActiveWorkstream('/repo', [], { MSD_WORKSTREAM: ' trimmed ' }, { getStored: () => null });
assert.equal(r.ws, 'trimmed');
assert.equal(r.source, 'env');
});
test('env whitespace-only falls to store', () => {
const r = resolveActiveWorkstream('/repo', [], { GSD_WORKSTREAM: ' ' }, { getStored: () => 'store-ws' });
const r = resolveActiveWorkstream('/repo', [], { MSD_WORKSTREAM: ' ' }, { getStored: () => 'store-ws' });
assert.equal(r.ws, 'store-ws');
assert.equal(r.source, 'store');
});
@@ -1065,7 +1065,7 @@ describe('resolveActiveWorkstream', () => {
test('throws for invalid name from env', () => {
assert.throws(
() => resolveActiveWorkstream('/repo', [], { GSD_WORKSTREAM: 'bad name' }, { getStored: () => null }),
() => resolveActiveWorkstream('/repo', [], { MSD_WORKSTREAM: 'bad name' }, { getStored: () => null }),
/Invalid workstream name/
);
});
@@ -1077,8 +1077,8 @@ describe('resolveActiveWorkstream', () => {
);
});
test('GSD_WORKSTREAM non-string falls to store', () => {
const r = resolveActiveWorkstream('/repo', [], { GSD_WORKSTREAM: 42 }, { getStored: () => 'store-ws' });
test('MSD_WORKSTREAM non-string falls to store', () => {
const r = resolveActiveWorkstream('/repo', [], { MSD_WORKSTREAM: 42 }, { getStored: () => 'store-ws' });
assert.equal(r.ws, 'store-ws');
assert.equal(r.source, 'store');
});
@@ -1094,7 +1094,7 @@ describe('resolveActiveWorkstream', () => {
});
test('source is exactly "env" string', () => {
const r = resolveActiveWorkstream('/repo', [], { GSD_WORKSTREAM: 'myws' }, { getStored: () => null });
const r = resolveActiveWorkstream('/repo', [], { MSD_WORKSTREAM: 'myws' }, { getStored: () => null });
assert.equal(r.source, 'env');
});
@@ -1112,51 +1112,51 @@ describe('resolveActiveWorkstream', () => {
// ── applyResolvedWorkstreamEnv ────────────────────────────────────────────────
describe('applyResolvedWorkstreamEnv', () => {
test('sets GSD_WORKSTREAM when ws present', () => {
test('sets MSD_WORKSTREAM when ws present', () => {
const env = {};
applyResolvedWorkstreamEnv({ ws: 'my-ws', source: 'cli', args: [] }, env);
assert.equal(env.GSD_WORKSTREAM, 'my-ws');
assert.equal(env.MSD_WORKSTREAM, 'my-ws');
});
test('does not mutate env when ws is null', () => {
const env = { GSD_WORKSTREAM: 'old' };
const env = { MSD_WORKSTREAM: 'old' };
applyResolvedWorkstreamEnv({ ws: null, source: 'none', args: [] }, env);
assert.equal(env.GSD_WORKSTREAM, 'old');
assert.equal(env.MSD_WORKSTREAM, 'old');
});
test('does not mutate env when resolution is null', () => {
const env = { GSD_WORKSTREAM: 'old' };
const env = { MSD_WORKSTREAM: 'old' };
applyResolvedWorkstreamEnv(null, env);
assert.equal(env.GSD_WORKSTREAM, 'old');
assert.equal(env.MSD_WORKSTREAM, 'old');
});
test('does not mutate env when resolution is undefined', () => {
const env = { GSD_WORKSTREAM: 'old' };
const env = { MSD_WORKSTREAM: 'old' };
applyResolvedWorkstreamEnv(undefined, env);
assert.equal(env.GSD_WORKSTREAM, 'old');
assert.equal(env.MSD_WORKSTREAM, 'old');
});
test('overwrites existing GSD_WORKSTREAM value', () => {
const env = { GSD_WORKSTREAM: 'old' };
test('overwrites existing MSD_WORKSTREAM value', () => {
const env = { MSD_WORKSTREAM: 'old' };
applyResolvedWorkstreamEnv({ ws: 'new-ws', source: 'store', args: [] }, env);
assert.equal(env.GSD_WORKSTREAM, 'new-ws');
assert.equal(env.MSD_WORKSTREAM, 'new-ws');
});
test('uses process.env by default (does not throw)', () => {
const saved = process.env.GSD_WORKSTREAM;
const saved = process.env.MSD_WORKSTREAM;
try {
applyResolvedWorkstreamEnv({ ws: 'default-env-ws', source: 'cli', args: [] });
assert.equal(process.env.GSD_WORKSTREAM, 'default-env-ws');
assert.equal(process.env.MSD_WORKSTREAM, 'default-env-ws');
} 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;
}
});
test('does not throw for ws empty string (falsy)', () => {
const env = { GSD_WORKSTREAM: 'old' };
const env = { MSD_WORKSTREAM: 'old' };
applyResolvedWorkstreamEnv({ ws: '', source: 'none', args: [] }, env);
assert.equal(env.GSD_WORKSTREAM, 'old');
assert.equal(env.MSD_WORKSTREAM, 'old');
});
});
@@ -1347,7 +1347,7 @@ describe('#3557 CLAUDE_CODE_SESSION_ID session key', () => {
let tmpDir;
let saved;
beforeEach(() => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-3557-'));
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-3557-'));
saved = saveSessionEnv();
clearSessionEnv();
});
@@ -1428,16 +1428,16 @@ describe('#3557 CLAUDE_CODE_SESSION_ID session key', () => {
// Row 5 — the new key must not disturb existing precedence (criterion 6).
test('existing key precedence unchanged by the new key', () => {
process.env.GSD_SESSION_KEY = 'explicit-key';
process.env.MSD_SESSION_KEY = 'explicit-key';
process.env.CLAUDE_CODE_SESSION_ID = 'sess-alpha-123';
const key = withNonTtyStdin(() => getWorkstreamSessionKey());
assert.equal(key, 'gsd-session-key-explicit-key',
'GSD_SESSION_KEY stays ahead of runtime keys in the probe order');
assert.equal(key, 'msd-session-key-explicit-key',
'MSD_SESSION_KEY stays ahead of runtime keys in the probe order');
// Pin the new key's position against BOTH immediate neighbors — a swap
// with either would silently change which signal wins when Claude Code
// exports more than one (review finding on #3557).
delete process.env.GSD_SESSION_KEY;
delete process.env.MSD_SESSION_KEY;
process.env.CLAUDE_SESSION_ID = 'legacy-id';
process.env.CLAUDE_CODE_SESSION_ID = 'sess-alpha-123';
assert.equal(withNonTtyStdin(() => getWorkstreamSessionKey()),