@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.
Files changed (78) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +1 -1
  3. package/dist/api.d.ts +6 -1
  4. package/dist/api.d.ts.map +1 -1
  5. package/dist/api.js +6 -1
  6. package/dist/api.js.map +1 -1
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +123 -5
  9. package/dist/cli.js.map +1 -1
  10. package/dist/commands/benchmark.d.ts.map +1 -1
  11. package/dist/commands/benchmark.js +556 -0
  12. package/dist/commands/benchmark.js.map +1 -1
  13. package/dist/commands/diff.d.ts.map +1 -1
  14. package/dist/commands/diff.js +17 -1
  15. package/dist/commands/diff.js.map +1 -1
  16. package/dist/commands/fix.d.ts +27 -1
  17. package/dist/commands/fix.d.ts.map +1 -1
  18. package/dist/commands/fix.js +137 -13
  19. package/dist/commands/fix.js.map +1 -1
  20. package/dist/commands/lsp.d.ts +24 -0
  21. package/dist/commands/lsp.d.ts.map +1 -0
  22. package/dist/commands/lsp.js +287 -0
  23. package/dist/commands/lsp.js.map +1 -0
  24. package/dist/commands/review.d.ts +37 -0
  25. package/dist/commands/review.d.ts.map +1 -0
  26. package/dist/commands/review.js +539 -0
  27. package/dist/commands/review.js.map +1 -0
  28. package/dist/commands/scaffold-plugin.d.ts +16 -0
  29. package/dist/commands/scaffold-plugin.d.ts.map +1 -0
  30. package/dist/commands/scaffold-plugin.js +271 -0
  31. package/dist/commands/scaffold-plugin.js.map +1 -0
  32. package/dist/commands/tune.d.ts +25 -0
  33. package/dist/commands/tune.d.ts.map +1 -0
  34. package/dist/commands/tune.js +408 -0
  35. package/dist/commands/tune.js.map +1 -0
  36. package/dist/config.d.ts +12 -0
  37. package/dist/config.d.ts.map +1 -1
  38. package/dist/config.js +128 -0
  39. package/dist/config.js.map +1 -1
  40. package/dist/disk-cache.d.ts +40 -0
  41. package/dist/disk-cache.d.ts.map +1 -0
  42. package/dist/disk-cache.js +196 -0
  43. package/dist/disk-cache.js.map +1 -0
  44. package/dist/evaluators/index.d.ts.map +1 -1
  45. package/dist/evaluators/index.js +50 -3
  46. package/dist/evaluators/index.js.map +1 -1
  47. package/dist/evaluators/v2.d.ts.map +1 -1
  48. package/dist/evaluators/v2.js +2 -2
  49. package/dist/evaluators/v2.js.map +1 -1
  50. package/dist/finding-lifecycle.d.ts +93 -0
  51. package/dist/finding-lifecycle.d.ts.map +1 -0
  52. package/dist/finding-lifecycle.js +214 -0
  53. package/dist/finding-lifecycle.js.map +1 -0
  54. package/dist/formatters/github-actions.d.ts +7 -0
  55. package/dist/formatters/github-actions.d.ts.map +1 -0
  56. package/dist/formatters/github-actions.js +69 -0
  57. package/dist/formatters/github-actions.js.map +1 -0
  58. package/dist/patches/index.d.ts.map +1 -1
  59. package/dist/patches/index.js +127 -0
  60. package/dist/patches/index.js.map +1 -1
  61. package/dist/presets.d.ts.map +1 -1
  62. package/dist/presets.js +103 -0
  63. package/dist/presets.js.map +1 -1
  64. package/dist/scoring.d.ts +8 -0
  65. package/dist/scoring.d.ts.map +1 -1
  66. package/dist/scoring.js +66 -26
  67. package/dist/scoring.js.map +1 -1
  68. package/dist/tools/register-evaluation.d.ts +1 -1
  69. package/dist/tools/register-evaluation.d.ts.map +1 -1
  70. package/dist/tools/register-evaluation.js +90 -1
  71. package/dist/tools/register-evaluation.js.map +1 -1
  72. package/dist/tools/register-workflow.d.ts.map +1 -1
  73. package/dist/tools/register-workflow.js +23 -20
  74. package/dist/tools/register-workflow.js.map +1 -1
  75. package/dist/types.d.ts +36 -2
  76. package/dist/types.d.ts.map +1 -1
  77. package/package.json +1 -1
  78. 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
@@ -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,CA4IzD;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,CAuCrE;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"}
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