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.
128 lines
5.3 KiB
JavaScript
128 lines
5.3 KiB
JavaScript
// allow-test-rule: source-text-is-the-product see #1866
|
|
// Agent .md files are the installed AI agents — the self-load instruction IS the deployed
|
|
// behavior. Checking text content IS checking what runs in production. Same exemption basis
|
|
// as tests/agent-skills-awareness.test.cjs (agent_skills is a config/state contract).
|
|
'use strict';
|
|
|
|
const { describe, test } = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const fc = require('fast-check');
|
|
|
|
const AGENTS_DIR = path.join(__dirname, '..', 'agents');
|
|
const REFS_DIR = path.join(__dirname, '..', 'msd-core', 'references');
|
|
const BOOTSTRAP_REF = 'agent-skills-bootstrap.md';
|
|
const BOOTSTRAP_PATH = path.join(REFS_DIR, BOOTSTRAP_REF);
|
|
|
|
// The 22 agent_skills consumer agents. This MUST stay in sync with the
|
|
// CONSUMER_AGENTS list in tests/agent-skills.test.cjs ("all 22 agent_skills
|
|
// consumer agents"). The parity test below enforces the bijection between
|
|
// this list and the set of agent files that carry the self-load bootstrap
|
|
// (Generative-Fix-Divergence guard — CLAUDE.md "Generative Fix Divergence").
|
|
const CONSUMER_AGENTS = [
|
|
'msd-advisor-researcher',
|
|
'msd-assumptions-analyzer',
|
|
'msd-code-fixer',
|
|
'msd-code-reviewer',
|
|
'msd-codebase-mapper',
|
|
'msd-debugger',
|
|
'msd-doc-writer',
|
|
'msd-eval-auditor',
|
|
'msd-executor',
|
|
'msd-integration-checker',
|
|
'msd-nyquist-auditor',
|
|
'msd-phase-researcher',
|
|
'msd-plan-checker',
|
|
'msd-planner',
|
|
'msd-project-researcher',
|
|
'msd-research-synthesizer',
|
|
'msd-roadmapper',
|
|
'msd-security-auditor',
|
|
'msd-ui-auditor',
|
|
'msd-ui-checker',
|
|
'msd-ui-researcher',
|
|
'msd-verifier',
|
|
];
|
|
|
|
function readAgent(name) {
|
|
return fs.readFileSync(path.join(AGENTS_DIR, `${name}.md`), 'utf8');
|
|
}
|
|
|
|
function allAgentFiles() {
|
|
// #4407: .compact.md variant siblings carry the same self-load line as their
|
|
// canonical agent (preserved verbatim by design) but are not a distinct
|
|
// consumer identity — exclude them from the CONSUMER_AGENTS bijection.
|
|
return fs.readdirSync(AGENTS_DIR).filter((f) => f.endsWith('.md') && !f.endsWith('.compact.md'));
|
|
}
|
|
|
|
describe('agent_skills self-load bootstrap', () => {
|
|
test('bootstrap reference file exists at msd-core/references/', () => {
|
|
assert.ok(fs.existsSync(BOOTSTRAP_PATH), `missing bootstrap reference: ${BOOTSTRAP_PATH}`);
|
|
});
|
|
|
|
test('bootstrap documents the dedup guard + frontmatter-name query', () => {
|
|
assert.ok(fs.existsSync(BOOTSTRAP_PATH), 'bootstrap missing');
|
|
const content = fs.readFileSync(BOOTSTRAP_PATH, 'utf8');
|
|
assert.ok(/<agent_skills>/.test(content), 'bootstrap must name the <agent_skills> block');
|
|
// Dedup guard (C2): must instruct the agent to skip self-load when the
|
|
// orchestrator already injected an <agent_skills> block, so the prompt
|
|
// never carries two copies on runtimes where orchestrator injection runs.
|
|
assert.ok(/skip/i.test(content) && /already/i.test(content),
|
|
'bootstrap must document the dedup guard (skip when <agent_skills> already present)');
|
|
// The bootstrap uses the agent's own frontmatter name as the query type —
|
|
// there is no per-agent name baked into each agent file (keeps each file
|
|
// small and the wording uniform). Assert the bootstrap says so.
|
|
assert.ok(/frontmatter/i.test(content) && /query agent-skills/i.test(content),
|
|
'bootstrap must instruct query agent-skills using the frontmatter name');
|
|
});
|
|
|
|
describe('every consumer agent carries the self-load bootstrap reference', () => {
|
|
for (const name of CONSUMER_AGENTS) {
|
|
test(`${name} @-includes the bootstrap reference`, () => {
|
|
const content = readAgent(name);
|
|
assert.ok(
|
|
content.includes(BOOTSTRAP_REF),
|
|
`${name} must @-include references/${BOOTSTRAP_REF} (self-load contract)`
|
|
);
|
|
});
|
|
}
|
|
});
|
|
|
|
test('parity: set of agents referencing the bootstrap == CONSUMER_AGENTS (bijection)', () => {
|
|
const withBootstrap = allAgentFiles()
|
|
.filter((f) =>
|
|
fs.readFileSync(path.join(AGENTS_DIR, f), 'utf8').includes(BOOTSTRAP_REF))
|
|
.map((f) => f.replace(/\.md$/, ''));
|
|
|
|
const consumer = new Set(CONSUMER_AGENTS);
|
|
const bootstrap = new Set(withBootstrap);
|
|
const missing = [...consumer].filter((a) => !bootstrap.has(a));
|
|
const extra = [...bootstrap].filter((a) => !consumer.has(a));
|
|
assert.deepStrictEqual(
|
|
{ missing, extra },
|
|
{ missing: [], extra: [] },
|
|
`bootstrap presence must exactly match CONSUMER_AGENTS (Generative-Fix-Divergence)\n` +
|
|
` missing bootstrap: ${missing.join(', ') || '(none)'}\n` +
|
|
` extra bootstrap: ${extra.join(', ') || '(none)'}`
|
|
);
|
|
});
|
|
|
|
test('property (fast-check): for any sampled agent file, bootstrap-presence iff consumer-status', () => {
|
|
const files = allAgentFiles();
|
|
fc.assert(
|
|
fc.property(fc.shuffledSubarray(files, { minLength: 1 }), (sample) => {
|
|
for (const f of sample) {
|
|
const stem = f.replace(/\.md$/, '');
|
|
const content = fs.readFileSync(path.join(AGENTS_DIR, f), 'utf8');
|
|
const hasBootstrap = content.includes(BOOTSTRAP_REF);
|
|
const isConsumer = CONSUMER_AGENTS.includes(stem);
|
|
if (hasBootstrap !== isConsumer) return false;
|
|
}
|
|
return true;
|
|
}),
|
|
{ numRuns: 60 }
|
|
);
|
|
});
|
|
});
|