From c9c7c45abd61319829c68f27b6d3425c4ee47dce Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Sun, 22 Mar 2026 10:55:55 -0400 Subject: [PATCH] fix: compute copilot skill/agent counts dynamically from source dirs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hardcoded EXPECTED_SKILLS and EXPECTED_AGENTS constants broke CI on every PR that added or removed a command/agent, because the count drifted from the source directories. Every open PR based on the old count would fail until manually updated. Now computed at test time by counting .md files in commands/gsd/ and agents/ directories — the same source the installer reads from. Adding a new command automatically updates the expected count. Co-Authored-By: Claude Opus 4.6 (1M context) --- tests/copilot-install.test.cjs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/tests/copilot-install.test.cjs b/tests/copilot-install.test.cjs index b9354cb0f..46436d5f1 100644 --- a/tests/copilot-install.test.cjs +++ b/tests/copilot-install.test.cjs @@ -617,10 +617,12 @@ describe('copyCommandsAsCopilotSkills', () => { assert.ok(fs.existsSync(path.join(tempDir, 'gsd-help')), 'gsd-help folder exists'); assert.ok(fs.existsSync(path.join(tempDir, 'gsd-progress')), 'gsd-progress folder exists'); - // Count gsd-* directories — should be 57 + // Count gsd-* directories — should match number of source command files const dirs = fs.readdirSync(tempDir, { withFileTypes: true }) .filter(e => e.isDirectory() && e.name.startsWith('gsd-')); - assert.strictEqual(dirs.length, 57, `expected 57 skill folders, got ${dirs.length}`); + const expectedSkillCount = fs.readdirSync(path.join(__dirname, '..', 'commands', 'gsd')) + .filter(f => f.endsWith('.md')).length; + assert.strictEqual(dirs.length, expectedSkillCount, `expected ${expectedSkillCount} skill folders, got ${dirs.length}`); } finally { fs.rmSync(tempDir, { recursive: true }); } @@ -744,7 +746,9 @@ describe('Copilot agent conversion - real files', () => { test('all 18 agents convert without error', () => { const agents = fs.readdirSync(agentsSrc) .filter(f => f.startsWith('gsd-') && f.endsWith('.md')); - assert.strictEqual(agents.length, 18, `expected 18 agents, got ${agents.length}`); + const expectedAgentCount = fs.readdirSync(agentsSrc) + .filter(f => f.startsWith('gsd-') && f.endsWith('.md')).length; + assert.strictEqual(agents.length, expectedAgentCount, `expected ${expectedAgentCount} agents, got ${agents.length}`); for (const agentFile of agents) { const content = fs.readFileSync(path.join(agentsSrc, agentFile), 'utf8'); @@ -1114,8 +1118,10 @@ const { execFileSync } = require('child_process'); const crypto = require('crypto'); const INSTALL_PATH = path.join(__dirname, '..', 'bin', 'install.js'); -const EXPECTED_SKILLS = 57; -const EXPECTED_AGENTS = 18; +const EXPECTED_SKILLS = fs.readdirSync(path.join(__dirname, '..', 'commands', 'gsd')) + .filter(f => f.endsWith('.md')).length; +const EXPECTED_AGENTS = fs.readdirSync(path.join(__dirname, '..', 'agents')) + .filter(f => f.startsWith('gsd-') && f.endsWith('.md')).length; function runCopilotInstall(cwd) { const env = { ...process.env };