claude-skill-lint 0.3.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.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +383 -0
  3. package/bin/cli.js +10 -0
  4. package/dist/changed-files.d.ts +20 -0
  5. package/dist/changed-files.d.ts.map +1 -0
  6. package/dist/changed-files.js +49 -0
  7. package/dist/changed-files.js.map +1 -0
  8. package/dist/classify.d.ts +13 -0
  9. package/dist/classify.d.ts.map +1 -0
  10. package/dist/classify.js +72 -0
  11. package/dist/classify.js.map +1 -0
  12. package/dist/cli.d.ts +2 -0
  13. package/dist/cli.d.ts.map +1 -0
  14. package/dist/cli.js +124 -0
  15. package/dist/cli.js.map +1 -0
  16. package/dist/config.d.ts +19 -0
  17. package/dist/config.d.ts.map +1 -0
  18. package/dist/config.js +103 -0
  19. package/dist/config.js.map +1 -0
  20. package/dist/detect-format.d.ts +18 -0
  21. package/dist/detect-format.d.ts.map +1 -0
  22. package/dist/detect-format.js +137 -0
  23. package/dist/detect-format.js.map +1 -0
  24. package/dist/extract.d.ts +19 -0
  25. package/dist/extract.d.ts.map +1 -0
  26. package/dist/extract.js +197 -0
  27. package/dist/extract.js.map +1 -0
  28. package/dist/graph.d.ts +21 -0
  29. package/dist/graph.d.ts.map +1 -0
  30. package/dist/graph.js +94 -0
  31. package/dist/graph.js.map +1 -0
  32. package/dist/index.d.ts +26 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +30 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/init.d.ts +17 -0
  37. package/dist/init.d.ts.map +1 -0
  38. package/dist/init.js +45 -0
  39. package/dist/init.js.map +1 -0
  40. package/dist/lint.d.ts +16 -0
  41. package/dist/lint.d.ts.map +1 -0
  42. package/dist/lint.js +152 -0
  43. package/dist/lint.js.map +1 -0
  44. package/dist/profiles.d.ts +37 -0
  45. package/dist/profiles.d.ts.map +1 -0
  46. package/dist/profiles.js +161 -0
  47. package/dist/profiles.js.map +1 -0
  48. package/dist/reporter.d.ts +21 -0
  49. package/dist/reporter.d.ts.map +1 -0
  50. package/dist/reporter.js +110 -0
  51. package/dist/reporter.js.map +1 -0
  52. package/dist/types.d.ts +61 -0
  53. package/dist/types.d.ts.map +1 -0
  54. package/dist/types.js +6 -0
  55. package/dist/types.js.map +1 -0
  56. package/dist/validate-frontmatter.d.ts +41 -0
  57. package/dist/validate-frontmatter.d.ts.map +1 -0
  58. package/dist/validate-frontmatter.js +409 -0
  59. package/dist/validate-frontmatter.js.map +1 -0
  60. package/dist/validate-graph.d.ts +46 -0
  61. package/dist/validate-graph.d.ts.map +1 -0
  62. package/dist/validate-graph.js +651 -0
  63. package/dist/validate-graph.js.map +1 -0
  64. package/dist/validate-manifest.d.ts +22 -0
  65. package/dist/validate-manifest.d.ts.map +1 -0
  66. package/dist/validate-manifest.js +365 -0
  67. package/dist/validate-manifest.js.map +1 -0
  68. package/package.json +64 -0
  69. package/schemas/agent.schema.json +58 -0
  70. package/schemas/command.schema.json +60 -0
  71. package/schemas/skill.schema.json +74 -0
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Orchestrator — wires the full graph validation pipeline end-to-end.
3
+ * CLI args → loadConfig → detectFormat → extractAll → validateGraph → report → exit code
4
+ */
5
+ /** Options passed from the CLI to the graph orchestrator. */
6
+ export interface GraphOptions {
7
+ paths?: string[];
8
+ format: 'terminal' | 'json' | 'github';
9
+ strict: boolean;
10
+ }
11
+ /**
12
+ * Run the graph validation pipeline and return an exit code.
13
+ *
14
+ * Exit codes:
15
+ * 0 — no errors (or only warnings without --strict)
16
+ * 1 — validation errors found (or warnings with --strict)
17
+ *
18
+ * ConfigError is NOT caught here — the caller (cli.ts) handles it for exit code 2.
19
+ */
20
+ export declare function runGraph(options: GraphOptions): Promise<number>;
21
+ //# sourceMappingURL=graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH,6DAA6D;AAC7D,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;IACvC,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAmFrE"}
package/dist/graph.js ADDED
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Orchestrator — wires the full graph validation pipeline end-to-end.
3
+ * CLI args → loadConfig → detectFormat → extractAll → validateGraph → report → exit code
4
+ */
5
+ import { resolve } from 'node:path';
6
+ import { loadConfig } from './config.js';
7
+ import { detectFormat } from './detect-format.js';
8
+ import { extractAll } from './extract.js';
9
+ import { validateGraph } from './validate-graph.js';
10
+ import { reportTerminal, reportGitHub, reportJSON } from './reporter.js';
11
+ import { minimatch } from 'minimatch';
12
+ /**
13
+ * Run the graph validation pipeline and return an exit code.
14
+ *
15
+ * Exit codes:
16
+ * 0 — no errors (or only warnings without --strict)
17
+ * 1 — validation errors found (or warnings with --strict)
18
+ *
19
+ * ConfigError is NOT caught here — the caller (cli.ts) handles it for exit code 2.
20
+ */
21
+ export async function runGraph(options) {
22
+ // Determine root directory from the first path argument or cwd.
23
+ const rootDir = options.paths?.[0]
24
+ ? resolve(options.paths[0])
25
+ : process.cwd();
26
+ // (a) Load config — may throw ConfigError, handled by caller.
27
+ const config = loadConfig(rootDir);
28
+ // (a2) Auto-detect repository format and store in config for graph validation.
29
+ const format = detectFormat(rootDir, config);
30
+ config.format = format;
31
+ // (b) Build glob patterns from paths (default to config.skills_root).
32
+ const rawPaths = options.paths && options.paths.length > 0
33
+ ? options.paths
34
+ : [config.skills_root];
35
+ const patterns = rawPaths.map((p) => {
36
+ const resolved = resolve(p);
37
+ if (!resolved.endsWith('.md')) {
38
+ return `${resolved}/**/*.md`;
39
+ }
40
+ return resolved;
41
+ });
42
+ // (c) Extract all files, passing format for structured format discovery.
43
+ const isStructuredFormat = format === 'plugin' || format === 'multi-plugin' || format === 'project-skills';
44
+ let results = await extractAll(patterns, config.ignore, isStructuredFormat ? format : undefined);
45
+ // (d) Apply ignore patterns from config.
46
+ if (config.ignore.length > 0) {
47
+ results = results.filter((r) => {
48
+ for (const pattern of config.ignore) {
49
+ if (minimatch(r.filePath, pattern, { matchBase: true })) {
50
+ return false;
51
+ }
52
+ }
53
+ return true;
54
+ });
55
+ }
56
+ // (e) Zero files found — report and exit 0.
57
+ if (results.length === 0) {
58
+ if (options.format === 'json') {
59
+ process.stdout.write('[]\n');
60
+ }
61
+ else {
62
+ process.stdout.write('0 files checked\n');
63
+ }
64
+ return 0;
65
+ }
66
+ // (f) Validate graph.
67
+ const validationResults = validateGraph(results, config, rootDir);
68
+ // (g) Format and print report.
69
+ if (options.format === 'json') {
70
+ process.stdout.write(reportJSON(validationResults) + '\n');
71
+ }
72
+ else {
73
+ const output = options.format === 'github'
74
+ ? reportGitHub(validationResults, rootDir)
75
+ : reportTerminal(validationResults, results.length);
76
+ // (h) Print to stdout (skip empty output for clean CI).
77
+ if (output.length > 0) {
78
+ process.stdout.write(output + '\n');
79
+ }
80
+ }
81
+ // (i) --strict: warnings count as errors.
82
+ if (options.strict) {
83
+ const hasWarnings = validationResults.some((r) => r.severity === 'warning');
84
+ if (hasWarnings)
85
+ return 1;
86
+ }
87
+ // (j) Errors → exit 1.
88
+ const hasErrors = validationResults.some((r) => r.severity === 'error');
89
+ if (hasErrors)
90
+ return 1;
91
+ // (k) All clear → exit 0.
92
+ return 0;
93
+ }
94
+ //# sourceMappingURL=graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.js","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * claude-skill-lint — public API.
3
+ *
4
+ * Re-exports the programmatic surface for consumers who want to
5
+ * integrate skill linting into their own tooling without shelling
6
+ * out to the CLI.
7
+ */
8
+ export { runLint } from './lint.js';
9
+ export type { LintOptions } from './lint.js';
10
+ export { runGraph } from './graph.js';
11
+ export type { GraphOptions } from './graph.js';
12
+ export { runInit, buildConfigYaml } from './init.js';
13
+ export type { InitOptions } from './init.js';
14
+ export { loadConfig, getDefaults, ConfigError } from './config.js';
15
+ export { detectFormat } from './detect-format.js';
16
+ export { extractFile, extractAll } from './extract.js';
17
+ export { classifyFile } from './classify.js';
18
+ export { validateFrontmatter, getRuleset } from './validate-frontmatter.js';
19
+ export type { LevelRule } from './validate-frontmatter.js';
20
+ export { validateGraph } from './validate-graph.js';
21
+ export { validateManifest } from './validate-manifest.js';
22
+ export { resolveLevel, checkRatchet } from './profiles.js';
23
+ export { reportJSON, reportGitHub, reportTerminal } from './reporter.js';
24
+ export { getChangedFiles, ChangedFilesError } from './changed-files.js';
25
+ export type { RepoFormat, FileType, ParseError, ExtractResult, ValidationResult, LevelOverrides, ToolsConfig, LimitsConfig, GraphConfig, Config, } from './types.js';
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACrD,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAG7C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAGnE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAG7C,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5E,YAAY,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAE3D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG1D,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAG3D,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGzE,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAGxE,YAAY,EACV,UAAU,EACV,QAAQ,EACR,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,YAAY,EACZ,WAAW,EACX,MAAM,GACP,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * claude-skill-lint — public API.
3
+ *
4
+ * Re-exports the programmatic surface for consumers who want to
5
+ * integrate skill linting into their own tooling without shelling
6
+ * out to the CLI.
7
+ */
8
+ // ── Orchestrators (high-level entry points) ─────────────────────
9
+ export { runLint } from './lint.js';
10
+ export { runGraph } from './graph.js';
11
+ export { runInit, buildConfigYaml } from './init.js';
12
+ // ── Config ──────────────────────────────────────────────────────
13
+ export { loadConfig, getDefaults, ConfigError } from './config.js';
14
+ // ── Format detection ────────────────────────────────────────────
15
+ export { detectFormat } from './detect-format.js';
16
+ // ── Extraction ──────────────────────────────────────────────────
17
+ export { extractFile, extractAll } from './extract.js';
18
+ // ── Classification ──────────────────────────────────────────────
19
+ export { classifyFile } from './classify.js';
20
+ // ── Validation ──────────────────────────────────────────────────
21
+ export { validateFrontmatter, getRuleset } from './validate-frontmatter.js';
22
+ export { validateGraph } from './validate-graph.js';
23
+ export { validateManifest } from './validate-manifest.js';
24
+ // ── Profiles ────────────────────────────────────────────────────
25
+ export { resolveLevel, checkRatchet } from './profiles.js';
26
+ // ── Reporters ───────────────────────────────────────────────────
27
+ export { reportJSON, reportGitHub, reportTerminal } from './reporter.js';
28
+ // ── Git integration ─────────────────────────────────────────────
29
+ export { getChangedFiles, ChangedFilesError } from './changed-files.js';
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,mEAAmE;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAGrD,mEAAmE;AACnE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEnE,mEAAmE;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,mEAAmE;AACnE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEvD,mEAAmE;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,mEAAmE;AACnE,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAG5E,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,mEAAmE;AACnE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE3D,mEAAmE;AACnE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEzE,mEAAmE;AACnE,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/init.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Init subcommand — generates a .skill-lint.yaml config file with sensible defaults.
3
+ * Calls detectFormat() to auto-detect the repo format and includes it in the output.
4
+ */
5
+ import type { RepoFormat } from './types.js';
6
+ /** Options for the init subcommand. */
7
+ export type InitOptions = {
8
+ force?: boolean;
9
+ };
10
+ /** Build the YAML config string based on detected format. */
11
+ export declare function buildConfigYaml(detectedFormat: RepoFormat): string;
12
+ /**
13
+ * Run the init subcommand.
14
+ * @returns exit code (0 = success)
15
+ */
16
+ export declare function runInit(rootDir: string, options?: InitOptions): number;
17
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,uCAAuC;AACvC,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,6DAA6D;AAC7D,wBAAgB,eAAe,CAAC,cAAc,EAAE,UAAU,GAAG,MAAM,CAoClE;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,MAAM,CAuB1E"}
package/dist/init.js ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Init subcommand — generates a .skill-lint.yaml config file with sensible defaults.
3
+ * Calls detectFormat() to auto-detect the repo format and includes it in the output.
4
+ */
5
+ import { existsSync, writeFileSync } from 'node:fs';
6
+ import { join } from 'node:path';
7
+ import { getDefaults } from './config.js';
8
+ import { detectFormat } from './detect-format.js';
9
+ const CONFIG_FILENAME = '.skill-lint.yaml';
10
+ /** Build the YAML config string based on detected format. */
11
+ export function buildConfigYaml(detectedFormat) {
12
+ const lines = [
13
+ '# .skill-lint.yaml — generated by claude-skill-lint init',
14
+ `# Detected format: ${detectedFormat}`,
15
+ 'skills_root: "."',
16
+ 'default_level: 0',
17
+ ];
18
+ if (detectedFormat !== 'legacy-commands') {
19
+ lines.push(`format: ${detectedFormat}`);
20
+ }
21
+ lines.push('', 'models: [opus, sonnet, haiku]', '', 'tools:', ' mcp_pattern: "mcp__*"', ' custom: []', '', 'limits:', ' max_file_size: 15360', '', 'ignore:', ' - "**/README.md"', ' - "**/CLAUDE.md"', ' - "node_modules/**"', '', 'graph:', ' warn_orphans: true', ' detect_cycles: true', ' detect_duplicates: true', '');
22
+ return lines.join('\n');
23
+ }
24
+ /**
25
+ * Run the init subcommand.
26
+ * @returns exit code (0 = success)
27
+ */
28
+ export function runInit(rootDir, options = {}) {
29
+ const configPath = join(rootDir, CONFIG_FILENAME);
30
+ // AC-4: If config already exists and no --force, warn and exit 0
31
+ if (existsSync(configPath) && !options.force) {
32
+ process.stderr.write(`Warning: ${CONFIG_FILENAME} already exists. Use --force to overwrite.\n`);
33
+ return 0;
34
+ }
35
+ // AC-1: Call detectFormat() with a default config (no format override)
36
+ const detectedFormat = detectFormat(rootDir, getDefaults());
37
+ // Build and write the config file
38
+ const yaml = buildConfigYaml(detectedFormat);
39
+ writeFileSync(configPath, yaml, 'utf-8');
40
+ // AC-6: Success message to stderr
41
+ process.stderr.write(`Created ${configPath}\n`);
42
+ process.stderr.write('Run `claude-skill-lint lint .` to validate your files.\n');
43
+ return 0;
44
+ }
45
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,MAAM,eAAe,GAAG,kBAAkB,CAAC;AAO3C,6DAA6D;AAC7D,MAAM,UAAU,eAAe,CAAC,cAA0B;IACxD,MAAM,KAAK,GAAa;QACtB,0DAA0D;QAC1D,sBAAsB,cAAc,EAAE;QACtC,kBAAkB;QAClB,kBAAkB;KACnB,CAAC;IAEF,IAAI,cAAc,KAAK,iBAAiB,EAAE,CAAC;QACzC,KAAK,CAAC,IAAI,CAAC,WAAW,cAAc,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,IAAI,CACR,EAAE,EACF,+BAA+B,EAC/B,EAAE,EACF,QAAQ,EACR,yBAAyB,EACzB,cAAc,EACd,EAAE,EACF,SAAS,EACT,wBAAwB,EACxB,EAAE,EACF,SAAS,EACT,oBAAoB,EACpB,oBAAoB,EACpB,uBAAuB,EACvB,EAAE,EACF,QAAQ,EACR,sBAAsB,EACtB,uBAAuB,EACvB,2BAA2B,EAC3B,EAAE,CACH,CAAC;IAEF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAC,OAAe,EAAE,UAAuB,EAAE;IAChE,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IAElD,iEAAiE;IACjE,IAAI,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAC7C,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,YAAY,eAAe,8CAA8C,CAC1E,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,uEAAuE;IACvE,MAAM,cAAc,GAAG,YAAY,CAAC,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;IAE5D,kCAAkC;IAClC,MAAM,IAAI,GAAG,eAAe,CAAC,cAAc,CAAC,CAAC;IAC7C,aAAa,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAEzC,kCAAkC;IAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,UAAU,IAAI,CAAC,CAAC;IAChD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAEjF,OAAO,CAAC,CAAC;AACX,CAAC"}
package/dist/lint.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Orchestrator — wires the full lint pipeline end-to-end.
3
+ * CLI args → loadConfig → detectFormat → extractAll → validateFrontmatter + validateManifest → report → exit code
4
+ */
5
+ /** Options passed from the CLI to the lint orchestrator. */
6
+ export interface LintOptions {
7
+ paths?: string[];
8
+ level: number;
9
+ changedOnly: boolean;
10
+ base: string;
11
+ format: 'terminal' | 'json' | 'github';
12
+ strict: boolean;
13
+ ratchet: boolean;
14
+ }
15
+ export declare function runLint(options: LintOptions): Promise<number>;
16
+ //# sourceMappingURL=lint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../src/lint.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAgBH,4DAA4D;AAC5D,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,OAAO,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;IACvC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;CAClB;AAuHD,wBAAsB,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAuCnE"}
package/dist/lint.js ADDED
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Orchestrator — wires the full lint pipeline end-to-end.
3
+ * CLI args → loadConfig → detectFormat → extractAll → validateFrontmatter + validateManifest → report → exit code
4
+ */
5
+ import { resolve, dirname } from 'node:path';
6
+ import { existsSync, statSync } from 'node:fs';
7
+ import { loadConfig } from './config.js';
8
+ import { detectFormat } from './detect-format.js';
9
+ import { extractAll, extractFile } from './extract.js';
10
+ import { validateFrontmatter } from './validate-frontmatter.js';
11
+ import { validateManifest } from './validate-manifest.js';
12
+ import { reportTerminal, reportGitHub, reportJSON } from './reporter.js';
13
+ import { execFileSync } from 'node:child_process';
14
+ import { minimatch } from 'minimatch';
15
+ import { getChangedFiles } from './changed-files.js';
16
+ import { checkRatchet } from './profiles.js';
17
+ /**
18
+ * Shared validation pipeline: ratchet check → report → strict check → exit code.
19
+ *
20
+ * Note on stdout guard: the normal scan path had an `if (output.length > 0)` guard
21
+ * (to keep CI output clean when no issues are found and github format returns empty string).
22
+ * The changedOnly path did not have this guard (reportTerminal always returns a non-empty
23
+ * summary line). We harmonize here by always applying the guard — this is safe because
24
+ * reportTerminal always returns a non-empty string, so changedOnly behavior is unchanged.
25
+ *
26
+ * Note on --format github + --changed-only: the original changedOnly branch fell through
27
+ * to reportTerminal for github format (not a supported combination). This is preserved here:
28
+ * github format is only used when explicitly handled; the options.format check matches the
29
+ * original behavior.
30
+ */
31
+ async function runPipeline(input) {
32
+ const { results, validationResults, options, config, rootDir } = input;
33
+ // Ratchet check (additive — appends to validationResults).
34
+ if (options.ratchet) {
35
+ try {
36
+ const gitRoot = execFileSync('git', ['rev-parse', '--show-toplevel'], {
37
+ encoding: 'utf-8',
38
+ }).trim();
39
+ const ratchetResults = await checkRatchet(results, options.base, gitRoot, config);
40
+ validationResults.push(...ratchetResults);
41
+ }
42
+ catch {
43
+ // Base ref not fetchable → warning, skip ratchet.
44
+ process.stderr.write(`warning: could not read base ref "${options.base}", skipping ratchet\n`);
45
+ }
46
+ }
47
+ // Format and print report.
48
+ if (options.format === 'json') {
49
+ process.stdout.write(reportJSON(validationResults) + '\n');
50
+ }
51
+ else {
52
+ const output = options.format === 'github'
53
+ ? reportGitHub(validationResults, rootDir)
54
+ : reportTerminal(validationResults, results.length);
55
+ // Skip empty output for clean CI (e.g. github format with zero results).
56
+ if (output.length > 0) {
57
+ process.stdout.write(output + '\n');
58
+ }
59
+ }
60
+ // --strict: warnings count as errors.
61
+ if (options.strict) {
62
+ const hasWarnings = validationResults.some((r) => r.severity === 'warning');
63
+ if (hasWarnings)
64
+ return 1;
65
+ }
66
+ // Errors → exit 1.
67
+ const hasErrors = validationResults.some((r) => r.severity === 'error');
68
+ if (hasErrors)
69
+ return 1;
70
+ // All clear → exit 0.
71
+ return 0;
72
+ }
73
+ /** Zero-files early-exit helper (shared between both branches). */
74
+ function reportZeroFiles(outputFormat) {
75
+ process.stdout.write(outputFormat === 'json' ? '[]\n' : '0 files checked\n');
76
+ return 0;
77
+ }
78
+ /** Apply ignore patterns to an array of file paths. */
79
+ function applyIgnorePaths(files, ignorePatterns) {
80
+ if (ignorePatterns.length === 0)
81
+ return files;
82
+ return files.filter((f) => !ignorePatterns.some((p) => minimatch(f, p, { matchBase: true })));
83
+ }
84
+ /**
85
+ * Run the lint pipeline and return an exit code.
86
+ * Exit codes: 0 = clean, 1 = errors (or warnings with --strict), 2 = config/git error (caller).
87
+ */
88
+ /**
89
+ * Resolve the project root directory from paths or cwd.
90
+ *
91
+ * When a directory is passed (e.g. `lint .` or `lint test/fixtures/plugin`),
92
+ * use it directly as rootDir — this is the existing behavior.
93
+ *
94
+ * When file paths are passed (e.g. from a pre-commit hook like
95
+ * `lint commands/foo.md agents/bar.md`), the first path is a file, not
96
+ * the repo root. In that case, walk up from cwd to find the nearest
97
+ * directory containing .skill-lint.yaml. Falls back to cwd.
98
+ */
99
+ function resolveRootDir(firstPath) {
100
+ if (firstPath) {
101
+ const resolved = resolve(firstPath);
102
+ // If it's a directory, use it directly (existing behavior).
103
+ if (existsSync(resolved) && statSync(resolved).isDirectory()) {
104
+ return resolved;
105
+ }
106
+ }
107
+ // File path or no path — walk up from cwd to find config.
108
+ let dir = process.cwd();
109
+ while (true) {
110
+ if (existsSync(resolve(dir, '.skill-lint.yaml')))
111
+ return dir;
112
+ const parent = dirname(dir);
113
+ if (parent === dir)
114
+ break;
115
+ dir = parent;
116
+ }
117
+ return process.cwd();
118
+ }
119
+ export async function runLint(options) {
120
+ const rootDir = resolveRootDir(options.paths?.[0]);
121
+ const config = loadConfig(rootDir);
122
+ const format = detectFormat(rootDir, config);
123
+ // --changed-only branch: lint only files changed since base ref.
124
+ if (options.changedOnly) {
125
+ const changedFiles = applyIgnorePaths(getChangedFiles(options.base), config.ignore);
126
+ if (changedFiles.length === 0)
127
+ return reportZeroFiles(options.format);
128
+ const results = changedFiles.map((f) => extractFile(f));
129
+ const validationResults = await validateFrontmatter(results, options.level, config);
130
+ return runPipeline({ results, validationResults, options, config, rootDir });
131
+ }
132
+ // Normal scan branch: glob for .md files.
133
+ const rawPaths = options.paths && options.paths.length > 0 ? options.paths : [config.skills_root];
134
+ const patterns = rawPaths.map((p) => {
135
+ const resolved = resolve(p);
136
+ return resolved.endsWith('.md') ? resolved : `${resolved}/**/*.md`;
137
+ });
138
+ const isStructuredFormat = format === 'plugin' || format === 'multi-plugin' || format === 'project-skills';
139
+ let results = await extractAll(patterns, config.ignore, isStructuredFormat ? format : undefined);
140
+ if (config.ignore.length > 0) {
141
+ results = results.filter((r) => !config.ignore.some((p) => minimatch(r.filePath, p, { matchBase: true })));
142
+ }
143
+ if (results.length === 0)
144
+ return reportZeroFiles(options.format);
145
+ const validationResults = await validateFrontmatter(results, options.level, config);
146
+ // Manifest validation — normal path only.
147
+ if (format === 'plugin' || format === 'multi-plugin') {
148
+ validationResults.push(...validateManifest(rootDir, format, config));
149
+ }
150
+ return runPipeline({ results, validationResults, options, config, rootDir });
151
+ }
152
+ //# sourceMappingURL=lint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint.js","sourceRoot":"","sources":["../src/lint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Progressive quality level resolution for skill files.
3
+ *
4
+ * Priority chain (highest to lowest):
5
+ * 1. File frontmatter `quality_level` (if valid integer 0-3)
6
+ * 2. `.skill-lint.yaml` `levels` section (prefix match, longest prefix wins)
7
+ * 3. `.skill-lint.yaml` `default_level`
8
+ * 4. Hardcoded default: 0
9
+ *
10
+ * CLI `--level` sets a floor: effectiveLevel = max(resolvedLevel, cliLevel)
11
+ */
12
+ import type { Config, ExtractResult, ValidationResult } from './types.js';
13
+ /**
14
+ * Resolve the effective quality level for a single file.
15
+ *
16
+ * @param filePath - Absolute path to the file being validated.
17
+ * @param frontmatter - Parsed frontmatter data (may include `quality_level`).
18
+ * @param config - Config with `default_level`, `levels`, and `skills_root`.
19
+ * @returns The resolved level:
20
+ * - 0-3: explicit file frontmatter or directory override
21
+ * - -1: out-of-range quality_level (caller should warn and use default)
22
+ * - -2: no explicit override found (fell back to default_level or hardcoded 0)
23
+ */
24
+ export declare function resolveLevel(filePath: string, frontmatter: Record<string, unknown>, config: Pick<Config, 'default_level' | 'levels' | 'skills_root'>): number;
25
+ /**
26
+ * Anti-regression ratchet: compare each file's raw quality_level frontmatter
27
+ * against the same file in the base ref. If quality_level decreased, report
28
+ * a "quality-level-regression" error.
29
+ *
30
+ * @param files - Extracted file results to check.
31
+ * @param baseRef - Git ref to compare against (e.g. "origin/main").
32
+ * @param gitRoot - Absolute path to the git repository root.
33
+ * @param config - Config with `skills_root`.
34
+ * @returns Validation results for any regressions found.
35
+ */
36
+ export declare function checkRatchet(files: ExtractResult[], baseRef: string, gitRoot: string, _config: Pick<Config, 'skills_root'>): Promise<ValidationResult[]>;
37
+ //# sourceMappingURL=profiles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiles.d.ts","sourceRoot":"","sources":["../src/profiles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAM1E;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,eAAe,GAAG,QAAQ,GAAG,aAAa,CAAC,GAC/D,MAAM,CAsBR;AA4ED;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,aAAa,EAAE,EACtB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,GACnC,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA0C7B"}