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

@@ -8,13 +8,13 @@
/**
* Failing-first regression tests for #3409 (design:
* .gsd/phase/feat-3409-unreachable-shell-guard-lint/40-design.md; matrix:
* .gsd/phase/feat-3409-unreachable-shell-guard-lint/50-test-matrix.md,
* .msd/phase/feat-3409-unreachable-shell-guard-lint/40-design.md; matrix:
* .msd/phase/feat-3409-unreachable-shell-guard-lint/50-test-matrix.md,
* section "Regression — the three defects this PR fixes", rows G1-G4).
*
* Root cause (40-design.md): `gsd-tools.cjs`'s `--pick <field>` extractor
* Root cause (40-design.md): `msd-tools.cjs`'s `--pick <field>` extractor
* coerces a missing/absent field to the empty string and exits 0. So
* `X=$(gsd_run query V --pick F 2>/dev/null || echo D)` can NEVER reach its
* `X=$(msd_run query V --pick F 2>/dev/null || echo D)` can NEVER reach its
* `|| echo D` arm on field absence — only on a typo in the verb name. Three
* shipped shell guards silently rely on that unreachable arm:
*
@@ -46,9 +46,9 @@
* `extractFencedBashAfterAnchor` / `extractAssignmentBlockFor`) and executes it
* with `runHook(..., { interpreter: 'bash' })`
* (`tests/helpers/process-seam.cjs`), against a temp project fixture, driving
* the real CLI at `gsd-core/bin/gsd-tools.cjs` through the real `gsd_run`
* the real CLI at `msd-core/bin/msd-tools.cjs` through the real `msd_run`
* shell function sourced from the shipped
* `gsd-core/workflows/_runtime-launcher.snippet.sh` preamble.
* `msd-core/workflows/_runtime-launcher.snippet.sh` preamble.
*/
const { test, describe } = require('node:test');
@@ -61,10 +61,10 @@ const { runHook, OUTCOME } = require('./helpers/process-seam.cjs');
const { HOOK_FANOUT_TIMEOUT_MS } = require('./helpers/timeouts.cjs');
const REPO_ROOT = path.join(__dirname, '..');
const PLAN_PHASE_PATH = path.join(REPO_ROOT, 'gsd-core', 'workflows', 'plan-phase.md');
const COMPLETE_MILESTONE_PATH = path.join(REPO_ROOT, 'gsd-core', 'workflows', 'complete-milestone.md');
const LAUNCHER_PATH = path.join(REPO_ROOT, 'gsd-core', 'workflows', '_runtime-launcher.snippet.sh');
const GSD_TOOLS_PATH = path.join(REPO_ROOT, 'gsd-core', 'bin', 'gsd-tools.cjs');
const PLAN_PHASE_PATH = path.join(REPO_ROOT, 'msd-core', 'workflows', 'plan-phase.md');
const COMPLETE_MILESTONE_PATH = path.join(REPO_ROOT, 'msd-core', 'workflows', 'complete-milestone.md');
const LAUNCHER_PATH = path.join(REPO_ROOT, 'msd-core', 'workflows', '_runtime-launcher.snippet.sh');
const MSD_TOOLS_PATH = path.join(REPO_ROOT, 'msd-core', 'bin', 'msd-tools.cjs');
// A `cat`-under-blocked-stdin hang (G4) must be bounded well under this, but
// give the CI-shape headroom PROBE_TIMEOUT_MS documents for a short CLI call.
@@ -142,7 +142,7 @@ function extractAssignmentBlockFor(content, prefix, sourcePath) {
* @param {object} [options] - forwarded to runHook (cwd, env, timeoutMs).
*/
function runBashScript(t, script, options = {}) {
const scriptDir = createTempDir('gsd-3409-sh-');
const scriptDir = createTempDir('msd-3409-sh-');
t.after(() => cleanup(scriptDir));
const scriptPath = path.join(scriptDir, 'script.sh');
fs.writeFileSync(scriptPath, `#!/usr/bin/env bash\nset -e\n${script}`, { mode: 0o755 });
@@ -175,7 +175,7 @@ function parseKeyValueStdout(stdout) {
* (G2) case needs a nonzero prior-summary count.
*/
function buildPhase01Fixture({ withSummary }) {
const root = createTempDir('gsd-3409-fixture-');
const root = createTempDir('msd-3409-fixture-');
const phaseDir = path.join(root, '.planning', 'phases', '01-foundation');
fs.mkdirSync(phaseDir, { recursive: true });
if (withSummary) {
@@ -198,8 +198,8 @@ describe('#3409 G1/G2 — plan-phase.md Walking Skeleton gate observes a real su
const script = [
`. "${LAUNCHER_PATH}"`,
snippet,
'echo "GSD_TEST_WALKING_SKELETON=$WALKING_SKELETON"',
'echo "GSD_TEST_PRIOR_SUMMARIES=$PRIOR_SUMMARIES"',
'echo "MSD_TEST_WALKING_SKELETON=$WALKING_SKELETON"',
'echo "MSD_TEST_PRIOR_SUMMARIES=$PRIOR_SUMMARIES"',
].join('\n');
const result = runBashScript(t, script, {
cwd: projectRoot,
@@ -210,7 +210,7 @@ describe('#3409 G1/G2 — plan-phase.md Walking Skeleton gate observes a real su
padded_phase: '01',
},
// Bash FAN-OUT: the sourced `_runtime-launcher.snippet.sh` preamble
// defines the real `gsd_run` function, which the extracted snippet
// defines the real `msd_run` function, which the extracted snippet
// then calls — a bash + node invocation, not a single CLI probe. Same
// class as the observed CI failures in
// tests/quick-branching.test.cjs (PR #3787 run 32668773524) and
@@ -227,20 +227,20 @@ describe('#3409 G1/G2 — plan-phase.md Walking Skeleton gate observes a real su
test('G1: zero prior summaries — the gate observes a real integer 0, and fires', (t) => {
const root = buildPhase01Fixture({ withSummary: false });
t.after(() => cleanup(root));
const { GSD_TEST_WALKING_SKELETON, GSD_TEST_PRIOR_SUMMARIES } = runWalkingSkeletonGate(t, root);
const { MSD_TEST_WALKING_SKELETON, MSD_TEST_PRIOR_SUMMARIES } = runWalkingSkeletonGate(t, root);
// RED on the current tree: `--pick summaries_total` names a field that
// does not exist, so gsd-tools exits 0 with EMPTY stdout and the
// does not exist, so msd-tools exits 0 with EMPTY stdout and the
// unreachable `|| echo "0"` arm never fires — PRIOR_SUMMARIES is `""`,
// not the integer `"0"` this asserts.
assert.equal(GSD_TEST_PRIOR_SUMMARIES, '0', 'prior-summary count must resolve to the integer 0, not empty string');
assert.equal(GSD_TEST_WALKING_SKELETON, 'true', 'a fresh phase-01 project must enter Walking Skeleton mode');
assert.equal(MSD_TEST_PRIOR_SUMMARIES, '0', 'prior-summary count must resolve to the integer 0, not empty string');
assert.equal(MSD_TEST_WALKING_SKELETON, 'true', 'a fresh phase-01 project must enter Walking Skeleton mode');
});
test('G2 (load-bearing negative space): a project WITH prior summaries does not enter skeleton mode', (t) => {
const root = buildPhase01Fixture({ withSummary: true });
t.after(() => cleanup(root));
const { GSD_TEST_WALKING_SKELETON, GSD_TEST_PRIOR_SUMMARIES } = runWalkingSkeletonGate(t, root);
const { MSD_TEST_WALKING_SKELETON, MSD_TEST_PRIOR_SUMMARIES } = runWalkingSkeletonGate(t, root);
// RED on the current tree: PRIOR_SUMMARIES is `""` here too (same
// unreachable-arm defect), which fails this integer check even though
@@ -250,18 +250,18 @@ describe('#3409 G1/G2 — plan-phase.md Walking Skeleton gate observes a real su
// WALKING_SKELETON fire unconditionally, which the second assertion
// below also catches.
assert.match(
GSD_TEST_PRIOR_SUMMARIES,
MSD_TEST_PRIOR_SUMMARIES,
/^[1-9][0-9]*$/,
`prior-summary count must resolve to a nonzero integer, got ${JSON.stringify(GSD_TEST_PRIOR_SUMMARIES)}`,
`prior-summary count must resolve to a nonzero integer, got ${JSON.stringify(MSD_TEST_PRIOR_SUMMARIES)}`,
);
assert.equal(GSD_TEST_WALKING_SKELETON, 'false', 'a project with prior summaries must NOT enter Walking Skeleton mode');
assert.equal(MSD_TEST_WALKING_SKELETON, 'false', 'a project with prior summaries must NOT enter Walking Skeleton mode');
});
});
// ─── G3 — PHASE_REQ_IDS falls back to TBD (plan-phase.md) ─────────────────
test('#3409 G3: an empty phase_req_ids falls back to TBD, not the empty string', (t) => {
const root = createTempDir('gsd-3409-g3-');
const root = createTempDir('msd-3409-g3-');
t.after(() => cleanup(root));
fs.mkdirSync(path.join(root, '.planning', 'phases', '01-foundation'), { recursive: true });
// Deliberately no REQUIREMENTS.md / ROADMAP.md — phase 01 with zero
@@ -277,10 +277,10 @@ test('#3409 G3: an empty phase_req_ids falls back to TBD, not the empty string',
const script = [
`. "${LAUNCHER_PATH}"`,
block,
'echo "GSD_TEST_PHASE_REQ_IDS=$PHASE_REQ_IDS"',
'echo "MSD_TEST_PHASE_REQ_IDS=$PHASE_REQ_IDS"',
].join('\n');
// Bash FAN-OUT: same class as runWalkingSkeletonGate above — the sourced
// launcher's `gsd_run` shells out to node. See HOOK_FANOUT_TIMEOUT_MS in
// launcher's `msd_run` shells out to node. See HOOK_FANOUT_TIMEOUT_MS in
// ./helpers/timeouts.cjs for the class rationale.
const result = runBashScript(t, script, {
cwd: root,
@@ -290,12 +290,12 @@ test('#3409 G3: an empty phase_req_ids falls back to TBD, not the empty string',
assert.equal(result.outcome, OUTCOME.EXITED, `PHASE_REQ_IDS script did not exit cleanly: ${result.stderr}`);
assert.equal(result.exitCode, 0, `PHASE_REQ_IDS script exited non-zero: ${result.stderr}`);
const { GSD_TEST_PHASE_REQ_IDS } = parseKeyValueStdout(result.stdout);
const { MSD_TEST_PHASE_REQ_IDS } = parseKeyValueStdout(result.stdout);
// RED on the current tree: `--pick phase_req_ids` exits 0 with empty
// stdout on a `null` field, so the unreachable `|| echo TBD` arm never
// fires and PHASE_REQ_IDS resolves to `""` instead of the documented
// `TBD` sentinel (plan-phase.md: "Skip if phase_req_ids is null or TBD").
assert.equal(GSD_TEST_PHASE_REQ_IDS, 'TBD');
assert.equal(MSD_TEST_PHASE_REQ_IDS, 'TBD');
});
// ─── G4 — complete-milestone.md bare `cat <glob>` does not block on stdin ──
@@ -311,7 +311,7 @@ test('#3409 G4: the milestone summary read does not hang with no summaries', (t)
return;
}
const root = createTempDir('gsd-3409-g4-');
const root = createTempDir('msd-3409-g4-');
t.after(() => cleanup(root));
// Zero-summary milestone: a phase dir exists, but no *-SUMMARY.md file
// anywhere under it — the exact condition that makes the glob unmatched.
@@ -382,9 +382,9 @@ test('#3409 G4: the milestone summary read does not hang with no summaries', (t)
});
// Sanity: the module under test actually exists at the path every fixture
// above points `RUNTIME_DIR`/`gsd_run` at — a moved/renamed CLI would
// otherwise make every test above fail with a confusing "gsd-tools.cjs not
// above points `RUNTIME_DIR`/`msd_run` at — a moved/renamed CLI would
// otherwise make every test above fail with a confusing "msd-tools.cjs not
// found" error deep inside a bash script instead of a clear assertion here.
test('#3409: gsd-tools.cjs exists at the path this suite drives gsd_run through', () => {
assert.equal(fs.existsSync(GSD_TOOLS_PATH), true, `expected ${GSD_TOOLS_PATH} to exist`);
test('#3409: msd-tools.cjs exists at the path this suite drives msd_run through', () => {
assert.equal(fs.existsSync(MSD_TOOLS_PATH), true, `expected ${MSD_TOOLS_PATH} to exist`);
});