@kevinrabun/judges 3.59.0 → 3.61.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/CHANGELOG.md +19 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +112 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/adoption-track.d.ts +5 -0
- package/dist/commands/adoption-track.d.ts.map +1 -0
- package/dist/commands/adoption-track.js +247 -0
- package/dist/commands/adoption-track.js.map +1 -0
- package/dist/commands/ai-provenance.d.ts +5 -0
- package/dist/commands/ai-provenance.d.ts.map +1 -0
- package/dist/commands/ai-provenance.js +248 -0
- package/dist/commands/ai-provenance.js.map +1 -0
- package/dist/commands/blame-review.d.ts +5 -0
- package/dist/commands/blame-review.d.ts.map +1 -0
- package/dist/commands/blame-review.js +270 -0
- package/dist/commands/blame-review.js.map +1 -0
- package/dist/commands/context-blind.d.ts +5 -0
- package/dist/commands/context-blind.d.ts.map +1 -0
- package/dist/commands/context-blind.js +273 -0
- package/dist/commands/context-blind.js.map +1 -0
- package/dist/commands/evidence-chain.d.ts +5 -0
- package/dist/commands/evidence-chain.d.ts.map +1 -0
- package/dist/commands/evidence-chain.js +310 -0
- package/dist/commands/evidence-chain.js.map +1 -0
- package/dist/commands/finding-budget.d.ts +5 -0
- package/dist/commands/finding-budget.d.ts.map +1 -0
- package/dist/commands/finding-budget.js +233 -0
- package/dist/commands/finding-budget.js.map +1 -0
- package/dist/commands/hallucination-detect.d.ts +5 -0
- package/dist/commands/hallucination-detect.d.ts.map +1 -0
- package/dist/commands/hallucination-detect.js +351 -0
- package/dist/commands/hallucination-detect.js.map +1 -0
- package/dist/commands/merge-verdict.d.ts +5 -0
- package/dist/commands/merge-verdict.d.ts.map +1 -0
- package/dist/commands/merge-verdict.js +288 -0
- package/dist/commands/merge-verdict.js.map +1 -0
- package/dist/commands/over-abstraction.d.ts +5 -0
- package/dist/commands/over-abstraction.d.ts.map +1 -0
- package/dist/commands/over-abstraction.js +308 -0
- package/dist/commands/over-abstraction.js.map +1 -0
- package/dist/commands/quick-check.d.ts +5 -0
- package/dist/commands/quick-check.d.ts.map +1 -0
- package/dist/commands/quick-check.js +174 -0
- package/dist/commands/quick-check.js.map +1 -0
- package/dist/commands/review-contract.d.ts +5 -0
- package/dist/commands/review-contract.d.ts.map +1 -0
- package/dist/commands/review-contract.js +200 -0
- package/dist/commands/review-contract.js.map +1 -0
- package/dist/commands/review-digest.d.ts +5 -0
- package/dist/commands/review-digest.d.ts.map +1 -0
- package/dist/commands/review-digest.js +266 -0
- package/dist/commands/review-digest.js.map +1 -0
- package/dist/commands/review-handoff.d.ts +5 -0
- package/dist/commands/review-handoff.d.ts.map +1 -0
- package/dist/commands/review-handoff.js +209 -0
- package/dist/commands/review-handoff.js.map +1 -0
- package/dist/commands/review-receipt.d.ts +5 -0
- package/dist/commands/review-receipt.d.ts.map +1 -0
- package/dist/commands/review-receipt.js +221 -0
- package/dist/commands/review-receipt.js.map +1 -0
- package/dist/commands/security-theater.d.ts +5 -0
- package/dist/commands/security-theater.d.ts.map +1 -0
- package/dist/commands/security-theater.js +279 -0
- package/dist/commands/security-theater.js.map +1 -0
- package/dist/commands/stale-pattern.d.ts +5 -0
- package/dist/commands/stale-pattern.d.ts.map +1 -0
- package/dist/commands/stale-pattern.js +294 -0
- package/dist/commands/stale-pattern.js.map +1 -0
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evidence-chain — traversable reasoning chain showing exactly why each finding was raised.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, readdirSync, statSync } from "fs";
|
|
5
|
+
import { join, extname, relative } from "path";
|
|
6
|
+
// ─── File Collection ────────────────────────────────────────────────────────
|
|
7
|
+
const CODE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".py", ".java", ".go", ".cs"]);
|
|
8
|
+
function collectFiles(dir, max = 300) {
|
|
9
|
+
const files = [];
|
|
10
|
+
function walk(d) {
|
|
11
|
+
if (files.length >= max)
|
|
12
|
+
return;
|
|
13
|
+
let entries;
|
|
14
|
+
try {
|
|
15
|
+
entries = readdirSync(d);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
for (const e of entries) {
|
|
21
|
+
if (files.length >= max)
|
|
22
|
+
return;
|
|
23
|
+
if (e.startsWith(".") || e === "node_modules" || e === "dist" || e === "build")
|
|
24
|
+
continue;
|
|
25
|
+
const full = join(d, e);
|
|
26
|
+
try {
|
|
27
|
+
if (statSync(full).isDirectory())
|
|
28
|
+
walk(full);
|
|
29
|
+
else if (CODE_EXTS.has(extname(full)))
|
|
30
|
+
files.push(full);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
/* skip */
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
walk(dir);
|
|
38
|
+
return files;
|
|
39
|
+
}
|
|
40
|
+
const KNOWN_PATTERNS = [
|
|
41
|
+
{
|
|
42
|
+
id: "EC-INJECT-01",
|
|
43
|
+
regex: /\beval\s*\(/,
|
|
44
|
+
title: "eval() code injection",
|
|
45
|
+
severity: "critical",
|
|
46
|
+
chain: [
|
|
47
|
+
{ action: "Pattern match", detail: "Regex /\\beval\\s*\\(/ matched source line", result: "eval() call detected" },
|
|
48
|
+
{
|
|
49
|
+
action: "Context analysis",
|
|
50
|
+
detail: "Checked if input is user-controlled or static",
|
|
51
|
+
result: "Input source may be dynamic",
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
action: "Scope check",
|
|
55
|
+
detail: "Verified eval is in application code, not test/build",
|
|
56
|
+
result: "Found in application scope",
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
action: "Vulnerability classification",
|
|
60
|
+
detail: "CWE-94 (Code Injection), OWASP A03:2021",
|
|
61
|
+
result: "Critical — arbitrary code execution",
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: "EC-SECRET-01",
|
|
67
|
+
regex: /(?:password|secret|api[_-]?key)\s*[:=]\s*['"][^'"]{4,}['"]/,
|
|
68
|
+
title: "Hardcoded credential",
|
|
69
|
+
severity: "critical",
|
|
70
|
+
chain: [
|
|
71
|
+
{
|
|
72
|
+
action: "Pattern match",
|
|
73
|
+
detail: "Credential-like assignment detected",
|
|
74
|
+
result: "Value assigned to sensitive-named variable",
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
action: "Value analysis",
|
|
78
|
+
detail: "Checked if value is placeholder (test, example, TODO)",
|
|
79
|
+
result: "Value appears to be a real credential",
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
action: "Scope check",
|
|
83
|
+
detail: "Verified location is not test fixture or example file",
|
|
84
|
+
result: "Found in application code",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
action: "Vulnerability classification",
|
|
88
|
+
detail: "CWE-798 (Hardcoded Credentials), OWASP A07:2021",
|
|
89
|
+
result: "Critical — credential exposure in source",
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
id: "EC-XSS-01",
|
|
95
|
+
regex: /\.innerHTML\s*=/,
|
|
96
|
+
title: "XSS via innerHTML",
|
|
97
|
+
severity: "high",
|
|
98
|
+
chain: [
|
|
99
|
+
{
|
|
100
|
+
action: "Pattern match",
|
|
101
|
+
detail: "innerHTML assignment detected",
|
|
102
|
+
result: "DOM manipulation without sanitization",
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
action: "Input trace",
|
|
106
|
+
detail: "Checked if assigned value originates from user input",
|
|
107
|
+
result: "Input source requires manual verification",
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
action: "Sanitization check",
|
|
111
|
+
detail: "Searched for DOMPurify, sanitize-html, or encoding calls",
|
|
112
|
+
result: "No sanitization found in scope",
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
action: "Vulnerability classification",
|
|
116
|
+
detail: "CWE-79 (Cross-site Scripting), OWASP A03:2021",
|
|
117
|
+
result: "High — potential stored/reflected XSS",
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: "EC-SQLI-01",
|
|
123
|
+
regex: /(?:query|execute)\s*\([^)]*\+\s*(?:req|input|user|param)/,
|
|
124
|
+
title: "SQL injection via concatenation",
|
|
125
|
+
severity: "critical",
|
|
126
|
+
chain: [
|
|
127
|
+
{
|
|
128
|
+
action: "Pattern match",
|
|
129
|
+
detail: "String concatenation in SQL query detected",
|
|
130
|
+
result: "User input concatenated into query string",
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
action: "Parameterization check",
|
|
134
|
+
detail: "Looked for prepared statements or parameterized queries",
|
|
135
|
+
result: "No parameterization found",
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
action: "Input validation check",
|
|
139
|
+
detail: "Searched for input sanitization before query",
|
|
140
|
+
result: "No validation at call site",
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
action: "Vulnerability classification",
|
|
144
|
+
detail: "CWE-89 (SQL Injection), OWASP A03:2021",
|
|
145
|
+
result: "Critical — full database compromise possible",
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
id: "EC-ERR-01",
|
|
151
|
+
regex: /catch\s*\(\s*\w*\s*\)\s*\{\s*\}/,
|
|
152
|
+
title: "Empty catch block",
|
|
153
|
+
severity: "medium",
|
|
154
|
+
chain: [
|
|
155
|
+
{
|
|
156
|
+
action: "Pattern match",
|
|
157
|
+
detail: "Empty catch block detected via regex",
|
|
158
|
+
result: "Exception caught and silently discarded",
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
action: "Context analysis",
|
|
162
|
+
detail: "Checked surrounding code for error handling",
|
|
163
|
+
result: "No logging, rethrow, or fallback in catch",
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
action: "Impact assessment",
|
|
167
|
+
detail: "Silent error swallowing can mask bugs and security issues",
|
|
168
|
+
result: "Medium — errors hidden from monitoring",
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
id: "EC-DEPR-01",
|
|
174
|
+
regex: /new\s+Buffer\s*\(/,
|
|
175
|
+
title: "Deprecated new Buffer()",
|
|
176
|
+
severity: "high",
|
|
177
|
+
chain: [
|
|
178
|
+
{ action: "Pattern match", detail: "new Buffer() constructor detected", result: "Deprecated API usage found" },
|
|
179
|
+
{
|
|
180
|
+
action: "Security analysis",
|
|
181
|
+
detail: "new Buffer(n) may expose uninitialized memory",
|
|
182
|
+
result: "Potential information leak",
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
action: "Modern alternative",
|
|
186
|
+
detail: "Buffer.from(), Buffer.alloc(), Buffer.allocUnsafe()",
|
|
187
|
+
result: "High — use safe Buffer APIs",
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
},
|
|
191
|
+
];
|
|
192
|
+
// ─── Analysis ───────────────────────────────────────────────────────────────
|
|
193
|
+
function analyzeFile(filepath, baseDir) {
|
|
194
|
+
const results = [];
|
|
195
|
+
let content;
|
|
196
|
+
try {
|
|
197
|
+
content = readFileSync(filepath, "utf-8");
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
return results;
|
|
201
|
+
}
|
|
202
|
+
const lines = content.split("\n");
|
|
203
|
+
const rel = relative(baseDir, filepath);
|
|
204
|
+
for (let i = 0; i < lines.length; i++) {
|
|
205
|
+
const line = lines[i];
|
|
206
|
+
const trimmed = line.trim();
|
|
207
|
+
if (trimmed.startsWith("//") || trimmed.startsWith("*") || trimmed.startsWith("/*"))
|
|
208
|
+
continue;
|
|
209
|
+
for (const pattern of KNOWN_PATTERNS) {
|
|
210
|
+
if (pattern.regex.test(line)) {
|
|
211
|
+
// Count similar patterns across file
|
|
212
|
+
let similarCount = 0;
|
|
213
|
+
for (let j = 0; j < lines.length; j++) {
|
|
214
|
+
if (j !== i && pattern.regex.test(lines[j]))
|
|
215
|
+
similarCount++;
|
|
216
|
+
}
|
|
217
|
+
const contextStart = Math.max(0, i - 2);
|
|
218
|
+
const contextEnd = Math.min(lines.length, i + 3);
|
|
219
|
+
const codeContext = lines.slice(contextStart, contextEnd).join("\n");
|
|
220
|
+
const chain = pattern.chain.map((c, idx) => ({
|
|
221
|
+
step: idx + 1,
|
|
222
|
+
action: c.action,
|
|
223
|
+
detail: c.detail,
|
|
224
|
+
result: c.result,
|
|
225
|
+
}));
|
|
226
|
+
results.push({
|
|
227
|
+
findingId: `${pattern.id}@${rel}:${i + 1}`,
|
|
228
|
+
file: rel,
|
|
229
|
+
line: i + 1,
|
|
230
|
+
title: pattern.title,
|
|
231
|
+
severity: pattern.severity,
|
|
232
|
+
chain,
|
|
233
|
+
codeContext,
|
|
234
|
+
similarPatterns: similarCount,
|
|
235
|
+
confidenceScore: Math.min(95, 70 + chain.length * 5 + (similarCount > 0 ? 5 : 0)),
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return results;
|
|
241
|
+
}
|
|
242
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
243
|
+
export function runEvidenceChain(argv) {
|
|
244
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
245
|
+
console.log(`
|
|
246
|
+
judges evidence-chain — Traversable reasoning chain for findings
|
|
247
|
+
|
|
248
|
+
Usage:
|
|
249
|
+
judges evidence-chain [dir]
|
|
250
|
+
judges evidence-chain src/ --format json
|
|
251
|
+
judges evidence-chain src/ --finding EC-INJECT-01
|
|
252
|
+
|
|
253
|
+
Options:
|
|
254
|
+
[dir] Directory to scan (default: .)
|
|
255
|
+
--finding <id> Filter to specific finding ID
|
|
256
|
+
--format json JSON output
|
|
257
|
+
--help, -h Show this help
|
|
258
|
+
|
|
259
|
+
For any finding, produces: pattern matched → context analyzed →
|
|
260
|
+
confidence calibrated → CWE/OWASP classification → final reasoning.
|
|
261
|
+
`);
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
265
|
+
const findingFilter = argv.find((_a, i) => argv[i - 1] === "--finding");
|
|
266
|
+
const dir = argv.find((a) => !a.startsWith("-") &&
|
|
267
|
+
argv.indexOf(a) > 0 &&
|
|
268
|
+
argv[argv.indexOf(a) - 1] !== "--format" &&
|
|
269
|
+
argv[argv.indexOf(a) - 1] !== "--finding") || ".";
|
|
270
|
+
const files = collectFiles(dir);
|
|
271
|
+
let allResults = [];
|
|
272
|
+
for (const f of files)
|
|
273
|
+
allResults.push(...analyzeFile(f, dir));
|
|
274
|
+
if (findingFilter) {
|
|
275
|
+
allResults = allResults.filter((r) => r.findingId.includes(findingFilter));
|
|
276
|
+
}
|
|
277
|
+
if (format === "json") {
|
|
278
|
+
console.log(JSON.stringify({ results: allResults, count: allResults.length, timestamp: new Date().toISOString() }, null, 2));
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
console.log(`\n Evidence Chain: ${allResults.length} finding(s)\n ─────────────────────────────`);
|
|
282
|
+
if (allResults.length === 0) {
|
|
283
|
+
console.log(" No findings to trace.\n");
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
for (const result of allResults.slice(0, 10)) {
|
|
287
|
+
const icon = result.severity === "critical"
|
|
288
|
+
? "🔴"
|
|
289
|
+
: result.severity === "high"
|
|
290
|
+
? "🟠"
|
|
291
|
+
: result.severity === "medium"
|
|
292
|
+
? "🟡"
|
|
293
|
+
: "🔵";
|
|
294
|
+
console.log(`\n ${icon} ${result.title} [${result.findingId}]`);
|
|
295
|
+
console.log(` ${result.file}:${result.line} (confidence: ${result.confidenceScore}%)`);
|
|
296
|
+
console.log(` Reasoning chain:`);
|
|
297
|
+
for (const step of result.chain) {
|
|
298
|
+
console.log(` ${step.step}. ${step.action}: ${step.detail}`);
|
|
299
|
+
console.log(` → ${step.result}`);
|
|
300
|
+
}
|
|
301
|
+
if (result.similarPatterns > 0) {
|
|
302
|
+
console.log(` ℹ️ ${result.similarPatterns} similar pattern(s) found in same file`);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
if (allResults.length > 10)
|
|
306
|
+
console.log(`\n ... and ${allResults.length - 10} more findings`);
|
|
307
|
+
console.log();
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
//# sourceMappingURL=evidence-chain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence-chain.js","sourceRoot":"","sources":["../../src/commands/evidence-chain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finding-budget.d.ts","sourceRoot":"","sources":["../../src/commands/finding-budget.ts"],"names":[],"mappings":"AAAA;;GAEG;AAsMH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAuFrD"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finding-budget — manage finding volume per PR to prevent alert fatigue.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, readdirSync, statSync } from "fs";
|
|
5
|
+
import { join, extname, relative } from "path";
|
|
6
|
+
// ─── File Collection ────────────────────────────────────────────────────────
|
|
7
|
+
const CODE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".py", ".java", ".go", ".cs"]);
|
|
8
|
+
function collectFiles(dir, max = 300) {
|
|
9
|
+
const files = [];
|
|
10
|
+
function walk(d) {
|
|
11
|
+
if (files.length >= max)
|
|
12
|
+
return;
|
|
13
|
+
let entries;
|
|
14
|
+
try {
|
|
15
|
+
entries = readdirSync(d);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
for (const e of entries) {
|
|
21
|
+
if (files.length >= max)
|
|
22
|
+
return;
|
|
23
|
+
if (e.startsWith(".") || e === "node_modules" || e === "dist" || e === "build")
|
|
24
|
+
continue;
|
|
25
|
+
const full = join(d, e);
|
|
26
|
+
try {
|
|
27
|
+
if (statSync(full).isDirectory())
|
|
28
|
+
walk(full);
|
|
29
|
+
else if (CODE_EXTS.has(extname(full)))
|
|
30
|
+
files.push(full);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
/* skip */
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
walk(dir);
|
|
38
|
+
return files;
|
|
39
|
+
}
|
|
40
|
+
const SCAN_PATTERNS = [
|
|
41
|
+
{ regex: /eval\s*\(/, category: "Security", title: "eval() usage", severity: "critical", group: "injection" },
|
|
42
|
+
{
|
|
43
|
+
regex: /(?:password|secret|api[_-]?key)\s*[:=]\s*['"][^'"]+['"]/,
|
|
44
|
+
category: "Security",
|
|
45
|
+
title: "Hardcoded credential",
|
|
46
|
+
severity: "critical",
|
|
47
|
+
group: "secrets",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
regex: /\.innerHTML\s*=/,
|
|
51
|
+
category: "Security",
|
|
52
|
+
title: "innerHTML assignment",
|
|
53
|
+
severity: "high",
|
|
54
|
+
group: "injection",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
regex: /new\s+Buffer\s*\(/,
|
|
58
|
+
category: "Security",
|
|
59
|
+
title: "Deprecated Buffer()",
|
|
60
|
+
severity: "high",
|
|
61
|
+
group: "deprecated-api",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
regex: /catch\s*\(\s*\w*\s*\)\s*\{\s*\}/,
|
|
65
|
+
category: "Reliability",
|
|
66
|
+
title: "Empty catch block",
|
|
67
|
+
severity: "medium",
|
|
68
|
+
group: "error-handling",
|
|
69
|
+
},
|
|
70
|
+
{ regex: /console\.\w+\s*\(/, category: "Quality", title: "Console statement", severity: "low", group: "logging" },
|
|
71
|
+
{ regex: /TODO|FIXME|HACK/, category: "Debt", title: "Open TODO/FIXME", severity: "low", group: "tech-debt" },
|
|
72
|
+
{
|
|
73
|
+
regex: /process\.exit\s*\(/,
|
|
74
|
+
category: "Reliability",
|
|
75
|
+
title: "process.exit()",
|
|
76
|
+
severity: "medium",
|
|
77
|
+
group: "error-handling",
|
|
78
|
+
},
|
|
79
|
+
{ regex: /debugger\b/, category: "Quality", title: "Debugger statement", severity: "medium", group: "development" },
|
|
80
|
+
{
|
|
81
|
+
regex: /(?:setTimeout|setInterval)\s*\(\s*['"]/,
|
|
82
|
+
category: "Security",
|
|
83
|
+
title: "String timer (implicit eval)",
|
|
84
|
+
severity: "high",
|
|
85
|
+
group: "injection",
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
regex: /url\.parse\s*\(/,
|
|
89
|
+
category: "Quality",
|
|
90
|
+
title: "Deprecated url.parse()",
|
|
91
|
+
severity: "medium",
|
|
92
|
+
group: "deprecated-api",
|
|
93
|
+
},
|
|
94
|
+
{ regex: /var\s+\w+\s*=/, category: "Quality", title: "var declaration", severity: "low", group: "modernization" },
|
|
95
|
+
];
|
|
96
|
+
// ─── Analysis ───────────────────────────────────────────────────────────────
|
|
97
|
+
function scanFile(filepath, baseDir) {
|
|
98
|
+
const findings = [];
|
|
99
|
+
let content;
|
|
100
|
+
try {
|
|
101
|
+
content = readFileSync(filepath, "utf-8");
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return findings;
|
|
105
|
+
}
|
|
106
|
+
const lines = content.split("\n");
|
|
107
|
+
const rel = relative(baseDir, filepath);
|
|
108
|
+
for (let i = 0; i < lines.length; i++) {
|
|
109
|
+
const line = lines[i];
|
|
110
|
+
const trimmed = line.trim();
|
|
111
|
+
if (trimmed.startsWith("//") || trimmed.startsWith("*") || trimmed.startsWith("/*"))
|
|
112
|
+
continue;
|
|
113
|
+
for (const pattern of SCAN_PATTERNS) {
|
|
114
|
+
if (pattern.regex.test(line)) {
|
|
115
|
+
findings.push({
|
|
116
|
+
file: rel,
|
|
117
|
+
line: i + 1,
|
|
118
|
+
severity: pattern.severity,
|
|
119
|
+
category: pattern.category,
|
|
120
|
+
title: pattern.title,
|
|
121
|
+
group: pattern.group,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return findings;
|
|
127
|
+
}
|
|
128
|
+
function applyBudget(allFindings, budget) {
|
|
129
|
+
// Sort by severity: critical > high > medium > low
|
|
130
|
+
const severityOrder = { critical: 0, high: 1, medium: 2, low: 3 };
|
|
131
|
+
const sorted = [...allFindings].sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity]);
|
|
132
|
+
// Group related findings
|
|
133
|
+
const groupMap = new Map();
|
|
134
|
+
for (const f of sorted)
|
|
135
|
+
groupMap.set(f.group, (groupMap.get(f.group) || 0) + 1);
|
|
136
|
+
const groups = [...groupMap.entries()].sort((a, b) => b[1] - a[1]).map(([group, count]) => ({ group, count }));
|
|
137
|
+
// Select top findings within budget
|
|
138
|
+
const shown = sorted.slice(0, budget);
|
|
139
|
+
const deferred = Math.max(0, sorted.length - budget);
|
|
140
|
+
// Compute file count for density
|
|
141
|
+
const uniqueFiles = new Set(allFindings.map((f) => f.file));
|
|
142
|
+
const densityPerFile = uniqueFiles.size > 0 ? Math.round((allFindings.length / uniqueFiles.size) * 10) / 10 : 0;
|
|
143
|
+
// Risk tier
|
|
144
|
+
const critCount = allFindings.filter((f) => f.severity === "critical").length;
|
|
145
|
+
const highCount = allFindings.filter((f) => f.severity === "high").length;
|
|
146
|
+
const riskTier = critCount > 0 ? "critical" : highCount > 3 ? "high" : allFindings.length > budget ? "medium" : "low";
|
|
147
|
+
return {
|
|
148
|
+
total: allFindings.length,
|
|
149
|
+
budget,
|
|
150
|
+
overBudget: allFindings.length > budget,
|
|
151
|
+
shown,
|
|
152
|
+
deferred,
|
|
153
|
+
groups,
|
|
154
|
+
densityPerFile,
|
|
155
|
+
riskTier,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
159
|
+
export function runFindingBudget(argv) {
|
|
160
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
161
|
+
console.log(`
|
|
162
|
+
judges finding-budget — Manage finding volume to prevent alert fatigue
|
|
163
|
+
|
|
164
|
+
Usage:
|
|
165
|
+
judges finding-budget [dir]
|
|
166
|
+
judges finding-budget src/ --max 15
|
|
167
|
+
judges finding-budget src/ --format json
|
|
168
|
+
|
|
169
|
+
Options:
|
|
170
|
+
[dir] Directory to scan (default: .)
|
|
171
|
+
--max <n> Maximum findings to show (default: 20)
|
|
172
|
+
--format json JSON output
|
|
173
|
+
--help, -h Show this help
|
|
174
|
+
|
|
175
|
+
Features: risk-based prioritization, graduated disclosure, related-finding
|
|
176
|
+
grouping, density metrics, "start here" view showing most impactful items
|
|
177
|
+
within the budget.
|
|
178
|
+
|
|
179
|
+
Note: All analysis is local — no data is sent or stored externally.
|
|
180
|
+
`);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
184
|
+
const maxStr = argv.find((_a, i) => argv[i - 1] === "--max");
|
|
185
|
+
const budget = maxStr ? parseInt(maxStr, 10) : 20;
|
|
186
|
+
const dir = argv.find((a) => !a.startsWith("-") &&
|
|
187
|
+
argv.indexOf(a) > 0 &&
|
|
188
|
+
argv[argv.indexOf(a) - 1] !== "--format" &&
|
|
189
|
+
argv[argv.indexOf(a) - 1] !== "--max") || ".";
|
|
190
|
+
const files = collectFiles(dir);
|
|
191
|
+
const allFindings = [];
|
|
192
|
+
for (const f of files)
|
|
193
|
+
allFindings.push(...scanFile(f, dir));
|
|
194
|
+
const result = applyBudget(allFindings, budget);
|
|
195
|
+
if (format === "json") {
|
|
196
|
+
console.log(JSON.stringify({ result, timestamp: new Date().toISOString() }, null, 2));
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
const tierIcon = result.riskTier === "critical"
|
|
200
|
+
? "🔴"
|
|
201
|
+
: result.riskTier === "high"
|
|
202
|
+
? "🟠"
|
|
203
|
+
: result.riskTier === "medium"
|
|
204
|
+
? "🟡"
|
|
205
|
+
: "🟢";
|
|
206
|
+
console.log(`\n Finding Budget: ${tierIcon} ${result.riskTier.toUpperCase()} RISK\n ─────────────────────────────`);
|
|
207
|
+
console.log(` Total findings: ${result.total}`);
|
|
208
|
+
console.log(` Budget: ${result.budget}`);
|
|
209
|
+
console.log(` Showing: ${result.shown.length}`);
|
|
210
|
+
if (result.deferred > 0)
|
|
211
|
+
console.log(` Deferred: ${result.deferred} (fix shown items first)`);
|
|
212
|
+
console.log(` Density: ${result.densityPerFile} findings/file`);
|
|
213
|
+
if (result.shown.length > 0) {
|
|
214
|
+
console.log(`\n Start Here:`);
|
|
215
|
+
for (const f of result.shown) {
|
|
216
|
+
const icon = f.severity === "critical" ? "🔴" : f.severity === "high" ? "🟠" : f.severity === "medium" ? "🟡" : "🔵";
|
|
217
|
+
console.log(` ${icon} [${f.category}] ${f.title}`);
|
|
218
|
+
console.log(` ${f.file}:${f.line}`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (result.groups.length > 0) {
|
|
222
|
+
console.log(`\n Finding Groups:`);
|
|
223
|
+
for (const g of result.groups) {
|
|
224
|
+
console.log(` ${g.group}: ${g.count} finding(s)`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
if (result.overBudget) {
|
|
228
|
+
console.log(`\n ⚡ ${result.deferred} findings deferred — fix the ${result.shown.length} shown items first, then re-run to see more.`);
|
|
229
|
+
}
|
|
230
|
+
console.log();
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=finding-budget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finding-budget.js","sourceRoot":"","sources":["../../src/commands/finding-budget.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAwB/C,+EAA+E;AAE/E,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;AAExF,SAAS,YAAY,CAAC,GAAW,EAAE,GAAG,GAAG,GAAG;IAC1C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,SAAS,IAAI,CAAC,CAAS;QACrB,IAAI,KAAK,CAAC,MAAM,IAAI,GAAG;YAAE,OAAO;QAChC,IAAI,OAAiB,CAAC;QACtB,IAAI,CAAC;YACH,OAAO,GAAG,WAAW,CAAC,CAAC,CAAwB,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;QACT,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,IAAI,KAAK,CAAC,MAAM,IAAI,GAAG;gBAAE,OAAO;YAChC,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,cAAc,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,OAAO;gBAAE,SAAS;YACzF,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACxB,IAAI,CAAC;gBACH,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE;oBAAE,IAAI,CAAC,IAAI,CAAC,CAAC;qBACxC,IAAI,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;oBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1D,CAAC;YAAC,MAAM,CAAC;gBACP,UAAU;YACZ,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,KAAK,CAAC;AACf,CAAC;AAYD,MAAM,aAAa,GAAc;IAC/B,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE;IAC7G;QACE,KAAK,EAAE,yDAAyD;QAChE,QAAQ,EAAE,UAAU;QACpB,KAAK,EAAE,sBAAsB;QAC7B,QAAQ,EAAE,UAAU;QACpB,KAAK,EAAE,SAAS;KACjB;IACD;QACE,KAAK,EAAE,iBAAiB;QACxB,QAAQ,EAAE,UAAU;QACpB,KAAK,EAAE,sBAAsB;QAC7B,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,WAAW;KACnB;IACD;QACE,KAAK,EAAE,mBAAmB;QAC1B,QAAQ,EAAE,UAAU;QACpB,KAAK,EAAE,qBAAqB;QAC5B,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,gBAAgB;KACxB;IACD;QACE,KAAK,EAAE,iCAAiC;QACxC,QAAQ,EAAE,aAAa;QACvB,KAAK,EAAE,mBAAmB;QAC1B,QAAQ,EAAE,QAAQ;QAClB,KAAK,EAAE,gBAAgB;KACxB;IACD,EAAE,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE;IAClH,EAAE,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE;IAC7G;QACE,KAAK,EAAE,oBAAoB;QAC3B,QAAQ,EAAE,aAAa;QACvB,KAAK,EAAE,gBAAgB;QACvB,QAAQ,EAAE,QAAQ;QAClB,KAAK,EAAE,gBAAgB;KACxB;IACD,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,oBAAoB,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,aAAa,EAAE;IACnH;QACE,KAAK,EAAE,wCAAwC;QAC/C,QAAQ,EAAE,UAAU;QACpB,KAAK,EAAE,8BAA8B;QACrC,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,WAAW;KACnB;IACD;QACE,KAAK,EAAE,iBAAiB;QACxB,QAAQ,EAAE,SAAS;QACnB,KAAK,EAAE,wBAAwB;QAC/B,QAAQ,EAAE,QAAQ;QAClB,KAAK,EAAE,gBAAgB;KACxB;IACD,EAAE,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE;CACnH,CAAC;AAEF,+EAA+E;AAE/E,SAAS,QAAQ,CAAC,QAAgB,EAAE,OAAe;IACjD,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAExC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,SAAS;QAE9F,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE,CAAC;YACpC,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC7B,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,GAAG;oBACT,IAAI,EAAE,CAAC,GAAG,CAAC;oBACX,QAAQ,EAAE,OAAO,CAAC,QAAQ;oBAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;oBAC1B,KAAK,EAAE,OAAO,CAAC,KAAK;oBACpB,KAAK,EAAE,OAAO,CAAC,KAAK;iBACrB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,WAAW,CAAC,WAA4B,EAAE,MAAc;IAC/D,mDAAmD;IACnD,MAAM,aAAa,GAA2B,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IAC1F,MAAM,MAAM,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEtG,yBAAyB;IACzB,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC3C,KAAK,MAAM,CAAC,IAAI,MAAM;QAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAChF,MAAM,MAAM,GAAG,CAAC,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAE/G,oCAAoC;IACpC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAErD,iCAAiC;IACjC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5D,MAAM,cAAc,GAAG,WAAW,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAEhH,YAAY;IACZ,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,MAAM,CAAC;IAC9E,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,MAAM,CAAC;IAC1E,MAAM,QAAQ,GACZ,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;IAEvG,OAAO;QACL,KAAK,EAAE,WAAW,CAAC,MAAM;QACzB,MAAM;QACN,UAAU,EAAE,WAAW,CAAC,MAAM,GAAG,MAAM;QACvC,KAAK;QACL,QAAQ;QACR,MAAM;QACN,cAAc;QACd,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,+EAA+E;AAE/E,MAAM,UAAU,gBAAgB,CAAC,IAAc;IAC7C,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;CAmBf,CAAC,CAAC;QACC,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,UAAU,CAAC,IAAI,MAAM,CAAC;IAC1F,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC;IAC7E,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAClD,MAAM,GAAG,GACP,IAAI,CAAC,IAAI,CACP,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC;QAClB,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;QACnB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,UAAU;QACxC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,OAAO,CACxC,IAAI,GAAG,CAAC;IAEX,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,WAAW,GAAoB,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,WAAW,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAE7D,MAAM,MAAM,GAAG,WAAW,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAEhD,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACxF,CAAC;SAAM,CAAC;QACN,MAAM,QAAQ,GACZ,MAAM,CAAC,QAAQ,KAAK,UAAU;YAC5B,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,MAAM,CAAC,QAAQ,KAAK,MAAM;gBAC1B,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,MAAM,CAAC,QAAQ,KAAK,QAAQ;oBAC5B,CAAC,CAAC,IAAI;oBACN,CAAC,CAAC,IAAI,CAAC;QACf,OAAO,CAAC,GAAG,CACT,uBAAuB,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,wCAAwC,CACzG,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,wBAAwB,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,wBAAwB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,wBAAwB,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QAC3D,IAAI,MAAM,CAAC,QAAQ,GAAG,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,wBAAwB,MAAM,CAAC,QAAQ,0BAA0B,CAAC,CAAC;QACxG,OAAO,CAAC,GAAG,CAAC,wBAAwB,MAAM,CAAC,cAAc,gBAAgB,CAAC,CAAC;QAE3E,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;YACjC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBAC7B,MAAM,IAAI,GACR,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC1G,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,KAAK,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;gBACxD,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;YACrC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAC9B,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,aAAa,CAAC,CAAC;YACzD,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CACT,WAAW,MAAM,CAAC,QAAQ,gCAAgC,MAAM,CAAC,KAAK,CAAC,MAAM,8CAA8C,CAC5H,CAAC;QACJ,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hallucination-detect.d.ts","sourceRoot":"","sources":["../../src/commands/hallucination-detect.ts"],"names":[],"mappings":"AAAA;;GAEG;AA+TH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA6D3D"}
|