@kevinrabun/judges 3.52.0 → 3.54.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 +24 -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/approve-chain.d.ts +8 -0
- package/dist/commands/approve-chain.d.ts.map +1 -0
- package/dist/commands/approve-chain.js +235 -0
- package/dist/commands/approve-chain.js.map +1 -0
- package/dist/commands/coach-mode.d.ts +8 -0
- package/dist/commands/coach-mode.d.ts.map +1 -0
- package/dist/commands/coach-mode.js +230 -0
- package/dist/commands/coach-mode.js.map +1 -0
- package/dist/commands/code-similarity.d.ts +9 -0
- package/dist/commands/code-similarity.d.ts.map +1 -0
- package/dist/commands/code-similarity.js +232 -0
- package/dist/commands/code-similarity.js.map +1 -0
- package/dist/commands/compliance-weight.d.ts +9 -0
- package/dist/commands/compliance-weight.d.ts.map +1 -0
- package/dist/commands/compliance-weight.js +273 -0
- package/dist/commands/compliance-weight.js.map +1 -0
- package/dist/commands/context-inject.d.ts +9 -0
- package/dist/commands/context-inject.d.ts.map +1 -0
- package/dist/commands/context-inject.js +212 -0
- package/dist/commands/context-inject.js.map +1 -0
- package/dist/commands/cross-pr-regression.d.ts +9 -0
- package/dist/commands/cross-pr-regression.d.ts.map +1 -0
- package/dist/commands/cross-pr-regression.js +298 -0
- package/dist/commands/cross-pr-regression.js.map +1 -0
- package/dist/commands/doc-drift.d.ts +9 -0
- package/dist/commands/doc-drift.d.ts.map +1 -0
- package/dist/commands/doc-drift.js +259 -0
- package/dist/commands/doc-drift.js.map +1 -0
- package/dist/commands/exception-consistency.d.ts +7 -0
- package/dist/commands/exception-consistency.d.ts.map +1 -0
- package/dist/commands/exception-consistency.js +193 -0
- package/dist/commands/exception-consistency.js.map +1 -0
- package/dist/commands/finding-contest.d.ts +8 -0
- package/dist/commands/finding-contest.d.ts.map +1 -0
- package/dist/commands/finding-contest.js +193 -0
- package/dist/commands/finding-contest.js.map +1 -0
- package/dist/commands/habit-tracker.d.ts +8 -0
- package/dist/commands/habit-tracker.d.ts.map +1 -0
- package/dist/commands/habit-tracker.js +195 -0
- package/dist/commands/habit-tracker.js.map +1 -0
- package/dist/commands/prompt-replay.d.ts +8 -0
- package/dist/commands/prompt-replay.d.ts.map +1 -0
- package/dist/commands/prompt-replay.js +177 -0
- package/dist/commands/prompt-replay.js.map +1 -0
- package/dist/commands/refactor-safety.d.ts +9 -0
- package/dist/commands/refactor-safety.d.ts.map +1 -0
- package/dist/commands/refactor-safety.js +274 -0
- package/dist/commands/refactor-safety.js.map +1 -0
- package/dist/commands/resource-cleanup.d.ts +7 -0
- package/dist/commands/resource-cleanup.d.ts.map +1 -0
- package/dist/commands/resource-cleanup.js +236 -0
- package/dist/commands/resource-cleanup.js.map +1 -0
- package/dist/commands/review-replay.d.ts +9 -0
- package/dist/commands/review-replay.d.ts.map +1 -0
- package/dist/commands/review-replay.js +265 -0
- package/dist/commands/review-replay.js.map +1 -0
- package/dist/commands/snippet-eval.d.ts +8 -0
- package/dist/commands/snippet-eval.d.ts.map +1 -0
- package/dist/commands/snippet-eval.js +224 -0
- package/dist/commands/snippet-eval.js.map +1 -0
- package/dist/commands/team-trust.d.ts +8 -0
- package/dist/commands/team-trust.d.ts.map +1 -0
- package/dist/commands/team-trust.js +175 -0
- package/dist/commands/team-trust.js.map +1 -0
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Doc drift — detect when inline comments, docstrings, and type
|
|
3
|
+
* annotations contradict the actual code behavior. A critical
|
|
4
|
+
* AI-generation problem where docs are written separately.
|
|
5
|
+
*
|
|
6
|
+
* All analysis local.
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync, readFileSync, readdirSync } from "fs";
|
|
9
|
+
import { join, extname, relative } from "path";
|
|
10
|
+
// ─── Analysis ───────────────────────────────────────────────────────────────
|
|
11
|
+
function analyzeDrift(content) {
|
|
12
|
+
const lines = content.split("\n");
|
|
13
|
+
const issues = [];
|
|
14
|
+
for (let i = 0; i < lines.length; i++) {
|
|
15
|
+
const line = lines[i];
|
|
16
|
+
const nextLine = lines[i + 1] || "";
|
|
17
|
+
// 1. JSDoc @param mismatch
|
|
18
|
+
const paramMatch = line.match(/@param\s+(?:{[^}]+}\s+)?(\w+)/);
|
|
19
|
+
if (paramMatch) {
|
|
20
|
+
const paramName = paramMatch[1];
|
|
21
|
+
// Look ahead for function signature
|
|
22
|
+
for (let j = i + 1; j < Math.min(i + 5, lines.length); j++) {
|
|
23
|
+
const fnMatch = lines[j].match(/(?:function\s+\w+|(?:const|let)\s+\w+\s*=\s*(?:async\s*)?\(|^\s*(?:async\s*)?\()\s*([^)]*)\)/);
|
|
24
|
+
if (fnMatch) {
|
|
25
|
+
const params = fnMatch[1];
|
|
26
|
+
if (params && !params.includes(paramName)) {
|
|
27
|
+
issues.push({
|
|
28
|
+
line: i + 1,
|
|
29
|
+
type: "param-mismatch",
|
|
30
|
+
severity: "high",
|
|
31
|
+
detail: `@param "${paramName}" not found in function signature`,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// 2. @returns but function has no return
|
|
39
|
+
if (/@returns?\s/.test(line)) {
|
|
40
|
+
let fnBodyStart = -1;
|
|
41
|
+
for (let j = i + 1; j < Math.min(i + 5, lines.length); j++) {
|
|
42
|
+
if (/{\s*$/.test(lines[j])) {
|
|
43
|
+
fnBodyStart = j;
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (fnBodyStart >= 0) {
|
|
48
|
+
let depth = 0;
|
|
49
|
+
let hasReturn = false;
|
|
50
|
+
for (let j = fnBodyStart; j < lines.length; j++) {
|
|
51
|
+
depth += (lines[j].match(/{/g) || []).length;
|
|
52
|
+
depth -= (lines[j].match(/}/g) || []).length;
|
|
53
|
+
if (/\breturn\s+\S/.test(lines[j]))
|
|
54
|
+
hasReturn = true;
|
|
55
|
+
if (depth <= 0)
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
if (!hasReturn) {
|
|
59
|
+
issues.push({
|
|
60
|
+
line: i + 1,
|
|
61
|
+
type: "return-mismatch",
|
|
62
|
+
severity: "high",
|
|
63
|
+
detail: "@returns documented but function has no return value",
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// 3. Comment references wrong function/variable name
|
|
69
|
+
const commentMatch = line.match(/\/\/\s*(?:calls?|uses?|invokes?|sets?|gets?)\s+(\w+)/i);
|
|
70
|
+
if (commentMatch) {
|
|
71
|
+
const refName = commentMatch[1];
|
|
72
|
+
if (refName.length > 2 &&
|
|
73
|
+
!content.includes(`function ${refName}`) &&
|
|
74
|
+
!content.includes(`const ${refName}`) &&
|
|
75
|
+
!content.includes(`let ${refName}`) &&
|
|
76
|
+
!content.includes(`.${refName}`)) {
|
|
77
|
+
issues.push({
|
|
78
|
+
line: i + 1,
|
|
79
|
+
type: "wrong-name",
|
|
80
|
+
severity: "medium",
|
|
81
|
+
detail: `Comment references "${refName}" which doesn't exist in this file`,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// 4. Comment says "returns X" but next line does something else
|
|
86
|
+
const returnsComment = line.match(/\/\/\s*returns?\s+(true|false|null|undefined|void|nothing|\d+|an?\s+\w+)/i);
|
|
87
|
+
if (returnsComment && /\breturn\b/.test(nextLine)) {
|
|
88
|
+
const claimed = returnsComment[1].toLowerCase();
|
|
89
|
+
if (claimed === "true" && !nextLine.includes("true")) {
|
|
90
|
+
issues.push({
|
|
91
|
+
line: i + 1,
|
|
92
|
+
type: "stale-comment",
|
|
93
|
+
severity: "medium",
|
|
94
|
+
detail: `Comment says "returns true" but return statement differs`,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
else if (claimed === "false" && !nextLine.includes("false")) {
|
|
98
|
+
issues.push({
|
|
99
|
+
line: i + 1,
|
|
100
|
+
type: "stale-comment",
|
|
101
|
+
severity: "medium",
|
|
102
|
+
detail: `Comment says "returns false" but return statement differs`,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
else if (claimed === "null" && !nextLine.includes("null")) {
|
|
106
|
+
issues.push({
|
|
107
|
+
line: i + 1,
|
|
108
|
+
type: "stale-comment",
|
|
109
|
+
severity: "medium",
|
|
110
|
+
detail: `Comment says "returns null" but return statement differs`,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// 5. Dead documentation — comment block before deleted/empty code
|
|
115
|
+
if (/\/\*\*/.test(line) && !line.includes("*/")) {
|
|
116
|
+
let endComment = -1;
|
|
117
|
+
for (let j = i + 1; j < Math.min(i + 20, lines.length); j++) {
|
|
118
|
+
if (/\*\//.test(lines[j])) {
|
|
119
|
+
endComment = j;
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (endComment >= 0) {
|
|
124
|
+
const afterDoc = lines[endComment + 1]?.trim() || "";
|
|
125
|
+
if (afterDoc === "" || afterDoc === "}" || afterDoc === ");") {
|
|
126
|
+
issues.push({
|
|
127
|
+
line: i + 1,
|
|
128
|
+
type: "dead-doc",
|
|
129
|
+
severity: "low",
|
|
130
|
+
detail: "Documentation block with no code following it",
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// 6. TODO in documentation
|
|
136
|
+
if (/\/\*\*[\s\S]*TODO|@todo/i.test(line) || (/^\s*\*/.test(line) && /TODO/i.test(line))) {
|
|
137
|
+
issues.push({
|
|
138
|
+
line: i + 1,
|
|
139
|
+
type: "todo-doc",
|
|
140
|
+
severity: "low",
|
|
141
|
+
detail: "TODO found in documentation — may indicate incomplete AI-generated docs",
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return issues;
|
|
146
|
+
}
|
|
147
|
+
// ─── Scanner ────────────────────────────────────────────────────────────────
|
|
148
|
+
const SKIP = new Set(["node_modules", ".git", "dist", "build", "coverage"]);
|
|
149
|
+
const EXTS = new Set([".ts", ".js", ".py", ".java", ".cs", ".go", ".rb", ".php", ".rs"]);
|
|
150
|
+
function collectFiles(dir) {
|
|
151
|
+
const result = [];
|
|
152
|
+
function walk(d) {
|
|
153
|
+
let entries;
|
|
154
|
+
try {
|
|
155
|
+
entries = readdirSync(d);
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
for (const name of entries) {
|
|
161
|
+
if (SKIP.has(name) || name.startsWith("."))
|
|
162
|
+
continue;
|
|
163
|
+
const full = join(d, name);
|
|
164
|
+
try {
|
|
165
|
+
const sub = readdirSync(full);
|
|
166
|
+
void sub;
|
|
167
|
+
walk(full);
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
if (EXTS.has(extname(name).toLowerCase()))
|
|
171
|
+
result.push(full);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
walk(dir);
|
|
176
|
+
return result;
|
|
177
|
+
}
|
|
178
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
179
|
+
export function runDocDrift(argv) {
|
|
180
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
181
|
+
console.log(`
|
|
182
|
+
judges doc-drift — Detect documentation-to-code drift
|
|
183
|
+
|
|
184
|
+
Usage:
|
|
185
|
+
judges doc-drift <file-or-dir>
|
|
186
|
+
judges doc-drift src/ --min-issues 1
|
|
187
|
+
|
|
188
|
+
Options:
|
|
189
|
+
--min-issues <n> Only show files with at least N issues (default: 1)
|
|
190
|
+
--format json JSON output
|
|
191
|
+
--help, -h Show this help
|
|
192
|
+
|
|
193
|
+
Checks:
|
|
194
|
+
• @param name mismatches with function signature
|
|
195
|
+
• @returns documented but no return statement
|
|
196
|
+
• Comments referencing nonexistent identifiers
|
|
197
|
+
• Stale return value comments
|
|
198
|
+
• Dead documentation blocks
|
|
199
|
+
• TODO in documentation
|
|
200
|
+
`);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
204
|
+
const minIssues = parseInt(argv.find((_a, i) => argv[i - 1] === "--min-issues") || "1");
|
|
205
|
+
const target = argv.find((a) => !a.startsWith("--") && !argv[argv.indexOf(a) - 1]?.startsWith("--")) || ".";
|
|
206
|
+
if (!existsSync(target)) {
|
|
207
|
+
console.error(` Path not found: ${target}`);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
let files;
|
|
211
|
+
try {
|
|
212
|
+
readdirSync(target);
|
|
213
|
+
files = collectFiles(target);
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
files = [target];
|
|
217
|
+
}
|
|
218
|
+
const results = [];
|
|
219
|
+
for (const f of files) {
|
|
220
|
+
let content;
|
|
221
|
+
try {
|
|
222
|
+
content = readFileSync(f, "utf-8");
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
const issues = analyzeDrift(content);
|
|
228
|
+
const driftScore = Math.max(0, 100 -
|
|
229
|
+
issues.filter((i) => i.severity === "high").length * 20 -
|
|
230
|
+
issues.filter((i) => i.severity === "medium").length * 10 -
|
|
231
|
+
issues.filter((i) => i.severity === "low").length * 3);
|
|
232
|
+
results.push({ file: relative(target, f) || f, issues, driftScore });
|
|
233
|
+
}
|
|
234
|
+
const filtered = results.filter((r) => r.issues.length >= minIssues);
|
|
235
|
+
filtered.sort((a, b) => a.driftScore - b.driftScore);
|
|
236
|
+
if (format === "json") {
|
|
237
|
+
console.log(JSON.stringify({ files: filtered, scannedFiles: files.length, timestamp: new Date().toISOString() }, null, 2));
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
const totalIssues = results.reduce((s, r) => s + r.issues.length, 0);
|
|
241
|
+
console.log(`\n Doc Drift — ${files.length} files, ${totalIssues} issues\n ──────────────────────────`);
|
|
242
|
+
if (filtered.length === 0) {
|
|
243
|
+
console.log(` ✅ No documentation drift detected\n`);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
for (const r of filtered.slice(0, 20)) {
|
|
247
|
+
const icon = r.driftScore >= 80 ? "🟢" : r.driftScore >= 50 ? "🟡" : "🔴";
|
|
248
|
+
console.log(`\n ${icon} ${r.file} — ${r.driftScore}/100 (${r.issues.length} issues)`);
|
|
249
|
+
for (const iss of r.issues) {
|
|
250
|
+
const sev = iss.severity === "high" ? "🔴" : iss.severity === "medium" ? "🟠" : "🟡";
|
|
251
|
+
console.log(` ${sev} L${iss.line}: ${iss.detail}`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
if (filtered.length > 20)
|
|
255
|
+
console.log(` ... and ${filtered.length - 20} more files`);
|
|
256
|
+
console.log("");
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
//# sourceMappingURL=doc-drift.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doc-drift.js","sourceRoot":"","sources":["../../src/commands/doc-drift.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exception consistency — detect inconsistent exception handling
|
|
3
|
+
* patterns within a codebase: thrown-but-uncaught, asymmetric
|
|
4
|
+
* try/catch/finally, unhandled promise rejections, mixed strategies.
|
|
5
|
+
*/
|
|
6
|
+
export declare function runExceptionConsistency(argv: string[]): void;
|
|
7
|
+
//# sourceMappingURL=exception-consistency.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exception-consistency.d.ts","sourceRoot":"","sources":["../../src/commands/exception-consistency.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAmJH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAsE5D"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exception consistency — detect inconsistent exception handling
|
|
3
|
+
* patterns within a codebase: thrown-but-uncaught, asymmetric
|
|
4
|
+
* try/catch/finally, unhandled promise rejections, mixed strategies.
|
|
5
|
+
*/
|
|
6
|
+
import { readFileSync, readdirSync, statSync } from "fs";
|
|
7
|
+
import { join, extname } from "path";
|
|
8
|
+
// ─── File Collection ────────────────────────────────────────────────────────
|
|
9
|
+
const CODE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".py", ".java", ".cs", ".go", ".rs"]);
|
|
10
|
+
function collectFiles(dir, max = 500) {
|
|
11
|
+
const files = [];
|
|
12
|
+
function walk(d) {
|
|
13
|
+
if (files.length >= max)
|
|
14
|
+
return;
|
|
15
|
+
let entries;
|
|
16
|
+
try {
|
|
17
|
+
entries = readdirSync(d);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
for (const e of entries) {
|
|
23
|
+
if (files.length >= max)
|
|
24
|
+
return;
|
|
25
|
+
if (e.startsWith(".") || e === "node_modules" || e === "dist" || e === "build")
|
|
26
|
+
continue;
|
|
27
|
+
const full = join(d, e);
|
|
28
|
+
try {
|
|
29
|
+
if (statSync(full).isDirectory())
|
|
30
|
+
walk(full);
|
|
31
|
+
else if (CODE_EXTS.has(extname(full)))
|
|
32
|
+
files.push(full);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
/* skip */
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
walk(dir);
|
|
40
|
+
return files;
|
|
41
|
+
}
|
|
42
|
+
// ─── Patterns ───────────────────────────────────────────────────────────────
|
|
43
|
+
const PATTERNS = [
|
|
44
|
+
{
|
|
45
|
+
name: "empty-catch",
|
|
46
|
+
regex: /catch\s*\([^)]*\)\s*\{\s*\}/,
|
|
47
|
+
severity: "high",
|
|
48
|
+
message: "Empty catch block silently swallows exception",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: "catch-ignore-error",
|
|
52
|
+
regex: /catch\s*\(\s*_?\s*\)\s*\{/,
|
|
53
|
+
severity: "medium",
|
|
54
|
+
message: "Catch block ignores error variable",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: "throw-string",
|
|
58
|
+
regex: /throw\s+['"`]/,
|
|
59
|
+
severity: "medium",
|
|
60
|
+
message: "Throwing a string literal instead of an Error object",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: "catch-console-only",
|
|
64
|
+
regex: /catch\s*\([^)]*\)\s*\{\s*console\.(log|error|warn)\([^)]*\);\s*\}/,
|
|
65
|
+
severity: "medium",
|
|
66
|
+
message: "Catch block only logs — error is not re-thrown or handled",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: "unhandled-promise",
|
|
70
|
+
regex: /\.then\([^)]*\)\s*(?!\.catch)/,
|
|
71
|
+
severity: "medium",
|
|
72
|
+
message: "Promise chain without .catch() — potential unhandled rejection",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "async-no-try",
|
|
76
|
+
regex: /async\s+function\s+\w+[^{]*\{(?:(?!try\s*\{)[\s\S])*await\s/,
|
|
77
|
+
severity: "low",
|
|
78
|
+
message: "Async function uses await without try/catch",
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: "catch-rethrow-same",
|
|
82
|
+
regex: /catch\s*\(\s*(\w+)\s*\)\s*\{\s*throw\s+\1\s*;?\s*\}/,
|
|
83
|
+
severity: "low",
|
|
84
|
+
message: "Catch block only re-throws the same error — unnecessary try/catch",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: "generic-catch",
|
|
88
|
+
regex: /catch\s*\(\s*(\w+)\s*:\s*any\s*\)/,
|
|
89
|
+
severity: "low",
|
|
90
|
+
message: "Catching 'any' type — use typed error handling",
|
|
91
|
+
},
|
|
92
|
+
];
|
|
93
|
+
// ─── Analysis ───────────────────────────────────────────────────────────────
|
|
94
|
+
function analyzeFile(filePath) {
|
|
95
|
+
let content;
|
|
96
|
+
try {
|
|
97
|
+
content = readFileSync(filePath, "utf-8");
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return [];
|
|
101
|
+
}
|
|
102
|
+
const lines = content.split("\n");
|
|
103
|
+
const issues = [];
|
|
104
|
+
for (let i = 0; i < lines.length; i++) {
|
|
105
|
+
const line = lines[i];
|
|
106
|
+
// Check multi-line context (current + next 2 lines)
|
|
107
|
+
const context = lines.slice(i, Math.min(i + 3, lines.length)).join("\n");
|
|
108
|
+
for (const pat of PATTERNS) {
|
|
109
|
+
if ((pat.regex.test(context) && pat.regex.test(line)) ||
|
|
110
|
+
((i === 0 || !pat.regex.test(lines.slice(i - 1, i + 2).join("\n"))) && pat.regex.test(context))) {
|
|
111
|
+
// Deduplicate: only flag once per match block
|
|
112
|
+
if (!issues.some((x) => x.file === filePath && Math.abs(x.line - (i + 1)) < 3 && x.kind === pat.name)) {
|
|
113
|
+
issues.push({ file: filePath, line: i + 1, kind: pat.name, message: pat.message, severity: pat.severity });
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Detect mixed strategies: both callbacks and promises in same file
|
|
119
|
+
const hasCallbacks = /\bcallback\s*\(|function\s*\(\s*err\b/.test(content);
|
|
120
|
+
const hasPromises = /\.then\s*\(|new\s+Promise\s*\(|async\s/.test(content);
|
|
121
|
+
if (hasCallbacks && hasPromises) {
|
|
122
|
+
issues.push({
|
|
123
|
+
file: filePath,
|
|
124
|
+
line: 1,
|
|
125
|
+
kind: "mixed-strategy",
|
|
126
|
+
message: "File mixes callback-style (err) and promise/async patterns — consider unifying",
|
|
127
|
+
severity: "low",
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
return issues;
|
|
131
|
+
}
|
|
132
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
133
|
+
export function runExceptionConsistency(argv) {
|
|
134
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
135
|
+
console.log(`
|
|
136
|
+
judges exception-consistency — Detect inconsistent exception handling
|
|
137
|
+
|
|
138
|
+
Usage:
|
|
139
|
+
judges exception-consistency [dir]
|
|
140
|
+
judges exception-consistency src/ --severity high
|
|
141
|
+
judges exception-consistency --format json
|
|
142
|
+
|
|
143
|
+
Options:
|
|
144
|
+
[dir] Directory to scan (default: .)
|
|
145
|
+
--severity <level> Filter by minimum severity (high|medium|low)
|
|
146
|
+
--format json JSON output
|
|
147
|
+
--help, -h Show this help
|
|
148
|
+
`);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
152
|
+
const severityFilter = argv.find((_a, i) => argv[i - 1] === "--severity") || "low";
|
|
153
|
+
const dir = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0) || ".";
|
|
154
|
+
const severityOrder = { high: 3, medium: 2, low: 1 };
|
|
155
|
+
const minSev = severityOrder[severityFilter] || 1;
|
|
156
|
+
const files = collectFiles(dir);
|
|
157
|
+
const allIssues = [];
|
|
158
|
+
for (const f of files) {
|
|
159
|
+
const issues = analyzeFile(f);
|
|
160
|
+
allIssues.push(...issues.filter((x) => severityOrder[x.severity] >= minSev));
|
|
161
|
+
}
|
|
162
|
+
allIssues.sort((a, b) => severityOrder[b.severity] - severityOrder[a.severity]);
|
|
163
|
+
if (format === "json") {
|
|
164
|
+
console.log(JSON.stringify({ issues: allIssues, filesScanned: files.length, timestamp: new Date().toISOString() }, null, 2));
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
console.log(`\n Exception Consistency — ${files.length} files scanned, ${allIssues.length} issue(s)\n ──────────────────────────`);
|
|
168
|
+
if (allIssues.length === 0) {
|
|
169
|
+
console.log(" ✅ No inconsistent exception handling detected");
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
const byKind = new Map();
|
|
173
|
+
for (const issue of allIssues) {
|
|
174
|
+
byKind.set(issue.kind, (byKind.get(issue.kind) || 0) + 1);
|
|
175
|
+
}
|
|
176
|
+
console.log("\n Summary:");
|
|
177
|
+
for (const [kind, count] of byKind) {
|
|
178
|
+
console.log(` ${kind}: ${count}`);
|
|
179
|
+
}
|
|
180
|
+
console.log("\n Details:");
|
|
181
|
+
for (const issue of allIssues.slice(0, 50)) {
|
|
182
|
+
const icon = issue.severity === "high" ? "🔴" : issue.severity === "medium" ? "🟡" : "⚪";
|
|
183
|
+
console.log(` ${icon} [${issue.severity}] ${issue.file}:${issue.line}`);
|
|
184
|
+
console.log(` ${issue.message}`);
|
|
185
|
+
}
|
|
186
|
+
if (allIssues.length > 50) {
|
|
187
|
+
console.log(`\n ... and ${allIssues.length - 50} more issue(s)`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
console.log("");
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=exception-consistency.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exception-consistency.js","sourceRoot":"","sources":["../../src/commands/exception-consistency.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finding contest — gamified challenge mode where developers compete
|
|
3
|
+
* to fix the most findings in a codebase within a time window.
|
|
4
|
+
*
|
|
5
|
+
* Results stored locally in `.judges-contests/`.
|
|
6
|
+
*/
|
|
7
|
+
export declare function runFindingContest(argv: string[]): void;
|
|
8
|
+
//# sourceMappingURL=finding-contest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finding-contest.d.ts","sourceRoot":"","sources":["../../src/commands/finding-contest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAyEH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAuKtD"}
|