skilltest 0.2.0 → 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.
- package/CLAUDE.md +8 -0
- package/README.md +39 -4
- package/dist/index.js +290 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
- `lint`: static/offline quality checks
|
|
8
8
|
- `trigger`: model-based triggerability testing
|
|
9
9
|
- `eval`: end-to-end execution + grader-based scoring
|
|
10
|
+
- `check`: lint + trigger + eval quality gates in one run
|
|
10
11
|
|
|
11
12
|
The CLI is published as `skilltest` and built for `npx skilltest` usage.
|
|
12
13
|
|
|
@@ -18,6 +19,7 @@ The CLI is published as `skilltest` and built for `npx skilltest` usage.
|
|
|
18
19
|
- `src/core/linter/`: lint check modules and orchestrator
|
|
19
20
|
- `src/core/trigger-tester.ts`: query generation + trigger simulation + metrics
|
|
20
21
|
- `src/core/eval-runner.ts`: prompt generation/loading + skill execution + grading loop
|
|
22
|
+
- `src/core/check-runner.ts`: orchestrates lint + trigger + eval with threshold gates
|
|
21
23
|
- `src/core/grader.ts`: structured grader prompt + JSON parse
|
|
22
24
|
- `src/providers/`: LLM provider abstraction (`sendMessage`) and provider implementations
|
|
23
25
|
- `src/reporters/`: terminal rendering and JSON output helper
|
|
@@ -68,6 +70,9 @@ ANTHROPIC_API_KEY=your-key node dist/index.js trigger test-fixtures/sample-skill
|
|
|
68
70
|
- `sendMessage(systemPrompt, userMessage, { model }) => Promise<string>`
|
|
69
71
|
- Lint is fully offline and first-class.
|
|
70
72
|
- Trigger/eval rely on the same provider abstraction.
|
|
73
|
+
- `check` wraps lint + trigger + eval and enforces minimum thresholds:
|
|
74
|
+
- trigger F1
|
|
75
|
+
- eval assertion pass rate
|
|
71
76
|
- JSON mode is strict:
|
|
72
77
|
- no spinners
|
|
73
78
|
- no colored output
|
|
@@ -79,6 +84,8 @@ ANTHROPIC_API_KEY=your-key node dist/index.js trigger test-fixtures/sample-skill
|
|
|
79
84
|
## Gotchas
|
|
80
85
|
|
|
81
86
|
- `trigger --num-queries` must be even for balanced positive/negative cases.
|
|
87
|
+
- `check` also requires even `--num-queries`.
|
|
88
|
+
- `check` stops after lint failures unless `--continue-on-lint-fail` is set.
|
|
82
89
|
- OpenAI provider is implemented via dynamic import so Anthropic-only installs do not crash if optional deps are skipped.
|
|
83
90
|
- Frontmatter is validated with both `gray-matter` and `js-yaml`; malformed YAML should fail fast.
|
|
84
91
|
- Keep file references relative to skill root; out-of-root refs are lint failures.
|
|
@@ -94,6 +101,7 @@ ANTHROPIC_API_KEY=your-key node dist/index.js trigger test-fixtures/sample-skill
|
|
|
94
101
|
- Compatibility hints: `src/core/linter/compat.ts`
|
|
95
102
|
- Trigger fake skill pool + scoring: `src/core/trigger-tester.ts`
|
|
96
103
|
- Eval grading schema: `src/core/grader.ts`
|
|
104
|
+
- Combined quality gate orchestration: `src/core/check-runner.ts`
|
|
97
105
|
|
|
98
106
|
## Future Work (Not Implemented Yet)
|
|
99
107
|
|
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ Agent Skills are quick to write but hard to validate before deployment:
|
|
|
23
23
|
- You cannot easily measure trigger precision/recall.
|
|
24
24
|
- You do not know whether outputs are good until users exercise the skill.
|
|
25
25
|
|
|
26
|
-
`skilltest` closes this gap with one CLI and
|
|
26
|
+
`skilltest` closes this gap with one CLI and four modes.
|
|
27
27
|
|
|
28
28
|
## Install
|
|
29
29
|
|
|
@@ -61,12 +61,18 @@ End-to-end eval:
|
|
|
61
61
|
skilltest eval ./path/to/skill --provider anthropic --model claude-sonnet-4-5-20250929
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
+
Run full quality gate:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
skilltest check ./path/to/skill --provider anthropic --min-f1 0.8 --min-assert-pass-rate 0.9
|
|
68
|
+
```
|
|
69
|
+
|
|
64
70
|
Example lint summary:
|
|
65
71
|
|
|
66
72
|
```text
|
|
67
73
|
skilltest lint
|
|
68
74
|
target: ./test-fixtures/sample-skill
|
|
69
|
-
summary:
|
|
75
|
+
summary: 29/29 checks passed, 0 warnings, 0 failures
|
|
70
76
|
```
|
|
71
77
|
|
|
72
78
|
## Commands
|
|
@@ -153,6 +159,32 @@ Flags:
|
|
|
153
159
|
- `--api-key <key>` explicit key override
|
|
154
160
|
- `--verbose` show full model responses
|
|
155
161
|
|
|
162
|
+
### `skilltest check <path-to-skill>`
|
|
163
|
+
|
|
164
|
+
Runs `lint + trigger + eval` in one command and applies quality thresholds.
|
|
165
|
+
|
|
166
|
+
Default behavior:
|
|
167
|
+
|
|
168
|
+
1. Run lint.
|
|
169
|
+
2. Stop before model calls if lint has failures.
|
|
170
|
+
3. Run trigger and eval only when lint passes.
|
|
171
|
+
4. Fail quality gate when either threshold is below target.
|
|
172
|
+
|
|
173
|
+
Flags:
|
|
174
|
+
|
|
175
|
+
- `--provider <anthropic|openai>` default: `anthropic`
|
|
176
|
+
- `--model <model>` default: `claude-sonnet-4-5-20250929` (auto-switches to `gpt-4.1-mini` for `--provider openai` when unchanged)
|
|
177
|
+
- `--grader-model <model>` default: same as resolved `--model`
|
|
178
|
+
- `--api-key <key>` explicit key override
|
|
179
|
+
- `--queries <path>` custom trigger queries JSON
|
|
180
|
+
- `--num-queries <n>` default: `20` (must be even)
|
|
181
|
+
- `--prompts <path>` custom eval prompts JSON
|
|
182
|
+
- `--min-f1 <n>` default: `0.8`
|
|
183
|
+
- `--min-assert-pass-rate <n>` default: `0.9`
|
|
184
|
+
- `--save-results <path>` save combined check result JSON
|
|
185
|
+
- `--continue-on-lint-fail` continue trigger/eval even if lint fails
|
|
186
|
+
- `--verbose` include detailed trigger/eval sections
|
|
187
|
+
|
|
156
188
|
## Global Flags
|
|
157
189
|
|
|
158
190
|
- `--help` show help
|
|
@@ -195,8 +227,8 @@ Eval prompts (`--prompts`):
|
|
|
195
227
|
|
|
196
228
|
Exit codes:
|
|
197
229
|
|
|
198
|
-
- `0`: success
|
|
199
|
-
- `1`: lint
|
|
230
|
+
- `0`: success
|
|
231
|
+
- `1`: quality gate failed (`lint`, `check` thresholds, or command-specific failure conditions)
|
|
200
232
|
- `2`: runtime/config/API/parse error
|
|
201
233
|
|
|
202
234
|
JSON mode examples:
|
|
@@ -205,6 +237,7 @@ JSON mode examples:
|
|
|
205
237
|
skilltest lint ./skill --json
|
|
206
238
|
skilltest trigger ./skill --json
|
|
207
239
|
skilltest eval ./skill --json
|
|
240
|
+
skilltest check ./skill --json
|
|
208
241
|
```
|
|
209
242
|
|
|
210
243
|
## API Keys
|
|
@@ -294,6 +327,7 @@ jobs:
|
|
|
294
327
|
- run: npm run build
|
|
295
328
|
- run: npx skilltest trigger path/to/skill --num-queries 20 --json
|
|
296
329
|
- run: npx skilltest eval path/to/skill --prompts path/to/prompts.json --json
|
|
330
|
+
- run: npx skilltest check path/to/skill --min-f1 0.8 --min-assert-pass-rate 0.9 --json
|
|
297
331
|
```
|
|
298
332
|
|
|
299
333
|
## Local Development
|
|
@@ -311,6 +345,7 @@ Smoke tests:
|
|
|
311
345
|
node dist/index.js lint test-fixtures/sample-skill/
|
|
312
346
|
node dist/index.js trigger test-fixtures/sample-skill/ --num-queries 2
|
|
313
347
|
node dist/index.js eval test-fixtures/sample-skill/ --prompts test-fixtures/eval-prompts.json
|
|
348
|
+
node dist/index.js check test-fixtures/sample-skill/ --num-queries 2 --prompts test-fixtures/eval-prompts.json
|
|
314
349
|
```
|
|
315
350
|
|
|
316
351
|
## Release Checklist
|
package/dist/index.js
CHANGED
|
@@ -1076,6 +1076,88 @@ function renderEvalReport(result, enableColor, verbose) {
|
|
|
1076
1076
|
}
|
|
1077
1077
|
return lines.join("\n");
|
|
1078
1078
|
}
|
|
1079
|
+
function gateStatusLabel(value, c) {
|
|
1080
|
+
if (value === null) {
|
|
1081
|
+
return c.yellow("SKIP");
|
|
1082
|
+
}
|
|
1083
|
+
return value ? c.green("PASS") : c.red("FAIL");
|
|
1084
|
+
}
|
|
1085
|
+
function renderCheckReport(result, enableColor, verbose) {
|
|
1086
|
+
const c = getChalkInstance(enableColor);
|
|
1087
|
+
const lines = [];
|
|
1088
|
+
const lintGate = gateStatusLabel(result.gates.lintPassed, c);
|
|
1089
|
+
const triggerGate = gateStatusLabel(result.gates.triggerPassed, c);
|
|
1090
|
+
const evalGate = gateStatusLabel(result.gates.evalPassed, c);
|
|
1091
|
+
const overallGate = result.gates.overallPassed ? c.green("PASS") : c.red("FAIL");
|
|
1092
|
+
lines.push("skilltest check");
|
|
1093
|
+
lines.push(`target: ${result.target}`);
|
|
1094
|
+
lines.push(`provider/model: ${result.provider}/${result.model}`);
|
|
1095
|
+
lines.push(`grader model: ${result.graderModel}`);
|
|
1096
|
+
lines.push(
|
|
1097
|
+
`thresholds: min-f1=${result.thresholds.minF1.toFixed(2)} min-assert-pass-rate=${result.thresholds.minAssertPassRate.toFixed(2)}`
|
|
1098
|
+
);
|
|
1099
|
+
lines.push("");
|
|
1100
|
+
lines.push("Lint");
|
|
1101
|
+
lines.push(
|
|
1102
|
+
`- ${lintGate} ${result.lint.summary.passed}/${result.lint.summary.total} checks passed (${result.lint.summary.warnings} warnings, ${result.lint.summary.failures} failures)`
|
|
1103
|
+
);
|
|
1104
|
+
const lintIssues = verbose ? result.lint.issues : result.lint.issues.filter((issue) => issue.status !== "pass");
|
|
1105
|
+
for (const issue of lintIssues) {
|
|
1106
|
+
lines.push(renderIssueLine(issue, c));
|
|
1107
|
+
}
|
|
1108
|
+
lines.push("");
|
|
1109
|
+
lines.push("Trigger");
|
|
1110
|
+
if (result.trigger) {
|
|
1111
|
+
lines.push(
|
|
1112
|
+
`- ${triggerGate} f1=${formatPercent(result.trigger.metrics.f1)} (precision=${formatPercent(result.trigger.metrics.precision)} recall=${formatPercent(result.trigger.metrics.recall)})`
|
|
1113
|
+
);
|
|
1114
|
+
lines.push(
|
|
1115
|
+
` TP ${result.trigger.metrics.truePositives} TN ${result.trigger.metrics.trueNegatives} FP ${result.trigger.metrics.falsePositives} FN ${result.trigger.metrics.falseNegatives}`
|
|
1116
|
+
);
|
|
1117
|
+
const triggerCases = verbose ? result.trigger.cases : result.trigger.cases.filter((testCase) => !testCase.matched);
|
|
1118
|
+
for (const testCase of triggerCases) {
|
|
1119
|
+
const status = testCase.matched ? c.green("PASS") : c.red("FAIL");
|
|
1120
|
+
lines.push(` - ${status} ${testCase.query}`);
|
|
1121
|
+
lines.push(` expected=${testCase.expected} actual=${testCase.actual}`);
|
|
1122
|
+
}
|
|
1123
|
+
} else {
|
|
1124
|
+
lines.push(`- ${triggerGate} ${result.triggerSkippedReason ?? "Skipped."}`);
|
|
1125
|
+
}
|
|
1126
|
+
lines.push("");
|
|
1127
|
+
lines.push("Eval");
|
|
1128
|
+
if (result.eval) {
|
|
1129
|
+
const passRate = result.gates.evalAssertPassRate ?? 0;
|
|
1130
|
+
lines.push(
|
|
1131
|
+
`- ${evalGate} assertion pass rate=${formatPercent(passRate)} (${result.eval.summary.passedAssertions}/${result.eval.summary.totalAssertions})`
|
|
1132
|
+
);
|
|
1133
|
+
for (const promptResult of result.eval.results) {
|
|
1134
|
+
const failedAssertions = promptResult.assertions.filter((assertion) => !assertion.passed);
|
|
1135
|
+
if (!verbose && failedAssertions.length === 0) {
|
|
1136
|
+
continue;
|
|
1137
|
+
}
|
|
1138
|
+
lines.push(` - prompt: ${promptResult.prompt}`);
|
|
1139
|
+
lines.push(` response summary: ${promptResult.responseSummary.replace(/\s+/g, " ").trim()}`);
|
|
1140
|
+
const assertionsToRender = verbose ? promptResult.assertions : failedAssertions;
|
|
1141
|
+
for (const assertion of assertionsToRender) {
|
|
1142
|
+
const assertionStatus = assertion.passed ? c.green("PASS") : c.red("FAIL");
|
|
1143
|
+
lines.push(` ${assertionStatus} ${assertion.assertion}`);
|
|
1144
|
+
lines.push(` evidence: ${assertion.evidence}`);
|
|
1145
|
+
}
|
|
1146
|
+
if (verbose) {
|
|
1147
|
+
lines.push(` full response: ${promptResult.response}`);
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
} else {
|
|
1151
|
+
lines.push(`- ${evalGate} ${result.evalSkippedReason ?? "Skipped."}`);
|
|
1152
|
+
}
|
|
1153
|
+
lines.push("");
|
|
1154
|
+
lines.push("Quality Gate");
|
|
1155
|
+
lines.push(`- lint gate: ${lintGate}`);
|
|
1156
|
+
lines.push(`- trigger gate: ${triggerGate}`);
|
|
1157
|
+
lines.push(`- eval gate: ${evalGate}`);
|
|
1158
|
+
lines.push(`- overall: ${overallGate}`);
|
|
1159
|
+
return lines.join("\n");
|
|
1160
|
+
}
|
|
1079
1161
|
|
|
1080
1162
|
// src/reporters/json.ts
|
|
1081
1163
|
function renderJson(value) {
|
|
@@ -1835,6 +1917,213 @@ function registerEvalCommand(program) {
|
|
|
1835
1917
|
});
|
|
1836
1918
|
}
|
|
1837
1919
|
|
|
1920
|
+
// src/commands/check.ts
|
|
1921
|
+
import ora3 from "ora";
|
|
1922
|
+
import { z as z7 } from "zod";
|
|
1923
|
+
|
|
1924
|
+
// src/core/check-runner.ts
|
|
1925
|
+
function calculateEvalAssertPassRate(result) {
|
|
1926
|
+
if (result.summary.totalAssertions === 0) {
|
|
1927
|
+
return 0;
|
|
1928
|
+
}
|
|
1929
|
+
return result.summary.passedAssertions / result.summary.totalAssertions;
|
|
1930
|
+
}
|
|
1931
|
+
async function runCheck(inputPath, options) {
|
|
1932
|
+
options.onStage?.("lint");
|
|
1933
|
+
const lint = await runLinter(inputPath);
|
|
1934
|
+
const lintPassed = lint.summary.failures === 0;
|
|
1935
|
+
let trigger = null;
|
|
1936
|
+
let evalResult = null;
|
|
1937
|
+
let triggerSkippedReason;
|
|
1938
|
+
let evalSkippedReason;
|
|
1939
|
+
if (!lintPassed && !options.continueOnLintFail) {
|
|
1940
|
+
triggerSkippedReason = "Skipped because lint has failures (use --continue-on-lint-fail to override).";
|
|
1941
|
+
evalSkippedReason = "Skipped because lint has failures (use --continue-on-lint-fail to override).";
|
|
1942
|
+
} else {
|
|
1943
|
+
options.onStage?.("parse");
|
|
1944
|
+
let parsedSkill = null;
|
|
1945
|
+
try {
|
|
1946
|
+
parsedSkill = await parseSkillStrict(inputPath);
|
|
1947
|
+
} catch (error) {
|
|
1948
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1949
|
+
triggerSkippedReason = `Skipped: skill could not be parsed strictly (${message}).`;
|
|
1950
|
+
evalSkippedReason = `Skipped: skill could not be parsed strictly (${message}).`;
|
|
1951
|
+
}
|
|
1952
|
+
if (parsedSkill) {
|
|
1953
|
+
options.onStage?.("trigger");
|
|
1954
|
+
trigger = await runTriggerTest(parsedSkill, {
|
|
1955
|
+
provider: options.provider,
|
|
1956
|
+
model: options.model,
|
|
1957
|
+
queries: options.queries,
|
|
1958
|
+
numQueries: options.numQueries,
|
|
1959
|
+
verbose: options.verbose
|
|
1960
|
+
});
|
|
1961
|
+
options.onStage?.("eval");
|
|
1962
|
+
evalResult = await runEval(parsedSkill, {
|
|
1963
|
+
provider: options.provider,
|
|
1964
|
+
model: options.model,
|
|
1965
|
+
graderModel: options.graderModel,
|
|
1966
|
+
prompts: options.prompts
|
|
1967
|
+
});
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
const triggerF1 = trigger ? trigger.metrics.f1 : null;
|
|
1971
|
+
const evalAssertPassRate = evalResult ? calculateEvalAssertPassRate(evalResult) : null;
|
|
1972
|
+
const triggerPassed = triggerF1 === null ? null : triggerF1 >= options.minF1;
|
|
1973
|
+
const evalPassed = evalAssertPassRate === null ? null : evalAssertPassRate >= options.minAssertPassRate;
|
|
1974
|
+
const overallPassed = lintPassed && triggerPassed === true && evalPassed === true;
|
|
1975
|
+
return {
|
|
1976
|
+
target: inputPath,
|
|
1977
|
+
provider: options.provider.name,
|
|
1978
|
+
model: options.model,
|
|
1979
|
+
graderModel: options.graderModel,
|
|
1980
|
+
thresholds: {
|
|
1981
|
+
minF1: options.minF1,
|
|
1982
|
+
minAssertPassRate: options.minAssertPassRate
|
|
1983
|
+
},
|
|
1984
|
+
continueOnLintFail: options.continueOnLintFail,
|
|
1985
|
+
lint,
|
|
1986
|
+
trigger,
|
|
1987
|
+
eval: evalResult,
|
|
1988
|
+
triggerSkippedReason,
|
|
1989
|
+
evalSkippedReason,
|
|
1990
|
+
gates: {
|
|
1991
|
+
lintPassed,
|
|
1992
|
+
triggerPassed,
|
|
1993
|
+
evalPassed,
|
|
1994
|
+
triggerF1,
|
|
1995
|
+
evalAssertPassRate,
|
|
1996
|
+
overallPassed
|
|
1997
|
+
}
|
|
1998
|
+
};
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
// src/commands/check.ts
|
|
2002
|
+
var checkOptionsSchema = z7.object({
|
|
2003
|
+
provider: z7.enum(["anthropic", "openai"]),
|
|
2004
|
+
model: z7.string(),
|
|
2005
|
+
graderModel: z7.string().optional(),
|
|
2006
|
+
apiKey: z7.string().optional(),
|
|
2007
|
+
queries: z7.string().optional(),
|
|
2008
|
+
numQueries: z7.number().int().min(2),
|
|
2009
|
+
prompts: z7.string().optional(),
|
|
2010
|
+
minF1: z7.number().min(0).max(1),
|
|
2011
|
+
minAssertPassRate: z7.number().min(0).max(1),
|
|
2012
|
+
saveResults: z7.string().optional(),
|
|
2013
|
+
continueOnLintFail: z7.boolean().optional(),
|
|
2014
|
+
verbose: z7.boolean().optional()
|
|
2015
|
+
});
|
|
2016
|
+
var DEFAULT_ANTHROPIC_MODEL3 = "claude-sonnet-4-5-20250929";
|
|
2017
|
+
var DEFAULT_OPENAI_MODEL3 = "gpt-4.1-mini";
|
|
2018
|
+
function resolveModel3(provider, model) {
|
|
2019
|
+
if (provider === "openai" && model === DEFAULT_ANTHROPIC_MODEL3) {
|
|
2020
|
+
return DEFAULT_OPENAI_MODEL3;
|
|
2021
|
+
}
|
|
2022
|
+
return model;
|
|
2023
|
+
}
|
|
2024
|
+
function registerCheckCommand(program) {
|
|
2025
|
+
program.command("check").description("Run lint + trigger + eval with threshold-based quality gates.").argument("<path-to-skill>", "Path to SKILL.md or skill directory").option("--provider <provider>", "LLM provider: anthropic|openai", "anthropic").option("--model <model>", "Model for trigger/eval runs", DEFAULT_ANTHROPIC_MODEL3).option("--grader-model <model>", "Model used for grading (defaults to --model)").option("--api-key <key>", "API key override").option("--queries <path>", "Path to custom trigger queries JSON").option("--num-queries <n>", "Number of auto-generated trigger queries", (value) => Number.parseInt(value, 10), 20).option("--prompts <path>", "Path to eval prompts JSON").option("--min-f1 <n>", "Minimum required trigger F1 score (0-1)", (value) => Number.parseFloat(value), 0.8).option(
|
|
2026
|
+
"--min-assert-pass-rate <n>",
|
|
2027
|
+
"Minimum required eval assertion pass rate (0-1)",
|
|
2028
|
+
(value) => Number.parseFloat(value),
|
|
2029
|
+
0.9
|
|
2030
|
+
).option("--save-results <path>", "Save combined check results to JSON").option("--continue-on-lint-fail", "Continue trigger/eval stages even when lint has failures").option("--verbose", "Show detailed trigger/eval output sections").action(async (targetPath, commandOptions, command) => {
|
|
2031
|
+
const globalOptions = getGlobalCliOptions(command);
|
|
2032
|
+
const parsedOptions = checkOptionsSchema.safeParse(commandOptions);
|
|
2033
|
+
if (!parsedOptions.success) {
|
|
2034
|
+
writeError(new Error(parsedOptions.error.issues[0]?.message ?? "Invalid check options."), globalOptions.json);
|
|
2035
|
+
process.exitCode = 2;
|
|
2036
|
+
return;
|
|
2037
|
+
}
|
|
2038
|
+
const options = parsedOptions.data;
|
|
2039
|
+
if (options.numQueries % 2 !== 0) {
|
|
2040
|
+
writeError(
|
|
2041
|
+
new Error("--num-queries must be an even number so the suite can split should/should-not trigger cases."),
|
|
2042
|
+
globalOptions.json
|
|
2043
|
+
);
|
|
2044
|
+
process.exitCode = 2;
|
|
2045
|
+
return;
|
|
2046
|
+
}
|
|
2047
|
+
const spinner = globalOptions.json || !process.stdout.isTTY ? null : ora3("Preparing check run...").start();
|
|
2048
|
+
try {
|
|
2049
|
+
if (spinner) {
|
|
2050
|
+
spinner.text = "Initializing model provider...";
|
|
2051
|
+
}
|
|
2052
|
+
const provider = createProvider(options.provider, options.apiKey);
|
|
2053
|
+
let queries = void 0;
|
|
2054
|
+
if (options.queries) {
|
|
2055
|
+
if (spinner) {
|
|
2056
|
+
spinner.text = "Loading custom trigger queries...";
|
|
2057
|
+
}
|
|
2058
|
+
const loadedQueries = await readJsonFile(options.queries);
|
|
2059
|
+
const parsedQueries = triggerQueryArraySchema.safeParse(loadedQueries);
|
|
2060
|
+
if (!parsedQueries.success) {
|
|
2061
|
+
throw new Error(
|
|
2062
|
+
`Invalid --queries JSON: ${parsedQueries.error.issues[0]?.message ?? "unknown format issue"}`
|
|
2063
|
+
);
|
|
2064
|
+
}
|
|
2065
|
+
queries = parsedQueries.data;
|
|
2066
|
+
}
|
|
2067
|
+
let prompts = void 0;
|
|
2068
|
+
if (options.prompts) {
|
|
2069
|
+
if (spinner) {
|
|
2070
|
+
spinner.text = "Loading eval prompts...";
|
|
2071
|
+
}
|
|
2072
|
+
const loadedPrompts = await readJsonFile(options.prompts);
|
|
2073
|
+
const parsedPrompts = evalPromptArraySchema.safeParse(loadedPrompts);
|
|
2074
|
+
if (!parsedPrompts.success) {
|
|
2075
|
+
throw new Error(
|
|
2076
|
+
`Invalid --prompts JSON: ${parsedPrompts.error.issues[0]?.message ?? "unknown format issue"}`
|
|
2077
|
+
);
|
|
2078
|
+
}
|
|
2079
|
+
prompts = parsedPrompts.data;
|
|
2080
|
+
}
|
|
2081
|
+
const model = resolveModel3(options.provider, options.model);
|
|
2082
|
+
const graderModel = options.graderModel ?? model;
|
|
2083
|
+
const result = await runCheck(targetPath, {
|
|
2084
|
+
provider,
|
|
2085
|
+
model,
|
|
2086
|
+
graderModel,
|
|
2087
|
+
queries,
|
|
2088
|
+
numQueries: options.numQueries,
|
|
2089
|
+
prompts,
|
|
2090
|
+
minF1: options.minF1,
|
|
2091
|
+
minAssertPassRate: options.minAssertPassRate,
|
|
2092
|
+
continueOnLintFail: Boolean(options.continueOnLintFail),
|
|
2093
|
+
verbose: Boolean(options.verbose),
|
|
2094
|
+
onStage: (stage) => {
|
|
2095
|
+
if (!spinner) {
|
|
2096
|
+
return;
|
|
2097
|
+
}
|
|
2098
|
+
if (stage === "lint") {
|
|
2099
|
+
spinner.text = "Running lint checks...";
|
|
2100
|
+
} else if (stage === "parse") {
|
|
2101
|
+
spinner.text = "Parsing skill for model evaluations...";
|
|
2102
|
+
} else if (stage === "trigger") {
|
|
2103
|
+
spinner.text = "Running trigger test suite...";
|
|
2104
|
+
} else if (stage === "eval") {
|
|
2105
|
+
spinner.text = "Running end-to-end eval suite...";
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
});
|
|
2109
|
+
if (options.saveResults) {
|
|
2110
|
+
await writeJsonFile(options.saveResults, result);
|
|
2111
|
+
}
|
|
2112
|
+
spinner?.stop();
|
|
2113
|
+
if (globalOptions.json) {
|
|
2114
|
+
writeResult(result, true);
|
|
2115
|
+
} else {
|
|
2116
|
+
writeResult(renderCheckReport(result, globalOptions.color, Boolean(options.verbose)), false);
|
|
2117
|
+
}
|
|
2118
|
+
process.exitCode = result.gates.overallPassed ? 0 : 1;
|
|
2119
|
+
} catch (error) {
|
|
2120
|
+
spinner?.stop();
|
|
2121
|
+
writeError(error, globalOptions.json);
|
|
2122
|
+
process.exitCode = 2;
|
|
2123
|
+
}
|
|
2124
|
+
});
|
|
2125
|
+
}
|
|
2126
|
+
|
|
1838
2127
|
// src/index.ts
|
|
1839
2128
|
function resolveVersion() {
|
|
1840
2129
|
try {
|
|
@@ -1853,6 +2142,7 @@ async function run(argv) {
|
|
|
1853
2142
|
registerLintCommand(program);
|
|
1854
2143
|
registerTriggerCommand(program);
|
|
1855
2144
|
registerEvalCommand(program);
|
|
2145
|
+
registerCheckCommand(program);
|
|
1856
2146
|
await program.parseAsync(argv);
|
|
1857
2147
|
}
|
|
1858
2148
|
run(process.argv).catch((error) => {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/core/skill-parser.ts","../src/core/linter/compat.ts","../src/core/linter/content.ts","../src/core/linter/disclosure.ts","../src/utils/fs.ts","../src/core/linter/frontmatter.ts","../src/core/linter/security.ts","../src/core/linter/structure.ts","../src/core/linter/index.ts","../src/reporters/terminal.ts","../src/reporters/json.ts","../src/commands/common.ts","../src/commands/lint.ts","../src/commands/trigger.ts","../src/core/trigger-tester.ts","../src/utils/config.ts","../src/providers/anthropic.ts","../src/providers/openai.ts","../src/providers/index.ts","../src/commands/eval.ts","../src/core/eval-runner.ts","../src/core/grader.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { Command } from \"commander\";\nimport { registerLintCommand } from \"./commands/lint.js\";\nimport { registerTriggerCommand } from \"./commands/trigger.js\";\nimport { registerEvalCommand } from \"./commands/eval.js\";\n\nfunction resolveVersion(): string {\n try {\n const currentFilePath = fileURLToPath(import.meta.url);\n const packageJsonPath = path.resolve(path.dirname(currentFilePath), \"..\", \"package.json\");\n const raw = fs.readFileSync(packageJsonPath, \"utf8\");\n const parsed = JSON.parse(raw) as { version?: string };\n return parsed.version ?? \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\n\nexport async function run(argv: string[]): Promise<void> {\n const program = new Command();\n program\n .name(\"skilltest\")\n .description(\"The testing framework for Agent Skills.\")\n .version(resolveVersion())\n .option(\"--json\", \"Output results as JSON\")\n .option(\"--no-color\", \"Disable colored output\")\n .showHelpAfterError();\n\n registerLintCommand(program);\n registerTriggerCommand(program);\n registerEvalCommand(program);\n\n await program.parseAsync(argv);\n}\n\nrun(process.argv).catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`Error: ${message}\\n`);\n process.exitCode = 2;\n});\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport matter from \"gray-matter\";\nimport yaml from \"js-yaml\";\nimport { z } from \"zod\";\n\nexport interface SkillFileContext {\n skillRoot: string;\n skillFile: string;\n raw: string;\n lineCount: number;\n}\n\nexport interface FrontmatterParseResult {\n hasFrontmatter: boolean;\n rawFrontmatter: string | null;\n data: Record<string, unknown> | null;\n content: string;\n error: string | null;\n}\n\nconst frontmatterSchema = z\n .object({\n name: z.string(),\n description: z.string(),\n license: z.string().optional()\n })\n .passthrough();\n\nexport type SkillFrontmatter = z.infer<typeof frontmatterSchema>;\n\nexport interface ParsedSkill {\n skillRoot: string;\n skillFile: string;\n raw: string;\n content: string;\n frontmatterRaw: string | null;\n frontmatter: SkillFrontmatter;\n}\n\nconst FRONTMATTER_BLOCK_REGEX = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?/;\n\nexport async function resolveSkillPath(inputPath: string): Promise<{ skillRoot: string; skillFile: string }> {\n const absoluteInput = path.resolve(inputPath);\n let stat;\n\n try {\n stat = await fs.stat(absoluteInput);\n } catch {\n throw new Error(`Path not found: ${inputPath}`);\n }\n\n if (stat.isDirectory()) {\n const skillFile = path.join(absoluteInput, \"SKILL.md\");\n try {\n const skillStat = await fs.stat(skillFile);\n if (!skillStat.isFile()) {\n throw new Error();\n }\n } catch {\n throw new Error(`No SKILL.md found in directory: ${inputPath}`);\n }\n\n return { skillRoot: absoluteInput, skillFile };\n }\n\n if (!stat.isFile()) {\n throw new Error(`Path is not a file or directory: ${inputPath}`);\n }\n\n if (path.basename(absoluteInput) !== \"SKILL.md\") {\n throw new Error(`Expected SKILL.md or a directory containing SKILL.md. Received: ${inputPath}`);\n }\n\n return { skillRoot: path.dirname(absoluteInput), skillFile: absoluteInput };\n}\n\nexport async function loadSkillFile(inputPath: string): Promise<SkillFileContext> {\n const { skillRoot, skillFile } = await resolveSkillPath(inputPath);\n const raw = await fs.readFile(skillFile, \"utf8\");\n const lineCount = raw === \"\" ? 0 : raw.split(/\\r?\\n/).length;\n\n return { skillRoot, skillFile, raw, lineCount };\n}\n\nexport function parseFrontmatter(rawSkill: string): FrontmatterParseResult {\n const blockMatch = rawSkill.match(FRONTMATTER_BLOCK_REGEX);\n const rawFrontmatter = blockMatch?.[1] ?? null;\n\n if (!rawFrontmatter) {\n return {\n hasFrontmatter: false,\n rawFrontmatter: null,\n data: null,\n content: rawSkill,\n error: null\n };\n }\n\n try {\n const parsedByYaml = yaml.load(rawFrontmatter);\n if (parsedByYaml === null || typeof parsedByYaml !== \"object\" || Array.isArray(parsedByYaml)) {\n return {\n hasFrontmatter: true,\n rawFrontmatter,\n data: null,\n content: rawSkill.replace(FRONTMATTER_BLOCK_REGEX, \"\"),\n error: \"Frontmatter must parse into a YAML object.\"\n };\n }\n\n const parsedByMatter = matter(rawSkill);\n return {\n hasFrontmatter: true,\n rawFrontmatter,\n data: parsedByMatter.data as Record<string, unknown>,\n content: parsedByMatter.content,\n error: null\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Unknown frontmatter parse error\";\n return {\n hasFrontmatter: true,\n rawFrontmatter,\n data: null,\n content: rawSkill.replace(FRONTMATTER_BLOCK_REGEX, \"\"),\n error: message\n };\n }\n}\n\nexport async function parseSkillStrict(inputPath: string): Promise<ParsedSkill> {\n const skillContext = await loadSkillFile(inputPath);\n const parsedFrontmatter = parseFrontmatter(skillContext.raw);\n\n if (!parsedFrontmatter.hasFrontmatter) {\n throw new Error(\"SKILL.md is missing YAML frontmatter.\");\n }\n\n if (parsedFrontmatter.error) {\n throw new Error(`Invalid frontmatter: ${parsedFrontmatter.error}`);\n }\n\n const validation = frontmatterSchema.safeParse(parsedFrontmatter.data ?? {});\n if (!validation.success) {\n const issue = validation.error.issues[0];\n throw new Error(`Invalid frontmatter field '${issue.path.join(\".\")}': ${issue.message}`);\n }\n\n return {\n skillRoot: skillContext.skillRoot,\n skillFile: skillContext.skillFile,\n raw: skillContext.raw,\n content: parsedFrontmatter.content,\n frontmatterRaw: parsedFrontmatter.rawFrontmatter,\n frontmatter: validation.data\n };\n}\n\nconst RELATIVE_LINK_PREFIXES = [\"./\", \"../\", \"scripts/\", \"references/\", \"assets/\"];\n\nexport function extractRelativeFileReferences(markdown: string): string[] {\n const references = new Set<string>();\n\n const markdownLinkRegex = /\\[[^\\]]+\\]\\(([^)]+)\\)/g;\n for (const match of markdown.matchAll(markdownLinkRegex)) {\n const rawTarget = (match[1] ?? \"\").trim();\n const cleaned = cleanReferenceTarget(rawTarget);\n if (cleaned && isLikelyRelativePath(cleaned)) {\n references.add(cleaned);\n }\n }\n\n const inlineCodeRegex = /`([^`]+)`/g;\n for (const match of markdown.matchAll(inlineCodeRegex)) {\n const candidate = (match[1] ?? \"\").trim();\n if (isLikelyRelativePath(candidate)) {\n references.add(cleanReferenceTarget(candidate) as string);\n }\n }\n\n const barePathRegex = /\\b(?:scripts|references|assets)\\/[A-Za-z0-9._\\-/]+/g;\n for (const match of markdown.matchAll(barePathRegex)) {\n const candidate = match[0];\n if (candidate) {\n references.add(cleanReferenceTarget(candidate) as string);\n }\n }\n\n return Array.from(references);\n}\n\nexport function cleanReferenceTarget(target: string): string | null {\n if (!target) {\n return null;\n }\n\n let cleaned = target.trim();\n\n if (cleaned.startsWith(\"<\") && cleaned.endsWith(\">\")) {\n cleaned = cleaned.slice(1, -1).trim();\n }\n\n if (cleaned === \"\" || cleaned.startsWith(\"#\")) {\n return null;\n }\n\n if (/^(https?:|mailto:|tel:)/i.test(cleaned)) {\n return null;\n }\n\n const hashIndex = cleaned.indexOf(\"#\");\n if (hashIndex >= 0) {\n cleaned = cleaned.slice(0, hashIndex).trim();\n }\n\n return cleaned || null;\n}\n\nexport function isLikelyRelativePath(candidate: string): boolean {\n if (!candidate) {\n return false;\n }\n\n if (candidate.startsWith(\"/\")) {\n return false;\n }\n\n if (/^[A-Za-z]:\\\\/.test(candidate)) {\n return false;\n }\n\n if (/^(https?:|mailto:|tel:)/i.test(candidate)) {\n return false;\n }\n\n if (RELATIVE_LINK_PREFIXES.some((prefix) => candidate.startsWith(prefix))) {\n return true;\n }\n\n return /^[A-Za-z0-9._-]+(?:\\/[A-Za-z0-9._-]+)+$/.test(candidate);\n}\n","import { LintContext } from \"./context.js\";\nimport { LintIssue } from \"./types.js\";\n\nexport function runCompatibilityChecks(context: LintContext): LintIssue[] {\n const issues: LintIssue[] = [];\n const frontmatter = context.frontmatter.data ?? {};\n const body = context.frontmatter.content;\n\n const hasAllowedTools = Object.prototype.hasOwnProperty.call(frontmatter, \"allowed-tools\");\n const mentionsClaudeOnly = /\\bclaude code\\b/i.test(body);\n const mentionsCodexOnly = /\\bcodex\\b/i.test(body) && !/\\bopenai\\b/i.test(body);\n\n if (hasAllowedTools) {\n issues.push({\n id: \"compat.allowed-tools\",\n title: \"Platform-Specific Frontmatter\",\n status: \"warn\",\n message: \"Frontmatter includes allowed-tools, which is typically Claude-specific.\",\n suggestion: \"Document fallback behavior for platforms that ignore allowed-tools.\"\n });\n } else {\n issues.push({\n id: \"compat.allowed-tools\",\n title: \"Platform-Specific Frontmatter\",\n status: \"pass\",\n message: \"No known provider-specific frontmatter keys detected.\"\n });\n }\n\n if (mentionsClaudeOnly || mentionsCodexOnly) {\n const platform = mentionsClaudeOnly ? \"Claude\" : \"Codex\";\n issues.push({\n id: \"compat.provider-phrasing\",\n title: \"Provider-Specific Language\",\n status: \"warn\",\n message: `Skill body appears tuned to ${platform}-specific behavior.`,\n suggestion: \"Add neutral instructions or an explicit compatibility note for other agents.\"\n });\n } else {\n issues.push({\n id: \"compat.provider-phrasing\",\n title: \"Provider-Specific Language\",\n status: \"pass\",\n message: \"Skill body appears provider-neutral.\"\n });\n }\n\n const likelyCompatibility = hasAllowedTools || mentionsClaudeOnly || mentionsCodexOnly\n ? \"Likely compatible with some agents, but includes platform-specific assumptions.\"\n : \"Likely broadly compatible across Anthropic, OpenAI/Codex-style, and other markdown skill runners.\";\n\n issues.push({\n id: \"compat.summary\",\n title: \"Compatibility Hint\",\n status: hasAllowedTools || mentionsClaudeOnly || mentionsCodexOnly ? \"warn\" : \"pass\",\n message: likelyCompatibility\n });\n\n return issues;\n}\n","import { LintContext } from \"./context.js\";\nimport { LintIssue } from \"./types.js\";\n\nconst VAGUE_PATTERNS = [\n /\\bdo something appropriate\\b/i,\n /\\bhandle as needed\\b/i,\n /\\buse best judgment\\b/i,\n /\\bif possible\\b/i,\n /\\bwhen relevant\\b/i,\n /\\bdo what seems right\\b/i\n];\n\nconst SECRET_PATTERNS: Array<{ label: string; regex: RegExp }> = [\n { label: \"OpenAI key\", regex: /\\bsk-[A-Za-z0-9]{20,}\\b/ },\n { label: \"AWS access key\", regex: /\\bAKIA[0-9A-Z]{16}\\b/ },\n { label: \"GitHub token\", regex: /\\bghp_[A-Za-z0-9]{20,}\\b/ },\n { label: \"Slack token\", regex: /\\bxox[baprs]-[A-Za-z0-9-]{20,}\\b/ },\n { label: \"Generic private key header\", regex: /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/ }\n];\n\nexport function runContentChecks(context: LintContext): LintIssue[] {\n const issues: LintIssue[] = [];\n const body = context.frontmatter.content;\n const bodyLines = body\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n const description = typeof context.frontmatter.data?.description === \"string\" ? context.frontmatter.data.description : \"\";\n\n if (!/^#{1,6}\\s+\\S+/m.test(body)) {\n issues.push({\n id: \"content.headers\",\n title: \"Section Headers\",\n status: \"warn\",\n message: \"No markdown headers found in SKILL.md body.\",\n suggestion: \"Add section headers to improve scannability and maintenance.\"\n });\n } else {\n issues.push({\n id: \"content.headers\",\n title: \"Section Headers\",\n status: \"pass\",\n message: \"SKILL.md contains markdown section headers.\"\n });\n }\n\n const hasExamples = /example/i.test(body) || /```[\\s\\S]*?```/.test(body);\n if (!hasExamples) {\n issues.push({\n id: \"content.examples\",\n title: \"Examples\",\n status: \"warn\",\n message: \"No examples detected in SKILL.md body.\",\n suggestion: \"Add at least one concrete example to guide usage.\"\n });\n } else {\n issues.push({\n id: \"content.examples\",\n title: \"Examples\",\n status: \"pass\",\n message: \"Examples were detected in SKILL.md.\"\n });\n }\n\n const vagueMatches = VAGUE_PATTERNS.filter((pattern) => pattern.test(body));\n if (vagueMatches.length > 0) {\n issues.push({\n id: \"content.vagueness\",\n title: \"Instruction Specificity\",\n status: \"warn\",\n message: \"Potentially vague instruction phrases detected.\",\n suggestion: \"Replace vague guidance with explicit decision rules or step-by-step instructions.\"\n });\n } else {\n issues.push({\n id: \"content.vagueness\",\n title: \"Instruction Specificity\",\n status: \"pass\",\n message: \"No obvious vague placeholder phrasing found.\"\n });\n }\n\n if (context.frontmatter.rawFrontmatter && /[<>]/.test(context.frontmatter.rawFrontmatter)) {\n issues.push({\n id: \"content.frontmatter-angle-brackets\",\n title: \"Frontmatter Angle Brackets\",\n status: \"warn\",\n message: \"Frontmatter contains angle bracket characters (< or >), which can be misinterpreted in some agents.\",\n suggestion: \"Remove XML-like tags from frontmatter values when possible.\"\n });\n } else {\n issues.push({\n id: \"content.frontmatter-angle-brackets\",\n title: \"Frontmatter Angle Brackets\",\n status: \"pass\",\n message: \"No angle bracket tokens detected in frontmatter.\"\n });\n }\n\n const secretHits = new Set<string>();\n for (const pattern of SECRET_PATTERNS) {\n if (pattern.regex.test(context.skill.raw)) {\n secretHits.add(pattern.label);\n }\n }\n if (secretHits.size > 0) {\n issues.push({\n id: \"content.secrets\",\n title: \"Hardcoded Secrets\",\n status: \"fail\",\n message: `Potential secrets detected (${Array.from(secretHits).join(\", \")}).`,\n suggestion: \"Remove secrets from skill files and use environment variables or secret managers.\"\n });\n } else {\n issues.push({\n id: \"content.secrets\",\n title: \"Hardcoded Secrets\",\n status: \"pass\",\n message: \"No obvious API keys or secrets patterns were detected.\"\n });\n }\n\n if (bodyLines.length < 10) {\n issues.push({\n id: \"content.body-length\",\n title: \"Body Completeness\",\n status: \"warn\",\n message: `SKILL.md body has only ${bodyLines.length} non-empty lines.`,\n suggestion: \"Add more detailed instructions; short bodies are often incomplete.\"\n });\n } else {\n issues.push({\n id: \"content.body-length\",\n title: \"Body Completeness\",\n status: \"pass\",\n message: `SKILL.md body has ${bodyLines.length} non-empty lines.`\n });\n }\n\n if (description && description.length < 50) {\n issues.push({\n id: \"content.description-length\",\n title: \"Description Specificity\",\n status: \"warn\",\n message: `Description length is ${description.length} characters, which may be too vague for reliable triggering.`,\n suggestion: \"Expand description with concrete scope and activation conditions.\"\n });\n } else if (description) {\n issues.push({\n id: \"content.description-length\",\n title: \"Description Specificity\",\n status: \"pass\",\n message: \"Description length is sufficient for triggerability heuristics.\"\n });\n }\n\n return issues;\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport {\n cleanReferenceTarget,\n extractRelativeFileReferences,\n isLikelyRelativePath\n} from \"../skill-parser.js\";\nimport { pathExists, toPosixPath } from \"../../utils/fs.js\";\nimport { LintContext } from \"./context.js\";\nimport { LintIssue } from \"./types.js\";\n\nfunction isPathInsideRoot(root: string, candidate: string): boolean {\n const relative = path.relative(root, candidate);\n return !relative.startsWith(\"..\") && !path.isAbsolute(relative);\n}\n\nasync function detectNestedReferenceChain(skillRoot: string, rootContent: string): Promise<number> {\n const initialReferences = extractRelativeFileReferences(rootContent);\n let maxDepth = 0;\n\n for (const reference of initialReferences) {\n const firstLevelPath = path.resolve(skillRoot, reference);\n if (!(await pathExists(firstLevelPath))) {\n continue;\n }\n const firstLevelRaw = await fs.readFile(firstLevelPath, \"utf8\");\n const secondLevelRefs = extractRelativeFileReferences(firstLevelRaw);\n if (secondLevelRefs.length > 0) {\n maxDepth = Math.max(maxDepth, 1);\n }\n\n for (const secondLevelReference of secondLevelRefs) {\n const secondLevelPath = path.resolve(path.dirname(firstLevelPath), secondLevelReference);\n if (!(await pathExists(secondLevelPath))) {\n continue;\n }\n const secondLevelRaw = await fs.readFile(secondLevelPath, \"utf8\");\n const thirdLevelRefs = extractRelativeFileReferences(secondLevelRaw);\n if (thirdLevelRefs.length > 0) {\n maxDepth = Math.max(maxDepth, 2);\n }\n }\n }\n\n return maxDepth;\n}\n\nexport async function runDisclosureChecks(context: LintContext): Promise<LintIssue[]> {\n const issues: LintIssue[] = [];\n const references = extractRelativeFileReferences(context.skill.raw);\n const referencesDir = path.join(context.skill.skillRoot, \"references\");\n\n if (context.skill.lineCount > 200 && !(await pathExists(referencesDir))) {\n issues.push({\n id: \"disclosure.skill-split\",\n title: \"Progressive Disclosure\",\n status: \"warn\",\n message: \"SKILL.md exceeds 200 lines and no references/ directory is present.\",\n suggestion: \"Move detailed material into references/ files and keep SKILL.md focused.\"\n });\n } else {\n issues.push({\n id: \"disclosure.skill-split\",\n title: \"Progressive Disclosure\",\n status: \"pass\",\n message: \"Top-level file length and references/ usage look reasonable.\"\n });\n }\n\n const nonRelativeOrEscaping: string[] = [];\n for (const rawReference of references) {\n const cleaned = cleanReferenceTarget(rawReference);\n if (!cleaned) {\n continue;\n }\n if (path.isAbsolute(cleaned) || /^[A-Za-z]:\\\\/.test(cleaned) || cleaned.startsWith(\"~\")) {\n nonRelativeOrEscaping.push(cleaned);\n continue;\n }\n if (!isLikelyRelativePath(cleaned)) {\n nonRelativeOrEscaping.push(cleaned);\n continue;\n }\n const resolved = path.resolve(context.skill.skillRoot, cleaned);\n if (!isPathInsideRoot(context.skill.skillRoot, resolved)) {\n nonRelativeOrEscaping.push(cleaned);\n }\n }\n\n if (nonRelativeOrEscaping.length > 0) {\n issues.push({\n id: \"disclosure.relative-path-root\",\n title: \"Reference Path Scope\",\n status: \"fail\",\n message: `Found non-relative or out-of-root references: ${nonRelativeOrEscaping.join(\", \")}`,\n suggestion: \"Use relative paths that stay within the skill root directory.\"\n });\n } else {\n issues.push({\n id: \"disclosure.relative-path-root\",\n title: \"Reference Path Scope\",\n status: \"pass\",\n message: \"All detected file references are relative and scoped to skill root.\"\n });\n }\n\n const chainDepth = await detectNestedReferenceChain(context.skill.skillRoot, context.skill.raw);\n if (chainDepth > 1) {\n issues.push({\n id: \"disclosure.reference-depth\",\n title: \"Reference Chain Depth\",\n status: \"warn\",\n message: \"Deep reference chains detected (>1 level).\",\n suggestion: \"Avoid linking from references to more nested references where possible.\"\n });\n } else {\n issues.push({\n id: \"disclosure.reference-depth\",\n title: \"Reference Chain Depth\",\n status: \"pass\",\n message: \"Reference depth is shallow and easy to navigate.\"\n });\n }\n\n const normalizedReferences = references.map((item) => toPosixPath(item));\n if (normalizedReferences.some((item) => item.includes(\"../\"))) {\n issues.push({\n id: \"disclosure.parent-traversal\",\n title: \"Parent Traversal\",\n status: \"warn\",\n message: \"References include parent-directory traversal (../).\",\n suggestion: \"Prefer references rooted within the skill directory for portability.\"\n });\n } else {\n issues.push({\n id: \"disclosure.parent-traversal\",\n title: \"Parent Traversal\",\n status: \"pass\",\n message: \"No parent-directory traversal references detected.\"\n });\n }\n\n return issues;\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nexport async function pathExists(targetPath: string): Promise<boolean> {\n try {\n await fs.access(targetPath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function listFilesRecursive(directory: string): Promise<string[]> {\n const entries = await fs.readdir(directory, { withFileTypes: true });\n const files: string[] = [];\n\n for (const entry of entries) {\n const absolutePath = path.join(directory, entry.name);\n if (entry.isDirectory()) {\n files.push(...(await listFilesRecursive(absolutePath)));\n continue;\n }\n if (entry.isFile()) {\n files.push(absolutePath);\n }\n }\n\n return files;\n}\n\nexport async function readJsonFile<T>(filePath: string): Promise<T> {\n const raw = await fs.readFile(filePath, \"utf8\");\n return JSON.parse(raw) as T;\n}\n\nexport async function writeJsonFile(filePath: string, data: unknown): Promise<void> {\n const absolute = path.resolve(filePath);\n await fs.mkdir(path.dirname(absolute), { recursive: true });\n await fs.writeFile(absolute, `${JSON.stringify(data, null, 2)}\\n`, \"utf8\");\n}\n\nexport function toPosixPath(inputPath: string): string {\n return inputPath.split(path.sep).join(\"/\");\n}\n","import { LintContext } from \"./context.js\";\nimport { LintIssue } from \"./types.js\";\n\nconst SKILL_NAME_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\nfunction getStringField(data: Record<string, unknown> | null, key: string): string | null {\n if (!data) {\n return null;\n }\n const value = data[key];\n if (typeof value !== \"string\") {\n return null;\n }\n return value;\n}\n\nfunction descriptionLooksActionable(description: string): boolean {\n const whatPattern =\n /\\b(create|build|generate|analyze|test|validate|review|refactor|debug|audit|compose|transform|summari[sz]e|plan)\\b/i;\n const whenPattern = /\\b(when|if|for|whenever|use this|ideal for|best for|should use)\\b/i;\n return whatPattern.test(description) && whenPattern.test(description);\n}\n\nexport function runFrontmatterChecks(context: LintContext): LintIssue[] {\n const issues: LintIssue[] = [];\n\n if (!context.frontmatter.hasFrontmatter) {\n issues.push({\n id: \"frontmatter.exists\",\n title: \"Frontmatter Presence\",\n status: \"fail\",\n message: \"SKILL.md is missing YAML frontmatter delimited by --- blocks.\",\n suggestion: \"Add YAML frontmatter at the top with at least name and description.\"\n });\n return issues;\n }\n\n if (context.frontmatter.error) {\n issues.push({\n id: \"frontmatter.valid-yaml\",\n title: \"Frontmatter YAML\",\n status: \"fail\",\n message: `Frontmatter is not valid YAML: ${context.frontmatter.error}`,\n suggestion: \"Fix YAML syntax so the frontmatter parses as an object.\"\n });\n return issues;\n }\n\n issues.push({\n id: \"frontmatter.valid-yaml\",\n title: \"Frontmatter YAML\",\n status: \"pass\",\n message: \"Frontmatter exists and parses correctly.\"\n });\n\n const data = context.frontmatter.data ?? {};\n const name = getStringField(data, \"name\");\n if (!name) {\n issues.push({\n id: \"frontmatter.name.required\",\n title: \"Frontmatter Name\",\n status: \"fail\",\n message: \"Missing required frontmatter field: name.\",\n suggestion: \"Set name to lowercase words separated by single hyphens.\"\n });\n } else if (name.length > 64) {\n issues.push({\n id: \"frontmatter.name.length\",\n title: \"Frontmatter Name Length\",\n status: \"fail\",\n message: `name is too long (${name.length} chars, max 64).`,\n suggestion: \"Shorten the skill name to 64 characters or fewer.\"\n });\n } else if (!SKILL_NAME_REGEX.test(name)) {\n issues.push({\n id: \"frontmatter.name.format\",\n title: \"Frontmatter Name Format\",\n status: \"fail\",\n message: \"name must be lowercase alphanumeric with single hyphen separators only.\",\n suggestion: \"Use format like 'api-tester' or 'code-review'.\"\n });\n } else {\n issues.push({\n id: \"frontmatter.name.valid\",\n title: \"Frontmatter Name\",\n status: \"pass\",\n message: \"name is present and follows naming conventions.\"\n });\n }\n\n const description = getStringField(data, \"description\");\n if (!description || description.trim() === \"\") {\n issues.push({\n id: \"frontmatter.description.required\",\n title: \"Frontmatter Description\",\n status: \"fail\",\n message: \"Missing required frontmatter field: description.\",\n suggestion: \"Add a clear description of what the skill does and when to use it.\"\n });\n } else if (description.length > 1024) {\n issues.push({\n id: \"frontmatter.description.length\",\n title: \"Frontmatter Description Length\",\n status: \"fail\",\n message: `description is too long (${description.length} chars, max 1024).`,\n suggestion: \"Keep description concise while still specific.\"\n });\n } else {\n issues.push({\n id: \"frontmatter.description.valid\",\n title: \"Frontmatter Description\",\n status: \"pass\",\n message: \"description is present and within allowed length.\"\n });\n }\n\n const license = getStringField(data, \"license\");\n if (!license || license.trim() === \"\") {\n issues.push({\n id: \"frontmatter.license.recommended\",\n title: \"Frontmatter License\",\n status: \"warn\",\n message: \"No license field found in frontmatter.\",\n suggestion: \"Add a license (for example: MIT) to clarify reuse terms.\"\n });\n } else {\n issues.push({\n id: \"frontmatter.license.present\",\n title: \"Frontmatter License\",\n status: \"pass\",\n message: \"license field is present.\"\n });\n }\n\n if (description && description.trim() !== \"\" && !descriptionLooksActionable(description)) {\n issues.push({\n id: \"frontmatter.description.triggerability\",\n title: \"Description Trigger Clarity\",\n status: \"warn\",\n message: \"Description should explain both what the skill does and when it should be used.\",\n suggestion: \"Include explicit 'use when...' language plus concrete capability wording.\"\n });\n } else if (description) {\n issues.push({\n id: \"frontmatter.description.triggerability\",\n title: \"Description Trigger Clarity\",\n status: \"pass\",\n message: \"Description appears to cover both capability and usage context.\"\n });\n }\n\n return issues;\n}\n","import { LintContext } from \"./context.js\";\nimport { LintIssue } from \"./types.js\";\n\ninterface SecurityPattern {\n label: string;\n regex: RegExp;\n}\n\nconst DANGEROUS_COMMAND_PATTERNS: SecurityPattern[] = [\n {\n label: \"Destructive recursive delete\",\n regex: /\\b(?:sudo\\s+)?rm\\s+-rf\\s+(?:\\/|\\*|~\\/|\\.\\.\\/)/i\n },\n {\n label: \"Forceful recursive remove in PowerShell\",\n regex: /\\bRemove-Item\\b[^\\n]*\\b-Recurse\\b[^\\n]*\\b-Force\\b/i\n },\n {\n label: \"Remote script piped directly to shell\",\n regex: /\\b(?:curl|wget|Invoke-WebRequest)\\b[^\\n|]{0,220}\\|\\s*(?:bash|sh|zsh|pwsh|powershell|iex)\\b/i\n }\n];\n\nconst EXFILTRATION_PATTERNS: SecurityPattern[] = [\n {\n label: \"Reading SSH private keys\",\n regex: /\\b(?:cat|type|get-content)\\b[^\\n]*\\.ssh\\/id_(?:rsa|ed25519)\\b/i\n },\n {\n label: \"Reading cloud credential files\",\n regex: /\\b(?:cat|type|get-content)\\b[^\\n]*(?:\\.aws\\/credentials|\\.npmrc|\\.netrc)\\b/i\n },\n {\n label: \"Explicit credential exfiltration\",\n regex: /\\b(?:send|upload|post|exfiltrat(?:e|ion))\\b[^\\n]{0,200}\\b(?:api[_ -]?key|token|secret|credential|\\.env|id_rsa)\\b/i\n }\n];\n\nconst PRIVILEGE_ESCALATION_PATTERNS: SecurityPattern[] = [\n {\n label: \"Uses sudo/root escalation\",\n regex: /\\b(?:sudo|run as root|administrator privileges)\\b/i\n },\n {\n label: \"Asks to disable sandboxing or approvals\",\n regex: /\\b(?:disable sandbox|without approval|skip approval|require_escalated)\\b/i\n },\n {\n label: \"Inline expression execution\",\n regex: /\\b(?:Invoke-Expression|iex)\\b/i\n }\n];\n\nconst SHELL_ACTIVITY_PATTERNS: RegExp[] = [\n /```(?:bash|sh|zsh|pwsh|powershell|cmd)\\b[\\s\\S]*?```/i,\n /\\b(?:bash|sh|pwsh|powershell|cmd(?:\\.exe)?)\\b/i,\n /\\b(?:npm|pnpm|yarn|pip|git|docker|kubectl)\\s+[A-Za-z0-9-]/i\n];\n\nconst SAFETY_GUARDRAIL_PATTERN =\n /\\b(?:ask before|confirm|approval|dry[- ]run|sandbox|least privilege|redact|never expose|do not reveal)\\b/i;\n\nfunction collectMatches(content: string, patterns: SecurityPattern[]): string[] {\n const matches: string[] = [];\n for (const pattern of patterns) {\n if (pattern.regex.test(content)) {\n matches.push(pattern.label);\n }\n }\n return matches;\n}\n\nexport function runSecurityChecks(context: LintContext): LintIssue[] {\n const issues: LintIssue[] = [];\n const skillText = context.skill.raw;\n\n const dangerousCommandHits = collectMatches(skillText, DANGEROUS_COMMAND_PATTERNS);\n if (dangerousCommandHits.length > 0) {\n issues.push({\n id: \"security.dangerous-command-patterns\",\n title: \"Dangerous Command Patterns\",\n status: \"fail\",\n message: `Potentially dangerous command instruction patterns found: ${dangerousCommandHits.join(\", \")}.`,\n suggestion: \"Remove destructive/pipe-exec command examples or wrap them with explicit safety constraints.\"\n });\n } else {\n issues.push({\n id: \"security.dangerous-command-patterns\",\n title: \"Dangerous Command Patterns\",\n status: \"pass\",\n message: \"No high-risk destructive or direct pipe-to-shell patterns detected.\"\n });\n }\n\n const exfiltrationHits = collectMatches(skillText, EXFILTRATION_PATTERNS);\n if (exfiltrationHits.length > 0) {\n issues.push({\n id: \"security.exfiltration-patterns\",\n title: \"Sensitive Data Exfiltration\",\n status: \"fail\",\n message: `Possible sensitive data exfiltration patterns found: ${exfiltrationHits.join(\", \")}.`,\n suggestion: \"Remove instructions that access or transmit secrets/credential files.\"\n });\n } else {\n issues.push({\n id: \"security.exfiltration-patterns\",\n title: \"Sensitive Data Exfiltration\",\n status: \"pass\",\n message: \"No obvious credential access/exfiltration instructions detected.\"\n });\n }\n\n const escalationHits = collectMatches(skillText, PRIVILEGE_ESCALATION_PATTERNS);\n if (escalationHits.length > 0) {\n issues.push({\n id: \"security.privilege-escalation\",\n title: \"Privilege Escalation Language\",\n status: \"warn\",\n message: `Potentially risky privilege/execution language detected: ${escalationHits.join(\", \")}.`,\n suggestion: \"Prefer least-privilege execution and explicit approval steps for elevated commands.\"\n });\n } else {\n issues.push({\n id: \"security.privilege-escalation\",\n title: \"Privilege Escalation Language\",\n status: \"pass\",\n message: \"No obvious privilege-escalation language detected.\"\n });\n }\n\n const hasShellActivity = SHELL_ACTIVITY_PATTERNS.some((pattern) => pattern.test(skillText));\n if (hasShellActivity && !SAFETY_GUARDRAIL_PATTERN.test(skillText)) {\n issues.push({\n id: \"security.safety-guardrails\",\n title: \"Execution Safety Guardrails\",\n status: \"warn\",\n message: \"Shell/tool execution is present, but no explicit safety guardrails were detected.\",\n suggestion: \"Add guidance such as approval requirements, dry-run mode, scope checks, and redaction rules.\"\n });\n } else {\n issues.push({\n id: \"security.safety-guardrails\",\n title: \"Execution Safety Guardrails\",\n status: \"pass\",\n message: hasShellActivity\n ? \"Shell/tool execution instructions include at least one safety guardrail.\"\n : \"No shell/tool execution instructions detected.\"\n });\n }\n\n return issues;\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { extractRelativeFileReferences } from \"../skill-parser.js\";\nimport { listFilesRecursive, pathExists, toPosixPath } from \"../../utils/fs.js\";\nimport { LintContext } from \"./context.js\";\nimport { LintIssue } from \"./types.js\";\n\nfunction hasTableOfContents(content: string): boolean {\n if (/^#{1,6}\\s+table of contents\\b/im.test(content)) {\n return true;\n }\n return /^\\s*[-*]\\s+\\[[^\\]]+\\]\\(#[^)]+\\)/im.test(content);\n}\n\nfunction classifyReferencePath(relativePath: string): \"scripts\" | \"references\" | \"assets\" | \"other\" {\n const normalized = toPosixPath(relativePath).replace(/^\\.\\//, \"\");\n if (normalized.startsWith(\"scripts/\")) {\n return \"scripts\";\n }\n if (normalized.startsWith(\"references/\")) {\n return \"references\";\n }\n if (normalized.startsWith(\"assets/\")) {\n return \"assets\";\n }\n return \"other\";\n}\n\nexport async function runStructureChecks(context: LintContext): Promise<LintIssue[]> {\n const issues: LintIssue[] = [];\n const references = extractRelativeFileReferences(context.skill.raw);\n\n if (context.skill.lineCount > 500) {\n issues.push({\n id: \"structure.skill-size\",\n title: \"SKILL.md Size\",\n status: \"warn\",\n message: `SKILL.md is ${context.skill.lineCount} lines (recommended max is 500).`,\n suggestion: \"Split detailed guidance into references/ files.\"\n });\n } else {\n issues.push({\n id: \"structure.skill-size\",\n title: \"SKILL.md Size\",\n status: \"pass\",\n message: `SKILL.md length is ${context.skill.lineCount} lines.`\n });\n }\n\n const referencesDir = path.join(context.skill.skillRoot, \"references\");\n if (await pathExists(referencesDir)) {\n const files = await listFilesRecursive(referencesDir);\n let oversizedWithoutToc = 0;\n for (const file of files) {\n const raw = await fs.readFile(file, \"utf8\");\n const lineCount = raw === \"\" ? 0 : raw.split(/\\r?\\n/).length;\n if (lineCount > 300 && !hasTableOfContents(raw)) {\n oversizedWithoutToc += 1;\n issues.push({\n id: `structure.references.toc.${toPosixPath(path.relative(context.skill.skillRoot, file))}`,\n title: \"Reference File Navigation\",\n status: \"warn\",\n message: `${toPosixPath(path.relative(context.skill.skillRoot, file))} is ${lineCount} lines and has no table of contents.`,\n suggestion: \"Add a table of contents for long reference files.\"\n });\n }\n }\n\n if (oversizedWithoutToc === 0) {\n issues.push({\n id: \"structure.references.toc\",\n title: \"Reference File Navigation\",\n status: \"pass\",\n message: \"No oversized reference files missing a table of contents.\"\n });\n }\n } else {\n issues.push({\n id: \"structure.references.toc\",\n title: \"Reference File Navigation\",\n status: \"pass\",\n message: \"No references/ directory found, so no long reference files to validate.\"\n });\n }\n\n const missingByType: Record<string, string[]> = {\n scripts: [],\n references: [],\n assets: [],\n other: []\n };\n\n for (const reference of references) {\n const resolved = path.resolve(context.skill.skillRoot, reference);\n if (!(await pathExists(resolved))) {\n const kind = classifyReferencePath(reference);\n missingByType[kind].push(reference);\n }\n }\n\n const categories: Array<{ key: \"scripts\" | \"references\" | \"assets\"; title: string }> = [\n { key: \"scripts\", title: \"Script References\" },\n { key: \"references\", title: \"Reference File Links\" },\n { key: \"assets\", title: \"Asset References\" }\n ];\n\n for (const category of categories) {\n const missing = missingByType[category.key];\n if (missing.length > 0) {\n issues.push({\n id: `structure.${category.key}.exists`,\n title: category.title,\n status: \"fail\",\n message: `Missing referenced ${category.key} file(s): ${missing.join(\", \")}`,\n suggestion: \"Create the files or fix the paths in SKILL.md.\"\n });\n } else {\n issues.push({\n id: `structure.${category.key}.exists`,\n title: category.title,\n status: \"pass\",\n message: `All referenced ${category.key} files exist.`\n });\n }\n }\n\n const missingGeneric = missingByType.other;\n if (missingGeneric.length > 0) {\n issues.push({\n id: \"structure.relative-links.broken\",\n title: \"Relative Links\",\n status: \"fail\",\n message: `Broken relative path reference(s): ${missingGeneric.join(\", \")}`,\n suggestion: \"Fix or remove broken file links.\"\n });\n } else {\n issues.push({\n id: \"structure.relative-links.broken\",\n title: \"Relative Links\",\n status: \"pass\",\n message: \"No broken generic relative file references were found.\"\n });\n }\n\n return issues;\n}\n","import { loadSkillFile, parseFrontmatter } from \"../skill-parser.js\";\nimport { runCompatibilityChecks } from \"./compat.js\";\nimport { LintContext } from \"./context.js\";\nimport { runContentChecks } from \"./content.js\";\nimport { runDisclosureChecks } from \"./disclosure.js\";\nimport { runFrontmatterChecks } from \"./frontmatter.js\";\nimport { runSecurityChecks } from \"./security.js\";\nimport { runStructureChecks } from \"./structure.js\";\nimport { LintIssue, LintReport, LintSummary } from \"./types.js\";\n\nfunction summarizeIssues(issues: LintIssue[]): LintSummary {\n const summary: LintSummary = {\n total: issues.length,\n passed: 0,\n warnings: 0,\n failures: 0\n };\n\n for (const issue of issues) {\n if (issue.status === \"pass\") {\n summary.passed += 1;\n continue;\n }\n if (issue.status === \"warn\") {\n summary.warnings += 1;\n continue;\n }\n summary.failures += 1;\n }\n\n return summary;\n}\n\nexport async function runLinter(inputPath: string): Promise<LintReport> {\n const skill = await loadSkillFile(inputPath);\n const frontmatter = parseFrontmatter(skill.raw);\n const context: LintContext = {\n skill,\n frontmatter\n };\n\n const issues: LintIssue[] = [];\n issues.push(...runFrontmatterChecks(context));\n issues.push(...(await runStructureChecks(context)));\n issues.push(...runContentChecks(context));\n issues.push(...runSecurityChecks(context));\n issues.push(...(await runDisclosureChecks(context)));\n issues.push(...runCompatibilityChecks(context));\n\n return {\n target: inputPath,\n issues,\n summary: summarizeIssues(issues)\n };\n}\n\nexport type { LintIssue, LintReport, LintSummary } from \"./types.js\";\n","import { Chalk, ChalkInstance } from \"chalk\";\nimport { LintIssue, LintReport } from \"../core/linter/index.js\";\nimport { TriggerTestResult } from \"../core/trigger-tester.js\";\nimport { EvalResult } from \"../core/eval-runner.js\";\n\nfunction getChalkInstance(enableColor: boolean): ChalkInstance {\n return new Chalk({ level: enableColor ? 1 : 0 });\n}\n\nfunction renderIssueLine(issue: LintIssue, c: ChalkInstance): string {\n const label =\n issue.status === \"pass\" ? c.green(\"PASS\") : issue.status === \"warn\" ? c.yellow(\"WARN\") : c.red(\"FAIL\");\n const detail = issue.suggestion ? `\\n suggestion: ${issue.suggestion}` : \"\";\n return ` ${label} ${issue.title}\\n ${issue.message}${detail}`;\n}\n\nexport function renderLintReport(report: LintReport, enableColor: boolean): string {\n const c = getChalkInstance(enableColor);\n const { passed, warnings, failures, total } = report.summary;\n\n const headerLines = [\n `┌───────────────────────────────────────────────────────────────┐`,\n `│ skilltest lint │`,\n `├───────────────────────────────────────────────────────────────┤`,\n `│ target: ${report.target}`,\n `│ summary: ${passed}/${total} checks passed, ${warnings} warnings, ${failures} failures`,\n `└───────────────────────────────────────────────────────────────┘`\n ];\n\n const renderedIssues = report.issues.map((issue) => renderIssueLine(issue, c)).join(\"\\n\");\n return `${headerLines.join(\"\\n\")}\\n${renderedIssues}`;\n}\n\nfunction formatPercent(value: number): string {\n return `${(value * 100).toFixed(1)}%`;\n}\n\nexport function renderTriggerReport(result: TriggerTestResult, enableColor: boolean, verbose: boolean): string {\n const c = getChalkInstance(enableColor);\n const lines: string[] = [];\n lines.push(\"┌───────────────────────────────────────────────────────────────┐\");\n lines.push(\"│ skilltest trigger │\");\n lines.push(\"├───────────────────────────────────────────────────────────────┤\");\n lines.push(`│ skill: ${result.skillName}`);\n lines.push(`│ provider/model: ${result.provider}/${result.model}`);\n lines.push(\n `│ precision: ${formatPercent(result.metrics.precision)} recall: ${formatPercent(result.metrics.recall)} f1: ${formatPercent(result.metrics.f1)}`\n );\n lines.push(\n `│ TP ${result.metrics.truePositives} TN ${result.metrics.trueNegatives} FP ${result.metrics.falsePositives} FN ${result.metrics.falseNegatives}`\n );\n lines.push(\"└───────────────────────────────────────────────────────────────┘\");\n\n for (const [index, testCase] of result.cases.entries()) {\n const status = testCase.matched ? c.green(\"PASS\") : c.red(\"FAIL\");\n lines.push(`${index + 1}. ${status} query: ${testCase.query}`);\n lines.push(` expected: ${testCase.expected} | actual: ${testCase.actual}`);\n if (verbose && testCase.rawModelResponse) {\n lines.push(` model: ${testCase.rawModelResponse.replace(/\\s+/g, \" \").trim()}`);\n }\n }\n\n lines.push(\"Suggestions:\");\n for (const suggestion of result.suggestions) {\n lines.push(`- ${suggestion}`);\n }\n\n return lines.join(\"\\n\");\n}\n\nexport function renderEvalReport(result: EvalResult, enableColor: boolean, verbose: boolean): string {\n const c = getChalkInstance(enableColor);\n const lines: string[] = [];\n lines.push(\"┌───────────────────────────────────────────────────────────────┐\");\n lines.push(\"│ skilltest eval │\");\n lines.push(\"├───────────────────────────────────────────────────────────────┤\");\n lines.push(`│ skill: ${result.skillName}`);\n lines.push(`│ provider/model: ${result.provider}/${result.model}`);\n lines.push(`│ grader model: ${result.graderModel}`);\n lines.push(`│ assertions passed: ${result.summary.passedAssertions}/${result.summary.totalAssertions}`);\n lines.push(\"└───────────────────────────────────────────────────────────────┘\");\n\n for (const [index, promptResult] of result.results.entries()) {\n lines.push(`${index + 1}. prompt: ${promptResult.prompt}`);\n lines.push(` response summary: ${promptResult.responseSummary.replace(/\\s+/g, \" \").trim()}`);\n for (const assertion of promptResult.assertions) {\n const status = assertion.passed ? c.green(\"PASS\") : c.red(\"FAIL\");\n lines.push(` ${status} ${assertion.assertion}`);\n lines.push(` evidence: ${assertion.evidence}`);\n }\n if (verbose) {\n lines.push(` full response: ${promptResult.response}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n","export function renderJson(value: unknown): string {\n return JSON.stringify(value, null, 2);\n}\n","import { Command } from \"commander\";\nimport { renderJson } from \"../reporters/json.js\";\n\nexport interface GlobalCliOptions {\n json: boolean;\n color: boolean;\n}\n\nexport function getGlobalCliOptions(command: Command): GlobalCliOptions {\n const options = command.optsWithGlobals<{ json?: boolean; color?: boolean }>();\n return {\n json: Boolean(options.json),\n color: options.color !== false\n };\n}\n\nexport function writeResult(value: unknown, asJson: boolean): void {\n if (asJson) {\n process.stdout.write(`${renderJson(value)}\\n`);\n return;\n }\n process.stdout.write(`${String(value)}\\n`);\n}\n\nexport function writeError(error: unknown, asJson: boolean): void {\n const message = error instanceof Error ? error.message : String(error);\n if (asJson) {\n process.stdout.write(`${renderJson({ error: message })}\\n`);\n return;\n }\n process.stderr.write(`Error: ${message}\\n`);\n}\n","import { Command } from \"commander\";\nimport { runLinter } from \"../core/linter/index.js\";\nimport { renderLintReport } from \"../reporters/terminal.js\";\nimport { getGlobalCliOptions, writeError, writeResult } from \"./common.js\";\n\nexport function registerLintCommand(program: Command): void {\n program\n .command(\"lint\")\n .description(\"Run static lint checks against a SKILL.md file or skill directory.\")\n .argument(\"<path-to-skill>\", \"Path to SKILL.md or skill directory\")\n .action(async (targetPath: string, _commandOptions: unknown, command: Command) => {\n const globalOptions = getGlobalCliOptions(command);\n\n try {\n const report = await runLinter(targetPath);\n if (globalOptions.json) {\n writeResult(report, true);\n } else {\n writeResult(renderLintReport(report, globalOptions.color), false);\n }\n\n if (report.summary.failures > 0) {\n process.exitCode = 1;\n }\n } catch (error) {\n writeError(error, globalOptions.json);\n process.exitCode = 2;\n }\n });\n}\n","import ora from \"ora\";\nimport { Command } from \"commander\";\nimport { z } from \"zod\";\nimport { runTriggerTest, triggerQueryArraySchema } from \"../core/trigger-tester.js\";\nimport { parseSkillStrict } from \"../core/skill-parser.js\";\nimport { createProvider } from \"../providers/index.js\";\nimport { ProviderName } from \"../providers/types.js\";\nimport { renderTriggerReport } from \"../reporters/terminal.js\";\nimport { readJsonFile, writeJsonFile } from \"../utils/fs.js\";\nimport { getGlobalCliOptions, writeError, writeResult } from \"./common.js\";\n\nconst triggerOptionsSchema = z.object({\n model: z.string(),\n provider: z.enum([\"anthropic\", \"openai\"]),\n queries: z.string().optional(),\n numQueries: z.number().int().min(2),\n saveQueries: z.string().optional(),\n verbose: z.boolean().optional(),\n apiKey: z.string().optional()\n});\n\nconst DEFAULT_ANTHROPIC_MODEL = \"claude-sonnet-4-5-20250929\";\nconst DEFAULT_OPENAI_MODEL = \"gpt-4.1-mini\";\n\nfunction resolveModel(provider: \"anthropic\" | \"openai\", model: string): string {\n if (provider === \"openai\" && model === DEFAULT_ANTHROPIC_MODEL) {\n return DEFAULT_OPENAI_MODEL;\n }\n return model;\n}\n\nexport function registerTriggerCommand(program: Command): void {\n program\n .command(\"trigger\")\n .description(\"Evaluate whether a skill description triggers correctly.\")\n .argument(\"<path-to-skill>\", \"Path to SKILL.md or skill directory\")\n .option(\"--model <model>\", \"Model to use\", DEFAULT_ANTHROPIC_MODEL)\n .option(\"--provider <provider>\", \"LLM provider: anthropic|openai\", \"anthropic\")\n .option(\"--queries <path>\", \"Path to custom test queries JSON\")\n .option(\"--num-queries <n>\", \"Number of auto-generated queries\", (value) => Number.parseInt(value, 10), 20)\n .option(\"--save-queries <path>\", \"Save generated queries to a JSON file\")\n .option(\"--api-key <key>\", \"API key override\")\n .option(\"--verbose\", \"Show full model decisions\")\n .action(async (targetPath: string, commandOptions: unknown, command: Command) => {\n const globalOptions = getGlobalCliOptions(command);\n const parsedOptions = triggerOptionsSchema.safeParse(commandOptions);\n if (!parsedOptions.success) {\n writeError(new Error(parsedOptions.error.issues[0]?.message ?? \"Invalid trigger options.\"), globalOptions.json);\n process.exitCode = 2;\n return;\n }\n\n const options = parsedOptions.data;\n const spinner = globalOptions.json || !process.stdout.isTTY ? null : ora(\"Preparing trigger evaluation...\").start();\n\n try {\n if (options.numQueries % 2 !== 0) {\n throw new Error(\"--num-queries must be an even number so the suite can split should/should-not trigger cases.\");\n }\n\n if (spinner) {\n spinner.text = \"Parsing skill...\";\n }\n const skill = await parseSkillStrict(targetPath);\n\n if (spinner) {\n spinner.text = \"Initializing model provider...\";\n }\n const provider = createProvider(options.provider as ProviderName, options.apiKey);\n\n let queries = undefined;\n if (options.queries) {\n if (spinner) {\n spinner.text = \"Loading custom trigger queries...\";\n }\n const loaded = await readJsonFile<unknown>(options.queries);\n const parsedQueries = triggerQueryArraySchema.safeParse(loaded);\n if (!parsedQueries.success) {\n throw new Error(`Invalid --queries JSON: ${parsedQueries.error.issues[0]?.message ?? \"unknown format issue\"}`);\n }\n queries = parsedQueries.data;\n }\n\n if (spinner) {\n spinner.text = \"Running trigger simulations...\";\n }\n const model = resolveModel(options.provider, options.model);\n const result = await runTriggerTest(skill, {\n model,\n provider,\n queries,\n numQueries: options.numQueries,\n verbose: Boolean(options.verbose)\n });\n\n if (options.saveQueries) {\n await writeJsonFile(options.saveQueries, result.queries);\n }\n\n spinner?.stop();\n if (globalOptions.json) {\n writeResult(result, true);\n } else {\n writeResult(renderTriggerReport(result, globalOptions.color, Boolean(options.verbose)), false);\n }\n } catch (error) {\n spinner?.stop();\n writeError(error, globalOptions.json);\n process.exitCode = 2;\n }\n });\n}\n","import { z } from \"zod\";\nimport { ParsedSkill } from \"./skill-parser.js\";\nimport { LanguageModelProvider } from \"../providers/types.js\";\n\nexport interface TriggerQuery {\n query: string;\n should_trigger: boolean;\n}\n\nexport interface TriggerTestCaseResult {\n query: string;\n shouldTrigger: boolean;\n expected: string;\n actual: string;\n matched: boolean;\n rawModelResponse?: string;\n}\n\nexport interface TriggerMetrics {\n truePositives: number;\n trueNegatives: number;\n falsePositives: number;\n falseNegatives: number;\n precision: number;\n recall: number;\n f1: number;\n}\n\nexport interface TriggerTestResult {\n skillName: string;\n model: string;\n provider: string;\n queries: TriggerQuery[];\n cases: TriggerTestCaseResult[];\n metrics: TriggerMetrics;\n suggestions: string[];\n}\n\nconst triggerQuerySchema = z.object({\n query: z.string().min(1),\n should_trigger: z.boolean()\n});\n\nexport const triggerQueryArraySchema = z.array(triggerQuerySchema);\n\nconst FAKE_SKILLS: Array<{ name: string; description: string }> = [\n { name: \"code-review\", description: \"Reviews code changes for bugs, regressions, and maintainability issues.\" },\n { name: \"api-tester\", description: \"Designs and runs REST API tests, validating status codes and response shapes.\" },\n { name: \"db-migrator\", description: \"Plans and generates safe database migration scripts with rollback guidance.\" },\n { name: \"bug-repro\", description: \"Reproduces reported bugs by building deterministic minimal test cases.\" },\n { name: \"release-notes\", description: \"Drafts release notes from commits and PR metadata for stakeholders.\" },\n { name: \"log-analyzer\", description: \"Analyzes service logs to identify error clusters and likely root causes.\" },\n { name: \"performance-audit\", description: \"Finds hotspots in runtime and suggests profiling-driven optimizations.\" },\n { name: \"security-audit\", description: \"Checks code and config for common security vulnerabilities and risky defaults.\" },\n { name: \"refactor-planner\", description: \"Breaks large refactors into safe incremental steps with validation plans.\" },\n { name: \"schema-designer\", description: \"Designs JSON schemas and validates data contracts for integrations.\" },\n { name: \"docs-writer\", description: \"Writes developer documentation, tutorials, and API usage examples.\" },\n { name: \"cli-scaffolder\", description: \"Creates CLI project skeletons with argument parsing and help text.\" },\n { name: \"incident-triage\", description: \"Triage production incidents with severity tagging and next-action checklists.\" },\n { name: \"test-generator\", description: \"Generates unit and integration test cases from feature requirements.\" },\n { name: \"prompt-tuner\", description: \"Improves prompts for reliability, formatting, and failure handling.\" }\n];\n\nfunction shuffle<T>(values: T[]): T[] {\n const copy = [...values];\n for (let index = copy.length - 1; index > 0; index -= 1) {\n const swapIndex = Math.floor(Math.random() * (index + 1));\n [copy[index], copy[swapIndex]] = [copy[swapIndex], copy[index]];\n }\n return copy;\n}\n\nfunction sample<T>(values: T[], count: number): T[] {\n return shuffle(values).slice(0, Math.max(0, Math.min(count, values.length)));\n}\n\nfunction parseJsonArrayFromModelOutput(raw: string): unknown[] {\n const trimmed = raw.trim();\n if (trimmed.startsWith(\"[\") && trimmed.endsWith(\"]\")) {\n return JSON.parse(trimmed) as unknown[];\n }\n\n const start = trimmed.indexOf(\"[\");\n const end = trimmed.lastIndexOf(\"]\");\n if (start >= 0 && end > start) {\n const possibleJson = trimmed.slice(start, end + 1);\n return JSON.parse(possibleJson) as unknown[];\n }\n\n throw new Error(\"Model did not return a JSON array.\");\n}\n\nasync function generateQueriesWithModel(\n skill: ParsedSkill,\n provider: LanguageModelProvider,\n model: string,\n numQueries: number\n): Promise<TriggerQuery[]> {\n const shouldTriggerCount = Math.floor(numQueries / 2);\n const shouldNotTriggerCount = numQueries - shouldTriggerCount;\n\n const systemPrompt = [\n \"You generate realistic user prompts to test whether a specific agent skill triggers.\",\n \"Return JSON only. No markdown, no comments.\",\n \"Each entry must be an object: {\\\"query\\\": string, \\\"should_trigger\\\": boolean}.\",\n \"Create substantive prompts, not toy one-liners.\"\n ].join(\" \");\n\n const userPrompt = [\n `Skill name: ${skill.frontmatter.name}`,\n `Skill description: ${skill.frontmatter.description}`,\n `Generate ${numQueries} prompts total.`,\n `Exactly ${shouldTriggerCount} should have should_trigger=true.`,\n `Exactly ${shouldNotTriggerCount} should have should_trigger=false.`,\n \"Prompts should look like real user requests with enough context to drive a trigger decision.\"\n ].join(\"\\n\");\n\n const raw = await provider.sendMessage(systemPrompt, userPrompt, { model });\n const parsed = triggerQueryArraySchema.safeParse(parseJsonArrayFromModelOutput(raw));\n if (!parsed.success) {\n throw new Error(`Failed to parse generated queries: ${parsed.error.issues[0]?.message ?? \"invalid format\"}`);\n }\n\n const trueCount = parsed.data.filter((item) => item.should_trigger).length;\n const falseCount = parsed.data.length - trueCount;\n if (parsed.data.length !== numQueries || trueCount !== shouldTriggerCount || falseCount !== shouldNotTriggerCount) {\n throw new Error(\n `Generated query split mismatch. Expected ${numQueries} (${shouldTriggerCount}/${shouldNotTriggerCount}), got ${parsed.data.length} (${trueCount}/${falseCount}).`\n );\n }\n\n return parsed.data;\n}\n\nfunction parseDecision(rawResponse: string, skillNames: string[]): string {\n const normalized = rawResponse.trim().toLowerCase();\n if (normalized === \"none\" || normalized.startsWith(\"none\")) {\n return \"none\";\n }\n\n for (const skillName of skillNames) {\n const escaped = skillName.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const regex = new RegExp(`\\\\b${escaped}\\\\b`, \"i\");\n if (regex.test(rawResponse)) {\n return skillName;\n }\n }\n\n return \"unrecognized\";\n}\n\nfunction calculateMetrics(skillName: string, cases: TriggerTestCaseResult[]): TriggerMetrics {\n let truePositives = 0;\n let trueNegatives = 0;\n let falsePositives = 0;\n let falseNegatives = 0;\n\n for (const testCase of cases) {\n const choseTargetSkill = testCase.actual === skillName;\n if (testCase.shouldTrigger && choseTargetSkill) {\n truePositives += 1;\n continue;\n }\n if (testCase.shouldTrigger && !choseTargetSkill) {\n falseNegatives += 1;\n continue;\n }\n if (!testCase.shouldTrigger && choseTargetSkill) {\n falsePositives += 1;\n continue;\n }\n trueNegatives += 1;\n }\n\n const precisionDenominator = truePositives + falsePositives;\n const recallDenominator = truePositives + falseNegatives;\n const precision = precisionDenominator === 0 ? 0 : truePositives / precisionDenominator;\n const recall = recallDenominator === 0 ? 0 : truePositives / recallDenominator;\n const f1 = precision + recall === 0 ? 0 : (2 * precision * recall) / (precision + recall);\n\n return {\n truePositives,\n trueNegatives,\n falsePositives,\n falseNegatives,\n precision,\n recall,\n f1\n };\n}\n\nfunction buildSuggestions(metrics: TriggerMetrics): string[] {\n const suggestions: string[] = [];\n if (metrics.falseNegatives > 0) {\n suggestions.push(\n \"False negatives found: clarify capability keywords and add explicit 'use when ...' phrasing in description.\"\n );\n }\n if (metrics.falsePositives > 0) {\n suggestions.push(\"False positives found: narrow scope boundaries and add explicit non-goals in description.\");\n }\n if (suggestions.length === 0) {\n suggestions.push(\"Trigger behavior looks clean on this sample. Keep monitoring with domain-specific custom queries.\");\n }\n return suggestions;\n}\n\nexport interface RunTriggerTestOptions {\n model: string;\n provider: LanguageModelProvider;\n queries?: TriggerQuery[];\n numQueries: number;\n verbose?: boolean;\n}\n\nexport async function runTriggerTest(skill: ParsedSkill, options: RunTriggerTestOptions): Promise<TriggerTestResult> {\n const queries =\n options.queries && options.queries.length > 0\n ? triggerQueryArraySchema.parse(options.queries)\n : await generateQueriesWithModel(skill, options.provider, options.model, options.numQueries);\n\n const results: TriggerTestCaseResult[] = [];\n const skillName = skill.frontmatter.name;\n\n for (const testQuery of queries) {\n const fakeCount = 5 + Math.floor(Math.random() * 4);\n const fakeSkills = sample(FAKE_SKILLS, fakeCount);\n const allSkills = shuffle([\n ...fakeSkills,\n {\n name: skill.frontmatter.name,\n description: skill.frontmatter.description\n }\n ]);\n\n const skillListText = allSkills.map((entry) => `- ${entry.name}: ${entry.description}`).join(\"\\n\");\n\n const systemPrompt = [\n \"You are selecting one skill to activate for a user query.\",\n \"Choose the single best matching skill name from the provided list, or 'none' if no skill is a good fit.\",\n \"Respond with only the skill name or 'none'.\"\n ].join(\" \");\n\n const userPrompt = [`Available skills:`, skillListText, \"\", `User query: ${testQuery.query}`].join(\"\\n\");\n const rawResponse = await options.provider.sendMessage(systemPrompt, userPrompt, { model: options.model });\n const decision = parseDecision(\n rawResponse,\n allSkills.map((entry) => entry.name)\n );\n\n const expected = testQuery.should_trigger ? skillName : \"none\";\n const matched = testQuery.should_trigger ? decision === skillName : decision !== skillName;\n\n results.push({\n query: testQuery.query,\n shouldTrigger: testQuery.should_trigger,\n expected,\n actual: decision,\n matched,\n rawModelResponse: options.verbose ? rawResponse : undefined\n });\n }\n\n const metrics = calculateMetrics(skillName, results);\n\n return {\n skillName,\n model: options.model,\n provider: options.provider.name,\n queries,\n cases: results,\n metrics,\n suggestions: buildSuggestions(metrics)\n };\n}\n","export type ProviderName = \"anthropic\" | \"openai\";\n\nexport function resolveApiKey(provider: ProviderName, override?: string): string {\n if (override && override.trim() !== \"\") {\n return override.trim();\n }\n\n if (provider === \"anthropic\") {\n const envValue = process.env.ANTHROPIC_API_KEY?.trim();\n if (envValue) {\n return envValue;\n }\n throw new Error(\n \"No Anthropic API key found. Set ANTHROPIC_API_KEY environment variable or pass --api-key flag.\"\n );\n }\n\n const envValue = process.env.OPENAI_API_KEY?.trim();\n if (envValue) {\n return envValue;\n }\n throw new Error(\"No OpenAI API key found. Set OPENAI_API_KEY environment variable or pass --api-key flag.\");\n}\n","import Anthropic from \"@anthropic-ai/sdk\";\nimport { LanguageModelProvider, SendMessageOptions } from \"./types.js\";\n\nfunction wait(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nfunction isRateLimitError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n\n const maybeStatus = (error as { status?: number }).status;\n if (maybeStatus === 429) {\n return true;\n }\n\n const maybeMessage = (error as { message?: string }).message;\n if (typeof maybeMessage === \"string\" && /rate limit/i.test(maybeMessage)) {\n return true;\n }\n\n return false;\n}\n\nexport class AnthropicProvider implements LanguageModelProvider {\n public readonly name = \"anthropic\" as const;\n private readonly client: Anthropic;\n\n public constructor(apiKey: string) {\n this.client = new Anthropic({ apiKey });\n }\n\n public async sendMessage(systemPrompt: string, userMessage: string, options: SendMessageOptions): Promise<string> {\n let lastError: unknown;\n\n for (let attempt = 0; attempt < 3; attempt += 1) {\n try {\n const response = await this.client.messages.create({\n model: options.model,\n max_tokens: 2048,\n system: systemPrompt,\n messages: [\n {\n role: \"user\",\n content: userMessage\n }\n ]\n });\n\n const textBlocks = response.content.filter((block) => block.type === \"text\");\n const text = textBlocks.map((block) => block.text).join(\"\\n\").trim();\n if (text.length === 0) {\n throw new Error(\"Model returned an empty response.\");\n }\n return text;\n } catch (error) {\n lastError = error;\n if (!isRateLimitError(error) || attempt === 2) {\n break;\n }\n\n const delay = Math.min(4000, 500 * 2 ** attempt) + Math.floor(Math.random() * 250);\n await wait(delay);\n }\n }\n\n if (lastError instanceof Error) {\n throw new Error(`Anthropic API call failed: ${lastError.message}`);\n }\n throw new Error(\"Anthropic API call failed with an unknown error.\");\n }\n}\n","import { LanguageModelProvider, SendMessageOptions } from \"./types.js\";\n\ntype OpenAIClient = {\n chat: {\n completions: {\n create(input: {\n model: string;\n messages: Array<{ role: \"system\" | \"user\"; content: string }>;\n max_tokens?: number;\n }): Promise<{\n choices?: Array<{\n message?: {\n content?: string | Array<{ type?: string; text?: string }>;\n };\n }>;\n }>;\n };\n };\n};\n\nfunction wait(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nfunction isRetriableError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n\n const maybeStatus = (error as { status?: number }).status;\n if (maybeStatus === 429 || (typeof maybeStatus === \"number\" && maybeStatus >= 500)) {\n return true;\n }\n\n const maybeCode = (error as { code?: string }).code;\n if (typeof maybeCode === \"string\" && /timeout|econnreset|enotfound|eai_again/i.test(maybeCode)) {\n return true;\n }\n\n const maybeMessage = (error as { message?: string }).message;\n if (typeof maybeMessage === \"string\" && /(rate limit|timeout|temporarily unavailable|connection)/i.test(maybeMessage)) {\n return true;\n }\n\n return false;\n}\n\nfunction extractTextContent(content: string | Array<{ type?: string; text?: string }> | undefined): string {\n if (!content) {\n return \"\";\n }\n if (typeof content === \"string\") {\n return content.trim();\n }\n\n const text = content\n .map((item) => (item.type === \"text\" || !item.type ? item.text ?? \"\" : \"\"))\n .join(\"\\n\")\n .trim();\n return text;\n}\n\nexport class OpenAIProvider implements LanguageModelProvider {\n public readonly name = \"openai\" as const;\n private readonly apiKey: string;\n private client: OpenAIClient | null;\n\n public constructor(apiKey: string) {\n this.apiKey = apiKey;\n this.client = null;\n }\n\n private async ensureClient(): Promise<OpenAIClient> {\n if (this.client) {\n return this.client;\n }\n\n let openAiModule: unknown;\n try {\n const moduleName = \"openai\";\n openAiModule = await import(moduleName);\n } catch {\n throw new Error(\n \"OpenAI SDK is not installed. Install optional dependency 'openai' or run 'npm install' with optional dependencies enabled.\"\n );\n }\n\n const OpenAIConstructor = (openAiModule as { default?: new (config: { apiKey: string }) => OpenAIClient }).default;\n if (!OpenAIConstructor) {\n throw new Error(\"OpenAI SDK loaded but no default client export was found.\");\n }\n\n this.client = new OpenAIConstructor({ apiKey: this.apiKey });\n return this.client;\n }\n\n public async sendMessage(systemPrompt: string, userMessage: string, options: SendMessageOptions): Promise<string> {\n const client = await this.ensureClient();\n let lastError: unknown;\n\n for (let attempt = 0; attempt < 3; attempt += 1) {\n try {\n const response = await client.chat.completions.create({\n model: options.model,\n max_tokens: 2048,\n messages: [\n {\n role: \"system\",\n content: systemPrompt\n },\n {\n role: \"user\",\n content: userMessage\n }\n ]\n });\n\n const text = (response.choices ?? [])\n .map((choice) => extractTextContent(choice.message?.content))\n .join(\"\\n\")\n .trim();\n\n if (text.length === 0) {\n throw new Error(\"Model returned an empty response.\");\n }\n\n return text;\n } catch (error) {\n lastError = error;\n if (!isRetriableError(error) || attempt === 2) {\n break;\n }\n\n const delay = Math.min(4000, 500 * 2 ** attempt) + Math.floor(Math.random() * 250);\n await wait(delay);\n }\n }\n\n if (lastError instanceof Error) {\n throw new Error(`OpenAI API call failed: ${lastError.message}`);\n }\n throw new Error(\"OpenAI API call failed with an unknown error.\");\n }\n}\n","import { resolveApiKey } from \"../utils/config.js\";\nimport { AnthropicProvider } from \"./anthropic.js\";\nimport { OpenAIProvider } from \"./openai.js\";\nimport { LanguageModelProvider, ProviderName } from \"./types.js\";\n\nexport function createProvider(providerName: ProviderName, apiKeyOverride?: string): LanguageModelProvider {\n const apiKey = resolveApiKey(providerName, apiKeyOverride);\n if (providerName === \"anthropic\") {\n return new AnthropicProvider(apiKey);\n }\n return new OpenAIProvider(apiKey);\n}\n\nexport type { LanguageModelProvider, ProviderName };\n","import ora from \"ora\";\nimport { Command } from \"commander\";\nimport { z } from \"zod\";\nimport { runEval, evalPromptArraySchema } from \"../core/eval-runner.js\";\nimport { parseSkillStrict } from \"../core/skill-parser.js\";\nimport { createProvider } from \"../providers/index.js\";\nimport { ProviderName } from \"../providers/types.js\";\nimport { renderEvalReport } from \"../reporters/terminal.js\";\nimport { readJsonFile, writeJsonFile } from \"../utils/fs.js\";\nimport { getGlobalCliOptions, writeError, writeResult } from \"./common.js\";\n\nconst evalOptionsSchema = z.object({\n prompts: z.string().optional(),\n model: z.string(),\n graderModel: z.string().optional(),\n provider: z.enum([\"anthropic\", \"openai\"]),\n saveResults: z.string().optional(),\n verbose: z.boolean().optional(),\n apiKey: z.string().optional()\n});\n\nconst DEFAULT_ANTHROPIC_MODEL = \"claude-sonnet-4-5-20250929\";\nconst DEFAULT_OPENAI_MODEL = \"gpt-4.1-mini\";\n\nfunction resolveModel(provider: \"anthropic\" | \"openai\", model: string): string {\n if (provider === \"openai\" && model === DEFAULT_ANTHROPIC_MODEL) {\n return DEFAULT_OPENAI_MODEL;\n }\n return model;\n}\n\nexport function registerEvalCommand(program: Command): void {\n program\n .command(\"eval\")\n .description(\"Run end-to-end skill execution and quality evaluation.\")\n .argument(\"<path-to-skill>\", \"Path to SKILL.md or skill directory\")\n .option(\"--prompts <path>\", \"Path to eval prompts JSON\")\n .option(\"--model <model>\", \"Model to execute prompts\", DEFAULT_ANTHROPIC_MODEL)\n .option(\"--grader-model <model>\", \"Model used for grading (defaults to --model)\")\n .option(\"--provider <provider>\", \"LLM provider: anthropic|openai\", \"anthropic\")\n .option(\"--save-results <path>\", \"Save full evaluation results to JSON\")\n .option(\"--api-key <key>\", \"API key override\")\n .option(\"--verbose\", \"Show full model responses\")\n .action(async (targetPath: string, commandOptions: unknown, command: Command) => {\n const globalOptions = getGlobalCliOptions(command);\n const parsedOptions = evalOptionsSchema.safeParse(commandOptions);\n if (!parsedOptions.success) {\n writeError(new Error(parsedOptions.error.issues[0]?.message ?? \"Invalid eval options.\"), globalOptions.json);\n process.exitCode = 2;\n return;\n }\n\n const options = parsedOptions.data;\n const spinner = globalOptions.json || !process.stdout.isTTY ? null : ora(\"Preparing evaluation...\").start();\n\n try {\n if (spinner) {\n spinner.text = \"Parsing skill...\";\n }\n const skill = await parseSkillStrict(targetPath);\n\n if (spinner) {\n spinner.text = \"Initializing model provider...\";\n }\n const provider = createProvider(options.provider as ProviderName, options.apiKey);\n\n let prompts = undefined;\n if (options.prompts) {\n if (spinner) {\n spinner.text = \"Loading test prompts...\";\n }\n const loaded = await readJsonFile<unknown>(options.prompts);\n const parsedPrompts = evalPromptArraySchema.safeParse(loaded);\n if (!parsedPrompts.success) {\n throw new Error(`Invalid --prompts JSON: ${parsedPrompts.error.issues[0]?.message ?? \"unknown format issue\"}`);\n }\n prompts = parsedPrompts.data;\n }\n\n if (spinner) {\n spinner.text = \"Running eval prompts and grading responses...\";\n }\n const model = resolveModel(options.provider, options.model);\n const graderModel = options.graderModel ?? model;\n const result = await runEval(skill, {\n provider,\n model,\n graderModel,\n prompts\n });\n\n if (options.saveResults) {\n await writeJsonFile(options.saveResults, result);\n }\n\n spinner?.stop();\n if (globalOptions.json) {\n writeResult(result, true);\n } else {\n writeResult(renderEvalReport(result, globalOptions.color, Boolean(options.verbose)), false);\n }\n } catch (error) {\n spinner?.stop();\n writeError(error, globalOptions.json);\n process.exitCode = 2;\n }\n });\n}\n","import { z } from \"zod\";\nimport { gradeResponse, GradedAssertion } from \"./grader.js\";\nimport { ParsedSkill } from \"./skill-parser.js\";\nimport { LanguageModelProvider } from \"../providers/types.js\";\n\nexport interface EvalPrompt {\n prompt: string;\n assertions?: string[];\n}\n\nexport interface EvalPromptResult {\n prompt: string;\n assertions: GradedAssertion[];\n responseSummary: string;\n response: string;\n passedAssertions: number;\n totalAssertions: number;\n}\n\nexport interface EvalResultSummary {\n totalPrompts: number;\n totalAssertions: number;\n passedAssertions: number;\n}\n\nexport interface EvalResult {\n skillName: string;\n model: string;\n graderModel: string;\n provider: string;\n prompts: EvalPrompt[];\n results: EvalPromptResult[];\n summary: EvalResultSummary;\n}\n\nconst evalPromptSchema = z.object({\n prompt: z.string().min(1),\n assertions: z.array(z.string().min(1)).optional()\n});\n\nexport const evalPromptArraySchema = z.array(evalPromptSchema);\n\nfunction extractJsonArray(raw: string): unknown[] {\n const trimmed = raw.trim();\n if (trimmed.startsWith(\"[\") && trimmed.endsWith(\"]\")) {\n return JSON.parse(trimmed) as unknown[];\n }\n\n const start = trimmed.indexOf(\"[\");\n const end = trimmed.lastIndexOf(\"]\");\n if (start >= 0 && end > start) {\n return JSON.parse(trimmed.slice(start, end + 1)) as unknown[];\n }\n\n throw new Error(\"Model did not return a JSON array.\");\n}\n\nasync function generatePrompts(\n skill: ParsedSkill,\n provider: LanguageModelProvider,\n model: string,\n count: number\n): Promise<EvalPrompt[]> {\n const systemPrompt = [\n \"You generate realistic evaluation prompts for an agent skill.\",\n \"Return JSON only.\",\n \"Format: [{\\\"prompt\\\":\\\"...\\\",\\\"assertions\\\":[\\\"...\\\", \\\"...\\\"]}]\",\n \"Assertions should be concrete and checkable.\"\n ].join(\" \");\n\n const userPrompt = [\n `Skill name: ${skill.frontmatter.name}`,\n `Skill description: ${skill.frontmatter.description}`,\n \"Skill instructions:\",\n skill.content,\n \"\",\n `Generate ${count} prompts that stress the main capabilities and likely edge cases.`,\n \"Each prompt should include 2-4 assertions.\"\n ].join(\"\\n\");\n\n const raw = await provider.sendMessage(systemPrompt, userPrompt, { model });\n const parsed = evalPromptArraySchema.safeParse(extractJsonArray(raw));\n if (!parsed.success) {\n throw new Error(`Failed to parse generated eval prompts: ${parsed.error.issues[0]?.message ?? \"invalid prompt JSON\"}`);\n }\n\n if (parsed.data.length !== count) {\n throw new Error(`Expected ${count} prompts, got ${parsed.data.length}.`);\n }\n\n return parsed.data;\n}\n\nexport interface RunEvalOptions {\n provider: LanguageModelProvider;\n model: string;\n graderModel: string;\n prompts?: EvalPrompt[];\n}\n\nexport async function runEval(skill: ParsedSkill, options: RunEvalOptions): Promise<EvalResult> {\n const prompts =\n options.prompts && options.prompts.length > 0\n ? evalPromptArraySchema.parse(options.prompts)\n : await generatePrompts(skill, options.provider, options.model, 5);\n\n const results: EvalPromptResult[] = [];\n\n for (const evalPrompt of prompts) {\n const systemPrompt = [\n \"You are an AI assistant with an activated skill.\",\n \"Follow this SKILL.md content exactly where applicable.\",\n \"\",\n skill.raw\n ].join(\"\\n\");\n\n const response = await options.provider.sendMessage(systemPrompt, evalPrompt.prompt, { model: options.model });\n\n const gradedAssertions = await gradeResponse({\n provider: options.provider,\n model: options.graderModel,\n skillName: skill.frontmatter.name,\n skillBody: skill.content,\n userPrompt: evalPrompt.prompt,\n modelResponse: response,\n assertions: evalPrompt.assertions\n });\n\n const passedAssertions = gradedAssertions.filter((assertion) => assertion.passed).length;\n results.push({\n prompt: evalPrompt.prompt,\n assertions: gradedAssertions,\n responseSummary: response.slice(0, 200),\n response,\n passedAssertions,\n totalAssertions: gradedAssertions.length\n });\n }\n\n const totalAssertions = results.reduce((total, result) => total + result.totalAssertions, 0);\n const passedAssertions = results.reduce((total, result) => total + result.passedAssertions, 0);\n\n return {\n skillName: skill.frontmatter.name,\n model: options.model,\n graderModel: options.graderModel,\n provider: options.provider.name,\n prompts,\n results,\n summary: {\n totalPrompts: results.length,\n totalAssertions,\n passedAssertions\n }\n };\n}\n","import { z } from \"zod\";\nimport { LanguageModelProvider } from \"../providers/types.js\";\n\nexport interface GradedAssertion {\n assertion: string;\n passed: boolean;\n evidence: string;\n}\n\nconst gradedAssertionSchema = z.object({\n assertion: z.string(),\n passed: z.boolean(),\n evidence: z.string()\n});\n\nconst graderOutputSchema = z.object({\n assertions: z.array(gradedAssertionSchema)\n});\n\nfunction extractJsonObject(raw: string): Record<string, unknown> {\n const trimmed = raw.trim();\n if (trimmed.startsWith(\"{\") && trimmed.endsWith(\"}\")) {\n return JSON.parse(trimmed) as Record<string, unknown>;\n }\n\n const start = trimmed.indexOf(\"{\");\n const end = trimmed.lastIndexOf(\"}\");\n if (start >= 0 && end > start) {\n return JSON.parse(trimmed.slice(start, end + 1)) as Record<string, unknown>;\n }\n\n throw new Error(\"Grader did not return a JSON object.\");\n}\n\nexport interface GradeResponseOptions {\n provider: LanguageModelProvider;\n model: string;\n skillName: string;\n skillBody: string;\n userPrompt: string;\n modelResponse: string;\n assertions?: string[];\n}\n\nexport async function gradeResponse(options: GradeResponseOptions): Promise<GradedAssertion[]> {\n const assertionList =\n options.assertions && options.assertions.length > 0\n ? options.assertions\n : [\n \"The response follows the skill instructions faithfully.\",\n \"The response is well-structured and actionable.\",\n \"The response addresses the user prompt directly.\"\n ];\n\n const systemPrompt = [\n \"You are a strict evaluator for agent skill outputs.\",\n \"Assess each assertion and return JSON only.\",\n \"Required output format: {\\\"assertions\\\":[{\\\"assertion\\\":\\\"...\\\",\\\"passed\\\":true|false,\\\"evidence\\\":\\\"...\\\"}]}\"\n ].join(\" \");\n\n const userPrompt = [\n `Skill: ${options.skillName}`,\n \"Skill instructions:\",\n options.skillBody,\n \"\",\n `User prompt: ${options.userPrompt}`,\n \"\",\n \"Model response:\",\n options.modelResponse,\n \"\",\n \"Assertions to evaluate:\",\n assertionList.map((assertion, index) => `${index + 1}. ${assertion}`).join(\"\\n\")\n ].join(\"\\n\");\n\n const raw = await options.provider.sendMessage(systemPrompt, userPrompt, { model: options.model });\n const parsed = graderOutputSchema.safeParse(extractJsonObject(raw));\n\n if (!parsed.success) {\n throw new Error(`Failed to parse grader output: ${parsed.error.issues[0]?.message ?? \"invalid grader JSON\"}`);\n }\n\n return parsed.data.assertions;\n}\n"],"mappings":"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","names":["fs","path","fs","path","fs","path","path","fs","fs","path","path","fs","z","z","envValue","wait","z","ora","z","z","z","z","passedAssertions","z","DEFAULT_ANTHROPIC_MODEL","DEFAULT_OPENAI_MODEL","resolveModel","ora","path","fs"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/core/skill-parser.ts","../src/core/linter/compat.ts","../src/core/linter/content.ts","../src/core/linter/disclosure.ts","../src/utils/fs.ts","../src/core/linter/frontmatter.ts","../src/core/linter/security.ts","../src/core/linter/structure.ts","../src/core/linter/index.ts","../src/reporters/terminal.ts","../src/reporters/json.ts","../src/commands/common.ts","../src/commands/lint.ts","../src/commands/trigger.ts","../src/core/trigger-tester.ts","../src/utils/config.ts","../src/providers/anthropic.ts","../src/providers/openai.ts","../src/providers/index.ts","../src/commands/eval.ts","../src/core/eval-runner.ts","../src/core/grader.ts","../src/commands/check.ts","../src/core/check-runner.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { Command } from \"commander\";\nimport { registerLintCommand } from \"./commands/lint.js\";\nimport { registerTriggerCommand } from \"./commands/trigger.js\";\nimport { registerEvalCommand } from \"./commands/eval.js\";\nimport { registerCheckCommand } from \"./commands/check.js\";\n\nfunction resolveVersion(): string {\n try {\n const currentFilePath = fileURLToPath(import.meta.url);\n const packageJsonPath = path.resolve(path.dirname(currentFilePath), \"..\", \"package.json\");\n const raw = fs.readFileSync(packageJsonPath, \"utf8\");\n const parsed = JSON.parse(raw) as { version?: string };\n return parsed.version ?? \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\n\nexport async function run(argv: string[]): Promise<void> {\n const program = new Command();\n program\n .name(\"skilltest\")\n .description(\"The testing framework for Agent Skills.\")\n .version(resolveVersion())\n .option(\"--json\", \"Output results as JSON\")\n .option(\"--no-color\", \"Disable colored output\")\n .showHelpAfterError();\n\n registerLintCommand(program);\n registerTriggerCommand(program);\n registerEvalCommand(program);\n registerCheckCommand(program);\n\n await program.parseAsync(argv);\n}\n\nrun(process.argv).catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`Error: ${message}\\n`);\n process.exitCode = 2;\n});\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport matter from \"gray-matter\";\nimport yaml from \"js-yaml\";\nimport { z } from \"zod\";\n\nexport interface SkillFileContext {\n skillRoot: string;\n skillFile: string;\n raw: string;\n lineCount: number;\n}\n\nexport interface FrontmatterParseResult {\n hasFrontmatter: boolean;\n rawFrontmatter: string | null;\n data: Record<string, unknown> | null;\n content: string;\n error: string | null;\n}\n\nconst frontmatterSchema = z\n .object({\n name: z.string(),\n description: z.string(),\n license: z.string().optional()\n })\n .passthrough();\n\nexport type SkillFrontmatter = z.infer<typeof frontmatterSchema>;\n\nexport interface ParsedSkill {\n skillRoot: string;\n skillFile: string;\n raw: string;\n content: string;\n frontmatterRaw: string | null;\n frontmatter: SkillFrontmatter;\n}\n\nconst FRONTMATTER_BLOCK_REGEX = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?/;\n\nexport async function resolveSkillPath(inputPath: string): Promise<{ skillRoot: string; skillFile: string }> {\n const absoluteInput = path.resolve(inputPath);\n let stat;\n\n try {\n stat = await fs.stat(absoluteInput);\n } catch {\n throw new Error(`Path not found: ${inputPath}`);\n }\n\n if (stat.isDirectory()) {\n const skillFile = path.join(absoluteInput, \"SKILL.md\");\n try {\n const skillStat = await fs.stat(skillFile);\n if (!skillStat.isFile()) {\n throw new Error();\n }\n } catch {\n throw new Error(`No SKILL.md found in directory: ${inputPath}`);\n }\n\n return { skillRoot: absoluteInput, skillFile };\n }\n\n if (!stat.isFile()) {\n throw new Error(`Path is not a file or directory: ${inputPath}`);\n }\n\n if (path.basename(absoluteInput) !== \"SKILL.md\") {\n throw new Error(`Expected SKILL.md or a directory containing SKILL.md. Received: ${inputPath}`);\n }\n\n return { skillRoot: path.dirname(absoluteInput), skillFile: absoluteInput };\n}\n\nexport async function loadSkillFile(inputPath: string): Promise<SkillFileContext> {\n const { skillRoot, skillFile } = await resolveSkillPath(inputPath);\n const raw = await fs.readFile(skillFile, \"utf8\");\n const lineCount = raw === \"\" ? 0 : raw.split(/\\r?\\n/).length;\n\n return { skillRoot, skillFile, raw, lineCount };\n}\n\nexport function parseFrontmatter(rawSkill: string): FrontmatterParseResult {\n const blockMatch = rawSkill.match(FRONTMATTER_BLOCK_REGEX);\n const rawFrontmatter = blockMatch?.[1] ?? null;\n\n if (!rawFrontmatter) {\n return {\n hasFrontmatter: false,\n rawFrontmatter: null,\n data: null,\n content: rawSkill,\n error: null\n };\n }\n\n try {\n const parsedByYaml = yaml.load(rawFrontmatter);\n if (parsedByYaml === null || typeof parsedByYaml !== \"object\" || Array.isArray(parsedByYaml)) {\n return {\n hasFrontmatter: true,\n rawFrontmatter,\n data: null,\n content: rawSkill.replace(FRONTMATTER_BLOCK_REGEX, \"\"),\n error: \"Frontmatter must parse into a YAML object.\"\n };\n }\n\n const parsedByMatter = matter(rawSkill);\n return {\n hasFrontmatter: true,\n rawFrontmatter,\n data: parsedByMatter.data as Record<string, unknown>,\n content: parsedByMatter.content,\n error: null\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Unknown frontmatter parse error\";\n return {\n hasFrontmatter: true,\n rawFrontmatter,\n data: null,\n content: rawSkill.replace(FRONTMATTER_BLOCK_REGEX, \"\"),\n error: message\n };\n }\n}\n\nexport async function parseSkillStrict(inputPath: string): Promise<ParsedSkill> {\n const skillContext = await loadSkillFile(inputPath);\n const parsedFrontmatter = parseFrontmatter(skillContext.raw);\n\n if (!parsedFrontmatter.hasFrontmatter) {\n throw new Error(\"SKILL.md is missing YAML frontmatter.\");\n }\n\n if (parsedFrontmatter.error) {\n throw new Error(`Invalid frontmatter: ${parsedFrontmatter.error}`);\n }\n\n const validation = frontmatterSchema.safeParse(parsedFrontmatter.data ?? {});\n if (!validation.success) {\n const issue = validation.error.issues[0];\n throw new Error(`Invalid frontmatter field '${issue.path.join(\".\")}': ${issue.message}`);\n }\n\n return {\n skillRoot: skillContext.skillRoot,\n skillFile: skillContext.skillFile,\n raw: skillContext.raw,\n content: parsedFrontmatter.content,\n frontmatterRaw: parsedFrontmatter.rawFrontmatter,\n frontmatter: validation.data\n };\n}\n\nconst RELATIVE_LINK_PREFIXES = [\"./\", \"../\", \"scripts/\", \"references/\", \"assets/\"];\n\nexport function extractRelativeFileReferences(markdown: string): string[] {\n const references = new Set<string>();\n\n const markdownLinkRegex = /\\[[^\\]]+\\]\\(([^)]+)\\)/g;\n for (const match of markdown.matchAll(markdownLinkRegex)) {\n const rawTarget = (match[1] ?? \"\").trim();\n const cleaned = cleanReferenceTarget(rawTarget);\n if (cleaned && isLikelyRelativePath(cleaned)) {\n references.add(cleaned);\n }\n }\n\n const inlineCodeRegex = /`([^`]+)`/g;\n for (const match of markdown.matchAll(inlineCodeRegex)) {\n const candidate = (match[1] ?? \"\").trim();\n if (isLikelyRelativePath(candidate)) {\n references.add(cleanReferenceTarget(candidate) as string);\n }\n }\n\n const barePathRegex = /\\b(?:scripts|references|assets)\\/[A-Za-z0-9._\\-/]+/g;\n for (const match of markdown.matchAll(barePathRegex)) {\n const candidate = match[0];\n if (candidate) {\n references.add(cleanReferenceTarget(candidate) as string);\n }\n }\n\n return Array.from(references);\n}\n\nexport function cleanReferenceTarget(target: string): string | null {\n if (!target) {\n return null;\n }\n\n let cleaned = target.trim();\n\n if (cleaned.startsWith(\"<\") && cleaned.endsWith(\">\")) {\n cleaned = cleaned.slice(1, -1).trim();\n }\n\n if (cleaned === \"\" || cleaned.startsWith(\"#\")) {\n return null;\n }\n\n if (/^(https?:|mailto:|tel:)/i.test(cleaned)) {\n return null;\n }\n\n const hashIndex = cleaned.indexOf(\"#\");\n if (hashIndex >= 0) {\n cleaned = cleaned.slice(0, hashIndex).trim();\n }\n\n return cleaned || null;\n}\n\nexport function isLikelyRelativePath(candidate: string): boolean {\n if (!candidate) {\n return false;\n }\n\n if (candidate.startsWith(\"/\")) {\n return false;\n }\n\n if (/^[A-Za-z]:\\\\/.test(candidate)) {\n return false;\n }\n\n if (/^(https?:|mailto:|tel:)/i.test(candidate)) {\n return false;\n }\n\n if (RELATIVE_LINK_PREFIXES.some((prefix) => candidate.startsWith(prefix))) {\n return true;\n }\n\n return /^[A-Za-z0-9._-]+(?:\\/[A-Za-z0-9._-]+)+$/.test(candidate);\n}\n","import { LintContext } from \"./context.js\";\nimport { LintIssue } from \"./types.js\";\n\nexport function runCompatibilityChecks(context: LintContext): LintIssue[] {\n const issues: LintIssue[] = [];\n const frontmatter = context.frontmatter.data ?? {};\n const body = context.frontmatter.content;\n\n const hasAllowedTools = Object.prototype.hasOwnProperty.call(frontmatter, \"allowed-tools\");\n const mentionsClaudeOnly = /\\bclaude code\\b/i.test(body);\n const mentionsCodexOnly = /\\bcodex\\b/i.test(body) && !/\\bopenai\\b/i.test(body);\n\n if (hasAllowedTools) {\n issues.push({\n id: \"compat.allowed-tools\",\n title: \"Platform-Specific Frontmatter\",\n status: \"warn\",\n message: \"Frontmatter includes allowed-tools, which is typically Claude-specific.\",\n suggestion: \"Document fallback behavior for platforms that ignore allowed-tools.\"\n });\n } else {\n issues.push({\n id: \"compat.allowed-tools\",\n title: \"Platform-Specific Frontmatter\",\n status: \"pass\",\n message: \"No known provider-specific frontmatter keys detected.\"\n });\n }\n\n if (mentionsClaudeOnly || mentionsCodexOnly) {\n const platform = mentionsClaudeOnly ? \"Claude\" : \"Codex\";\n issues.push({\n id: \"compat.provider-phrasing\",\n title: \"Provider-Specific Language\",\n status: \"warn\",\n message: `Skill body appears tuned to ${platform}-specific behavior.`,\n suggestion: \"Add neutral instructions or an explicit compatibility note for other agents.\"\n });\n } else {\n issues.push({\n id: \"compat.provider-phrasing\",\n title: \"Provider-Specific Language\",\n status: \"pass\",\n message: \"Skill body appears provider-neutral.\"\n });\n }\n\n const likelyCompatibility = hasAllowedTools || mentionsClaudeOnly || mentionsCodexOnly\n ? \"Likely compatible with some agents, but includes platform-specific assumptions.\"\n : \"Likely broadly compatible across Anthropic, OpenAI/Codex-style, and other markdown skill runners.\";\n\n issues.push({\n id: \"compat.summary\",\n title: \"Compatibility Hint\",\n status: hasAllowedTools || mentionsClaudeOnly || mentionsCodexOnly ? \"warn\" : \"pass\",\n message: likelyCompatibility\n });\n\n return issues;\n}\n","import { LintContext } from \"./context.js\";\nimport { LintIssue } from \"./types.js\";\n\nconst VAGUE_PATTERNS = [\n /\\bdo something appropriate\\b/i,\n /\\bhandle as needed\\b/i,\n /\\buse best judgment\\b/i,\n /\\bif possible\\b/i,\n /\\bwhen relevant\\b/i,\n /\\bdo what seems right\\b/i\n];\n\nconst SECRET_PATTERNS: Array<{ label: string; regex: RegExp }> = [\n { label: \"OpenAI key\", regex: /\\bsk-[A-Za-z0-9]{20,}\\b/ },\n { label: \"AWS access key\", regex: /\\bAKIA[0-9A-Z]{16}\\b/ },\n { label: \"GitHub token\", regex: /\\bghp_[A-Za-z0-9]{20,}\\b/ },\n { label: \"Slack token\", regex: /\\bxox[baprs]-[A-Za-z0-9-]{20,}\\b/ },\n { label: \"Generic private key header\", regex: /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/ }\n];\n\nexport function runContentChecks(context: LintContext): LintIssue[] {\n const issues: LintIssue[] = [];\n const body = context.frontmatter.content;\n const bodyLines = body\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n const description = typeof context.frontmatter.data?.description === \"string\" ? context.frontmatter.data.description : \"\";\n\n if (!/^#{1,6}\\s+\\S+/m.test(body)) {\n issues.push({\n id: \"content.headers\",\n title: \"Section Headers\",\n status: \"warn\",\n message: \"No markdown headers found in SKILL.md body.\",\n suggestion: \"Add section headers to improve scannability and maintenance.\"\n });\n } else {\n issues.push({\n id: \"content.headers\",\n title: \"Section Headers\",\n status: \"pass\",\n message: \"SKILL.md contains markdown section headers.\"\n });\n }\n\n const hasExamples = /example/i.test(body) || /```[\\s\\S]*?```/.test(body);\n if (!hasExamples) {\n issues.push({\n id: \"content.examples\",\n title: \"Examples\",\n status: \"warn\",\n message: \"No examples detected in SKILL.md body.\",\n suggestion: \"Add at least one concrete example to guide usage.\"\n });\n } else {\n issues.push({\n id: \"content.examples\",\n title: \"Examples\",\n status: \"pass\",\n message: \"Examples were detected in SKILL.md.\"\n });\n }\n\n const vagueMatches = VAGUE_PATTERNS.filter((pattern) => pattern.test(body));\n if (vagueMatches.length > 0) {\n issues.push({\n id: \"content.vagueness\",\n title: \"Instruction Specificity\",\n status: \"warn\",\n message: \"Potentially vague instruction phrases detected.\",\n suggestion: \"Replace vague guidance with explicit decision rules or step-by-step instructions.\"\n });\n } else {\n issues.push({\n id: \"content.vagueness\",\n title: \"Instruction Specificity\",\n status: \"pass\",\n message: \"No obvious vague placeholder phrasing found.\"\n });\n }\n\n if (context.frontmatter.rawFrontmatter && /[<>]/.test(context.frontmatter.rawFrontmatter)) {\n issues.push({\n id: \"content.frontmatter-angle-brackets\",\n title: \"Frontmatter Angle Brackets\",\n status: \"warn\",\n message: \"Frontmatter contains angle bracket characters (< or >), which can be misinterpreted in some agents.\",\n suggestion: \"Remove XML-like tags from frontmatter values when possible.\"\n });\n } else {\n issues.push({\n id: \"content.frontmatter-angle-brackets\",\n title: \"Frontmatter Angle Brackets\",\n status: \"pass\",\n message: \"No angle bracket tokens detected in frontmatter.\"\n });\n }\n\n const secretHits = new Set<string>();\n for (const pattern of SECRET_PATTERNS) {\n if (pattern.regex.test(context.skill.raw)) {\n secretHits.add(pattern.label);\n }\n }\n if (secretHits.size > 0) {\n issues.push({\n id: \"content.secrets\",\n title: \"Hardcoded Secrets\",\n status: \"fail\",\n message: `Potential secrets detected (${Array.from(secretHits).join(\", \")}).`,\n suggestion: \"Remove secrets from skill files and use environment variables or secret managers.\"\n });\n } else {\n issues.push({\n id: \"content.secrets\",\n title: \"Hardcoded Secrets\",\n status: \"pass\",\n message: \"No obvious API keys or secrets patterns were detected.\"\n });\n }\n\n if (bodyLines.length < 10) {\n issues.push({\n id: \"content.body-length\",\n title: \"Body Completeness\",\n status: \"warn\",\n message: `SKILL.md body has only ${bodyLines.length} non-empty lines.`,\n suggestion: \"Add more detailed instructions; short bodies are often incomplete.\"\n });\n } else {\n issues.push({\n id: \"content.body-length\",\n title: \"Body Completeness\",\n status: \"pass\",\n message: `SKILL.md body has ${bodyLines.length} non-empty lines.`\n });\n }\n\n if (description && description.length < 50) {\n issues.push({\n id: \"content.description-length\",\n title: \"Description Specificity\",\n status: \"warn\",\n message: `Description length is ${description.length} characters, which may be too vague for reliable triggering.`,\n suggestion: \"Expand description with concrete scope and activation conditions.\"\n });\n } else if (description) {\n issues.push({\n id: \"content.description-length\",\n title: \"Description Specificity\",\n status: \"pass\",\n message: \"Description length is sufficient for triggerability heuristics.\"\n });\n }\n\n return issues;\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport {\n cleanReferenceTarget,\n extractRelativeFileReferences,\n isLikelyRelativePath\n} from \"../skill-parser.js\";\nimport { pathExists, toPosixPath } from \"../../utils/fs.js\";\nimport { LintContext } from \"./context.js\";\nimport { LintIssue } from \"./types.js\";\n\nfunction isPathInsideRoot(root: string, candidate: string): boolean {\n const relative = path.relative(root, candidate);\n return !relative.startsWith(\"..\") && !path.isAbsolute(relative);\n}\n\nasync function detectNestedReferenceChain(skillRoot: string, rootContent: string): Promise<number> {\n const initialReferences = extractRelativeFileReferences(rootContent);\n let maxDepth = 0;\n\n for (const reference of initialReferences) {\n const firstLevelPath = path.resolve(skillRoot, reference);\n if (!(await pathExists(firstLevelPath))) {\n continue;\n }\n const firstLevelRaw = await fs.readFile(firstLevelPath, \"utf8\");\n const secondLevelRefs = extractRelativeFileReferences(firstLevelRaw);\n if (secondLevelRefs.length > 0) {\n maxDepth = Math.max(maxDepth, 1);\n }\n\n for (const secondLevelReference of secondLevelRefs) {\n const secondLevelPath = path.resolve(path.dirname(firstLevelPath), secondLevelReference);\n if (!(await pathExists(secondLevelPath))) {\n continue;\n }\n const secondLevelRaw = await fs.readFile(secondLevelPath, \"utf8\");\n const thirdLevelRefs = extractRelativeFileReferences(secondLevelRaw);\n if (thirdLevelRefs.length > 0) {\n maxDepth = Math.max(maxDepth, 2);\n }\n }\n }\n\n return maxDepth;\n}\n\nexport async function runDisclosureChecks(context: LintContext): Promise<LintIssue[]> {\n const issues: LintIssue[] = [];\n const references = extractRelativeFileReferences(context.skill.raw);\n const referencesDir = path.join(context.skill.skillRoot, \"references\");\n\n if (context.skill.lineCount > 200 && !(await pathExists(referencesDir))) {\n issues.push({\n id: \"disclosure.skill-split\",\n title: \"Progressive Disclosure\",\n status: \"warn\",\n message: \"SKILL.md exceeds 200 lines and no references/ directory is present.\",\n suggestion: \"Move detailed material into references/ files and keep SKILL.md focused.\"\n });\n } else {\n issues.push({\n id: \"disclosure.skill-split\",\n title: \"Progressive Disclosure\",\n status: \"pass\",\n message: \"Top-level file length and references/ usage look reasonable.\"\n });\n }\n\n const nonRelativeOrEscaping: string[] = [];\n for (const rawReference of references) {\n const cleaned = cleanReferenceTarget(rawReference);\n if (!cleaned) {\n continue;\n }\n if (path.isAbsolute(cleaned) || /^[A-Za-z]:\\\\/.test(cleaned) || cleaned.startsWith(\"~\")) {\n nonRelativeOrEscaping.push(cleaned);\n continue;\n }\n if (!isLikelyRelativePath(cleaned)) {\n nonRelativeOrEscaping.push(cleaned);\n continue;\n }\n const resolved = path.resolve(context.skill.skillRoot, cleaned);\n if (!isPathInsideRoot(context.skill.skillRoot, resolved)) {\n nonRelativeOrEscaping.push(cleaned);\n }\n }\n\n if (nonRelativeOrEscaping.length > 0) {\n issues.push({\n id: \"disclosure.relative-path-root\",\n title: \"Reference Path Scope\",\n status: \"fail\",\n message: `Found non-relative or out-of-root references: ${nonRelativeOrEscaping.join(\", \")}`,\n suggestion: \"Use relative paths that stay within the skill root directory.\"\n });\n } else {\n issues.push({\n id: \"disclosure.relative-path-root\",\n title: \"Reference Path Scope\",\n status: \"pass\",\n message: \"All detected file references are relative and scoped to skill root.\"\n });\n }\n\n const chainDepth = await detectNestedReferenceChain(context.skill.skillRoot, context.skill.raw);\n if (chainDepth > 1) {\n issues.push({\n id: \"disclosure.reference-depth\",\n title: \"Reference Chain Depth\",\n status: \"warn\",\n message: \"Deep reference chains detected (>1 level).\",\n suggestion: \"Avoid linking from references to more nested references where possible.\"\n });\n } else {\n issues.push({\n id: \"disclosure.reference-depth\",\n title: \"Reference Chain Depth\",\n status: \"pass\",\n message: \"Reference depth is shallow and easy to navigate.\"\n });\n }\n\n const normalizedReferences = references.map((item) => toPosixPath(item));\n if (normalizedReferences.some((item) => item.includes(\"../\"))) {\n issues.push({\n id: \"disclosure.parent-traversal\",\n title: \"Parent Traversal\",\n status: \"warn\",\n message: \"References include parent-directory traversal (../).\",\n suggestion: \"Prefer references rooted within the skill directory for portability.\"\n });\n } else {\n issues.push({\n id: \"disclosure.parent-traversal\",\n title: \"Parent Traversal\",\n status: \"pass\",\n message: \"No parent-directory traversal references detected.\"\n });\n }\n\n return issues;\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nexport async function pathExists(targetPath: string): Promise<boolean> {\n try {\n await fs.access(targetPath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function listFilesRecursive(directory: string): Promise<string[]> {\n const entries = await fs.readdir(directory, { withFileTypes: true });\n const files: string[] = [];\n\n for (const entry of entries) {\n const absolutePath = path.join(directory, entry.name);\n if (entry.isDirectory()) {\n files.push(...(await listFilesRecursive(absolutePath)));\n continue;\n }\n if (entry.isFile()) {\n files.push(absolutePath);\n }\n }\n\n return files;\n}\n\nexport async function readJsonFile<T>(filePath: string): Promise<T> {\n const raw = await fs.readFile(filePath, \"utf8\");\n return JSON.parse(raw) as T;\n}\n\nexport async function writeJsonFile(filePath: string, data: unknown): Promise<void> {\n const absolute = path.resolve(filePath);\n await fs.mkdir(path.dirname(absolute), { recursive: true });\n await fs.writeFile(absolute, `${JSON.stringify(data, null, 2)}\\n`, \"utf8\");\n}\n\nexport function toPosixPath(inputPath: string): string {\n return inputPath.split(path.sep).join(\"/\");\n}\n","import { LintContext } from \"./context.js\";\nimport { LintIssue } from \"./types.js\";\n\nconst SKILL_NAME_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\nfunction getStringField(data: Record<string, unknown> | null, key: string): string | null {\n if (!data) {\n return null;\n }\n const value = data[key];\n if (typeof value !== \"string\") {\n return null;\n }\n return value;\n}\n\nfunction descriptionLooksActionable(description: string): boolean {\n const whatPattern =\n /\\b(create|build|generate|analyze|test|validate|review|refactor|debug|audit|compose|transform|summari[sz]e|plan)\\b/i;\n const whenPattern = /\\b(when|if|for|whenever|use this|ideal for|best for|should use)\\b/i;\n return whatPattern.test(description) && whenPattern.test(description);\n}\n\nexport function runFrontmatterChecks(context: LintContext): LintIssue[] {\n const issues: LintIssue[] = [];\n\n if (!context.frontmatter.hasFrontmatter) {\n issues.push({\n id: \"frontmatter.exists\",\n title: \"Frontmatter Presence\",\n status: \"fail\",\n message: \"SKILL.md is missing YAML frontmatter delimited by --- blocks.\",\n suggestion: \"Add YAML frontmatter at the top with at least name and description.\"\n });\n return issues;\n }\n\n if (context.frontmatter.error) {\n issues.push({\n id: \"frontmatter.valid-yaml\",\n title: \"Frontmatter YAML\",\n status: \"fail\",\n message: `Frontmatter is not valid YAML: ${context.frontmatter.error}`,\n suggestion: \"Fix YAML syntax so the frontmatter parses as an object.\"\n });\n return issues;\n }\n\n issues.push({\n id: \"frontmatter.valid-yaml\",\n title: \"Frontmatter YAML\",\n status: \"pass\",\n message: \"Frontmatter exists and parses correctly.\"\n });\n\n const data = context.frontmatter.data ?? {};\n const name = getStringField(data, \"name\");\n if (!name) {\n issues.push({\n id: \"frontmatter.name.required\",\n title: \"Frontmatter Name\",\n status: \"fail\",\n message: \"Missing required frontmatter field: name.\",\n suggestion: \"Set name to lowercase words separated by single hyphens.\"\n });\n } else if (name.length > 64) {\n issues.push({\n id: \"frontmatter.name.length\",\n title: \"Frontmatter Name Length\",\n status: \"fail\",\n message: `name is too long (${name.length} chars, max 64).`,\n suggestion: \"Shorten the skill name to 64 characters or fewer.\"\n });\n } else if (!SKILL_NAME_REGEX.test(name)) {\n issues.push({\n id: \"frontmatter.name.format\",\n title: \"Frontmatter Name Format\",\n status: \"fail\",\n message: \"name must be lowercase alphanumeric with single hyphen separators only.\",\n suggestion: \"Use format like 'api-tester' or 'code-review'.\"\n });\n } else {\n issues.push({\n id: \"frontmatter.name.valid\",\n title: \"Frontmatter Name\",\n status: \"pass\",\n message: \"name is present and follows naming conventions.\"\n });\n }\n\n const description = getStringField(data, \"description\");\n if (!description || description.trim() === \"\") {\n issues.push({\n id: \"frontmatter.description.required\",\n title: \"Frontmatter Description\",\n status: \"fail\",\n message: \"Missing required frontmatter field: description.\",\n suggestion: \"Add a clear description of what the skill does and when to use it.\"\n });\n } else if (description.length > 1024) {\n issues.push({\n id: \"frontmatter.description.length\",\n title: \"Frontmatter Description Length\",\n status: \"fail\",\n message: `description is too long (${description.length} chars, max 1024).`,\n suggestion: \"Keep description concise while still specific.\"\n });\n } else {\n issues.push({\n id: \"frontmatter.description.valid\",\n title: \"Frontmatter Description\",\n status: \"pass\",\n message: \"description is present and within allowed length.\"\n });\n }\n\n const license = getStringField(data, \"license\");\n if (!license || license.trim() === \"\") {\n issues.push({\n id: \"frontmatter.license.recommended\",\n title: \"Frontmatter License\",\n status: \"warn\",\n message: \"No license field found in frontmatter.\",\n suggestion: \"Add a license (for example: MIT) to clarify reuse terms.\"\n });\n } else {\n issues.push({\n id: \"frontmatter.license.present\",\n title: \"Frontmatter License\",\n status: \"pass\",\n message: \"license field is present.\"\n });\n }\n\n if (description && description.trim() !== \"\" && !descriptionLooksActionable(description)) {\n issues.push({\n id: \"frontmatter.description.triggerability\",\n title: \"Description Trigger Clarity\",\n status: \"warn\",\n message: \"Description should explain both what the skill does and when it should be used.\",\n suggestion: \"Include explicit 'use when...' language plus concrete capability wording.\"\n });\n } else if (description) {\n issues.push({\n id: \"frontmatter.description.triggerability\",\n title: \"Description Trigger Clarity\",\n status: \"pass\",\n message: \"Description appears to cover both capability and usage context.\"\n });\n }\n\n return issues;\n}\n","import { LintContext } from \"./context.js\";\nimport { LintIssue } from \"./types.js\";\n\ninterface SecurityPattern {\n label: string;\n regex: RegExp;\n}\n\nconst DANGEROUS_COMMAND_PATTERNS: SecurityPattern[] = [\n {\n label: \"Destructive recursive delete\",\n regex: /\\b(?:sudo\\s+)?rm\\s+-rf\\s+(?:\\/|\\*|~\\/|\\.\\.\\/)/i\n },\n {\n label: \"Forceful recursive remove in PowerShell\",\n regex: /\\bRemove-Item\\b[^\\n]*\\b-Recurse\\b[^\\n]*\\b-Force\\b/i\n },\n {\n label: \"Remote script piped directly to shell\",\n regex: /\\b(?:curl|wget|Invoke-WebRequest)\\b[^\\n|]{0,220}\\|\\s*(?:bash|sh|zsh|pwsh|powershell|iex)\\b/i\n }\n];\n\nconst EXFILTRATION_PATTERNS: SecurityPattern[] = [\n {\n label: \"Reading SSH private keys\",\n regex: /\\b(?:cat|type|get-content)\\b[^\\n]*\\.ssh\\/id_(?:rsa|ed25519)\\b/i\n },\n {\n label: \"Reading cloud credential files\",\n regex: /\\b(?:cat|type|get-content)\\b[^\\n]*(?:\\.aws\\/credentials|\\.npmrc|\\.netrc)\\b/i\n },\n {\n label: \"Explicit credential exfiltration\",\n regex: /\\b(?:send|upload|post|exfiltrat(?:e|ion))\\b[^\\n]{0,200}\\b(?:api[_ -]?key|token|secret|credential|\\.env|id_rsa)\\b/i\n }\n];\n\nconst PRIVILEGE_ESCALATION_PATTERNS: SecurityPattern[] = [\n {\n label: \"Uses sudo/root escalation\",\n regex: /\\b(?:sudo|run as root|administrator privileges)\\b/i\n },\n {\n label: \"Asks to disable sandboxing or approvals\",\n regex: /\\b(?:disable sandbox|without approval|skip approval|require_escalated)\\b/i\n },\n {\n label: \"Inline expression execution\",\n regex: /\\b(?:Invoke-Expression|iex)\\b/i\n }\n];\n\nconst SHELL_ACTIVITY_PATTERNS: RegExp[] = [\n /```(?:bash|sh|zsh|pwsh|powershell|cmd)\\b[\\s\\S]*?```/i,\n /\\b(?:bash|sh|pwsh|powershell|cmd(?:\\.exe)?)\\b/i,\n /\\b(?:npm|pnpm|yarn|pip|git|docker|kubectl)\\s+[A-Za-z0-9-]/i\n];\n\nconst SAFETY_GUARDRAIL_PATTERN =\n /\\b(?:ask before|confirm|approval|dry[- ]run|sandbox|least privilege|redact|never expose|do not reveal)\\b/i;\n\nfunction collectMatches(content: string, patterns: SecurityPattern[]): string[] {\n const matches: string[] = [];\n for (const pattern of patterns) {\n if (pattern.regex.test(content)) {\n matches.push(pattern.label);\n }\n }\n return matches;\n}\n\nexport function runSecurityChecks(context: LintContext): LintIssue[] {\n const issues: LintIssue[] = [];\n const skillText = context.skill.raw;\n\n const dangerousCommandHits = collectMatches(skillText, DANGEROUS_COMMAND_PATTERNS);\n if (dangerousCommandHits.length > 0) {\n issues.push({\n id: \"security.dangerous-command-patterns\",\n title: \"Dangerous Command Patterns\",\n status: \"fail\",\n message: `Potentially dangerous command instruction patterns found: ${dangerousCommandHits.join(\", \")}.`,\n suggestion: \"Remove destructive/pipe-exec command examples or wrap them with explicit safety constraints.\"\n });\n } else {\n issues.push({\n id: \"security.dangerous-command-patterns\",\n title: \"Dangerous Command Patterns\",\n status: \"pass\",\n message: \"No high-risk destructive or direct pipe-to-shell patterns detected.\"\n });\n }\n\n const exfiltrationHits = collectMatches(skillText, EXFILTRATION_PATTERNS);\n if (exfiltrationHits.length > 0) {\n issues.push({\n id: \"security.exfiltration-patterns\",\n title: \"Sensitive Data Exfiltration\",\n status: \"fail\",\n message: `Possible sensitive data exfiltration patterns found: ${exfiltrationHits.join(\", \")}.`,\n suggestion: \"Remove instructions that access or transmit secrets/credential files.\"\n });\n } else {\n issues.push({\n id: \"security.exfiltration-patterns\",\n title: \"Sensitive Data Exfiltration\",\n status: \"pass\",\n message: \"No obvious credential access/exfiltration instructions detected.\"\n });\n }\n\n const escalationHits = collectMatches(skillText, PRIVILEGE_ESCALATION_PATTERNS);\n if (escalationHits.length > 0) {\n issues.push({\n id: \"security.privilege-escalation\",\n title: \"Privilege Escalation Language\",\n status: \"warn\",\n message: `Potentially risky privilege/execution language detected: ${escalationHits.join(\", \")}.`,\n suggestion: \"Prefer least-privilege execution and explicit approval steps for elevated commands.\"\n });\n } else {\n issues.push({\n id: \"security.privilege-escalation\",\n title: \"Privilege Escalation Language\",\n status: \"pass\",\n message: \"No obvious privilege-escalation language detected.\"\n });\n }\n\n const hasShellActivity = SHELL_ACTIVITY_PATTERNS.some((pattern) => pattern.test(skillText));\n if (hasShellActivity && !SAFETY_GUARDRAIL_PATTERN.test(skillText)) {\n issues.push({\n id: \"security.safety-guardrails\",\n title: \"Execution Safety Guardrails\",\n status: \"warn\",\n message: \"Shell/tool execution is present, but no explicit safety guardrails were detected.\",\n suggestion: \"Add guidance such as approval requirements, dry-run mode, scope checks, and redaction rules.\"\n });\n } else {\n issues.push({\n id: \"security.safety-guardrails\",\n title: \"Execution Safety Guardrails\",\n status: \"pass\",\n message: hasShellActivity\n ? \"Shell/tool execution instructions include at least one safety guardrail.\"\n : \"No shell/tool execution instructions detected.\"\n });\n }\n\n return issues;\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { extractRelativeFileReferences } from \"../skill-parser.js\";\nimport { listFilesRecursive, pathExists, toPosixPath } from \"../../utils/fs.js\";\nimport { LintContext } from \"./context.js\";\nimport { LintIssue } from \"./types.js\";\n\nfunction hasTableOfContents(content: string): boolean {\n if (/^#{1,6}\\s+table of contents\\b/im.test(content)) {\n return true;\n }\n return /^\\s*[-*]\\s+\\[[^\\]]+\\]\\(#[^)]+\\)/im.test(content);\n}\n\nfunction classifyReferencePath(relativePath: string): \"scripts\" | \"references\" | \"assets\" | \"other\" {\n const normalized = toPosixPath(relativePath).replace(/^\\.\\//, \"\");\n if (normalized.startsWith(\"scripts/\")) {\n return \"scripts\";\n }\n if (normalized.startsWith(\"references/\")) {\n return \"references\";\n }\n if (normalized.startsWith(\"assets/\")) {\n return \"assets\";\n }\n return \"other\";\n}\n\nexport async function runStructureChecks(context: LintContext): Promise<LintIssue[]> {\n const issues: LintIssue[] = [];\n const references = extractRelativeFileReferences(context.skill.raw);\n\n if (context.skill.lineCount > 500) {\n issues.push({\n id: \"structure.skill-size\",\n title: \"SKILL.md Size\",\n status: \"warn\",\n message: `SKILL.md is ${context.skill.lineCount} lines (recommended max is 500).`,\n suggestion: \"Split detailed guidance into references/ files.\"\n });\n } else {\n issues.push({\n id: \"structure.skill-size\",\n title: \"SKILL.md Size\",\n status: \"pass\",\n message: `SKILL.md length is ${context.skill.lineCount} lines.`\n });\n }\n\n const referencesDir = path.join(context.skill.skillRoot, \"references\");\n if (await pathExists(referencesDir)) {\n const files = await listFilesRecursive(referencesDir);\n let oversizedWithoutToc = 0;\n for (const file of files) {\n const raw = await fs.readFile(file, \"utf8\");\n const lineCount = raw === \"\" ? 0 : raw.split(/\\r?\\n/).length;\n if (lineCount > 300 && !hasTableOfContents(raw)) {\n oversizedWithoutToc += 1;\n issues.push({\n id: `structure.references.toc.${toPosixPath(path.relative(context.skill.skillRoot, file))}`,\n title: \"Reference File Navigation\",\n status: \"warn\",\n message: `${toPosixPath(path.relative(context.skill.skillRoot, file))} is ${lineCount} lines and has no table of contents.`,\n suggestion: \"Add a table of contents for long reference files.\"\n });\n }\n }\n\n if (oversizedWithoutToc === 0) {\n issues.push({\n id: \"structure.references.toc\",\n title: \"Reference File Navigation\",\n status: \"pass\",\n message: \"No oversized reference files missing a table of contents.\"\n });\n }\n } else {\n issues.push({\n id: \"structure.references.toc\",\n title: \"Reference File Navigation\",\n status: \"pass\",\n message: \"No references/ directory found, so no long reference files to validate.\"\n });\n }\n\n const missingByType: Record<string, string[]> = {\n scripts: [],\n references: [],\n assets: [],\n other: []\n };\n\n for (const reference of references) {\n const resolved = path.resolve(context.skill.skillRoot, reference);\n if (!(await pathExists(resolved))) {\n const kind = classifyReferencePath(reference);\n missingByType[kind].push(reference);\n }\n }\n\n const categories: Array<{ key: \"scripts\" | \"references\" | \"assets\"; title: string }> = [\n { key: \"scripts\", title: \"Script References\" },\n { key: \"references\", title: \"Reference File Links\" },\n { key: \"assets\", title: \"Asset References\" }\n ];\n\n for (const category of categories) {\n const missing = missingByType[category.key];\n if (missing.length > 0) {\n issues.push({\n id: `structure.${category.key}.exists`,\n title: category.title,\n status: \"fail\",\n message: `Missing referenced ${category.key} file(s): ${missing.join(\", \")}`,\n suggestion: \"Create the files or fix the paths in SKILL.md.\"\n });\n } else {\n issues.push({\n id: `structure.${category.key}.exists`,\n title: category.title,\n status: \"pass\",\n message: `All referenced ${category.key} files exist.`\n });\n }\n }\n\n const missingGeneric = missingByType.other;\n if (missingGeneric.length > 0) {\n issues.push({\n id: \"structure.relative-links.broken\",\n title: \"Relative Links\",\n status: \"fail\",\n message: `Broken relative path reference(s): ${missingGeneric.join(\", \")}`,\n suggestion: \"Fix or remove broken file links.\"\n });\n } else {\n issues.push({\n id: \"structure.relative-links.broken\",\n title: \"Relative Links\",\n status: \"pass\",\n message: \"No broken generic relative file references were found.\"\n });\n }\n\n return issues;\n}\n","import { loadSkillFile, parseFrontmatter } from \"../skill-parser.js\";\nimport { runCompatibilityChecks } from \"./compat.js\";\nimport { LintContext } from \"./context.js\";\nimport { runContentChecks } from \"./content.js\";\nimport { runDisclosureChecks } from \"./disclosure.js\";\nimport { runFrontmatterChecks } from \"./frontmatter.js\";\nimport { runSecurityChecks } from \"./security.js\";\nimport { runStructureChecks } from \"./structure.js\";\nimport { LintIssue, LintReport, LintSummary } from \"./types.js\";\n\nfunction summarizeIssues(issues: LintIssue[]): LintSummary {\n const summary: LintSummary = {\n total: issues.length,\n passed: 0,\n warnings: 0,\n failures: 0\n };\n\n for (const issue of issues) {\n if (issue.status === \"pass\") {\n summary.passed += 1;\n continue;\n }\n if (issue.status === \"warn\") {\n summary.warnings += 1;\n continue;\n }\n summary.failures += 1;\n }\n\n return summary;\n}\n\nexport async function runLinter(inputPath: string): Promise<LintReport> {\n const skill = await loadSkillFile(inputPath);\n const frontmatter = parseFrontmatter(skill.raw);\n const context: LintContext = {\n skill,\n frontmatter\n };\n\n const issues: LintIssue[] = [];\n issues.push(...runFrontmatterChecks(context));\n issues.push(...(await runStructureChecks(context)));\n issues.push(...runContentChecks(context));\n issues.push(...runSecurityChecks(context));\n issues.push(...(await runDisclosureChecks(context)));\n issues.push(...runCompatibilityChecks(context));\n\n return {\n target: inputPath,\n issues,\n summary: summarizeIssues(issues)\n };\n}\n\nexport type { LintIssue, LintReport, LintSummary } from \"./types.js\";\n","import { Chalk, ChalkInstance } from \"chalk\";\nimport { LintIssue, LintReport } from \"../core/linter/index.js\";\nimport { TriggerTestResult } from \"../core/trigger-tester.js\";\nimport { EvalResult } from \"../core/eval-runner.js\";\nimport { CheckRunResult } from \"../core/check-runner.js\";\n\nfunction getChalkInstance(enableColor: boolean): ChalkInstance {\n return new Chalk({ level: enableColor ? 1 : 0 });\n}\n\nfunction renderIssueLine(issue: LintIssue, c: ChalkInstance): string {\n const label =\n issue.status === \"pass\" ? c.green(\"PASS\") : issue.status === \"warn\" ? c.yellow(\"WARN\") : c.red(\"FAIL\");\n const detail = issue.suggestion ? `\\n suggestion: ${issue.suggestion}` : \"\";\n return ` ${label} ${issue.title}\\n ${issue.message}${detail}`;\n}\n\nexport function renderLintReport(report: LintReport, enableColor: boolean): string {\n const c = getChalkInstance(enableColor);\n const { passed, warnings, failures, total } = report.summary;\n\n const headerLines = [\n `┌───────────────────────────────────────────────────────────────┐`,\n `│ skilltest lint │`,\n `├───────────────────────────────────────────────────────────────┤`,\n `│ target: ${report.target}`,\n `│ summary: ${passed}/${total} checks passed, ${warnings} warnings, ${failures} failures`,\n `└───────────────────────────────────────────────────────────────┘`\n ];\n\n const renderedIssues = report.issues.map((issue) => renderIssueLine(issue, c)).join(\"\\n\");\n return `${headerLines.join(\"\\n\")}\\n${renderedIssues}`;\n}\n\nfunction formatPercent(value: number): string {\n return `${(value * 100).toFixed(1)}%`;\n}\n\nexport function renderTriggerReport(result: TriggerTestResult, enableColor: boolean, verbose: boolean): string {\n const c = getChalkInstance(enableColor);\n const lines: string[] = [];\n lines.push(\"┌───────────────────────────────────────────────────────────────┐\");\n lines.push(\"│ skilltest trigger │\");\n lines.push(\"├───────────────────────────────────────────────────────────────┤\");\n lines.push(`│ skill: ${result.skillName}`);\n lines.push(`│ provider/model: ${result.provider}/${result.model}`);\n lines.push(\n `│ precision: ${formatPercent(result.metrics.precision)} recall: ${formatPercent(result.metrics.recall)} f1: ${formatPercent(result.metrics.f1)}`\n );\n lines.push(\n `│ TP ${result.metrics.truePositives} TN ${result.metrics.trueNegatives} FP ${result.metrics.falsePositives} FN ${result.metrics.falseNegatives}`\n );\n lines.push(\"└───────────────────────────────────────────────────────────────┘\");\n\n for (const [index, testCase] of result.cases.entries()) {\n const status = testCase.matched ? c.green(\"PASS\") : c.red(\"FAIL\");\n lines.push(`${index + 1}. ${status} query: ${testCase.query}`);\n lines.push(` expected: ${testCase.expected} | actual: ${testCase.actual}`);\n if (verbose && testCase.rawModelResponse) {\n lines.push(` model: ${testCase.rawModelResponse.replace(/\\s+/g, \" \").trim()}`);\n }\n }\n\n lines.push(\"Suggestions:\");\n for (const suggestion of result.suggestions) {\n lines.push(`- ${suggestion}`);\n }\n\n return lines.join(\"\\n\");\n}\n\nexport function renderEvalReport(result: EvalResult, enableColor: boolean, verbose: boolean): string {\n const c = getChalkInstance(enableColor);\n const lines: string[] = [];\n lines.push(\"┌───────────────────────────────────────────────────────────────┐\");\n lines.push(\"│ skilltest eval │\");\n lines.push(\"├───────────────────────────────────────────────────────────────┤\");\n lines.push(`│ skill: ${result.skillName}`);\n lines.push(`│ provider/model: ${result.provider}/${result.model}`);\n lines.push(`│ grader model: ${result.graderModel}`);\n lines.push(`│ assertions passed: ${result.summary.passedAssertions}/${result.summary.totalAssertions}`);\n lines.push(\"└───────────────────────────────────────────────────────────────┘\");\n\n for (const [index, promptResult] of result.results.entries()) {\n lines.push(`${index + 1}. prompt: ${promptResult.prompt}`);\n lines.push(` response summary: ${promptResult.responseSummary.replace(/\\s+/g, \" \").trim()}`);\n for (const assertion of promptResult.assertions) {\n const status = assertion.passed ? c.green(\"PASS\") : c.red(\"FAIL\");\n lines.push(` ${status} ${assertion.assertion}`);\n lines.push(` evidence: ${assertion.evidence}`);\n }\n if (verbose) {\n lines.push(` full response: ${promptResult.response}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction gateStatusLabel(value: boolean | null, c: ChalkInstance): string {\n if (value === null) {\n return c.yellow(\"SKIP\");\n }\n return value ? c.green(\"PASS\") : c.red(\"FAIL\");\n}\n\nexport function renderCheckReport(result: CheckRunResult, enableColor: boolean, verbose: boolean): string {\n const c = getChalkInstance(enableColor);\n const lines: string[] = [];\n\n const lintGate = gateStatusLabel(result.gates.lintPassed, c);\n const triggerGate = gateStatusLabel(result.gates.triggerPassed, c);\n const evalGate = gateStatusLabel(result.gates.evalPassed, c);\n const overallGate = result.gates.overallPassed ? c.green(\"PASS\") : c.red(\"FAIL\");\n\n lines.push(\"skilltest check\");\n lines.push(`target: ${result.target}`);\n lines.push(`provider/model: ${result.provider}/${result.model}`);\n lines.push(`grader model: ${result.graderModel}`);\n lines.push(\n `thresholds: min-f1=${result.thresholds.minF1.toFixed(2)} min-assert-pass-rate=${result.thresholds.minAssertPassRate.toFixed(2)}`\n );\n lines.push(\"\");\n lines.push(\"Lint\");\n lines.push(\n `- ${lintGate} ${result.lint.summary.passed}/${result.lint.summary.total} checks passed (${result.lint.summary.warnings} warnings, ${result.lint.summary.failures} failures)`\n );\n\n const lintIssues = verbose ? result.lint.issues : result.lint.issues.filter((issue) => issue.status !== \"pass\");\n for (const issue of lintIssues) {\n lines.push(renderIssueLine(issue, c));\n }\n\n lines.push(\"\");\n lines.push(\"Trigger\");\n if (result.trigger) {\n lines.push(\n `- ${triggerGate} f1=${formatPercent(result.trigger.metrics.f1)} (precision=${formatPercent(result.trigger.metrics.precision)} recall=${formatPercent(result.trigger.metrics.recall)})`\n );\n lines.push(\n ` TP ${result.trigger.metrics.truePositives} TN ${result.trigger.metrics.trueNegatives} FP ${result.trigger.metrics.falsePositives} FN ${result.trigger.metrics.falseNegatives}`\n );\n\n const triggerCases = verbose ? result.trigger.cases : result.trigger.cases.filter((testCase) => !testCase.matched);\n for (const testCase of triggerCases) {\n const status = testCase.matched ? c.green(\"PASS\") : c.red(\"FAIL\");\n lines.push(` - ${status} ${testCase.query}`);\n lines.push(` expected=${testCase.expected} actual=${testCase.actual}`);\n }\n } else {\n lines.push(`- ${triggerGate} ${result.triggerSkippedReason ?? \"Skipped.\"}`);\n }\n\n lines.push(\"\");\n lines.push(\"Eval\");\n if (result.eval) {\n const passRate = result.gates.evalAssertPassRate ?? 0;\n lines.push(\n `- ${evalGate} assertion pass rate=${formatPercent(passRate)} (${result.eval.summary.passedAssertions}/${result.eval.summary.totalAssertions})`\n );\n\n for (const promptResult of result.eval.results) {\n const failedAssertions = promptResult.assertions.filter((assertion) => !assertion.passed);\n if (!verbose && failedAssertions.length === 0) {\n continue;\n }\n lines.push(` - prompt: ${promptResult.prompt}`);\n lines.push(` response summary: ${promptResult.responseSummary.replace(/\\s+/g, \" \").trim()}`);\n const assertionsToRender = verbose ? promptResult.assertions : failedAssertions;\n for (const assertion of assertionsToRender) {\n const assertionStatus = assertion.passed ? c.green(\"PASS\") : c.red(\"FAIL\");\n lines.push(` ${assertionStatus} ${assertion.assertion}`);\n lines.push(` evidence: ${assertion.evidence}`);\n }\n if (verbose) {\n lines.push(` full response: ${promptResult.response}`);\n }\n }\n } else {\n lines.push(`- ${evalGate} ${result.evalSkippedReason ?? \"Skipped.\"}`);\n }\n\n lines.push(\"\");\n lines.push(\"Quality Gate\");\n lines.push(`- lint gate: ${lintGate}`);\n lines.push(`- trigger gate: ${triggerGate}`);\n lines.push(`- eval gate: ${evalGate}`);\n lines.push(`- overall: ${overallGate}`);\n\n return lines.join(\"\\n\");\n}\n","export function renderJson(value: unknown): string {\n return JSON.stringify(value, null, 2);\n}\n","import { Command } from \"commander\";\nimport { renderJson } from \"../reporters/json.js\";\n\nexport interface GlobalCliOptions {\n json: boolean;\n color: boolean;\n}\n\nexport function getGlobalCliOptions(command: Command): GlobalCliOptions {\n const options = command.optsWithGlobals<{ json?: boolean; color?: boolean }>();\n return {\n json: Boolean(options.json),\n color: options.color !== false\n };\n}\n\nexport function writeResult(value: unknown, asJson: boolean): void {\n if (asJson) {\n process.stdout.write(`${renderJson(value)}\\n`);\n return;\n }\n process.stdout.write(`${String(value)}\\n`);\n}\n\nexport function writeError(error: unknown, asJson: boolean): void {\n const message = error instanceof Error ? error.message : String(error);\n if (asJson) {\n process.stdout.write(`${renderJson({ error: message })}\\n`);\n return;\n }\n process.stderr.write(`Error: ${message}\\n`);\n}\n","import { Command } from \"commander\";\nimport { runLinter } from \"../core/linter/index.js\";\nimport { renderLintReport } from \"../reporters/terminal.js\";\nimport { getGlobalCliOptions, writeError, writeResult } from \"./common.js\";\n\nexport function registerLintCommand(program: Command): void {\n program\n .command(\"lint\")\n .description(\"Run static lint checks against a SKILL.md file or skill directory.\")\n .argument(\"<path-to-skill>\", \"Path to SKILL.md or skill directory\")\n .action(async (targetPath: string, _commandOptions: unknown, command: Command) => {\n const globalOptions = getGlobalCliOptions(command);\n\n try {\n const report = await runLinter(targetPath);\n if (globalOptions.json) {\n writeResult(report, true);\n } else {\n writeResult(renderLintReport(report, globalOptions.color), false);\n }\n\n if (report.summary.failures > 0) {\n process.exitCode = 1;\n }\n } catch (error) {\n writeError(error, globalOptions.json);\n process.exitCode = 2;\n }\n });\n}\n","import ora from \"ora\";\nimport { Command } from \"commander\";\nimport { z } from \"zod\";\nimport { runTriggerTest, triggerQueryArraySchema } from \"../core/trigger-tester.js\";\nimport { parseSkillStrict } from \"../core/skill-parser.js\";\nimport { createProvider } from \"../providers/index.js\";\nimport { ProviderName } from \"../providers/types.js\";\nimport { renderTriggerReport } from \"../reporters/terminal.js\";\nimport { readJsonFile, writeJsonFile } from \"../utils/fs.js\";\nimport { getGlobalCliOptions, writeError, writeResult } from \"./common.js\";\n\nconst triggerOptionsSchema = z.object({\n model: z.string(),\n provider: z.enum([\"anthropic\", \"openai\"]),\n queries: z.string().optional(),\n numQueries: z.number().int().min(2),\n saveQueries: z.string().optional(),\n verbose: z.boolean().optional(),\n apiKey: z.string().optional()\n});\n\nconst DEFAULT_ANTHROPIC_MODEL = \"claude-sonnet-4-5-20250929\";\nconst DEFAULT_OPENAI_MODEL = \"gpt-4.1-mini\";\n\nfunction resolveModel(provider: \"anthropic\" | \"openai\", model: string): string {\n if (provider === \"openai\" && model === DEFAULT_ANTHROPIC_MODEL) {\n return DEFAULT_OPENAI_MODEL;\n }\n return model;\n}\n\nexport function registerTriggerCommand(program: Command): void {\n program\n .command(\"trigger\")\n .description(\"Evaluate whether a skill description triggers correctly.\")\n .argument(\"<path-to-skill>\", \"Path to SKILL.md or skill directory\")\n .option(\"--model <model>\", \"Model to use\", DEFAULT_ANTHROPIC_MODEL)\n .option(\"--provider <provider>\", \"LLM provider: anthropic|openai\", \"anthropic\")\n .option(\"--queries <path>\", \"Path to custom test queries JSON\")\n .option(\"--num-queries <n>\", \"Number of auto-generated queries\", (value) => Number.parseInt(value, 10), 20)\n .option(\"--save-queries <path>\", \"Save generated queries to a JSON file\")\n .option(\"--api-key <key>\", \"API key override\")\n .option(\"--verbose\", \"Show full model decisions\")\n .action(async (targetPath: string, commandOptions: unknown, command: Command) => {\n const globalOptions = getGlobalCliOptions(command);\n const parsedOptions = triggerOptionsSchema.safeParse(commandOptions);\n if (!parsedOptions.success) {\n writeError(new Error(parsedOptions.error.issues[0]?.message ?? \"Invalid trigger options.\"), globalOptions.json);\n process.exitCode = 2;\n return;\n }\n\n const options = parsedOptions.data;\n const spinner = globalOptions.json || !process.stdout.isTTY ? null : ora(\"Preparing trigger evaluation...\").start();\n\n try {\n if (options.numQueries % 2 !== 0) {\n throw new Error(\"--num-queries must be an even number so the suite can split should/should-not trigger cases.\");\n }\n\n if (spinner) {\n spinner.text = \"Parsing skill...\";\n }\n const skill = await parseSkillStrict(targetPath);\n\n if (spinner) {\n spinner.text = \"Initializing model provider...\";\n }\n const provider = createProvider(options.provider as ProviderName, options.apiKey);\n\n let queries = undefined;\n if (options.queries) {\n if (spinner) {\n spinner.text = \"Loading custom trigger queries...\";\n }\n const loaded = await readJsonFile<unknown>(options.queries);\n const parsedQueries = triggerQueryArraySchema.safeParse(loaded);\n if (!parsedQueries.success) {\n throw new Error(`Invalid --queries JSON: ${parsedQueries.error.issues[0]?.message ?? \"unknown format issue\"}`);\n }\n queries = parsedQueries.data;\n }\n\n if (spinner) {\n spinner.text = \"Running trigger simulations...\";\n }\n const model = resolveModel(options.provider, options.model);\n const result = await runTriggerTest(skill, {\n model,\n provider,\n queries,\n numQueries: options.numQueries,\n verbose: Boolean(options.verbose)\n });\n\n if (options.saveQueries) {\n await writeJsonFile(options.saveQueries, result.queries);\n }\n\n spinner?.stop();\n if (globalOptions.json) {\n writeResult(result, true);\n } else {\n writeResult(renderTriggerReport(result, globalOptions.color, Boolean(options.verbose)), false);\n }\n } catch (error) {\n spinner?.stop();\n writeError(error, globalOptions.json);\n process.exitCode = 2;\n }\n });\n}\n","import { z } from \"zod\";\nimport { ParsedSkill } from \"./skill-parser.js\";\nimport { LanguageModelProvider } from \"../providers/types.js\";\n\nexport interface TriggerQuery {\n query: string;\n should_trigger: boolean;\n}\n\nexport interface TriggerTestCaseResult {\n query: string;\n shouldTrigger: boolean;\n expected: string;\n actual: string;\n matched: boolean;\n rawModelResponse?: string;\n}\n\nexport interface TriggerMetrics {\n truePositives: number;\n trueNegatives: number;\n falsePositives: number;\n falseNegatives: number;\n precision: number;\n recall: number;\n f1: number;\n}\n\nexport interface TriggerTestResult {\n skillName: string;\n model: string;\n provider: string;\n queries: TriggerQuery[];\n cases: TriggerTestCaseResult[];\n metrics: TriggerMetrics;\n suggestions: string[];\n}\n\nconst triggerQuerySchema = z.object({\n query: z.string().min(1),\n should_trigger: z.boolean()\n});\n\nexport const triggerQueryArraySchema = z.array(triggerQuerySchema);\n\nconst FAKE_SKILLS: Array<{ name: string; description: string }> = [\n { name: \"code-review\", description: \"Reviews code changes for bugs, regressions, and maintainability issues.\" },\n { name: \"api-tester\", description: \"Designs and runs REST API tests, validating status codes and response shapes.\" },\n { name: \"db-migrator\", description: \"Plans and generates safe database migration scripts with rollback guidance.\" },\n { name: \"bug-repro\", description: \"Reproduces reported bugs by building deterministic minimal test cases.\" },\n { name: \"release-notes\", description: \"Drafts release notes from commits and PR metadata for stakeholders.\" },\n { name: \"log-analyzer\", description: \"Analyzes service logs to identify error clusters and likely root causes.\" },\n { name: \"performance-audit\", description: \"Finds hotspots in runtime and suggests profiling-driven optimizations.\" },\n { name: \"security-audit\", description: \"Checks code and config for common security vulnerabilities and risky defaults.\" },\n { name: \"refactor-planner\", description: \"Breaks large refactors into safe incremental steps with validation plans.\" },\n { name: \"schema-designer\", description: \"Designs JSON schemas and validates data contracts for integrations.\" },\n { name: \"docs-writer\", description: \"Writes developer documentation, tutorials, and API usage examples.\" },\n { name: \"cli-scaffolder\", description: \"Creates CLI project skeletons with argument parsing and help text.\" },\n { name: \"incident-triage\", description: \"Triage production incidents with severity tagging and next-action checklists.\" },\n { name: \"test-generator\", description: \"Generates unit and integration test cases from feature requirements.\" },\n { name: \"prompt-tuner\", description: \"Improves prompts for reliability, formatting, and failure handling.\" }\n];\n\nfunction shuffle<T>(values: T[]): T[] {\n const copy = [...values];\n for (let index = copy.length - 1; index > 0; index -= 1) {\n const swapIndex = Math.floor(Math.random() * (index + 1));\n [copy[index], copy[swapIndex]] = [copy[swapIndex], copy[index]];\n }\n return copy;\n}\n\nfunction sample<T>(values: T[], count: number): T[] {\n return shuffle(values).slice(0, Math.max(0, Math.min(count, values.length)));\n}\n\nfunction parseJsonArrayFromModelOutput(raw: string): unknown[] {\n const trimmed = raw.trim();\n if (trimmed.startsWith(\"[\") && trimmed.endsWith(\"]\")) {\n return JSON.parse(trimmed) as unknown[];\n }\n\n const start = trimmed.indexOf(\"[\");\n const end = trimmed.lastIndexOf(\"]\");\n if (start >= 0 && end > start) {\n const possibleJson = trimmed.slice(start, end + 1);\n return JSON.parse(possibleJson) as unknown[];\n }\n\n throw new Error(\"Model did not return a JSON array.\");\n}\n\nasync function generateQueriesWithModel(\n skill: ParsedSkill,\n provider: LanguageModelProvider,\n model: string,\n numQueries: number\n): Promise<TriggerQuery[]> {\n const shouldTriggerCount = Math.floor(numQueries / 2);\n const shouldNotTriggerCount = numQueries - shouldTriggerCount;\n\n const systemPrompt = [\n \"You generate realistic user prompts to test whether a specific agent skill triggers.\",\n \"Return JSON only. No markdown, no comments.\",\n \"Each entry must be an object: {\\\"query\\\": string, \\\"should_trigger\\\": boolean}.\",\n \"Create substantive prompts, not toy one-liners.\"\n ].join(\" \");\n\n const userPrompt = [\n `Skill name: ${skill.frontmatter.name}`,\n `Skill description: ${skill.frontmatter.description}`,\n `Generate ${numQueries} prompts total.`,\n `Exactly ${shouldTriggerCount} should have should_trigger=true.`,\n `Exactly ${shouldNotTriggerCount} should have should_trigger=false.`,\n \"Prompts should look like real user requests with enough context to drive a trigger decision.\"\n ].join(\"\\n\");\n\n const raw = await provider.sendMessage(systemPrompt, userPrompt, { model });\n const parsed = triggerQueryArraySchema.safeParse(parseJsonArrayFromModelOutput(raw));\n if (!parsed.success) {\n throw new Error(`Failed to parse generated queries: ${parsed.error.issues[0]?.message ?? \"invalid format\"}`);\n }\n\n const trueCount = parsed.data.filter((item) => item.should_trigger).length;\n const falseCount = parsed.data.length - trueCount;\n if (parsed.data.length !== numQueries || trueCount !== shouldTriggerCount || falseCount !== shouldNotTriggerCount) {\n throw new Error(\n `Generated query split mismatch. Expected ${numQueries} (${shouldTriggerCount}/${shouldNotTriggerCount}), got ${parsed.data.length} (${trueCount}/${falseCount}).`\n );\n }\n\n return parsed.data;\n}\n\nfunction parseDecision(rawResponse: string, skillNames: string[]): string {\n const normalized = rawResponse.trim().toLowerCase();\n if (normalized === \"none\" || normalized.startsWith(\"none\")) {\n return \"none\";\n }\n\n for (const skillName of skillNames) {\n const escaped = skillName.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const regex = new RegExp(`\\\\b${escaped}\\\\b`, \"i\");\n if (regex.test(rawResponse)) {\n return skillName;\n }\n }\n\n return \"unrecognized\";\n}\n\nfunction calculateMetrics(skillName: string, cases: TriggerTestCaseResult[]): TriggerMetrics {\n let truePositives = 0;\n let trueNegatives = 0;\n let falsePositives = 0;\n let falseNegatives = 0;\n\n for (const testCase of cases) {\n const choseTargetSkill = testCase.actual === skillName;\n if (testCase.shouldTrigger && choseTargetSkill) {\n truePositives += 1;\n continue;\n }\n if (testCase.shouldTrigger && !choseTargetSkill) {\n falseNegatives += 1;\n continue;\n }\n if (!testCase.shouldTrigger && choseTargetSkill) {\n falsePositives += 1;\n continue;\n }\n trueNegatives += 1;\n }\n\n const precisionDenominator = truePositives + falsePositives;\n const recallDenominator = truePositives + falseNegatives;\n const precision = precisionDenominator === 0 ? 0 : truePositives / precisionDenominator;\n const recall = recallDenominator === 0 ? 0 : truePositives / recallDenominator;\n const f1 = precision + recall === 0 ? 0 : (2 * precision * recall) / (precision + recall);\n\n return {\n truePositives,\n trueNegatives,\n falsePositives,\n falseNegatives,\n precision,\n recall,\n f1\n };\n}\n\nfunction buildSuggestions(metrics: TriggerMetrics): string[] {\n const suggestions: string[] = [];\n if (metrics.falseNegatives > 0) {\n suggestions.push(\n \"False negatives found: clarify capability keywords and add explicit 'use when ...' phrasing in description.\"\n );\n }\n if (metrics.falsePositives > 0) {\n suggestions.push(\"False positives found: narrow scope boundaries and add explicit non-goals in description.\");\n }\n if (suggestions.length === 0) {\n suggestions.push(\"Trigger behavior looks clean on this sample. Keep monitoring with domain-specific custom queries.\");\n }\n return suggestions;\n}\n\nexport interface RunTriggerTestOptions {\n model: string;\n provider: LanguageModelProvider;\n queries?: TriggerQuery[];\n numQueries: number;\n verbose?: boolean;\n}\n\nexport async function runTriggerTest(skill: ParsedSkill, options: RunTriggerTestOptions): Promise<TriggerTestResult> {\n const queries =\n options.queries && options.queries.length > 0\n ? triggerQueryArraySchema.parse(options.queries)\n : await generateQueriesWithModel(skill, options.provider, options.model, options.numQueries);\n\n const results: TriggerTestCaseResult[] = [];\n const skillName = skill.frontmatter.name;\n\n for (const testQuery of queries) {\n const fakeCount = 5 + Math.floor(Math.random() * 4);\n const fakeSkills = sample(FAKE_SKILLS, fakeCount);\n const allSkills = shuffle([\n ...fakeSkills,\n {\n name: skill.frontmatter.name,\n description: skill.frontmatter.description\n }\n ]);\n\n const skillListText = allSkills.map((entry) => `- ${entry.name}: ${entry.description}`).join(\"\\n\");\n\n const systemPrompt = [\n \"You are selecting one skill to activate for a user query.\",\n \"Choose the single best matching skill name from the provided list, or 'none' if no skill is a good fit.\",\n \"Respond with only the skill name or 'none'.\"\n ].join(\" \");\n\n const userPrompt = [`Available skills:`, skillListText, \"\", `User query: ${testQuery.query}`].join(\"\\n\");\n const rawResponse = await options.provider.sendMessage(systemPrompt, userPrompt, { model: options.model });\n const decision = parseDecision(\n rawResponse,\n allSkills.map((entry) => entry.name)\n );\n\n const expected = testQuery.should_trigger ? skillName : \"none\";\n const matched = testQuery.should_trigger ? decision === skillName : decision !== skillName;\n\n results.push({\n query: testQuery.query,\n shouldTrigger: testQuery.should_trigger,\n expected,\n actual: decision,\n matched,\n rawModelResponse: options.verbose ? rawResponse : undefined\n });\n }\n\n const metrics = calculateMetrics(skillName, results);\n\n return {\n skillName,\n model: options.model,\n provider: options.provider.name,\n queries,\n cases: results,\n metrics,\n suggestions: buildSuggestions(metrics)\n };\n}\n","export type ProviderName = \"anthropic\" | \"openai\";\n\nexport function resolveApiKey(provider: ProviderName, override?: string): string {\n if (override && override.trim() !== \"\") {\n return override.trim();\n }\n\n if (provider === \"anthropic\") {\n const envValue = process.env.ANTHROPIC_API_KEY?.trim();\n if (envValue) {\n return envValue;\n }\n throw new Error(\n \"No Anthropic API key found. Set ANTHROPIC_API_KEY environment variable or pass --api-key flag.\"\n );\n }\n\n const envValue = process.env.OPENAI_API_KEY?.trim();\n if (envValue) {\n return envValue;\n }\n throw new Error(\"No OpenAI API key found. Set OPENAI_API_KEY environment variable or pass --api-key flag.\");\n}\n","import Anthropic from \"@anthropic-ai/sdk\";\nimport { LanguageModelProvider, SendMessageOptions } from \"./types.js\";\n\nfunction wait(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nfunction isRateLimitError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n\n const maybeStatus = (error as { status?: number }).status;\n if (maybeStatus === 429) {\n return true;\n }\n\n const maybeMessage = (error as { message?: string }).message;\n if (typeof maybeMessage === \"string\" && /rate limit/i.test(maybeMessage)) {\n return true;\n }\n\n return false;\n}\n\nexport class AnthropicProvider implements LanguageModelProvider {\n public readonly name = \"anthropic\" as const;\n private readonly client: Anthropic;\n\n public constructor(apiKey: string) {\n this.client = new Anthropic({ apiKey });\n }\n\n public async sendMessage(systemPrompt: string, userMessage: string, options: SendMessageOptions): Promise<string> {\n let lastError: unknown;\n\n for (let attempt = 0; attempt < 3; attempt += 1) {\n try {\n const response = await this.client.messages.create({\n model: options.model,\n max_tokens: 2048,\n system: systemPrompt,\n messages: [\n {\n role: \"user\",\n content: userMessage\n }\n ]\n });\n\n const textBlocks = response.content.filter((block) => block.type === \"text\");\n const text = textBlocks.map((block) => block.text).join(\"\\n\").trim();\n if (text.length === 0) {\n throw new Error(\"Model returned an empty response.\");\n }\n return text;\n } catch (error) {\n lastError = error;\n if (!isRateLimitError(error) || attempt === 2) {\n break;\n }\n\n const delay = Math.min(4000, 500 * 2 ** attempt) + Math.floor(Math.random() * 250);\n await wait(delay);\n }\n }\n\n if (lastError instanceof Error) {\n throw new Error(`Anthropic API call failed: ${lastError.message}`);\n }\n throw new Error(\"Anthropic API call failed with an unknown error.\");\n }\n}\n","import { LanguageModelProvider, SendMessageOptions } from \"./types.js\";\n\ntype OpenAIClient = {\n chat: {\n completions: {\n create(input: {\n model: string;\n messages: Array<{ role: \"system\" | \"user\"; content: string }>;\n max_tokens?: number;\n }): Promise<{\n choices?: Array<{\n message?: {\n content?: string | Array<{ type?: string; text?: string }>;\n };\n }>;\n }>;\n };\n };\n};\n\nfunction wait(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nfunction isRetriableError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n\n const maybeStatus = (error as { status?: number }).status;\n if (maybeStatus === 429 || (typeof maybeStatus === \"number\" && maybeStatus >= 500)) {\n return true;\n }\n\n const maybeCode = (error as { code?: string }).code;\n if (typeof maybeCode === \"string\" && /timeout|econnreset|enotfound|eai_again/i.test(maybeCode)) {\n return true;\n }\n\n const maybeMessage = (error as { message?: string }).message;\n if (typeof maybeMessage === \"string\" && /(rate limit|timeout|temporarily unavailable|connection)/i.test(maybeMessage)) {\n return true;\n }\n\n return false;\n}\n\nfunction extractTextContent(content: string | Array<{ type?: string; text?: string }> | undefined): string {\n if (!content) {\n return \"\";\n }\n if (typeof content === \"string\") {\n return content.trim();\n }\n\n const text = content\n .map((item) => (item.type === \"text\" || !item.type ? item.text ?? \"\" : \"\"))\n .join(\"\\n\")\n .trim();\n return text;\n}\n\nexport class OpenAIProvider implements LanguageModelProvider {\n public readonly name = \"openai\" as const;\n private readonly apiKey: string;\n private client: OpenAIClient | null;\n\n public constructor(apiKey: string) {\n this.apiKey = apiKey;\n this.client = null;\n }\n\n private async ensureClient(): Promise<OpenAIClient> {\n if (this.client) {\n return this.client;\n }\n\n let openAiModule: unknown;\n try {\n const moduleName = \"openai\";\n openAiModule = await import(moduleName);\n } catch {\n throw new Error(\n \"OpenAI SDK is not installed. Install optional dependency 'openai' or run 'npm install' with optional dependencies enabled.\"\n );\n }\n\n const OpenAIConstructor = (openAiModule as { default?: new (config: { apiKey: string }) => OpenAIClient }).default;\n if (!OpenAIConstructor) {\n throw new Error(\"OpenAI SDK loaded but no default client export was found.\");\n }\n\n this.client = new OpenAIConstructor({ apiKey: this.apiKey });\n return this.client;\n }\n\n public async sendMessage(systemPrompt: string, userMessage: string, options: SendMessageOptions): Promise<string> {\n const client = await this.ensureClient();\n let lastError: unknown;\n\n for (let attempt = 0; attempt < 3; attempt += 1) {\n try {\n const response = await client.chat.completions.create({\n model: options.model,\n max_tokens: 2048,\n messages: [\n {\n role: \"system\",\n content: systemPrompt\n },\n {\n role: \"user\",\n content: userMessage\n }\n ]\n });\n\n const text = (response.choices ?? [])\n .map((choice) => extractTextContent(choice.message?.content))\n .join(\"\\n\")\n .trim();\n\n if (text.length === 0) {\n throw new Error(\"Model returned an empty response.\");\n }\n\n return text;\n } catch (error) {\n lastError = error;\n if (!isRetriableError(error) || attempt === 2) {\n break;\n }\n\n const delay = Math.min(4000, 500 * 2 ** attempt) + Math.floor(Math.random() * 250);\n await wait(delay);\n }\n }\n\n if (lastError instanceof Error) {\n throw new Error(`OpenAI API call failed: ${lastError.message}`);\n }\n throw new Error(\"OpenAI API call failed with an unknown error.\");\n }\n}\n","import { resolveApiKey } from \"../utils/config.js\";\nimport { AnthropicProvider } from \"./anthropic.js\";\nimport { OpenAIProvider } from \"./openai.js\";\nimport { LanguageModelProvider, ProviderName } from \"./types.js\";\n\nexport function createProvider(providerName: ProviderName, apiKeyOverride?: string): LanguageModelProvider {\n const apiKey = resolveApiKey(providerName, apiKeyOverride);\n if (providerName === \"anthropic\") {\n return new AnthropicProvider(apiKey);\n }\n return new OpenAIProvider(apiKey);\n}\n\nexport type { LanguageModelProvider, ProviderName };\n","import ora from \"ora\";\nimport { Command } from \"commander\";\nimport { z } from \"zod\";\nimport { runEval, evalPromptArraySchema } from \"../core/eval-runner.js\";\nimport { parseSkillStrict } from \"../core/skill-parser.js\";\nimport { createProvider } from \"../providers/index.js\";\nimport { ProviderName } from \"../providers/types.js\";\nimport { renderEvalReport } from \"../reporters/terminal.js\";\nimport { readJsonFile, writeJsonFile } from \"../utils/fs.js\";\nimport { getGlobalCliOptions, writeError, writeResult } from \"./common.js\";\n\nconst evalOptionsSchema = z.object({\n prompts: z.string().optional(),\n model: z.string(),\n graderModel: z.string().optional(),\n provider: z.enum([\"anthropic\", \"openai\"]),\n saveResults: z.string().optional(),\n verbose: z.boolean().optional(),\n apiKey: z.string().optional()\n});\n\nconst DEFAULT_ANTHROPIC_MODEL = \"claude-sonnet-4-5-20250929\";\nconst DEFAULT_OPENAI_MODEL = \"gpt-4.1-mini\";\n\nfunction resolveModel(provider: \"anthropic\" | \"openai\", model: string): string {\n if (provider === \"openai\" && model === DEFAULT_ANTHROPIC_MODEL) {\n return DEFAULT_OPENAI_MODEL;\n }\n return model;\n}\n\nexport function registerEvalCommand(program: Command): void {\n program\n .command(\"eval\")\n .description(\"Run end-to-end skill execution and quality evaluation.\")\n .argument(\"<path-to-skill>\", \"Path to SKILL.md or skill directory\")\n .option(\"--prompts <path>\", \"Path to eval prompts JSON\")\n .option(\"--model <model>\", \"Model to execute prompts\", DEFAULT_ANTHROPIC_MODEL)\n .option(\"--grader-model <model>\", \"Model used for grading (defaults to --model)\")\n .option(\"--provider <provider>\", \"LLM provider: anthropic|openai\", \"anthropic\")\n .option(\"--save-results <path>\", \"Save full evaluation results to JSON\")\n .option(\"--api-key <key>\", \"API key override\")\n .option(\"--verbose\", \"Show full model responses\")\n .action(async (targetPath: string, commandOptions: unknown, command: Command) => {\n const globalOptions = getGlobalCliOptions(command);\n const parsedOptions = evalOptionsSchema.safeParse(commandOptions);\n if (!parsedOptions.success) {\n writeError(new Error(parsedOptions.error.issues[0]?.message ?? \"Invalid eval options.\"), globalOptions.json);\n process.exitCode = 2;\n return;\n }\n\n const options = parsedOptions.data;\n const spinner = globalOptions.json || !process.stdout.isTTY ? null : ora(\"Preparing evaluation...\").start();\n\n try {\n if (spinner) {\n spinner.text = \"Parsing skill...\";\n }\n const skill = await parseSkillStrict(targetPath);\n\n if (spinner) {\n spinner.text = \"Initializing model provider...\";\n }\n const provider = createProvider(options.provider as ProviderName, options.apiKey);\n\n let prompts = undefined;\n if (options.prompts) {\n if (spinner) {\n spinner.text = \"Loading test prompts...\";\n }\n const loaded = await readJsonFile<unknown>(options.prompts);\n const parsedPrompts = evalPromptArraySchema.safeParse(loaded);\n if (!parsedPrompts.success) {\n throw new Error(`Invalid --prompts JSON: ${parsedPrompts.error.issues[0]?.message ?? \"unknown format issue\"}`);\n }\n prompts = parsedPrompts.data;\n }\n\n if (spinner) {\n spinner.text = \"Running eval prompts and grading responses...\";\n }\n const model = resolveModel(options.provider, options.model);\n const graderModel = options.graderModel ?? model;\n const result = await runEval(skill, {\n provider,\n model,\n graderModel,\n prompts\n });\n\n if (options.saveResults) {\n await writeJsonFile(options.saveResults, result);\n }\n\n spinner?.stop();\n if (globalOptions.json) {\n writeResult(result, true);\n } else {\n writeResult(renderEvalReport(result, globalOptions.color, Boolean(options.verbose)), false);\n }\n } catch (error) {\n spinner?.stop();\n writeError(error, globalOptions.json);\n process.exitCode = 2;\n }\n });\n}\n","import { z } from \"zod\";\nimport { gradeResponse, GradedAssertion } from \"./grader.js\";\nimport { ParsedSkill } from \"./skill-parser.js\";\nimport { LanguageModelProvider } from \"../providers/types.js\";\n\nexport interface EvalPrompt {\n prompt: string;\n assertions?: string[];\n}\n\nexport interface EvalPromptResult {\n prompt: string;\n assertions: GradedAssertion[];\n responseSummary: string;\n response: string;\n passedAssertions: number;\n totalAssertions: number;\n}\n\nexport interface EvalResultSummary {\n totalPrompts: number;\n totalAssertions: number;\n passedAssertions: number;\n}\n\nexport interface EvalResult {\n skillName: string;\n model: string;\n graderModel: string;\n provider: string;\n prompts: EvalPrompt[];\n results: EvalPromptResult[];\n summary: EvalResultSummary;\n}\n\nconst evalPromptSchema = z.object({\n prompt: z.string().min(1),\n assertions: z.array(z.string().min(1)).optional()\n});\n\nexport const evalPromptArraySchema = z.array(evalPromptSchema);\n\nfunction extractJsonArray(raw: string): unknown[] {\n const trimmed = raw.trim();\n if (trimmed.startsWith(\"[\") && trimmed.endsWith(\"]\")) {\n return JSON.parse(trimmed) as unknown[];\n }\n\n const start = trimmed.indexOf(\"[\");\n const end = trimmed.lastIndexOf(\"]\");\n if (start >= 0 && end > start) {\n return JSON.parse(trimmed.slice(start, end + 1)) as unknown[];\n }\n\n throw new Error(\"Model did not return a JSON array.\");\n}\n\nasync function generatePrompts(\n skill: ParsedSkill,\n provider: LanguageModelProvider,\n model: string,\n count: number\n): Promise<EvalPrompt[]> {\n const systemPrompt = [\n \"You generate realistic evaluation prompts for an agent skill.\",\n \"Return JSON only.\",\n \"Format: [{\\\"prompt\\\":\\\"...\\\",\\\"assertions\\\":[\\\"...\\\", \\\"...\\\"]}]\",\n \"Assertions should be concrete and checkable.\"\n ].join(\" \");\n\n const userPrompt = [\n `Skill name: ${skill.frontmatter.name}`,\n `Skill description: ${skill.frontmatter.description}`,\n \"Skill instructions:\",\n skill.content,\n \"\",\n `Generate ${count} prompts that stress the main capabilities and likely edge cases.`,\n \"Each prompt should include 2-4 assertions.\"\n ].join(\"\\n\");\n\n const raw = await provider.sendMessage(systemPrompt, userPrompt, { model });\n const parsed = evalPromptArraySchema.safeParse(extractJsonArray(raw));\n if (!parsed.success) {\n throw new Error(`Failed to parse generated eval prompts: ${parsed.error.issues[0]?.message ?? \"invalid prompt JSON\"}`);\n }\n\n if (parsed.data.length !== count) {\n throw new Error(`Expected ${count} prompts, got ${parsed.data.length}.`);\n }\n\n return parsed.data;\n}\n\nexport interface RunEvalOptions {\n provider: LanguageModelProvider;\n model: string;\n graderModel: string;\n prompts?: EvalPrompt[];\n}\n\nexport async function runEval(skill: ParsedSkill, options: RunEvalOptions): Promise<EvalResult> {\n const prompts =\n options.prompts && options.prompts.length > 0\n ? evalPromptArraySchema.parse(options.prompts)\n : await generatePrompts(skill, options.provider, options.model, 5);\n\n const results: EvalPromptResult[] = [];\n\n for (const evalPrompt of prompts) {\n const systemPrompt = [\n \"You are an AI assistant with an activated skill.\",\n \"Follow this SKILL.md content exactly where applicable.\",\n \"\",\n skill.raw\n ].join(\"\\n\");\n\n const response = await options.provider.sendMessage(systemPrompt, evalPrompt.prompt, { model: options.model });\n\n const gradedAssertions = await gradeResponse({\n provider: options.provider,\n model: options.graderModel,\n skillName: skill.frontmatter.name,\n skillBody: skill.content,\n userPrompt: evalPrompt.prompt,\n modelResponse: response,\n assertions: evalPrompt.assertions\n });\n\n const passedAssertions = gradedAssertions.filter((assertion) => assertion.passed).length;\n results.push({\n prompt: evalPrompt.prompt,\n assertions: gradedAssertions,\n responseSummary: response.slice(0, 200),\n response,\n passedAssertions,\n totalAssertions: gradedAssertions.length\n });\n }\n\n const totalAssertions = results.reduce((total, result) => total + result.totalAssertions, 0);\n const passedAssertions = results.reduce((total, result) => total + result.passedAssertions, 0);\n\n return {\n skillName: skill.frontmatter.name,\n model: options.model,\n graderModel: options.graderModel,\n provider: options.provider.name,\n prompts,\n results,\n summary: {\n totalPrompts: results.length,\n totalAssertions,\n passedAssertions\n }\n };\n}\n","import { z } from \"zod\";\nimport { LanguageModelProvider } from \"../providers/types.js\";\n\nexport interface GradedAssertion {\n assertion: string;\n passed: boolean;\n evidence: string;\n}\n\nconst gradedAssertionSchema = z.object({\n assertion: z.string(),\n passed: z.boolean(),\n evidence: z.string()\n});\n\nconst graderOutputSchema = z.object({\n assertions: z.array(gradedAssertionSchema)\n});\n\nfunction extractJsonObject(raw: string): Record<string, unknown> {\n const trimmed = raw.trim();\n if (trimmed.startsWith(\"{\") && trimmed.endsWith(\"}\")) {\n return JSON.parse(trimmed) as Record<string, unknown>;\n }\n\n const start = trimmed.indexOf(\"{\");\n const end = trimmed.lastIndexOf(\"}\");\n if (start >= 0 && end > start) {\n return JSON.parse(trimmed.slice(start, end + 1)) as Record<string, unknown>;\n }\n\n throw new Error(\"Grader did not return a JSON object.\");\n}\n\nexport interface GradeResponseOptions {\n provider: LanguageModelProvider;\n model: string;\n skillName: string;\n skillBody: string;\n userPrompt: string;\n modelResponse: string;\n assertions?: string[];\n}\n\nexport async function gradeResponse(options: GradeResponseOptions): Promise<GradedAssertion[]> {\n const assertionList =\n options.assertions && options.assertions.length > 0\n ? options.assertions\n : [\n \"The response follows the skill instructions faithfully.\",\n \"The response is well-structured and actionable.\",\n \"The response addresses the user prompt directly.\"\n ];\n\n const systemPrompt = [\n \"You are a strict evaluator for agent skill outputs.\",\n \"Assess each assertion and return JSON only.\",\n \"Required output format: {\\\"assertions\\\":[{\\\"assertion\\\":\\\"...\\\",\\\"passed\\\":true|false,\\\"evidence\\\":\\\"...\\\"}]}\"\n ].join(\" \");\n\n const userPrompt = [\n `Skill: ${options.skillName}`,\n \"Skill instructions:\",\n options.skillBody,\n \"\",\n `User prompt: ${options.userPrompt}`,\n \"\",\n \"Model response:\",\n options.modelResponse,\n \"\",\n \"Assertions to evaluate:\",\n assertionList.map((assertion, index) => `${index + 1}. ${assertion}`).join(\"\\n\")\n ].join(\"\\n\");\n\n const raw = await options.provider.sendMessage(systemPrompt, userPrompt, { model: options.model });\n const parsed = graderOutputSchema.safeParse(extractJsonObject(raw));\n\n if (!parsed.success) {\n throw new Error(`Failed to parse grader output: ${parsed.error.issues[0]?.message ?? \"invalid grader JSON\"}`);\n }\n\n return parsed.data.assertions;\n}\n","import ora from \"ora\";\nimport { Command } from \"commander\";\nimport { z } from \"zod\";\nimport { runCheck } from \"../core/check-runner.js\";\nimport { evalPromptArraySchema } from \"../core/eval-runner.js\";\nimport { triggerQueryArraySchema } from \"../core/trigger-tester.js\";\nimport { createProvider } from \"../providers/index.js\";\nimport { ProviderName } from \"../providers/types.js\";\nimport { renderCheckReport } from \"../reporters/terminal.js\";\nimport { readJsonFile, writeJsonFile } from \"../utils/fs.js\";\nimport { getGlobalCliOptions, writeError, writeResult } from \"./common.js\";\n\nconst checkOptionsSchema = z.object({\n provider: z.enum([\"anthropic\", \"openai\"]),\n model: z.string(),\n graderModel: z.string().optional(),\n apiKey: z.string().optional(),\n queries: z.string().optional(),\n numQueries: z.number().int().min(2),\n prompts: z.string().optional(),\n minF1: z.number().min(0).max(1),\n minAssertPassRate: z.number().min(0).max(1),\n saveResults: z.string().optional(),\n continueOnLintFail: z.boolean().optional(),\n verbose: z.boolean().optional()\n});\n\nconst DEFAULT_ANTHROPIC_MODEL = \"claude-sonnet-4-5-20250929\";\nconst DEFAULT_OPENAI_MODEL = \"gpt-4.1-mini\";\n\nfunction resolveModel(provider: \"anthropic\" | \"openai\", model: string): string {\n if (provider === \"openai\" && model === DEFAULT_ANTHROPIC_MODEL) {\n return DEFAULT_OPENAI_MODEL;\n }\n return model;\n}\n\nexport function registerCheckCommand(program: Command): void {\n program\n .command(\"check\")\n .description(\"Run lint + trigger + eval with threshold-based quality gates.\")\n .argument(\"<path-to-skill>\", \"Path to SKILL.md or skill directory\")\n .option(\"--provider <provider>\", \"LLM provider: anthropic|openai\", \"anthropic\")\n .option(\"--model <model>\", \"Model for trigger/eval runs\", DEFAULT_ANTHROPIC_MODEL)\n .option(\"--grader-model <model>\", \"Model used for grading (defaults to --model)\")\n .option(\"--api-key <key>\", \"API key override\")\n .option(\"--queries <path>\", \"Path to custom trigger queries JSON\")\n .option(\"--num-queries <n>\", \"Number of auto-generated trigger queries\", (value) => Number.parseInt(value, 10), 20)\n .option(\"--prompts <path>\", \"Path to eval prompts JSON\")\n .option(\"--min-f1 <n>\", \"Minimum required trigger F1 score (0-1)\", (value) => Number.parseFloat(value), 0.8)\n .option(\n \"--min-assert-pass-rate <n>\",\n \"Minimum required eval assertion pass rate (0-1)\",\n (value) => Number.parseFloat(value),\n 0.9\n )\n .option(\"--save-results <path>\", \"Save combined check results to JSON\")\n .option(\"--continue-on-lint-fail\", \"Continue trigger/eval stages even when lint has failures\")\n .option(\"--verbose\", \"Show detailed trigger/eval output sections\")\n .action(async (targetPath: string, commandOptions: unknown, command: Command) => {\n const globalOptions = getGlobalCliOptions(command);\n const parsedOptions = checkOptionsSchema.safeParse(commandOptions);\n if (!parsedOptions.success) {\n writeError(new Error(parsedOptions.error.issues[0]?.message ?? \"Invalid check options.\"), globalOptions.json);\n process.exitCode = 2;\n return;\n }\n\n const options = parsedOptions.data;\n if (options.numQueries % 2 !== 0) {\n writeError(\n new Error(\"--num-queries must be an even number so the suite can split should/should-not trigger cases.\"),\n globalOptions.json\n );\n process.exitCode = 2;\n return;\n }\n\n const spinner = globalOptions.json || !process.stdout.isTTY ? null : ora(\"Preparing check run...\").start();\n\n try {\n if (spinner) {\n spinner.text = \"Initializing model provider...\";\n }\n const provider = createProvider(options.provider as ProviderName, options.apiKey);\n\n let queries = undefined;\n if (options.queries) {\n if (spinner) {\n spinner.text = \"Loading custom trigger queries...\";\n }\n const loadedQueries = await readJsonFile<unknown>(options.queries);\n const parsedQueries = triggerQueryArraySchema.safeParse(loadedQueries);\n if (!parsedQueries.success) {\n throw new Error(\n `Invalid --queries JSON: ${parsedQueries.error.issues[0]?.message ?? \"unknown format issue\"}`\n );\n }\n queries = parsedQueries.data;\n }\n\n let prompts = undefined;\n if (options.prompts) {\n if (spinner) {\n spinner.text = \"Loading eval prompts...\";\n }\n const loadedPrompts = await readJsonFile<unknown>(options.prompts);\n const parsedPrompts = evalPromptArraySchema.safeParse(loadedPrompts);\n if (!parsedPrompts.success) {\n throw new Error(\n `Invalid --prompts JSON: ${parsedPrompts.error.issues[0]?.message ?? \"unknown format issue\"}`\n );\n }\n prompts = parsedPrompts.data;\n }\n\n const model = resolveModel(options.provider, options.model);\n const graderModel = options.graderModel ?? model;\n\n const result = await runCheck(targetPath, {\n provider,\n model,\n graderModel,\n queries,\n numQueries: options.numQueries,\n prompts,\n minF1: options.minF1,\n minAssertPassRate: options.minAssertPassRate,\n continueOnLintFail: Boolean(options.continueOnLintFail),\n verbose: Boolean(options.verbose),\n onStage: (stage) => {\n if (!spinner) {\n return;\n }\n if (stage === \"lint\") {\n spinner.text = \"Running lint checks...\";\n } else if (stage === \"parse\") {\n spinner.text = \"Parsing skill for model evaluations...\";\n } else if (stage === \"trigger\") {\n spinner.text = \"Running trigger test suite...\";\n } else if (stage === \"eval\") {\n spinner.text = \"Running end-to-end eval suite...\";\n }\n }\n });\n\n if (options.saveResults) {\n await writeJsonFile(options.saveResults, result);\n }\n\n spinner?.stop();\n if (globalOptions.json) {\n writeResult(result, true);\n } else {\n writeResult(renderCheckReport(result, globalOptions.color, Boolean(options.verbose)), false);\n }\n\n process.exitCode = result.gates.overallPassed ? 0 : 1;\n } catch (error) {\n spinner?.stop();\n writeError(error, globalOptions.json);\n process.exitCode = 2;\n }\n });\n}\n","import { runEval, EvalPrompt, EvalResult } from \"./eval-runner.js\";\nimport { runLinter, LintReport } from \"./linter/index.js\";\nimport { parseSkillStrict } from \"./skill-parser.js\";\nimport { runTriggerTest, TriggerQuery, TriggerTestResult } from \"./trigger-tester.js\";\nimport { LanguageModelProvider } from \"../providers/types.js\";\n\nexport interface CheckThresholds {\n minF1: number;\n minAssertPassRate: number;\n}\n\nexport interface CheckGates {\n lintPassed: boolean;\n triggerPassed: boolean | null;\n evalPassed: boolean | null;\n triggerF1: number | null;\n evalAssertPassRate: number | null;\n overallPassed: boolean;\n}\n\nexport interface CheckRunResult {\n target: string;\n provider: string;\n model: string;\n graderModel: string;\n thresholds: CheckThresholds;\n continueOnLintFail: boolean;\n lint: LintReport;\n trigger: TriggerTestResult | null;\n eval: EvalResult | null;\n triggerSkippedReason?: string;\n evalSkippedReason?: string;\n gates: CheckGates;\n}\n\nexport interface RunCheckOptions {\n provider: LanguageModelProvider;\n model: string;\n graderModel: string;\n numQueries: number;\n queries?: TriggerQuery[];\n prompts?: EvalPrompt[];\n minF1: number;\n minAssertPassRate: number;\n continueOnLintFail: boolean;\n verbose?: boolean;\n onStage?: (stage: string) => void;\n}\n\nfunction calculateEvalAssertPassRate(result: EvalResult): number {\n if (result.summary.totalAssertions === 0) {\n return 0;\n }\n return result.summary.passedAssertions / result.summary.totalAssertions;\n}\n\nexport async function runCheck(inputPath: string, options: RunCheckOptions): Promise<CheckRunResult> {\n options.onStage?.(\"lint\");\n const lint = await runLinter(inputPath);\n const lintPassed = lint.summary.failures === 0;\n\n let trigger: TriggerTestResult | null = null;\n let evalResult: EvalResult | null = null;\n let triggerSkippedReason: string | undefined;\n let evalSkippedReason: string | undefined;\n\n if (!lintPassed && !options.continueOnLintFail) {\n triggerSkippedReason = \"Skipped because lint has failures (use --continue-on-lint-fail to override).\";\n evalSkippedReason = \"Skipped because lint has failures (use --continue-on-lint-fail to override).\";\n } else {\n options.onStage?.(\"parse\");\n let parsedSkill = null;\n try {\n parsedSkill = await parseSkillStrict(inputPath);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n triggerSkippedReason = `Skipped: skill could not be parsed strictly (${message}).`;\n evalSkippedReason = `Skipped: skill could not be parsed strictly (${message}).`;\n }\n\n if (parsedSkill) {\n options.onStage?.(\"trigger\");\n trigger = await runTriggerTest(parsedSkill, {\n provider: options.provider,\n model: options.model,\n queries: options.queries,\n numQueries: options.numQueries,\n verbose: options.verbose\n });\n\n options.onStage?.(\"eval\");\n evalResult = await runEval(parsedSkill, {\n provider: options.provider,\n model: options.model,\n graderModel: options.graderModel,\n prompts: options.prompts\n });\n }\n }\n\n const triggerF1 = trigger ? trigger.metrics.f1 : null;\n const evalAssertPassRate = evalResult ? calculateEvalAssertPassRate(evalResult) : null;\n const triggerPassed = triggerF1 === null ? null : triggerF1 >= options.minF1;\n const evalPassed = evalAssertPassRate === null ? null : evalAssertPassRate >= options.minAssertPassRate;\n const overallPassed = lintPassed && triggerPassed === true && evalPassed === true;\n\n return {\n target: inputPath,\n provider: options.provider.name,\n model: options.model,\n graderModel: options.graderModel,\n thresholds: {\n minF1: options.minF1,\n minAssertPassRate: options.minAssertPassRate\n },\n continueOnLintFail: options.continueOnLintFail,\n lint,\n trigger,\n eval: evalResult,\n triggerSkippedReason,\n evalSkippedReason,\n gates: {\n lintPassed,\n triggerPassed,\n evalPassed,\n triggerF1,\n evalAssertPassRate,\n overallPassed\n }\n };\n}\n"],"mappings":"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","names":["fs","path","fs","path","fs","path","path","fs","fs","path","path","fs","z","z","envValue","wait","z","ora","z","z","z","z","passedAssertions","z","DEFAULT_ANTHROPIC_MODEL","DEFAULT_OPENAI_MODEL","resolveModel","ora","ora","z","z","DEFAULT_ANTHROPIC_MODEL","DEFAULT_OPENAI_MODEL","resolveModel","ora","path","fs"]}
|