@kevinrabun/judges 3.119.0 → 3.122.0
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/README.md +1 -1
- package/dist/api.d.ts +2 -1
- package/dist/api.js +3 -1
- package/dist/cli-dispatch.d.ts +7 -0
- package/dist/cli-dispatch.js +654 -0
- package/dist/cli-formatters.d.ts +6 -0
- package/dist/cli-formatters.js +186 -0
- package/dist/cli.js +69 -4159
- package/dist/commands/baseline.js +2 -42
- package/dist/commands/coverage.js +3 -39
- package/dist/commands/diff.js +2 -38
- package/dist/commands/fix-pr.js +2 -23
- package/dist/commands/fix.js +3 -27
- package/dist/commands/llm-benchmark.d.ts +7 -0
- package/dist/commands/llm-benchmark.js +27 -1
- package/dist/commands/quality-gate.js +1 -12
- package/dist/commands/review-parallel.js +1 -19
- package/dist/commands/review.js +2 -33
- package/dist/commands/rule-test.js +1 -15
- package/dist/commands/tune.js +2 -29
- package/dist/commands/watch.js +3 -42
- package/dist/config.js +1 -1
- package/dist/evaluators/hallucination-detection.js +343 -0
- package/dist/evaluators/index.d.ts +2 -11
- package/dist/evaluators/index.js +3 -181
- package/dist/evaluators/security.js +226 -2
- package/dist/evaluators/suppressions.d.ts +49 -0
- package/dist/evaluators/suppressions.js +185 -0
- package/dist/ext-to-lang.d.ts +16 -0
- package/dist/ext-to-lang.js +60 -0
- package/dist/github-app.d.ts +1 -3
- package/dist/github-app.js +2 -34
- package/dist/parallel.js +2 -14
- package/dist/probabilistic/llm-response-validator.js +1 -1
- package/dist/reports/public-repo-report.js +9 -1
- package/dist/skill-loader.js +9 -6
- package/dist/tools/register-evaluation.js +2 -29
- package/package.json +1 -1
- package/server.json +2 -2
- package/src/skill-loader.ts +9 -6
|
@@ -9,50 +9,10 @@
|
|
|
9
9
|
// ──────────────────────────────────────────────────────────────────────────────
|
|
10
10
|
import { createHash } from "crypto";
|
|
11
11
|
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
12
|
-
import { resolve,
|
|
12
|
+
import { resolve, relative } from "path";
|
|
13
13
|
import { evaluateWithTribunal } from "../evaluators/index.js";
|
|
14
14
|
import { collectFiles } from "../cli.js";
|
|
15
|
-
|
|
16
|
-
const EXT_TO_LANG = {
|
|
17
|
-
".ts": "typescript",
|
|
18
|
-
".tsx": "typescript",
|
|
19
|
-
".js": "javascript",
|
|
20
|
-
".jsx": "javascript",
|
|
21
|
-
".mjs": "javascript",
|
|
22
|
-
".cjs": "javascript",
|
|
23
|
-
".py": "python",
|
|
24
|
-
".rs": "rust",
|
|
25
|
-
".go": "go",
|
|
26
|
-
".java": "java",
|
|
27
|
-
".cs": "csharp",
|
|
28
|
-
".rb": "ruby",
|
|
29
|
-
".php": "php",
|
|
30
|
-
".swift": "swift",
|
|
31
|
-
".kt": "kotlin",
|
|
32
|
-
".scala": "scala",
|
|
33
|
-
".c": "c",
|
|
34
|
-
".cpp": "cpp",
|
|
35
|
-
".h": "c",
|
|
36
|
-
".hpp": "cpp",
|
|
37
|
-
".yaml": "yaml",
|
|
38
|
-
".yml": "yaml",
|
|
39
|
-
".json": "json",
|
|
40
|
-
".tf": "terraform",
|
|
41
|
-
".hcl": "terraform",
|
|
42
|
-
".sh": "bash",
|
|
43
|
-
".bash": "bash",
|
|
44
|
-
".ps1": "powershell",
|
|
45
|
-
".psm1": "powershell",
|
|
46
|
-
".dart": "dart",
|
|
47
|
-
".sql": "sql",
|
|
48
|
-
".bicep": "bicep",
|
|
49
|
-
};
|
|
50
|
-
function detectLanguage(filePath) {
|
|
51
|
-
if (filePath.toLowerCase().includes("dockerfile"))
|
|
52
|
-
return "dockerfile";
|
|
53
|
-
const ext = extname(filePath.toLowerCase());
|
|
54
|
-
return EXT_TO_LANG[ext];
|
|
55
|
-
}
|
|
15
|
+
import { detectLanguageFromPath as detectLanguage } from "../ext-to-lang.js";
|
|
56
16
|
// ─── Fingerprinting ────────────────────────────────────────────────────────
|
|
57
17
|
// Hash ruleId + title + normalized surrounding source context so that findings
|
|
58
18
|
// survive line-number shifts caused by unrelated edits.
|
|
@@ -6,42 +6,10 @@
|
|
|
6
6
|
// const report = computeLanguageCoverage(fileList);
|
|
7
7
|
// console.log(formatCoverageReport(report));
|
|
8
8
|
// ──────────────────────────────────────────────────────────────────────────────
|
|
9
|
-
import { extname } from "path";
|
|
10
9
|
import { normalizeLanguage } from "../language-patterns.js";
|
|
11
10
|
import { JUDGES } from "../judges/index.js";
|
|
12
|
-
// ─── Extension → Language mapping
|
|
13
|
-
|
|
14
|
-
".ts": "typescript",
|
|
15
|
-
".tsx": "typescript",
|
|
16
|
-
".js": "javascript",
|
|
17
|
-
".jsx": "javascript",
|
|
18
|
-
".mjs": "javascript",
|
|
19
|
-
".cjs": "javascript",
|
|
20
|
-
".py": "python",
|
|
21
|
-
".rs": "rust",
|
|
22
|
-
".go": "go",
|
|
23
|
-
".java": "java",
|
|
24
|
-
".cs": "csharp",
|
|
25
|
-
".rb": "ruby",
|
|
26
|
-
".php": "php",
|
|
27
|
-
".swift": "swift",
|
|
28
|
-
".kt": "kotlin",
|
|
29
|
-
".scala": "scala",
|
|
30
|
-
".c": "c",
|
|
31
|
-
".cpp": "cpp",
|
|
32
|
-
".h": "c",
|
|
33
|
-
".hpp": "cpp",
|
|
34
|
-
".yaml": "yaml",
|
|
35
|
-
".yml": "yaml",
|
|
36
|
-
".json": "json",
|
|
37
|
-
".tf": "terraform",
|
|
38
|
-
".hcl": "terraform",
|
|
39
|
-
".sh": "bash",
|
|
40
|
-
".bash": "bash",
|
|
41
|
-
".ps1": "powershell",
|
|
42
|
-
".psm1": "powershell",
|
|
43
|
-
".bicep": "bicep",
|
|
44
|
-
};
|
|
11
|
+
// ─── Extension → Language mapping ────────────────────────────────────────────
|
|
12
|
+
import { detectLanguageFromPath } from "../ext-to-lang.js";
|
|
45
13
|
/**
|
|
46
14
|
* Languages for which the Judges Panel has first-class evaluator coverage.
|
|
47
15
|
* A language is "covered" if normalizeLanguage returns a recognized LangFamily
|
|
@@ -70,11 +38,7 @@ const COVERED_LANGUAGES = new Set([
|
|
|
70
38
|
* Detect language from file path extension.
|
|
71
39
|
*/
|
|
72
40
|
export function detectFileLanguage(filePath) {
|
|
73
|
-
|
|
74
|
-
if (lower.endsWith("dockerfile") || lower.includes("dockerfile."))
|
|
75
|
-
return "dockerfile";
|
|
76
|
-
const ext = extname(lower);
|
|
77
|
-
return EXT_TO_LANG[ext] ?? "unknown";
|
|
41
|
+
return detectLanguageFromPath(filePath) ?? "unknown";
|
|
78
42
|
}
|
|
79
43
|
/**
|
|
80
44
|
* Count how many judges can evaluate a given language.
|
package/dist/commands/diff.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// judges diff --file changes.patch --language typescript
|
|
7
7
|
// ──────────────────────────────────────────────────────────────────────────────
|
|
8
8
|
import { readFileSync, existsSync } from "fs";
|
|
9
|
-
import { resolve
|
|
9
|
+
import { resolve } from "path";
|
|
10
10
|
import { evaluateDiff } from "../evaluators/index.js";
|
|
11
11
|
/**
|
|
12
12
|
* Parse a unified diff into hunks with changed line information.
|
|
@@ -79,43 +79,7 @@ function parseUnifiedDiff(diffText) {
|
|
|
79
79
|
return hunks;
|
|
80
80
|
}
|
|
81
81
|
// ─── Language Detection ─────────────────────────────────────────────────────
|
|
82
|
-
|
|
83
|
-
".ts": "typescript",
|
|
84
|
-
".tsx": "typescript",
|
|
85
|
-
".js": "javascript",
|
|
86
|
-
".jsx": "javascript",
|
|
87
|
-
".mjs": "javascript",
|
|
88
|
-
".cjs": "javascript",
|
|
89
|
-
".py": "python",
|
|
90
|
-
".rs": "rust",
|
|
91
|
-
".go": "go",
|
|
92
|
-
".java": "java",
|
|
93
|
-
".cs": "csharp",
|
|
94
|
-
".rb": "ruby",
|
|
95
|
-
".php": "php",
|
|
96
|
-
".swift": "swift",
|
|
97
|
-
".kt": "kotlin",
|
|
98
|
-
".scala": "scala",
|
|
99
|
-
".c": "c",
|
|
100
|
-
".cpp": "cpp",
|
|
101
|
-
".h": "c",
|
|
102
|
-
".hpp": "cpp",
|
|
103
|
-
".yaml": "yaml",
|
|
104
|
-
".yml": "yaml",
|
|
105
|
-
".json": "json",
|
|
106
|
-
".tf": "terraform",
|
|
107
|
-
".hcl": "terraform",
|
|
108
|
-
".sh": "bash",
|
|
109
|
-
".bash": "bash",
|
|
110
|
-
".ps1": "powershell",
|
|
111
|
-
".psm1": "powershell",
|
|
112
|
-
};
|
|
113
|
-
function detectLanguage(filePath) {
|
|
114
|
-
const ext = extname(filePath.toLowerCase());
|
|
115
|
-
if (filePath.toLowerCase().includes("dockerfile"))
|
|
116
|
-
return "dockerfile";
|
|
117
|
-
return EXT_TO_LANG[ext];
|
|
118
|
-
}
|
|
82
|
+
import { detectLanguageFromPath as detectLanguage } from "../ext-to-lang.js";
|
|
119
83
|
// ─── Deletion Analysis ──────────────────────────────────────────────────────
|
|
120
84
|
/**
|
|
121
85
|
* Patterns that indicate security-relevant code. When these are removed
|
package/dist/commands/fix-pr.js
CHANGED
|
@@ -20,30 +20,9 @@ import { tmpdir } from "os";
|
|
|
20
20
|
import { evaluateWithTribunal } from "../evaluators/index.js";
|
|
21
21
|
import { applyPatches } from "./fix.js";
|
|
22
22
|
import { parseGitHubRepo, runGit, tryRunGit } from "../tools/command-safety.js";
|
|
23
|
-
|
|
24
|
-
const EXT_TO_LANG = {
|
|
25
|
-
".ts": "typescript",
|
|
26
|
-
".tsx": "typescript",
|
|
27
|
-
".js": "javascript",
|
|
28
|
-
".jsx": "javascript",
|
|
29
|
-
".mjs": "javascript",
|
|
30
|
-
".cjs": "javascript",
|
|
31
|
-
".py": "python",
|
|
32
|
-
".rs": "rust",
|
|
33
|
-
".go": "go",
|
|
34
|
-
".java": "java",
|
|
35
|
-
".cs": "csharp",
|
|
36
|
-
".cpp": "cpp",
|
|
37
|
-
".cc": "cpp",
|
|
38
|
-
".h": "c",
|
|
39
|
-
".hpp": "cpp",
|
|
40
|
-
};
|
|
41
|
-
const SUPPORTED_EXTENSIONS = new Set(Object.keys(EXT_TO_LANG));
|
|
23
|
+
import { detectLanguageFromPath, SUPPORTED_EXTENSIONS } from "../ext-to-lang.js";
|
|
42
24
|
function detectLanguage(filePath) {
|
|
43
|
-
|
|
44
|
-
if (base.endsWith("dockerfile") || base.includes("dockerfile."))
|
|
45
|
-
return "dockerfile";
|
|
46
|
-
return EXT_TO_LANG[extname(base)] || "typescript";
|
|
25
|
+
return detectLanguageFromPath(filePath) ?? "typescript";
|
|
47
26
|
}
|
|
48
27
|
// ─── File Collection ────────────────────────────────────────────────────────
|
|
49
28
|
function collectFiles(dir, maxFiles = 200) {
|
package/dist/commands/fix.js
CHANGED
|
@@ -10,36 +10,12 @@
|
|
|
10
10
|
* judges fix src/app.ts --judge cyber # Fixes from one judge only
|
|
11
11
|
*/
|
|
12
12
|
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
13
|
-
import { resolve
|
|
13
|
+
import { resolve } from "path";
|
|
14
14
|
import { evaluateWithTribunal, evaluateWithJudge } from "../evaluators/index.js";
|
|
15
15
|
import { getJudge } from "../judges/index.js";
|
|
16
|
-
|
|
17
|
-
const EXT_TO_LANG = {
|
|
18
|
-
".ts": "typescript",
|
|
19
|
-
".tsx": "typescript",
|
|
20
|
-
".js": "javascript",
|
|
21
|
-
".jsx": "javascript",
|
|
22
|
-
".mjs": "javascript",
|
|
23
|
-
".cjs": "javascript",
|
|
24
|
-
".py": "python",
|
|
25
|
-
".rs": "rust",
|
|
26
|
-
".go": "go",
|
|
27
|
-
".java": "java",
|
|
28
|
-
".cs": "csharp",
|
|
29
|
-
".cpp": "cpp",
|
|
30
|
-
".cc": "cpp",
|
|
31
|
-
".cxx": "cpp",
|
|
32
|
-
".h": "c",
|
|
33
|
-
".hpp": "cpp",
|
|
34
|
-
".ps1": "powershell",
|
|
35
|
-
".psm1": "powershell",
|
|
36
|
-
};
|
|
16
|
+
import { detectLanguageFromPath } from "../ext-to-lang.js";
|
|
37
17
|
function detectLanguage(filePath) {
|
|
38
|
-
|
|
39
|
-
if (base.endsWith("dockerfile") || base.includes("dockerfile."))
|
|
40
|
-
return "dockerfile";
|
|
41
|
-
const ext = extname(base);
|
|
42
|
-
return EXT_TO_LANG[ext] || "typescript";
|
|
18
|
+
return detectLanguageFromPath(filePath) ?? "typescript";
|
|
43
19
|
}
|
|
44
20
|
const SEVERITY_RANK = {
|
|
45
21
|
critical: 5,
|
|
@@ -82,6 +82,13 @@ export interface LlmCaseResult {
|
|
|
82
82
|
* Matches patterns like CYBER-001, SEC-003, AUTH-001, etc.
|
|
83
83
|
*/
|
|
84
84
|
export declare function getValidRulePrefixes(): Set<string>;
|
|
85
|
+
/**
|
|
86
|
+
* Valid prefixes for tribunal mode — excludes meta-judges that are not
|
|
87
|
+
* included in the tribunal prompt (INTENT, COH, MFPR, FPR, OVER).
|
|
88
|
+
* Findings with these prefixes are hallucinated by the LLM and should
|
|
89
|
+
* not be scored.
|
|
90
|
+
*/
|
|
91
|
+
export declare function getTribunalValidPrefixes(): Set<string>;
|
|
85
92
|
export declare function parseLlmRuleIds(response: string): string[];
|
|
86
93
|
/**
|
|
87
94
|
* Preferred entrypoint: extract findings from raw LLM text with validation. Falls back to regex rule-id scan.
|
|
@@ -30,6 +30,15 @@ export const TRIBUNAL_JUDGES = JUDGES.filter((j) => !TRIBUNAL_EXCLUDED_PREFIXES.
|
|
|
30
30
|
export function getValidRulePrefixes() {
|
|
31
31
|
return new Set(JUDGES.map((j) => j.rulePrefix));
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Valid prefixes for tribunal mode — excludes meta-judges that are not
|
|
35
|
+
* included in the tribunal prompt (INTENT, COH, MFPR, FPR, OVER).
|
|
36
|
+
* Findings with these prefixes are hallucinated by the LLM and should
|
|
37
|
+
* not be scored.
|
|
38
|
+
*/
|
|
39
|
+
export function getTribunalValidPrefixes() {
|
|
40
|
+
return new Set(TRIBUNAL_JUDGES.map((j) => j.rulePrefix));
|
|
41
|
+
}
|
|
33
42
|
export function parseLlmRuleIds(response) {
|
|
34
43
|
const validPrefixes = getValidRulePrefixes();
|
|
35
44
|
const pattern = /\b([A-Z]{2,})-(\d{3})\b/g;
|
|
@@ -174,6 +183,14 @@ export function selectStratifiedSample(cases, targetSize) {
|
|
|
174
183
|
* Returns a fully populated LlmCaseResult.
|
|
175
184
|
*/
|
|
176
185
|
export function scoreLlmCase(tc, detectedRuleIds, rawResponse, tokensUsed) {
|
|
186
|
+
// ── Prefix-level FP deduplication ─────────────────────────────────────
|
|
187
|
+
// TPs are counted per-expected-rule using prefix matching: a single
|
|
188
|
+
// detected CYBER-xxx satisfies all expected CYBER-yyy rules.
|
|
189
|
+
// FPs should use symmetric counting: each erroneously-firing judge prefix
|
|
190
|
+
// counts as ONE false positive regardless of how many rule IDs the LLM
|
|
191
|
+
// generates for that prefix. This prevents verbose LLM output from
|
|
192
|
+
// inflating the FP metric (e.g. CYBER-001…005 on clean code = 1 FP,
|
|
193
|
+
// not 5).
|
|
177
194
|
const detectedPrefixes = new Set(detectedRuleIds.map((r) => r.split("-")[0]));
|
|
178
195
|
const matchedExpected = tc.expectedRuleIds.filter((expected) => {
|
|
179
196
|
const prefix = expected.split("-")[0];
|
|
@@ -189,7 +206,7 @@ export function scoreLlmCase(tc, detectedRuleIds, rawResponse, tokensUsed) {
|
|
|
189
206
|
// doesn't match any expected prefix (prevents silent over-reporting).
|
|
190
207
|
const isCleanCase = tc.expectedRuleIds.length === 0;
|
|
191
208
|
const expectedPrefixes = new Set(tc.expectedRuleIds.map((r) => r.split("-")[0]));
|
|
192
|
-
const
|
|
209
|
+
const falsePositiveIdsRaw = isCleanCase
|
|
193
210
|
? detectedRuleIds
|
|
194
211
|
: tc.unexpectedRuleIds
|
|
195
212
|
? detectedRuleIds.filter((found) => {
|
|
@@ -200,6 +217,15 @@ export function scoreLlmCase(tc, detectedRuleIds, rawResponse, tokensUsed) {
|
|
|
200
217
|
const prefix = found.split("-")[0];
|
|
201
218
|
return !expectedPrefixes.has(prefix);
|
|
202
219
|
});
|
|
220
|
+
// Deduplicate FPs by prefix — keep one representative rule ID per prefix
|
|
221
|
+
const fpPrefixSeen = new Set();
|
|
222
|
+
const falsePositiveIds = falsePositiveIdsRaw.filter((id) => {
|
|
223
|
+
const prefix = id.split("-")[0];
|
|
224
|
+
if (fpPrefixSeen.has(prefix))
|
|
225
|
+
return false;
|
|
226
|
+
fpPrefixSeen.add(prefix);
|
|
227
|
+
return true;
|
|
228
|
+
});
|
|
203
229
|
const casePassed = isCleanCase ? falsePositiveIds.length === 0 : matchedExpected.length > 0;
|
|
204
230
|
return {
|
|
205
231
|
caseId: tc.id,
|
|
@@ -159,18 +159,7 @@ export function parseQualityGateConfig(obj) {
|
|
|
159
159
|
return Object.keys(gates).length > 0 ? gates : undefined;
|
|
160
160
|
}
|
|
161
161
|
// ─── CLI Runner ─────────────────────────────────────────────────────────────
|
|
162
|
-
|
|
163
|
-
".ts": "typescript",
|
|
164
|
-
".tsx": "typescript",
|
|
165
|
-
".js": "javascript",
|
|
166
|
-
".jsx": "javascript",
|
|
167
|
-
".py": "python",
|
|
168
|
-
".rs": "rust",
|
|
169
|
-
".go": "go",
|
|
170
|
-
".java": "java",
|
|
171
|
-
".cs": "csharp",
|
|
172
|
-
".cpp": "cpp",
|
|
173
|
-
};
|
|
162
|
+
import { EXT_TO_LANG } from "../ext-to-lang.js";
|
|
174
163
|
export function runQualityGate(argv) {
|
|
175
164
|
if (argv.includes("--help") || argv.includes("-h")) {
|
|
176
165
|
console.log(`
|
|
@@ -4,25 +4,7 @@
|
|
|
4
4
|
import { readFileSync, existsSync, readdirSync } from "fs";
|
|
5
5
|
import { join, extname } from "path";
|
|
6
6
|
// ─── Language Detection ─────────────────────────────────────────────────────
|
|
7
|
-
|
|
8
|
-
".ts": "typescript",
|
|
9
|
-
".tsx": "typescript",
|
|
10
|
-
".js": "javascript",
|
|
11
|
-
".jsx": "javascript",
|
|
12
|
-
".py": "python",
|
|
13
|
-
".java": "java",
|
|
14
|
-
".cs": "csharp",
|
|
15
|
-
".go": "go",
|
|
16
|
-
".rs": "rust",
|
|
17
|
-
".rb": "ruby",
|
|
18
|
-
".php": "php",
|
|
19
|
-
".cpp": "cpp",
|
|
20
|
-
".c": "c",
|
|
21
|
-
".swift": "swift",
|
|
22
|
-
".kt": "kotlin",
|
|
23
|
-
".scala": "scala",
|
|
24
|
-
};
|
|
25
|
-
const SOURCE_EXTS = new Set(Object.keys(EXT_TO_LANG));
|
|
7
|
+
import { SUPPORTED_EXTENSIONS as SOURCE_EXTS, EXT_TO_LANG } from "../ext-to-lang.js";
|
|
26
8
|
// ─── File Discovery ─────────────────────────────────────────────────────────
|
|
27
9
|
function discoverFiles(dir, maxFiles) {
|
|
28
10
|
const files = [];
|
package/dist/commands/review.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import { execFileSync } from "child_process";
|
|
17
17
|
import { readFileSync, writeFileSync, unlinkSync } from "fs";
|
|
18
18
|
import { tmpdir } from "os";
|
|
19
|
-
import { resolve, join
|
|
19
|
+
import { resolve, join } from "path";
|
|
20
20
|
import { createHash } from "node:crypto";
|
|
21
21
|
import { evaluateDiff, evaluateWithTribunal } from "../evaluators/index.js";
|
|
22
22
|
import { evaluateProject } from "../evaluators/project.js";
|
|
@@ -63,38 +63,7 @@ function hashBody(body) {
|
|
|
63
63
|
return createHash("sha1").update(body).digest("hex").slice(0, 8);
|
|
64
64
|
}
|
|
65
65
|
// ─── Language Detection ─────────────────────────────────────────────────────
|
|
66
|
-
|
|
67
|
-
".ts": "typescript",
|
|
68
|
-
".tsx": "typescript",
|
|
69
|
-
".js": "javascript",
|
|
70
|
-
".jsx": "javascript",
|
|
71
|
-
".mjs": "javascript",
|
|
72
|
-
".cjs": "javascript",
|
|
73
|
-
".py": "python",
|
|
74
|
-
".rs": "rust",
|
|
75
|
-
".go": "go",
|
|
76
|
-
".java": "java",
|
|
77
|
-
".cs": "csharp",
|
|
78
|
-
".rb": "ruby",
|
|
79
|
-
".php": "php",
|
|
80
|
-
".swift": "swift",
|
|
81
|
-
".kt": "kotlin",
|
|
82
|
-
".tf": "terraform",
|
|
83
|
-
".hcl": "terraform",
|
|
84
|
-
".bicep": "bicep",
|
|
85
|
-
".sh": "bash",
|
|
86
|
-
".ps1": "powershell",
|
|
87
|
-
".c": "c",
|
|
88
|
-
".cpp": "cpp",
|
|
89
|
-
".h": "c",
|
|
90
|
-
".hpp": "cpp",
|
|
91
|
-
};
|
|
92
|
-
function detectLanguage(filePath) {
|
|
93
|
-
const ext = extname(filePath.toLowerCase());
|
|
94
|
-
if (filePath.toLowerCase().includes("dockerfile"))
|
|
95
|
-
return "dockerfile";
|
|
96
|
-
return EXT_TO_LANG[ext];
|
|
97
|
-
}
|
|
66
|
+
import { detectLanguageFromPath as detectLanguage } from "../ext-to-lang.js";
|
|
98
67
|
// ─── Severity Helpers ───────────────────────────────────────────────────────
|
|
99
68
|
const SEVERITY_ORDER = ["critical", "high", "medium", "low", "info"];
|
|
100
69
|
function severityRank(s) {
|
|
@@ -34,21 +34,7 @@ function collectFiles(dirPath) {
|
|
|
34
34
|
return results;
|
|
35
35
|
}
|
|
36
36
|
// ─── Language matching ──────────────────────────────────────────────────────
|
|
37
|
-
|
|
38
|
-
".ts": "typescript",
|
|
39
|
-
".tsx": "typescript",
|
|
40
|
-
".js": "javascript",
|
|
41
|
-
".jsx": "javascript",
|
|
42
|
-
".py": "python",
|
|
43
|
-
".go": "go",
|
|
44
|
-
".rs": "rust",
|
|
45
|
-
".java": "java",
|
|
46
|
-
".cs": "csharp",
|
|
47
|
-
".cpp": "cpp",
|
|
48
|
-
".c": "c",
|
|
49
|
-
".rb": "ruby",
|
|
50
|
-
".php": "php",
|
|
51
|
-
};
|
|
37
|
+
import { EXT_TO_LANG } from "../ext-to-lang.js";
|
|
52
38
|
function matchesLanguage(filePath, languages) {
|
|
53
39
|
if (!languages || languages.length === 0)
|
|
54
40
|
return true;
|
package/dist/commands/tune.js
CHANGED
|
@@ -14,37 +14,10 @@
|
|
|
14
14
|
* judges tune --max-files 20 # Limit sample size
|
|
15
15
|
*/
|
|
16
16
|
import { existsSync, readFileSync, readdirSync, statSync, writeFileSync } from "fs";
|
|
17
|
-
import { resolve,
|
|
17
|
+
import { resolve, join } from "path";
|
|
18
18
|
import { evaluateWithTribunal } from "../evaluators/index.js";
|
|
19
19
|
import { PRESETS } from "../presets.js";
|
|
20
|
-
|
|
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
|
-
}
|
|
20
|
+
import { detectLanguageFromPath as detectLanguage } from "../ext-to-lang.js";
|
|
48
21
|
// ─── Framework Detection ────────────────────────────────────────────────────
|
|
49
22
|
function detectFramework(dir) {
|
|
50
23
|
const signals = [];
|
package/dist/commands/watch.js
CHANGED
|
@@ -11,50 +11,11 @@ import { existsSync, readFileSync, statSync, watch as fsWatch } from "fs";
|
|
|
11
11
|
import { resolve, extname, join, relative } from "path";
|
|
12
12
|
import { evaluateWithTribunal, evaluateWithJudge } from "../evaluators/index.js";
|
|
13
13
|
import { getJudge } from "../judges/index.js";
|
|
14
|
+
import { detectLanguageFromPath, SUPPORTED_EXTENSIONS } from "../ext-to-lang.js";
|
|
14
15
|
// ─── Language Detection ─────────────────────────────────────────────────────
|
|
15
|
-
const WATCH_EXTENSIONS =
|
|
16
|
-
".ts",
|
|
17
|
-
".tsx",
|
|
18
|
-
".js",
|
|
19
|
-
".jsx",
|
|
20
|
-
".mjs",
|
|
21
|
-
".cjs",
|
|
22
|
-
".py",
|
|
23
|
-
".rs",
|
|
24
|
-
".go",
|
|
25
|
-
".java",
|
|
26
|
-
".cs",
|
|
27
|
-
".cpp",
|
|
28
|
-
".cc",
|
|
29
|
-
".cxx",
|
|
30
|
-
".h",
|
|
31
|
-
".hpp",
|
|
32
|
-
".ps1",
|
|
33
|
-
".psm1",
|
|
34
|
-
]);
|
|
35
|
-
const EXT_TO_LANG = {
|
|
36
|
-
".ts": "typescript",
|
|
37
|
-
".tsx": "typescript",
|
|
38
|
-
".js": "javascript",
|
|
39
|
-
".jsx": "javascript",
|
|
40
|
-
".mjs": "javascript",
|
|
41
|
-
".cjs": "javascript",
|
|
42
|
-
".py": "python",
|
|
43
|
-
".rs": "rust",
|
|
44
|
-
".go": "go",
|
|
45
|
-
".java": "java",
|
|
46
|
-
".cs": "csharp",
|
|
47
|
-
".cpp": "cpp",
|
|
48
|
-
".cc": "cpp",
|
|
49
|
-
".cxx": "cpp",
|
|
50
|
-
".h": "c",
|
|
51
|
-
".hpp": "cpp",
|
|
52
|
-
".ps1": "powershell",
|
|
53
|
-
".psm1": "powershell",
|
|
54
|
-
};
|
|
16
|
+
const WATCH_EXTENSIONS = SUPPORTED_EXTENSIONS;
|
|
55
17
|
function detectLanguage(filePath) {
|
|
56
|
-
|
|
57
|
-
return EXT_TO_LANG[ext] || "typescript";
|
|
18
|
+
return detectLanguageFromPath(filePath) ?? "typescript";
|
|
58
19
|
}
|
|
59
20
|
export function parseWatchArgs(argv) {
|
|
60
21
|
const args = {
|
package/dist/config.js
CHANGED
|
@@ -12,7 +12,7 @@ import { matchGlobPath } from "./tools/command-safety.js";
|
|
|
12
12
|
export function expandEnvPlaceholders(content) {
|
|
13
13
|
if (!content)
|
|
14
14
|
return content;
|
|
15
|
-
return content.replace(/\$\{([^}]
|
|
15
|
+
return content.replace(/\$\{([^}]{1,100})\}/g, (_match, varName) => {
|
|
16
16
|
const envVal = process.env[varName];
|
|
17
17
|
return envVal !== undefined ? envVal : "";
|
|
18
18
|
});
|