@kevinrabun/judges 3.50.0 → 3.52.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.
Files changed (70) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +112 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/ai-gate.d.ts +8 -0
  6. package/dist/commands/ai-gate.d.ts.map +1 -0
  7. package/dist/commands/ai-gate.js +213 -0
  8. package/dist/commands/ai-gate.js.map +1 -0
  9. package/dist/commands/ai-output-compare.d.ts +9 -0
  10. package/dist/commands/ai-output-compare.d.ts.map +1 -0
  11. package/dist/commands/ai-output-compare.js +203 -0
  12. package/dist/commands/ai-output-compare.js.map +1 -0
  13. package/dist/commands/ai-pattern-trend.d.ts +9 -0
  14. package/dist/commands/ai-pattern-trend.d.ts.map +1 -0
  15. package/dist/commands/ai-pattern-trend.js +224 -0
  16. package/dist/commands/ai-pattern-trend.js.map +1 -0
  17. package/dist/commands/arch-audit.d.ts +9 -0
  18. package/dist/commands/arch-audit.d.ts.map +1 -0
  19. package/dist/commands/arch-audit.js +284 -0
  20. package/dist/commands/arch-audit.js.map +1 -0
  21. package/dist/commands/chat-notify.d.ts +9 -0
  22. package/dist/commands/chat-notify.d.ts.map +1 -0
  23. package/dist/commands/chat-notify.js +259 -0
  24. package/dist/commands/chat-notify.js.map +1 -0
  25. package/dist/commands/clarity-score.d.ts +9 -0
  26. package/dist/commands/clarity-score.d.ts.map +1 -0
  27. package/dist/commands/clarity-score.js +261 -0
  28. package/dist/commands/clarity-score.js.map +1 -0
  29. package/dist/commands/design-audit.d.ts +9 -0
  30. package/dist/commands/design-audit.d.ts.map +1 -0
  31. package/dist/commands/design-audit.js +302 -0
  32. package/dist/commands/design-audit.js.map +1 -0
  33. package/dist/commands/hallucination-score.d.ts +9 -0
  34. package/dist/commands/hallucination-score.d.ts.map +1 -0
  35. package/dist/commands/hallucination-score.js +317 -0
  36. package/dist/commands/hallucination-score.js.map +1 -0
  37. package/dist/commands/impact-scan.d.ts +9 -0
  38. package/dist/commands/impact-scan.d.ts.map +1 -0
  39. package/dist/commands/impact-scan.js +282 -0
  40. package/dist/commands/impact-scan.js.map +1 -0
  41. package/dist/commands/judge-learn.d.ts +9 -0
  42. package/dist/commands/judge-learn.d.ts.map +1 -0
  43. package/dist/commands/judge-learn.js +218 -0
  44. package/dist/commands/judge-learn.js.map +1 -0
  45. package/dist/commands/model-report.d.ts +9 -0
  46. package/dist/commands/model-report.d.ts.map +1 -0
  47. package/dist/commands/model-report.js +195 -0
  48. package/dist/commands/model-report.js.map +1 -0
  49. package/dist/commands/remediation-lib.d.ts +9 -0
  50. package/dist/commands/remediation-lib.d.ts.map +1 -0
  51. package/dist/commands/remediation-lib.js +266 -0
  52. package/dist/commands/remediation-lib.js.map +1 -0
  53. package/dist/commands/test-suggest.d.ts +9 -0
  54. package/dist/commands/test-suggest.d.ts.map +1 -0
  55. package/dist/commands/test-suggest.js +248 -0
  56. package/dist/commands/test-suggest.js.map +1 -0
  57. package/dist/commands/trust-adaptive.d.ts +9 -0
  58. package/dist/commands/trust-adaptive.d.ts.map +1 -0
  59. package/dist/commands/trust-adaptive.js +194 -0
  60. package/dist/commands/trust-adaptive.js.map +1 -0
  61. package/dist/commands/vendor-lock-detect.d.ts +8 -0
  62. package/dist/commands/vendor-lock-detect.d.ts.map +1 -0
  63. package/dist/commands/vendor-lock-detect.js +289 -0
  64. package/dist/commands/vendor-lock-detect.js.map +1 -0
  65. package/dist/commands/watch-judge.d.ts +8 -0
  66. package/dist/commands/watch-judge.d.ts.map +1 -0
  67. package/dist/commands/watch-judge.js +180 -0
  68. package/dist/commands/watch-judge.js.map +1 -0
  69. package/package.json +1 -1
  70. package/server.json +2 -2
@@ -0,0 +1,302 @@
1
+ /**
2
+ * Design audit — detect AI-generated code that breaks project
3
+ * conventions, introduces unnecessary abstractions, or creates
4
+ * architectural deviation from the baseline.
5
+ *
6
+ * All analysis local.
7
+ */
8
+ import { existsSync, readFileSync, readdirSync } from "fs";
9
+ import { join, extname, relative } from "path";
10
+ // ─── Analysers ──────────────────────────────────────────────────────────────
11
+ function analyzeDesignCoherence(content, _filePath, baselinePatterns) {
12
+ const lines = content.split("\n");
13
+ const metrics = [];
14
+ const issues = [];
15
+ // 1. Convention adherence — does file follow project patterns?
16
+ const usesProjectImportStyle = baselinePatterns.importStyle === "named" ? /import\s*{/.test(content) : /import\s+\w+\s+from/.test(content);
17
+ const conventionScore = usesProjectImportStyle ? 80 : 40;
18
+ metrics.push({ id: "convention", label: "Convention Adherence", score: conventionScore, weight: 20 });
19
+ if (conventionScore < 60)
20
+ issues.push({
21
+ id: "import-style",
22
+ label: "Import Style Deviation",
23
+ severity: "low",
24
+ detail: "Import style differs from project convention",
25
+ });
26
+ // 2. Unnecessary abstraction
27
+ const classCount = (content.match(/\bclass\s+\w+/g) || []).length;
28
+ const interfaceCount = (content.match(/\binterface\s+\w+/g) || []).length;
29
+ const abstractCount = (content.match(/\babstract\s+class/g) || []).length;
30
+ const singleMethodClasses = (content.match(/class\s+\w+[\s\S]*?{[\s\S]*?(\w+\s*\([\s\S]*?\)[\s\S]*?{[\s\S]*?})[\s\S]*?}/g) || []).length;
31
+ const overAbstraction = abstractCount > 1 || (classCount > 0 && singleMethodClasses === classCount);
32
+ const abstractionScore = overAbstraction ? 30 : classCount + interfaceCount > 8 ? 50 : 100;
33
+ metrics.push({
34
+ id: "abstraction",
35
+ label: "Abstraction Level",
36
+ score: abstractionScore,
37
+ weight: 20,
38
+ detail: `${classCount} classes, ${interfaceCount} interfaces, ${abstractCount} abstract`,
39
+ });
40
+ if (overAbstraction) {
41
+ issues.push({
42
+ id: "over-abstraction",
43
+ label: "Over-Abstraction",
44
+ severity: "medium",
45
+ detail: "Excessive abstraction layers — AI often creates unnecessary wrappers",
46
+ });
47
+ }
48
+ // 3. Orphaned dependencies
49
+ const imports = content.match(/import\s+(?:{[^}]+}|\w+)\s+from\s+["']([^"']+)["']/g) || [];
50
+ const unusedImportCount = imports.filter((imp) => {
51
+ const names = imp
52
+ .match(/import\s+{([^}]+)}/)?.[1]
53
+ ?.split(",")
54
+ .map((s) => s
55
+ .trim()
56
+ .split(/\s+as\s+/)
57
+ .pop()
58
+ ?.trim()) || [];
59
+ const defaultName = imp.match(/import\s+(\w+)\s+from/)?.[1];
60
+ const allNames = [...names, defaultName].filter(Boolean);
61
+ const afterImport = content.slice(content.indexOf(imp) + imp.length);
62
+ return allNames.some((n) => !new RegExp(`\\b${n}\\b`).test(afterImport));
63
+ }).length;
64
+ const orphanScore = unusedImportCount === 0 ? 100 : unusedImportCount <= 2 ? 60 : 30;
65
+ metrics.push({
66
+ id: "orphaned-deps",
67
+ label: "Dependency Hygiene",
68
+ score: orphanScore,
69
+ weight: 15,
70
+ detail: `${unusedImportCount} potentially unused imports`,
71
+ });
72
+ if (unusedImportCount > 0) {
73
+ issues.push({
74
+ id: "unused-imports",
75
+ label: "Orphaned Imports",
76
+ severity: "low",
77
+ detail: `${unusedImportCount} import(s) may be unused — common AI-generation artifact`,
78
+ });
79
+ }
80
+ // 4. Pattern consistency
81
+ const usesCallbacks = /\bcallback\b|\.then\(|function\s*\(err/.test(content);
82
+ const usesAsync = /\basync\b.*\bawait\b/s.test(content);
83
+ const usesPromise = /new\s+Promise/.test(content);
84
+ const asyncPatterns = [usesCallbacks, usesAsync, usesPromise].filter(Boolean).length;
85
+ const patternScore = asyncPatterns <= 1 ? 100 : asyncPatterns === 2 ? 60 : 30;
86
+ metrics.push({ id: "pattern-consistency", label: "Pattern Consistency", score: patternScore, weight: 15 });
87
+ if (asyncPatterns > 1) {
88
+ issues.push({
89
+ id: "mixed-async",
90
+ label: "Mixed Async Patterns",
91
+ severity: "medium",
92
+ detail: "Mixes callbacks, async/await, and/or raw Promises — pick one style",
93
+ });
94
+ }
95
+ // 5. Error handling consistency
96
+ const tryCatchCount = (content.match(/\btry\s*{/g) || []).length;
97
+ const catchSuppressCount = (content.match(/catch\s*\([^)]*\)\s*{\s*}/g) || []).length;
98
+ const throwCount = (content.match(/\bthrow\s+/g) || []).length;
99
+ const errorScore = catchSuppressCount === 0 ? 100 : catchSuppressCount <= 1 ? 70 : 30;
100
+ metrics.push({
101
+ id: "error-handling",
102
+ label: "Error Handling",
103
+ score: errorScore,
104
+ weight: 15,
105
+ detail: `${tryCatchCount} try/catch, ${catchSuppressCount} suppressed, ${throwCount} throws`,
106
+ });
107
+ if (catchSuppressCount > 0) {
108
+ issues.push({
109
+ id: "suppressed-errors",
110
+ label: "Suppressed Errors",
111
+ severity: "high",
112
+ detail: `${catchSuppressCount} empty catch block(s) — errors silently swallowed`,
113
+ });
114
+ }
115
+ // 6. Naming coherence
116
+ const camelCase = (content.match(/\b[a-z][a-zA-Z0-9]*[A-Z][a-zA-Z0-9]*/g) || []).length;
117
+ const snakeCase = (content.match(/\b[a-z]+_[a-z]+/g) || []).length;
118
+ const mixedNaming = camelCase > 0 && snakeCase > 0;
119
+ const namingScore = mixedNaming ? (Math.abs(camelCase - snakeCase) > 5 ? 50 : 30) : 100;
120
+ metrics.push({ id: "naming-coherence", label: "Naming Coherence", score: namingScore, weight: 15 });
121
+ if (mixedNaming) {
122
+ issues.push({
123
+ id: "mixed-naming",
124
+ label: "Mixed Naming Convention",
125
+ severity: "low",
126
+ detail: `${camelCase} camelCase + ${snakeCase} snake_case identifiers`,
127
+ });
128
+ }
129
+ void lines;
130
+ return { metrics, issues };
131
+ }
132
+ function detectBaseline(files) {
133
+ let namedCount = 0;
134
+ let defaultCount = 0;
135
+ let totalLength = 0;
136
+ let asyncCount = 0;
137
+ let callbackCount = 0;
138
+ for (const f of files.slice(0, 20)) {
139
+ try {
140
+ const content = readFileSync(f, "utf-8");
141
+ totalLength += content.split("\n").length;
142
+ namedCount += (content.match(/import\s*{/g) || []).length;
143
+ defaultCount += (content.match(/import\s+\w+\s+from/g) || []).length;
144
+ if (/\basync\b/.test(content))
145
+ asyncCount++;
146
+ if (/\.then\(/.test(content))
147
+ callbackCount++;
148
+ }
149
+ catch {
150
+ /* skip */
151
+ }
152
+ }
153
+ return {
154
+ importStyle: namedCount >= defaultCount ? "named" : "default",
155
+ avgFileLength: files.length > 0 ? Math.round(totalLength / Math.min(files.length, 20)) : 0,
156
+ primaryAsyncPattern: asyncCount >= callbackCount ? "async/await" : "callbacks",
157
+ };
158
+ }
159
+ // ─── Scanner ────────────────────────────────────────────────────────────────
160
+ const SKIP = new Set(["node_modules", ".git", "dist", "build", "coverage"]);
161
+ const EXTS = new Set([".ts", ".js", ".py", ".java", ".cs", ".go", ".rb", ".php", ".rs"]);
162
+ function collectFiles(dir) {
163
+ const result = [];
164
+ function walk(d) {
165
+ let entries;
166
+ try {
167
+ entries = readdirSync(d);
168
+ }
169
+ catch {
170
+ return;
171
+ }
172
+ for (const name of entries) {
173
+ if (SKIP.has(name) || name.startsWith("."))
174
+ continue;
175
+ const full = join(d, name);
176
+ try {
177
+ const sub = readdirSync(full);
178
+ void sub;
179
+ walk(full);
180
+ }
181
+ catch {
182
+ if (EXTS.has(extname(name).toLowerCase()))
183
+ result.push(full);
184
+ }
185
+ }
186
+ }
187
+ walk(dir);
188
+ return result;
189
+ }
190
+ function gradeFor(score) {
191
+ if (score >= 90)
192
+ return "A";
193
+ if (score >= 80)
194
+ return "B";
195
+ if (score >= 70)
196
+ return "C";
197
+ if (score >= 60)
198
+ return "D";
199
+ return "F";
200
+ }
201
+ function computeOverall(metrics) {
202
+ const totalWeight = metrics.reduce((s, m) => s + m.weight, 0);
203
+ const weighted = metrics.reduce((s, m) => s + m.score * m.weight, 0);
204
+ return totalWeight > 0 ? Math.round(weighted / totalWeight) : 0;
205
+ }
206
+ // ─── CLI ────────────────────────────────────────────────────────────────────
207
+ export function runDesignAudit(argv) {
208
+ if (argv.includes("--help") || argv.includes("-h")) {
209
+ console.log(`
210
+ judges design-audit — Detect code that breaks project conventions
211
+
212
+ Usage:
213
+ judges design-audit <file-or-dir>
214
+ judges design-audit src/ --min-grade C
215
+
216
+ Options:
217
+ --min-grade <A-F> Only show files at or below this grade
218
+ --format json JSON output
219
+ --help, -h Show this help
220
+
221
+ Checks:
222
+ • Convention adherence (import style, project patterns)
223
+ • Abstraction level (over-engineering, unnecessary wrappers)
224
+ • Dependency hygiene (orphaned/unused imports)
225
+ • Pattern consistency (mixed async styles)
226
+ • Error handling (suppressed errors, empty catch blocks)
227
+ • Naming coherence (mixed camelCase/snake_case)
228
+ `);
229
+ return;
230
+ }
231
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
232
+ const minGrade = argv.find((_a, i) => argv[i - 1] === "--min-grade");
233
+ const target = argv.find((a) => !a.startsWith("--") && !argv[argv.indexOf(a) - 1]?.startsWith("--")) || ".";
234
+ if (!existsSync(target)) {
235
+ console.error(` Path not found: ${target}`);
236
+ return;
237
+ }
238
+ let files;
239
+ try {
240
+ readdirSync(target);
241
+ files = collectFiles(target);
242
+ }
243
+ catch {
244
+ files = [target];
245
+ }
246
+ const baseline = detectBaseline(files);
247
+ const results = [];
248
+ for (const f of files) {
249
+ let content;
250
+ try {
251
+ content = readFileSync(f, "utf-8");
252
+ }
253
+ catch {
254
+ continue;
255
+ }
256
+ const { metrics, issues } = analyzeDesignCoherence(content, f, baseline);
257
+ const overall = computeOverall(metrics);
258
+ results.push({ file: relative(target, f) || f, overallScore: overall, grade: gradeFor(overall), metrics, issues });
259
+ }
260
+ let filtered = results;
261
+ if (minGrade) {
262
+ const gradeOrder = ["A", "B", "C", "D", "F"];
263
+ const minIdx = gradeOrder.indexOf(minGrade.toUpperCase());
264
+ if (minIdx >= 0)
265
+ filtered = results.filter((r) => gradeOrder.indexOf(r.grade) >= minIdx);
266
+ }
267
+ filtered.sort((a, b) => a.overallScore - b.overallScore);
268
+ if (format === "json") {
269
+ console.log(JSON.stringify({ files: filtered, baseline, scannedFiles: files.length, timestamp: new Date().toISOString() }, null, 2));
270
+ }
271
+ else {
272
+ const avgScore = results.length > 0 ? Math.round(results.reduce((s, r) => s + r.overallScore, 0) / results.length) : 0;
273
+ console.log(`\n Design Coherence Audit — ${files.length} files`);
274
+ console.log(` Average: ${avgScore}/100 (${gradeFor(avgScore)})`);
275
+ console.log(` Baseline: ${baseline.importStyle} imports, ${baseline.primaryAsyncPattern}, ~${baseline.avgFileLength} lines/file\n ──────────────────────────`);
276
+ if (filtered.length === 0) {
277
+ console.log(` ✅ All files meet design coherence threshold\n`);
278
+ return;
279
+ }
280
+ for (const r of filtered.slice(0, 20)) {
281
+ const icon = r.grade === "A" || r.grade === "B" ? "🟢" : r.grade === "C" ? "🟡" : r.grade === "D" ? "🟠" : "🔴";
282
+ console.log(`\n ${icon} ${r.file} — ${r.overallScore}/100 (${r.grade})`);
283
+ for (const m of r.metrics) {
284
+ const mIcon = m.score >= 70 ? "✓" : m.score >= 40 ? "~" : "✗";
285
+ console.log(` ${mIcon} ${m.label.padEnd(24)} ${String(m.score).padEnd(4)} ${m.detail || ""}`);
286
+ }
287
+ if (r.issues.length > 0) {
288
+ for (const iss of r.issues) {
289
+ const sev = iss.severity === "high" ? "🔴" : iss.severity === "medium" ? "🟠" : "🟡";
290
+ console.log(` ${sev} ${iss.detail}`);
291
+ }
292
+ }
293
+ }
294
+ if (filtered.length > 20)
295
+ console.log(` ... and ${filtered.length - 20} more files`);
296
+ const dist = { A: 0, B: 0, C: 0, D: 0, F: 0 };
297
+ for (const r of results)
298
+ dist[r.grade]++;
299
+ console.log(`\n Distribution: A:${dist.A} B:${dist.B} C:${dist.C} D:${dist.D} F:${dist.F}\n`);
300
+ }
301
+ }
302
+ //# sourceMappingURL=design-audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"design-audit.js","sourceRoot":"","sources":["../../src/commands/design-audit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Hallucination score — assign a hallucination risk score (0–100)
3
+ * to AI-generated code based on detected patterns: generic naming,
4
+ * suspicious imports, implausible logic, unverified API usage.
5
+ *
6
+ * All analysis local.
7
+ */
8
+ export declare function runHallucinationScore(argv: string[]): void;
9
+ //# sourceMappingURL=hallucination-score.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hallucination-score.d.ts","sourceRoot":"","sources":["../../src/commands/hallucination-score.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA8PH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAmG1D"}
@@ -0,0 +1,317 @@
1
+ /**
2
+ * Hallucination score — assign a hallucination risk score (0–100)
3
+ * to AI-generated code based on detected patterns: generic naming,
4
+ * suspicious imports, implausible logic, unverified API usage.
5
+ *
6
+ * All analysis local.
7
+ */
8
+ import { existsSync, readFileSync, readdirSync } from "fs";
9
+ import { join, extname } from "path";
10
+ // ─── Detectors ──────────────────────────────────────────────────────────────
11
+ function detectHallucinationSignals(content, lines) {
12
+ const signals = [];
13
+ // 1. Non-existent or suspicious imports
14
+ const importLines = lines
15
+ .map((l, i) => ({ line: i + 1, text: l }))
16
+ .filter((l) => /\bimport\s|require\s*\(/.test(l.text));
17
+ for (const imp of importLines) {
18
+ // Suspicious package names (very generic or implausible)
19
+ if (/["'](?:utils|helpers|common|shared|lib|core|base)["']/.test(imp.text) && !/from\s*["']\./.test(imp.text)) {
20
+ signals.push({
21
+ id: "suspicious-import",
22
+ description: "Generic import name — may reference non-existent package",
23
+ weight: 15,
24
+ line: imp.line,
25
+ evidence: imp.text.trim(),
26
+ });
27
+ }
28
+ // Version-specific imports (hallucinated API paths)
29
+ if (/["'][^"']+\/v\d+\/[^"']+["']/.test(imp.text)) {
30
+ signals.push({
31
+ id: "versioned-import-path",
32
+ description: "Version-specific import path — verify API exists",
33
+ weight: 10,
34
+ line: imp.line,
35
+ evidence: imp.text.trim(),
36
+ });
37
+ }
38
+ }
39
+ // 2. Generic/placeholder variable names
40
+ let genericNames = 0;
41
+ for (let i = 0; i < lines.length; i++) {
42
+ if (/\b(?:const|let|var)\s+(?:data|result|value|item|thing|stuff|temp|tmp|foo|bar|baz|x|y|z)\s*[=:]/.test(lines[i])) {
43
+ genericNames++;
44
+ }
45
+ }
46
+ if (genericNames > 3) {
47
+ signals.push({
48
+ id: "generic-naming",
49
+ description: `${genericNames} generic variable names — AI may have generated placeholder code`,
50
+ weight: 10,
51
+ });
52
+ }
53
+ // 3. TODO/FIXME comments left by AI
54
+ let todoCount = 0;
55
+ for (let i = 0; i < lines.length; i++) {
56
+ if (/\/\/\s*(?:TODO|FIXME|HACK|XXX|PLACEHOLDER)/i.test(lines[i])) {
57
+ todoCount++;
58
+ }
59
+ }
60
+ if (todoCount > 2) {
61
+ signals.push({
62
+ id: "excessive-todos",
63
+ description: `${todoCount} TODO/FIXME comments — AI left implementation gaps`,
64
+ weight: 20,
65
+ });
66
+ }
67
+ // 4. Unreachable or dead code patterns
68
+ for (let i = 0; i < lines.length; i++) {
69
+ if (/\breturn\b/.test(lines[i]) &&
70
+ i + 1 < lines.length &&
71
+ /^\s*\S/.test(lines[i + 1]) &&
72
+ !/^\s*[}\])]/.test(lines[i + 1]) &&
73
+ !/^\s*(?:case|default|\/\/|\/?\*)/.test(lines[i + 1])) {
74
+ signals.push({
75
+ id: "dead-code",
76
+ description: "Code after return statement — likely hallucinated",
77
+ weight: 15,
78
+ line: i + 2,
79
+ evidence: lines[i + 1].trim().substring(0, 60),
80
+ });
81
+ }
82
+ }
83
+ // 5. Contradictory logic
84
+ for (let i = 0; i < lines.length; i++) {
85
+ if (/if\s*\(\s*true\s*\)|if\s*\(\s*false\s*\)/.test(lines[i])) {
86
+ signals.push({
87
+ id: "tautology",
88
+ description: "Tautological condition (always true/false)",
89
+ weight: 20,
90
+ line: i + 1,
91
+ });
92
+ }
93
+ if (/=\s*null.*\.\w+|=\s*undefined.*\.\w+/.test(lines[i])) {
94
+ signals.push({
95
+ id: "null-access",
96
+ description: "Property access on value just assigned null/undefined",
97
+ weight: 25,
98
+ line: i + 1,
99
+ });
100
+ }
101
+ }
102
+ // 6. Copy-paste artifacts
103
+ const lineSet = new Map();
104
+ for (let i = 0; i < lines.length; i++) {
105
+ const trimmed = lines[i].trim();
106
+ if (trimmed.length > 20) {
107
+ if (!lineSet.has(trimmed))
108
+ lineSet.set(trimmed, []);
109
+ lineSet.get(trimmed).push(i + 1);
110
+ }
111
+ }
112
+ let duplicateBlocks = 0;
113
+ for (const [, lineNums] of lineSet) {
114
+ if (lineNums.length >= 3)
115
+ duplicateBlocks++;
116
+ }
117
+ if (duplicateBlocks > 2) {
118
+ signals.push({
119
+ id: "copy-paste-artifact",
120
+ description: `${duplicateBlocks} repeated code blocks — AI may have duplicated patterns`,
121
+ weight: 15,
122
+ });
123
+ }
124
+ // 7. Magic numbers/strings
125
+ let magicCount = 0;
126
+ for (let i = 0; i < lines.length; i++) {
127
+ if (/\b(?:0x[0-9a-f]{4,}|\d{5,})\b/i.test(lines[i]) && !/\bconst\b/.test(lines[i]) && !/\/\//.test(lines[i])) {
128
+ magicCount++;
129
+ }
130
+ }
131
+ if (magicCount > 3) {
132
+ signals.push({
133
+ id: "magic-numbers",
134
+ description: `${magicCount} unexplained magic numbers — AI may have hallucinated constants`,
135
+ weight: 10,
136
+ });
137
+ }
138
+ // 8. Inconsistent error handling
139
+ const tryCatchCount = (content.match(/\btry\s*{/g) || []).length;
140
+ const catchCount = (content.match(/\bcatch\s*\(/g) || []).length;
141
+ const emptyHandlers = (content.match(/catch\s*\([^)]*\)\s*{\s*}/g) || []).length;
142
+ if (emptyHandlers > 0) {
143
+ signals.push({
144
+ id: "empty-catch",
145
+ description: `${emptyHandlers} empty catch block(s) — errors silently swallowed`,
146
+ weight: 15,
147
+ });
148
+ }
149
+ if (tryCatchCount > 0 && catchCount < tryCatchCount) {
150
+ signals.push({
151
+ id: "unmatched-try",
152
+ description: "More try blocks than catch blocks — incomplete error handling",
153
+ weight: 10,
154
+ });
155
+ }
156
+ // 9. Commented-out code (AI artifact)
157
+ let commentedCode = 0;
158
+ for (let i = 0; i < lines.length; i++) {
159
+ if (/^\s*\/\/\s*(?:const|let|var|function|class|import|return|if|for|while)\b/.test(lines[i])) {
160
+ commentedCode++;
161
+ }
162
+ }
163
+ if (commentedCode > 3) {
164
+ signals.push({
165
+ id: "commented-code",
166
+ description: `${commentedCode} lines of commented-out code — AI left alternative implementations`,
167
+ weight: 10,
168
+ });
169
+ }
170
+ // 10. Functions with no implementation
171
+ for (let i = 0; i < lines.length; i++) {
172
+ if (/\bfunction\s+\w+\s*\([^)]*\)\s*{\s*}/.test(lines[i]) || /=>\s*{\s*}/.test(lines[i])) {
173
+ signals.push({
174
+ id: "empty-function",
175
+ description: "Empty function body — stub not implemented",
176
+ weight: 20,
177
+ line: i + 1,
178
+ });
179
+ }
180
+ }
181
+ return signals;
182
+ }
183
+ // ─── Scanner ────────────────────────────────────────────────────────────────
184
+ const SKIP = new Set(["node_modules", ".git", "dist", "build", "coverage"]);
185
+ const EXTS = new Set([".ts", ".js", ".py", ".java", ".cs", ".go", ".rb", ".php", ".rs", ".swift", ".kt"]);
186
+ function collectFiles(dir) {
187
+ const result = [];
188
+ function walk(d) {
189
+ let entries;
190
+ try {
191
+ entries = readdirSync(d);
192
+ }
193
+ catch {
194
+ return;
195
+ }
196
+ for (const name of entries) {
197
+ if (SKIP.has(name) || name.startsWith("."))
198
+ continue;
199
+ const full = join(d, name);
200
+ try {
201
+ const sub = readdirSync(full);
202
+ void sub;
203
+ walk(full);
204
+ }
205
+ catch {
206
+ if (EXTS.has(extname(name).toLowerCase()))
207
+ result.push(full);
208
+ }
209
+ }
210
+ }
211
+ walk(dir);
212
+ return result;
213
+ }
214
+ function computeScore(signals) {
215
+ const raw = signals.reduce((sum, s) => sum + s.weight, 0);
216
+ return Math.min(100, raw);
217
+ }
218
+ function riskLevel(score) {
219
+ if (score >= 70)
220
+ return "critical";
221
+ if (score >= 45)
222
+ return "high";
223
+ if (score >= 20)
224
+ return "medium";
225
+ return "low";
226
+ }
227
+ // ─── CLI ────────────────────────────────────────────────────────────────────
228
+ export function runHallucinationScore(argv) {
229
+ if (argv.includes("--help") || argv.includes("-h")) {
230
+ console.log(`
231
+ judges hallucination-score — Assess hallucination risk in AI-generated code
232
+
233
+ Usage:
234
+ judges hallucination-score <file-or-dir>
235
+ judges hallucination-score src/ --min-risk medium
236
+
237
+ Options:
238
+ --min-risk <level> Only show files at or above this risk (low, medium, high, critical)
239
+ --format json JSON output
240
+ --help, -h Show this help
241
+
242
+ Signals detected:
243
+ • Suspicious/non-existent imports
244
+ • Generic placeholder naming
245
+ • Excessive TODO/FIXME comments
246
+ • Dead code after return statements
247
+ • Tautological conditions
248
+ • Copy-paste artifacts
249
+ • Magic numbers
250
+ • Empty catch blocks
251
+ • Commented-out code
252
+ • Empty function stubs
253
+ `);
254
+ return;
255
+ }
256
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
257
+ const minRisk = argv.find((_a, i) => argv[i - 1] === "--min-risk");
258
+ const target = argv.find((a) => !a.startsWith("--") && !argv[argv.indexOf(a) - 1]?.startsWith("--")) || ".";
259
+ if (!existsSync(target)) {
260
+ console.error(` Path not found: ${target}`);
261
+ return;
262
+ }
263
+ let files;
264
+ try {
265
+ readdirSync(target);
266
+ files = collectFiles(target);
267
+ }
268
+ catch {
269
+ files = [target];
270
+ }
271
+ const scored = [];
272
+ for (const f of files) {
273
+ let content;
274
+ try {
275
+ content = readFileSync(f, "utf-8");
276
+ }
277
+ catch {
278
+ continue;
279
+ }
280
+ const lines = content.split("\n");
281
+ const signals = detectHallucinationSignals(content, lines);
282
+ const score = computeScore(signals);
283
+ scored.push({ file: f, score, riskLevel: riskLevel(score), signals });
284
+ }
285
+ let filtered = scored;
286
+ if (minRisk) {
287
+ const order = ["low", "medium", "high", "critical"];
288
+ const minIdx = order.indexOf(minRisk);
289
+ if (minIdx >= 0)
290
+ filtered = scored.filter((s) => order.indexOf(s.riskLevel) >= minIdx);
291
+ }
292
+ filtered.sort((a, b) => b.score - a.score);
293
+ if (format === "json") {
294
+ console.log(JSON.stringify({ files: filtered, scannedFiles: files.length, timestamp: new Date().toISOString() }, null, 2));
295
+ }
296
+ else {
297
+ console.log(`\n Hallucination Risk Assessment — ${files.length} files`);
298
+ console.log(` ──────────────────────────`);
299
+ if (filtered.length === 0) {
300
+ console.log(` ✅ No hallucination risks above threshold\n`);
301
+ return;
302
+ }
303
+ for (const f of filtered.slice(0, 20)) {
304
+ const icon = f.riskLevel === "critical" ? "🔴" : f.riskLevel === "high" ? "🟠" : f.riskLevel === "medium" ? "🟡" : "🟢";
305
+ console.log(`\n ${icon} ${f.file} — Score: ${f.score}/100 (${f.riskLevel})`);
306
+ for (const s of f.signals) {
307
+ console.log(` • ${s.description}${s.line ? ` (line ${s.line})` : ""}`);
308
+ }
309
+ }
310
+ if (filtered.length > 20)
311
+ console.log(` ... and ${filtered.length - 20} more files`);
312
+ const avgScore = Math.round(filtered.reduce((sum, f) => sum + f.score, 0) / filtered.length);
313
+ console.log(`\n Average risk score: ${avgScore}/100`);
314
+ console.log(` Critical: ${filtered.filter((f) => f.riskLevel === "critical").length} | High: ${filtered.filter((f) => f.riskLevel === "high").length} | Medium: ${filtered.filter((f) => f.riskLevel === "medium").length} | Low: ${filtered.filter((f) => f.riskLevel === "low").length}\n`);
315
+ }
316
+ }
317
+ //# sourceMappingURL=hallucination-score.js.map