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

@@ -3,7 +3,7 @@
// runtime loads — testing text content tests the deployed contract.
/**
* GSD Tools Tests — Codebase Drift Detection (#2003)
* MSD Tools Tests — Codebase Drift Detection (#2003)
*
* Unit tests for bin/lib/drift.cjs plus CLI surface via verify codebase-drift.
* Exercises the four drift categories (new dir, barrel, migration, route),
@@ -21,16 +21,16 @@ const {
createTempProject,
createTempGitProject,
cleanup,
runGsdTools,
runMsdTools,
} = require('./helpers.cjs');
const { gitOrThrow, throwIfFailed } = require('./helpers/git-fixture.cjs');
const { runHook } = require('./helpers/process-seam.cjs');
const { scanFencedBlocks } = require('../gsd-core/bin/lib/markdown-sectionizer.cjs');
const { scanFencedBlocks } = require('../msd-core/bin/lib/markdown-sectionizer.cjs');
const DRIFT_PATH = path.join(
__dirname,
'..',
'gsd-core',
'msd-core',
'bin',
'lib',
'drift.cjs',
@@ -38,7 +38,7 @@ const DRIFT_PATH = path.join(
const CONFIG_SCHEMA_PATH = path.join(
__dirname,
'..',
'gsd-core',
'msd-core',
'bin',
'lib',
'config-schema.cjs',
@@ -360,7 +360,7 @@ describe('sanitizePaths', () => {
describe('last_mapped_commit frontmatter', () => {
let tmp;
beforeEach(() => {
tmp = createTempProject('gsd-drift-');
tmp = createTempProject('msd-drift-');
fs.mkdirSync(path.join(tmp, '.planning', 'codebase'), { recursive: true });
});
afterEach(() => cleanup(tmp));
@@ -484,7 +484,7 @@ describe('detectDrift — non-blocking guarantee', () => {
const CAPABILITY_REGISTRY_PATH = path.join(
__dirname,
'..',
'gsd-core',
'msd-core',
'bin',
'lib',
'capability-registry.cjs',
@@ -517,32 +517,32 @@ describe('config-schema — drift keys', () => {
describe('config-set drift validation via CLI', () => {
let tmp;
beforeEach(() => {
tmp = createTempGitProject('gsd-drift-cfg-');
tmp = createTempGitProject('msd-drift-cfg-');
});
afterEach(() => cleanup(tmp));
test('accepts warn', () => {
const r = runGsdTools(['config-set', 'workflow.drift_action', 'warn'], tmp);
const r = runMsdTools(['config-set', 'workflow.drift_action', 'warn'], tmp);
assert.strictEqual(r.success, true, r.error);
});
test('accepts auto-remap', () => {
const r = runGsdTools(['config-set', 'workflow.drift_action', 'auto-remap'], tmp);
const r = runMsdTools(['config-set', 'workflow.drift_action', 'auto-remap'], tmp);
assert.strictEqual(r.success, true, r.error);
});
test('rejects bogus drift_action value', () => {
const r = runGsdTools(['config-set', 'workflow.drift_action', 'sometimes'], tmp);
const r = runMsdTools(['config-set', 'workflow.drift_action', 'sometimes'], tmp);
assert.strictEqual(r.success, false);
});
test('drift_threshold accepts integer', () => {
const r = runGsdTools(['config-set', 'workflow.drift_threshold', '5'], tmp);
const r = runMsdTools(['config-set', 'workflow.drift_threshold', '5'], tmp);
assert.strictEqual(r.success, true, r.error);
});
test('drift_threshold rejects non-numeric', () => {
const r = runGsdTools(['config-set', 'workflow.drift_threshold', 'many'], tmp);
const r = runMsdTools(['config-set', 'workflow.drift_threshold', 'many'], tmp);
assert.strictEqual(r.success, false);
});
});
@@ -569,10 +569,10 @@ describe('docs parity', () => {
// ─── Mapper --paths flag documented ──────────────────────────────────────────
describe('gsd-codebase-mapper --paths flag', () => {
describe('msd-codebase-mapper --paths flag', () => {
test('agent doc mentions --paths', () => {
const doc = fs.readFileSync(
path.join(__dirname, '..', 'agents', 'gsd-codebase-mapper.md'),
path.join(__dirname, '..', 'agents', 'msd-codebase-mapper.md'),
'utf8',
);
assert.ok(/--paths/.test(doc));
@@ -591,7 +591,7 @@ describe('gsd-codebase-mapper --paths flag', () => {
path.join(
__dirname,
'..',
'gsd-core',
'msd-core',
'workflows',
'map-codebase.md',
),
@@ -606,7 +606,7 @@ describe('gsd-codebase-mapper --paths flag', () => {
// After ADR-857 phase-6 migration, codebase_drift_gate is no longer an inline
// step in execute-phase.md. Instead, it is declared as a gate in the `drift`
// capability at the `execute:wave:post` hook point. The execute-phase.md
// dispatches capability gates via `gsd_run loop render-hooks execute:wave:post`,
// dispatches capability gates via `msd_run loop render-hooks execute:wave:post`,
// which fires the drift gates automatically.
describe('execute-phase integrates codebase_drift_gate', () => {
@@ -619,7 +619,7 @@ describe('execute-phase integrates codebase_drift_gate', () => {
path.join(
__dirname,
'..',
'gsd-core',
'msd-core',
'workflows',
'execute-phase.md',
),
@@ -651,7 +651,7 @@ describe('execute-phase integrates codebase_drift_gate', () => {
path.join(
__dirname,
'..',
'gsd-core',
'msd-core',
'workflows',
'execute-phase.md',
),
@@ -666,13 +666,13 @@ describe('execute-phase integrates codebase_drift_gate', () => {
describe('verify codebase-drift CLI', () => {
let tmp;
beforeEach(() => {
tmp = createTempGitProject('gsd-drift-cli-');
tmp = createTempGitProject('msd-drift-cli-');
fs.mkdirSync(path.join(tmp, '.planning', 'codebase'), { recursive: true });
});
afterEach(() => cleanup(tmp));
test('returns skipped JSON when STRUCTURE.md missing', () => {
const r = runGsdTools(['verify', 'codebase-drift'], tmp);
const r = runMsdTools(['verify', 'codebase-drift'], tmp);
assert.strictEqual(r.success, true, r.error);
const data = JSON.parse(r.output);
assert.strictEqual(data.skipped, true);
@@ -684,7 +684,7 @@ describe('verify codebase-drift CLI', () => {
fs.writeFileSync(structure, '# Codebase Structure\n\n- `src/`\n');
const head = git(tmp, 'rev-parse', 'HEAD');
writeMappedCommit(structure, head, '2026-04-22');
const r = runGsdTools(['verify', 'codebase-drift'], tmp);
const r = runMsdTools(['verify', 'codebase-drift'], tmp);
assert.strictEqual(r.success, true, r.error);
const data = JSON.parse(r.output);
assert.strictEqual(data.action_required, false);
@@ -704,7 +704,7 @@ describe('verify codebase-drift CLI', () => {
}
git(tmp, 'add', '-A');
git(tmp, 'commit', '-m', 'add packages');
const r = runGsdTools(['verify', 'codebase-drift'], tmp);
const r = runMsdTools(['verify', 'codebase-drift'], tmp);
assert.strictEqual(r.success, true, r.error);
const data = JSON.parse(r.output);
assert.strictEqual(data.action_required, true);
@@ -736,7 +736,7 @@ describe('verify codebase-drift CLI', () => {
git(tmp, 'add', '-A');
git(tmp, 'commit', '-m', 'add non-ascii doc');
const r = runGsdTools(['verify', 'codebase-drift'], tmp);
const r = runMsdTools(['verify', 'codebase-drift'], tmp);
assert.strictEqual(r.success, true, r.error);
const data = JSON.parse(r.output);
// The file lives under a DOCUMENTED directory — it is mapped, not drift:
@@ -776,7 +776,7 @@ describe('verify codebase-drift CLI', () => {
git(tmp, 'add', '-A');
git(tmp, 'commit', '-m', 'add non-ascii dir');
const r = runGsdTools(['verify', 'codebase-drift'], tmp);
const r = runMsdTools(['verify', 'codebase-drift'], tmp);
assert.strictEqual(r.success, true, r.error);
const data = JSON.parse(r.output);
assert.strictEqual(data.action_required, true, 'undocumented dir must stay drift');
@@ -815,7 +815,7 @@ describe('verify codebase-drift CLI', () => {
git(tmp, 'add', '-A');
git(tmp, 'commit', '-m', 'rename to non-ascii');
const r = runGsdTools(['verify', 'codebase-drift'], tmp);
const r = runMsdTools(['verify', 'codebase-drift'], tmp);
assert.strictEqual(r.success, true, r.error);
const data = JSON.parse(r.output);
const leaked = JSON.stringify(data.elements.map((el) => el.path));
@@ -824,9 +824,9 @@ describe('verify codebase-drift CLI', () => {
});
test('never exits non-zero when git repo is missing (non-blocking)', () => {
const nonGit = createTempProject('gsd-drift-nongit-');
const nonGit = createTempProject('msd-drift-nongit-');
try {
const r = runGsdTools(['verify', 'codebase-drift'], nonGit);
const r = runMsdTools(['verify', 'codebase-drift'], nonGit);
assert.strictEqual(r.success, true, 'must exit 0 even without git');
const data = JSON.parse(r.output);
assert.strictEqual(data.skipped, true);
@@ -845,7 +845,7 @@ describe('verify codebase-drift CLI', () => {
describe('verify codebase-drift — workflow config read from nested shape (#1493)', () => {
let tmp;
beforeEach(() => {
tmp = createTempGitProject('gsd-drift-1493-');
tmp = createTempGitProject('msd-drift-1493-');
fs.mkdirSync(path.join(tmp, '.planning', 'codebase'), { recursive: true });
});
afterEach(() => cleanup(tmp));
@@ -872,7 +872,7 @@ describe('verify codebase-drift — workflow config read from nested shape (#149
git(tmp, 'add', '-A');
git(tmp, 'commit', '-m', 'add package barrel');
const r = runGsdTools(['verify', 'codebase-drift'], tmp);
const r = runMsdTools(['verify', 'codebase-drift'], tmp);
assert.strictEqual(r.success, true, r.error);
const data = JSON.parse(r.output);
assert.strictEqual(
@@ -900,7 +900,7 @@ describe('verify codebase-drift — workflow config read from nested shape (#149
git(tmp, 'add', '-A');
git(tmp, 'commit', '-m', 'add one package barrel');
const r = runGsdTools(['verify', 'codebase-drift'], tmp);
const r = runMsdTools(['verify', 'codebase-drift'], tmp);
assert.strictEqual(r.success, true, r.error);
const data = JSON.parse(r.output);
assert.strictEqual(data.threshold, 100,
@@ -919,11 +919,11 @@ describe('verify codebase-drift — workflow config read from nested shape (#149
__foldDescribe("folded:bug-619-codebase-drift-gate-shim (consolidation epic #1969 B6 #1975)", () => {
// allow-test-rule: source-text-is-the-product (see #619)
// codebase-drift-gate.md is the shipped orchestration step contract. Bug #619:
// the initial drift check ran the bare PATH binary `gsd-tools verify codebase-drift`.
// On a shim-only install (gsd-tools.cjs present, `gsd-tools` not on PATH) that exits
// the initial drift check ran the bare PATH binary `msd-tools verify codebase-drift`.
// On a shim-only install (msd-tools.cjs present, `msd-tools` not on PATH) that exits
// 127, `2>/dev/null` hides it, and the `|| echo` fallback marks the gate skipped —
// so post-execution drift detection silently never runs. The fix resolves gsd-tools
// through the runtime shim launcher (gsd_run), defining the canonical preamble once in
// so post-execution drift detection silently never runs. The fix resolves msd-tools
// through the runtime shim launcher (msd_run), defining the canonical preamble once in
// this always-run block so the file stays compliant with the single-preamble parity
// invariant (the conditional auto-remap block reuses the launcher via shared shell scope).
//
@@ -941,9 +941,9 @@ const path = require('node:path');
const { cleanup, readFileNormalized } = require('./helpers.cjs');
const GATE_MD = path.join(
__dirname, '..', 'gsd-core', 'workflows', 'execute-phase', 'steps', 'codebase-drift-gate.md',
__dirname, '..', 'msd-core', 'workflows', 'execute-phase', 'steps', 'codebase-drift-gate.md',
);
const SNIPPET_FILE = path.join(__dirname, '..', 'gsd-core', 'workflows', '_runtime-launcher.snippet.sh');
const SNIPPET_FILE = path.join(__dirname, '..', 'msd-core', 'workflows', '_runtime-launcher.snippet.sh');
// readFileNormalized() strips \r\n -> \n before bashBlock() slices a fence
// out of the result and hands it to runHook('-c', ..., {interpreter:'bash'})
@@ -966,24 +966,24 @@ function bashBlock(content, n) {
return blocks[n];
}
describe('bug #619 — codebase-drift-gate resolves gsd-tools via the runtime shim, not the bare PATH binary', () => {
describe('bug #619 — codebase-drift-gate resolves msd-tools via the runtime shim, not the bare PATH binary', () => {
test('codebase-drift-gate.md is readable', () => {
assert.ok(readGate().length > 0, 'codebase-drift-gate.md must not be empty');
});
// ── Source contract (the .md is the product) ──────────────────────────────
test('the drift check resolves gsd-tools via the shim launcher (gsd_run), not the bare binary (#619)', () => {
test('the drift check resolves msd-tools via the shim launcher (msd_run), not the bare binary (#619)', () => {
const content = readGate();
assert.match(
content,
/DRIFT=\$\(gsd_run verify codebase-drift 2>\/dev\/null \|\| echo '\{"skipped":true,"reason":"sdk-failed"\}'\)/,
'drift check must call `gsd_run verify codebase-drift` with the non-blocking skip fallback',
/DRIFT=\$\(msd_run verify codebase-drift 2>\/dev\/null \|\| echo '\{"skipped":true,"reason":"sdk-failed"\}'\)/,
'drift check must call `msd_run verify codebase-drift` with the non-blocking skip fallback',
);
assert.doesNotMatch(
content,
/\bgsd-tools verify codebase-drift\b/,
'the bare `gsd-tools verify codebase-drift` PATH-binary call (the #619 bug) must be gone',
/\bmsd-tools verify codebase-drift\b/,
'the bare `msd-tools verify codebase-drift` PATH-binary call (the #619 bug) must be gone',
);
});
@@ -1015,25 +1015,25 @@ describe('bug #619 — codebase-drift-gate resolves gsd-tools via the runtime sh
const block0 = bashBlock(content, 0);
assert.ok(block0.includes(snippet), 'the canonical preamble must be in the drift-check block');
assert.ok(
block0.indexOf(snippet) < block0.indexOf('gsd_run verify codebase-drift'),
'the preamble must precede the gsd_run drift call in the same block',
block0.indexOf(snippet) < block0.indexOf('msd_run verify codebase-drift'),
'the preamble must precede the msd_run drift call in the same block',
);
// The auto-remap block reuses gsd_run but must NOT carry its own preamble.
// The auto-remap block reuses msd_run but must NOT carry its own preamble.
const content2 = content.slice(content.indexOf('AGENT_SKILLS_MAPPER'));
assert.ok(!content2.includes(snippet), 'the auto-remap block must not re-declare the preamble (single-preamble parity)');
});
// ── Behavioral proof: the shim resolves on a shim-only topology ───────────
test('shipped drift-check block runs the shim (gsd-tools.cjs), not skip, on a shim-only install (#619)', () => {
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-619-'));
test('shipped drift-check block runs the shim (msd-tools.cjs), not skip, on a shim-only install (#619)', () => {
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-619-'));
try {
// Shim-only topology: gsd-tools.cjs present under RUNTIME_DIR; no `gsd-tools` on PATH.
const binDir = path.join(tmp, 'gsd-core', 'bin');
// Shim-only topology: msd-tools.cjs present under RUNTIME_DIR; no `msd-tools` on PATH.
const binDir = path.join(tmp, 'msd-core', 'bin');
fs.mkdirSync(binDir, { recursive: true });
fs.writeFileSync(
path.join(binDir, 'gsd-tools.cjs'),
path.join(binDir, 'msd-tools.cjs'),
'if (process.argv[2] === "verify" && process.argv[3] === "codebase-drift") {\n' +
' process.stdout.write(JSON.stringify({ action_required: false, sentinel: "SHIM_RAN" }));\n' +
'}\n',
@@ -1047,25 +1047,25 @@ describe('bug #619 — codebase-drift-gate resolves gsd-tools via the runtime sh
throwIfFailed(shimResult, 'bash -c <shim-only drift-check block>');
const out = shimResult.stdout;
assert.match(out, /SHIM_RAN/, 'the drift check must execute the resolved shim, proving gsd_run resolution');
assert.match(out, /SHIM_RAN/, 'the drift check must execute the resolved shim, proving msd_run resolution');
assert.doesNotMatch(out, /sdk-failed/, 'the gate must NOT silently skip when the shim is present (#619)');
} finally {
cleanup(tmp);
}
});
test('red-proof: the old bare `gsd-tools` form would skip when gsd-tools is not on PATH', () => {
// Documents the #619 bug: the pre-fix bare-binary call, with no `gsd-tools` on PATH,
// hits the 127 → `|| echo` skip path even though the shim (gsd-tools.cjs) exists.
test('red-proof: the old bare `msd-tools` form would skip when msd-tools is not on PATH', () => {
// Documents the #619 bug: the pre-fix bare-binary call, with no `msd-tools` on PATH,
// hits the 127 → `|| echo` skip path even though the shim (msd-tools.cjs) exists.
const oldForm =
'DRIFT=$(gsd-tools verify codebase-drift 2>/dev/null || echo \'{"skipped":true,"reason":"sdk-failed"}\'); printf "%s" "$DRIFT"';
'DRIFT=$(msd-tools verify codebase-drift 2>/dev/null || echo \'{"skipped":true,"reason":"sdk-failed"}\'); printf "%s" "$DRIFT"';
const oldFormResult = runHook('-c', ['export PATH=/nonexistent-empty-path; ' + oldForm], {
interpreter: 'bash',
env: { ...process.env },
});
throwIfFailed(oldFormResult, 'bash -c <#619 bare-binary red-proof>');
const out = oldFormResult.stdout;
assert.match(out, /sdk-failed/, 'sanity: the bare-binary form skips without gsd-tools on PATH — the bug the fix removes');
assert.match(out, /sdk-failed/, 'sanity: the bare-binary form skips without msd-tools on PATH — the bug the fix removes');
});
});
});
@@ -1074,7 +1074,7 @@ describe('bug #619 — codebase-drift-gate resolves gsd-tools via the runtime sh
// ─── Regression #3418: the drift baseline is written by code, not by prose ───
//
// `writeMappedCommit` shipped correct and callerless: nothing in the tree
// invoked it, so a full `/gsd:map-codebase` run wrote no `last_mapped_commit`.
// invoked it, so a full `/msd:map-codebase` run wrote no `last_mapped_commit`.
// `cmdVerifyCodebaseDrift` then read null and fell back to diffing HEAD against
// the empty tree, so every tracked file read as newly added and the gate
// reported maximum drift identically on every run. Two halves, tested here:
@@ -1097,7 +1097,7 @@ describe('stamp-codebase-map CLI (#3418)', () => {
}
beforeEach(() => {
tmp = createTempGitProject('gsd-stamp-3418-');
tmp = createTempGitProject('msd-stamp-3418-');
codebaseDir = path.join(tmp, '.planning', 'codebase');
fs.mkdirSync(codebaseDir, { recursive: true });
});
@@ -1107,7 +1107,7 @@ describe('stamp-codebase-map CLI (#3418)', () => {
writeMap();
const head = git(tmp, 'rev-parse', 'HEAD');
const r = runGsdTools(['stamp-codebase-map'], tmp);
const r = runMsdTools(['stamp-codebase-map'], tmp);
assert.strictEqual(r.success, true, r.error);
const data = JSON.parse(r.output);
@@ -1131,7 +1131,7 @@ describe('stamp-codebase-map CLI (#3418)', () => {
const fastDocs = ['STACK.md', 'INTEGRATIONS.md', 'ARCHITECTURE.md', 'STRUCTURE.md'];
writeMap(fastDocs);
const r = runGsdTools(['stamp-codebase-map'], tmp);
const r = runMsdTools(['stamp-codebase-map'], tmp);
assert.strictEqual(r.success, true, r.error);
const data = JSON.parse(r.output);
@@ -1150,7 +1150,7 @@ describe('stamp-codebase-map CLI (#3418)', () => {
// currency they do not have.
writeMap();
const r = runGsdTools(
const r = runMsdTools(
['stamp-codebase-map', '--files', 'STRUCTURE.md,ARCHITECTURE.md'], tmp,
);
assert.strictEqual(r.success, true, r.error);
@@ -1164,7 +1164,7 @@ describe('stamp-codebase-map CLI (#3418)', () => {
test('--files with an empty value stamps nothing rather than all seven (#4124 review)', () => {
writeMap();
const r = runGsdTools(['stamp-codebase-map', '--files', ''], tmp);
const r = runMsdTools(['stamp-codebase-map', '--files', ''], tmp);
assert.strictEqual(r.success, true, 'must stay non-blocking');
const data = JSON.parse(r.output);
@@ -1177,7 +1177,7 @@ describe('stamp-codebase-map CLI (#3418)', () => {
test('a bare --files stamps nothing rather than all seven (#4124 review)', () => {
writeMap();
const r = runGsdTools(['stamp-codebase-map', '--files'], tmp);
const r = runMsdTools(['stamp-codebase-map', '--files'], tmp);
assert.strictEqual(r.success, true, 'must stay non-blocking');
const data = JSON.parse(r.output);
@@ -1190,7 +1190,7 @@ describe('stamp-codebase-map CLI (#3418)', () => {
test('--files with an unknown name stamps nothing and reports why (#3418)', () => {
writeMap();
const r = runGsdTools(['stamp-codebase-map', '--files', '../../etc/passwd'], tmp);
const r = runMsdTools(['stamp-codebase-map', '--files', '../../etc/passwd'], tmp);
assert.strictEqual(r.success, true, 'must stay non-blocking');
const data = JSON.parse(r.output);
@@ -1202,13 +1202,13 @@ describe('stamp-codebase-map CLI (#3418)', () => {
});
test('skips without a git repo instead of failing the run (#3418)', () => {
const nonGit = createTempProject('gsd-stamp-nongit-');
const nonGit = createTempProject('msd-stamp-nongit-');
try {
fs.mkdirSync(path.join(nonGit, '.planning', 'codebase'), { recursive: true });
fs.writeFileSync(
path.join(nonGit, '.planning', 'codebase', 'STRUCTURE.md'), '# STRUCTURE\n',
);
const r = runGsdTools(['stamp-codebase-map'], nonGit);
const r = runMsdTools(['stamp-codebase-map'], nonGit);
assert.strictEqual(r.success, true, 'must exit 0 outside a git repo');
const data = JSON.parse(r.output);
assert.strictEqual(data.skipped, true);
@@ -1219,7 +1219,7 @@ describe('stamp-codebase-map CLI (#3418)', () => {
});
test('skips when no codebase map exists (#3418)', () => {
const r = runGsdTools(['stamp-codebase-map'], tmp);
const r = runMsdTools(['stamp-codebase-map'], tmp);
assert.strictEqual(r.success, true, r.error);
const data = JSON.parse(r.output);
assert.strictEqual(data.skipped, true);
@@ -1230,14 +1230,14 @@ describe('stamp-codebase-map CLI (#3418)', () => {
// The end-to-end loop the issue reported broken: map, stamp, commit, then
// ask the gate. Before the fix this reported every tracked file as drift.
writeMap();
const r1 = runGsdTools(['stamp-codebase-map'], tmp);
const r1 = runMsdTools(['stamp-codebase-map'], tmp);
assert.strictEqual(r1.success, true, r1.error);
const stampedAt = JSON.parse(r1.output).commit;
git(tmp, 'add', '-A');
git(tmp, 'commit', '-m', 'map codebase');
const r2 = runGsdTools(['verify', 'codebase-drift'], tmp);
const r2 = runMsdTools(['verify', 'codebase-drift'], tmp);
assert.strictEqual(r2.success, true, r2.error);
const data = JSON.parse(r2.output);
@@ -1250,16 +1250,16 @@ describe('stamp-codebase-map CLI (#3418)', () => {
test('the map\'s own commit does not read as drift on the next run (#3418)', () => {
// The stamp is written before `.planning/codebase/*.md` is committed, so
// the commit carrying the baseline lands after it. Counting GSD's own
// the commit carrying the baseline lands after it. Counting MSD's own
// planning artifacts as codebase structure would re-poison the gate with
// seven new directories -- over the default threshold of three -- on the
// first invocation after a clean map.
writeMap();
runGsdTools(['stamp-codebase-map'], tmp);
runMsdTools(['stamp-codebase-map'], tmp);
git(tmp, 'add', '-A');
git(tmp, 'commit', '-m', 'map codebase');
const data = JSON.parse(runGsdTools(['verify', 'codebase-drift'], tmp).output);
const data = JSON.parse(runMsdTools(['verify', 'codebase-drift'], tmp).output);
assert.strictEqual(data.action_required, false,
'the map documents are planning artifacts, not codebase structure');
assert.deepStrictEqual(data.affected_paths, []);
@@ -1276,7 +1276,7 @@ describe('stamp-codebase-map CLI (#3418)', () => {
pid: 999999, cwd: tmp, acquired: new Date(0).toISOString(),
}));
const r = runGsdTools(['stamp-codebase-map'], tmp);
const r = runMsdTools(['stamp-codebase-map'], tmp);
assert.strictEqual(r.success, true, r.error);
assert.strictEqual(JSON.parse(r.output).skipped, false);
assert.strictEqual(fs.existsSync(lockPath), false,
@@ -1294,12 +1294,12 @@ describe('stamp-codebase-map CLI (#3418)', () => {
fs.writeFileSync(path.join(subCodebase, doc), `# ${doc}\n\nBody.\n`);
}
const r1 = runGsdTools(['stamp-codebase-map'], sub);
const r1 = runMsdTools(['stamp-codebase-map'], sub);
assert.strictEqual(r1.success, true, r1.error);
git(tmp, 'add', '-A');
git(tmp, 'commit', '-m', 'map codebase from a subdirectory');
const data = JSON.parse(runGsdTools(['verify', 'codebase-drift'], sub).output);
const data = JSON.parse(runMsdTools(['verify', 'codebase-drift'], sub).output);
assert.strictEqual(data.skipped, false);
assert.strictEqual(data.action_required, false,
'the map documents under sub/.planning are still planning artifacts');
@@ -1312,7 +1312,7 @@ describe('verify codebase-drift: an absent baseline is not total drift (#3418)',
let structure;
beforeEach(() => {
tmp = createTempGitProject('gsd-drift-3418-');
tmp = createTempGitProject('msd-drift-3418-');
fs.mkdirSync(path.join(tmp, '.planning', 'codebase'), { recursive: true });
structure = path.join(tmp, '.planning', 'codebase', 'STRUCTURE.md');
@@ -1330,7 +1330,7 @@ describe('verify codebase-drift: an absent baseline is not total drift (#3418)',
afterEach(() => cleanup(tmp));
test('an unstamped STRUCTURE.md skips with no-mapped-commit (#3418)', () => {
const r = runGsdTools(['verify', 'codebase-drift'], tmp);
const r = runMsdTools(['verify', 'codebase-drift'], tmp);
assert.strictEqual(r.success, true, r.error);
const data = JSON.parse(r.output);
@@ -1351,7 +1351,7 @@ describe('verify codebase-drift: an absent baseline is not total drift (#3418)',
// empty tree.
writeMappedCommit(structure, 'deadbeef'.repeat(5), '2026-04-22');
const r = runGsdTools(['verify', 'codebase-drift'], tmp);
const r = runMsdTools(['verify', 'codebase-drift'], tmp);
assert.strictEqual(r.success, true, r.error);
const data = JSON.parse(r.output);
@@ -1369,7 +1369,7 @@ describe('verify codebase-drift: an absent baseline is not total drift (#3418)',
const tree = git(tmp, 'rev-parse', 'HEAD^{tree}');
writeMappedCommit(structure, tree, '2026-04-22');
const r = runGsdTools(['verify', 'codebase-drift'], tmp);
const r = runMsdTools(['verify', 'codebase-drift'], tmp);
assert.strictEqual(r.success, true, r.error);
const data = JSON.parse(r.output);