Files
msd-core/tests/retired-artifact-cleanup.test.cjs
Jakub Zych a9a7a328e6 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.
2026-10-06 01:47:40 +02:00

156 lines
6.4 KiB
JavaScript

'use strict';
const { test } = require('node:test');
const assert = require('node:assert/strict');
const crypto = require('node:crypto');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const retiredArtifactCleanup = require('../msd-core/bin/lib/retired-artifact-cleanup.cjs');
const capabilityRegistry = require('../msd-core/bin/lib/capability-registry.cjs');
const cursorBehaviors = capabilityRegistry.runtimes.cursor.runtime.hostBehaviors;
function createFixture(t) {
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-retired-cleanup-'));
const configDir = path.join(root, 'config');
fs.mkdirSync(configDir, { recursive: true });
t.after(() => {
// eslint-disable-next-line local/no-raw-rmsync-in-tests -- isolated temp fixture cleanup
fs.rmSync(root, { recursive: true, force: true });
});
return { root, configDir };
}
function setDeclarations(t, declarations) {
const original = cursorBehaviors.retiredArtifacts;
cursorBehaviors.retiredArtifacts = declarations;
t.after(() => {
cursorBehaviors.retiredArtifacts = original;
});
}
function writeFile(root, relPath, content) {
const filePath = path.join(root, relPath);
fs.mkdirSync(path.dirname(filePath), { recursive: true });
fs.writeFileSync(filePath, content, 'utf8');
return filePath;
}
function sha256(content) {
return crypto.createHash('sha256').update(content).digest('hex');
}
function writeManifest(configDir, files) {
fs.writeFileSync(path.join(configDir, 'msd-file-manifest.json'), JSON.stringify({
version: '1.8.0',
timestamp: '2026-07-28T00:00:00.000Z',
mode: 'full',
files,
}), 'utf8');
}
test('rejects malformed and escaping retired-artifact declarations', (t) => {
const { root, configDir } = createFixture(t);
const outsideFile = writeFile(root, 'escape/msd-help.md', '# outside\n');
const localFile = writeFile(configDir, 'commands/msd-help.md', '# local\n');
setDeclarations(t, [
{ destSubpath: null, prefix: 'msd-', suffix: '.md' },
{ destSubpath: '../escape', prefix: 'msd-', suffix: '.md' },
]);
const result = retiredArtifactCleanup.pruneRetiredRuntimeArtifacts('cursor', configDir);
assert.deepEqual(result, { removed: [], preserved: [] });
assert.ok(fs.existsSync(outsideFile), 'an escaping destination must never be touched');
assert.ok(fs.existsSync(localFile), 'a malformed declaration must not affect valid-looking files');
});
test('refuses a symlinked retired destination directory', (t) => {
const { root, configDir } = createFixture(t);
const targetDir = path.join(root, 'outside-commands');
const targetFile = writeFile(targetDir, 'msd-help.md', '# outside\n');
const linkType = process.platform === 'win32' ? 'junction' : 'dir';
fs.symlinkSync(targetDir, path.join(configDir, 'commands'), linkType);
setDeclarations(t, [{ destSubpath: 'commands', prefix: 'msd-', suffix: '.md' }]);
const result = retiredArtifactCleanup.pruneRetiredRuntimeArtifacts('cursor', configDir);
assert.deepEqual(result, { removed: [], preserved: [] });
assert.ok(fs.existsSync(targetFile), 'cleanup must not follow the destination symlink');
});
test('preserves and reports a user-modified managed file', (t) => {
const { configDir } = createFixture(t);
const relPath = 'commands/msd-help.md';
const originalContent = '# generated\n';
const modifiedContent = '# user changed this\n';
const filePath = writeFile(configDir, relPath, modifiedContent);
writeManifest(configDir, { [relPath]: sha256(originalContent) });
setDeclarations(t, [{ destSubpath: 'commands', prefix: 'msd-', suffix: '.md' }]);
const result = retiredArtifactCleanup.pruneRetiredRuntimeArtifacts('cursor', configDir);
assert.deepEqual(result, { removed: [], preserved: [relPath] });
assert.equal(fs.readFileSync(filePath, 'utf8'), modifiedContent);
assert.ok(fs.existsSync(path.dirname(filePath)), 'directory must remain while a preserved file exists');
});
test('removes and reports a managed-pristine file and then removes the empty directory', (t) => {
const { configDir } = createFixture(t);
const relPath = 'commands/msd-help.md';
const content = '# generated\n';
const filePath = writeFile(configDir, relPath, content);
const commandsDir = path.dirname(filePath);
writeManifest(configDir, { [relPath]: sha256(content) });
setDeclarations(t, [{ destSubpath: 'commands', prefix: 'msd-', suffix: '.md' }]);
const result = retiredArtifactCleanup.pruneRetiredRuntimeArtifacts('cursor', configDir);
assert.deepEqual(result, { removed: [relPath], preserved: [] });
assert.ok(!fs.existsSync(filePath));
assert.ok(!fs.existsSync(commandsDir), 'an empty retired destination should be removed');
});
test('leaves non-matching files untouched and keeps their directory', (t) => {
const { configDir } = createFixture(t);
const managedRelPath = 'commands/msd-help.md';
const managedContent = '# generated\n';
const managedFile = writeFile(configDir, managedRelPath, managedContent);
const unrelatedFile = writeFile(configDir, 'commands/user-command.md', '# user\n');
writeManifest(configDir, { [managedRelPath]: sha256(managedContent) });
setDeclarations(t, [{ destSubpath: 'commands', prefix: 'msd-', suffix: '.md' }]);
const result = retiredArtifactCleanup.pruneRetiredRuntimeArtifacts('cursor', configDir);
assert.deepEqual(result, { removed: [managedRelPath], preserved: [] });
assert.ok(!fs.existsSync(managedFile));
assert.ok(fs.existsSync(unrelatedFile));
assert.ok(fs.existsSync(path.dirname(unrelatedFile)), 'a non-empty destination must remain');
});
test('reports a managed-pristine file as preserved when unlinkSync fails', (t) => {
const { configDir } = createFixture(t);
const relPath = 'commands/msd-help.md';
const content = '# generated\n';
const filePath = writeFile(configDir, relPath, content);
writeManifest(configDir, { [relPath]: sha256(content) });
setDeclarations(t, [{ destSubpath: 'commands', prefix: 'msd-', suffix: '.md' }]);
const originalUnlinkSync = fs.unlinkSync;
fs.unlinkSync = (candidate) => {
if (path.resolve(candidate) === path.resolve(filePath)) throw new Error('injected unlink failure');
return originalUnlinkSync(candidate);
};
let result;
try {
result = retiredArtifactCleanup.pruneRetiredRuntimeArtifacts('cursor', configDir);
} finally {
fs.unlinkSync = originalUnlinkSync;
}
assert.deepEqual(result, { removed: [], preserved: [relPath] });
assert.ok(fs.existsSync(filePath), 'a failed unlink must leave the file in place');
});