@kevinrabun/judges 3.23.6 → 3.23.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +37 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/benchmark.d.ts.map +1 -1
- package/dist/commands/benchmark.js +556 -0
- package/dist/commands/benchmark.js.map +1 -1
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +17 -1
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/review.d.ts +37 -0
- package/dist/commands/review.d.ts.map +1 -0
- package/dist/commands/review.js +539 -0
- package/dist/commands/review.js.map +1 -0
- package/dist/commands/tune.d.ts +25 -0
- package/dist/commands/tune.d.ts.map +1 -0
- package/dist/commands/tune.js +408 -0
- package/dist/commands/tune.js.map +1 -0
- package/dist/finding-lifecycle.d.ts +93 -0
- package/dist/finding-lifecycle.d.ts.map +1 -0
- package/dist/finding-lifecycle.js +214 -0
- package/dist/finding-lifecycle.js.map +1 -0
- package/dist/patches/index.d.ts.map +1 -1
- package/dist/patches/index.js +127 -0
- package/dist/patches/index.js.map +1 -1
- package/dist/presets.d.ts.map +1 -1
- package/dist/presets.js +103 -0
- package/dist/presets.js.map +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `judges tune` — Analyze your project and suggest optimal .judgesrc.json configuration.
|
|
3
|
+
*
|
|
4
|
+
* Runs an initial evaluation on a sample of project files, then recommends:
|
|
5
|
+
* - Which preset best fits your project
|
|
6
|
+
* - Rules to disable based on consistent FP patterns
|
|
7
|
+
* - Severity overrides for noisy rules
|
|
8
|
+
* - Framework-specific settings
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* judges tune # Analyze current directory
|
|
12
|
+
* judges tune --dir ./src # Analyze specific directory
|
|
13
|
+
* judges tune --apply # Write .judgesrc.json automatically
|
|
14
|
+
* judges tune --max-files 20 # Limit sample size
|
|
15
|
+
*/
|
|
16
|
+
import { existsSync, readFileSync, readdirSync, statSync, writeFileSync } from "fs";
|
|
17
|
+
import { resolve, extname, join } from "path";
|
|
18
|
+
import { evaluateWithTribunal } from "../evaluators/index.js";
|
|
19
|
+
import { PRESETS } from "../presets.js";
|
|
20
|
+
// ─── Language Detection ─────────────────────────────────────────────────────
|
|
21
|
+
const EXT_TO_LANG = {
|
|
22
|
+
".ts": "typescript",
|
|
23
|
+
".tsx": "typescript",
|
|
24
|
+
".js": "javascript",
|
|
25
|
+
".jsx": "javascript",
|
|
26
|
+
".mjs": "javascript",
|
|
27
|
+
".cjs": "javascript",
|
|
28
|
+
".py": "python",
|
|
29
|
+
".rs": "rust",
|
|
30
|
+
".go": "go",
|
|
31
|
+
".java": "java",
|
|
32
|
+
".cs": "csharp",
|
|
33
|
+
".rb": "ruby",
|
|
34
|
+
".php": "php",
|
|
35
|
+
".swift": "swift",
|
|
36
|
+
".kt": "kotlin",
|
|
37
|
+
".tf": "terraform",
|
|
38
|
+
".hcl": "terraform",
|
|
39
|
+
".bicep": "bicep",
|
|
40
|
+
".sh": "bash",
|
|
41
|
+
};
|
|
42
|
+
function detectLanguage(filePath) {
|
|
43
|
+
const ext = extname(filePath.toLowerCase());
|
|
44
|
+
if (filePath.toLowerCase().includes("dockerfile"))
|
|
45
|
+
return "dockerfile";
|
|
46
|
+
return EXT_TO_LANG[ext];
|
|
47
|
+
}
|
|
48
|
+
// ─── Framework Detection ────────────────────────────────────────────────────
|
|
49
|
+
function detectFramework(dir) {
|
|
50
|
+
const signals = [];
|
|
51
|
+
// Check package.json for JS/TS frameworks
|
|
52
|
+
const pkgPath = join(dir, "package.json");
|
|
53
|
+
if (existsSync(pkgPath)) {
|
|
54
|
+
try {
|
|
55
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
56
|
+
const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
|
|
57
|
+
if (deps["next"])
|
|
58
|
+
signals.push({ framework: "Next.js", preset: "nextjs", confidence: 0.95 });
|
|
59
|
+
if (deps["react"] && !deps["next"])
|
|
60
|
+
signals.push({ framework: "React", preset: "react", confidence: 0.9 });
|
|
61
|
+
if (deps["express"])
|
|
62
|
+
signals.push({ framework: "Express", preset: "express", confidence: 0.9 });
|
|
63
|
+
if (deps["fastify"])
|
|
64
|
+
signals.push({ framework: "Express", preset: "express", confidence: 0.8 });
|
|
65
|
+
if (deps["koa"])
|
|
66
|
+
signals.push({ framework: "Express", preset: "express", confidence: 0.7 });
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// Invalid package.json
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Check for Python frameworks
|
|
73
|
+
const reqPath = join(dir, "requirements.txt");
|
|
74
|
+
const pyprojectPath = join(dir, "pyproject.toml");
|
|
75
|
+
const pipfilePath = join(dir, "Pipfile");
|
|
76
|
+
const pythonManifests = [reqPath, pyprojectPath, pipfilePath].filter(existsSync);
|
|
77
|
+
for (const manifest of pythonManifests) {
|
|
78
|
+
try {
|
|
79
|
+
const content = readFileSync(manifest, "utf-8").toLowerCase();
|
|
80
|
+
if (content.includes("fastapi"))
|
|
81
|
+
signals.push({ framework: "FastAPI", preset: "fastapi", confidence: 0.9 });
|
|
82
|
+
if (content.includes("django"))
|
|
83
|
+
signals.push({ framework: "Django", preset: "django", confidence: 0.9 });
|
|
84
|
+
if (content.includes("flask"))
|
|
85
|
+
signals.push({ framework: "FastAPI", preset: "fastapi", confidence: 0.7 });
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// ignore
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Check for Java frameworks
|
|
92
|
+
const pomPath = join(dir, "pom.xml");
|
|
93
|
+
const gradlePath = join(dir, "build.gradle");
|
|
94
|
+
const gradleKtsPath = join(dir, "build.gradle.kts");
|
|
95
|
+
for (const manifest of [pomPath, gradlePath, gradleKtsPath].filter(existsSync)) {
|
|
96
|
+
try {
|
|
97
|
+
const content = readFileSync(manifest, "utf-8").toLowerCase();
|
|
98
|
+
if (content.includes("spring-boot") || content.includes("spring.boot"))
|
|
99
|
+
signals.push({ framework: "Spring Boot", preset: "spring-boot", confidence: 0.9 });
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// ignore
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// Check for Ruby frameworks
|
|
106
|
+
const gemfilePath = join(dir, "Gemfile");
|
|
107
|
+
if (existsSync(gemfilePath)) {
|
|
108
|
+
try {
|
|
109
|
+
const content = readFileSync(gemfilePath, "utf-8").toLowerCase();
|
|
110
|
+
if (content.includes("rails"))
|
|
111
|
+
signals.push({ framework: "Rails", preset: "rails", confidence: 0.9 });
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
// ignore
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Check for Terraform
|
|
118
|
+
const hasTfFiles = existsSync(dir) && readdirSync(dir).some((f) => f.endsWith(".tf"));
|
|
119
|
+
if (hasTfFiles)
|
|
120
|
+
signals.push({ framework: "Terraform", preset: "terraform", confidence: 0.85 });
|
|
121
|
+
// Check for Kubernetes
|
|
122
|
+
const hasK8sFiles = existsSync(dir) &&
|
|
123
|
+
readdirSync(dir).some((f) => {
|
|
124
|
+
if (!f.endsWith(".yaml") && !f.endsWith(".yml"))
|
|
125
|
+
return false;
|
|
126
|
+
try {
|
|
127
|
+
const content = readFileSync(join(dir, f), "utf-8");
|
|
128
|
+
return /apiVersion:\s/.test(content) && /kind:\s/.test(content);
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
if (hasK8sFiles)
|
|
135
|
+
signals.push({ framework: "Kubernetes", preset: "kubernetes", confidence: 0.8 });
|
|
136
|
+
// Return highest confidence signal
|
|
137
|
+
signals.sort((a, b) => b.confidence - a.confidence);
|
|
138
|
+
return signals[0];
|
|
139
|
+
}
|
|
140
|
+
// ─── File Collection ────────────────────────────────────────────────────────
|
|
141
|
+
function collectSampleFiles(dir, maxFiles) {
|
|
142
|
+
const files = [];
|
|
143
|
+
const skipDirs = new Set([
|
|
144
|
+
"node_modules",
|
|
145
|
+
".git",
|
|
146
|
+
"dist",
|
|
147
|
+
"build",
|
|
148
|
+
".next",
|
|
149
|
+
"__pycache__",
|
|
150
|
+
".venv",
|
|
151
|
+
"venv",
|
|
152
|
+
"target",
|
|
153
|
+
"bin",
|
|
154
|
+
"obj",
|
|
155
|
+
"vendor",
|
|
156
|
+
".terraform",
|
|
157
|
+
]);
|
|
158
|
+
function walk(dirPath, depth) {
|
|
159
|
+
if (depth > 5 || files.length >= maxFiles)
|
|
160
|
+
return;
|
|
161
|
+
try {
|
|
162
|
+
const entries = readdirSync(dirPath);
|
|
163
|
+
for (const entry of entries) {
|
|
164
|
+
if (files.length >= maxFiles)
|
|
165
|
+
break;
|
|
166
|
+
if (entry.startsWith("."))
|
|
167
|
+
continue;
|
|
168
|
+
if (skipDirs.has(entry))
|
|
169
|
+
continue;
|
|
170
|
+
const fullPath = join(dirPath, entry);
|
|
171
|
+
try {
|
|
172
|
+
const stat = statSync(fullPath);
|
|
173
|
+
if (stat.isDirectory()) {
|
|
174
|
+
walk(fullPath, depth + 1);
|
|
175
|
+
}
|
|
176
|
+
else if (stat.isFile() && stat.size < 100_000) {
|
|
177
|
+
const lang = detectLanguage(fullPath);
|
|
178
|
+
if (lang) {
|
|
179
|
+
try {
|
|
180
|
+
const content = readFileSync(fullPath, "utf-8");
|
|
181
|
+
if (content.trim().length > 10) {
|
|
182
|
+
files.push({ path: fullPath, content, lang });
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
// Binary file or read error
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// Permission error
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
// Can't read directory
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
walk(dir, 0);
|
|
201
|
+
return files;
|
|
202
|
+
}
|
|
203
|
+
// ─── Analysis & Recommendation ──────────────────────────────────────────────
|
|
204
|
+
function analyzeFindings(allFindings, totalFiles) {
|
|
205
|
+
const ruleCount = {};
|
|
206
|
+
const judgeCount = {};
|
|
207
|
+
const ruleSeverity = {};
|
|
208
|
+
for (const { finding } of allFindings) {
|
|
209
|
+
ruleCount[finding.ruleId] = (ruleCount[finding.ruleId] || 0) + 1;
|
|
210
|
+
ruleSeverity[finding.ruleId] = ruleSeverity[finding.ruleId] || [];
|
|
211
|
+
ruleSeverity[finding.ruleId].push(finding.severity);
|
|
212
|
+
// Extract judge name from ruleId (e.g., "SEC-001" → "security")
|
|
213
|
+
const parts = finding.ruleId.split("-");
|
|
214
|
+
if (parts.length > 1) {
|
|
215
|
+
const judgePrefix = parts[0];
|
|
216
|
+
judgeCount[judgePrefix] = (judgeCount[judgePrefix] || 0) + 1;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// Identify rules that fire on >50% of files (likely FP or style preference)
|
|
220
|
+
const disabledRules = [];
|
|
221
|
+
const severityOverrides = {};
|
|
222
|
+
const threshold = Math.max(totalFiles * 0.5, 3);
|
|
223
|
+
for (const [ruleId, count] of Object.entries(ruleCount)) {
|
|
224
|
+
if (count >= threshold) {
|
|
225
|
+
// If it fires on >80% of files, disable it entirely
|
|
226
|
+
if (count >= totalFiles * 0.8) {
|
|
227
|
+
disabledRules.push(ruleId);
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
// Downgrade to info
|
|
231
|
+
severityOverrides[ruleId] = { severity: "info" };
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// Identify judges with very low signal (many findings but all low/info)
|
|
236
|
+
const disabledJudges = [];
|
|
237
|
+
const statsMessage = `Analyzed ${totalFiles} files, found ${allFindings.length} findings across ${Object.keys(ruleCount).length} rules`;
|
|
238
|
+
const config = {};
|
|
239
|
+
if (disabledRules.length > 0)
|
|
240
|
+
config.disabledRules = disabledRules;
|
|
241
|
+
if (Object.keys(severityOverrides).length > 0)
|
|
242
|
+
config.ruleOverrides = severityOverrides;
|
|
243
|
+
if (disabledJudges.length > 0)
|
|
244
|
+
config.disabledJudges = disabledJudges;
|
|
245
|
+
return {
|
|
246
|
+
preset: undefined,
|
|
247
|
+
detectedFramework: undefined,
|
|
248
|
+
disabledRules,
|
|
249
|
+
severityOverrides,
|
|
250
|
+
disabledJudges,
|
|
251
|
+
statsMessage,
|
|
252
|
+
config,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
// ─── CLI Entry Point ────────────────────────────────────────────────────────
|
|
256
|
+
export function parseTuneArgs(argv) {
|
|
257
|
+
const args = {
|
|
258
|
+
dir: process.cwd(),
|
|
259
|
+
apply: false,
|
|
260
|
+
maxFiles: 15,
|
|
261
|
+
verbose: false,
|
|
262
|
+
};
|
|
263
|
+
for (let i = 3; i < argv.length; i++) {
|
|
264
|
+
const arg = argv[i];
|
|
265
|
+
switch (arg) {
|
|
266
|
+
case "--dir":
|
|
267
|
+
case "-d":
|
|
268
|
+
args.dir = resolve(argv[++i]);
|
|
269
|
+
break;
|
|
270
|
+
case "--apply":
|
|
271
|
+
args.apply = true;
|
|
272
|
+
break;
|
|
273
|
+
case "--max-files":
|
|
274
|
+
args.maxFiles = parseInt(argv[++i], 10);
|
|
275
|
+
break;
|
|
276
|
+
case "--verbose":
|
|
277
|
+
case "-v":
|
|
278
|
+
args.verbose = true;
|
|
279
|
+
break;
|
|
280
|
+
default:
|
|
281
|
+
if (!arg.startsWith("-")) {
|
|
282
|
+
args.dir = resolve(arg);
|
|
283
|
+
}
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return args;
|
|
288
|
+
}
|
|
289
|
+
export function runTune(argv) {
|
|
290
|
+
const args = parseTuneArgs(argv);
|
|
291
|
+
console.log("");
|
|
292
|
+
console.log("╔══════════════════════════════════════════════════════════════╗");
|
|
293
|
+
console.log("║ Judges Panel — Tune ║");
|
|
294
|
+
console.log("╚══════════════════════════════════════════════════════════════╝");
|
|
295
|
+
console.log("");
|
|
296
|
+
console.log(` Analyzing: ${args.dir}`);
|
|
297
|
+
console.log(` Sample size: up to ${args.maxFiles} files`);
|
|
298
|
+
console.log("");
|
|
299
|
+
// 1. Detect framework
|
|
300
|
+
const framework = detectFramework(args.dir);
|
|
301
|
+
if (framework) {
|
|
302
|
+
console.log(` 🔍 Detected framework: ${framework.framework} (confidence: ${Math.round(framework.confidence * 100)}%)`);
|
|
303
|
+
console.log(` Recommended preset: ${framework.preset}`);
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
console.log(" 🔍 No specific framework detected");
|
|
307
|
+
}
|
|
308
|
+
console.log("");
|
|
309
|
+
// 2. Collect sample files
|
|
310
|
+
const files = collectSampleFiles(args.dir, args.maxFiles);
|
|
311
|
+
if (files.length === 0) {
|
|
312
|
+
console.log(" ⚠️ No source files found to analyze.");
|
|
313
|
+
process.exit(0);
|
|
314
|
+
}
|
|
315
|
+
console.log(` 📂 Found ${files.length} files to analyze`);
|
|
316
|
+
// 3. Run evaluation on sample
|
|
317
|
+
console.log(" ⏳ Running evaluation...");
|
|
318
|
+
const allFindings = [];
|
|
319
|
+
for (const file of files) {
|
|
320
|
+
try {
|
|
321
|
+
const result = evaluateWithTribunal(file.content, file.lang);
|
|
322
|
+
for (const finding of result.findings) {
|
|
323
|
+
allFindings.push({ file: file.path, finding });
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
catch {
|
|
327
|
+
// Skip files that fail evaluation
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
console.log(` ✅ Found ${allFindings.length} findings`);
|
|
331
|
+
console.log("");
|
|
332
|
+
// 4. Generate recommendations
|
|
333
|
+
const rec = analyzeFindings(allFindings, files.length);
|
|
334
|
+
rec.detectedFramework = framework?.framework;
|
|
335
|
+
rec.preset = framework?.preset;
|
|
336
|
+
// Merge framework preset config
|
|
337
|
+
if (rec.preset && PRESETS[rec.preset]) {
|
|
338
|
+
const presetConfig = PRESETS[rec.preset].config;
|
|
339
|
+
rec.config = {
|
|
340
|
+
preset: rec.preset,
|
|
341
|
+
...rec.config,
|
|
342
|
+
disabledJudges: [...new Set([...(presetConfig.disabledJudges || []), ...(rec.config.disabledJudges || [])])],
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
// 5. Display recommendations
|
|
346
|
+
console.log(" ─── Recommendations ───────────────────────────────────────");
|
|
347
|
+
console.log("");
|
|
348
|
+
console.log(` ${rec.statsMessage}`);
|
|
349
|
+
console.log("");
|
|
350
|
+
if (rec.preset) {
|
|
351
|
+
console.log(` 📋 Preset: "${rec.preset}"`);
|
|
352
|
+
}
|
|
353
|
+
if (rec.disabledRules.length > 0) {
|
|
354
|
+
console.log(` 🔇 Disable noisy rules (fire on >80% of files):`);
|
|
355
|
+
for (const rule of rec.disabledRules) {
|
|
356
|
+
console.log(` - ${rule}`);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
if (Object.keys(rec.severityOverrides).length > 0) {
|
|
360
|
+
console.log(` 📉 Downgrade rules to info (fire on >50% of files):`);
|
|
361
|
+
for (const [rule, override] of Object.entries(rec.severityOverrides)) {
|
|
362
|
+
console.log(` - ${rule} → ${override.severity ?? "info"}`);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
if ((rec.config.disabledJudges || []).length > 0) {
|
|
366
|
+
console.log(` ⏭️ Disabled judges (from preset + analysis):`);
|
|
367
|
+
for (const judge of rec.config.disabledJudges || []) {
|
|
368
|
+
console.log(` - ${judge}`);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
console.log("");
|
|
372
|
+
// 6. Build final .judgesrc.json
|
|
373
|
+
const judgesrc = {};
|
|
374
|
+
if (rec.config.preset)
|
|
375
|
+
judgesrc.preset = rec.config.preset;
|
|
376
|
+
if ((rec.config.disabledRules || []).length > 0)
|
|
377
|
+
judgesrc.disabledRules = rec.config.disabledRules;
|
|
378
|
+
if (Object.keys(rec.config.ruleOverrides || {}).length > 0)
|
|
379
|
+
judgesrc.ruleOverrides = rec.config.ruleOverrides;
|
|
380
|
+
if ((rec.config.disabledJudges || []).length > 0)
|
|
381
|
+
judgesrc.disabledJudges = rec.config.disabledJudges;
|
|
382
|
+
if ((rec.config.languages || []).length > 0)
|
|
383
|
+
judgesrc.languages = rec.config.languages;
|
|
384
|
+
const configJson = JSON.stringify(judgesrc, null, 2);
|
|
385
|
+
console.log(" 📄 Recommended .judgesrc.json:");
|
|
386
|
+
console.log("");
|
|
387
|
+
for (const line of configJson.split("\n")) {
|
|
388
|
+
console.log(` ${line}`);
|
|
389
|
+
}
|
|
390
|
+
console.log("");
|
|
391
|
+
if (args.apply) {
|
|
392
|
+
const outputPath = join(args.dir, ".judgesrc.json");
|
|
393
|
+
if (existsSync(outputPath)) {
|
|
394
|
+
console.log(` ⚠️ ${outputPath} already exists — writing to .judgesrc.tuned.json instead`);
|
|
395
|
+
writeFileSync(join(args.dir, ".judgesrc.tuned.json"), configJson + "\n", "utf-8");
|
|
396
|
+
console.log(` ✅ Written to ${join(args.dir, ".judgesrc.tuned.json")}`);
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
writeFileSync(outputPath, configJson + "\n", "utf-8");
|
|
400
|
+
console.log(` ✅ Written to ${outputPath}`);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
else {
|
|
404
|
+
console.log(" 💡 Run `judges tune --apply` to write this config automatically.");
|
|
405
|
+
}
|
|
406
|
+
console.log("");
|
|
407
|
+
}
|
|
408
|
+
//# sourceMappingURL=tune.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tune.js","sourceRoot":"","sources":["../../src/commands/tune.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finding Lifecycle Tracking
|
|
3
|
+
*
|
|
4
|
+
* Tracks individual findings across multiple evaluation runs, enabling:
|
|
5
|
+
* - New vs. recurring finding classification
|
|
6
|
+
* - "Fixed" detection when a finding disappears
|
|
7
|
+
* - Finding trend statistics (are things getting better or worse?)
|
|
8
|
+
* - Age tracking (how long has a finding been open?)
|
|
9
|
+
*
|
|
10
|
+
* Data stored in .judges-findings.json
|
|
11
|
+
*/
|
|
12
|
+
import type { Finding, Severity } from "./types.js";
|
|
13
|
+
export interface TrackedFinding {
|
|
14
|
+
/** Stable fingerprint based on ruleId + file + code context */
|
|
15
|
+
fingerprint: string;
|
|
16
|
+
/** Rule that generated this finding */
|
|
17
|
+
ruleId: string;
|
|
18
|
+
/** Finding severity */
|
|
19
|
+
severity: Severity;
|
|
20
|
+
/** File where the finding was detected */
|
|
21
|
+
filePath: string;
|
|
22
|
+
/** Finding title for display */
|
|
23
|
+
title: string;
|
|
24
|
+
/** First seen timestamp */
|
|
25
|
+
firstSeen: string;
|
|
26
|
+
/** Last seen timestamp */
|
|
27
|
+
lastSeen: string;
|
|
28
|
+
/** Number of consecutive runs this finding has appeared */
|
|
29
|
+
runCount: number;
|
|
30
|
+
/** Whether this finding is currently active */
|
|
31
|
+
status: "open" | "fixed";
|
|
32
|
+
/** When the finding was resolved */
|
|
33
|
+
fixedAt?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface FindingStore {
|
|
36
|
+
version: string;
|
|
37
|
+
lastRunAt: string;
|
|
38
|
+
runNumber: number;
|
|
39
|
+
findings: TrackedFinding[];
|
|
40
|
+
}
|
|
41
|
+
export interface FindingDelta {
|
|
42
|
+
/** Findings that appeared for the first time in this run */
|
|
43
|
+
introduced: TrackedFinding[];
|
|
44
|
+
/** Findings that are still present from previous runs */
|
|
45
|
+
recurring: TrackedFinding[];
|
|
46
|
+
/** Findings from previous runs that are no longer present */
|
|
47
|
+
fixed: TrackedFinding[];
|
|
48
|
+
/** Summary statistics */
|
|
49
|
+
stats: {
|
|
50
|
+
totalOpen: number;
|
|
51
|
+
totalFixed: number;
|
|
52
|
+
introduced: number;
|
|
53
|
+
recurring: number;
|
|
54
|
+
fixed: number;
|
|
55
|
+
trend: "improving" | "stable" | "degrading";
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Generate a stable fingerprint for a finding that survives minor code edits.
|
|
60
|
+
* Based on ruleId + file path + approximate code location.
|
|
61
|
+
*/
|
|
62
|
+
export declare function generateFindingFingerprint(finding: Finding, filePath: string): string;
|
|
63
|
+
export declare function loadFindingStore(dir?: string): FindingStore;
|
|
64
|
+
export declare function saveFindingStore(store: FindingStore, dir?: string): void;
|
|
65
|
+
/**
|
|
66
|
+
* Update the finding store with results from a new evaluation run.
|
|
67
|
+
* Returns a delta describing what changed since the last run.
|
|
68
|
+
*
|
|
69
|
+
* When `dirOrStore` is a string, reads/writes `.judges-findings.json` in that
|
|
70
|
+
* directory. When a `FindingStore` object is passed directly, operates
|
|
71
|
+
* in-memory (useful for testing) and does NOT persist to disk.
|
|
72
|
+
*/
|
|
73
|
+
export declare function updateFindings(currentFindings: Array<{
|
|
74
|
+
finding: Finding;
|
|
75
|
+
filePath: string;
|
|
76
|
+
}>, dirOrStore?: string | FindingStore): FindingDelta;
|
|
77
|
+
/**
|
|
78
|
+
* Get summary statistics from the finding store.
|
|
79
|
+
*/
|
|
80
|
+
export declare function getFindingStats(dirOrStore?: string | FindingStore): {
|
|
81
|
+
totalOpen: number;
|
|
82
|
+
totalFixed: number;
|
|
83
|
+
oldestOpen: string | undefined;
|
|
84
|
+
bySeverity: Record<string, number>;
|
|
85
|
+
byRule: Record<string, number>;
|
|
86
|
+
avgAge: number;
|
|
87
|
+
runCount: number;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Format finding delta as a human-readable summary for CLI output.
|
|
91
|
+
*/
|
|
92
|
+
export declare function formatDelta(delta: FindingDelta): string;
|
|
93
|
+
//# sourceMappingURL=finding-lifecycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finding-lifecycle.d.ts","sourceRoot":"","sources":["../src/finding-lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAIpD,MAAM,WAAW,cAAc;IAC7B,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,uBAAuB;IACvB,QAAQ,EAAE,QAAQ,CAAC;IACnB,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,cAAc,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,YAAY;IAC3B,4DAA4D;IAC5D,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,yDAAyD;IACzD,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,6DAA6D;IAC7D,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,yBAAyB;IACzB,KAAK,EAAE;QACL,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;KAC7C,CAAC;CACH;AAID;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOrF;AAMD,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,MAAY,GAAG,YAAY,CAoBhE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,GAAE,MAAY,GAAG,IAAI,CAG7E;AAID;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,eAAe,EAAE,KAAK,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,EAC9D,UAAU,GAAE,MAAM,GAAG,YAAkB,GACtC,YAAY,CAmGd;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,UAAU,GAAE,MAAM,GAAG,YAAkB,GAAG;IACxE,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB,CA6BA;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAgCvD"}
|