import { Command } from 'commander';
import path from 'path';
import fs from 'fs';
import chalk from 'chalk';
import { loadSkill } from '@fpf/skill-core';
export const validateCommand = new Command('validate')
.description('Validate a skill definition (SKILL.md)')
.argument('[path]', 'Path to the skill directory or skill name (defaults to current directory)', '.')
.action(async (pathOrName: string) => {
let skillPath = path.resolve(pathOrName);
// Logic to resolve skill path if it doesn't exist locally (registry lookup)
if (!fs.existsSync(skillPath)) {
let registryRoot = path.resolve('contexts/Skills/src');
// Try to find registry relative to CWD if not in project root
if (!fs.existsSync(registryRoot)) {
const alt = path.resolve('../../contexts/Skills/src');
if (fs.existsSync(alt)) registryRoot = alt;
}
// check if registryRoot is valid before joining
if (fs.existsSync(registryRoot)) {
// Try direct child
let tryPath = path.join(registryRoot, pathOrName);
if (fs.existsSync(tryPath)) {
skillPath = tryPath;
} else {
// Try searching subdirectories (domain/skill)
// Simple 2-level check as per loose spec
try {
const domains = fs.readdirSync(registryRoot);
for (const domain of domains) {
const domainPath = path.join(registryRoot, domain);
if (fs.statSync(domainPath).isDirectory()) {
const possiblePath = path.join(domainPath, pathOrName);
if (fs.existsSync(possiblePath)) {
skillPath = possiblePath;
break;
}
}
}
} catch (e) {
// ignore
}
}
}
}
if (!fs.existsSync(path.join(skillPath, 'SKILL.md'))) {
console.error(chalk.red(`Error: No SKILL.md found at ${skillPath}`));
console.error(chalk.gray(`Searched in: ${skillPath}`));
process.exit(1);
}
console.log(chalk.blue(`Validating skill at: ${skillPath}...`));
const { isValid, errors, result } = await loadSkill(skillPath);
if (isValid) {
console.log(chalk.green('✅ Skill is VALID'));
console.log(chalk.gray(`Name: ${result.boundary.name}`));
console.log(chalk.gray(`Version: ${result.boundary.version || 'N/A'}`));
} else {
console.log(chalk.red('❌ Skill is INVALID'));
errors?.forEach(e => console.error(chalk.red(`- ${e}`)));
process.exit(1);
}
});