docs(agents): standardize required_reading patterns across agent specs (#2176)
Closes #2168 Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
78
tests/agent-required-reading-consistency.test.cjs
Normal file
78
tests/agent-required-reading-consistency.test.cjs
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* GSD Agent Required Reading Consistency Tests
|
||||
*
|
||||
* Validates that all agent .md files use the standardized <required_reading>
|
||||
* pattern and that no legacy <files_to_read> blocks remain.
|
||||
*
|
||||
* See: https://github.com/gsd-build/get-shit-done/issues/2168
|
||||
*/
|
||||
|
||||
const { test, describe } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const AGENTS_DIR = path.join(__dirname, '..', 'agents');
|
||||
|
||||
const ALL_AGENTS = fs.readdirSync(AGENTS_DIR)
|
||||
.filter(f => f.startsWith('gsd-') && f.endsWith('.md'))
|
||||
.map(f => f.replace('.md', ''));
|
||||
|
||||
// ─── No Legacy files_to_read Blocks ────────────────────────────────────────
|
||||
|
||||
describe('READING: no legacy <files_to_read> blocks remain', () => {
|
||||
for (const agent of ALL_AGENTS) {
|
||||
test(`${agent} does not contain <files_to_read>`, () => {
|
||||
const content = fs.readFileSync(path.join(AGENTS_DIR, agent + '.md'), 'utf-8');
|
||||
assert.ok(
|
||||
!content.includes('<files_to_read>'),
|
||||
`${agent} still has <files_to_read> opening tag — migrate to <required_reading>`
|
||||
);
|
||||
assert.ok(
|
||||
!content.includes('</files_to_read>'),
|
||||
`${agent} still has </files_to_read> closing tag — migrate to </required_reading>`
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
test('no backtick references to files_to_read in any agent', () => {
|
||||
for (const agent of ALL_AGENTS) {
|
||||
const content = fs.readFileSync(path.join(AGENTS_DIR, agent + '.md'), 'utf-8');
|
||||
assert.ok(
|
||||
!content.includes('`<files_to_read>`'),
|
||||
`${agent} still references \`<files_to_read>\` in prose — update to \`<required_reading>\``
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Standardized required_reading Pattern ─────────────────────────────────
|
||||
|
||||
describe('READING: agents with reading blocks use <required_reading>', () => {
|
||||
// Agents that have any kind of reading instruction should use required_reading
|
||||
const AGENTS_WITH_READING = ALL_AGENTS.filter(name => {
|
||||
const content = fs.readFileSync(path.join(AGENTS_DIR, name + '.md'), 'utf-8');
|
||||
return content.includes('required_reading') || content.includes('files_to_read');
|
||||
});
|
||||
|
||||
test('at least 20 agents have reading instructions', () => {
|
||||
assert.ok(
|
||||
AGENTS_WITH_READING.length >= 20,
|
||||
`Expected at least 20 agents with reading instructions, found ${AGENTS_WITH_READING.length}`
|
||||
);
|
||||
});
|
||||
|
||||
for (const agent of AGENTS_WITH_READING) {
|
||||
test(`${agent} uses required_reading (not files_to_read)`, () => {
|
||||
const content = fs.readFileSync(path.join(AGENTS_DIR, agent + '.md'), 'utf-8');
|
||||
assert.ok(
|
||||
content.includes('required_reading'),
|
||||
`${agent} has reading instructions but does not use required_reading`
|
||||
);
|
||||
assert.ok(
|
||||
!content.includes('files_to_read'),
|
||||
`${agent} still uses files_to_read — must be migrated to required_reading`
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -89,13 +89,13 @@ describe('gates taxonomy (#1715)', () => {
|
||||
test('gsd-plan-checker.md references gates.md in required_reading block', () => {
|
||||
const planChecker = path.join(ROOT, 'agents', 'gsd-plan-checker.md');
|
||||
const content = fs.readFileSync(planChecker, 'utf-8');
|
||||
const match = content.match(/<required_reading>\n([\s\S]*?)\n<\/required_reading>/);
|
||||
assert.ok(
|
||||
content.includes('<required_reading>'),
|
||||
match,
|
||||
'gsd-plan-checker.md must have a <required_reading> block'
|
||||
);
|
||||
const reqBlock = content.split('<required_reading>')[1].split('</required_reading>')[0];
|
||||
assert.ok(
|
||||
reqBlock.includes('references/gates.md'),
|
||||
match[1].includes('references/gates.md'),
|
||||
'gsd-plan-checker.md must reference gates.md inside <required_reading>'
|
||||
);
|
||||
});
|
||||
@@ -103,13 +103,13 @@ describe('gates taxonomy (#1715)', () => {
|
||||
test('gsd-verifier.md references gates.md in required_reading block', () => {
|
||||
const verifier = path.join(ROOT, 'agents', 'gsd-verifier.md');
|
||||
const content = fs.readFileSync(verifier, 'utf-8');
|
||||
const match = content.match(/<required_reading>\n([\s\S]*?)\n<\/required_reading>/);
|
||||
assert.ok(
|
||||
content.includes('<required_reading>'),
|
||||
match,
|
||||
'gsd-verifier.md must have a <required_reading> block'
|
||||
);
|
||||
const reqBlock = content.split('<required_reading>')[1].split('</required_reading>')[0];
|
||||
assert.ok(
|
||||
reqBlock.includes('references/gates.md'),
|
||||
match[1].includes('references/gates.md'),
|
||||
'gsd-verifier.md must reference gates.md inside <required_reading>'
|
||||
);
|
||||
});
|
||||
|
||||
@@ -217,7 +217,9 @@ describe('verification overrides reference (#1747)', () => {
|
||||
verifierContent = verifierContent || fs.readFileSync(verifierPath, 'utf-8');
|
||||
const roleEnd = verifierContent.indexOf('</role>');
|
||||
const projectCtx = verifierContent.indexOf('<project_context>');
|
||||
const reqReading = verifierContent.indexOf('<required_reading>');
|
||||
// Use regex to find the actual XML tag (on its own line), not backtick-escaped prose mentions
|
||||
const reqMatch = verifierContent.match(/^<required_reading>/m);
|
||||
const reqReading = reqMatch ? reqMatch.index : -1;
|
||||
assert.ok(roleEnd > -1, '</role> tag should exist');
|
||||
assert.ok(projectCtx > -1, '<project_context> tag should exist');
|
||||
assert.ok(reqReading > -1, '<required_reading> tag should exist');
|
||||
|
||||
Reference in New Issue
Block a user