@claude-collective/cli 0.13.4 → 0.21.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/CHANGELOG.md +183 -0
- package/config/skills-matrix.yaml +180 -113
- package/config/stacks.yaml +6 -6
- package/dist/{chunk-K3NB6DSG.js → chunk-2LSGX6R4.js} +54 -114
- package/dist/chunk-2LSGX6R4.js.map +1 -0
- package/dist/chunk-2OKUEELH.js +32 -0
- package/dist/chunk-2OKUEELH.js.map +1 -0
- package/dist/{chunk-V46GGCCI.js → chunk-374JNMR6.js} +14 -96
- package/dist/chunk-374JNMR6.js.map +1 -0
- package/dist/chunk-3EHUF54X.js +133 -0
- package/dist/chunk-3EHUF54X.js.map +1 -0
- package/dist/{chunk-7Q44DMSP.js → chunk-3XR4PALU.js} +92 -145
- package/dist/chunk-3XR4PALU.js.map +1 -0
- package/dist/{chunk-IAUAQJQ2.js → chunk-5K2ZLUO5.js} +5 -5
- package/dist/{chunk-IAUAQJQ2.js.map → chunk-5K2ZLUO5.js.map} +1 -1
- package/dist/{chunk-ACNBKXXJ.js → chunk-5KXUDHAB.js} +8 -36
- package/dist/chunk-5KXUDHAB.js.map +1 -0
- package/dist/chunk-7SLV7CMF.js +615 -0
- package/dist/chunk-7SLV7CMF.js.map +1 -0
- package/dist/{chunk-CDX4W4DM.js → chunk-A46TPNBJ.js} +61 -32
- package/dist/chunk-A46TPNBJ.js.map +1 -0
- package/dist/{chunk-TKFPKEV3.js → chunk-AL74GBW4.js} +1 -1
- package/dist/chunk-AL74GBW4.js.map +1 -0
- package/dist/chunk-BQX23RBV.js +191 -0
- package/dist/chunk-BQX23RBV.js.map +1 -0
- package/dist/{chunk-IMDW5ZUP.js → chunk-CA4LH4LI.js} +5 -5
- package/dist/chunk-CA4LH4LI.js.map +1 -0
- package/dist/{chunk-D237EVNB.js → chunk-CBLPAMZO.js} +5 -8
- package/dist/chunk-CBLPAMZO.js.map +1 -0
- package/dist/{chunk-B7CCVP6Q.js → chunk-CKPQHGXR.js} +52 -274
- package/dist/chunk-CKPQHGXR.js.map +1 -0
- package/dist/{chunk-SVYPSDWY.js → chunk-CXOFOJCN.js} +6 -10
- package/dist/chunk-CXOFOJCN.js.map +1 -0
- package/dist/{chunk-UQTEPWU7.js → chunk-EHGD7HIE.js} +2 -6
- package/dist/chunk-EHGD7HIE.js.map +1 -0
- package/dist/{chunk-76DWXGQE.js → chunk-FJFEKPXF.js} +1 -1
- package/dist/chunk-FJFEKPXF.js.map +1 -0
- package/dist/{chunk-E3FJH4TF.js → chunk-HEOHU5EZ.js} +2 -13
- package/dist/chunk-HEOHU5EZ.js.map +1 -0
- package/dist/{chunk-JIPWV2FX.js → chunk-HGCBZUH5.js} +6 -27
- package/dist/chunk-HGCBZUH5.js.map +1 -0
- package/dist/{chunk-ED4E6Q2T.js → chunk-HPGFY5ZN.js} +4 -4
- package/dist/chunk-HPGFY5ZN.js.map +1 -0
- package/dist/chunk-INJ2EFRW.js +127 -0
- package/dist/chunk-INJ2EFRW.js.map +1 -0
- package/dist/{chunk-KAAEN2PO.js → chunk-IOBFMF6X.js} +6 -2
- package/dist/{chunk-KAAEN2PO.js.map → chunk-IOBFMF6X.js.map} +1 -1
- package/dist/{chunk-K7EVM5LY.js → chunk-KH3HA7J7.js} +8 -33
- package/dist/chunk-KH3HA7J7.js.map +1 -0
- package/dist/{chunk-4K4ZXQRM.js → chunk-N6JNE326.js} +38 -94
- package/dist/chunk-N6JNE326.js.map +1 -0
- package/dist/chunk-NAGU7TVZ.js +36 -0
- package/dist/chunk-NAGU7TVZ.js.map +1 -0
- package/dist/{chunk-Z7G4B5HJ.js → chunk-OQYYMQJR.js} +68 -142
- package/dist/chunk-OQYYMQJR.js.map +1 -0
- package/dist/{chunk-RFTSZDHV.js → chunk-PLZOUVDD.js} +159 -53
- package/dist/chunk-PLZOUVDD.js.map +1 -0
- package/dist/chunk-Q3J43SF3.js +21 -0
- package/dist/chunk-Q3J43SF3.js.map +1 -0
- package/dist/{chunk-3U3R4NCG.js → chunk-T25OEQFI.js} +6 -2
- package/dist/chunk-T25OEQFI.js.map +1 -0
- package/dist/chunk-UMORK7OK.js +29 -0
- package/dist/chunk-UMORK7OK.js.map +1 -0
- package/dist/{chunk-ZFPSUQOU.js → chunk-VFHWU7JU.js} +12 -121
- package/dist/chunk-VFHWU7JU.js.map +1 -0
- package/dist/{chunk-GDH553MV.js → chunk-VS4GVTZE.js} +3 -3
- package/dist/chunk-VS4GVTZE.js.map +1 -0
- package/dist/chunk-WFEFICFM.js +67 -0
- package/dist/chunk-WFEFICFM.js.map +1 -0
- package/dist/{chunk-P26A2K5N.js → chunk-WG6KIAPK.js} +6 -16
- package/dist/chunk-WG6KIAPK.js.map +1 -0
- package/dist/{chunk-X6QONICW.js → chunk-ZEI3ZUDU.js} +3 -7
- package/dist/chunk-ZEI3ZUDU.js.map +1 -0
- package/dist/chunk-ZNIDWLL5.js +68 -0
- package/dist/chunk-ZNIDWLL5.js.map +1 -0
- package/dist/chunk-ZSVMS677.js +45 -0
- package/dist/chunk-ZSVMS677.js.map +1 -0
- package/dist/cli/defaults/agent-mappings.yaml +13 -13
- package/dist/commands/build/marketplace.js +8 -14
- package/dist/commands/build/marketplace.js.map +1 -1
- package/dist/commands/build/plugins.js +10 -21
- package/dist/commands/build/plugins.js.map +1 -1
- package/dist/commands/build/stack.js +13 -18
- package/dist/commands/build/stack.js.map +1 -1
- package/dist/commands/compile.js +25 -40
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/config/get.js +7 -7
- package/dist/commands/config/get.js.map +1 -1
- package/dist/commands/config/index.js +6 -6
- package/dist/commands/config/index.js.map +1 -1
- package/dist/commands/config/path.js +5 -7
- package/dist/commands/config/path.js.map +1 -1
- package/dist/commands/config/set-project.js +8 -9
- package/dist/commands/config/set-project.js.map +1 -1
- package/dist/commands/config/show.js +5 -5
- package/dist/commands/config/unset-project.js +8 -9
- package/dist/commands/config/unset-project.js.map +1 -1
- package/dist/commands/diff.js +17 -40
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/doctor.js +14 -25
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +41 -54
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +24 -44
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/import/skill.js +19 -39
- package/dist/commands/import/skill.js.map +1 -1
- package/dist/commands/info.js +10 -15
- package/dist/commands/info.js.map +1 -1
- package/dist/commands/init.js +452 -451
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/list.js +85 -9
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/new/agent.js +9 -10
- package/dist/commands/new/agent.js.map +1 -1
- package/dist/commands/new/skill.js +12 -16
- package/dist/commands/new/skill.js.map +1 -1
- package/dist/commands/outdated.js +12 -89
- package/dist/commands/outdated.js.map +1 -1
- package/dist/commands/search.js +12 -18
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/uninstall.js +12 -21
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +26 -146
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/validate.js +407 -15
- package/dist/commands/validate.js.map +1 -1
- package/dist/commands/version/bump.js +7 -23
- package/dist/commands/version/bump.js.map +1 -1
- package/dist/commands/version/index.js +6 -21
- package/dist/commands/version/index.js.map +1 -1
- package/dist/commands/version/set.js +6 -23
- package/dist/commands/version/set.js.map +1 -1
- package/dist/commands/version/show.js +6 -21
- package/dist/commands/version/show.js.map +1 -1
- package/dist/components/common/message.js +2 -6
- package/dist/components/common/message.js.map +1 -1
- package/dist/components/common/spinner.js.map +1 -1
- package/dist/components/skill-search/skill-search.js +1 -1
- package/dist/components/wizard/category-grid.js +1 -1
- package/dist/components/wizard/category-grid.test.js +20 -92
- package/dist/components/wizard/category-grid.test.js.map +1 -1
- package/dist/components/wizard/menu-item.js +9 -0
- package/dist/components/wizard/section-progress.js +1 -1
- package/dist/components/wizard/section-progress.test.js +13 -103
- package/dist/components/wizard/section-progress.test.js.map +1 -1
- package/dist/components/wizard/step-approach.js +5 -4
- package/dist/components/wizard/step-build.js +3 -4
- package/dist/components/wizard/step-build.test.js +81 -186
- package/dist/components/wizard/step-build.test.js.map +1 -1
- package/dist/components/wizard/step-confirm.js +1 -2
- package/dist/components/wizard/step-refine.js +1 -2
- package/dist/components/wizard/step-refine.test.js +6 -14
- package/dist/components/wizard/step-refine.test.js.map +1 -1
- package/dist/components/wizard/step-stack.js +5 -3
- package/dist/components/wizard/view-title.js +9 -0
- package/dist/components/wizard/wizard-layout.js +16 -0
- package/dist/components/wizard/wizard-layout.js.map +1 -0
- package/dist/components/wizard/wizard-tabs.js +1 -1
- package/dist/components/wizard/wizard.js +12 -13
- package/dist/config/skills-matrix.yaml +180 -113
- package/dist/config/stacks.yaml +6 -6
- package/dist/hooks/init.js +5 -7
- package/dist/hooks/init.js.map +1 -1
- package/dist/src/agents/developer/web-developer/examples.md +1 -6
- package/dist/src/agents/meta/documentor/workflow.md +1 -5
- package/dist/src/agents/migration/cli-migrator/anti-patterns.md +1 -3
- package/dist/src/agents/tester/web-tester/output-format.md +1 -3
- package/dist/stores/wizard-store.js +2 -2
- package/dist/stores/wizard-store.test.js +60 -23
- package/dist/stores/wizard-store.test.js.map +1 -1
- package/package.json +1 -1
- package/src/agents/developer/web-developer/examples.md +1 -6
- package/src/agents/meta/documentor/workflow.md +1 -5
- package/src/agents/migration/cli-migrator/anti-patterns.md +1 -3
- package/src/agents/tester/web-tester/output-format.md +1 -3
- package/dist/chunk-3U3R4NCG.js.map +0 -1
- package/dist/chunk-4K4ZXQRM.js.map +0 -1
- package/dist/chunk-76DWXGQE.js.map +0 -1
- package/dist/chunk-7Q44DMSP.js.map +0 -1
- package/dist/chunk-ACNBKXXJ.js.map +0 -1
- package/dist/chunk-B7CCVP6Q.js.map +0 -1
- package/dist/chunk-BDLUZVKU.js +0 -54
- package/dist/chunk-BDLUZVKU.js.map +0 -1
- package/dist/chunk-CDX4W4DM.js.map +0 -1
- package/dist/chunk-D237EVNB.js.map +0 -1
- package/dist/chunk-DRXPNNPB.js +0 -393
- package/dist/chunk-DRXPNNPB.js.map +0 -1
- package/dist/chunk-E3FJH4TF.js.map +0 -1
- package/dist/chunk-ED4E6Q2T.js.map +0 -1
- package/dist/chunk-GDH553MV.js.map +0 -1
- package/dist/chunk-HLJX2FTL.js +0 -95
- package/dist/chunk-HLJX2FTL.js.map +0 -1
- package/dist/chunk-I2DSLOXZ.js +0 -75
- package/dist/chunk-I2DSLOXZ.js.map +0 -1
- package/dist/chunk-I4TPKIYX.js +0 -493
- package/dist/chunk-I4TPKIYX.js.map +0 -1
- package/dist/chunk-IBE7JIAG.js +0 -129
- package/dist/chunk-IBE7JIAG.js.map +0 -1
- package/dist/chunk-IMDW5ZUP.js.map +0 -1
- package/dist/chunk-JIPWV2FX.js.map +0 -1
- package/dist/chunk-K3NB6DSG.js.map +0 -1
- package/dist/chunk-K7EVM5LY.js.map +0 -1
- package/dist/chunk-NDY25DTL.js +0 -453
- package/dist/chunk-NDY25DTL.js.map +0 -1
- package/dist/chunk-P26A2K5N.js.map +0 -1
- package/dist/chunk-RFTSZDHV.js.map +0 -1
- package/dist/chunk-SVYPSDWY.js.map +0 -1
- package/dist/chunk-TKFPKEV3.js.map +0 -1
- package/dist/chunk-UQTEPWU7.js.map +0 -1
- package/dist/chunk-V46GGCCI.js.map +0 -1
- package/dist/chunk-X6QONICW.js.map +0 -1
- package/dist/chunk-Y2LW7R3Y.js +0 -23
- package/dist/chunk-Y2LW7R3Y.js.map +0 -1
- package/dist/chunk-Z7G4B5HJ.js.map +0 -1
- package/dist/chunk-ZENYS6KW.js +0 -90
- package/dist/chunk-ZENYS6KW.js.map +0 -1
- package/dist/chunk-ZFPSUQOU.js.map +0 -1
- package/dist/commands/config/set.js +0 -61
- package/dist/commands/config/set.js.map +0 -1
- package/dist/commands/config/unset.js +0 -57
- package/dist/commands/config/unset.js.map +0 -1
- package/dist/commands/test-imports.js +0 -92
- package/dist/commands/test-imports.js.map +0 -1
- package/dist/components/wizard/step-stack-options.js +0 -11
- package/dist/components/wizard/wizard-footer.js +0 -9
- /package/dist/components/wizard/{step-stack-options.js.map → menu-item.js.map} +0 -0
- /package/dist/components/wizard/{wizard-footer.js.map → view-title.js.map} +0 -0
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
printPluginValidationResult,
|
|
4
|
-
validateAllPlugins,
|
|
5
|
-
validatePlugin
|
|
6
|
-
} from "../chunk-NDY25DTL.js";
|
|
7
2
|
import {
|
|
8
3
|
BaseCommand,
|
|
9
4
|
EXIT_CODES
|
|
10
5
|
} from "../chunk-EHS3TWWP.js";
|
|
11
6
|
import {
|
|
7
|
+
directoryExists,
|
|
12
8
|
fileExists,
|
|
9
|
+
listDirectories,
|
|
13
10
|
readFile
|
|
14
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-AL74GBW4.js";
|
|
15
12
|
import {
|
|
16
13
|
PROJECT_ROOT
|
|
17
|
-
} from "../chunk-
|
|
14
|
+
} from "../chunk-FJFEKPXF.js";
|
|
18
15
|
import {
|
|
19
16
|
init_esm_shims
|
|
20
17
|
} from "../chunk-DHET7RCE.js";
|
|
@@ -22,15 +19,19 @@ import {
|
|
|
22
19
|
// src/cli/commands/validate.ts
|
|
23
20
|
init_esm_shims();
|
|
24
21
|
import { Args, Flags } from "@oclif/core";
|
|
25
|
-
import
|
|
22
|
+
import path3 from "path";
|
|
26
23
|
|
|
27
24
|
// src/cli/lib/schema-validator.ts
|
|
28
25
|
init_esm_shims();
|
|
29
26
|
import Ajv from "ajv";
|
|
30
27
|
import addFormats from "ajv-formats";
|
|
31
28
|
import path from "path";
|
|
32
|
-
import { parse as
|
|
29
|
+
import { parse as parseYaml2 } from "yaml";
|
|
33
30
|
import fg from "fast-glob";
|
|
31
|
+
|
|
32
|
+
// src/cli/utils/frontmatter.ts
|
|
33
|
+
init_esm_shims();
|
|
34
|
+
import { parse as parseYaml } from "yaml";
|
|
34
35
|
function extractFrontmatter(content) {
|
|
35
36
|
const frontmatterRegex = /^---\r?\n([\s\S]*?)\r?\n---/;
|
|
36
37
|
const match = content.match(frontmatterRegex);
|
|
@@ -43,6 +44,8 @@ function extractFrontmatter(content) {
|
|
|
43
44
|
return null;
|
|
44
45
|
}
|
|
45
46
|
}
|
|
47
|
+
|
|
48
|
+
// src/cli/lib/schema-validator.ts
|
|
46
49
|
var VALIDATION_TARGETS = [
|
|
47
50
|
{
|
|
48
51
|
name: "Skills Matrix",
|
|
@@ -108,9 +111,7 @@ async function loadSchema(schemaName, rootDir = process.cwd()) {
|
|
|
108
111
|
return schema;
|
|
109
112
|
}
|
|
110
113
|
}
|
|
111
|
-
throw new Error(
|
|
112
|
-
`Schema not found: ${schemaName}. Searched: ${locations.join(", ")}`
|
|
113
|
-
);
|
|
114
|
+
throw new Error(`Schema not found: ${schemaName}. Searched: ${locations.join(", ")}`);
|
|
114
115
|
}
|
|
115
116
|
async function getValidator(schemaName, rootDir = process.cwd()) {
|
|
116
117
|
const cacheKey = `${rootDir}:${schemaName}`;
|
|
@@ -156,7 +157,7 @@ async function validateFile(filePath, validate, extractor) {
|
|
|
156
157
|
};
|
|
157
158
|
}
|
|
158
159
|
} else {
|
|
159
|
-
parsed =
|
|
160
|
+
parsed = parseYaml2(content);
|
|
160
161
|
}
|
|
161
162
|
const isValid = validate(parsed);
|
|
162
163
|
if (isValid) {
|
|
@@ -250,6 +251,397 @@ function printValidationResults(result) {
|
|
|
250
251
|
}
|
|
251
252
|
}
|
|
252
253
|
|
|
254
|
+
// src/cli/lib/plugin-validator.ts
|
|
255
|
+
init_esm_shims();
|
|
256
|
+
import Ajv2 from "ajv";
|
|
257
|
+
import addFormats2 from "ajv-formats";
|
|
258
|
+
import path2 from "path";
|
|
259
|
+
import fg2 from "fast-glob";
|
|
260
|
+
var PLUGIN_DIR = ".claude-plugin";
|
|
261
|
+
var PLUGIN_MANIFEST = "plugin.json";
|
|
262
|
+
var KEBAB_CASE_REGEX = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
263
|
+
var SEMVER_REGEX = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
|
|
264
|
+
var schemaCache2 = /* @__PURE__ */ new Map();
|
|
265
|
+
var validatorCache2 = /* @__PURE__ */ new Map();
|
|
266
|
+
var REMOTE_SCHEMAS = {
|
|
267
|
+
"skill-frontmatter.schema.json": "https://raw.githubusercontent.com/claude-collective/skills/main/src/schemas/skill-frontmatter.schema.json"
|
|
268
|
+
};
|
|
269
|
+
async function loadSchema2(schemaName) {
|
|
270
|
+
if (schemaCache2.has(schemaName)) {
|
|
271
|
+
return schemaCache2.get(schemaName);
|
|
272
|
+
}
|
|
273
|
+
const locations = [
|
|
274
|
+
path2.join(PROJECT_ROOT, "src", "schemas", schemaName),
|
|
275
|
+
path2.join(process.cwd(), "src", "schemas", schemaName)
|
|
276
|
+
];
|
|
277
|
+
for (const schemaPath of locations) {
|
|
278
|
+
if (await fileExists(schemaPath)) {
|
|
279
|
+
const content = await readFile(schemaPath);
|
|
280
|
+
const schema = JSON.parse(content);
|
|
281
|
+
schemaCache2.set(schemaName, schema);
|
|
282
|
+
return schema;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
const remoteUrl = REMOTE_SCHEMAS[schemaName];
|
|
286
|
+
if (remoteUrl) {
|
|
287
|
+
try {
|
|
288
|
+
const response = await fetch(remoteUrl);
|
|
289
|
+
if (response.ok) {
|
|
290
|
+
const schema = await response.json();
|
|
291
|
+
schemaCache2.set(schemaName, schema);
|
|
292
|
+
return schema;
|
|
293
|
+
}
|
|
294
|
+
} catch {
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
throw new Error(
|
|
298
|
+
`Schema not found: ${schemaName}. Searched: ${locations.join(", ")}${remoteUrl ? ` and ${remoteUrl}` : ""}`
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
async function getValidator2(schemaName) {
|
|
302
|
+
if (validatorCache2.has(schemaName)) {
|
|
303
|
+
return validatorCache2.get(schemaName);
|
|
304
|
+
}
|
|
305
|
+
const ajv = new Ajv2({ allErrors: true, strict: false });
|
|
306
|
+
addFormats2(ajv);
|
|
307
|
+
const schema = await loadSchema2(schemaName);
|
|
308
|
+
const validate = ajv.compile(schema);
|
|
309
|
+
validatorCache2.set(schemaName, validate);
|
|
310
|
+
return validate;
|
|
311
|
+
}
|
|
312
|
+
function formatAjvErrors2(errors) {
|
|
313
|
+
if (!errors) return [];
|
|
314
|
+
return errors.map((err) => {
|
|
315
|
+
const errorPath = err.instancePath ? err.instancePath.replace(/^\//, "").replace(/\//g, ".") : "";
|
|
316
|
+
const message = err.message || "Unknown error";
|
|
317
|
+
if (err.keyword === "additionalProperties") {
|
|
318
|
+
const prop = err.params.additionalProperty;
|
|
319
|
+
return `Unrecognized key: "${prop}"`;
|
|
320
|
+
}
|
|
321
|
+
if (err.keyword === "enum") {
|
|
322
|
+
const allowed = err.params.allowedValues;
|
|
323
|
+
return errorPath ? `${errorPath}: ${message}. Allowed: ${allowed?.join(", ")}` : `${message}. Allowed: ${allowed?.join(", ")}`;
|
|
324
|
+
}
|
|
325
|
+
if (err.keyword === "pattern") {
|
|
326
|
+
let hint = "";
|
|
327
|
+
if (errorPath === "name") {
|
|
328
|
+
hint = " (must be kebab-case)";
|
|
329
|
+
} else if (errorPath === "version") {
|
|
330
|
+
hint = " (must be semver: x.y.z)";
|
|
331
|
+
}
|
|
332
|
+
return errorPath ? `${errorPath}: ${message}${hint}` : `${message}${hint}`;
|
|
333
|
+
}
|
|
334
|
+
return errorPath ? `${errorPath}: ${message}` : message;
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
function isKebabCase(str) {
|
|
338
|
+
return KEBAB_CASE_REGEX.test(str);
|
|
339
|
+
}
|
|
340
|
+
function isValidSemver(str) {
|
|
341
|
+
return SEMVER_REGEX.test(str);
|
|
342
|
+
}
|
|
343
|
+
async function validatePluginStructure(pluginPath) {
|
|
344
|
+
const errors = [];
|
|
345
|
+
const warnings = [];
|
|
346
|
+
if (!await directoryExists(pluginPath)) {
|
|
347
|
+
return {
|
|
348
|
+
valid: false,
|
|
349
|
+
errors: [`Plugin directory does not exist: ${pluginPath}`],
|
|
350
|
+
warnings: []
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
const pluginDir = path2.join(pluginPath, PLUGIN_DIR);
|
|
354
|
+
if (!await directoryExists(pluginDir)) {
|
|
355
|
+
errors.push(`Missing ${PLUGIN_DIR}/ directory`);
|
|
356
|
+
}
|
|
357
|
+
const manifestPath = path2.join(pluginDir, PLUGIN_MANIFEST);
|
|
358
|
+
if (!await fileExists(manifestPath)) {
|
|
359
|
+
errors.push(`Missing ${PLUGIN_DIR}/${PLUGIN_MANIFEST}`);
|
|
360
|
+
}
|
|
361
|
+
const readmePath = path2.join(pluginPath, "README.md");
|
|
362
|
+
if (!await fileExists(readmePath)) {
|
|
363
|
+
warnings.push("Missing README.md (recommended for documentation)");
|
|
364
|
+
}
|
|
365
|
+
return {
|
|
366
|
+
valid: errors.length === 0,
|
|
367
|
+
errors,
|
|
368
|
+
warnings
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
async function validatePluginManifest(manifestPath) {
|
|
372
|
+
const errors = [];
|
|
373
|
+
const warnings = [];
|
|
374
|
+
if (!await fileExists(manifestPath)) {
|
|
375
|
+
return {
|
|
376
|
+
valid: false,
|
|
377
|
+
errors: [`Manifest file not found: ${manifestPath}`],
|
|
378
|
+
warnings: []
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
let manifest;
|
|
382
|
+
try {
|
|
383
|
+
const content = await readFile(manifestPath);
|
|
384
|
+
manifest = JSON.parse(content);
|
|
385
|
+
} catch (err) {
|
|
386
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
387
|
+
return {
|
|
388
|
+
valid: false,
|
|
389
|
+
errors: [`Invalid JSON in ${PLUGIN_MANIFEST}: ${message}`],
|
|
390
|
+
warnings: []
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
const validate = await getValidator2("plugin.schema.json");
|
|
394
|
+
const isValid = validate(manifest);
|
|
395
|
+
if (!isValid) {
|
|
396
|
+
errors.push(...formatAjvErrors2(validate.errors));
|
|
397
|
+
}
|
|
398
|
+
if (manifest.name && typeof manifest.name === "string") {
|
|
399
|
+
if (!isKebabCase(manifest.name)) {
|
|
400
|
+
errors.push(`name must be kebab-case: "${manifest.name}"`);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
if (manifest.version && typeof manifest.version === "string") {
|
|
404
|
+
if (!isValidSemver(manifest.version)) {
|
|
405
|
+
warnings.push(
|
|
406
|
+
`version "${manifest.version}" is not valid semver (expected: major.minor.patch)`
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
if (!manifest.description) {
|
|
411
|
+
warnings.push("Missing description field (recommended for discoverability)");
|
|
412
|
+
}
|
|
413
|
+
const pluginDir = path2.dirname(path2.dirname(manifestPath));
|
|
414
|
+
if (manifest.skills && typeof manifest.skills === "string") {
|
|
415
|
+
const skillsPath = path2.join(pluginDir, manifest.skills);
|
|
416
|
+
if (!await directoryExists(skillsPath)) {
|
|
417
|
+
errors.push(`Skills path does not exist: ${manifest.skills}`);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
if (manifest.agents && typeof manifest.agents === "string") {
|
|
421
|
+
const agentsPath = path2.join(pluginDir, manifest.agents);
|
|
422
|
+
if (!await directoryExists(agentsPath)) {
|
|
423
|
+
errors.push(`Agents path does not exist: ${manifest.agents}`);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
return {
|
|
427
|
+
valid: errors.length === 0,
|
|
428
|
+
errors,
|
|
429
|
+
warnings
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
async function validateSkillFrontmatter(skillPath) {
|
|
433
|
+
const errors = [];
|
|
434
|
+
const warnings = [];
|
|
435
|
+
if (!await fileExists(skillPath)) {
|
|
436
|
+
return {
|
|
437
|
+
valid: false,
|
|
438
|
+
errors: [`Skill file not found: ${skillPath}`],
|
|
439
|
+
warnings: []
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
const content = await readFile(skillPath);
|
|
443
|
+
const frontmatter = extractFrontmatter(content);
|
|
444
|
+
if (frontmatter === null) {
|
|
445
|
+
return {
|
|
446
|
+
valid: false,
|
|
447
|
+
errors: ["Missing or invalid YAML frontmatter"],
|
|
448
|
+
warnings: []
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
const validate = await getValidator2("skill-frontmatter.schema.json");
|
|
452
|
+
const isValid = validate(frontmatter);
|
|
453
|
+
if (!isValid) {
|
|
454
|
+
errors.push(...formatAjvErrors2(validate.errors));
|
|
455
|
+
}
|
|
456
|
+
return {
|
|
457
|
+
valid: errors.length === 0,
|
|
458
|
+
errors,
|
|
459
|
+
warnings
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
async function validateAgentFrontmatter(agentPath) {
|
|
463
|
+
const errors = [];
|
|
464
|
+
const warnings = [];
|
|
465
|
+
if (!await fileExists(agentPath)) {
|
|
466
|
+
return {
|
|
467
|
+
valid: false,
|
|
468
|
+
errors: [`Agent file not found: ${agentPath}`],
|
|
469
|
+
warnings: []
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
const content = await readFile(agentPath);
|
|
473
|
+
const frontmatter = extractFrontmatter(content);
|
|
474
|
+
if (frontmatter === null) {
|
|
475
|
+
return {
|
|
476
|
+
valid: false,
|
|
477
|
+
errors: ["Missing or invalid YAML frontmatter"],
|
|
478
|
+
warnings: []
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
const validate = await getValidator2("agent-frontmatter.schema.json");
|
|
482
|
+
const isValid = validate(frontmatter);
|
|
483
|
+
if (!isValid) {
|
|
484
|
+
errors.push(...formatAjvErrors2(validate.errors));
|
|
485
|
+
}
|
|
486
|
+
const fm = frontmatter;
|
|
487
|
+
if (fm.name && typeof fm.name === "string") {
|
|
488
|
+
if (!isKebabCase(fm.name)) {
|
|
489
|
+
errors.push(`name must be kebab-case: "${fm.name}"`);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
return {
|
|
493
|
+
valid: errors.length === 0,
|
|
494
|
+
errors,
|
|
495
|
+
warnings
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
async function validatePlugin(pluginPath) {
|
|
499
|
+
const errors = [];
|
|
500
|
+
const warnings = [];
|
|
501
|
+
const structureResult = await validatePluginStructure(pluginPath);
|
|
502
|
+
errors.push(...structureResult.errors);
|
|
503
|
+
warnings.push(...structureResult.warnings);
|
|
504
|
+
if (!structureResult.valid) {
|
|
505
|
+
return { valid: false, errors, warnings };
|
|
506
|
+
}
|
|
507
|
+
const manifestPath = path2.join(pluginPath, PLUGIN_DIR, PLUGIN_MANIFEST);
|
|
508
|
+
const manifestResult = await validatePluginManifest(manifestPath);
|
|
509
|
+
errors.push(...manifestResult.errors);
|
|
510
|
+
warnings.push(...manifestResult.warnings);
|
|
511
|
+
let manifest = null;
|
|
512
|
+
try {
|
|
513
|
+
const content = await readFile(manifestPath);
|
|
514
|
+
manifest = JSON.parse(content);
|
|
515
|
+
} catch {
|
|
516
|
+
}
|
|
517
|
+
if (manifest) {
|
|
518
|
+
if (manifest.skills && typeof manifest.skills === "string") {
|
|
519
|
+
const skillsDir = path2.join(pluginPath, manifest.skills);
|
|
520
|
+
if (await directoryExists(skillsDir)) {
|
|
521
|
+
const skillFiles = await fg2("**/SKILL.md", {
|
|
522
|
+
cwd: skillsDir,
|
|
523
|
+
absolute: true
|
|
524
|
+
});
|
|
525
|
+
if (skillFiles.length === 0) {
|
|
526
|
+
warnings.push(
|
|
527
|
+
`Skills directory exists but contains no SKILL.md files: ${manifest.skills}`
|
|
528
|
+
);
|
|
529
|
+
}
|
|
530
|
+
for (const skillFile of skillFiles) {
|
|
531
|
+
const relativePath = path2.relative(pluginPath, skillFile);
|
|
532
|
+
const skillResult = await validateSkillFrontmatter(skillFile);
|
|
533
|
+
if (!skillResult.valid) {
|
|
534
|
+
errors.push(...skillResult.errors.map((e) => `${relativePath}: ${e}`));
|
|
535
|
+
}
|
|
536
|
+
warnings.push(...skillResult.warnings.map((w) => `${relativePath}: ${w}`));
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
if (manifest.agents && typeof manifest.agents === "string") {
|
|
541
|
+
const agentsDir = path2.join(pluginPath, manifest.agents);
|
|
542
|
+
if (await directoryExists(agentsDir)) {
|
|
543
|
+
const agentFiles = await fg2("*.md", {
|
|
544
|
+
cwd: agentsDir,
|
|
545
|
+
absolute: true
|
|
546
|
+
});
|
|
547
|
+
if (agentFiles.length === 0) {
|
|
548
|
+
warnings.push(`Agents directory exists but contains no .md files: ${manifest.agents}`);
|
|
549
|
+
}
|
|
550
|
+
for (const agentFile of agentFiles) {
|
|
551
|
+
const relativePath = path2.relative(pluginPath, agentFile);
|
|
552
|
+
const agentResult = await validateAgentFrontmatter(agentFile);
|
|
553
|
+
if (!agentResult.valid) {
|
|
554
|
+
errors.push(...agentResult.errors.map((e) => `${relativePath}: ${e}`));
|
|
555
|
+
}
|
|
556
|
+
warnings.push(...agentResult.warnings.map((w) => `${relativePath}: ${w}`));
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
return {
|
|
562
|
+
valid: errors.length === 0,
|
|
563
|
+
errors,
|
|
564
|
+
warnings
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
async function validateAllPlugins(pluginsDir) {
|
|
568
|
+
const results = [];
|
|
569
|
+
if (!await directoryExists(pluginsDir)) {
|
|
570
|
+
return {
|
|
571
|
+
valid: false,
|
|
572
|
+
results: [
|
|
573
|
+
{
|
|
574
|
+
name: pluginsDir,
|
|
575
|
+
result: {
|
|
576
|
+
valid: false,
|
|
577
|
+
errors: [`Directory does not exist: ${pluginsDir}`],
|
|
578
|
+
warnings: []
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
],
|
|
582
|
+
summary: { total: 0, valid: 0, invalid: 1, withWarnings: 0 }
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
const allDirs = await listDirectories(pluginsDir);
|
|
586
|
+
const pluginDirs = [];
|
|
587
|
+
for (const dirName of allDirs) {
|
|
588
|
+
const potentialPluginDir = path2.join(pluginsDir, dirName, PLUGIN_DIR);
|
|
589
|
+
if (await directoryExists(potentialPluginDir)) {
|
|
590
|
+
pluginDirs.push(dirName);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
if (pluginDirs.length === 0) {
|
|
594
|
+
return {
|
|
595
|
+
valid: false,
|
|
596
|
+
results: [
|
|
597
|
+
{
|
|
598
|
+
name: pluginsDir,
|
|
599
|
+
result: {
|
|
600
|
+
valid: false,
|
|
601
|
+
errors: [
|
|
602
|
+
`No plugins found in directory: ${pluginsDir}. Plugins must contain a ${PLUGIN_DIR}/ directory.`
|
|
603
|
+
],
|
|
604
|
+
warnings: []
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
],
|
|
608
|
+
summary: { total: 0, valid: 0, invalid: 1, withWarnings: 0 }
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
for (const pluginName of pluginDirs) {
|
|
612
|
+
const pluginPath = path2.join(pluginsDir, pluginName);
|
|
613
|
+
const result = await validatePlugin(pluginPath);
|
|
614
|
+
results.push({ name: pluginName, result });
|
|
615
|
+
}
|
|
616
|
+
const summary = {
|
|
617
|
+
total: results.length,
|
|
618
|
+
valid: results.filter((r) => r.result.valid).length,
|
|
619
|
+
invalid: results.filter((r) => !r.result.valid).length,
|
|
620
|
+
withWarnings: results.filter((r) => r.result.warnings.length > 0).length
|
|
621
|
+
};
|
|
622
|
+
return {
|
|
623
|
+
valid: summary.invalid === 0,
|
|
624
|
+
results,
|
|
625
|
+
summary
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
function printPluginValidationResult(name, result, verbose = false) {
|
|
629
|
+
const status = result.valid ? "\u2713" : "\u2717";
|
|
630
|
+
if (result.valid && result.warnings.length === 0 && !verbose) {
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
console.log(`
|
|
634
|
+
${status} ${name}`);
|
|
635
|
+
if (result.errors.length > 0) {
|
|
636
|
+
console.log(" Errors:");
|
|
637
|
+
result.errors.forEach((e) => console.log(` - ${e}`));
|
|
638
|
+
}
|
|
639
|
+
if (result.warnings.length > 0) {
|
|
640
|
+
console.log(" Warnings:");
|
|
641
|
+
result.warnings.forEach((w) => console.log(` - ${w}`));
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
253
645
|
// src/cli/commands/validate.ts
|
|
254
646
|
var Validate = class _Validate extends BaseCommand {
|
|
255
647
|
static summary = "Validate YAML files against schemas or validate compiled plugins";
|
|
@@ -304,7 +696,7 @@ var Validate = class _Validate extends BaseCommand {
|
|
|
304
696
|
}
|
|
305
697
|
}
|
|
306
698
|
async validatePlugins(pluginPath, verbose, all) {
|
|
307
|
-
const targetPath = pluginPath ?
|
|
699
|
+
const targetPath = pluginPath ? path3.resolve(pluginPath) : process.cwd();
|
|
308
700
|
if (all) {
|
|
309
701
|
await this.validateAllPluginsInDirectory(targetPath, verbose);
|
|
310
702
|
} else {
|
|
@@ -350,7 +742,7 @@ var Validate = class _Validate extends BaseCommand {
|
|
|
350
742
|
const result = await validatePlugin(targetPath);
|
|
351
743
|
const summary = result.valid ? "Done: Plugin is valid" : "Done: Plugin has errors";
|
|
352
744
|
this.log(summary);
|
|
353
|
-
printPluginValidationResult(
|
|
745
|
+
printPluginValidationResult(path3.basename(targetPath), result, true);
|
|
354
746
|
if (result.valid && result.warnings.length === 0) {
|
|
355
747
|
this.log("");
|
|
356
748
|
this.logSuccess("Plugin validated successfully");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/commands/validate.ts","../../src/cli/lib/schema-validator.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { BaseCommand } from \"../base-command.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport {\n validateAllSchemas,\n printValidationResults,\n} from \"../lib/schema-validator.js\";\nimport {\n validatePlugin,\n validateAllPlugins,\n printPluginValidationResult,\n} from \"../lib/plugin-validator.js\";\n\nexport default class Validate extends BaseCommand {\n static summary =\n \"Validate YAML files against schemas or validate compiled plugins\";\n static description =\n \"Validates skill/agent YAML files against JSON schemas, or validates compiled plugin structure and content. \" +\n \"Without arguments, validates all YAML files in the current directory against their schemas. \" +\n \"With a path argument or --plugins flag, validates plugin(s) instead.\";\n\n static args = {\n path: Args.string({\n description: \"Path to plugin or plugins directory to validate\",\n required: false,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n verbose: Flags.boolean({\n char: \"v\",\n description: \"Enable verbose logging\",\n default: false,\n }),\n all: Flags.boolean({\n char: \"a\",\n description: \"Validate all plugins in directory\",\n default: false,\n }),\n plugins: Flags.boolean({\n char: \"p\",\n description: \"Validate plugins instead of schemas\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Validate);\n\n if (args.path || flags.plugins) {\n await this.validatePlugins(args.path, flags.verbose, flags.all);\n } else {\n await this.validateSchemas();\n }\n }\n\n private async validateSchemas(): Promise<void> {\n this.log(\"\");\n this.log(\"Validating all schemas\");\n this.log(\"\");\n\n try {\n const result = await validateAllSchemas();\n\n const summary = result.valid\n ? `Done: ${result.summary.validFiles}/${result.summary.totalFiles} files valid`\n : `Done: ${result.summary.invalidFiles} invalid files`;\n\n this.log(summary);\n printValidationResults(result);\n\n if (!result.valid) {\n this.exit(EXIT_CODES.ERROR);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this.error(`Validation failed: ${message}`, { exit: EXIT_CODES.ERROR });\n }\n }\n\n private async validatePlugins(\n pluginPath: string | undefined,\n verbose: boolean,\n all: boolean,\n ): Promise<void> {\n const targetPath = pluginPath ? path.resolve(pluginPath) : process.cwd();\n\n if (all) {\n await this.validateAllPluginsInDirectory(targetPath, verbose);\n } else {\n await this.validateSinglePlugin(targetPath, verbose);\n }\n }\n\n private async validateAllPluginsInDirectory(\n targetPath: string,\n verbose: boolean,\n ): Promise<void> {\n this.log(\"\");\n this.log(`Validating all plugins in: ${targetPath}`);\n this.log(\"\");\n\n try {\n const result = await validateAllPlugins(targetPath);\n\n const summary = result.valid\n ? `Done: ${result.summary.valid}/${result.summary.total} plugins valid`\n : `Done: ${result.summary.invalid} invalid plugins`;\n\n this.log(summary);\n\n this.log(\"\");\n this.log(\" Plugin Validation Summary:\");\n this.log(\" -------------------------\");\n this.log(` Total plugins: ${result.summary.total}`);\n this.log(` Valid: ${result.summary.valid}`);\n this.log(` Invalid: ${result.summary.invalid}`);\n this.log(` With warnings: ${result.summary.withWarnings}`);\n\n for (const { name, result: pluginResult } of result.results) {\n printPluginValidationResult(name, pluginResult, verbose);\n }\n\n if (result.valid) {\n this.log(\"\");\n this.logSuccess(\"All plugins validated successfully\");\n this.log(\"\");\n } else {\n this.log(\"\");\n this.error(\"Validation failed\", { exit: EXIT_CODES.ERROR });\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this.error(`Validation failed: ${message}`, { exit: EXIT_CODES.ERROR });\n }\n }\n\n private async validateSinglePlugin(\n targetPath: string,\n verbose: boolean,\n ): Promise<void> {\n this.log(\"\");\n this.log(`Validating plugin: ${targetPath}`);\n this.log(\"\");\n\n try {\n const result = await validatePlugin(targetPath);\n\n const summary = result.valid\n ? \"Done: Plugin is valid\"\n : \"Done: Plugin has errors\";\n\n this.log(summary);\n\n printPluginValidationResult(path.basename(targetPath), result, true);\n\n if (result.valid && result.warnings.length === 0) {\n this.log(\"\");\n this.logSuccess(\"Plugin validated successfully\");\n this.log(\"\");\n } else if (result.valid) {\n this.log(\"\");\n this.logWarning(\"Plugin valid with warnings\");\n this.log(\"\");\n } else {\n this.log(\"\");\n this.error(\"Validation failed\", { exit: EXIT_CODES.ERROR });\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this.error(`Validation failed: ${message}`, { exit: EXIT_CODES.ERROR });\n }\n }\n}\n","import Ajv, { type ValidateFunction, type ErrorObject } from \"ajv\";\nimport addFormats from \"ajv-formats\";\nimport path from \"path\";\nimport { readFile, fileExists } from \"../utils/fs\";\nimport { parse as parseYaml } from \"yaml\";\nimport fg from \"fast-glob\";\nimport { PROJECT_ROOT } from \"../consts\";\n\nexport interface FileValidationError {\n file: string;\n errors: string[];\n}\n\nexport interface SchemaValidationResult {\n schemaName: string;\n valid: boolean;\n totalFiles: number;\n validFiles: number;\n invalidFiles: FileValidationError[];\n}\n\nexport interface FullValidationResult {\n valid: boolean;\n results: SchemaValidationResult[];\n summary: {\n totalSchemas: number;\n totalFiles: number;\n validFiles: number;\n invalidFiles: number;\n };\n}\n\ntype ContentExtractor = (content: string) => unknown | null;\n\ninterface ValidationTarget {\n name: string;\n schema: string;\n pattern: string;\n baseDir: string;\n extractor?: ContentExtractor;\n}\n\nfunction extractFrontmatter(content: string): unknown | null {\n const frontmatterRegex = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---/;\n const match = content.match(frontmatterRegex);\n\n if (!match || !match[1]) {\n return null;\n }\n\n try {\n return parseYaml(match[1]);\n } catch {\n return null;\n }\n}\n\nconst VALIDATION_TARGETS: ValidationTarget[] = [\n {\n name: \"Skills Matrix\",\n schema: \"skills-matrix.schema.json\",\n pattern: \"skills-matrix.yaml\",\n baseDir: \"src/config\",\n },\n {\n name: \"Skill Metadata\",\n schema: \"metadata.schema.json\",\n pattern: \"**/metadata.yaml\",\n baseDir: \"src/skills\",\n },\n {\n name: \"Stack Skill Metadata\",\n schema: \"metadata.schema.json\",\n pattern: \"**/skills/**/metadata.yaml\",\n baseDir: \"src/stacks\",\n },\n {\n name: \"Stack Config\",\n schema: \"stack.schema.json\",\n pattern: \"*/config.yaml\",\n baseDir: \"src/stacks\",\n },\n {\n name: \"Agent Definition\",\n schema: \"agent.schema.json\",\n pattern: \"**/agent.yaml\",\n baseDir: \"src/agents\",\n },\n {\n name: \"Skill Frontmatter\",\n schema: \"skill-frontmatter.schema.json\",\n pattern: \"**/SKILL.md\",\n baseDir: \"src/skills\",\n extractor: extractFrontmatter,\n },\n {\n name: \"Stack Skill Frontmatter\",\n schema: \"skill-frontmatter.schema.json\",\n pattern: \"**/skills/**/SKILL.md\",\n baseDir: \"src/stacks\",\n extractor: extractFrontmatter,\n },\n];\n\nconst schemaCache = new Map<string, object>();\nconst validatorCache = new Map<string, ValidateFunction>();\n\nasync function loadSchema(\n schemaName: string,\n rootDir: string = process.cwd(),\n): Promise<object> {\n const cacheKey = `${rootDir}:${schemaName}`;\n if (schemaCache.has(cacheKey)) {\n return schemaCache.get(cacheKey)!;\n }\n\n // Try multiple locations for schema files:\n // 1. CLI repo's schemas (for agent schemas)\n // 2. Target directory's schemas (for stack/skill schemas in claude-subagents)\n const locations = [\n path.join(PROJECT_ROOT, \"src\", \"schemas\", schemaName),\n path.join(rootDir, \"src\", \"schemas\", schemaName),\n ];\n\n for (const schemaPath of locations) {\n if (await fileExists(schemaPath)) {\n const content = await readFile(schemaPath);\n const schema = JSON.parse(content);\n schemaCache.set(cacheKey, schema);\n return schema;\n }\n }\n\n throw new Error(\n `Schema not found: ${schemaName}. Searched: ${locations.join(\", \")}`,\n );\n}\n\nasync function getValidator(\n schemaName: string,\n rootDir: string = process.cwd(),\n): Promise<ValidateFunction> {\n const cacheKey = `${rootDir}:${schemaName}`;\n if (validatorCache.has(cacheKey)) {\n return validatorCache.get(cacheKey)!;\n }\n\n const ajv = new Ajv({ allErrors: true, strict: false });\n addFormats(ajv);\n const schema = await loadSchema(schemaName, rootDir);\n const validate = ajv.compile(schema);\n validatorCache.set(cacheKey, validate);\n return validate;\n}\n\nfunction formatAjvErrors(errors: ErrorObject[] | null | undefined): string[] {\n if (!errors) return [];\n\n return errors.map((err) => {\n const errorPath = err.instancePath\n ? err.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\")\n : \"\";\n const message = err.message || \"Unknown error\";\n\n if (err.keyword === \"additionalProperties\") {\n const prop = (err.params as { additionalProperty?: string })\n .additionalProperty;\n return `Unrecognized key: \"${prop}\"`;\n }\n\n if (err.keyword === \"enum\") {\n const allowed = (err.params as { allowedValues?: string[] })\n .allowedValues;\n return errorPath\n ? `${errorPath}: ${message}. Allowed: ${allowed?.join(\", \")}`\n : `${message}. Allowed: ${allowed?.join(\", \")}`;\n }\n\n return errorPath ? `${errorPath}: ${message}` : message;\n });\n}\n\nasync function validateFile(\n filePath: string,\n validate: ValidateFunction,\n extractor?: ContentExtractor,\n): Promise<{ valid: boolean; errors: string[] }> {\n try {\n if (!(await fileExists(filePath))) {\n return { valid: false, errors: [`File not found: ${filePath}`] };\n }\n\n const content = await readFile(filePath);\n\n let parsed: unknown;\n if (extractor) {\n parsed = extractor(content);\n if (parsed === null) {\n return {\n valid: false,\n errors: [\"Failed to extract content (no valid frontmatter found)\"],\n };\n }\n } else {\n parsed = parseYaml(content);\n }\n\n const isValid = validate(parsed);\n\n if (isValid) {\n return { valid: true, errors: [] };\n }\n\n return { valid: false, errors: formatAjvErrors(validate.errors) };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return { valid: false, errors: [`Failed to parse content: ${message}`] };\n }\n}\n\nasync function validateTarget(\n target: ValidationTarget,\n rootDir: string = process.cwd(),\n): Promise<SchemaValidationResult> {\n const baseDir = path.join(rootDir, target.baseDir);\n const pattern = path.join(baseDir, target.pattern);\n const files = await fg(pattern, { absolute: true });\n\n const result: SchemaValidationResult = {\n schemaName: target.name,\n valid: true,\n totalFiles: files.length,\n validFiles: 0,\n invalidFiles: [],\n };\n\n if (files.length === 0) {\n return result;\n }\n\n const validate = await getValidator(target.schema, rootDir);\n\n for (const file of files) {\n const validation = await validateFile(file, validate, target.extractor);\n const relativePath = path.relative(rootDir, file);\n\n if (validation.valid) {\n result.validFiles++;\n } else {\n result.valid = false;\n result.invalidFiles.push({\n file: relativePath,\n errors: validation.errors,\n });\n }\n }\n\n return result;\n}\n\nexport async function validateAllSchemas(\n rootDir: string = process.cwd(),\n): Promise<FullValidationResult> {\n const results: SchemaValidationResult[] = [];\n\n for (const target of VALIDATION_TARGETS) {\n const result = await validateTarget(target, rootDir);\n results.push(result);\n }\n\n const summary = {\n totalSchemas: results.length,\n totalFiles: results.reduce((sum, r) => sum + r.totalFiles, 0),\n validFiles: results.reduce((sum, r) => sum + r.validFiles, 0),\n invalidFiles: results.reduce((sum, r) => sum + r.invalidFiles.length, 0),\n };\n\n return {\n valid: results.every((r) => r.valid),\n results,\n summary,\n };\n}\n\nexport function printValidationResults(result: FullValidationResult): void {\n console.log(`\\n Schema Validation Summary:`);\n console.log(` ─────────────────────────`);\n console.log(` Total schemas checked: ${result.summary.totalSchemas}`);\n console.log(` Total files: ${result.summary.totalFiles}`);\n console.log(` Valid: ${result.summary.validFiles}`);\n console.log(` Invalid: ${result.summary.invalidFiles}`);\n\n for (const schemaResult of result.results) {\n if (schemaResult.totalFiles === 0) continue;\n\n const status = schemaResult.valid ? \"✓\" : \"✗\";\n console.log(\n `\\n ${status} ${schemaResult.schemaName}: ${schemaResult.validFiles}/${schemaResult.totalFiles} valid`,\n );\n\n if (schemaResult.invalidFiles.length > 0) {\n for (const file of schemaResult.invalidFiles) {\n console.log(`\\n ${file.file}:`);\n file.errors.forEach((e) => console.log(` - ${e}`));\n }\n }\n }\n\n if (result.valid) {\n console.log(`\\n ✓ All schemas validated successfully\\n`);\n } else {\n console.log(`\\n ✗ Validation failed\\n`);\n }\n}\n"],"mappings":"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","names":["path","path"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/validate.ts","../../src/cli/lib/schema-validator.ts","../../src/cli/utils/frontmatter.ts","../../src/cli/lib/plugin-validator.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { BaseCommand } from \"../base-command.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { validateAllSchemas, printValidationResults } from \"../lib/schema-validator.js\";\nimport {\n validatePlugin,\n validateAllPlugins,\n printPluginValidationResult,\n} from \"../lib/plugin-validator.js\";\n\nexport default class Validate extends BaseCommand {\n static summary = \"Validate YAML files against schemas or validate compiled plugins\";\n static description =\n \"Validates skill/agent YAML files against JSON schemas, or validates compiled plugin structure and content. \" +\n \"Without arguments, validates all YAML files in the current directory against their schemas. \" +\n \"With a path argument or --plugins flag, validates plugin(s) instead.\";\n\n static args = {\n path: Args.string({\n description: \"Path to plugin or plugins directory to validate\",\n required: false,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n verbose: Flags.boolean({\n char: \"v\",\n description: \"Enable verbose logging\",\n default: false,\n }),\n all: Flags.boolean({\n char: \"a\",\n description: \"Validate all plugins in directory\",\n default: false,\n }),\n plugins: Flags.boolean({\n char: \"p\",\n description: \"Validate plugins instead of schemas\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Validate);\n\n if (args.path || flags.plugins) {\n await this.validatePlugins(args.path, flags.verbose, flags.all);\n } else {\n await this.validateSchemas();\n }\n }\n\n private async validateSchemas(): Promise<void> {\n this.log(\"\");\n this.log(\"Validating all schemas\");\n this.log(\"\");\n\n try {\n const result = await validateAllSchemas();\n\n const summary = result.valid\n ? `Done: ${result.summary.validFiles}/${result.summary.totalFiles} files valid`\n : `Done: ${result.summary.invalidFiles} invalid files`;\n\n this.log(summary);\n printValidationResults(result);\n\n if (!result.valid) {\n this.exit(EXIT_CODES.ERROR);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this.error(`Validation failed: ${message}`, { exit: EXIT_CODES.ERROR });\n }\n }\n\n private async validatePlugins(\n pluginPath: string | undefined,\n verbose: boolean,\n all: boolean,\n ): Promise<void> {\n const targetPath = pluginPath ? path.resolve(pluginPath) : process.cwd();\n\n if (all) {\n await this.validateAllPluginsInDirectory(targetPath, verbose);\n } else {\n await this.validateSinglePlugin(targetPath, verbose);\n }\n }\n\n private async validateAllPluginsInDirectory(targetPath: string, verbose: boolean): Promise<void> {\n this.log(\"\");\n this.log(`Validating all plugins in: ${targetPath}`);\n this.log(\"\");\n\n try {\n const result = await validateAllPlugins(targetPath);\n\n const summary = result.valid\n ? `Done: ${result.summary.valid}/${result.summary.total} plugins valid`\n : `Done: ${result.summary.invalid} invalid plugins`;\n\n this.log(summary);\n\n this.log(\"\");\n this.log(\" Plugin Validation Summary:\");\n this.log(\" -------------------------\");\n this.log(` Total plugins: ${result.summary.total}`);\n this.log(` Valid: ${result.summary.valid}`);\n this.log(` Invalid: ${result.summary.invalid}`);\n this.log(` With warnings: ${result.summary.withWarnings}`);\n\n for (const { name, result: pluginResult } of result.results) {\n printPluginValidationResult(name, pluginResult, verbose);\n }\n\n if (result.valid) {\n this.log(\"\");\n this.logSuccess(\"All plugins validated successfully\");\n this.log(\"\");\n } else {\n this.log(\"\");\n this.error(\"Validation failed\", { exit: EXIT_CODES.ERROR });\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this.error(`Validation failed: ${message}`, { exit: EXIT_CODES.ERROR });\n }\n }\n\n private async validateSinglePlugin(targetPath: string, verbose: boolean): Promise<void> {\n this.log(\"\");\n this.log(`Validating plugin: ${targetPath}`);\n this.log(\"\");\n\n try {\n const result = await validatePlugin(targetPath);\n\n const summary = result.valid ? \"Done: Plugin is valid\" : \"Done: Plugin has errors\";\n\n this.log(summary);\n\n printPluginValidationResult(path.basename(targetPath), result, true);\n\n if (result.valid && result.warnings.length === 0) {\n this.log(\"\");\n this.logSuccess(\"Plugin validated successfully\");\n this.log(\"\");\n } else if (result.valid) {\n this.log(\"\");\n this.logWarning(\"Plugin valid with warnings\");\n this.log(\"\");\n } else {\n this.log(\"\");\n this.error(\"Validation failed\", { exit: EXIT_CODES.ERROR });\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this.error(`Validation failed: ${message}`, { exit: EXIT_CODES.ERROR });\n }\n }\n}\n","import Ajv, { type ValidateFunction, type ErrorObject } from \"ajv\";\nimport addFormats from \"ajv-formats\";\nimport path from \"path\";\nimport { readFile, fileExists } from \"../utils/fs\";\nimport { parse as parseYaml } from \"yaml\";\nimport fg from \"fast-glob\";\nimport { PROJECT_ROOT } from \"../consts\";\nimport { extractFrontmatter } from \"../utils/frontmatter\";\n\nexport interface FileValidationError {\n file: string;\n errors: string[];\n}\n\nexport interface SchemaValidationResult {\n schemaName: string;\n valid: boolean;\n totalFiles: number;\n validFiles: number;\n invalidFiles: FileValidationError[];\n}\n\nexport interface FullValidationResult {\n valid: boolean;\n results: SchemaValidationResult[];\n summary: {\n totalSchemas: number;\n totalFiles: number;\n validFiles: number;\n invalidFiles: number;\n };\n}\n\ntype ContentExtractor = (content: string) => unknown | null;\n\ninterface ValidationTarget {\n name: string;\n schema: string;\n pattern: string;\n baseDir: string;\n extractor?: ContentExtractor;\n}\n\nconst VALIDATION_TARGETS: ValidationTarget[] = [\n {\n name: \"Skills Matrix\",\n schema: \"skills-matrix.schema.json\",\n pattern: \"skills-matrix.yaml\",\n baseDir: \"src/config\",\n },\n {\n name: \"Skill Metadata\",\n schema: \"metadata.schema.json\",\n pattern: \"**/metadata.yaml\",\n baseDir: \"src/skills\",\n },\n {\n name: \"Stack Skill Metadata\",\n schema: \"metadata.schema.json\",\n pattern: \"**/skills/**/metadata.yaml\",\n baseDir: \"src/stacks\",\n },\n {\n name: \"Stack Config\",\n schema: \"stack.schema.json\",\n pattern: \"*/config.yaml\",\n baseDir: \"src/stacks\",\n },\n {\n name: \"Agent Definition\",\n schema: \"agent.schema.json\",\n pattern: \"**/agent.yaml\",\n baseDir: \"src/agents\",\n },\n {\n name: \"Skill Frontmatter\",\n schema: \"skill-frontmatter.schema.json\",\n pattern: \"**/SKILL.md\",\n baseDir: \"src/skills\",\n extractor: extractFrontmatter,\n },\n {\n name: \"Stack Skill Frontmatter\",\n schema: \"skill-frontmatter.schema.json\",\n pattern: \"**/skills/**/SKILL.md\",\n baseDir: \"src/stacks\",\n extractor: extractFrontmatter,\n },\n];\n\nconst schemaCache = new Map<string, object>();\nconst validatorCache = new Map<string, ValidateFunction>();\n\nasync function loadSchema(schemaName: string, rootDir: string = process.cwd()): Promise<object> {\n const cacheKey = `${rootDir}:${schemaName}`;\n if (schemaCache.has(cacheKey)) {\n return schemaCache.get(cacheKey)!;\n }\n\n // Try multiple locations for schema files:\n // 1. CLI repo's schemas (for agent schemas)\n // 2. Target directory's schemas (for stack/skill schemas in claude-subagents)\n const locations = [\n path.join(PROJECT_ROOT, \"src\", \"schemas\", schemaName),\n path.join(rootDir, \"src\", \"schemas\", schemaName),\n ];\n\n for (const schemaPath of locations) {\n if (await fileExists(schemaPath)) {\n const content = await readFile(schemaPath);\n const schema = JSON.parse(content);\n schemaCache.set(cacheKey, schema);\n return schema;\n }\n }\n\n throw new Error(`Schema not found: ${schemaName}. Searched: ${locations.join(\", \")}`);\n}\n\nasync function getValidator(\n schemaName: string,\n rootDir: string = process.cwd(),\n): Promise<ValidateFunction> {\n const cacheKey = `${rootDir}:${schemaName}`;\n if (validatorCache.has(cacheKey)) {\n return validatorCache.get(cacheKey)!;\n }\n\n const ajv = new Ajv({ allErrors: true, strict: false });\n addFormats(ajv);\n const schema = await loadSchema(schemaName, rootDir);\n const validate = ajv.compile(schema);\n validatorCache.set(cacheKey, validate);\n return validate;\n}\n\nfunction formatAjvErrors(errors: ErrorObject[] | null | undefined): string[] {\n if (!errors) return [];\n\n return errors.map((err) => {\n const errorPath = err.instancePath\n ? err.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\")\n : \"\";\n const message = err.message || \"Unknown error\";\n\n if (err.keyword === \"additionalProperties\") {\n const prop = (err.params as { additionalProperty?: string }).additionalProperty;\n return `Unrecognized key: \"${prop}\"`;\n }\n\n if (err.keyword === \"enum\") {\n const allowed = (err.params as { allowedValues?: string[] }).allowedValues;\n return errorPath\n ? `${errorPath}: ${message}. Allowed: ${allowed?.join(\", \")}`\n : `${message}. Allowed: ${allowed?.join(\", \")}`;\n }\n\n return errorPath ? `${errorPath}: ${message}` : message;\n });\n}\n\nasync function validateFile(\n filePath: string,\n validate: ValidateFunction,\n extractor?: ContentExtractor,\n): Promise<{ valid: boolean; errors: string[] }> {\n try {\n if (!(await fileExists(filePath))) {\n return { valid: false, errors: [`File not found: ${filePath}`] };\n }\n\n const content = await readFile(filePath);\n\n let parsed: unknown;\n if (extractor) {\n parsed = extractor(content);\n if (parsed === null) {\n return {\n valid: false,\n errors: [\"Failed to extract content (no valid frontmatter found)\"],\n };\n }\n } else {\n parsed = parseYaml(content);\n }\n\n const isValid = validate(parsed);\n\n if (isValid) {\n return { valid: true, errors: [] };\n }\n\n return { valid: false, errors: formatAjvErrors(validate.errors) };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return { valid: false, errors: [`Failed to parse content: ${message}`] };\n }\n}\n\nasync function validateTarget(\n target: ValidationTarget,\n rootDir: string = process.cwd(),\n): Promise<SchemaValidationResult> {\n const baseDir = path.join(rootDir, target.baseDir);\n const pattern = path.join(baseDir, target.pattern);\n const files = await fg(pattern, { absolute: true });\n\n const result: SchemaValidationResult = {\n schemaName: target.name,\n valid: true,\n totalFiles: files.length,\n validFiles: 0,\n invalidFiles: [],\n };\n\n if (files.length === 0) {\n return result;\n }\n\n const validate = await getValidator(target.schema, rootDir);\n\n for (const file of files) {\n const validation = await validateFile(file, validate, target.extractor);\n const relativePath = path.relative(rootDir, file);\n\n if (validation.valid) {\n result.validFiles++;\n } else {\n result.valid = false;\n result.invalidFiles.push({\n file: relativePath,\n errors: validation.errors,\n });\n }\n }\n\n return result;\n}\n\nexport async function validateAllSchemas(\n rootDir: string = process.cwd(),\n): Promise<FullValidationResult> {\n const results: SchemaValidationResult[] = [];\n\n for (const target of VALIDATION_TARGETS) {\n const result = await validateTarget(target, rootDir);\n results.push(result);\n }\n\n const summary = {\n totalSchemas: results.length,\n totalFiles: results.reduce((sum, r) => sum + r.totalFiles, 0),\n validFiles: results.reduce((sum, r) => sum + r.validFiles, 0),\n invalidFiles: results.reduce((sum, r) => sum + r.invalidFiles.length, 0),\n };\n\n return {\n valid: results.every((r) => r.valid),\n results,\n summary,\n };\n}\n\nexport function printValidationResults(result: FullValidationResult): void {\n console.log(`\\n Schema Validation Summary:`);\n console.log(` ─────────────────────────`);\n console.log(` Total schemas checked: ${result.summary.totalSchemas}`);\n console.log(` Total files: ${result.summary.totalFiles}`);\n console.log(` Valid: ${result.summary.validFiles}`);\n console.log(` Invalid: ${result.summary.invalidFiles}`);\n\n for (const schemaResult of result.results) {\n if (schemaResult.totalFiles === 0) continue;\n\n const status = schemaResult.valid ? \"✓\" : \"✗\";\n console.log(\n `\\n ${status} ${schemaResult.schemaName}: ${schemaResult.validFiles}/${schemaResult.totalFiles} valid`,\n );\n\n if (schemaResult.invalidFiles.length > 0) {\n for (const file of schemaResult.invalidFiles) {\n console.log(`\\n ${file.file}:`);\n file.errors.forEach((e) => console.log(` - ${e}`));\n }\n }\n }\n\n if (result.valid) {\n console.log(`\\n ✓ All schemas validated successfully\\n`);\n } else {\n console.log(`\\n ✗ Validation failed\\n`);\n }\n}\n","import { parse as parseYaml } from \"yaml\";\n\n/**\n * Extract and parse YAML frontmatter from a markdown string.\n * Returns the parsed YAML object, or null if no valid frontmatter found.\n */\nexport function extractFrontmatter(content: string): unknown | null {\n const frontmatterRegex = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---/;\n const match = content.match(frontmatterRegex);\n\n if (!match || !match[1]) {\n return null;\n }\n\n try {\n return parseYaml(match[1]);\n } catch {\n return null;\n }\n}\n","import Ajv, { type ValidateFunction, type ErrorObject } from \"ajv\";\nimport addFormats from \"ajv-formats\";\nimport path from \"path\";\nimport { parse as parseYaml } from \"yaml\";\nimport fg from \"fast-glob\";\nimport { fileExists, readFile, directoryExists, listDirectories } from \"../utils/fs\";\nimport { PROJECT_ROOT } from \"../consts\";\nimport type { ValidationResult } from \"../../types\";\nimport { extractFrontmatter } from \"../utils/frontmatter\";\n\nconst PLUGIN_DIR = \".claude-plugin\";\nconst PLUGIN_MANIFEST = \"plugin.json\";\nconst SKILL_FILE = \"SKILL.md\";\nconst KEBAB_CASE_REGEX = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;\nconst SEMVER_REGEX =\n /^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$/;\n\nconst schemaCache = new Map<string, object>();\nconst validatorCache = new Map<string, ValidateFunction>();\n\n// Remote schemas hosted on GitHub (source of truth for skill schemas)\nconst REMOTE_SCHEMAS: Record<string, string> = {\n \"skill-frontmatter.schema.json\":\n \"https://raw.githubusercontent.com/claude-collective/skills/main/src/schemas/skill-frontmatter.schema.json\",\n};\n\nasync function loadSchema(schemaName: string): Promise<object> {\n if (schemaCache.has(schemaName)) {\n return schemaCache.get(schemaName)!;\n }\n\n // Try local locations first for CLI-owned schemas\n const locations = [\n path.join(PROJECT_ROOT, \"src\", \"schemas\", schemaName),\n path.join(process.cwd(), \"src\", \"schemas\", schemaName),\n ];\n\n for (const schemaPath of locations) {\n if (await fileExists(schemaPath)) {\n const content = await readFile(schemaPath);\n const schema = JSON.parse(content);\n schemaCache.set(schemaName, schema);\n return schema;\n }\n }\n\n // Fall back to remote schema from GitHub (for skill schemas)\n const remoteUrl = REMOTE_SCHEMAS[schemaName];\n if (remoteUrl) {\n try {\n const response = await fetch(remoteUrl);\n if (response.ok) {\n const schema = await response.json();\n schemaCache.set(schemaName, schema);\n return schema;\n }\n } catch {\n // Fall through to error\n }\n }\n\n throw new Error(\n `Schema not found: ${schemaName}. Searched: ${locations.join(\", \")}${remoteUrl ? ` and ${remoteUrl}` : \"\"}`,\n );\n}\n\nasync function getValidator(schemaName: string): Promise<ValidateFunction> {\n if (validatorCache.has(schemaName)) {\n return validatorCache.get(schemaName)!;\n }\n\n const ajv = new Ajv({ allErrors: true, strict: false });\n addFormats(ajv);\n const schema = await loadSchema(schemaName);\n const validate = ajv.compile(schema);\n validatorCache.set(schemaName, validate);\n return validate;\n}\n\nfunction formatAjvErrors(errors: ErrorObject[] | null | undefined): string[] {\n if (!errors) return [];\n\n return errors.map((err) => {\n const errorPath = err.instancePath\n ? err.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\")\n : \"\";\n const message = err.message || \"Unknown error\";\n\n if (err.keyword === \"additionalProperties\") {\n const prop = (err.params as { additionalProperty?: string }).additionalProperty;\n return `Unrecognized key: \"${prop}\"`;\n }\n\n if (err.keyword === \"enum\") {\n const allowed = (err.params as { allowedValues?: string[] }).allowedValues;\n return errorPath\n ? `${errorPath}: ${message}. Allowed: ${allowed?.join(\", \")}`\n : `${message}. Allowed: ${allowed?.join(\", \")}`;\n }\n\n if (err.keyword === \"pattern\") {\n let hint = \"\";\n if (errorPath === \"name\") {\n hint = \" (must be kebab-case)\";\n } else if (errorPath === \"version\") {\n hint = \" (must be semver: x.y.z)\";\n }\n return errorPath ? `${errorPath}: ${message}${hint}` : `${message}${hint}`;\n }\n\n return errorPath ? `${errorPath}: ${message}` : message;\n });\n}\n\nfunction isKebabCase(str: string): boolean {\n return KEBAB_CASE_REGEX.test(str);\n}\n\nfunction isValidSemver(str: string): boolean {\n return SEMVER_REGEX.test(str);\n}\n\nexport async function validatePluginStructure(pluginPath: string): Promise<ValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!(await directoryExists(pluginPath))) {\n return {\n valid: false,\n errors: [`Plugin directory does not exist: ${pluginPath}`],\n warnings: [],\n };\n }\n\n const pluginDir = path.join(pluginPath, PLUGIN_DIR);\n if (!(await directoryExists(pluginDir))) {\n errors.push(`Missing ${PLUGIN_DIR}/ directory`);\n }\n\n const manifestPath = path.join(pluginDir, PLUGIN_MANIFEST);\n if (!(await fileExists(manifestPath))) {\n errors.push(`Missing ${PLUGIN_DIR}/${PLUGIN_MANIFEST}`);\n }\n\n const readmePath = path.join(pluginPath, \"README.md\");\n if (!(await fileExists(readmePath))) {\n warnings.push(\"Missing README.md (recommended for documentation)\");\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\nexport async function validatePluginManifest(manifestPath: string): Promise<ValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!(await fileExists(manifestPath))) {\n return {\n valid: false,\n errors: [`Manifest file not found: ${manifestPath}`],\n warnings: [],\n };\n }\n\n let manifest: Record<string, unknown>;\n try {\n const content = await readFile(manifestPath);\n manifest = JSON.parse(content);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n valid: false,\n errors: [`Invalid JSON in ${PLUGIN_MANIFEST}: ${message}`],\n warnings: [],\n };\n }\n\n const validate = await getValidator(\"plugin.schema.json\");\n const isValid = validate(manifest);\n\n if (!isValid) {\n errors.push(...formatAjvErrors(validate.errors));\n }\n\n if (manifest.name && typeof manifest.name === \"string\") {\n if (!isKebabCase(manifest.name)) {\n errors.push(`name must be kebab-case: \"${manifest.name}\"`);\n }\n }\n\n if (manifest.version && typeof manifest.version === \"string\") {\n if (!isValidSemver(manifest.version)) {\n warnings.push(\n `version \"${manifest.version}\" is not valid semver (expected: major.minor.patch)`,\n );\n }\n }\n\n if (!manifest.description) {\n warnings.push(\"Missing description field (recommended for discoverability)\");\n }\n\n const pluginDir = path.dirname(path.dirname(manifestPath));\n\n if (manifest.skills && typeof manifest.skills === \"string\") {\n const skillsPath = path.join(pluginDir, manifest.skills);\n if (!(await directoryExists(skillsPath))) {\n errors.push(`Skills path does not exist: ${manifest.skills}`);\n }\n }\n\n if (manifest.agents && typeof manifest.agents === \"string\") {\n const agentsPath = path.join(pluginDir, manifest.agents);\n if (!(await directoryExists(agentsPath))) {\n errors.push(`Agents path does not exist: ${manifest.agents}`);\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\nexport async function validateSkillFrontmatter(skillPath: string): Promise<ValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!(await fileExists(skillPath))) {\n return {\n valid: false,\n errors: [`Skill file not found: ${skillPath}`],\n warnings: [],\n };\n }\n\n const content = await readFile(skillPath);\n const frontmatter = extractFrontmatter(content);\n\n if (frontmatter === null) {\n return {\n valid: false,\n errors: [\"Missing or invalid YAML frontmatter\"],\n warnings: [],\n };\n }\n\n const validate = await getValidator(\"skill-frontmatter.schema.json\");\n const isValid = validate(frontmatter);\n\n if (!isValid) {\n errors.push(...formatAjvErrors(validate.errors));\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\nexport async function validateAgentFrontmatter(agentPath: string): Promise<ValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!(await fileExists(agentPath))) {\n return {\n valid: false,\n errors: [`Agent file not found: ${agentPath}`],\n warnings: [],\n };\n }\n\n const content = await readFile(agentPath);\n const frontmatter = extractFrontmatter(content);\n\n if (frontmatter === null) {\n return {\n valid: false,\n errors: [\"Missing or invalid YAML frontmatter\"],\n warnings: [],\n };\n }\n\n const validate = await getValidator(\"agent-frontmatter.schema.json\");\n const isValid = validate(frontmatter);\n\n if (!isValid) {\n errors.push(...formatAjvErrors(validate.errors));\n }\n\n const fm = frontmatter as Record<string, unknown>;\n\n if (fm.name && typeof fm.name === \"string\") {\n if (!isKebabCase(fm.name)) {\n errors.push(`name must be kebab-case: \"${fm.name}\"`);\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\nexport async function validatePlugin(pluginPath: string): Promise<ValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n const structureResult = await validatePluginStructure(pluginPath);\n errors.push(...structureResult.errors);\n warnings.push(...structureResult.warnings);\n\n if (!structureResult.valid) {\n return { valid: false, errors, warnings };\n }\n\n const manifestPath = path.join(pluginPath, PLUGIN_DIR, PLUGIN_MANIFEST);\n const manifestResult = await validatePluginManifest(manifestPath);\n errors.push(...manifestResult.errors);\n warnings.push(...manifestResult.warnings);\n\n let manifest: Record<string, unknown> | null = null;\n try {\n const content = await readFile(manifestPath);\n manifest = JSON.parse(content);\n } catch {}\n\n if (manifest) {\n if (manifest.skills && typeof manifest.skills === \"string\") {\n const skillsDir = path.join(pluginPath, manifest.skills);\n if (await directoryExists(skillsDir)) {\n const skillFiles = await fg(\"**/SKILL.md\", {\n cwd: skillsDir,\n absolute: true,\n });\n\n if (skillFiles.length === 0) {\n warnings.push(\n `Skills directory exists but contains no SKILL.md files: ${manifest.skills}`,\n );\n }\n\n for (const skillFile of skillFiles) {\n const relativePath = path.relative(pluginPath, skillFile);\n const skillResult = await validateSkillFrontmatter(skillFile);\n\n if (!skillResult.valid) {\n errors.push(...skillResult.errors.map((e) => `${relativePath}: ${e}`));\n }\n warnings.push(...skillResult.warnings.map((w) => `${relativePath}: ${w}`));\n }\n }\n }\n\n if (manifest.agents && typeof manifest.agents === \"string\") {\n const agentsDir = path.join(pluginPath, manifest.agents);\n if (await directoryExists(agentsDir)) {\n const agentFiles = await fg(\"*.md\", {\n cwd: agentsDir,\n absolute: true,\n });\n\n if (agentFiles.length === 0) {\n warnings.push(`Agents directory exists but contains no .md files: ${manifest.agents}`);\n }\n\n for (const agentFile of agentFiles) {\n const relativePath = path.relative(pluginPath, agentFile);\n const agentResult = await validateAgentFrontmatter(agentFile);\n\n if (!agentResult.valid) {\n errors.push(...agentResult.errors.map((e) => `${relativePath}: ${e}`));\n }\n warnings.push(...agentResult.warnings.map((w) => `${relativePath}: ${w}`));\n }\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\nexport async function validateAllPlugins(pluginsDir: string): Promise<{\n valid: boolean;\n results: Array<{ name: string; result: ValidationResult }>;\n summary: {\n total: number;\n valid: number;\n invalid: number;\n withWarnings: number;\n };\n}> {\n const results: Array<{ name: string; result: ValidationResult }> = [];\n\n if (!(await directoryExists(pluginsDir))) {\n return {\n valid: false,\n results: [\n {\n name: pluginsDir,\n result: {\n valid: false,\n errors: [`Directory does not exist: ${pluginsDir}`],\n warnings: [],\n },\n },\n ],\n summary: { total: 0, valid: 0, invalid: 1, withWarnings: 0 },\n };\n }\n\n const allDirs = await listDirectories(pluginsDir);\n const pluginDirs: string[] = [];\n\n for (const dirName of allDirs) {\n const potentialPluginDir = path.join(pluginsDir, dirName, PLUGIN_DIR);\n if (await directoryExists(potentialPluginDir)) {\n pluginDirs.push(dirName);\n }\n }\n\n if (pluginDirs.length === 0) {\n return {\n valid: false,\n results: [\n {\n name: pluginsDir,\n result: {\n valid: false,\n errors: [\n `No plugins found in directory: ${pluginsDir}. Plugins must contain a ${PLUGIN_DIR}/ directory.`,\n ],\n warnings: [],\n },\n },\n ],\n summary: { total: 0, valid: 0, invalid: 1, withWarnings: 0 },\n };\n }\n\n for (const pluginName of pluginDirs) {\n const pluginPath = path.join(pluginsDir, pluginName);\n const result = await validatePlugin(pluginPath);\n results.push({ name: pluginName, result });\n }\n\n const summary = {\n total: results.length,\n valid: results.filter((r) => r.result.valid).length,\n invalid: results.filter((r) => !r.result.valid).length,\n withWarnings: results.filter((r) => r.result.warnings.length > 0).length,\n };\n\n return {\n valid: summary.invalid === 0,\n results,\n summary,\n };\n}\n\nexport function printPluginValidationResult(\n name: string,\n result: ValidationResult,\n verbose = false,\n): void {\n const status = result.valid ? \"\\u2713\" : \"\\u2717\";\n\n if (result.valid && result.warnings.length === 0 && !verbose) {\n return;\n }\n\n console.log(`\\n ${status} ${name}`);\n\n if (result.errors.length > 0) {\n console.log(\" Errors:\");\n result.errors.forEach((e) => console.log(` - ${e}`));\n }\n\n if (result.warnings.length > 0) {\n console.log(\" Warnings:\");\n result.warnings.forEach((w) => console.log(` - ${w}`));\n }\n}\n"],"mappings":"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","names":["path","parseYaml","parseYaml","Ajv","addFormats","path","fg","schemaCache","validatorCache","loadSchema","path","getValidator","Ajv","addFormats","formatAjvErrors","fg","path"]}
|