skill-validator 1.0.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/API.md +387 -0
- package/CHANGELOG.md +62 -0
- package/DEPLOYMENT.md +238 -0
- package/LICENSE +21 -0
- package/PUBLISHING.md +313 -0
- package/README.md +375 -0
- package/bin/skill-validator.js +145 -0
- package/lib/formatter.js +103 -0
- package/lib/validator.js +253 -0
- package/package.json +55 -0
package/API.md
ADDED
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
# API Documentation
|
|
2
|
+
|
|
3
|
+
## Using Skill Validator as a Library
|
|
4
|
+
|
|
5
|
+
You can use skill-validator programmatically in your Node.js applications.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install skill-validator
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## SkillValidator Class
|
|
14
|
+
|
|
15
|
+
### Constructor
|
|
16
|
+
|
|
17
|
+
```javascript
|
|
18
|
+
const { SkillValidator } = require('skill-validator');
|
|
19
|
+
|
|
20
|
+
const validator = new SkillValidator();
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Methods
|
|
24
|
+
|
|
25
|
+
#### `validate(content, filepath?)`
|
|
26
|
+
|
|
27
|
+
Validates skill.md content and returns a detailed report.
|
|
28
|
+
|
|
29
|
+
**Parameters:**
|
|
30
|
+
- `content` (string, required) - The skill.md file content to validate
|
|
31
|
+
- `filepath` (string, optional) - File path for identification in report (defaults to 'skill.md')
|
|
32
|
+
|
|
33
|
+
**Returns:** Report object (see Report Structure below)
|
|
34
|
+
|
|
35
|
+
**Example:**
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
const { SkillValidator } = require('skill-validator');
|
|
39
|
+
const fs = require('fs');
|
|
40
|
+
|
|
41
|
+
const validator = new SkillValidator();
|
|
42
|
+
const skillContent = fs.readFileSync('my-skill.md', 'utf-8');
|
|
43
|
+
|
|
44
|
+
const report = validator.validate(skillContent, 'skills/my-skill.md');
|
|
45
|
+
|
|
46
|
+
console.log(`Validation: ${report.passed ? 'PASSED' : 'FAILED'}`);
|
|
47
|
+
console.log(`Issues found: ${report.issueCount}`);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Report Structure
|
|
51
|
+
|
|
52
|
+
The validate method returns an object with this structure:
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
{
|
|
56
|
+
// File identification
|
|
57
|
+
filepath: string, // Path provided to validate()
|
|
58
|
+
|
|
59
|
+
// Overall status
|
|
60
|
+
passed: boolean, // true if no critical issues
|
|
61
|
+
issueCount: number, // Total number of issues
|
|
62
|
+
criticalCount: number, // Number of critical issues
|
|
63
|
+
warningCount: number, // Number of warnings
|
|
64
|
+
infoCount: number, // Number of info messages
|
|
65
|
+
|
|
66
|
+
// Detailed issues
|
|
67
|
+
issues: Issue[] // Array of Issue objects
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Issue Object
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
{
|
|
75
|
+
type: 'security' | 'documentation' | 'bestPractices',
|
|
76
|
+
severity: 'critical' | 'warning' | 'info',
|
|
77
|
+
message: string, // Human-readable message
|
|
78
|
+
context?: string // Code snippet or context (for security issues)
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Validation Rules
|
|
83
|
+
|
|
84
|
+
### Security Issues
|
|
85
|
+
|
|
86
|
+
Detects:
|
|
87
|
+
- Hardcoded passwords, API keys, tokens, secrets
|
|
88
|
+
- Dangerous functions (eval, exec without validation)
|
|
89
|
+
- Unencrypted HTTP URLs
|
|
90
|
+
- Bearer token patterns
|
|
91
|
+
|
|
92
|
+
**Severity:** Mostly `critical`, some `warning`
|
|
93
|
+
|
|
94
|
+
### Documentation Issues
|
|
95
|
+
|
|
96
|
+
Checks for required sections:
|
|
97
|
+
- Overview/Description
|
|
98
|
+
- Parameters/Arguments
|
|
99
|
+
- Returns/Output
|
|
100
|
+
- Examples
|
|
101
|
+
- Error Handling
|
|
102
|
+
|
|
103
|
+
**Severity:** `warning`
|
|
104
|
+
|
|
105
|
+
### Best Practices Issues
|
|
106
|
+
|
|
107
|
+
Validates:
|
|
108
|
+
- Error handling documentation
|
|
109
|
+
- Permission/authentication documentation
|
|
110
|
+
- Input validation documentation
|
|
111
|
+
- Usage warnings
|
|
112
|
+
- Code block language specification
|
|
113
|
+
|
|
114
|
+
**Severity:** `warning` and `info`
|
|
115
|
+
|
|
116
|
+
## Complete Example
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
119
|
+
const { SkillValidator } = require('skill-validator');
|
|
120
|
+
const fs = require('fs');
|
|
121
|
+
const path = require('path');
|
|
122
|
+
|
|
123
|
+
function validateSkills(directory) {
|
|
124
|
+
const validator = new SkillValidator();
|
|
125
|
+
const results = [];
|
|
126
|
+
|
|
127
|
+
// Recursive directory walk
|
|
128
|
+
function walkDir(dir) {
|
|
129
|
+
const files = fs.readdirSync(dir);
|
|
130
|
+
|
|
131
|
+
files.forEach(file => {
|
|
132
|
+
const fullPath = path.join(dir, file);
|
|
133
|
+
const stat = fs.statSync(fullPath);
|
|
134
|
+
|
|
135
|
+
if (stat.isDirectory()) {
|
|
136
|
+
walkDir(fullPath);
|
|
137
|
+
} else if (file === 'skill.md' || file.endsWith('.skill.md')) {
|
|
138
|
+
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
139
|
+
const report = validator.validate(content, fullPath);
|
|
140
|
+
results.push(report);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
walkDir(directory);
|
|
146
|
+
|
|
147
|
+
// Generate summary
|
|
148
|
+
const summary = {
|
|
149
|
+
total: results.length,
|
|
150
|
+
passed: results.filter(r => r.passed).length,
|
|
151
|
+
failed: results.filter(r => !r.passed).length,
|
|
152
|
+
criticalIssues: results.reduce((sum, r) => sum + r.criticalCount, 0),
|
|
153
|
+
details: results
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
return summary;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Usage
|
|
160
|
+
const report = validateSkills('./skills');
|
|
161
|
+
console.log(JSON.stringify(report, null, 2));
|
|
162
|
+
|
|
163
|
+
// Filter for critical issues only
|
|
164
|
+
const critical = report.details
|
|
165
|
+
.filter(r => r.criticalCount > 0)
|
|
166
|
+
.map(r => ({ file: r.filepath, issues: r.issues.filter(i => i.severity === 'critical') }));
|
|
167
|
+
|
|
168
|
+
console.log('Critical Issues:', critical);
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Integration Examples
|
|
172
|
+
|
|
173
|
+
### Express.js Middleware
|
|
174
|
+
|
|
175
|
+
```javascript
|
|
176
|
+
const express = require('express');
|
|
177
|
+
const { SkillValidator } = require('skill-validator');
|
|
178
|
+
|
|
179
|
+
const app = express();
|
|
180
|
+
const validator = new SkillValidator();
|
|
181
|
+
|
|
182
|
+
app.post('/validate-skill', express.text({ type: 'text/markdown' }), (req, res) => {
|
|
183
|
+
try {
|
|
184
|
+
const report = validator.validate(req.body);
|
|
185
|
+
res.json({
|
|
186
|
+
success: report.passed,
|
|
187
|
+
report: report
|
|
188
|
+
});
|
|
189
|
+
} catch (error) {
|
|
190
|
+
res.status(400).json({ error: error.message });
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
app.listen(3000);
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### CI/CD Integration
|
|
198
|
+
|
|
199
|
+
```javascript
|
|
200
|
+
// scripts/validate-skills.js
|
|
201
|
+
const { SkillValidator } = require('skill-validator');
|
|
202
|
+
const fs = require('fs');
|
|
203
|
+
|
|
204
|
+
const validator = new SkillValidator();
|
|
205
|
+
let exitCode = 0;
|
|
206
|
+
|
|
207
|
+
// Validate all skills
|
|
208
|
+
const files = fs.readdirSync('./skills').filter(f => f.endsWith('.md'));
|
|
209
|
+
|
|
210
|
+
files.forEach(file => {
|
|
211
|
+
const content = fs.readFileSync(`./skills/${file}`, 'utf-8');
|
|
212
|
+
const report = validator.validate(content, file);
|
|
213
|
+
|
|
214
|
+
if (!report.passed) {
|
|
215
|
+
console.error(`❌ ${file}: ${report.criticalCount} critical issues`);
|
|
216
|
+
exitCode = 1;
|
|
217
|
+
} else {
|
|
218
|
+
console.log(`✅ ${file}: OK`);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
process.exit(exitCode);
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Use in `package.json`:
|
|
226
|
+
```json
|
|
227
|
+
{
|
|
228
|
+
"scripts": {
|
|
229
|
+
"validate-skills": "node scripts/validate-skills.js"
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Test Suite
|
|
235
|
+
|
|
236
|
+
```javascript
|
|
237
|
+
const { SkillValidator } = require('skill-validator');
|
|
238
|
+
|
|
239
|
+
describe('Skill Validation', () => {
|
|
240
|
+
const validator = new SkillValidator();
|
|
241
|
+
|
|
242
|
+
test('should pass well-documented skill', () => {
|
|
243
|
+
const content = `
|
|
244
|
+
# Overview
|
|
245
|
+
Complete documentation
|
|
246
|
+
|
|
247
|
+
## Parameters
|
|
248
|
+
- input: string
|
|
249
|
+
|
|
250
|
+
## Returns
|
|
251
|
+
- output: string
|
|
252
|
+
|
|
253
|
+
## Examples
|
|
254
|
+
\`\`\`javascript
|
|
255
|
+
const result = await skill();
|
|
256
|
+
\`\`\`
|
|
257
|
+
|
|
258
|
+
## Error Handling
|
|
259
|
+
Errors are caught.
|
|
260
|
+
|
|
261
|
+
## Permissions
|
|
262
|
+
No special permissions needed.
|
|
263
|
+
`;
|
|
264
|
+
|
|
265
|
+
const report = validator.validate(content);
|
|
266
|
+
expect(report.passed).toBe(true);
|
|
267
|
+
expect(report.criticalCount).toBe(0);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
test('should detect security issues', () => {
|
|
271
|
+
const content = `
|
|
272
|
+
# Skill
|
|
273
|
+
password = "secret123"
|
|
274
|
+
`;
|
|
275
|
+
|
|
276
|
+
const report = validator.validate(content);
|
|
277
|
+
expect(report.passed).toBe(false);
|
|
278
|
+
expect(report.criticalCount).toBeGreaterThan(0);
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## Error Handling
|
|
284
|
+
|
|
285
|
+
The `validate()` method doesn't throw errors - it captures them in the report:
|
|
286
|
+
|
|
287
|
+
```javascript
|
|
288
|
+
const { SkillValidator } = require('skill-validator');
|
|
289
|
+
|
|
290
|
+
try {
|
|
291
|
+
const validator = new SkillValidator();
|
|
292
|
+
const report = validator.validate(null); // Invalid input
|
|
293
|
+
|
|
294
|
+
if (!report.passed) {
|
|
295
|
+
console.log('Validation failed:');
|
|
296
|
+
console.log(report.issues);
|
|
297
|
+
}
|
|
298
|
+
} catch (error) {
|
|
299
|
+
console.error('Unexpected error:', error);
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## Performance
|
|
304
|
+
|
|
305
|
+
The validator is optimized for:
|
|
306
|
+
- **Single file validation:** <5ms
|
|
307
|
+
- **Typical skill.md:** <1ms
|
|
308
|
+
- **Large directory scan:** <100ms for 100 files
|
|
309
|
+
|
|
310
|
+
No external API calls or network overhead.
|
|
311
|
+
|
|
312
|
+
## Advanced Usage
|
|
313
|
+
|
|
314
|
+
### Custom Rule Implementation
|
|
315
|
+
|
|
316
|
+
Create extensions by subclassing:
|
|
317
|
+
|
|
318
|
+
```javascript
|
|
319
|
+
const { SkillValidator } = require('skill-validator');
|
|
320
|
+
|
|
321
|
+
class CustomValidator extends SkillValidator {
|
|
322
|
+
checkCustomRules(content) {
|
|
323
|
+
const issues = [];
|
|
324
|
+
|
|
325
|
+
// Add your custom validation logic
|
|
326
|
+
if (!content.includes('License')) {
|
|
327
|
+
issues.push({
|
|
328
|
+
type: 'documentation',
|
|
329
|
+
severity: 'info',
|
|
330
|
+
message: 'Missing License section'
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
return issues;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
validate(content, filepath) {
|
|
338
|
+
const baseReport = super.validate(content, filepath);
|
|
339
|
+
const customIssues = this.checkCustomRules(content);
|
|
340
|
+
|
|
341
|
+
baseReport.issues.push(...customIssues);
|
|
342
|
+
baseReport.issueCount = baseReport.issues.length;
|
|
343
|
+
|
|
344
|
+
return baseReport;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const validator = new CustomValidator();
|
|
349
|
+
const report = validator.validate(skillContent);
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
## Troubleshooting
|
|
353
|
+
|
|
354
|
+
### Invalid input types
|
|
355
|
+
|
|
356
|
+
```javascript
|
|
357
|
+
// ❌ Wrong
|
|
358
|
+
validator.validate(123); // String expected
|
|
359
|
+
validator.validate(Buffer.from()); // String expected
|
|
360
|
+
|
|
361
|
+
// ✅ Correct
|
|
362
|
+
validator.validate('# Skill\nContent');
|
|
363
|
+
validator.validate(fs.readFileSync('skill.md', 'utf-8'));
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### Always check the report
|
|
367
|
+
|
|
368
|
+
```javascript
|
|
369
|
+
const report = validator.validate(content);
|
|
370
|
+
|
|
371
|
+
// Check if validation passed
|
|
372
|
+
if (report.passed) {
|
|
373
|
+
console.log('✅ Ready for production');
|
|
374
|
+
} else {
|
|
375
|
+
// Handle critical issues
|
|
376
|
+
const critical = report.issues.filter(i => i.severity === 'critical');
|
|
377
|
+
console.error('❌ Fix these issues:', critical);
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
## License
|
|
382
|
+
|
|
383
|
+
skill-validator is MIT licensed. Use freely in your applications.
|
|
384
|
+
|
|
385
|
+
---
|
|
386
|
+
|
|
387
|
+
For CLI usage, see [README.md](./README.md)
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] - 2024-01-01
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Initial release of skill-validator CLI tool
|
|
12
|
+
- Security checks for hardcoded credentials, dangerous functions, and unencrypted URLs
|
|
13
|
+
- Documentation validation for required sections (Overview, Parameters, Returns, Examples, Error Handling)
|
|
14
|
+
- Best practices validation for error handling, permissions, input validation, and code blocks
|
|
15
|
+
- Support for single file validation with `validate` command
|
|
16
|
+
- Support for directory scanning with `scan` command
|
|
17
|
+
- Colorized terminal reports with severity levels
|
|
18
|
+
- JSON output format for automation and tooling
|
|
19
|
+
- Comprehensive test suite with 17 passing tests
|
|
20
|
+
- Full API documentation for programmatic usage
|
|
21
|
+
- Example skills (good and bad) for testing
|
|
22
|
+
- MIT License
|
|
23
|
+
- GitHub Actions CI/CD setup
|
|
24
|
+
- npm package publication support
|
|
25
|
+
|
|
26
|
+
### Features
|
|
27
|
+
- Fast validation (<5ms per file)
|
|
28
|
+
- Zero external dependencies
|
|
29
|
+
- Exit code support for CI/CD pipelines
|
|
30
|
+
- File output support for reports
|
|
31
|
+
- Recursive directory scanning
|
|
32
|
+
- Comprehensive validation rule set
|
|
33
|
+
|
|
34
|
+
## Future Releases
|
|
35
|
+
|
|
36
|
+
### [1.1.0] (Planned)
|
|
37
|
+
- Config file support (.skillvalidatorrc)
|
|
38
|
+
- Custom rule definitions
|
|
39
|
+
- HTML report generation
|
|
40
|
+
- Integration with skill templates
|
|
41
|
+
- Performance benchmarks
|
|
42
|
+
|
|
43
|
+
### [2.0.0] (Planned)
|
|
44
|
+
- VS Code extension
|
|
45
|
+
- GitHub Action for CI/CD
|
|
46
|
+
- Extended test coverage
|
|
47
|
+
- Support for YAML/JSON skill formats
|
|
48
|
+
- Advanced security scanning rules
|
|
49
|
+
- Custom validation rule marketplace
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Version History
|
|
54
|
+
|
|
55
|
+
| Version | Release Date | Status |
|
|
56
|
+
|---------|------------|--------|
|
|
57
|
+
| 1.0.0 | 2024-01-01 | Released |
|
|
58
|
+
|
|
59
|
+
## Support
|
|
60
|
+
|
|
61
|
+
For issues and feature requests, visit:
|
|
62
|
+
https://github.com/bagalobsta/skill-validator/issues
|
package/DEPLOYMENT.md
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# 🚀 Deployment & Quick Start
|
|
2
|
+
|
|
3
|
+
## Installation
|
|
4
|
+
|
|
5
|
+
### From npm (Recommended)
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g skill-validator
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### From source
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
git clone https://github.com/bagalobsta/skill-validator.git
|
|
15
|
+
cd skill-validator
|
|
16
|
+
npm install
|
|
17
|
+
npm run validate examples/good-skill.md
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
### Validate a Single File
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
skill-validator validate my-skill.md
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Example Output:**
|
|
29
|
+
```
|
|
30
|
+
📋 Skill Validator Report
|
|
31
|
+
════════════════════════════════════════════════════
|
|
32
|
+
|
|
33
|
+
File: my-skill.md
|
|
34
|
+
Status: ✓ PASSED
|
|
35
|
+
|
|
36
|
+
Summary:
|
|
37
|
+
Total Issues: 0
|
|
38
|
+
Critical: 0
|
|
39
|
+
Warnings: 0
|
|
40
|
+
Info: 0
|
|
41
|
+
|
|
42
|
+
✨ No issues found! Your skill is well documented.
|
|
43
|
+
|
|
44
|
+
════════════════════════════════════════════════════
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Scan a Directory
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
skill-validator scan ./skills/
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Get JSON Output
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
skill-validator validate my-skill.md --json
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Save Report to File
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
skill-validator validate my-skill.md --output report.txt
|
|
63
|
+
skill-validator validate my-skill.md --json --output report.json
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## GitHub Actions Integration
|
|
67
|
+
|
|
68
|
+
Add to `.github/workflows/validate-skills.yml`:
|
|
69
|
+
|
|
70
|
+
```yaml
|
|
71
|
+
name: Validate Skills
|
|
72
|
+
|
|
73
|
+
on: [push, pull_request]
|
|
74
|
+
|
|
75
|
+
jobs:
|
|
76
|
+
validate:
|
|
77
|
+
runs-on: ubuntu-latest
|
|
78
|
+
steps:
|
|
79
|
+
- uses: actions/checkout@v3
|
|
80
|
+
|
|
81
|
+
- uses: actions/setup-node@v3
|
|
82
|
+
with:
|
|
83
|
+
node-version: '18'
|
|
84
|
+
|
|
85
|
+
- run: npm install -g skill-validator
|
|
86
|
+
|
|
87
|
+
- run: skill-validator scan ./skills/
|
|
88
|
+
|
|
89
|
+
- run: skill-validator scan ./skills/ --json --output report.json
|
|
90
|
+
|
|
91
|
+
- uses: actions/upload-artifact@v3
|
|
92
|
+
if: always()
|
|
93
|
+
with:
|
|
94
|
+
name: validation-report
|
|
95
|
+
path: report.json
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Docker
|
|
99
|
+
|
|
100
|
+
Create a `Dockerfile`:
|
|
101
|
+
|
|
102
|
+
```dockerfile
|
|
103
|
+
FROM node:18-alpine
|
|
104
|
+
WORKDIR /app
|
|
105
|
+
RUN npm install -g skill-validator
|
|
106
|
+
COPY . .
|
|
107
|
+
CMD ["skill-validator", "scan", "."]
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Build and run:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
docker build -t skill-validator .
|
|
114
|
+
docker run skill-validator
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Pre-commit Hook
|
|
118
|
+
|
|
119
|
+
Create `.git/hooks/pre-commit`:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
#!/bin/bash
|
|
123
|
+
skill-validator scan . || {
|
|
124
|
+
echo "❌ Skill validation failed. Fix issues before committing."
|
|
125
|
+
exit 1
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Make it executable:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
chmod +x .git/hooks/pre-commit
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## CI/CD Pipeline Examples
|
|
136
|
+
|
|
137
|
+
### GitLab CI
|
|
138
|
+
|
|
139
|
+
```yaml
|
|
140
|
+
validate-skills:
|
|
141
|
+
image: node:18
|
|
142
|
+
script:
|
|
143
|
+
- npm install -g skill-validator
|
|
144
|
+
- skill-validator scan ./skills/ --json --output report.json
|
|
145
|
+
artifacts:
|
|
146
|
+
paths:
|
|
147
|
+
- report.json
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Jenkins
|
|
151
|
+
|
|
152
|
+
```groovy
|
|
153
|
+
stage('Validate Skills') {
|
|
154
|
+
steps {
|
|
155
|
+
sh 'npm install -g skill-validator'
|
|
156
|
+
sh 'skill-validator scan ./skills/'
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Programmatic Usage
|
|
162
|
+
|
|
163
|
+
See [API.md](./API.md) for detailed examples.
|
|
164
|
+
|
|
165
|
+
Quick example:
|
|
166
|
+
|
|
167
|
+
```javascript
|
|
168
|
+
const { SkillValidator } = require('skill-validator');
|
|
169
|
+
const fs = require('fs');
|
|
170
|
+
|
|
171
|
+
const validator = new SkillValidator();
|
|
172
|
+
const content = fs.readFileSync('skill.md', 'utf-8');
|
|
173
|
+
const report = validator.validate(content);
|
|
174
|
+
|
|
175
|
+
if (report.passed) {
|
|
176
|
+
console.log('✅ Skill is valid');
|
|
177
|
+
} else {
|
|
178
|
+
console.log(`❌ Found ${report.issueCount} issues`);
|
|
179
|
+
report.issues.forEach(issue => {
|
|
180
|
+
console.log(` [${issue.severity}] ${issue.message}`);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Exit Codes
|
|
186
|
+
|
|
187
|
+
- `0` - Validation passed (no critical issues)
|
|
188
|
+
- `1` - Validation failed (critical issues found)
|
|
189
|
+
|
|
190
|
+
Perfect for CI/CD:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
skill-validator validate skill.md && echo "✅ Ready!" || echo "❌ Fix issues"
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Troubleshooting
|
|
197
|
+
|
|
198
|
+
### Command not found
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
# Install globally
|
|
202
|
+
npm install -g skill-validator
|
|
203
|
+
|
|
204
|
+
# Or use with npx
|
|
205
|
+
npx skill-validator --version
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Permission denied
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
# Update npm permissions
|
|
212
|
+
npm install -g --unsafe-perm skill-validator
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Update to latest version
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
npm install -g skill-validator@latest
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Support
|
|
222
|
+
|
|
223
|
+
- 📖 [GitHub Repo](https://github.com/bagalobsta/skill-validator)
|
|
224
|
+
- 🐛 [Report Issues](https://github.com/bagalobsta/skill-validator/issues)
|
|
225
|
+
- 💬 [Discussions](https://github.com/bagalobsta/skill-validator/discussions)
|
|
226
|
+
- 📧 [Email Support](mailto:bagalobsta@protonmail.com)
|
|
227
|
+
|
|
228
|
+
## Next Steps
|
|
229
|
+
|
|
230
|
+
1. ✅ Install skill-validator
|
|
231
|
+
2. ✅ Validate your skills
|
|
232
|
+
3. ✅ Fix any issues found
|
|
233
|
+
4. ✅ Integrate into CI/CD
|
|
234
|
+
5. ✅ Share with your team
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
Ready to ship! 🚀
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Bagalobsta
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|