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:
@@ -2,7 +2,7 @@
|
||||
* #1928 — Gemini CLI runtime removal + Antigravity redirect.
|
||||
*
|
||||
* Google sunset Gemini CLI on 2026-06-18; Antigravity CLI is the official
|
||||
* successor. GSD removes the `gemini` runtime and turns `--gemini` into an
|
||||
* successor. MSD removes the `gemini` runtime and turns `--gemini` into an
|
||||
* explicit deprecation redirect (NOT a silent alias — Hyrum's Law, per the
|
||||
* issue's rejected alternative #2).
|
||||
*
|
||||
@@ -48,10 +48,10 @@ const {
|
||||
getRuntimeNewProjectCommand,
|
||||
runtimeFlags,
|
||||
getProjectInstructionFile,
|
||||
} = require(path.join(ROOT, 'gsd-core', 'bin', 'lib', 'runtime-name-policy.cjs'));
|
||||
} = require(path.join(ROOT, 'msd-core', 'bin', 'lib', 'runtime-name-policy.cjs'));
|
||||
|
||||
const registry = require(path.join(ROOT, 'gsd-core', 'bin', 'lib', 'capability-registry.cjs'));
|
||||
const catalog = require(path.join(ROOT, 'gsd-core', 'bin', 'shared', 'model-catalog.json'));
|
||||
const registry = require(path.join(ROOT, 'msd-core', 'bin', 'lib', 'capability-registry.cjs'));
|
||||
const catalog = require(path.join(ROOT, 'msd-core', 'bin', 'shared', 'model-catalog.json'));
|
||||
|
||||
const { convertClaudeAgentToAntigravityAgent } = require('../bin/install.js');
|
||||
|
||||
@@ -59,7 +59,7 @@ const { convertClaudeAgentToAntigravityAgent } = require('../bin/install.js');
|
||||
// touch the real machine. Runtime-config env overrides are stripped so the
|
||||
// child resolves config dirs strictly under the temp HOME.
|
||||
function runInstaller(args, homeDir) {
|
||||
const env = { ...process.env, HOME: homeDir, USERPROFILE: homeDir, GSD_TEST_MODE: '1' };
|
||||
const env = { ...process.env, HOME: homeDir, USERPROFILE: homeDir, MSD_TEST_MODE: '1' };
|
||||
for (const k of [
|
||||
'CLAUDE_CONFIG_DIR', 'GEMINI_CONFIG_DIR', 'ANTIGRAVITY_CONFIG_DIR',
|
||||
'XDG_CONFIG_HOME', 'CODEX_CONFIG_DIR', 'OPENCODE_CONFIG_DIR', 'KILO_CONFIG_DIR',
|
||||
@@ -71,7 +71,7 @@ function runInstaller(args, homeDir) {
|
||||
|
||||
describe('#1928 --gemini CLI deprecation redirect', () => {
|
||||
test('--gemini alone prints the sunset notice and exits non-zero without installing', (t) => {
|
||||
const home = createTempDir('gsd-1928-gemini-only-');
|
||||
const home = createTempDir('msd-1928-gemini-only-');
|
||||
t.after(() => cleanup(home));
|
||||
|
||||
const r = runInstaller(['--gemini'], home);
|
||||
@@ -87,7 +87,7 @@ describe('#1928 --gemini CLI deprecation redirect', () => {
|
||||
});
|
||||
|
||||
test('--gemini --global still exits 1 (removed flag regardless of scope)', (t) => {
|
||||
const home = createTempDir('gsd-1928-gemini-global-');
|
||||
const home = createTempDir('msd-1928-gemini-global-');
|
||||
t.after(() => cleanup(home));
|
||||
|
||||
const r = runInstaller(['--gemini', '--global'], home);
|
||||
@@ -96,7 +96,7 @@ describe('#1928 --gemini CLI deprecation redirect', () => {
|
||||
});
|
||||
|
||||
test('the redirect is a clean message — no stack trace leaks to the user', (t) => {
|
||||
const home = createTempDir('gsd-1928-gemini-clean-');
|
||||
const home = createTempDir('msd-1928-gemini-clean-');
|
||||
t.after(() => cleanup(home));
|
||||
|
||||
const r = runInstaller(['--gemini'], home);
|
||||
@@ -106,7 +106,7 @@ describe('#1928 --gemini CLI deprecation redirect', () => {
|
||||
});
|
||||
|
||||
test('--gemini --help still prints usage (the redirect must not suppress help)', (t) => {
|
||||
const home = createTempDir('gsd-1928-gemini-help-');
|
||||
const home = createTempDir('msd-1928-gemini-help-');
|
||||
t.after(() => cleanup(home));
|
||||
|
||||
const r = runInstaller(['--gemini', '--help'], home);
|
||||
@@ -116,16 +116,16 @@ describe('#1928 --gemini CLI deprecation redirect', () => {
|
||||
});
|
||||
|
||||
test('--gemini --uninstall guides manual cleanup and does NOT uninstall Claude', (t) => {
|
||||
const home = createTempDir('gsd-1928-gemini-uninstall-');
|
||||
const home = createTempDir('msd-1928-gemini-uninstall-');
|
||||
t.after(() => cleanup(home));
|
||||
|
||||
// Sentinel: a pre-existing Claude install that must survive. Run WITHOUT
|
||||
// GSD_TEST_MODE so the real uninstall dispatch is active — the redirect must
|
||||
// MSD_TEST_MODE so the real uninstall dispatch is active — the redirect must
|
||||
// exit before it (the dispatch defaults an empty selection to 'claude').
|
||||
fs.mkdirSync(path.join(home, '.claude'), { recursive: true });
|
||||
fs.writeFileSync(path.join(home, '.claude', 'sentinel.txt'), 'keep me');
|
||||
const env = { ...process.env, HOME: home, USERPROFILE: home };
|
||||
delete env.GSD_TEST_MODE;
|
||||
delete env.MSD_TEST_MODE;
|
||||
delete env.CLAUDE_CONFIG_DIR;
|
||||
const r = spawnSync(process.execPath, [INSTALL_JS, '--gemini', '--uninstall', '--global'], {
|
||||
cwd: home, env, encoding: 'utf8', timeout: INSTALL_TIMEOUT_MS,
|
||||
@@ -180,7 +180,7 @@ describe('#1928 gemini removed from every runtime-name-policy surface', () => {
|
||||
/retired by #1928/,
|
||||
'config-home fragment removed → must now refuse, not fail-closed-default',
|
||||
);
|
||||
assert.strictEqual(getRuntimeNewProjectCommand('gemini'), '/gsd-new-project', 'new-project override removed → default (unchanged by #4709)');
|
||||
assert.strictEqual(getRuntimeNewProjectCommand('gemini'), '/msd-new-project', 'new-project override removed → default (unchanged by #4709)');
|
||||
});
|
||||
|
||||
test('runtimeFlags has no isGemini and covers exactly the non-claude, CLI-installable registry runtimes (count-agnostic)', () => {
|
||||
@@ -218,7 +218,7 @@ describe('#1928 Antigravity preserved (shared surface with the removed gemini ru
|
||||
});
|
||||
|
||||
test('the Antigravity-native tool vocabulary powers Antigravity agent conversion (#4705)', () => {
|
||||
const input = ['---', 'name: gsd-x', 'description: d', 'tools: Read, Write, WebFetch, Skill', '---', '', 'body'].join('\n');
|
||||
const input = ['---', 'name: msd-x', 'description: d', 'tools: Read, Write, WebFetch, Skill', '---', '', 'body'].join('\n');
|
||||
const result = convertClaudeAgentToAntigravityAgent(input);
|
||||
const toolsBlock = result.slice(result.indexOf('tools:')).split('\n').filter((l) => l.startsWith('- '));
|
||||
assert.ok(toolsBlock.includes('- view_file'), 'Read → view_file (native name, #4705)');
|
||||
@@ -232,7 +232,7 @@ describe('#1928 Antigravity preserved (shared surface with the removed gemini ru
|
||||
// claudeToGeminiTools/convertGeminiToolName to claudeToAntigravityTools/convertAntigravityToolName
|
||||
// in place; a partial rename would leave BOTH names live as two aliases for one concept, which
|
||||
// is exactly the drift this epic exists to end.
|
||||
const mod = require(path.join(ROOT, 'gsd-core', 'bin', 'lib', 'runtime-artifact-conversion.cjs'));
|
||||
const mod = require(path.join(ROOT, 'msd-core', 'bin', 'lib', 'runtime-artifact-conversion.cjs'));
|
||||
|
||||
assert.ok(
|
||||
Object.prototype.hasOwnProperty.call(mod, 'claudeToAntigravityTools'),
|
||||
@@ -324,7 +324,7 @@ describe('#4709 no shipped surface mints a retired runtime id', () => {
|
||||
*/
|
||||
function shippedMarkdown() {
|
||||
return [
|
||||
...markdownFilesUnder(path.join(ROOT, 'gsd-core', 'workflows')),
|
||||
...markdownFilesUnder(path.join(ROOT, 'msd-core', 'workflows')),
|
||||
...markdownFilesUnder(path.join(ROOT, 'commands')),
|
||||
...markdownFilesUnder(path.join(ROOT, 'skills')),
|
||||
...markdownFilesUnder(path.join(ROOT, 'agents')),
|
||||
@@ -334,7 +334,7 @@ describe('#4709 no shipped surface mints a retired runtime id', () => {
|
||||
const relPath = (p) => path.relative(ROOT, p).split(path.sep).join('/');
|
||||
const linesOf = (file) => fs.readFileSync(file, 'utf8').split(/\r?\n/);
|
||||
|
||||
const SETTINGS_ADVANCED = path.join(ROOT, 'gsd-core', 'workflows', 'settings-advanced.md');
|
||||
const SETTINGS_ADVANCED = path.join(ROOT, 'msd-core', 'workflows', 'settings-advanced.md');
|
||||
|
||||
test('every RUNTIME= assignment in workflow text names a canonical runtime', () => {
|
||||
// Bare-literal assignments only: RUNTIME=codex / RUNTIME="codex". A `$VAR`, `$(cmd)` or
|
||||
@@ -403,7 +403,7 @@ describe('#4709 no shipped surface mints a retired runtime id', () => {
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(offenders, [],
|
||||
'a runtime selection menu offers a runtime GSD does not support — selecting it writes a '
|
||||
'a runtime selection menu offers a runtime MSD does not support — selecting it writes a '
|
||||
+ `config value that silently resolves to Claude Code. Offenders:\n ${offenders.join('\n ')}`);
|
||||
});
|
||||
|
||||
@@ -455,7 +455,7 @@ describe('#4709 no shipped surface mints a retired runtime id', () => {
|
||||
'antigravity must remain a model-catalog runtime');
|
||||
|
||||
// The three model IDs the stale `gemini` table row carried belong to the google PROVIDER
|
||||
// preset and must survive — they name real Google models, not a GSD runtime.
|
||||
// preset and must survive — they name real Google models, not a MSD runtime.
|
||||
const google = JSON.stringify(catalog.providerPresets.google);
|
||||
for (const model of ['gemini-3.1-pro-preview', 'gemini-3-flash', 'gemini-2.5-flash-lite']) {
|
||||
assert.ok(google.includes(model), `google provider preset must still offer ${model}`);
|
||||
@@ -501,7 +501,7 @@ describe('#4709 no shipped surface mints a retired runtime id', () => {
|
||||
}
|
||||
|
||||
assert.deepStrictEqual(offenders, [],
|
||||
'a PR template asks contributors which runtime they tested and lists one GSD does not '
|
||||
'a PR template asks contributors which runtime they tested and lists one MSD does not '
|
||||
+ 'support. Labels must match the runtime label table (src/runtime-name-policy.cts '
|
||||
+ `RUNTIME_LABELS), so a retired runtime cannot linger here. Offenders:\n ${offenders.join('\n ')}`);
|
||||
});
|
||||
@@ -515,7 +515,7 @@ describe('#4709 no shipped surface mints a retired runtime id', () => {
|
||||
* decision, so retiring it corrects a mistake and needs no ADR-2782 amendment.
|
||||
*
|
||||
* The lane spawned `gemini {{model}} -p -`, a binary Google no longer serves for the
|
||||
* free/Pro/Ultra tiers that ARE GSD's audience.
|
||||
* free/Pro/Ultra tiers that ARE MSD's audience.
|
||||
*
|
||||
* Every assertion below is STRUCTURAL — a declared lane, an owned config key, a capability count.
|
||||
* None asserts that the string "gemini" is absent, because that string is load-bearing across
|
||||
@@ -553,7 +553,7 @@ describe('#4709 the Gemini CLI reviewer lane is retired', () => {
|
||||
assert.deepStrictEqual(
|
||||
offenders,
|
||||
[],
|
||||
'the retired lane still owns config keys, so `gsd config-set` would accept settings for a '
|
||||
'the retired lane still owns config keys, so `msd config-set` would accept settings for a '
|
||||
+ `lane that cannot run. Offenders:\n ${offenders.join('\n ')}`,
|
||||
);
|
||||
});
|
||||
@@ -665,7 +665,7 @@ describe('#4728 Gemini CLI prose retired from localized docs and runtime-loaded
|
||||
});
|
||||
|
||||
test('no runtime-loaded workflow file names the retired Gemini runtime', () => {
|
||||
// Walk gsd-core/workflows/ recursively (this MUST cover nested dirs like
|
||||
// Walk msd-core/workflows/ recursively (this MUST cover nested dirs like
|
||||
// new-project/steps/, where #4728's auto-mode-config.md defect lived) and assert no `.md`
|
||||
// file contains a case-sensitive standalone `Gemini` token, i.e. no match for /\bGemini\b/.
|
||||
//
|
||||
@@ -678,11 +678,11 @@ describe('#4728 Gemini CLI prose retired from localized docs and runtime-loaded
|
||||
// gemini-2.5-flash-lite
|
||||
// - env vars are uppercase: GEMINI_CONFIG_DIR, GEMINI_SESSION_ID, GEMINI_API_KEY
|
||||
// - the generated runtime-launcher preamble only ever uses GEMINI_CONFIG_DIR / $HOME/.gemini
|
||||
// So a bare capitalised `Gemini` anywhere under gsd-core/workflows/ can only mean the retired
|
||||
// So a bare capitalised `Gemini` anywhere under msd-core/workflows/ can only mean the retired
|
||||
// RUNTIME is being named — which is exactly the defect this test exists to catch. These files
|
||||
// are runtime-loaded (read by the agent at execution time), so a stale "Gemini" mention here
|
||||
// actively steers execution toward a retired runtime, not merely misinforms a reader.
|
||||
const WORKFLOWS_ROOT = path.join(ROOT, 'gsd-core', 'workflows');
|
||||
const WORKFLOWS_ROOT = path.join(ROOT, 'msd-core', 'workflows');
|
||||
const GEMINI_TOKEN = /\bGemini\b/;
|
||||
// Two allowlisted exceptions, both matched by line CONTENT (never line number, so neither can
|
||||
// silently drift if the file is edited above the matched line):
|
||||
@@ -698,10 +698,10 @@ describe('#4728 Gemini CLI prose retired from localized docs and runtime-loaded
|
||||
// taxonomy the whole #4709 epic rests on, so this line is correct as written and must
|
||||
// keep working, not get rewritten to dodge the predicate.
|
||||
const isAllowlistedLegacyLine = (file, line) =>
|
||||
(relPath(file) === 'gsd-core/workflows/reapply-patches.md'
|
||||
(relPath(file) === 'msd-core/workflows/reapply-patches.md'
|
||||
&& line.includes('Legacy:')
|
||||
&& line.includes('pre-#1928'))
|
||||
|| (relPath(file) === 'gsd-core/workflows/settings-advanced.md'
|
||||
|| (relPath(file) === 'msd-core/workflows/settings-advanced.md'
|
||||
&& line.includes('Known provider'));
|
||||
|
||||
/** Recursively collect every `.md` file under `dir`. */
|
||||
@@ -721,7 +721,7 @@ describe('#4728 Gemini CLI prose retired from localized docs and runtime-loaded
|
||||
const files = markdownFilesUnder(WORKFLOWS_ROOT);
|
||||
// Guard against an empty or failed walk making this test pass vacuously.
|
||||
assert.ok(files.length >= 50,
|
||||
`expected at least 50 .md files under gsd-core/workflows/, found ${files.length} — the `
|
||||
`expected at least 50 .md files under msd-core/workflows/, found ${files.length} — the `
|
||||
+ 'recursive walk may be broken');
|
||||
|
||||
const offenders = [];
|
||||
@@ -735,7 +735,7 @@ describe('#4728 Gemini CLI prose retired from localized docs and runtime-loaded
|
||||
}
|
||||
|
||||
assert.deepStrictEqual(offenders, [],
|
||||
'a runtime-loaded workflow file under gsd-core/workflows/ still names the retired Gemini '
|
||||
'a runtime-loaded workflow file under msd-core/workflows/ still names the retired Gemini '
|
||||
+ 'runtime, steering the agent (these files are read at execution time, not just by a '
|
||||
+ `reader) toward a retired runtime. Offenders:\n ${offenders.join('\n ')}`);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user