feat(skills): audit scan results and block unroutable skills

This commit is contained in:
William Valentin
2026-02-15 11:06:52 -08:00
parent 83752d4e1c
commit 56e887a6bf
5 changed files with 50 additions and 1 deletions
+10
View File
@@ -3,6 +3,7 @@ import { resolve, basename } from 'path';
import type { Skill } from './types.js';
import { loadSkill } from './loader.js';
import { scanSkillDirectory } from './scanner.js';
import { auditLogger } from '../audit/index.js';
/**
* SkillInstaller manages installing and removing skills in the managed
@@ -39,6 +40,15 @@ export class SkillInstaller {
}
const scan = scanSkillDirectory(sourceDir);
auditLogger?.skillsScan({
skill_name: basename(sourceDir),
tier: 'unknown',
phase: 'install',
ok: scan.ok,
error_count: scan.issues.filter(i => i.severity === 'error').length,
warn_count: scan.issues.filter(i => i.severity === 'warn').length,
issue_codes: Array.from(new Set(scan.issues.map(i => i.code))),
});
if (!scan.ok) {
const codes = Array.from(new Set(scan.issues.map(i => i.code))).join(', ');
throw new Error(`Skill scan failed: ${codes || 'unknown_issue'}`);
+10
View File
@@ -11,6 +11,7 @@ import { execSync } from 'child_process';
import { platform } from 'os';
import type { Skill, SkillManifest, SkillRequirements, SkillTier } from './types.js';
import { scanSkillDirectory } from './scanner.js';
import { auditLogger } from '../audit/index.js';
function isStringArray(value: unknown): value is string[] {
return Array.isArray(value) && value.every((item) => typeof item === 'string');
@@ -200,6 +201,15 @@ export function loadSkill(directory: string, tier: SkillTier): Skill | null {
const instructions = readFileSync(instructionsPath, 'utf-8');
const scan = scanSkillDirectory(absDir);
auditLogger?.skillsScan({
skill_name: basename(absDir),
tier,
phase: 'load',
ok: scan.ok,
error_count: scan.issues.filter(i => i.severity === 'error').length,
warn_count: scan.issues.filter(i => i.severity === 'warn').length,
issue_codes: Array.from(new Set(scan.issues.map(i => i.code))),
});
const scanReasons = scan.issues.map((i) => `${i.code}: ${i.message}${i.path ? ` (${basename(i.path)})` : ''}`);
const inferManifest = (): SkillManifest => {