@kevinrabun/judges 3.23.6 → 3.23.8
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 +40 -0
- package/README.md +1 -1
- package/dist/api.d.ts +6 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +6 -1
- package/dist/api.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +123 -5
- 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/fix.d.ts +27 -1
- package/dist/commands/fix.d.ts.map +1 -1
- package/dist/commands/fix.js +137 -13
- package/dist/commands/fix.js.map +1 -1
- package/dist/commands/lsp.d.ts +24 -0
- package/dist/commands/lsp.d.ts.map +1 -0
- package/dist/commands/lsp.js +287 -0
- package/dist/commands/lsp.js.map +1 -0
- 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/scaffold-plugin.d.ts +16 -0
- package/dist/commands/scaffold-plugin.d.ts.map +1 -0
- package/dist/commands/scaffold-plugin.js +271 -0
- package/dist/commands/scaffold-plugin.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/config.d.ts +12 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +128 -0
- package/dist/config.js.map +1 -1
- package/dist/disk-cache.d.ts +40 -0
- package/dist/disk-cache.d.ts.map +1 -0
- package/dist/disk-cache.js +196 -0
- package/dist/disk-cache.js.map +1 -0
- package/dist/evaluators/index.d.ts.map +1 -1
- package/dist/evaluators/index.js +50 -3
- package/dist/evaluators/index.js.map +1 -1
- package/dist/evaluators/v2.d.ts.map +1 -1
- package/dist/evaluators/v2.js +2 -2
- package/dist/evaluators/v2.js.map +1 -1
- 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/formatters/github-actions.d.ts +7 -0
- package/dist/formatters/github-actions.d.ts.map +1 -0
- package/dist/formatters/github-actions.js +69 -0
- package/dist/formatters/github-actions.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/dist/scoring.d.ts +8 -0
- package/dist/scoring.d.ts.map +1 -1
- package/dist/scoring.js +66 -26
- package/dist/scoring.js.map +1 -1
- package/dist/tools/register-evaluation.d.ts +1 -1
- package/dist/tools/register-evaluation.d.ts.map +1 -1
- package/dist/tools/register-evaluation.js +90 -1
- package/dist/tools/register-evaluation.js.map +1 -1
- package/dist/tools/register-workflow.d.ts.map +1 -1
- package/dist/tools/register-workflow.js +23 -20
- package/dist/tools/register-workflow.js.map +1 -1
- package/dist/types.d.ts +36 -2
- package/dist/types.d.ts.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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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -56,4 +56,16 @@ export declare function loadPluginJudges(pluginSpecifiers: string[], baseDir?: s
|
|
|
56
56
|
* Returns an array of validation error messages (empty if all valid).
|
|
57
57
|
*/
|
|
58
58
|
export declare function validatePluginSpecifiers(specifiers: string[]): string[];
|
|
59
|
+
/**
|
|
60
|
+
* Apply path-scoped overrides to a base config for a specific file.
|
|
61
|
+
*
|
|
62
|
+
* Each override entry carries a glob `files` pattern (e.g. `"**\/*.test.ts"`).
|
|
63
|
+
* If the file path matches, the override's partial config is merged on top
|
|
64
|
+
* of the base config. Multiple matching overrides are applied in order.
|
|
65
|
+
*
|
|
66
|
+
* @param config - The resolved base config
|
|
67
|
+
* @param filePath - The relative file path to match against override globs
|
|
68
|
+
* @returns A new config with matching overrides applied
|
|
69
|
+
*/
|
|
70
|
+
export declare function applyOverridesForFile(config: JudgesConfig, filePath: string): JudgesConfig;
|
|
59
71
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAY,eAAe,EAAE,MAAM,YAAY,CAAC;AAQ1E;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAY,eAAe,EAAE,MAAM,YAAY,CAAC;AAQ1E;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CA8LzD;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,YAAY,CAE5C;AAOD;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,YAAY,EAAE,CAgC3F;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,GAAG,OAAO,EAAE,YAAY,EAAE,GAAG,YAAY,CAkDrE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,YAAY,CAIpF;AAID;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,eAAe,CAY3E;AAWD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,gBAAgB,CACpC,gBAAgB,EAAE,MAAM,EAAE,EAC1B,OAAO,CAAC,EAAE,MAAM,EAChB,QAAQ,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAoB,GAC9C,OAAO,CAAC,eAAe,EAAE,CAAC,CAyD5B;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAgBvE;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,CAwB1F"}
|
package/dist/config.js
CHANGED
|
@@ -133,6 +133,54 @@ export function parseConfig(jsonStr) {
|
|
|
133
133
|
}
|
|
134
134
|
config.plugins = obj.plugins;
|
|
135
135
|
}
|
|
136
|
+
// failOnScoreBelow
|
|
137
|
+
if (obj.failOnScoreBelow !== undefined) {
|
|
138
|
+
if (typeof obj.failOnScoreBelow !== "number" || obj.failOnScoreBelow < 0 || obj.failOnScoreBelow > 10) {
|
|
139
|
+
throw new ConfigError('Invalid .judgesrc: "failOnScoreBelow" must be a number between 0 and 10');
|
|
140
|
+
}
|
|
141
|
+
config.failOnScoreBelow = obj.failOnScoreBelow;
|
|
142
|
+
}
|
|
143
|
+
// judgeWeights
|
|
144
|
+
if (obj.judgeWeights !== undefined) {
|
|
145
|
+
if (typeof obj.judgeWeights !== "object" || obj.judgeWeights === null || Array.isArray(obj.judgeWeights)) {
|
|
146
|
+
throw new ConfigError('Invalid .judgesrc: "judgeWeights" must be an object mapping judge IDs to numbers');
|
|
147
|
+
}
|
|
148
|
+
const weights = {};
|
|
149
|
+
for (const [key, val] of Object.entries(obj.judgeWeights)) {
|
|
150
|
+
if (typeof val !== "number" || val < 0) {
|
|
151
|
+
throw new ConfigError(`Invalid .judgesrc: judgeWeights["${key}"] must be a non-negative number`);
|
|
152
|
+
}
|
|
153
|
+
weights[key] = val;
|
|
154
|
+
}
|
|
155
|
+
config.judgeWeights = weights;
|
|
156
|
+
}
|
|
157
|
+
// overrides
|
|
158
|
+
if (obj.overrides !== undefined) {
|
|
159
|
+
if (!Array.isArray(obj.overrides)) {
|
|
160
|
+
throw new ConfigError('Invalid .judgesrc: "overrides" must be an array of override objects');
|
|
161
|
+
}
|
|
162
|
+
const parsedOverrides = [];
|
|
163
|
+
for (let i = 0; i < obj.overrides.length; i++) {
|
|
164
|
+
const entry = obj.overrides[i];
|
|
165
|
+
if (typeof entry !== "object" || entry === null || typeof entry.files !== "string") {
|
|
166
|
+
throw new ConfigError(`Invalid .judgesrc: overrides[${i}] must have a "files" glob string`);
|
|
167
|
+
}
|
|
168
|
+
// Clone the entry, strip 'files', parse the rest as partial config
|
|
169
|
+
const { files, ...rest } = entry;
|
|
170
|
+
let partial = {};
|
|
171
|
+
if (Object.keys(rest).length > 0) {
|
|
172
|
+
try {
|
|
173
|
+
partial = parseConfig(JSON.stringify(rest));
|
|
174
|
+
}
|
|
175
|
+
catch (e) {
|
|
176
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
177
|
+
throw new ConfigError(`Invalid .judgesrc: overrides[${i}]: ${msg}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
parsedOverrides.push({ files: files, ...partial });
|
|
181
|
+
}
|
|
182
|
+
config.overrides = parsedOverrides;
|
|
183
|
+
}
|
|
136
184
|
return config;
|
|
137
185
|
}
|
|
138
186
|
/**
|
|
@@ -222,10 +270,20 @@ export function mergeConfigs(...configs) {
|
|
|
222
270
|
merged.baseline = cfg.baseline;
|
|
223
271
|
if (cfg.format !== undefined)
|
|
224
272
|
merged.format = cfg.format;
|
|
273
|
+
if (cfg.failOnScoreBelow !== undefined)
|
|
274
|
+
merged.failOnScoreBelow = cfg.failOnScoreBelow;
|
|
225
275
|
// Deep-merge ruleOverrides
|
|
226
276
|
if (cfg.ruleOverrides) {
|
|
227
277
|
merged.ruleOverrides = { ...(merged.ruleOverrides ?? {}), ...cfg.ruleOverrides };
|
|
228
278
|
}
|
|
279
|
+
// Deep-merge judgeWeights
|
|
280
|
+
if (cfg.judgeWeights) {
|
|
281
|
+
merged.judgeWeights = { ...(merged.judgeWeights ?? {}), ...cfg.judgeWeights };
|
|
282
|
+
}
|
|
283
|
+
// Overrides: concatenate (later entries take precedence naturally)
|
|
284
|
+
if (cfg.overrides) {
|
|
285
|
+
merged.overrides = [...(merged.overrides ?? []), ...cfg.overrides];
|
|
286
|
+
}
|
|
229
287
|
}
|
|
230
288
|
return merged;
|
|
231
289
|
}
|
|
@@ -353,4 +411,74 @@ export function validatePluginSpecifiers(specifiers) {
|
|
|
353
411
|
}
|
|
354
412
|
return errors;
|
|
355
413
|
}
|
|
414
|
+
// ─── Per-File Config Overrides ──────────────────────────────────────────────
|
|
415
|
+
/**
|
|
416
|
+
* Apply path-scoped overrides to a base config for a specific file.
|
|
417
|
+
*
|
|
418
|
+
* Each override entry carries a glob `files` pattern (e.g. `"**\/*.test.ts"`).
|
|
419
|
+
* If the file path matches, the override's partial config is merged on top
|
|
420
|
+
* of the base config. Multiple matching overrides are applied in order.
|
|
421
|
+
*
|
|
422
|
+
* @param config - The resolved base config
|
|
423
|
+
* @param filePath - The relative file path to match against override globs
|
|
424
|
+
* @returns A new config with matching overrides applied
|
|
425
|
+
*/
|
|
426
|
+
export function applyOverridesForFile(config, filePath) {
|
|
427
|
+
if (!config.overrides || config.overrides.length === 0) {
|
|
428
|
+
return config;
|
|
429
|
+
}
|
|
430
|
+
// Normalize path separators for glob matching
|
|
431
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
432
|
+
const matchingOverrides = [];
|
|
433
|
+
for (const override of config.overrides) {
|
|
434
|
+
if (globMatch(normalized, override.files)) {
|
|
435
|
+
// Extract config fields (everything except 'files')
|
|
436
|
+
const { files: _files, ...partial } = override;
|
|
437
|
+
matchingOverrides.push(partial);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
if (matchingOverrides.length === 0) {
|
|
441
|
+
return config;
|
|
442
|
+
}
|
|
443
|
+
// Merge: base config first, then matching overrides in order
|
|
444
|
+
const { overrides: _overrides, ...baseWithoutOverrides } = config;
|
|
445
|
+
return mergeConfigs(baseWithoutOverrides, ...matchingOverrides);
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Simple glob matcher supporting `*`, `**`, and `?`.
|
|
449
|
+
* - `*` matches any characters except `/`
|
|
450
|
+
* - `**` matches any characters including `/` (directory recursion)
|
|
451
|
+
* - `?` matches exactly one character except `/`
|
|
452
|
+
*/
|
|
453
|
+
function globMatch(path, pattern) {
|
|
454
|
+
// Escape regex special chars except *, ?, and /
|
|
455
|
+
let regex = "";
|
|
456
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
457
|
+
const ch = pattern[i];
|
|
458
|
+
if (ch === "*") {
|
|
459
|
+
if (pattern[i + 1] === "*") {
|
|
460
|
+
// ** — match anything including path separators
|
|
461
|
+
regex += ".*";
|
|
462
|
+
i++; // skip second *
|
|
463
|
+
// Skip optional trailing /
|
|
464
|
+
if (pattern[i + 1] === "/")
|
|
465
|
+
i++;
|
|
466
|
+
}
|
|
467
|
+
else {
|
|
468
|
+
// * — match anything except /
|
|
469
|
+
regex += "[^/]*";
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
else if (ch === "?") {
|
|
473
|
+
regex += "[^/]";
|
|
474
|
+
}
|
|
475
|
+
else if (".+^${}()|[]\\".includes(ch)) {
|
|
476
|
+
regex += "\\" + ch;
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
regex += ch;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
return new RegExp("^" + regex + "$", "i").test(path);
|
|
483
|
+
}
|
|
356
484
|
//# sourceMappingURL=config.js.map
|