Files
msd-core/tests/inventory-manifest-sync.test.cjs
Behruz Nassre Esfahani fc5ca178a2 test(#1178): consolidate duplicated agent-roster helper into tests/helpers (#1420)
* test(#1178): consolidate duplicated agent-roster helper into tests/helpers

The "list gsd-*.md agent files, strip .md, sort" derivation was hand-duplicated
across the suite (two listAgentFiles(), an identical agentFilesOnDisk(), and
inline readdir blocks). Add tests/helpers/agent-roster.cjs exporting
listAgentFiles(agentsDir?) and route the genuinely-identical source-roster sites
through it. Semantically-different sites (installed-dest dirs, absolute-path
returns, .toml-inclusive Codex rosters, full-.md-filename readers, the uniform
multi-family inventory table) are left intact, each with a one-line comment.

Test-only; no production code touched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(#1178): note AGENTS_DIR export is for future call sites

Review nit: clarify that the currently-unused AGENTS_DIR export is intentional
— available for future tests needing the canonical source agents path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Tom Boucher <trekkie@nomorestars.com>
2026-06-23 19:34:08 -04:00

58 lines
2.8 KiB
JavaScript

'use strict';
/**
* Asserts docs/INVENTORY-MANIFEST.json is in sync with the filesystem.
* A stale manifest means a surface shipped without updating INVENTORY.md.
* Fix by running: node scripts/gen-inventory-manifest.cjs --write
* then adding the corresponding row(s) in docs/INVENTORY.md.
*/
const { test } = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const ROOT = path.resolve(__dirname, '..');
const MANIFEST_PATH = path.join(ROOT, 'docs', 'INVENTORY-MANIFEST.json');
// The `agents` row is NOT swapped to the shared listAgentFiles() helper: it is one
// row in a uniform multi-family table (each with its own filter/toName + an isFile
// guard); folding only agents in would break that uniformity.
const FAMILIES = [
{ name: 'agents', dir: path.join(ROOT, 'agents'), filter: (f) => /^gsd-.*\.md$/.test(f), toName: (f) => f.replace(/\.md$/, '') },
{ name: 'commands', dir: path.join(ROOT, 'commands', 'gsd'), filter: (f) => f.endsWith('.md'), toName: (f) => '/gsd-' + f.replace(/\.md$/, '') },
{ name: 'workflows', dir: path.join(ROOT, 'gsd-core', 'workflows'), filter: (f) => f.endsWith('.md'), toName: (f) => f },
{ name: 'references', dir: path.join(ROOT, 'gsd-core', 'references'), filter: (f) => f.endsWith('.md'), toName: (f) => f },
{ name: 'cli_modules', dir: path.join(ROOT, 'gsd-core', 'bin', 'lib'), filter: (f) => f.endsWith('.cjs'), toName: (f) => f },
{ name: 'hooks', dir: path.join(ROOT, 'hooks'), filter: (f) => /\.(js|sh)$/.test(f), toName: (f) => f },
];
test('docs/INVENTORY-MANIFEST.json matches the filesystem', () => {
const committed = JSON.parse(fs.readFileSync(MANIFEST_PATH, 'utf8'));
const additions = [];
const removals = [];
for (const { name, dir, filter, toName } of FAMILIES) {
const live = new Set(
fs.readdirSync(dir)
.filter((f) => fs.statSync(path.join(dir, f)).isFile() && filter(f))
.map(toName),
);
const recorded = new Set((committed.families || {})[name] || []);
for (const entry of live) {
if (!recorded.has(entry)) additions.push(name + '/' + entry);
}
for (const entry of recorded) {
if (!live.has(entry)) removals.push(name + '/' + entry);
}
}
const msg = [
additions.length ? 'New surfaces not in manifest (run node scripts/gen-inventory-manifest.cjs --write):\n' + additions.map((e) => ' + ' + e).join('\n') : '',
removals.length ? 'Manifest entries with no matching file:\n' + removals.map((e) => ' - ' + e).join('\n') : '',
].filter(Boolean).join('\n');
assert.ok(additions.length === 0 && removals.length === 0, msg);
});