@uinaf/skillcheck 1.4.0 → 1.4.1
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/dist/cli.js +35 -6
- package/docs/usage.md +5 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -357,6 +357,17 @@ function readJson(file) {
|
|
|
357
357
|
return;
|
|
358
358
|
}
|
|
359
359
|
}
|
|
360
|
+
function liveScenarios(root) {
|
|
361
|
+
const cli = path.join(root, "cli");
|
|
362
|
+
if (!(fs.existsSync(path.join(root, "skills")) || fs.existsSync(cli) && fs.readdirSync(cli).some((d) => fs.existsSync(path.join(cli, d, "skills"))))) return void 0;
|
|
363
|
+
return new Set(discoverScenarios(root).map((dir) => {
|
|
364
|
+
const parts = dir.split(path.sep);
|
|
365
|
+
return `${parts.at(-3)}\0${parts.at(-1)}`;
|
|
366
|
+
}));
|
|
367
|
+
}
|
|
368
|
+
function isLive(live, e) {
|
|
369
|
+
return live === void 0 || live.has(`${e.skill}\0${e.scenario}`);
|
|
370
|
+
}
|
|
360
371
|
function discoverScenarios(root) {
|
|
361
372
|
const roots = [path.join(root, "skills")];
|
|
362
373
|
const cliDir = path.join(root, "cli");
|
|
@@ -464,15 +475,26 @@ function resultIdentity(file, dir) {
|
|
|
464
475
|
variant
|
|
465
476
|
};
|
|
466
477
|
}
|
|
467
|
-
function reduceResults(dir, allowMixed) {
|
|
478
|
+
function reduceResults(dir, allowMixed, live) {
|
|
468
479
|
const entries = [];
|
|
469
480
|
const skipped = [];
|
|
481
|
+
const retired = /* @__PURE__ */ new Set();
|
|
470
482
|
const gradedAt = /* @__PURE__ */ new Map();
|
|
471
483
|
const shas = /* @__PURE__ */ new Set();
|
|
472
484
|
const files = fs.readdirSync(dir);
|
|
473
485
|
const incomplete = new Set(files.filter((f) => f.endsWith(".json.attempt")).map((f) => f.replace(/\.attempt$/, "")));
|
|
474
486
|
const results = files.filter((f) => f.endsWith(".json") && !f.endsWith(".meta.json"));
|
|
475
487
|
for (const f of [.../* @__PURE__ */ new Set([...results, ...incomplete])].sort()) {
|
|
488
|
+
let identity;
|
|
489
|
+
try {
|
|
490
|
+
identity = resultIdentity(f, dir);
|
|
491
|
+
} catch {
|
|
492
|
+
identity = void 0;
|
|
493
|
+
}
|
|
494
|
+
if (identity !== void 0 && identity.scenario !== "" && !isLive(live, identity)) {
|
|
495
|
+
retired.add(entryKey(identity));
|
|
496
|
+
continue;
|
|
497
|
+
}
|
|
476
498
|
if (f.endsWith("--cursor.json")) {
|
|
477
499
|
console.error(`skipping ${f}: Cursor harness is retired`);
|
|
478
500
|
skipped.push(f);
|
|
@@ -522,7 +544,8 @@ function reduceResults(dir, allowMixed) {
|
|
|
522
544
|
treeSha: shas.size === 1 ? [...shas][0] : shas.size === 0 ? "none" : "mixed",
|
|
523
545
|
entries,
|
|
524
546
|
skipped,
|
|
525
|
-
gradedAt
|
|
547
|
+
gradedAt,
|
|
548
|
+
retired
|
|
526
549
|
};
|
|
527
550
|
}
|
|
528
551
|
function entryKey(e) {
|
|
@@ -565,12 +588,17 @@ function readExistingScorecard(out) {
|
|
|
565
588
|
function cmdSummarize(argv) {
|
|
566
589
|
const { positional, flags } = parseArgs(argv);
|
|
567
590
|
if (positional.length > 0) fail("usage: skillcheck summarize [--root DIR] [--allow-mixed]");
|
|
568
|
-
const
|
|
591
|
+
const root = resolveRoot(flags);
|
|
592
|
+
const dirs = stateDirs(root);
|
|
569
593
|
if (!fs.existsSync(dirs.results)) fail(`no results directory at ${dirs.results}; run some evals first`);
|
|
570
|
-
const
|
|
594
|
+
const live = liveScenarios(root);
|
|
595
|
+
const { entries, skipped, gradedAt, retired: retiredResults } = reduceResults(dirs.results, flags.get("--allow-mixed") === true, live);
|
|
571
596
|
fs.mkdirSync(dirs.scorecards, { recursive: true });
|
|
572
597
|
const out = path.join(dirs.scorecards, `${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.json`);
|
|
573
|
-
const
|
|
598
|
+
const previous = readExistingScorecard(out);
|
|
599
|
+
const existing = previous.filter((e) => isLive(live, e));
|
|
600
|
+
for (const e of previous) if (!isLive(live, e)) retiredResults.add(entryKey(e));
|
|
601
|
+
const retired = retiredResults.size;
|
|
574
602
|
const skippedKeys = new Set(skipped.map((file) => ({
|
|
575
603
|
key: entryKey(resultIdentity(file, dirs.results)),
|
|
576
604
|
modifiedAt: fs.statSync(fs.existsSync(path.join(dirs.results, `${file}.attempt`)) ? path.join(dirs.results, `${file}.attempt`) : path.join(dirs.results, file)).mtimeMs
|
|
@@ -587,6 +615,7 @@ function cmdSummarize(argv) {
|
|
|
587
615
|
scenarios: merged.entries
|
|
588
616
|
};
|
|
589
617
|
fs.writeFileSync(out, JSON.stringify(scorecard, null, 2) + "\n");
|
|
618
|
+
if (retired > 0) console.log(`dropped ${retired} row(s) for scenarios no longer in the tree`);
|
|
590
619
|
const scenarios = merged.entries.filter((e) => e.variant !== "control");
|
|
591
620
|
console.log(`${out}: ${scenarios.length} scenario(s), ${scenarios.filter((e) => e.pass).length} passing, ${merged.entries.length - scenarios.length} control(s), ${skipped.length} skipped file(s)`);
|
|
592
621
|
if (existing.length > 0) console.log(`merged into today's scorecard: ${entries.length} from this run, ${merged.carried} carried over`);
|
|
@@ -688,4 +717,4 @@ if (isMainModule()) {
|
|
|
688
717
|
}
|
|
689
718
|
}
|
|
690
719
|
//#endregion
|
|
691
|
-
export { NOISY_SPREAD, aggregateTrials, assertUniformConfig, classifyResult, ensurePrivateDir, formatStats, mergeScorecard, parseArgs, parsePositiveInt, reduceResults, resolveRoot, resultRunConfig, runConfigOf, runOptions, stateDirs, summarizeSkills, toolVersion, treeShaOf };
|
|
720
|
+
export { NOISY_SPREAD, aggregateTrials, assertUniformConfig, classifyResult, ensurePrivateDir, formatStats, liveScenarios, mergeScorecard, parseArgs, parsePositiveInt, reduceResults, resolveRoot, resultRunConfig, runConfigOf, runOptions, stateDirs, summarizeSkills, toolVersion, treeShaOf };
|
package/docs/usage.md
CHANGED
|
@@ -179,6 +179,11 @@ six of twenty-nine scenarios therefore leaves twenty-nine rows in the file, not
|
|
|
179
179
|
six. A same-date file that cannot be parsed stops the write instead of being
|
|
180
180
|
overwritten.
|
|
181
181
|
|
|
182
|
+
Rows for scenarios that no longer exist in the tree, whether carried from
|
|
183
|
+
today's scorecard or left in `results/`, are dropped and counted on stdout.
|
|
184
|
+
A root with no skills tree (`skills/` or `cli/*/skills/`) holds results only
|
|
185
|
+
and keeps every row.
|
|
186
|
+
|
|
182
187
|
Files that are not promptfoo results and ungraded transport errors are skipped
|
|
183
188
|
with a warning rather than failing the reduction. Graded assertion failures
|
|
184
189
|
remain scored results. If a skipped file matches an existing scorecard row,
|