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:
@@ -1,15 +1,15 @@
|
||||
'use strict';
|
||||
/**
|
||||
* One-shot script + library: bidirectional GSD slash-command namespace normalizer.
|
||||
* One-shot script + library: bidirectional MSD slash-command namespace normalizer.
|
||||
*
|
||||
* - Default direction (transformContent): retired /gsd-<cmd> → /gsd:<cmd>
|
||||
* - Default direction (transformContent): retired /msd-<cmd> → /msd:<cmd>
|
||||
* (keeps monorepo sources, docs, and workflows in the active colon form).
|
||||
* - Reverse direction (transformContentToHyphen): /gsd:<cmd> / gsd:<cmd> → gsd-<cmd>
|
||||
* - Reverse direction (transformContentToHyphen): /msd:<cmd> / msd:<cmd> → msd-<cmd>
|
||||
* (used during skill installation for runtimes that register skills under the
|
||||
* canonical hyphen form established in #2808).
|
||||
*
|
||||
* Both directions only rewrite known commands from `commands/gsd/*.md` (longest-first
|
||||
* matching + word-boundary safety). Non-commands (gsd-sdk, gsd-tools, etc.) are
|
||||
* Both directions only rewrite known commands from `commands/msd/*.md` (longest-first
|
||||
* matching + word-boundary safety). Non-commands (msd-sdk, msd-tools, etc.) are
|
||||
* intentionally left untouched.
|
||||
*
|
||||
* The transforms are pure and exported for use by the installer and tests.
|
||||
@@ -18,14 +18,14 @@
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
|
||||
const COMMANDS_DIR = path.join(__dirname, '..', 'commands', 'gsd');
|
||||
const COMMANDS_DIR = path.join(__dirname, '..', 'commands', 'msd');
|
||||
const SEARCH_DIRS = [
|
||||
path.join(__dirname, '..', 'gsd-core', 'bin', 'lib'),
|
||||
path.join(__dirname, '..', 'gsd-core', 'workflows'),
|
||||
path.join(__dirname, '..', 'gsd-core', 'references'),
|
||||
path.join(__dirname, '..', 'gsd-core', 'templates'),
|
||||
path.join(__dirname, '..', 'gsd-core', 'contexts'),
|
||||
path.join(__dirname, '..', 'commands', 'gsd'),
|
||||
path.join(__dirname, '..', 'msd-core', 'bin', 'lib'),
|
||||
path.join(__dirname, '..', 'msd-core', 'workflows'),
|
||||
path.join(__dirname, '..', 'msd-core', 'references'),
|
||||
path.join(__dirname, '..', 'msd-core', 'templates'),
|
||||
path.join(__dirname, '..', 'msd-core', 'contexts'),
|
||||
path.join(__dirname, '..', 'commands', 'msd'),
|
||||
path.join(__dirname, '..', 'agents'),
|
||||
path.join(__dirname, '..', 'hooks'),
|
||||
];
|
||||
@@ -44,30 +44,30 @@ function isTestFile(name) {
|
||||
}
|
||||
|
||||
function buildPattern(cmdNames) {
|
||||
// Empty input would compile `/gsd-()(?=[^a-zA-Z0-9_-]|$)/g`, which the regex
|
||||
// engine still matches at any `/gsd-` token followed by a non-word boundary
|
||||
// (e.g. EOL, whitespace, punctuation) — rewriting it to a stray `/gsd:`.
|
||||
// Empty input would compile `/msd-()(?=[^a-zA-Z0-9_-]|$)/g`, which the regex
|
||||
// engine still matches at any `/msd-` token followed by a non-word boundary
|
||||
// (e.g. EOL, whitespace, punctuation) — rewriting it to a stray `/msd:`.
|
||||
// Short-circuit so the caller can no-op on a missing/empty registry rather
|
||||
// than perform an unintended broad rewrite.
|
||||
if (!Array.isArray(cmdNames) || cmdNames.length === 0) return null;
|
||||
const sorted = [...cmdNames].sort((a, b) => b.length - a.length); // longest first to avoid partial matches
|
||||
return new RegExp(`/gsd-(${sorted.join('|')})(?=[^a-zA-Z0-9_-]|$)`, 'g');
|
||||
return new RegExp(`/msd-(${sorted.join('|')})(?=[^a-zA-Z0-9_-]|$)`, 'g');
|
||||
}
|
||||
|
||||
/**
|
||||
* Pure transform: rewrite retired `/gsd-<cmd>` to `/gsd:<cmd>` for the given command names.
|
||||
* Returns the rewritten string. Identifiers not in `cmdNames` (e.g. `/gsd-sdk`,
|
||||
* `/gsd-tools`) are left untouched.
|
||||
* Pure transform: rewrite retired `/msd-<cmd>` to `/msd:<cmd>` for the given command names.
|
||||
* Returns the rewritten string. Identifiers not in `cmdNames` (e.g. `/msd-sdk`,
|
||||
* `/msd-tools`) are left untouched.
|
||||
*/
|
||||
function transformContent(src, cmdNames) {
|
||||
const pattern = buildPattern(cmdNames);
|
||||
if (!pattern) return src;
|
||||
return src.replace(pattern, (_, cmd) => `/gsd:${cmd}`);
|
||||
return src.replace(pattern, (_, cmd) => `/msd:${cmd}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build regex for the reverse direction (colon form → hyphen form).
|
||||
* Matches both "gsd:cmd" and "/gsd:cmd" (the leading / is preserved automatically
|
||||
* Matches both "msd:cmd" and "/msd:cmd" (the leading / is preserved automatically
|
||||
* because it is not part of the match). Uses longest-first ordering plus
|
||||
* bidirectional word-boundary safety (negative lookbehind on the left, lookahead
|
||||
* on the right) so matches only occur at token boundaries.
|
||||
@@ -75,20 +75,20 @@ function transformContent(src, cmdNames) {
|
||||
function buildColonPattern(cmdNames) {
|
||||
if (!Array.isArray(cmdNames) || cmdNames.length === 0) return null;
|
||||
const sorted = [...cmdNames].sort((a, b) => b.length - a.length);
|
||||
return new RegExp(`(?<![a-zA-Z0-9_-])gsd:(${sorted.join('|')})(?=[^a-zA-Z0-9_-]|$)`, 'g');
|
||||
return new RegExp(`(?<![a-zA-Z0-9_-])msd:(${sorted.join('|')})(?=[^a-zA-Z0-9_-]|$)`, 'g');
|
||||
}
|
||||
|
||||
/**
|
||||
* Pure transform (reverse): rewrite `/gsd:<cmd>` / `gsd:<cmd>` to hyphen form
|
||||
* for known GSD commands.
|
||||
* Pure transform (reverse): rewrite `/msd:<cmd>` / `msd:<cmd>` to hyphen form
|
||||
* for known MSD commands.
|
||||
*
|
||||
* Non-command identifiers (e.g. gsd-sdk, gsd-tools) are left untouched, matching
|
||||
* Non-command identifiers (e.g. msd-sdk, msd-tools) are left untouched, matching
|
||||
* the safety contract of the forward transform.
|
||||
*/
|
||||
function transformContentToHyphen(src, cmdNames) {
|
||||
const pattern = buildColonPattern(cmdNames);
|
||||
if (!pattern) return src;
|
||||
return src.replace(pattern, (_, cmd) => `gsd-${cmd}`);
|
||||
return src.replace(pattern, (_, cmd) => `msd-${cmd}`);
|
||||
}
|
||||
|
||||
function readCmdNames() {
|
||||
@@ -102,7 +102,7 @@ function readCmdNames() {
|
||||
// not silently handed an empty registry while the real problem goes undetected.
|
||||
if (err.code !== 'ENOENT') throw err;
|
||||
// COMMANDS_DIR may not exist on installs that use skill-based runtimes or
|
||||
// global Claude installs (no local commands/gsd/ directory). Return [] so
|
||||
// global Claude installs (no local commands/msd/ directory). Return [] so
|
||||
// callers that handle an empty array gracefully (buildPattern returns null,
|
||||
// transformContent is a no-op) are not broken by a missing directory.
|
||||
return [];
|
||||
|
||||
Reference in New Issue
Block a user