skill-tools 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +190 -0
- package/README.md +62 -0
- package/dist/cli.js +979 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +716 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +111 -0
- package/dist/index.d.ts +111 -0
- package/dist/index.js +709 -0
- package/dist/index.js.map +1 -0
- package/package.json +73 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/rules/consistent-headings.ts","../src/rules/description-specificity.ts","../src/rules/description-trigger-keywords.ts","../src/rules/instructions-has-error-handling.ts","../src/rules/instructions-has-examples.ts","../src/rules/no-hardcoded-paths.ts","../src/rules/no-secrets.ts","../src/rules/progressive-disclosure.ts","../src/rules/index.ts","../src/linter.ts","../src/scorer/description-quality.ts","../src/scorer/instruction-clarity.ts","../src/scorer/progressive-disclosure-score.ts","../src/scorer/security-score.ts","../src/scorer/spec-compliance.ts","../src/scorer/index.ts","../src/validator.ts"],"names":["MAX_POINTS","progressiveDisclosure","resolveSkillFiles","parseSkill","join","readdirSync","existsSync","statSync"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { Diagnostic, Skill } from '@skill-tools/core';\nimport type { RuleDefinition } from './types.js';\n\n/**\n * Check that heading hierarchy is consistent (no skipping levels).\n * E.g., going from H1 directly to H4 is a problem.\n */\nexport const consistentHeadings: RuleDefinition = {\n\tid: 'consistent-headings',\n\tdescription: 'Headings should follow a consistent hierarchy without skipping levels',\n\tdefaultSeverity: 'info',\n\n\tcheck(skill: Skill): Diagnostic[] {\n\t\tconst diagnostics: Diagnostic[] = [];\n\t\tconst sections = skill.sections;\n\n\t\tfor (let i = 1; i < sections.length; i++) {\n\t\t\tconst prev = sections[i - 1]!;\n\t\t\tconst curr = sections[i]!;\n\n\t\t\t// A heading can go deeper by at most 1 level from its predecessor\n\t\t\tif (curr.depth > prev.depth + 1) {\n\t\t\t\tdiagnostics.push({\n\t\t\t\t\truleId: 'consistent-headings',\n\t\t\t\t\tseverity: 'info',\n\t\t\t\t\tmessage: `Heading \"${curr.heading}\" (H${curr.depth}) skips levels from \"${prev.heading}\" (H${prev.depth})`,\n\t\t\t\t\tfile: skill.filePath,\n\t\t\t\t\tline: curr.line,\n\t\t\t\t\tfix: `Change to H${prev.depth + 1} for consistent hierarchy`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn diagnostics;\n\t},\n};\n","import type { Diagnostic, Skill } from '@skill-tools/core';\nimport type { RuleDefinition } from './types.js';\n\n/**\n * Generic/vague verbs that don't tell an agent when to trigger the skill.\n */\nconst GENERIC_VERBS = [\n\t'manage',\n\t'handle',\n\t'process',\n\t'deal with',\n\t'work with',\n\t'do stuff',\n\t'help with',\n\t'assist with',\n\t'take care of',\n];\n\n/**\n * Check that the description contains specific, actionable language\n * rather than generic verbs that don't help agent routing.\n */\nexport const descriptionSpecificity: RuleDefinition = {\n\tid: 'description-specificity',\n\tdescription:\n\t\t'Description should contain specific nouns or action verbs, not generic phrases like \"manages\" or \"handles\"',\n\tdefaultSeverity: 'warning',\n\n\tcheck(skill: Skill): Diagnostic[] {\n\t\tconst desc = skill.metadata.description;\n\t\tif (!desc) return [];\n\n\t\tconst diagnostics: Diagnostic[] = [];\n\t\tconst lowerDesc = desc.toLowerCase();\n\n\t\tconst foundGeneric = GENERIC_VERBS.filter((verb) => lowerDesc.includes(verb));\n\t\tif (foundGeneric.length > 0) {\n\t\t\tdiagnostics.push({\n\t\t\t\truleId: 'description-specificity',\n\t\t\t\tseverity: 'warning',\n\t\t\t\tmessage: `Description uses generic verbs: ${foundGeneric.map((v) => `\"${v}\"`).join(', ')}. Use specific action verbs instead`,\n\t\t\t\tfile: skill.filePath,\n\t\t\t\tline: 1,\n\t\t\t\tfix: 'Replace generic verbs with specific ones. E.g., \"Deploy apps to Vercel\" instead of \"Handle Vercel deployments\"',\n\t\t\t});\n\t\t}\n\n\t\treturn diagnostics;\n\t},\n};\n","import type { Diagnostic, Skill } from '@skill-tools/core';\nimport type { RuleDefinition } from './types.js';\n\n/**\n * Check that the description contains trigger keywords — words a user\n * would naturally type that should cause the agent to invoke this skill.\n *\n * The spec says: \"Check the description includes keywords users would naturally say\"\n */\nexport const descriptionTriggerKeywords: RuleDefinition = {\n\tid: 'description-trigger-keywords',\n\tdescription:\n\t\t'Description should contain words that a user would naturally type to trigger this skill',\n\tdefaultSeverity: 'warning',\n\n\tcheck(skill: Skill): Diagnostic[] {\n\t\tconst desc = skill.metadata.description;\n\t\tif (!desc) return [];\n\n\t\tconst diagnostics: Diagnostic[] = [];\n\n\t\t// A good description should include \"Use when\" or \"Use for\" to specify trigger conditions\n\t\tconst hasTriggerPhrase =\n\t\t\t/\\buse when\\b|\\buse for\\b|\\buse this\\b|\\binvoke when\\b|\\btrigger when\\b/i.test(desc);\n\n\t\t// Alternatively, check for imperative verbs that describe what the skill does\n\t\tconst hasActionVerb =\n\t\t\t/\\b(deploy|test|build|run|create|generate|analyze|review|format|lint|fix|check|commit|push|pull|fetch|install|configure|setup|search|find|list|delete|update|migrate|convert|export|import)\\b/i.test(\n\t\t\t\tdesc,\n\t\t\t);\n\n\t\tif (!hasTriggerPhrase && !hasActionVerb) {\n\t\t\tdiagnostics.push({\n\t\t\t\truleId: 'description-trigger-keywords',\n\t\t\t\tseverity: 'warning',\n\t\t\t\tmessage:\n\t\t\t\t\t'Description lacks trigger keywords. Include \"Use when...\" or specific action verbs (deploy, test, build, etc.)',\n\t\t\t\tfile: skill.filePath,\n\t\t\t\tline: 1,\n\t\t\t\tfix: 'Add trigger context: \"Deploy apps to Vercel. Use when the user wants to publish or ship a web app.\"',\n\t\t\t});\n\t\t}\n\n\t\treturn diagnostics;\n\t},\n};\n","import type { Diagnostic, Skill } from '@skill-tools/core';\nimport type { RuleDefinition } from './types.js';\n\n/**\n * Check that instructions include error handling guidance.\n * Skills that tell agents what to do when things fail are more robust.\n */\nexport const instructionsHasErrorHandling: RuleDefinition = {\n\tid: 'instructions-has-error-handling',\n\tdescription: 'Instructions should mention what to do when things fail',\n\tdefaultSeverity: 'info',\n\n\tcheck(skill: Skill): Diagnostic[] {\n\t\tconst diagnostics: Diagnostic[] = [];\n\t\tconst body = skill.body.toLowerCase();\n\n\t\tconst hasErrorSection = /#{1,3}\\s+(?:error|troubleshoot|fail|issue|problem|debug)/i.test(\n\t\t\tskill.body,\n\t\t);\n\n\t\tconst hasErrorKeywords =\n\t\t\t/\\b(?:error|fail|troubleshoot|if .+ fails|when .+ fails|common issues|known issues)\\b/.test(\n\t\t\t\tbody,\n\t\t\t);\n\n\t\tif (!hasErrorSection && !hasErrorKeywords) {\n\t\t\tdiagnostics.push({\n\t\t\t\truleId: 'instructions-has-error-handling',\n\t\t\t\tseverity: 'info',\n\t\t\t\tmessage:\n\t\t\t\t\t'Instructions have no error handling guidance. Add a section about common failures',\n\t\t\t\tfile: skill.filePath,\n\t\t\t\tfix: 'Add an \"## Error Handling\" section describing common failures and how to resolve them',\n\t\t\t});\n\t\t}\n\n\t\treturn diagnostics;\n\t},\n};\n","import type { Diagnostic, Skill } from '@skill-tools/core';\nimport type { RuleDefinition } from './types.js';\n\n/**\n * Check that skill instructions include at least one concrete example.\n * Examples help agents understand expected input/output patterns.\n */\nexport const instructionsHasExamples: RuleDefinition = {\n\tid: 'instructions-has-examples',\n\tdescription: 'Skill instructions should include at least one concrete example',\n\tdefaultSeverity: 'info',\n\n\tcheck(skill: Skill): Diagnostic[] {\n\t\tconst diagnostics: Diagnostic[] = [];\n\t\tconst body = skill.body;\n\n\t\t// Look for code blocks, numbered steps, or example sections\n\t\tconst hasCodeBlock = /```[\\s\\S]*?```/.test(body);\n\t\tconst hasExampleSection = /^#{1,3}\\s+(?:example|usage|demo)/im.test(body);\n\t\tconst hasInlineCode = /`[^`]+`/.test(body);\n\t\tconst hasNumberedSteps = /^\\d+\\.\\s+/m.test(body);\n\n\t\tif (!hasCodeBlock && !hasExampleSection && !hasInlineCode && !hasNumberedSteps) {\n\t\t\tdiagnostics.push({\n\t\t\t\truleId: 'instructions-has-examples',\n\t\t\t\tseverity: 'info',\n\t\t\t\tmessage:\n\t\t\t\t\t'Instructions have no examples. Add code blocks, numbered steps, or an Examples section',\n\t\t\t\tfile: skill.filePath,\n\t\t\t\tfix: 'Add a code block showing expected usage:\\n```bash\\nskill-tools check ./my-skill/\\n```',\n\t\t\t});\n\t\t}\n\n\t\treturn diagnostics;\n\t},\n};\n","import type { Diagnostic, Skill } from '@skill-tools/core';\nimport type { RuleDefinition } from './types.js';\n\n/**\n * Pattern for common hardcoded absolute paths.\n * Matches /Users/..., /home/..., C:\\..., etc.\n */\nconst HARDCODED_PATH_PATTERN =\n\t/(?:\\/Users\\/\\w+|\\/home\\/\\w+|[A-Z]:\\\\\\\\?Users\\\\\\\\?\\w+|\\/var\\/|\\/tmp\\/\\w+)/;\n\n/**\n * Check for hardcoded filesystem paths that won't work on other machines.\n */\nexport const noHardcodedPaths: RuleDefinition = {\n\tid: 'no-hardcoded-paths',\n\tdescription: 'Flag absolute filesystem paths that are machine-specific',\n\tdefaultSeverity: 'error',\n\n\tcheck(skill: Skill): Diagnostic[] {\n\t\tconst diagnostics: Diagnostic[] = [];\n\t\tconst lines = skill.body.split('\\n');\n\n\t\tfor (let i = 0; i < lines.length; i++) {\n\t\t\tconst line = lines[i]!;\n\n\t\t\t// Skip lines inside code fences that are clearly examples showing path patterns\n\t\t\t// But still flag hardcoded paths even in code blocks\n\t\t\tif (HARDCODED_PATH_PATTERN.test(line)) {\n\t\t\t\tconst match = HARDCODED_PATH_PATTERN.exec(line);\n\t\t\t\tdiagnostics.push({\n\t\t\t\t\truleId: 'no-hardcoded-paths',\n\t\t\t\t\tseverity: 'error',\n\t\t\t\t\tmessage: `Hardcoded path found: \"${match?.[0]}\". Use environment variables or relative paths`,\n\t\t\t\t\tfile: skill.filePath,\n\t\t\t\t\tline: i + 1,\n\t\t\t\t\tfix: 'Replace with $HOME, relative paths, or environment variables',\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn diagnostics;\n\t},\n};\n","import type { Diagnostic, Skill } from '@skill-tools/core';\nimport type { RuleDefinition } from './types.js';\n\n/**\n * Patterns that look like secrets, API keys, or tokens.\n * Each pattern has a label for the diagnostic message.\n */\nconst SECRET_PATTERNS: Array<{ pattern: RegExp; label: string }> = [\n\t{ pattern: /sk-[a-zA-Z0-9]{20,}/, label: 'OpenAI API key' },\n\t{ pattern: /sk_live_[a-zA-Z0-9]{20,}/, label: 'Stripe live key' },\n\t{ pattern: /sk_test_[a-zA-Z0-9]{20,}/, label: 'Stripe test key' },\n\t{ pattern: /ghp_[a-zA-Z0-9]{36,}/, label: 'GitHub personal access token' },\n\t{ pattern: /gho_[a-zA-Z0-9]{36,}/, label: 'GitHub OAuth token' },\n\t{ pattern: /github_pat_[a-zA-Z0-9_]{20,}/, label: 'GitHub fine-grained token' },\n\t{ pattern: /xoxb-[a-zA-Z0-9-]+/, label: 'Slack bot token' },\n\t{ pattern: /xoxp-[a-zA-Z0-9-]+/, label: 'Slack user token' },\n\t{ pattern: /AKIA[0-9A-Z]{16}/, label: 'AWS access key ID' },\n\t{ pattern: /-----BEGIN (?:RSA |EC )?PRIVATE KEY-----/, label: 'Private key' },\n\t{ pattern: /eyJ[a-zA-Z0-9_-]{20,500}\\.[a-zA-Z0-9_-]{20,500}\\./, label: 'JWT token' },\n];\n\n/**\n * Check for patterns that look like embedded secrets or credentials.\n */\nexport const noSecrets: RuleDefinition = {\n\tid: 'no-secrets',\n\tdescription: 'Flag patterns that look like API keys, tokens, or passwords',\n\tdefaultSeverity: 'error',\n\n\tcheck(skill: Skill): Diagnostic[] {\n\t\tconst diagnostics: Diagnostic[] = [];\n\t\tconst lines = skill.rawContent.split('\\n');\n\n\t\tfor (let i = 0; i < lines.length; i++) {\n\t\t\tconst line = lines[i]!;\n\n\t\t\tfor (const { pattern, label } of SECRET_PATTERNS) {\n\t\t\t\tif (pattern.test(line)) {\n\t\t\t\t\tdiagnostics.push({\n\t\t\t\t\t\truleId: 'no-secrets',\n\t\t\t\t\t\tseverity: 'error',\n\t\t\t\t\t\tmessage: `Possible ${label} detected. Never embed secrets in SKILL.md files`,\n\t\t\t\t\t\tfile: skill.filePath,\n\t\t\t\t\t\tline: i + 1,\n\t\t\t\t\t\tfix: 'Use environment variable references (e.g., $API_KEY) instead of actual secrets',\n\t\t\t\t\t});\n\t\t\t\t\tbreak; // One diagnostic per line is enough\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn diagnostics;\n\t},\n};\n","import type { Diagnostic, Skill } from '@skill-tools/core';\nimport type { RuleDefinition } from './types.js';\n\nconst DEFAULT_MAX_LINES = 500;\n\n/**\n * Check that large skills use progressive disclosure — moving detailed\n * content to references/ or scripts/ to keep the main SKILL.md lean.\n *\n * The spec recommends: \"Keep SKILL.md under 500 lines\"\n */\nexport const progressiveDisclosure: RuleDefinition = {\n\tid: 'progressive-disclosure',\n\tdescription: 'Large SKILL.md files should use references/ or scripts/ to keep the main file lean',\n\tdefaultSeverity: 'warning',\n\n\tcheck(skill: Skill): Diagnostic[] {\n\t\tconst diagnostics: Diagnostic[] = [];\n\n\t\tif (skill.lineCount > DEFAULT_MAX_LINES) {\n\t\t\tconst hasReferences = skill.fileReferences.some((r) => r.path.startsWith('references/'));\n\t\t\tconst hasScripts = skill.fileReferences.some((r) => r.path.startsWith('scripts/'));\n\n\t\t\tif (!hasReferences && !hasScripts) {\n\t\t\t\tdiagnostics.push({\n\t\t\t\t\truleId: 'progressive-disclosure',\n\t\t\t\t\tseverity: 'warning',\n\t\t\t\t\tmessage: `SKILL.md is ${skill.lineCount} lines (recommended: <${DEFAULT_MAX_LINES}). Move detailed content to references/ or scripts/`,\n\t\t\t\t\tfile: skill.filePath,\n\t\t\t\t\tfix: 'Create a references/ directory and move detailed API docs, examples, or reference tables there. Link from SKILL.md: [See API reference](references/api.md)',\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn diagnostics;\n\t},\n};\n","import { consistentHeadings } from './consistent-headings.js';\nimport { descriptionSpecificity } from './description-specificity.js';\nimport { descriptionTriggerKeywords } from './description-trigger-keywords.js';\nimport { instructionsHasErrorHandling } from './instructions-has-error-handling.js';\nimport { instructionsHasExamples } from './instructions-has-examples.js';\nimport { noHardcodedPaths } from './no-hardcoded-paths.js';\nimport { noSecrets } from './no-secrets.js';\nimport { progressiveDisclosure } from './progressive-disclosure.js';\nimport type { RuleDefinition } from './types.js';\n\nexport type { RuleConfig, RuleDefinition, RulesConfig } from './types.js';\n\n/**\n * All built-in lint rules, keyed by rule ID.\n */\nexport const builtinRules: ReadonlyMap<string, RuleDefinition> = new Map([\n\t[descriptionSpecificity.id, descriptionSpecificity],\n\t[descriptionTriggerKeywords.id, descriptionTriggerKeywords],\n\t[progressiveDisclosure.id, progressiveDisclosure],\n\t[noHardcodedPaths.id, noHardcodedPaths],\n\t[noSecrets.id, noSecrets],\n\t[instructionsHasExamples.id, instructionsHasExamples],\n\t[instructionsHasErrorHandling.id, instructionsHasErrorHandling],\n\t[consistentHeadings.id, consistentHeadings],\n]);\n\n/**\n * The \"recommended\" preset: default severity for each rule.\n */\nexport const recommendedConfig: Record<string, string> = Object.fromEntries(\n\tArray.from(builtinRules.values()).map((rule) => [rule.id, rule.defaultSeverity]),\n);\n","import type { Diagnostic, DiagnosticSeverity, Skill } from '@skill-tools/core';\nimport { builtinRules } from './rules/index.js';\nimport type { RuleConfig, RulesConfig } from './rules/types.js';\n\n/**\n * Result of linting a single skill.\n */\nexport interface LintResult {\n\t/** Path to the SKILL.md file */\n\treadonly filePath: string;\n\t/** Skill name */\n\treadonly name: string;\n\t/** All lint diagnostics */\n\treadonly diagnostics: readonly Diagnostic[];\n\t/** Count of errors */\n\treadonly errorCount: number;\n\t/** Count of warnings */\n\treadonly warningCount: number;\n\t/** Count of info messages */\n\treadonly infoCount: number;\n}\n\n/**\n * Lint a parsed skill against all enabled rules.\n *\n * @param skill - The parsed Skill object\n * @param rulesConfig - Optional rule severity overrides\n * @returns LintResult with all diagnostics\n */\nexport function lint(skill: Skill, rulesConfig?: RulesConfig): LintResult {\n\tconst diagnostics: Diagnostic[] = [];\n\n\tfor (const [ruleId, rule] of builtinRules) {\n\t\tconst configuredSeverity = rulesConfig?.[ruleId];\n\n\t\t// Skip disabled rules\n\t\tif (configuredSeverity === 'off') continue;\n\n\t\t// Run the rule\n\t\tconst ruleDiagnostics = rule.check(skill);\n\n\t\t// Apply configured severity override (after the 'off' check above,\n\t\t// configuredSeverity can only be a DiagnosticSeverity or undefined)\n\t\tconst severity: DiagnosticSeverity =\n\t\t\t(configuredSeverity as DiagnosticSeverity | undefined) ?? rule.defaultSeverity;\n\n\t\tfor (const diag of ruleDiagnostics) {\n\t\t\tdiagnostics.push({\n\t\t\t\t...diag,\n\t\t\t\tseverity,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn {\n\t\tfilePath: skill.filePath,\n\t\tname: skill.metadata.name ?? 'unknown',\n\t\tdiagnostics,\n\t\terrorCount: diagnostics.filter((d) => d.severity === 'error').length,\n\t\twarningCount: diagnostics.filter((d) => d.severity === 'warning').length,\n\t\tinfoCount: diagnostics.filter((d) => d.severity === 'info').length,\n\t};\n}\n\n/**\n * Parse a rules config that might come from a .skill-toolsrc.yml file.\n * Normalizes string values to proper RuleConfig types.\n */\nexport function parseRulesConfig(raw: Record<string, unknown>): RulesConfig {\n\tconst config: RulesConfig = {};\n\tconst validSeverities = new Set<RuleConfig>(['error', 'warning', 'info', 'off']);\n\n\tfor (const [key, value] of Object.entries(raw)) {\n\t\tif (typeof value === 'string' && validSeverities.has(value as RuleConfig)) {\n\t\t\tconfig[key] = value as RuleConfig;\n\t\t}\n\t}\n\n\treturn config;\n}\n","import type { DimensionScore, Skill } from '@skill-tools/core';\n\nconst MAX_POINTS = 30;\n\n/**\n * Score the quality of the skill description (30 points max).\n *\n * Factors:\n * - Length (optimal: 50-300 chars)\n * - Specificity (contains action verbs, concrete nouns)\n * - Trigger context (includes \"Use when...\" or similar)\n * - Uniqueness (doesn't just repeat the skill name)\n */\nexport function scoreDescriptionQuality(skill: Skill): DimensionScore {\n\tconst desc = skill.metadata.description;\n\tif (!desc) {\n\t\treturn {\n\t\t\tscore: 0,\n\t\t\tmax: MAX_POINTS,\n\t\t\tlabel: 'Description Quality',\n\t\t\tdetails: 'No description provided',\n\t\t};\n\t}\n\n\tlet points = 0;\n\tconst details: string[] = [];\n\n\t// Length score (0-8 points)\n\tconst len = desc.length;\n\tif (len >= 50 && len <= 300) {\n\t\tpoints += 8;\n\t} else if (len >= 30 && len <= 400) {\n\t\tpoints += 5;\n\t} else if (len >= 10) {\n\t\tpoints += 2;\n\t}\n\tdetails.push(`Length: ${len} chars`);\n\n\t// Specificity score (0-8 points)\n\tconst actionVerbs =\n\t\t/\\b(deploy|test|build|run|create|generate|analyze|review|format|lint|fix|check|commit|push|pull|fetch|install|configure|search|find|list|delete|update|migrate|convert|export|import)\\b/gi;\n\tconst verbCount = (desc.match(actionVerbs) ?? []).length;\n\tif (verbCount >= 2) {\n\t\tpoints += 8;\n\t} else if (verbCount === 1) {\n\t\tpoints += 5;\n\t}\n\tdetails.push(`Action verbs: ${verbCount}`);\n\n\t// Trigger context score (0-8 points)\n\tconst hasTriggerContext =\n\t\t/\\buse when\\b|\\buse for\\b|\\buse this\\b|\\binvoke when\\b|\\bwhen the user\\b/i.test(desc);\n\tif (hasTriggerContext) {\n\t\tpoints += 8;\n\t\tdetails.push('Has trigger context');\n\t}\n\n\t// Not just repeating the name (0-6 points)\n\tconst name = skill.metadata.name ?? '';\n\tconst nameWords = name.split('-').filter((w) => w.length > 2);\n\tconst descLower = desc.toLowerCase();\n\tconst nameRepetitions = nameWords.filter((w) => descLower.includes(w)).length;\n\tconst ratio = nameWords.length > 0 ? nameRepetitions / nameWords.length : 0;\n\n\tif (ratio < 0.5) {\n\t\tpoints += 6;\n\t} else if (ratio < 0.8) {\n\t\tpoints += 3;\n\t}\n\n\treturn {\n\t\tscore: Math.min(points, MAX_POINTS),\n\t\tmax: MAX_POINTS,\n\t\tlabel: 'Description Quality',\n\t\tdetails: details.join(', '),\n\t};\n}\n","import type { DimensionScore, Skill } from '@skill-tools/core';\n\nconst MAX_POINTS = 25;\n\n/**\n * Score the clarity of the skill instructions (25 points max).\n *\n * Factors:\n * - Has concrete examples (code blocks, inline code)\n * - Has numbered steps or structured instructions\n * - Has error handling guidance\n * - Body is non-trivially long (provides real value)\n */\nexport function scoreInstructionClarity(skill: Skill): DimensionScore {\n\tconst body = skill.body;\n\tif (!body || body.trim().length === 0) {\n\t\treturn { score: 0, max: MAX_POINTS, label: 'Instruction Clarity', details: 'No instructions' };\n\t}\n\n\tlet points = 0;\n\tconst details: string[] = [];\n\n\t// Has code blocks (0-7 points)\n\tconst codeBlockCount = (body.match(/```[\\s\\S]*?```/g) ?? []).length;\n\tif (codeBlockCount >= 2) {\n\t\tpoints += 7;\n\t\tdetails.push(`${codeBlockCount} code blocks`);\n\t} else if (codeBlockCount === 1) {\n\t\tpoints += 4;\n\t\tdetails.push('1 code block');\n\t}\n\n\t// Has numbered steps (0-6 points)\n\tconst numberedSteps = (body.match(/^\\d+\\.\\s+/gm) ?? []).length;\n\tif (numberedSteps >= 3) {\n\t\tpoints += 6;\n\t\tdetails.push(`${numberedSteps} numbered steps`);\n\t} else if (numberedSteps >= 1) {\n\t\tpoints += 3;\n\t\tdetails.push(`${numberedSteps} numbered steps`);\n\t}\n\n\t// Has error handling (0-6 points)\n\tconst hasErrorSection = /#{1,3}\\s+(?:error|troubleshoot|fail|issue|problem|debug)/i.test(body);\n\tconst hasErrorKeywords =\n\t\t/\\b(?:error|fail|troubleshoot|if .+ fails|when .+ fails|common issues)\\b/i.test(body);\n\tif (hasErrorSection) {\n\t\tpoints += 6;\n\t\tdetails.push('Error handling section');\n\t} else if (hasErrorKeywords) {\n\t\tpoints += 3;\n\t\tdetails.push('Error mentions');\n\t}\n\n\t// Body substance (0-6 points)\n\tconst wordCount = body.split(/\\s+/).length;\n\tif (wordCount >= 100) {\n\t\tpoints += 6;\n\t} else if (wordCount >= 50) {\n\t\tpoints += 4;\n\t} else if (wordCount >= 20) {\n\t\tpoints += 2;\n\t}\n\tdetails.push(`${wordCount} words`);\n\n\treturn {\n\t\tscore: Math.min(points, MAX_POINTS),\n\t\tmax: MAX_POINTS,\n\t\tlabel: 'Instruction Clarity',\n\t\tdetails: details.join(', '),\n\t};\n}\n","import type { DimensionScore, Skill } from '@skill-tools/core';\n\nconst MAX_POINTS = 15;\n\n/**\n * Score progressive disclosure (15 points max).\n *\n * Factors:\n * - Lean main SKILL.md (short enough to not need references)\n * - Uses references/scripts when large\n * - References are actually linked from SKILL.md\n */\nexport function scoreProgressiveDisclosure(skill: Skill): DimensionScore {\n\tlet points = 0;\n\tconst details: string[] = [];\n\n\tconst isSmall = skill.lineCount <= 100;\n\tconst isMedium = skill.lineCount <= 500;\n\n\tif (isSmall) {\n\t\t// Small skills automatically get full marks — no progressive disclosure needed\n\t\tpoints += 15;\n\t\tdetails.push('Skill is compact');\n\t} else if (isMedium) {\n\t\t// Medium skills get partial credit\n\t\tpoints += 8;\n\n\t\t// Bonus for using references/scripts\n\t\tconst hasRefs = skill.fileReferences.some(\n\t\t\t(r) => r.path.startsWith('references/') || r.path.startsWith('scripts/'),\n\t\t);\n\t\tif (hasRefs) {\n\t\t\tpoints += 7;\n\t\t\tdetails.push('Uses supporting files');\n\t\t} else {\n\t\t\tdetails.push('Could benefit from references/');\n\t\t}\n\t} else {\n\t\t// Large skills need progressive disclosure\n\t\tconst hasRefs = skill.fileReferences.some(\n\t\t\t(r) => r.path.startsWith('references/') || r.path.startsWith('scripts/'),\n\t\t);\n\t\tif (hasRefs) {\n\t\t\tpoints += 10;\n\t\t\tdetails.push('Uses supporting files (recommended: further reduce main file)');\n\t\t} else {\n\t\t\tpoints += 2;\n\t\t\tdetails.push('Large file without progressive disclosure');\n\t\t}\n\t}\n\n\treturn {\n\t\tscore: Math.min(points, MAX_POINTS),\n\t\tmax: MAX_POINTS,\n\t\tlabel: 'Progressive Disclosure',\n\t\tdetails: details.join(', '),\n\t};\n}\n","import type { DimensionScore, Skill } from '@skill-tools/core';\nimport { noHardcodedPaths } from '../rules/no-hardcoded-paths.js';\nimport { noSecrets } from '../rules/no-secrets.js';\n\nconst MAX_POINTS = 10;\n\n/**\n * Score security (10 points max).\n *\n * Factors:\n * - No hardcoded secrets\n * - No hardcoded paths\n * - No suspicious shell patterns\n */\nexport function scoreSecurityScore(skill: Skill): DimensionScore {\n\tlet points = MAX_POINTS;\n\tconst details: string[] = [];\n\n\t// Check for secrets\n\tconst secretDiags = noSecrets.check(skill);\n\tif (secretDiags.length > 0) {\n\t\tpoints -= 10; // Fatal: any secret is a full deduction\n\t\tdetails.push(`${secretDiags.length} possible secret(s) found`);\n\t}\n\n\t// Check for hardcoded paths\n\tconst pathDiags = noHardcodedPaths.check(skill);\n\tif (pathDiags.length > 0) {\n\t\tpoints -= 3;\n\t\tdetails.push(`${pathDiags.length} hardcoded path(s)`);\n\t}\n\n\t// Check for suspicious shell patterns\n\tconst body = skill.body;\n\tconst suspiciousPatterns = [\n\t\t/\\brm\\s+-rf\\s+\\/(?!\\s)/, // rm -rf / (not followed by space)\n\t\t/\\bcurl\\s+.*\\|\\s*(?:bash|sh)\\b/, // curl | bash\n\t\t/\\beval\\s+\\$/, // eval $\n\t];\n\tfor (const pattern of suspiciousPatterns) {\n\t\tif (pattern.test(body)) {\n\t\t\tpoints -= 2;\n\t\t\tdetails.push('Suspicious shell pattern');\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (details.length === 0) {\n\t\tdetails.push('No security issues');\n\t}\n\n\treturn {\n\t\tscore: Math.max(0, points),\n\t\tmax: MAX_POINTS,\n\t\tlabel: 'Security',\n\t\tdetails: details.join(', '),\n\t};\n}\n","import type { DimensionScore, Skill } from '@skill-tools/core';\n\nconst MAX_POINTS = 20;\n\n/**\n * Score spec compliance (20 points max).\n *\n * Factors:\n * - Has name field\n * - Has description field\n * - Name follows format rules\n * - Token count within budget\n * - Has frontmatter\n */\nexport function scoreSpecCompliance(skill: Skill): DimensionScore {\n\tlet points = 0;\n\tconst details: string[] = [];\n\n\t// Has name (0-5 points)\n\tif (skill.metadata.name) {\n\t\tpoints += 5;\n\t\tdetails.push('Has name');\n\t}\n\n\t// Has description (0-5 points)\n\tif (skill.metadata.description) {\n\t\tpoints += 5;\n\t\tdetails.push('Has description');\n\t}\n\n\t// Token budget (0-5 points)\n\tif (skill.tokenCount <= 5000) {\n\t\tpoints += 5;\n\t\tdetails.push(`${skill.tokenCount} tokens (within budget)`);\n\t} else if (skill.tokenCount <= 7500) {\n\t\tpoints += 2;\n\t\tdetails.push(`${skill.tokenCount} tokens (over budget)`);\n\t} else {\n\t\tdetails.push(`${skill.tokenCount} tokens (far over budget)`);\n\t}\n\n\t// Line count (0-5 points)\n\tif (skill.lineCount <= 500) {\n\t\tpoints += 5;\n\t\tdetails.push(`${skill.lineCount} lines`);\n\t} else if (skill.lineCount <= 750) {\n\t\tpoints += 2;\n\t\tdetails.push(`${skill.lineCount} lines (over recommendation)`);\n\t} else {\n\t\tdetails.push(`${skill.lineCount} lines (far over recommendation)`);\n\t}\n\n\treturn {\n\t\tscore: Math.min(points, MAX_POINTS),\n\t\tmax: MAX_POINTS,\n\t\tlabel: 'Spec Compliance',\n\t\tdetails: details.join(', '),\n\t};\n}\n","import type { QualityScore, ScoreSuggestion, Skill } from '@skill-tools/core';\nimport { scoreDescriptionQuality } from './description-quality.js';\nimport { scoreInstructionClarity } from './instruction-clarity.js';\nimport { scoreProgressiveDisclosure } from './progressive-disclosure-score.js';\nimport { scoreSecurityScore } from './security-score.js';\nimport { scoreSpecCompliance } from './spec-compliance.js';\n\n/**\n * Compute the overall quality score for a skill.\n *\n * Score breakdown (100 points total):\n * - Description Quality: 30 points\n * - Instruction Clarity: 25 points\n * - Spec Compliance: 20 points\n * - Progressive Disclosure: 15 points\n * - Security: 10 points\n *\n * @param skill - The parsed Skill object\n * @returns QualityScore with dimension breakdowns and suggestions\n */\nexport function score(skill: Skill): QualityScore {\n\tconst descriptionQuality = scoreDescriptionQuality(skill);\n\tconst instructionClarity = scoreInstructionClarity(skill);\n\tconst specCompliance = scoreSpecCompliance(skill);\n\tconst progressiveDisclosure = scoreProgressiveDisclosure(skill);\n\tconst security = scoreSecurityScore(skill);\n\n\tconst totalScore =\n\t\tdescriptionQuality.score +\n\t\tinstructionClarity.score +\n\t\tspecCompliance.score +\n\t\tprogressiveDisclosure.score +\n\t\tsecurity.score;\n\n\tconst dimensions = {\n\t\tdescription_quality: descriptionQuality,\n\t\tinstruction_clarity: instructionClarity,\n\t\tspec_compliance: specCompliance,\n\t\tprogressive_disclosure: progressiveDisclosure,\n\t\tsecurity,\n\t};\n\n\tconst suggestions = generateSuggestions(skill, dimensions);\n\n\treturn {\n\t\tscore: totalScore,\n\t\tdimensions,\n\t\tsuggestions,\n\t};\n}\n\n/**\n * Generate actionable suggestions based on dimension scores.\n */\nfunction generateSuggestions(\n\tskill: Skill,\n\tdimensions: Record<string, { score: number; max: number }>,\n): ScoreSuggestion[] {\n\tconst suggestions: ScoreSuggestion[] = [];\n\n\tconst descDim = dimensions.description_quality!;\n\tconst instrDim = dimensions.instruction_clarity!;\n\tconst progDim = dimensions.progressive_disclosure!;\n\tconst secDim = dimensions.security!;\n\n\t// Description suggestions\n\tif (!skill.metadata.description) {\n\t\tsuggestions.push({\n\t\t\tmessage: 'Add a description field to the frontmatter',\n\t\t\tpointsGain: 15,\n\t\t\tdimension: 'description_quality',\n\t\t});\n\t} else {\n\t\tif (descDim.score < descDim.max * 0.6) {\n\t\t\tif (!/\\buse when\\b/i.test(skill.metadata.description)) {\n\t\t\t\tsuggestions.push({\n\t\t\t\t\tmessage: 'Add \"Use when...\" to the description to clarify trigger conditions',\n\t\t\t\t\tpointsGain: 8,\n\t\t\t\t\tdimension: 'description_quality',\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t// Instruction suggestions\n\tif (instrDim.score < instrDim.max * 0.5) {\n\t\tconst hasCodeBlock = /```[\\s\\S]*?```/.test(skill.body);\n\t\tif (!hasCodeBlock) {\n\t\t\tsuggestions.push({\n\t\t\t\tmessage: 'Add a concrete usage example with a code block',\n\t\t\t\tpointsGain: 5,\n\t\t\t\tdimension: 'instruction_clarity',\n\t\t\t});\n\t\t}\n\n\t\tconst hasNumberedSteps = /^\\d+\\.\\s+/m.test(skill.body);\n\t\tif (!hasNumberedSteps) {\n\t\t\tsuggestions.push({\n\t\t\t\tmessage: 'Add numbered steps for the main workflow',\n\t\t\t\tpointsGain: 4,\n\t\t\t\tdimension: 'instruction_clarity',\n\t\t\t});\n\t\t}\n\n\t\tconst hasErrorHandling = /#{1,3}\\s+(?:error|troubleshoot)/i.test(skill.body);\n\t\tif (!hasErrorHandling) {\n\t\t\tsuggestions.push({\n\t\t\t\tmessage: 'Add an \"## Error Handling\" section',\n\t\t\t\tpointsGain: 3,\n\t\t\t\tdimension: 'instruction_clarity',\n\t\t\t});\n\t\t}\n\t}\n\n\t// Spec compliance suggestions\n\tif (!skill.metadata.name) {\n\t\tsuggestions.push({\n\t\t\tmessage: 'Add a name field to the frontmatter',\n\t\t\tpointsGain: 5,\n\t\t\tdimension: 'spec_compliance',\n\t\t});\n\t}\n\n\tif (skill.tokenCount > 5000) {\n\t\tsuggestions.push({\n\t\t\tmessage: `Reduce token count from ${skill.tokenCount} to under 5,000`,\n\t\t\tpointsGain: 3,\n\t\t\tdimension: 'spec_compliance',\n\t\t});\n\t}\n\n\t// Progressive disclosure suggestions\n\tif (progDim.score < progDim.max * 0.5 && skill.lineCount > 200) {\n\t\tsuggestions.push({\n\t\t\tmessage: 'Move detailed reference content to a references/ directory',\n\t\t\tpointsGain: 5,\n\t\t\tdimension: 'progressive_disclosure',\n\t\t});\n\t}\n\n\t// Security suggestions\n\tif (secDim.score < secDim.max) {\n\t\tsuggestions.push({\n\t\t\tmessage: 'Fix security issues (secrets, hardcoded paths, or suspicious patterns)',\n\t\t\tpointsGain: secDim.max - secDim.score,\n\t\t\tdimension: 'security',\n\t\t});\n\t}\n\n\t// Sort by point gain descending\n\tsuggestions.sort((a, b) => b.pointsGain - a.pointsGain);\n\n\treturn suggestions;\n}\n","import { existsSync, readdirSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { Diagnostic, Skill } from '@skill-tools/core';\nimport { parseSkill, resolveSkillFiles } from '@skill-tools/core';\n\n/**\n * Result of validating a single skill.\n */\nexport interface ValidationResult {\n\t/** Path to the SKILL.md file */\n\treadonly filePath: string;\n\t/** Skill directory name */\n\treadonly name: string;\n\t/** Whether the skill passed validation (no errors) */\n\treadonly valid: boolean;\n\t/** Parsed skill, if parsing succeeded */\n\treadonly skill: Skill | null;\n\t/** All diagnostics from parsing + structural validation */\n\treadonly diagnostics: readonly Diagnostic[];\n}\n\n/**\n * Validate a SKILL.md file or directory of skills.\n *\n * Runs the parser and structural checks on each discovered skill.\n * Returns validation results with diagnostics for each skill.\n *\n * @param path - Path to a SKILL.md file, skill directory, or directory of skills\n * @returns Array of validation results\n */\nexport async function validate(path: string): Promise<ValidationResult[]> {\n\tconst locations = await resolveSkillFiles(path);\n\n\tif (locations.length === 0) {\n\t\treturn [\n\t\t\t{\n\t\t\t\tfilePath: path,\n\t\t\t\tname: 'unknown',\n\t\t\t\tvalid: false,\n\t\t\t\tskill: null,\n\t\t\t\tdiagnostics: [\n\t\t\t\t\t{\n\t\t\t\t\t\truleId: 'skill-not-found',\n\t\t\t\t\t\tseverity: 'error',\n\t\t\t\t\t\tmessage: `No SKILL.md file found at path: ${path}`,\n\t\t\t\t\t\tfile: path,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t];\n\t}\n\n\tconst results: ValidationResult[] = [];\n\n\tfor (const location of locations) {\n\t\tconst parseResult = await parseSkill(location.skillFile);\n\t\tconst extraDiagnostics = parseResult.ok ? validateStructure(parseResult.skill) : [];\n\n\t\tconst allDiagnostics = [...parseResult.diagnostics, ...extraDiagnostics];\n\t\tconst hasErrors = allDiagnostics.some((d) => d.severity === 'error');\n\n\t\tresults.push({\n\t\t\tfilePath: location.skillFile,\n\t\t\tname: parseResult.ok\n\t\t\t\t? (parseResult.skill.metadata.name ?? location.dirName)\n\t\t\t\t: location.dirName,\n\t\t\tvalid: !hasErrors,\n\t\t\tskill: parseResult.ok ? parseResult.skill : null,\n\t\t\tdiagnostics: allDiagnostics,\n\t\t});\n\t}\n\n\treturn results;\n}\n\n/**\n * Run structural validation checks on a parsed skill.\n * These go beyond what the parser checks.\n */\nfunction validateStructure(skill: Skill): Diagnostic[] {\n\tconst diagnostics: Diagnostic[] = [];\n\n\t// Check that skill directories follow conventions\n\tconst dirPath = skill.dirPath;\n\n\t// Check for unexpected top-level files/directories\n\tconst expectedDirs = ['scripts', 'references', 'assets', 'examples', 'agents'];\n\tconst entries = safeReaddir(dirPath);\n\tfor (const entry of entries) {\n\t\tif (entry === 'SKILL.md' || entry.startsWith('.')) continue;\n\n\t\tconst entryPath = join(dirPath, entry);\n\t\tconst isDir = safeIsDirectory(entryPath);\n\n\t\tif (isDir && !expectedDirs.includes(entry)) {\n\t\t\tdiagnostics.push({\n\t\t\t\truleId: 'unexpected-directory',\n\t\t\t\tseverity: 'info',\n\t\t\t\tmessage: `Unexpected directory \"${entry}\" in skill directory. Expected: ${expectedDirs.join(', ')}`,\n\t\t\t\tfile: skill.filePath,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Verify encoding is UTF-8 (check for BOM or binary content)\n\tif (skill.rawContent.charCodeAt(0) === 0xfeff) {\n\t\tdiagnostics.push({\n\t\t\truleId: 'no-bom',\n\t\t\tseverity: 'warning',\n\t\t\tmessage: 'SKILL.md contains a UTF-8 BOM (byte order mark). Remove it for compatibility',\n\t\t\tfile: skill.filePath,\n\t\t\tline: 1,\n\t\t\tfix: 'Save the file without BOM',\n\t\t});\n\t}\n\n\t// Check for binary content (null bytes)\n\tif (skill.rawContent.includes('\\0')) {\n\t\tdiagnostics.push({\n\t\t\truleId: 'no-binary',\n\t\t\tseverity: 'error',\n\t\t\tmessage: 'SKILL.md contains binary content (null bytes). It must be a text file',\n\t\t\tfile: skill.filePath,\n\t\t});\n\t}\n\n\treturn diagnostics;\n}\n\n/**\n * Safely read directory entries. Returns empty array on failure.\n */\nfunction safeReaddir(dirPath: string): string[] {\n\ttry {\n\t\treturn readdirSync(dirPath).map(String);\n\t} catch {\n\t\treturn [];\n\t}\n}\n\n/**\n * Safely check if a path is a directory.\n */\nfunction safeIsDirectory(path: string): boolean {\n\ttry {\n\t\treturn existsSync(path) && statSync(path).isDirectory();\n\t} catch {\n\t\treturn false;\n\t}\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { DiagnosticSeverity, Skill, Diagnostic, QualityScore } from '@skill-tools/core';
|
|
2
|
+
export { Diagnostic, DiagnosticSeverity, DimensionScore, ParseResult, QualityScore, ScoreSuggestion, Skill, SkillMetadata } from '@skill-tools/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Configuration for a single linting rule.
|
|
6
|
+
*/
|
|
7
|
+
type RuleConfig = DiagnosticSeverity | 'off';
|
|
8
|
+
/**
|
|
9
|
+
* Definition of a linting rule.
|
|
10
|
+
*/
|
|
11
|
+
interface RuleDefinition {
|
|
12
|
+
/** Unique rule ID */
|
|
13
|
+
readonly id: string;
|
|
14
|
+
/** Human-readable description of what the rule checks */
|
|
15
|
+
readonly description: string;
|
|
16
|
+
/** Default severity */
|
|
17
|
+
readonly defaultSeverity: DiagnosticSeverity;
|
|
18
|
+
/**
|
|
19
|
+
* Run the rule against a parsed skill.
|
|
20
|
+
* Returns diagnostics (with severity from the rule definition).
|
|
21
|
+
* The engine will override severity based on user config.
|
|
22
|
+
*/
|
|
23
|
+
check(skill: Skill): Diagnostic[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Map of rule IDs to their configured severity.
|
|
27
|
+
*/
|
|
28
|
+
type RulesConfig = Record<string, RuleConfig>;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Result of linting a single skill.
|
|
32
|
+
*/
|
|
33
|
+
interface LintResult {
|
|
34
|
+
/** Path to the SKILL.md file */
|
|
35
|
+
readonly filePath: string;
|
|
36
|
+
/** Skill name */
|
|
37
|
+
readonly name: string;
|
|
38
|
+
/** All lint diagnostics */
|
|
39
|
+
readonly diagnostics: readonly Diagnostic[];
|
|
40
|
+
/** Count of errors */
|
|
41
|
+
readonly errorCount: number;
|
|
42
|
+
/** Count of warnings */
|
|
43
|
+
readonly warningCount: number;
|
|
44
|
+
/** Count of info messages */
|
|
45
|
+
readonly infoCount: number;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Lint a parsed skill against all enabled rules.
|
|
49
|
+
*
|
|
50
|
+
* @param skill - The parsed Skill object
|
|
51
|
+
* @param rulesConfig - Optional rule severity overrides
|
|
52
|
+
* @returns LintResult with all diagnostics
|
|
53
|
+
*/
|
|
54
|
+
declare function lint(skill: Skill, rulesConfig?: RulesConfig): LintResult;
|
|
55
|
+
/**
|
|
56
|
+
* Parse a rules config that might come from a .skill-toolsrc.yml file.
|
|
57
|
+
* Normalizes string values to proper RuleConfig types.
|
|
58
|
+
*/
|
|
59
|
+
declare function parseRulesConfig(raw: Record<string, unknown>): RulesConfig;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* All built-in lint rules, keyed by rule ID.
|
|
63
|
+
*/
|
|
64
|
+
declare const builtinRules: ReadonlyMap<string, RuleDefinition>;
|
|
65
|
+
/**
|
|
66
|
+
* The "recommended" preset: default severity for each rule.
|
|
67
|
+
*/
|
|
68
|
+
declare const recommendedConfig: Record<string, string>;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Compute the overall quality score for a skill.
|
|
72
|
+
*
|
|
73
|
+
* Score breakdown (100 points total):
|
|
74
|
+
* - Description Quality: 30 points
|
|
75
|
+
* - Instruction Clarity: 25 points
|
|
76
|
+
* - Spec Compliance: 20 points
|
|
77
|
+
* - Progressive Disclosure: 15 points
|
|
78
|
+
* - Security: 10 points
|
|
79
|
+
*
|
|
80
|
+
* @param skill - The parsed Skill object
|
|
81
|
+
* @returns QualityScore with dimension breakdowns and suggestions
|
|
82
|
+
*/
|
|
83
|
+
declare function score(skill: Skill): QualityScore;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Result of validating a single skill.
|
|
87
|
+
*/
|
|
88
|
+
interface ValidationResult {
|
|
89
|
+
/** Path to the SKILL.md file */
|
|
90
|
+
readonly filePath: string;
|
|
91
|
+
/** Skill directory name */
|
|
92
|
+
readonly name: string;
|
|
93
|
+
/** Whether the skill passed validation (no errors) */
|
|
94
|
+
readonly valid: boolean;
|
|
95
|
+
/** Parsed skill, if parsing succeeded */
|
|
96
|
+
readonly skill: Skill | null;
|
|
97
|
+
/** All diagnostics from parsing + structural validation */
|
|
98
|
+
readonly diagnostics: readonly Diagnostic[];
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Validate a SKILL.md file or directory of skills.
|
|
102
|
+
*
|
|
103
|
+
* Runs the parser and structural checks on each discovered skill.
|
|
104
|
+
* Returns validation results with diagnostics for each skill.
|
|
105
|
+
*
|
|
106
|
+
* @param path - Path to a SKILL.md file, skill directory, or directory of skills
|
|
107
|
+
* @returns Array of validation results
|
|
108
|
+
*/
|
|
109
|
+
declare function validate(path: string): Promise<ValidationResult[]>;
|
|
110
|
+
|
|
111
|
+
export { type LintResult, type RuleConfig, type RuleDefinition, type RulesConfig, type ValidationResult, builtinRules, lint, parseRulesConfig, recommendedConfig, score, validate };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { DiagnosticSeverity, Skill, Diagnostic, QualityScore } from '@skill-tools/core';
|
|
2
|
+
export { Diagnostic, DiagnosticSeverity, DimensionScore, ParseResult, QualityScore, ScoreSuggestion, Skill, SkillMetadata } from '@skill-tools/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Configuration for a single linting rule.
|
|
6
|
+
*/
|
|
7
|
+
type RuleConfig = DiagnosticSeverity | 'off';
|
|
8
|
+
/**
|
|
9
|
+
* Definition of a linting rule.
|
|
10
|
+
*/
|
|
11
|
+
interface RuleDefinition {
|
|
12
|
+
/** Unique rule ID */
|
|
13
|
+
readonly id: string;
|
|
14
|
+
/** Human-readable description of what the rule checks */
|
|
15
|
+
readonly description: string;
|
|
16
|
+
/** Default severity */
|
|
17
|
+
readonly defaultSeverity: DiagnosticSeverity;
|
|
18
|
+
/**
|
|
19
|
+
* Run the rule against a parsed skill.
|
|
20
|
+
* Returns diagnostics (with severity from the rule definition).
|
|
21
|
+
* The engine will override severity based on user config.
|
|
22
|
+
*/
|
|
23
|
+
check(skill: Skill): Diagnostic[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Map of rule IDs to their configured severity.
|
|
27
|
+
*/
|
|
28
|
+
type RulesConfig = Record<string, RuleConfig>;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Result of linting a single skill.
|
|
32
|
+
*/
|
|
33
|
+
interface LintResult {
|
|
34
|
+
/** Path to the SKILL.md file */
|
|
35
|
+
readonly filePath: string;
|
|
36
|
+
/** Skill name */
|
|
37
|
+
readonly name: string;
|
|
38
|
+
/** All lint diagnostics */
|
|
39
|
+
readonly diagnostics: readonly Diagnostic[];
|
|
40
|
+
/** Count of errors */
|
|
41
|
+
readonly errorCount: number;
|
|
42
|
+
/** Count of warnings */
|
|
43
|
+
readonly warningCount: number;
|
|
44
|
+
/** Count of info messages */
|
|
45
|
+
readonly infoCount: number;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Lint a parsed skill against all enabled rules.
|
|
49
|
+
*
|
|
50
|
+
* @param skill - The parsed Skill object
|
|
51
|
+
* @param rulesConfig - Optional rule severity overrides
|
|
52
|
+
* @returns LintResult with all diagnostics
|
|
53
|
+
*/
|
|
54
|
+
declare function lint(skill: Skill, rulesConfig?: RulesConfig): LintResult;
|
|
55
|
+
/**
|
|
56
|
+
* Parse a rules config that might come from a .skill-toolsrc.yml file.
|
|
57
|
+
* Normalizes string values to proper RuleConfig types.
|
|
58
|
+
*/
|
|
59
|
+
declare function parseRulesConfig(raw: Record<string, unknown>): RulesConfig;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* All built-in lint rules, keyed by rule ID.
|
|
63
|
+
*/
|
|
64
|
+
declare const builtinRules: ReadonlyMap<string, RuleDefinition>;
|
|
65
|
+
/**
|
|
66
|
+
* The "recommended" preset: default severity for each rule.
|
|
67
|
+
*/
|
|
68
|
+
declare const recommendedConfig: Record<string, string>;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Compute the overall quality score for a skill.
|
|
72
|
+
*
|
|
73
|
+
* Score breakdown (100 points total):
|
|
74
|
+
* - Description Quality: 30 points
|
|
75
|
+
* - Instruction Clarity: 25 points
|
|
76
|
+
* - Spec Compliance: 20 points
|
|
77
|
+
* - Progressive Disclosure: 15 points
|
|
78
|
+
* - Security: 10 points
|
|
79
|
+
*
|
|
80
|
+
* @param skill - The parsed Skill object
|
|
81
|
+
* @returns QualityScore with dimension breakdowns and suggestions
|
|
82
|
+
*/
|
|
83
|
+
declare function score(skill: Skill): QualityScore;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Result of validating a single skill.
|
|
87
|
+
*/
|
|
88
|
+
interface ValidationResult {
|
|
89
|
+
/** Path to the SKILL.md file */
|
|
90
|
+
readonly filePath: string;
|
|
91
|
+
/** Skill directory name */
|
|
92
|
+
readonly name: string;
|
|
93
|
+
/** Whether the skill passed validation (no errors) */
|
|
94
|
+
readonly valid: boolean;
|
|
95
|
+
/** Parsed skill, if parsing succeeded */
|
|
96
|
+
readonly skill: Skill | null;
|
|
97
|
+
/** All diagnostics from parsing + structural validation */
|
|
98
|
+
readonly diagnostics: readonly Diagnostic[];
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Validate a SKILL.md file or directory of skills.
|
|
102
|
+
*
|
|
103
|
+
* Runs the parser and structural checks on each discovered skill.
|
|
104
|
+
* Returns validation results with diagnostics for each skill.
|
|
105
|
+
*
|
|
106
|
+
* @param path - Path to a SKILL.md file, skill directory, or directory of skills
|
|
107
|
+
* @returns Array of validation results
|
|
108
|
+
*/
|
|
109
|
+
declare function validate(path: string): Promise<ValidationResult[]>;
|
|
110
|
+
|
|
111
|
+
export { type LintResult, type RuleConfig, type RuleDefinition, type RulesConfig, type ValidationResult, builtinRules, lint, parseRulesConfig, recommendedConfig, score, validate };
|