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

@@ -122,7 +122,7 @@ const SCHEMA_DEFAULTS: Record<string, unknown> = {
// Derived from the defaults manifest rather than restated, so the manifest
// stays the single source of truth for the smart-zone budget (#2630).
'workflow.smart_zone_tokens': CONFIG_DEFAULTS.smart_zone_tokens,
// #2971: /gsd:pr-branch reads this key directly; an absent key must resolve to the
// #2971: /msd:pr-branch reads this key directly; an absent key must resolve to the
// manifest default rather than "Key not found". Derived from the defaults manifest so
// the manifest stays the single source of truth.
'planning.pr_strict': CONFIG_DEFAULTS.pr_strict,
@@ -301,8 +301,8 @@ function validateShipPrBodySections(value: unknown): void {
*
* Merges (increasing priority):
* 1. Hardcoded defaults — every key that loadConfig() resolves, plus mode/granularity
* 2. User-level defaults from ~/.gsd/defaults.json (if present)
* 3. userChoices — the settings the user explicitly selected during /gsd:new-project
* 2. User-level defaults from ~/.msd/defaults.json (if present)
* 3. userChoices — the settings the user explicitly selected during /msd:new-project
*
* Uses the canonical `git` namespace for branching keys (consistent with VALID_CONFIG_KEYS
* and the settings workflow). loadConfig() handles both flat and nested formats, so this
@@ -315,23 +315,23 @@ function buildNewProjectConfig(userChoices: Record<string, unknown>): Record<str
const homedir = os.homedir();
// Detect API key availability
const braveKeyFile = path.join(homedir, '.gsd', 'brave_api_key');
const braveKeyFile = path.join(homedir, '.msd', 'brave_api_key');
const hasBraveSearch = !!(process.env['BRAVE_API_KEY'] || fs.existsSync(braveKeyFile));
const firecrawlKeyFile = path.join(homedir, '.gsd', 'firecrawl_api_key');
const firecrawlKeyFile = path.join(homedir, '.msd', 'firecrawl_api_key');
const hasFirecrawl = !!(process.env['FIRECRAWL_API_KEY'] || fs.existsSync(firecrawlKeyFile));
const exaKeyFile = path.join(homedir, '.gsd', 'exa_api_key');
const exaKeyFile = path.join(homedir, '.msd', 'exa_api_key');
const hasExaSearch = !!(process.env['EXA_API_KEY'] || fs.existsSync(exaKeyFile));
const tavilyKeyFile = path.join(homedir, '.gsd', 'tavily_api_key');
const tavilyKeyFile = path.join(homedir, '.msd', 'tavily_api_key');
const hasTavilySearch = !!(process.env['TAVILY_API_KEY'] || fs.existsSync(tavilyKeyFile));
const refKeyFile = path.join(homedir, '.gsd', 'ref_api_key');
const refKeyFile = path.join(homedir, '.msd', 'ref_api_key');
const hasRefSearch = !!(process.env['REF_API_KEY'] || fs.existsSync(refKeyFile));
const perplexityKeyFile = path.join(homedir, '.gsd', 'perplexity_api_key');
const perplexityKeyFile = path.join(homedir, '.msd', 'perplexity_api_key');
const hasPerplexity = !!(process.env['PERPLEXITY_API_KEY'] || fs.existsSync(perplexityKeyFile));
const jinaKeyFile = path.join(homedir, '.gsd', 'jina_api_key');
const jinaKeyFile = path.join(homedir, '.msd', 'jina_api_key');
const hasJina = !!(process.env['JINA_API_KEY'] || fs.existsSync(jinaKeyFile));
// Load user-level defaults from ~/.gsd/defaults.json if available
const globalDefaultsPath = path.join(homedir, '.gsd', 'defaults.json');
// Load user-level defaults from ~/.msd/defaults.json if available
const globalDefaultsPath = path.join(homedir, '.msd', 'defaults.json');
let userDefaults: Record<string, unknown> = {};
try {
if (fs.existsSync(globalDefaultsPath)) {
@@ -427,7 +427,7 @@ function buildNewProjectConfig(userChoices: Record<string, unknown>): Record<str
// Claude Code projects, resolving agents to wrong model IDs. `resolve_model_ids`
// already has a per-install guard (#2297); `runtime` gets the same treatment
// by excluding it from the defaults spread. Projects detect the runtime from
// the install path / .gsd-runtime marker, not from a copied config key.
// the install path / .msd-runtime marker, not from a copied config key.
const safeDefaults = { ...userDefaults };
delete safeDefaults['runtime'];
@@ -476,8 +476,8 @@ function buildNewProjectConfig(userChoices: Record<string, unknown>): Record<str
* Command: create a fully-materialized .planning/config.json for a new project.
*
* Accepts user-chosen settings as a JSON string (the keys the user explicitly
* configured during /gsd:new-project). All remaining keys are filled from
* hardcoded defaults and optional ~/.gsd/defaults.json.
* configured during /msd:new-project). All remaining keys are filled from
* hardcoded defaults and optional ~/.msd/defaults.json.
*
* Idempotent: if config.json already exists, returns { created: false }.
*/
@@ -1003,7 +1003,7 @@ function cmdConfigSet(cwd: string, keyPath: string | undefined, value: string |
}
}
// Statusline GSD-state format enum validation
// Statusline MSD-state format enum validation
const VALID_STATE_FORMATS = ['full', 'compact'];
if (kp === 'statusline.state_format') assertEnumValue(parsedValue, val, VALID_STATE_FORMATS, 'statusline.state_format');
@@ -1020,8 +1020,8 @@ function cmdConfigSet(cwd: string, keyPath: string | undefined, value: string |
// and honour in agreement ON THE DOMAIN: the hook falls back to its default
// for a value outside it, so reporting success would be a lie. That agreement
// is per-key and no wider — a value accepted here can still be superseded at
// read time by the hook's pair check, and a scoped write (GSD_PROJECT /
// GSD_WORKSTREAM) lands in a config the hook does not read at all. The PAIR
// read time by the hook's pair check, and a scoped write (MSD_PROJECT /
// MSD_WORKSTREAM) lands in a config the hook does not read at all. The PAIR
// (critical < warning) is deliberately NOT enforced here: config-set writes
// one key per call, so a two-step retune can be transiently inconsistent on
// disk and a check here would reject that intermediate write.
@@ -1291,10 +1291,10 @@ function cmdConfigGet(cwd: string, keyPath: string | undefined, raw: boolean, de
* that file directly.
*/
function resolveFromRootConfig(cwd: string, kp: string): { found: boolean; value: unknown } {
// Only meaningful when a workstream is active (GSD_WORKSTREAM set) — that is what
// Only meaningful when a workstream is active (MSD_WORKSTREAM set) — that is what
// redirects planningDir away from root AND what loadConfigResolved gates root-reading
// on. Gating on `process.env.GSD_WORKSTREAM` (not on a planningDir !== planningRoot
// path inequality) avoids a false trigger under GSD_PROJECT alone, where planningDir
// on. Gating on `process.env.MSD_WORKSTREAM` (not on a planningDir !== planningRoot
// path inequality) avoids a false trigger under MSD_PROJECT alone, where planningDir
// diverges from planningRoot without a workstream and loadConfigResolved does NOT
// inherit root — matching the runtime's own `if (ws)` gate keeps the two surfaces
// from diverging on the project-scoped (non-workstream) case.
@@ -1405,7 +1405,7 @@ function cmdConfigPath(cwd: string, _raw: boolean, workstreamContext: Workstream
*
* Wraps the Configuration Module's migrateOnDisk() for the CLI surface. This
* is the Phase 2 acceptance-criteria deliverable for opt-in migration (#3536):
* users can run `gsd-tools migrate-config` to apply all four legacy-key
* users can run `msd-tools migrate-config` to apply all four legacy-key
* migrations to their .planning/config.json without having to load any config
* implicitly via another command.
*
@@ -1419,7 +1419,7 @@ function cmdConfigPath(cwd: string, _raw: boolean, workstreamContext: Workstream
function cmdMigrateConfig(cwd: string, raw: boolean): void {
const ws = resolveEnvWorkstream();
// #3749: resolve the migration target through the project-aware resolver so
// GSD_PROJECT scopes the write; migrateOnDisk itself cannot (see its
// MSD_PROJECT scopes the write; migrateOnDisk itself cannot (see its
// configPathOverride note).
const scopedConfigPath = path.join(planningDir(cwd, ws || undefined), 'config.json');
const report = migrateOnDisk(cwd, ws || undefined, scopedConfigPath);