import { describe, test, expect } from 'bun:test'; import { validateSkill } from './helpers/skill-parser'; import { ALL_COMMANDS, COMMAND_DESCRIPTIONS, READ_COMMANDS, WRITE_COMMANDS, META_COMMANDS } from '../browse/src/commands'; import { SNAPSHOT_FLAGS } from '../browse/src/snapshot'; import * as fs from 'fs'; import * as path from 'path'; const ROOT = path.resolve(import.meta.dir, '..'); describe('SKILL.md command validation', () => { test('all $B commands in SKILL.md are valid browse commands', () => { const result = validateSkill(path.join(ROOT, 'SKILL.md')); expect(result.invalid).toHaveLength(0); expect(result.valid.length).toBeGreaterThan(0); }); test('all snapshot flags in SKILL.md are valid', () => { const result = validateSkill(path.join(ROOT, 'SKILL.md')); expect(result.snapshotFlagErrors).toHaveLength(0); }); test('all $B commands in browse/SKILL.md are valid browse commands', () => { const result = validateSkill(path.join(ROOT, 'browse', 'SKILL.md')); expect(result.invalid).toHaveLength(0); expect(result.valid.length).toBeGreaterThan(0); }); test('all snapshot flags in browse/SKILL.md are valid', () => { const result = validateSkill(path.join(ROOT, 'browse', 'SKILL.md')); expect(result.snapshotFlagErrors).toHaveLength(0); }); test('all $B commands in qa/SKILL.md are valid browse commands', () => { const qaSkill = path.join(ROOT, 'qa', 'SKILL.md'); if (!fs.existsSync(qaSkill)) return; // skip if missing const result = validateSkill(qaSkill); expect(result.invalid).toHaveLength(0); }); test('all snapshot flags in qa/SKILL.md are valid', () => { const qaSkill = path.join(ROOT, 'qa', 'SKILL.md'); if (!fs.existsSync(qaSkill)) return; const result = validateSkill(qaSkill); expect(result.snapshotFlagErrors).toHaveLength(0); }); }); describe('Command registry consistency', () => { test('COMMAND_DESCRIPTIONS covers all commands in sets', () => { const allCmds = new Set([...READ_COMMANDS, ...WRITE_COMMANDS, ...META_COMMANDS]); const descKeys = new Set(Object.keys(COMMAND_DESCRIPTIONS)); for (const cmd of allCmds) { expect(descKeys.has(cmd)).toBe(true); } }); test('COMMAND_DESCRIPTIONS has no extra commands not in sets', () => { const allCmds = new Set([...READ_COMMANDS, ...WRITE_COMMANDS, ...META_COMMANDS]); for (const key of Object.keys(COMMAND_DESCRIPTIONS)) { expect(allCmds.has(key)).toBe(true); } }); test('ALL_COMMANDS matches union of all sets', () => { const union = new Set([...READ_COMMANDS, ...WRITE_COMMANDS, ...META_COMMANDS]); expect(ALL_COMMANDS.size).toBe(union.size); for (const cmd of union) { expect(ALL_COMMANDS.has(cmd)).toBe(true); } }); test('SNAPSHOT_FLAGS option keys are valid SnapshotOptions fields', () => { const validKeys = new Set([ 'interactive', 'compact', 'depth', 'selector', 'diff', 'annotate', 'outputPath', 'cursorInteractive', ]); for (const flag of SNAPSHOT_FLAGS) { expect(validKeys.has(flag.optionKey)).toBe(true); } }); }); describe('Generated SKILL.md freshness', () => { test('no unresolved {{placeholders}} in generated SKILL.md', () => { const content = fs.readFileSync(path.join(ROOT, 'SKILL.md'), 'utf-8'); const unresolved = content.match(/\{\{\w+\}\}/g); expect(unresolved).toBeNull(); }); test('no unresolved {{placeholders}} in generated browse/SKILL.md', () => { const content = fs.readFileSync(path.join(ROOT, 'browse', 'SKILL.md'), 'utf-8'); const unresolved = content.match(/\{\{\w+\}\}/g); expect(unresolved).toBeNull(); }); test('generated SKILL.md has AUTO-GENERATED header', () => { const content = fs.readFileSync(path.join(ROOT, 'SKILL.md'), 'utf-8'); expect(content).toContain('AUTO-GENERATED'); }); });