@sanity/ailf 0.1.0 → 0.1.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/_vendor/ailf-core/examples/index.d.ts +6 -4
- package/dist/_vendor/ailf-core/examples/index.js +9 -4
- package/dist/_vendor/ailf-core/ports/context.d.ts +4 -0
- package/dist/adapters/task-sources/repo-schemas.d.ts +12 -2
- package/dist/adapters/task-sources/repo-schemas.js +28 -2
- package/dist/cli.js +0 -0
- package/dist/commands/init.js +39 -5
- package/dist/commands/pipeline-action.js +44 -6
- package/dist/commands/publish.js +2 -1
- package/dist/commands/validate-tasks.js +4 -1
- package/dist/composition-root.js +9 -5
- package/dist/orchestration/build-app-context.js +2 -0
- package/package.json +1 -1
- package/dist/commands/update-quality-scores.d.ts +0 -5
- package/dist/commands/update-quality-scores.js +0 -20
- package/dist/lib/agent-behavior-report.d.ts +0 -8
- package/dist/lib/agent-behavior-report.js +0 -185
- package/dist/lib/baseline.d.ts +0 -19
- package/dist/lib/baseline.js +0 -153
- package/dist/lib/calculate-scores.d.ts +0 -23
- package/dist/lib/calculate-scores.js +0 -42
- package/dist/lib/compare.d.ts +0 -18
- package/dist/lib/compare.js +0 -170
- package/dist/lib/coverage-audit.d.ts +0 -4
- package/dist/lib/coverage-audit.js +0 -42
- package/dist/lib/discovery-report.d.ts +0 -13
- package/dist/lib/discovery-report.js +0 -57
- package/dist/lib/fetch-docs.d.ts +0 -30
- package/dist/lib/fetch-docs.js +0 -171
- package/dist/lib/generate-configs.d.ts +0 -25
- package/dist/lib/generate-configs.js +0 -42
- package/dist/lib/grader-api.d.ts +0 -21
- package/dist/lib/grader-api.js +0 -34
- package/dist/lib/grader-compare.d.ts +0 -19
- package/dist/lib/grader-compare.js +0 -91
- package/dist/lib/grader-consistency.d.ts +0 -27
- package/dist/lib/grader-consistency.js +0 -79
- package/dist/lib/grader-sensitivity.d.ts +0 -19
- package/dist/lib/grader-sensitivity.js +0 -75
- package/dist/lib/grader-validate.d.ts +0 -19
- package/dist/lib/grader-validate.js +0 -78
- package/dist/lib/measure-retrieval.d.ts +0 -14
- package/dist/lib/measure-retrieval.js +0 -71
- package/dist/lib/pr-comment.d.ts +0 -16
- package/dist/lib/pr-comment.js +0 -28
- package/dist/lib/readiness-report.d.ts +0 -13
- package/dist/lib/readiness-report.js +0 -108
- package/dist/lib/webhook-server.d.ts +0 -11
- package/dist/lib/webhook-server.js +0 -24
- package/dist/lib/weekly-digest.d.ts +0 -24
- package/dist/lib/weekly-digest.js +0 -148
- package/dist/orchestration/env-bridge.d.ts +0 -21
- package/dist/orchestration/env-bridge.js +0 -66
- package/dist/orchestration/steps/fetch-docs-shell.d.ts +0 -17
- package/dist/orchestration/steps/fetch-docs-shell.js +0 -30
- package/dist/pipeline/steps/calculate-scores-step.d.ts +0 -11
- package/dist/pipeline/steps/calculate-scores-step.js +0 -89
- package/dist/pipeline/steps/compare-step.d.ts +0 -18
- package/dist/pipeline/steps/compare-step.js +0 -90
- package/dist/pipeline/steps/eval-step.d.ts +0 -53
- package/dist/pipeline/steps/eval-step.js +0 -347
- package/dist/pipeline/steps/fetch-docs-step.d.ts +0 -11
- package/dist/pipeline/steps/fetch-docs-step.js +0 -84
- package/dist/pipeline/steps/generate-configs-step.d.ts +0 -11
- package/dist/pipeline/steps/generate-configs-step.js +0 -98
- package/dist/pipeline/steps/grader-consistency-step.d.ts +0 -21
- package/dist/pipeline/steps/grader-consistency-step.js +0 -74
- package/dist/pipeline/steps/publish-report-step.d.ts +0 -57
- package/dist/pipeline/steps/publish-report-step.js +0 -243
- package/dist/pipeline/steps/report-step.d.ts +0 -13
- package/dist/pipeline/steps/report-step.js +0 -56
- package/dist/pipeline/steps/update-scores-step.d.ts +0 -11
- package/dist/pipeline/steps/update-scores-step.js +0 -42
- package/dist/scripts/agent-behavior-report.d.ts +0 -19
- package/dist/scripts/agent-behavior-report.js +0 -315
- package/dist/scripts/baseline.d.ts +0 -43
- package/dist/scripts/baseline.js +0 -267
- package/dist/scripts/calculate-scores.d.ts +0 -166
- package/dist/scripts/calculate-scores.js +0 -1296
- package/dist/scripts/compare.d.ts +0 -22
- package/dist/scripts/compare.js +0 -334
- package/dist/scripts/coverage-audit.d.ts +0 -44
- package/dist/scripts/coverage-audit.js +0 -209
- package/dist/scripts/debug-eval.d.ts +0 -19
- package/dist/scripts/debug-eval.js +0 -73
- package/dist/scripts/discovery-report.d.ts +0 -58
- package/dist/scripts/discovery-report.js +0 -250
- package/dist/scripts/fetch-docs.d.ts +0 -35
- package/dist/scripts/fetch-docs.js +0 -472
- package/dist/scripts/generate-configs.d.ts +0 -66
- package/dist/scripts/generate-configs.js +0 -459
- package/dist/scripts/grader-api.d.ts +0 -27
- package/dist/scripts/grader-api.js +0 -206
- package/dist/scripts/grader-compare.d.ts +0 -22
- package/dist/scripts/grader-compare.js +0 -368
- package/dist/scripts/grader-consistency.d.ts +0 -20
- package/dist/scripts/grader-consistency.js +0 -313
- package/dist/scripts/grader-sensitivity.d.ts +0 -22
- package/dist/scripts/grader-sensitivity.js +0 -354
- package/dist/scripts/grader-validate.d.ts +0 -19
- package/dist/scripts/grader-validate.js +0 -267
- package/dist/scripts/measure-retrieval.d.ts +0 -10
- package/dist/scripts/measure-retrieval.js +0 -145
- package/dist/scripts/pipeline.d.ts +0 -76
- package/dist/scripts/pipeline.js +0 -1031
- package/dist/scripts/pr-comment.d.ts +0 -10
- package/dist/scripts/pr-comment.js +0 -510
- package/dist/scripts/readiness-report.d.ts +0 -88
- package/dist/scripts/readiness-report.js +0 -342
- package/dist/scripts/update-quality-scores.d.ts +0 -15
- package/dist/scripts/update-quality-scores.js +0 -184
- package/dist/scripts/validate.d.ts +0 -13
- package/dist/scripts/validate.js +0 -79
- package/dist/scripts/webhook-server.d.ts +0 -26
- package/dist/scripts/webhook-server.js +0 -147
- package/dist/scripts/weekly-digest.d.ts +0 -24
- package/dist/scripts/weekly-digest.js +0 -144
- package/dist/sinks/format-slack.d.ts +0 -64
- package/dist/sinks/format-slack.js +0 -306
- package/dist/sinks/slack-sink.d.ts +0 -27
- package/dist/sinks/slack-sink.js +0 -78
- package/dist/sinks/webhook-sink.d.ts +0 -19
- package/dist/sinks/webhook-sink.js +0 -50
- package/tasks/.expanded.agentic.yaml +0 -51
- package/tasks/.expanded.yaml +0 -66
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lib/agent-behavior-report.ts — DEPRECATED re-export shim.
|
|
3
|
-
* @deprecated Import from ../pipeline/agent-behavior-report.js instead.
|
|
4
|
-
*/
|
|
5
|
-
// oxlint-disable-next-line import/no-unassigned-import -- side-effect: loads .env into process.env
|
|
6
|
-
import "dotenv/config";
|
|
7
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
8
|
-
import { dirname, join } from "path";
|
|
9
|
-
export { analyzeResults, CANONICAL_DOC_MAP, detectFeatureArea, } from "../pipeline/agent-behavior-report.js";
|
|
10
|
-
import { analyzeResults, } from "../pipeline/agent-behavior-report.js";
|
|
11
|
-
export function main(resultsPathArg) {
|
|
12
|
-
const ROOT = join(dirname(new URL(import.meta.url).pathname), "..", "..");
|
|
13
|
-
const resultsPath = resultsPathArg ??
|
|
14
|
-
process.argv[2] ??
|
|
15
|
-
join(ROOT, "results", "latest", "eval-results.json");
|
|
16
|
-
if (!existsSync(resultsPath)) {
|
|
17
|
-
console.error(`Results file not found: ${resultsPath}`);
|
|
18
|
-
console.error("Run an evaluation first: pnpm eval:observed");
|
|
19
|
-
process.exit(1);
|
|
20
|
-
}
|
|
21
|
-
console.log(`Reading results from: ${resultsPath}`);
|
|
22
|
-
console.log();
|
|
23
|
-
const json = JSON.parse(readFileSync(resultsPath, "utf-8"));
|
|
24
|
-
const rawResults = Array.isArray(json.results)
|
|
25
|
-
? json.results
|
|
26
|
-
: json.results.results;
|
|
27
|
-
const analysis = analyzeResults(rawResults);
|
|
28
|
-
if (!analysis.hasData) {
|
|
29
|
-
console.log("No agent behavior data found in the results.");
|
|
30
|
-
console.log("Make sure you ran the evaluation with the observed config:");
|
|
31
|
-
console.log(" pnpm eval:observed");
|
|
32
|
-
process.exit(0);
|
|
33
|
-
}
|
|
34
|
-
printReport(analysis);
|
|
35
|
-
// Persist detailed report as JSON
|
|
36
|
-
const outDir = join(ROOT, "results", "latest");
|
|
37
|
-
mkdirSync(outDir, { recursive: true });
|
|
38
|
-
const reportData = {
|
|
39
|
-
features: analysis.features.map((f) => ({
|
|
40
|
-
avgDocPages: f.avgDocPages,
|
|
41
|
-
avgNetworkMs: f.avgNetworkMs,
|
|
42
|
-
avgSearches: f.avgSearches,
|
|
43
|
-
canonicalCoverage: f.canonicalCoverage,
|
|
44
|
-
canonicalSlugs: f.canonicalSlugs,
|
|
45
|
-
docSlugsVisited: f.allDocSlugs,
|
|
46
|
-
externalDomains: f.allExternalDomains,
|
|
47
|
-
feature: f.feature,
|
|
48
|
-
searchQueries: f.allSearchQueries,
|
|
49
|
-
taskCount: f.tasks.length,
|
|
50
|
-
})),
|
|
51
|
-
tasks: analysis.tasks.map((t) => ({
|
|
52
|
-
behavior: t.behavior,
|
|
53
|
-
description: t.description,
|
|
54
|
-
feature: t.feature,
|
|
55
|
-
hasDocs: t.hasDocs,
|
|
56
|
-
})),
|
|
57
|
-
timestamp: new Date().toISOString(),
|
|
58
|
-
totalTasks: analysis.tasks.length,
|
|
59
|
-
};
|
|
60
|
-
writeFileSync(join(outDir, "agent-behavior-report.json"), JSON.stringify(reportData, null, 2));
|
|
61
|
-
console.log("Agent behavior report written to results/latest/agent-behavior-report.json");
|
|
62
|
-
}
|
|
63
|
-
// ---------------------------------------------------------------------------
|
|
64
|
-
// Report output (kept in shim for backward compat)
|
|
65
|
-
// ---------------------------------------------------------------------------
|
|
66
|
-
function printReport(analysis) {
|
|
67
|
-
console.log("=".repeat(80));
|
|
68
|
-
console.log(" AGENT BEHAVIOR OBSERVATION REPORT");
|
|
69
|
-
console.log("=".repeat(80));
|
|
70
|
-
console.log();
|
|
71
|
-
// ---- Overview table ----
|
|
72
|
-
console.log("OVERVIEW BY FEATURE AREA");
|
|
73
|
-
console.log("-".repeat(80));
|
|
74
|
-
const h = "| Feature Area | Tasks | Avg Docs | Avg Search | Avg Net(ms) | Canon% |";
|
|
75
|
-
const sep = "|---------------------|-------|----------|------------|-------------|--------|";
|
|
76
|
-
console.log(h);
|
|
77
|
-
console.log(sep);
|
|
78
|
-
for (const f of analysis.features) {
|
|
79
|
-
console.log(`| ${f.feature.padEnd(19)} | ` +
|
|
80
|
-
`${f.tasks.length.toString().padStart(5)} | ` +
|
|
81
|
-
`${f.avgDocPages.toFixed(1).padStart(8)} | ` +
|
|
82
|
-
`${f.avgSearches.toFixed(1).padStart(10)} | ` +
|
|
83
|
-
`${Math.round(f.avgNetworkMs).toString().padStart(11)} | ` +
|
|
84
|
-
`${(f.canonicalCoverage * 100).toFixed(0).padStart(5)}% |`);
|
|
85
|
-
}
|
|
86
|
-
console.log();
|
|
87
|
-
// ---- Canonical coverage breakdown ----
|
|
88
|
-
console.log("CANONICAL DOCUMENTATION COVERAGE");
|
|
89
|
-
console.log("-".repeat(80));
|
|
90
|
-
console.log();
|
|
91
|
-
for (const f of analysis.features) {
|
|
92
|
-
console.log(` ${f.feature} (${(f.canonicalCoverage * 100).toFixed(0)}% canonical coverage):`);
|
|
93
|
-
if (f.canonicalSlugs.length === 0) {
|
|
94
|
-
console.log(" (no canonical docs defined)");
|
|
95
|
-
}
|
|
96
|
-
else {
|
|
97
|
-
for (const slug of f.canonicalSlugs) {
|
|
98
|
-
const found = f.allDocSlugs.some((visited) => visited.includes(slug));
|
|
99
|
-
const marker = found ? "[x]" : "[ ]";
|
|
100
|
-
console.log(` ${marker} ${slug}`);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
if (f.allDocSlugs.length > 0) {
|
|
104
|
-
const nonCanonical = f.allDocSlugs.filter((slug) => !f.canonicalSlugs.some((c) => slug.includes(c)));
|
|
105
|
-
if (nonCanonical.length > 0) {
|
|
106
|
-
console.log(" Additional docs visited:");
|
|
107
|
-
for (const slug of nonCanonical) {
|
|
108
|
-
console.log(` + ${slug}`);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
console.log();
|
|
113
|
-
}
|
|
114
|
-
// ---- Search strategy ----
|
|
115
|
-
const allSearches = analysis.features.flatMap((f) => f.allSearchQueries);
|
|
116
|
-
if (allSearches.length > 0) {
|
|
117
|
-
console.log("SEARCH STRATEGY");
|
|
118
|
-
console.log("-".repeat(80));
|
|
119
|
-
console.log();
|
|
120
|
-
for (const f of analysis.features) {
|
|
121
|
-
if (f.allSearchQueries.length === 0)
|
|
122
|
-
continue;
|
|
123
|
-
console.log(` ${f.feature}:`);
|
|
124
|
-
for (const q of f.allSearchQueries) {
|
|
125
|
-
console.log(` -> "${q}"`);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
console.log();
|
|
129
|
-
}
|
|
130
|
-
// ---- Per-task detail ----
|
|
131
|
-
console.log("PER-TASK DETAIL");
|
|
132
|
-
console.log("-".repeat(80));
|
|
133
|
-
console.log();
|
|
134
|
-
for (const f of analysis.features) {
|
|
135
|
-
console.log(` ## ${f.feature}`);
|
|
136
|
-
console.log();
|
|
137
|
-
for (const t of f.tasks) {
|
|
138
|
-
const variant = t.hasDocs ? "[gold]" : "[baseline]";
|
|
139
|
-
console.log(` ${variant} ${t.description}`);
|
|
140
|
-
console.log(` Requests: ${t.behavior.totalRequests} | ` +
|
|
141
|
-
`Doc pages: ${t.behavior.docPagesVisited} | ` +
|
|
142
|
-
`Searches: ${t.behavior.searchesPerformed} | ` +
|
|
143
|
-
`External: ${t.behavior.externalRequestCount}`);
|
|
144
|
-
if (t.behavior.docSlugsVisited.length > 0) {
|
|
145
|
-
console.log(` Docs: ${t.behavior.docSlugsVisited.join(", ")}`);
|
|
146
|
-
}
|
|
147
|
-
if (t.behavior.uniqueSearchQueries.length > 0) {
|
|
148
|
-
console.log(` Queries: ${t.behavior.uniqueSearchQueries.map((q) => `"${q}"`).join(", ")}`);
|
|
149
|
-
}
|
|
150
|
-
console.log();
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
// ---- External domains ----
|
|
154
|
-
const allDomains = [
|
|
155
|
-
...new Set(analysis.features.flatMap((f) => f.allExternalDomains)),
|
|
156
|
-
];
|
|
157
|
-
if (allDomains.length > 0) {
|
|
158
|
-
console.log("EXTERNAL DOMAINS");
|
|
159
|
-
console.log("-".repeat(80));
|
|
160
|
-
console.log();
|
|
161
|
-
for (const d of allDomains) {
|
|
162
|
-
console.log(` - ${d}`);
|
|
163
|
-
}
|
|
164
|
-
console.log();
|
|
165
|
-
}
|
|
166
|
-
// ---- Summary stats ----
|
|
167
|
-
console.log("OVERALL STATISTICS");
|
|
168
|
-
console.log("-".repeat(80));
|
|
169
|
-
console.log();
|
|
170
|
-
const totalTasks = analysis.tasks.length;
|
|
171
|
-
const tasksUsingDocs = analysis.tasks.filter((t) => t.behavior.usedDocs).length;
|
|
172
|
-
const tasksUsingSearch = analysis.tasks.filter((t) => t.behavior.usedSearch).length;
|
|
173
|
-
const avgCanonical = analysis.features.reduce((s, f) => s + f.canonicalCoverage, 0) /
|
|
174
|
-
(analysis.features.length || 1);
|
|
175
|
-
console.log(` Total tasks observed: ${totalTasks}`);
|
|
176
|
-
console.log(` Tasks that used docs: ${tasksUsingDocs}/${totalTasks} (${((tasksUsingDocs / totalTasks) * 100).toFixed(0)}%)`);
|
|
177
|
-
console.log(` Tasks that used search: ${tasksUsingSearch}/${totalTasks} (${((tasksUsingSearch / totalTasks) * 100).toFixed(0)}%)`);
|
|
178
|
-
console.log(` Avg canonical coverage: ${(avgCanonical * 100).toFixed(1)}%`);
|
|
179
|
-
console.log();
|
|
180
|
-
}
|
|
181
|
-
// Only run when invoked directly (not when imported)
|
|
182
|
-
if (process.argv[1]?.endsWith("agent-behavior-report.ts") ||
|
|
183
|
-
process.argv[1]?.endsWith("agent-behavior-report.js")) {
|
|
184
|
-
main();
|
|
185
|
-
}
|
package/dist/lib/baseline.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lib/baseline.ts — DEPRECATED re-export shim.
|
|
3
|
-
*
|
|
4
|
-
* The real implementation has moved to pipeline/baseline.ts.
|
|
5
|
-
* This shim preserves backward compatibility for:
|
|
6
|
-
* - Direct CLI invocation: `tsx src/lib/baseline.ts`
|
|
7
|
-
* - Test imports that haven't been updated yet
|
|
8
|
-
*
|
|
9
|
-
* TODO: Update all importers to use pipeline/baseline.ts, then delete this file.
|
|
10
|
-
*
|
|
11
|
-
* @deprecated Import from ../pipeline/baseline.js instead.
|
|
12
|
-
*/
|
|
13
|
-
export type { BaselineMetadata, CompareResult, ScoreComparison, } from "../pipeline/baseline.js";
|
|
14
|
-
export declare function saveBaseline(tag?: string): {
|
|
15
|
-
success: boolean;
|
|
16
|
-
message: string;
|
|
17
|
-
};
|
|
18
|
-
export declare function compareBaseline(baselineFile?: string): import("./baseline.js").CompareResult;
|
|
19
|
-
export declare function listBaselines(): import("./baseline.js").BaselineMetadata[];
|
package/dist/lib/baseline.js
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lib/baseline.ts — DEPRECATED re-export shim.
|
|
3
|
-
*
|
|
4
|
-
* The real implementation has moved to pipeline/baseline.ts.
|
|
5
|
-
* This shim preserves backward compatibility for:
|
|
6
|
-
* - Direct CLI invocation: `tsx src/lib/baseline.ts`
|
|
7
|
-
* - Test imports that haven't been updated yet
|
|
8
|
-
*
|
|
9
|
-
* TODO: Update all importers to use pipeline/baseline.ts, then delete this file.
|
|
10
|
-
*
|
|
11
|
-
* @deprecated Import from ../pipeline/baseline.js instead.
|
|
12
|
-
*/
|
|
13
|
-
import { dirname, resolve } from "path";
|
|
14
|
-
import { fileURLToPath } from "url";
|
|
15
|
-
import { saveBaseline as _saveBaseline, compareBaseline as _compareBaseline, listBaselines as _listBaselines, } from "../pipeline/baseline.js";
|
|
16
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
17
|
-
const ROOT = resolve(__dirname, "../..");
|
|
18
|
-
export function saveBaseline(tag) {
|
|
19
|
-
return _saveBaseline(ROOT, tag);
|
|
20
|
-
}
|
|
21
|
-
export function compareBaseline(baselineFile) {
|
|
22
|
-
return _compareBaseline(ROOT, baselineFile);
|
|
23
|
-
}
|
|
24
|
-
export function listBaselines() {
|
|
25
|
-
return _listBaselines(ROOT);
|
|
26
|
-
}
|
|
27
|
-
// ---------------------------------------------------------------------------
|
|
28
|
-
// CLI
|
|
29
|
-
// ---------------------------------------------------------------------------
|
|
30
|
-
if (process.argv[1]?.endsWith("baseline.ts") ||
|
|
31
|
-
process.argv[1]?.endsWith("baseline.js")) {
|
|
32
|
-
const args = process.argv.slice(2);
|
|
33
|
-
const command = args[0] || "save";
|
|
34
|
-
function getArg(name) {
|
|
35
|
-
const idx = args.indexOf(`--${name}`);
|
|
36
|
-
return idx !== -1 && idx + 1 < args.length ? args[idx + 1] : undefined;
|
|
37
|
-
}
|
|
38
|
-
switch (command) {
|
|
39
|
-
case "compare": {
|
|
40
|
-
const file = getArg("file");
|
|
41
|
-
console.log("=== Baseline Comparison ===\n");
|
|
42
|
-
const result = compareBaseline(file);
|
|
43
|
-
if (!result.success) {
|
|
44
|
-
console.error(` ❌ ${result.message}`);
|
|
45
|
-
process.exit(1);
|
|
46
|
-
}
|
|
47
|
-
console.log(` ${result.message}\n`);
|
|
48
|
-
console.log(" " +
|
|
49
|
-
"Feature Area".padEnd(18) +
|
|
50
|
-
"Current".padEnd(10) +
|
|
51
|
-
"Baseline".padEnd(10) +
|
|
52
|
-
"Delta");
|
|
53
|
-
console.log(" " + "-".repeat(50));
|
|
54
|
-
for (const c of result.comparisons) {
|
|
55
|
-
const deltaStr = c.delta > 0 ? `+${c.delta}` : c.delta === 0 ? "=" : String(c.delta);
|
|
56
|
-
const icon = c.delta > 0 ? "📈" : c.delta < 0 ? "📉" : "➡️";
|
|
57
|
-
console.log(" " +
|
|
58
|
-
c.feature.padEnd(18) +
|
|
59
|
-
String(c.current).padEnd(10) +
|
|
60
|
-
String(c.baseline).padEnd(10) +
|
|
61
|
-
`${icon} ${deltaStr}`);
|
|
62
|
-
}
|
|
63
|
-
// Cost comparison (only if cost data exists)
|
|
64
|
-
const hasCostData = result.comparisons.some((c) => c.costCurrent !== undefined || c.costBaseline !== undefined);
|
|
65
|
-
if (hasCostData) {
|
|
66
|
-
console.log();
|
|
67
|
-
console.log(" Cost Comparison:");
|
|
68
|
-
console.log(" " +
|
|
69
|
-
"Feature Area".padEnd(18) +
|
|
70
|
-
"Current".padEnd(10) +
|
|
71
|
-
"Baseline".padEnd(10) +
|
|
72
|
-
"Delta");
|
|
73
|
-
console.log(" " + "-".repeat(50));
|
|
74
|
-
for (const c of result.comparisons) {
|
|
75
|
-
if (c.costCurrent === undefined && c.costBaseline === undefined) {
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
const cur = `$${(c.costCurrent ?? 0).toFixed(4)}`;
|
|
79
|
-
const base = `$${(c.costBaseline ?? 0).toFixed(4)}`;
|
|
80
|
-
const delta = c.costDelta ?? 0;
|
|
81
|
-
const deltaStr = delta > 0
|
|
82
|
-
? `+$${delta.toFixed(4)}`
|
|
83
|
-
: delta < 0
|
|
84
|
-
? `-$${Math.abs(delta).toFixed(4)}`
|
|
85
|
-
: "=";
|
|
86
|
-
const icon = delta > 0 ? "📈" : delta < 0 ? "📉" : "➡️";
|
|
87
|
-
console.log(" " +
|
|
88
|
-
c.feature.padEnd(18) +
|
|
89
|
-
cur.padEnd(10) +
|
|
90
|
-
base.padEnd(10) +
|
|
91
|
-
`${icon} ${deltaStr}`);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
console.log();
|
|
95
|
-
const overallIcon = result.overallDelta > 0 ? "📈" : result.overallDelta < 0 ? "📉" : "➡️";
|
|
96
|
-
const overallStr = result.overallDelta > 0
|
|
97
|
-
? `+${result.overallDelta}`
|
|
98
|
-
: result.overallDelta === 0
|
|
99
|
-
? "="
|
|
100
|
-
: String(result.overallDelta);
|
|
101
|
-
console.log(` Overall: ${overallIcon} ${overallStr} points`);
|
|
102
|
-
break;
|
|
103
|
-
}
|
|
104
|
-
case "history": {
|
|
105
|
-
console.log("=== Baseline History ===\n");
|
|
106
|
-
const baselines = listBaselines();
|
|
107
|
-
if (baselines.length === 0) {
|
|
108
|
-
console.log(" No baselines saved yet.");
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
const hasCosts = baselines.some((b) => b.totalCost !== undefined || b.graderCost !== undefined);
|
|
112
|
-
const costHeader = hasCosts ? "Cost".padEnd(10) : "";
|
|
113
|
-
console.log(" " +
|
|
114
|
-
"Date".padEnd(22) +
|
|
115
|
-
"Avg".padEnd(6) +
|
|
116
|
-
"Areas".padEnd(7) +
|
|
117
|
-
costHeader +
|
|
118
|
-
"Tag");
|
|
119
|
-
console.log(" " + "-".repeat(hasCosts ? 60 : 50));
|
|
120
|
-
for (const b of baselines) {
|
|
121
|
-
const date = new Date(b.timestamp).toLocaleString();
|
|
122
|
-
const combinedCost = (b.totalCost ?? 0) + (b.graderCost ?? 0);
|
|
123
|
-
const costStr = hasCosts
|
|
124
|
-
? (combinedCost > 0 ? `$${combinedCost.toFixed(2)}` : "-").padEnd(10)
|
|
125
|
-
: "";
|
|
126
|
-
console.log(" " +
|
|
127
|
-
date.padEnd(22) +
|
|
128
|
-
String(b.avgScore).padEnd(6) +
|
|
129
|
-
String(b.areaCount).padEnd(7) +
|
|
130
|
-
costStr +
|
|
131
|
-
(b.tag ?? ""));
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
break;
|
|
135
|
-
}
|
|
136
|
-
case "save": {
|
|
137
|
-
const tag = getArg("tag");
|
|
138
|
-
console.log("=== Saving baseline snapshot ===\n");
|
|
139
|
-
const result = saveBaseline(tag);
|
|
140
|
-
if (result.success) {
|
|
141
|
-
console.log(` ✅ ${result.message}`);
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
console.error(` ❌ ${result.message}`);
|
|
145
|
-
process.exit(1);
|
|
146
|
-
}
|
|
147
|
-
break;
|
|
148
|
-
}
|
|
149
|
-
default:
|
|
150
|
-
console.error(`Unknown command: "${command}". Use: save, history, compare`);
|
|
151
|
-
process.exit(1);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lib/calculate-scores.ts — DEPRECATED re-export shim.
|
|
3
|
-
*
|
|
4
|
-
* The real implementation has moved to pipeline/calculate-scores.ts.
|
|
5
|
-
* This shim preserves backward compatibility for:
|
|
6
|
-
* - Direct CLI invocation: `tsx src/lib/calculate-scores.ts`
|
|
7
|
-
* - Test imports that haven't been updated yet
|
|
8
|
-
*
|
|
9
|
-
* TODO: Update all importers to use pipeline/calculate-scores.ts, then delete this file.
|
|
10
|
-
*
|
|
11
|
-
* @deprecated Import from ../pipeline/calculate-scores.js instead.
|
|
12
|
-
*/
|
|
13
|
-
export { calculateAndWriteScores, calculateScoresPerModel, extractGraderJudgments, scoreAgenticResults, type CalculateScoresOptions, type PromptfooResultsWrapper, type RawPromptfooFile, type RawTestResult, } from "../pipeline/calculate-scores.js";
|
|
14
|
-
export { classifyRubric, detectFeatureArea, extractUrlMetadata, mergeScores, parseRubricScore, type ActualScoreEntry, type ComponentResult, type TestResult, type UrlMetadata, } from "../_vendor/ailf-core/index.d.ts";
|
|
15
|
-
import type { CalculateScoresOptions } from "../pipeline/calculate-scores.js";
|
|
16
|
-
/**
|
|
17
|
-
* Legacy main() entry point — wraps calculateAndWriteScores() with env var fallbacks.
|
|
18
|
-
*
|
|
19
|
-
* @deprecated Use calculateAndWriteScores() from pipeline/calculate-scores.ts instead.
|
|
20
|
-
*/
|
|
21
|
-
export declare function main(options?: Omit<CalculateScoresOptions, "rootDir"> & {
|
|
22
|
-
rootDir?: string;
|
|
23
|
-
}): void;
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lib/calculate-scores.ts — DEPRECATED re-export shim.
|
|
3
|
-
*
|
|
4
|
-
* The real implementation has moved to pipeline/calculate-scores.ts.
|
|
5
|
-
* This shim preserves backward compatibility for:
|
|
6
|
-
* - Direct CLI invocation: `tsx src/lib/calculate-scores.ts`
|
|
7
|
-
* - Test imports that haven't been updated yet
|
|
8
|
-
*
|
|
9
|
-
* TODO: Update all importers to use pipeline/calculate-scores.ts, then delete this file.
|
|
10
|
-
*
|
|
11
|
-
* @deprecated Import from ../pipeline/calculate-scores.js instead.
|
|
12
|
-
*/
|
|
13
|
-
import { dirname, join } from "path";
|
|
14
|
-
import { fileURLToPath } from "url";
|
|
15
|
-
// Re-export everything from the real implementation
|
|
16
|
-
export { calculateAndWriteScores, calculateScoresPerModel, extractGraderJudgments, scoreAgenticResults, } from "../pipeline/calculate-scores.js";
|
|
17
|
-
// Re-export core types/functions for backward compatibility
|
|
18
|
-
export { classifyRubric, detectFeatureArea, extractUrlMetadata, mergeScores, parseRubricScore, } from "../_vendor/ailf-core/index.js";
|
|
19
|
-
import { calculateAndWriteScores } from "../pipeline/calculate-scores.js";
|
|
20
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
21
|
-
const ROOT = join(__dirname, "..", "..");
|
|
22
|
-
/**
|
|
23
|
-
* Legacy main() entry point — wraps calculateAndWriteScores() with env var fallbacks.
|
|
24
|
-
*
|
|
25
|
-
* @deprecated Use calculateAndWriteScores() from pipeline/calculate-scores.ts instead.
|
|
26
|
-
*/
|
|
27
|
-
export function main(options) {
|
|
28
|
-
calculateAndWriteScores({
|
|
29
|
-
rootDir: options?.rootDir ?? ROOT,
|
|
30
|
-
allowedOrigins: options?.allowedOrigins,
|
|
31
|
-
mode: options?.mode ?? process.env.EVAL_MODE ?? "baseline",
|
|
32
|
-
resolvedSource: options?.resolvedSource,
|
|
33
|
-
resultsPath: options?.resultsPath,
|
|
34
|
-
searchMode: options?.searchMode,
|
|
35
|
-
source: options?.source,
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
// Only run when invoked directly (not when imported for testing)
|
|
39
|
-
if (process.argv[1]?.endsWith("calculate-scores.ts") ||
|
|
40
|
-
process.argv[1]?.endsWith("calculate-scores.js")) {
|
|
41
|
-
main();
|
|
42
|
-
}
|
package/dist/lib/compare.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* compare.ts
|
|
3
|
-
*
|
|
4
|
-
* CLI for structured comparison between two evaluation runs.
|
|
5
|
-
*
|
|
6
|
-
* Usage:
|
|
7
|
-
* pnpm compare # compare current vs latest baseline
|
|
8
|
-
* pnpm compare --baseline <path> # compare current vs specific file
|
|
9
|
-
* pnpm compare --baseline <path> --experiment <path> # compare two specific files
|
|
10
|
-
* pnpm compare --threshold 5 # custom noise threshold
|
|
11
|
-
* pnpm compare --output /tmp/comparison.json # write JSON report to file
|
|
12
|
-
* pnpm compare --format json # output raw JSON (default: table)
|
|
13
|
-
*
|
|
14
|
-
* Reads: results/latest/score-summary.json (as experiment, unless --experiment)
|
|
15
|
-
* Reads: results/baselines/<latest>.json (as baseline, unless --baseline)
|
|
16
|
-
*/
|
|
17
|
-
export { formatComparisonMarkdown, formatComparisonTable, } from "../_vendor/ailf-core/index.d.ts";
|
|
18
|
-
export declare function main(): void;
|
package/dist/lib/compare.js
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* compare.ts
|
|
3
|
-
*
|
|
4
|
-
* CLI for structured comparison between two evaluation runs.
|
|
5
|
-
*
|
|
6
|
-
* Usage:
|
|
7
|
-
* pnpm compare # compare current vs latest baseline
|
|
8
|
-
* pnpm compare --baseline <path> # compare current vs specific file
|
|
9
|
-
* pnpm compare --baseline <path> --experiment <path> # compare two specific files
|
|
10
|
-
* pnpm compare --threshold 5 # custom noise threshold
|
|
11
|
-
* pnpm compare --output /tmp/comparison.json # write JSON report to file
|
|
12
|
-
* pnpm compare --format json # output raw JSON (default: table)
|
|
13
|
-
*
|
|
14
|
-
* Reads: results/latest/score-summary.json (as experiment, unless --experiment)
|
|
15
|
-
* Reads: results/baselines/<latest>.json (as baseline, unless --baseline)
|
|
16
|
-
*/
|
|
17
|
-
import { existsSync, readFileSync, readdirSync, writeFileSync } from "fs";
|
|
18
|
-
import { dirname, join, resolve } from "path";
|
|
19
|
-
import { fileURLToPath } from "url";
|
|
20
|
-
import { formatComparisonTable, } from "../_vendor/ailf-core/index.js";
|
|
21
|
-
import { compare } from "../pipeline/compare.js";
|
|
22
|
-
import { DEFAULT_NOISE_THRESHOLD, } from "../pipeline/types.js";
|
|
23
|
-
// Re-export pure formatters from core for backward compatibility.
|
|
24
|
-
export { formatComparisonMarkdown, formatComparisonTable, } from "../_vendor/ailf-core/index.js";
|
|
25
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
26
|
-
const ROOT = resolve(__dirname, "..", "..");
|
|
27
|
-
const BASELINES_DIR = join(ROOT, "results", "baselines");
|
|
28
|
-
const SCORE_SUMMARY_PATH = join(ROOT, "results", "latest", "score-summary.json");
|
|
29
|
-
// ---------------------------------------------------------------------------
|
|
30
|
-
// CLI argument parsing
|
|
31
|
-
// ---------------------------------------------------------------------------
|
|
32
|
-
const args = process.argv.slice(2);
|
|
33
|
-
function getFlag(name) {
|
|
34
|
-
return args.includes(`--${name}`);
|
|
35
|
-
}
|
|
36
|
-
function getOption(name) {
|
|
37
|
-
const idx = args.indexOf(`--${name}`);
|
|
38
|
-
return idx !== -1 && idx + 1 < args.length ? args[idx + 1] : undefined;
|
|
39
|
-
}
|
|
40
|
-
const baselinePath = getOption("baseline");
|
|
41
|
-
const experimentPath = getOption("experiment");
|
|
42
|
-
const thresholdStr = getOption("threshold");
|
|
43
|
-
const threshold = thresholdStr
|
|
44
|
-
? parseFloat(thresholdStr)
|
|
45
|
-
: DEFAULT_NOISE_THRESHOLD;
|
|
46
|
-
const outputPath = getOption("output");
|
|
47
|
-
const format = getOption("format") ?? "table";
|
|
48
|
-
const showHelp = getFlag("help") || getFlag("h");
|
|
49
|
-
if (showHelp) {
|
|
50
|
-
console.log(`
|
|
51
|
-
Usage: pnpm compare [options]
|
|
52
|
-
|
|
53
|
-
Compare two evaluation score summaries and produce structured deltas.
|
|
54
|
-
|
|
55
|
-
Options:
|
|
56
|
-
--baseline <path> Baseline score-summary.json (default: latest baseline)
|
|
57
|
-
--experiment <path> Experiment score-summary.json (default: results/latest/score-summary.json)
|
|
58
|
-
--threshold <n> Noise threshold for unchanged classification (default: ${DEFAULT_NOISE_THRESHOLD})
|
|
59
|
-
--output <path> Write JSON report to file
|
|
60
|
-
--format <fmt> Output format: table (default) or json
|
|
61
|
-
--help, -h Show this help
|
|
62
|
-
|
|
63
|
-
Examples:
|
|
64
|
-
pnpm compare # current scores vs latest baseline
|
|
65
|
-
pnpm compare --threshold 5 # wider noise band
|
|
66
|
-
pnpm compare --format json # machine-readable output
|
|
67
|
-
pnpm compare --baseline results/baselines/20260310_02_43_44.json
|
|
68
|
-
pnpm compare --baseline before.json --experiment after.json
|
|
69
|
-
`);
|
|
70
|
-
process.exit(0);
|
|
71
|
-
}
|
|
72
|
-
// ---------------------------------------------------------------------------
|
|
73
|
-
// File loading helpers
|
|
74
|
-
// ---------------------------------------------------------------------------
|
|
75
|
-
/**
|
|
76
|
-
* formatComparisonMarkdown — re-exported from @sanity/ailf-core above.
|
|
77
|
-
* formatComparisonTable — re-exported from @sanity/ailf-core above.
|
|
78
|
-
*/
|
|
79
|
-
function findLatestBaseline() {
|
|
80
|
-
if (!existsSync(BASELINES_DIR))
|
|
81
|
-
return null;
|
|
82
|
-
const files = readdirSync(BASELINES_DIR)
|
|
83
|
-
.filter((f) => f.endsWith(".json"))
|
|
84
|
-
.sort()
|
|
85
|
-
.reverse();
|
|
86
|
-
return files.length > 0 ? join(BASELINES_DIR, files[0]) : null;
|
|
87
|
-
}
|
|
88
|
-
function loadSummary(path) {
|
|
89
|
-
if (!existsSync(path)) {
|
|
90
|
-
console.error(`❌ File not found: ${path}`);
|
|
91
|
-
process.exit(1);
|
|
92
|
-
}
|
|
93
|
-
const raw = readFileSync(path, "utf-8");
|
|
94
|
-
return JSON.parse(raw);
|
|
95
|
-
}
|
|
96
|
-
// ---------------------------------------------------------------------------
|
|
97
|
-
// Main
|
|
98
|
-
// ---------------------------------------------------------------------------
|
|
99
|
-
export function main() {
|
|
100
|
-
// Resolve experiment path
|
|
101
|
-
const expPath = experimentPath ?? SCORE_SUMMARY_PATH;
|
|
102
|
-
const experiment = loadSummary(expPath);
|
|
103
|
-
// Resolve baseline path
|
|
104
|
-
let basePath;
|
|
105
|
-
if (baselinePath) {
|
|
106
|
-
basePath = resolve(baselinePath);
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
const latest = findLatestBaseline();
|
|
110
|
-
if (!latest) {
|
|
111
|
-
console.error("❌ No baselines found. Run 'pnpm baseline:save' first, or use --baseline <path>.");
|
|
112
|
-
process.exit(1);
|
|
113
|
-
}
|
|
114
|
-
basePath = latest;
|
|
115
|
-
}
|
|
116
|
-
const baseline = loadSummary(basePath);
|
|
117
|
-
// Try to load grader consistency data for empirical thresholds
|
|
118
|
-
const consistencyPath = join(ROOT, "results", "latest", "grader-consistency.json");
|
|
119
|
-
let graderConsistency;
|
|
120
|
-
if (existsSync(consistencyPath) && !thresholdStr) {
|
|
121
|
-
try {
|
|
122
|
-
const consistencyRaw = JSON.parse(readFileSync(consistencyPath, "utf-8"));
|
|
123
|
-
if (consistencyRaw.recommendedThreshold && consistencyRaw.perDimension) {
|
|
124
|
-
graderConsistency =
|
|
125
|
-
consistencyRaw;
|
|
126
|
-
console.log(` 📊 Using empirical noise threshold: ±${graderConsistency.recommendedThreshold.toFixed(1)} (from grader consistency data)`);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
catch {
|
|
130
|
-
// Non-fatal — fall back to default threshold
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
console.log(` Baseline: ${basePath}`);
|
|
134
|
-
console.log(` Experiment: ${expPath}`);
|
|
135
|
-
if (!graderConsistency) {
|
|
136
|
-
console.log(` Threshold: ±${threshold} (default — run --grader-replications for empirical threshold)`);
|
|
137
|
-
}
|
|
138
|
-
console.log("");
|
|
139
|
-
const report = compare(baseline, experiment, {
|
|
140
|
-
graderConsistency,
|
|
141
|
-
noiseThreshold: threshold,
|
|
142
|
-
});
|
|
143
|
-
if (format === "json") {
|
|
144
|
-
const json = JSON.stringify(report, null, 2);
|
|
145
|
-
if (outputPath) {
|
|
146
|
-
writeFileSync(outputPath, json);
|
|
147
|
-
console.log(` ✅ Comparison report written to ${outputPath}`);
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
console.log(json);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
const table = formatComparisonTable(report);
|
|
155
|
-
console.log(table);
|
|
156
|
-
if (outputPath) {
|
|
157
|
-
const json = JSON.stringify(report, null, 2);
|
|
158
|
-
writeFileSync(outputPath, json);
|
|
159
|
-
console.log(` ✅ Comparison report also written to ${outputPath}`);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
// Write comparison report to results/latest for other steps to consume
|
|
163
|
-
const latestComparisonPath = join(ROOT, "results", "latest", "comparison-report.json");
|
|
164
|
-
writeFileSync(latestComparisonPath, JSON.stringify(report, null, 2));
|
|
165
|
-
}
|
|
166
|
-
// Only run when invoked directly
|
|
167
|
-
if (process.argv[1]?.endsWith("compare.ts") ||
|
|
168
|
-
process.argv[1]?.endsWith("compare.js")) {
|
|
169
|
-
main();
|
|
170
|
-
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
export { countReferencedDocs, countTasksByArea, formatCoverageConsole, formatCoverageMarkdown, loadFeatureRegistry, runCoverageAudit, } from "../pipeline/coverage-audit.js";
|
|
2
|
-
export type { CoverageAuditReport, ProductFeature } from "../pipeline/types.js";
|
|
3
|
-
/** @deprecated Use pipeline functions directly with explicit rootDir */
|
|
4
|
-
export declare function main(): void;
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lib/coverage-audit.ts — DEPRECATED re-export shim.
|
|
3
|
-
* @deprecated Import from ../pipeline/coverage-audit.js instead.
|
|
4
|
-
*/
|
|
5
|
-
import { dirname, resolve } from "path";
|
|
6
|
-
import { fileURLToPath } from "url";
|
|
7
|
-
export { countReferencedDocs, countTasksByArea, formatCoverageConsole, formatCoverageMarkdown, loadFeatureRegistry, runCoverageAudit, } from "../pipeline/coverage-audit.js";
|
|
8
|
-
import { countReferencedDocs, formatCoverageConsole, formatCoverageMarkdown, runCoverageAudit, } from "../pipeline/coverage-audit.js";
|
|
9
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
|
-
const ROOT = resolve(__dirname, "../..");
|
|
11
|
-
/** @deprecated Use pipeline functions directly with explicit rootDir */
|
|
12
|
-
export function main() {
|
|
13
|
-
const args = process.argv.slice(2);
|
|
14
|
-
const formatArg = args.includes("--format")
|
|
15
|
-
? args[args.indexOf("--format") + 1]
|
|
16
|
-
: undefined;
|
|
17
|
-
const jsonOutput = args.includes("--json");
|
|
18
|
-
const report = runCoverageAudit(ROOT);
|
|
19
|
-
if (!report) {
|
|
20
|
-
console.error("❌ Coverage audit failed.");
|
|
21
|
-
process.exit(1);
|
|
22
|
-
}
|
|
23
|
-
if (jsonOutput) {
|
|
24
|
-
console.log(JSON.stringify(report, null, 2));
|
|
25
|
-
}
|
|
26
|
-
else if (formatArg === "md" || formatArg === "markdown") {
|
|
27
|
-
console.log(formatCoverageMarkdown(report));
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
console.log(formatCoverageConsole(report));
|
|
31
|
-
}
|
|
32
|
-
if (!jsonOutput && formatArg !== "md") {
|
|
33
|
-
const docStats = countReferencedDocs(ROOT);
|
|
34
|
-
console.log("DOCUMENT UTILIZATION:");
|
|
35
|
-
console.log(` ${docStats.total} unique document slugs referenced across evaluation tasks`);
|
|
36
|
-
console.log("");
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
if (process.argv[1]?.endsWith("coverage-audit.ts") ||
|
|
40
|
-
process.argv[1]?.endsWith("coverage-audit.js")) {
|
|
41
|
-
main();
|
|
42
|
-
}
|