@kevinrabun/judges 3.59.0 → 3.60.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 +12 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +56 -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/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/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/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/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/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,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adoption-track — measure team-level Judges adoption metrics from local data.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, readdirSync, statSync, existsSync } 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 = 500) {
|
|
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
|
+
function analyzeConfig(dir) {
|
|
41
|
+
const configPaths = [
|
|
42
|
+
join(dir, ".judgesrc"),
|
|
43
|
+
join(dir, ".judgesrc.json"),
|
|
44
|
+
join(dir, "judgesrc.json"),
|
|
45
|
+
join(dir, ".judges.json"),
|
|
46
|
+
];
|
|
47
|
+
for (const p of configPaths) {
|
|
48
|
+
if (existsSync(p)) {
|
|
49
|
+
try {
|
|
50
|
+
const raw = readFileSync(p, "utf-8");
|
|
51
|
+
const config = JSON.parse(raw);
|
|
52
|
+
let completeness = 20; // Base for having a config at all
|
|
53
|
+
if (config.preset)
|
|
54
|
+
completeness += 15;
|
|
55
|
+
if (config.minSeverity)
|
|
56
|
+
completeness += 10;
|
|
57
|
+
if (config.judges && Object.keys(config.judges).length > 0)
|
|
58
|
+
completeness += 20;
|
|
59
|
+
if (config.disabledRules && config.disabledRules.length > 0)
|
|
60
|
+
completeness += 10;
|
|
61
|
+
if (config.ruleOverrides && Object.keys(config.ruleOverrides).length > 0)
|
|
62
|
+
completeness += 15;
|
|
63
|
+
if (config.disabledJudges && config.disabledJudges.length > 0)
|
|
64
|
+
completeness += 10;
|
|
65
|
+
return { config, completeness: Math.min(100, completeness) };
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
/* malformed config */
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Check package.json for judges config
|
|
73
|
+
const pkgPath = join(dir, "package.json");
|
|
74
|
+
if (existsSync(pkgPath)) {
|
|
75
|
+
try {
|
|
76
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
77
|
+
if (pkg.judges || pkg.judgesConfig) {
|
|
78
|
+
return { config: (pkg.judges || pkg.judgesConfig), completeness: 30 };
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
/* skip */
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return { config: null, completeness: 0 };
|
|
86
|
+
}
|
|
87
|
+
// ─── Suppression tracking ───────────────────────────────────────────────────
|
|
88
|
+
function countSuppressions(files) {
|
|
89
|
+
let total = 0;
|
|
90
|
+
const categories = new Map();
|
|
91
|
+
for (const f of files) {
|
|
92
|
+
let content;
|
|
93
|
+
try {
|
|
94
|
+
content = readFileSync(f, "utf-8");
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const suppressions = content.match(/judges-disable|judges-ignore|judges-suppress|noinspection|@suppress/gi) || [];
|
|
100
|
+
total += suppressions.length;
|
|
101
|
+
// Categorize by nearby judge name
|
|
102
|
+
const lines = content.split("\n");
|
|
103
|
+
for (let i = 0; i < lines.length; i++) {
|
|
104
|
+
if (/judges-disable|judges-ignore|judges-suppress/i.test(lines[i])) {
|
|
105
|
+
const ruleMatch = lines[i].match(/(?:judges-(?:disable|ignore|suppress))\s+(\S+)/i);
|
|
106
|
+
const cat = ruleMatch ? ruleMatch[1] : "unspecified";
|
|
107
|
+
categories.set(cat, (categories.get(cat) || 0) + 1);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return { total, categories };
|
|
112
|
+
}
|
|
113
|
+
// ─── Cold spots (directories with no judges integration) ────────────────────
|
|
114
|
+
function findColdSpots(dir, files) {
|
|
115
|
+
const dirCounts = new Map();
|
|
116
|
+
const dirFiles = new Map();
|
|
117
|
+
for (const f of files) {
|
|
118
|
+
const rel = relative(dir, f);
|
|
119
|
+
const parts = rel.split(/[/\\]/);
|
|
120
|
+
if (parts.length > 1) {
|
|
121
|
+
const topDir = parts[0];
|
|
122
|
+
dirFiles.set(topDir, (dirFiles.get(topDir) || 0) + 1);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// Directories with code but no suppression comments → likely not being reviewed
|
|
126
|
+
for (const f of files) {
|
|
127
|
+
let content;
|
|
128
|
+
try {
|
|
129
|
+
content = readFileSync(f, "utf-8");
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
const rel = relative(dir, f);
|
|
135
|
+
const parts = rel.split(/[/\\]/);
|
|
136
|
+
if (parts.length > 1) {
|
|
137
|
+
const topDir = parts[0];
|
|
138
|
+
if (/judges-|@judges|judges\.config/i.test(content)) {
|
|
139
|
+
dirCounts.set(topDir, (dirCounts.get(topDir) || 0) + 1);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Directories with files but zero judges references
|
|
144
|
+
const coldSpots = [];
|
|
145
|
+
for (const [d, count] of dirFiles) {
|
|
146
|
+
if (count >= 3 && !dirCounts.has(d)) {
|
|
147
|
+
coldSpots.push(d);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return coldSpots;
|
|
151
|
+
}
|
|
152
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
153
|
+
export function runAdoptionTrack(argv) {
|
|
154
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
155
|
+
console.log(`
|
|
156
|
+
judges adoption-track — Measure team-level Judges adoption metrics
|
|
157
|
+
|
|
158
|
+
Usage:
|
|
159
|
+
judges adoption-track [dir]
|
|
160
|
+
judges adoption-track --format json
|
|
161
|
+
|
|
162
|
+
Options:
|
|
163
|
+
[dir] Directory to scan (default: .)
|
|
164
|
+
--format json JSON output
|
|
165
|
+
--help, -h Show this help
|
|
166
|
+
|
|
167
|
+
Measures: config completeness, suppression rate, rule override count,
|
|
168
|
+
cold spots (directories with code but no review engagement),
|
|
169
|
+
adoption health score.
|
|
170
|
+
|
|
171
|
+
Note: All metrics are computed from local files only — no data is sent
|
|
172
|
+
or stored externally.
|
|
173
|
+
`);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
177
|
+
const dir = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0) || ".";
|
|
178
|
+
const files = collectFiles(dir);
|
|
179
|
+
const { config, completeness } = analyzeConfig(dir);
|
|
180
|
+
const { total: suppressionTotal, categories: suppressionCats } = countSuppressions(files);
|
|
181
|
+
const coldSpots = findColdSpots(dir, files);
|
|
182
|
+
const suppressionRate = files.length > 0 ? Math.round((suppressionTotal / files.length) * 100) : 0;
|
|
183
|
+
const ruleOverrideCount = config?.ruleOverrides ? Object.keys(config.ruleOverrides).length : 0;
|
|
184
|
+
const disabledCount = config?.disabledJudges?.length || 0;
|
|
185
|
+
// Estimate active vs total judges (heuristic)
|
|
186
|
+
const totalJudgeCount = 60; // Approximate total available judges
|
|
187
|
+
const activeJudgeCount = totalJudgeCount - disabledCount;
|
|
188
|
+
const coverageEstimate = files.length > 0 ? Math.round((activeJudgeCount / totalJudgeCount) * 100) : 0;
|
|
189
|
+
// Health score
|
|
190
|
+
let healthScore = 0;
|
|
191
|
+
healthScore += completeness * 0.3; // Config completeness weight
|
|
192
|
+
healthScore += coverageEstimate * 0.3; // Coverage weight
|
|
193
|
+
healthScore += Math.max(0, 100 - suppressionRate * 2) * 0.2; // Low suppression is good
|
|
194
|
+
healthScore += Math.max(0, 100 - coldSpots.length * 15) * 0.2; // Few cold spots is good
|
|
195
|
+
healthScore = Math.round(Math.min(100, Math.max(0, healthScore)));
|
|
196
|
+
const metrics = {
|
|
197
|
+
configCompleteness: completeness,
|
|
198
|
+
coverageEstimate,
|
|
199
|
+
suppressionRate,
|
|
200
|
+
ruleOverrideCount,
|
|
201
|
+
activeJudgeCount,
|
|
202
|
+
totalJudgeCount,
|
|
203
|
+
coldSpots,
|
|
204
|
+
healthScore,
|
|
205
|
+
};
|
|
206
|
+
if (format === "json") {
|
|
207
|
+
console.log(JSON.stringify({
|
|
208
|
+
metrics,
|
|
209
|
+
suppressionCategories: Object.fromEntries(suppressionCats),
|
|
210
|
+
filesScanned: files.length,
|
|
211
|
+
timestamp: new Date().toISOString(),
|
|
212
|
+
}, null, 2));
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
const badge = healthScore >= 80 ? "✅ HIGH ADOPTION" : healthScore >= 50 ? "⚠️ PARTIAL ADOPTION" : "❌ LOW ADOPTION";
|
|
216
|
+
console.log(`\n Adoption Track: ${badge} (${healthScore}/100)\n ─────────────────────────────`);
|
|
217
|
+
console.log(` Files scanned: ${files.length}`);
|
|
218
|
+
console.log(` Config completeness: ${completeness}%${config ? "" : " (no config found)"}`);
|
|
219
|
+
console.log(` Judge coverage: ${coverageEstimate}% (${activeJudgeCount}/${totalJudgeCount} judges active)`);
|
|
220
|
+
console.log(` Suppression rate: ${suppressionRate}% (${suppressionTotal} suppressions)`);
|
|
221
|
+
console.log(` Rule overrides: ${ruleOverrideCount}`);
|
|
222
|
+
if (suppressionCats.size > 0) {
|
|
223
|
+
console.log(`\n Suppressed categories:`);
|
|
224
|
+
for (const [cat, count] of [...suppressionCats.entries()].sort((a, b) => b[1] - a[1]).slice(0, 10)) {
|
|
225
|
+
console.log(` ${cat}: ${count}`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (coldSpots.length > 0) {
|
|
229
|
+
console.log(`\n Cold spots (low/no engagement):`);
|
|
230
|
+
for (const spot of coldSpots.slice(0, 10))
|
|
231
|
+
console.log(` 📁 ${spot}/`);
|
|
232
|
+
}
|
|
233
|
+
console.log(`\n Recommendations:`);
|
|
234
|
+
if (completeness < 50)
|
|
235
|
+
console.log(` → Create or improve .judgesrc configuration`);
|
|
236
|
+
if (disabledCount > 10)
|
|
237
|
+
console.log(` → Review disabled judges — ${disabledCount} disabled may be excessive`);
|
|
238
|
+
if (suppressionRate > 20)
|
|
239
|
+
console.log(` → High suppression rate (${suppressionRate}%) — review if suppressions are justified`);
|
|
240
|
+
if (coldSpots.length > 0)
|
|
241
|
+
console.log(` → Engage cold-spot directories: ${coldSpots.slice(0, 3).join(", ")}`);
|
|
242
|
+
if (healthScore >= 80)
|
|
243
|
+
console.log(` → Adoption is healthy — maintain current practices`);
|
|
244
|
+
console.log();
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=adoption-track.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adoption-track.js","sourceRoot":"","sources":["../../src/commands/adoption-track.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-blind.d.ts","sourceRoot":"","sources":["../../src/commands/context-blind.ts"],"names":[],"mappings":"AAAA;;GAEG;AAmOH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAoEpD"}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context blind — flag when AI reinvents utilities already present in the codebase.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, readdirSync, statSync } from "fs";
|
|
5
|
+
import { join, extname, basename } from "path";
|
|
6
|
+
// ─── File Collection ────────────────────────────────────────────────────────
|
|
7
|
+
const CODE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx"]);
|
|
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
|
+
function buildProjectInventory(files) {
|
|
41
|
+
const assets = [];
|
|
42
|
+
for (const filepath of files) {
|
|
43
|
+
let content;
|
|
44
|
+
try {
|
|
45
|
+
content = readFileSync(filepath, "utf-8");
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const lines = content.split("\n");
|
|
51
|
+
for (let i = 0; i < lines.length; i++) {
|
|
52
|
+
const line = lines[i];
|
|
53
|
+
// Exported functions
|
|
54
|
+
const funcMatch = line.match(/export\s+(?:async\s+)?function\s+(\w+)/);
|
|
55
|
+
if (funcMatch) {
|
|
56
|
+
const name = funcMatch[1];
|
|
57
|
+
let category = "general";
|
|
58
|
+
if (/format|stringify|serialize|render|display/i.test(name))
|
|
59
|
+
category = "formatting";
|
|
60
|
+
else if (/validate|check|verify|assert|is[A-Z]/i.test(name))
|
|
61
|
+
category = "validation";
|
|
62
|
+
else if (/parse|deserialize|decode|extract/i.test(name))
|
|
63
|
+
category = "parsing";
|
|
64
|
+
else if (/log|error|warn|debug|trace|info/i.test(name))
|
|
65
|
+
category = "logging";
|
|
66
|
+
else if (/fetch|request|get|post|put|delete|api|http/i.test(name))
|
|
67
|
+
category = "http";
|
|
68
|
+
else if (/config|setting|option|env/i.test(name))
|
|
69
|
+
category = "config";
|
|
70
|
+
else if (/hash|encrypt|decrypt|sign|token|auth/i.test(name))
|
|
71
|
+
category = "security";
|
|
72
|
+
else if (/sort|filter|map|reduce|transform|convert/i.test(name))
|
|
73
|
+
category = "data-transform";
|
|
74
|
+
else if (/path|file|dir|folder|read|write/i.test(name))
|
|
75
|
+
category = "filesystem";
|
|
76
|
+
else if (/date|time|duration|format.*date|parse.*date/i.test(name))
|
|
77
|
+
category = "datetime";
|
|
78
|
+
assets.push({ name, type: "function", file: filepath, line: i + 1, category });
|
|
79
|
+
}
|
|
80
|
+
// Exported classes
|
|
81
|
+
const classMatch = line.match(/export\s+class\s+(\w+)/);
|
|
82
|
+
if (classMatch) {
|
|
83
|
+
const name = classMatch[1];
|
|
84
|
+
let category = "general";
|
|
85
|
+
if (/Error|Exception/i.test(name))
|
|
86
|
+
category = "error";
|
|
87
|
+
else if (/Logger|Log/i.test(name))
|
|
88
|
+
category = "logging";
|
|
89
|
+
else if (/Client|Service|Api/i.test(name))
|
|
90
|
+
category = "http";
|
|
91
|
+
else if (/Config|Settings/i.test(name))
|
|
92
|
+
category = "config";
|
|
93
|
+
else if (/Cache/i.test(name))
|
|
94
|
+
category = "cache";
|
|
95
|
+
else if (/Validator/i.test(name))
|
|
96
|
+
category = "validation";
|
|
97
|
+
assets.push({ name, type: "class", file: filepath, line: i + 1, category });
|
|
98
|
+
}
|
|
99
|
+
// Exported consts (utility objects, instances)
|
|
100
|
+
const constMatch = line.match(/export\s+const\s+(\w+)/);
|
|
101
|
+
if (constMatch) {
|
|
102
|
+
assets.push({ name: constMatch[1], type: "const", file: filepath, line: i + 1, category: "general" });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return assets;
|
|
107
|
+
}
|
|
108
|
+
function analyzeFile(filepath, inventory) {
|
|
109
|
+
const issues = [];
|
|
110
|
+
let content;
|
|
111
|
+
try {
|
|
112
|
+
content = readFileSync(filepath, "utf-8");
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return issues;
|
|
116
|
+
}
|
|
117
|
+
const lines = content.split("\n");
|
|
118
|
+
const _fname = basename(filepath);
|
|
119
|
+
for (let i = 0; i < lines.length; i++) {
|
|
120
|
+
const line = lines[i];
|
|
121
|
+
// New function that duplicates an existing exported function's purpose
|
|
122
|
+
const newFuncMatch = line.match(/(?:function|const)\s+(\w+)\s*(?:=\s*(?:async\s*)?\(|\()/);
|
|
123
|
+
if (newFuncMatch && !line.includes("export")) {
|
|
124
|
+
const name = newFuncMatch[1];
|
|
125
|
+
// Check if a similarly-named exported function exists elsewhere
|
|
126
|
+
for (const asset of inventory) {
|
|
127
|
+
if (asset.file === filepath)
|
|
128
|
+
continue;
|
|
129
|
+
if (asset.name.toLowerCase() === name.toLowerCase() && asset.type === "function") {
|
|
130
|
+
issues.push({
|
|
131
|
+
file: filepath,
|
|
132
|
+
line: i + 1,
|
|
133
|
+
issue: "Reinvents existing project function",
|
|
134
|
+
severity: "high",
|
|
135
|
+
detail: `\`${name}\` already exported from \`${basename(asset.file)}:${asset.line}\` — reuse instead of reimplementing`,
|
|
136
|
+
});
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// Hand-rolled validation when project has validators
|
|
142
|
+
const hasValidators = inventory.some((a) => a.category === "validation");
|
|
143
|
+
if (hasValidators && /(?:if\s*\(\s*typeof\s+\w+\s*!==?\s*['"]|if\s*\(\s*!\w+\s*\|\|\s*typeof)/.test(line)) {
|
|
144
|
+
const block = lines.slice(i, Math.min(i + 5, lines.length)).join("\n");
|
|
145
|
+
const typeChecks = (block.match(/typeof\s+\w+/g) || []).length;
|
|
146
|
+
if (typeChecks >= 3) {
|
|
147
|
+
const validator = inventory.find((a) => a.category === "validation");
|
|
148
|
+
issues.push({
|
|
149
|
+
file: filepath,
|
|
150
|
+
line: i + 1,
|
|
151
|
+
issue: "Hand-rolled validation (project has validators)",
|
|
152
|
+
severity: "medium",
|
|
153
|
+
detail: `${typeChecks} inline type checks — project has validation utilities (e.g., \`${validator?.name}\` in ${validator ? basename(validator.file) : "?"})`,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Custom error class when project has error hierarchy
|
|
158
|
+
if (/class\s+\w*Error\s+extends\s+Error/.test(line) && !line.includes("export")) {
|
|
159
|
+
const existingErrors = inventory.filter((a) => a.category === "error");
|
|
160
|
+
if (existingErrors.length > 0) {
|
|
161
|
+
issues.push({
|
|
162
|
+
file: filepath,
|
|
163
|
+
line: i + 1,
|
|
164
|
+
issue: "New error class (project has error hierarchy)",
|
|
165
|
+
severity: "medium",
|
|
166
|
+
detail: `Project already has ${existingErrors.length} error class(es) — extend existing hierarchy instead`,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// New HTTP client setup when project has one
|
|
171
|
+
if (/(?:axios\.create|new\s+(?:HttpClient|FetchClient)|createHttpClient)/i.test(line)) {
|
|
172
|
+
const existingClients = inventory.filter((a) => a.category === "http" && a.type === "class");
|
|
173
|
+
if (existingClients.length > 0) {
|
|
174
|
+
issues.push({
|
|
175
|
+
file: filepath,
|
|
176
|
+
line: i + 1,
|
|
177
|
+
issue: "New HTTP client (project has one)",
|
|
178
|
+
severity: "medium",
|
|
179
|
+
detail: `Project already has HTTP client(s) (e.g., \`${existingClients[0].name}\`) — reuse the configured instance`,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// New logger setup when project has one
|
|
184
|
+
if (/(?:new\s+Logger|createLogger|winston\.create|pino\()/i.test(line)) {
|
|
185
|
+
const existingLoggers = inventory.filter((a) => a.category === "logging");
|
|
186
|
+
if (existingLoggers.length > 0) {
|
|
187
|
+
issues.push({
|
|
188
|
+
file: filepath,
|
|
189
|
+
line: i + 1,
|
|
190
|
+
issue: "New logger (project has logging utility)",
|
|
191
|
+
severity: "medium",
|
|
192
|
+
detail: `Project already has logging (e.g., \`${existingLoggers[0].name}\`) — reuse instead of creating another`,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// Config loading when project has config module
|
|
197
|
+
if (/(?:dotenv\.config|process\.env\.\w+.*process\.env\.\w+.*process\.env)/i.test(line)) {
|
|
198
|
+
const existingConfig = inventory.filter((a) => a.category === "config");
|
|
199
|
+
if (existingConfig.length > 0) {
|
|
200
|
+
issues.push({
|
|
201
|
+
file: filepath,
|
|
202
|
+
line: i + 1,
|
|
203
|
+
issue: "Direct env access (project has config module)",
|
|
204
|
+
severity: "low",
|
|
205
|
+
detail: `Project has config utilities (e.g., \`${existingConfig[0].name}\`) — use centralized config instead of direct env access`,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return issues;
|
|
211
|
+
}
|
|
212
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
213
|
+
export function runContextBlind(argv) {
|
|
214
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
215
|
+
console.log(`
|
|
216
|
+
judges context-blind — Flag AI code that reinvents existing project utilities
|
|
217
|
+
|
|
218
|
+
Usage:
|
|
219
|
+
judges context-blind [dir]
|
|
220
|
+
judges context-blind src/ --format json
|
|
221
|
+
|
|
222
|
+
Options:
|
|
223
|
+
[dir] Directory to scan (default: .)
|
|
224
|
+
--format json JSON output
|
|
225
|
+
--help, -h Show this help
|
|
226
|
+
|
|
227
|
+
Checks: duplicate function names, hand-rolled validation, redundant error classes,
|
|
228
|
+
new HTTP clients, new loggers, direct env access when project has config module.
|
|
229
|
+
`);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
233
|
+
const dir = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0) || ".";
|
|
234
|
+
const files = collectFiles(dir);
|
|
235
|
+
const inventory = buildProjectInventory(files);
|
|
236
|
+
const allIssues = [];
|
|
237
|
+
for (const f of files)
|
|
238
|
+
allIssues.push(...analyzeFile(f, inventory));
|
|
239
|
+
const highCount = allIssues.filter((i) => i.severity === "high").length;
|
|
240
|
+
const medCount = allIssues.filter((i) => i.severity === "medium").length;
|
|
241
|
+
const score = Math.max(0, 100 - highCount * 10 - medCount * 5);
|
|
242
|
+
if (format === "json") {
|
|
243
|
+
console.log(JSON.stringify({
|
|
244
|
+
issues: allIssues,
|
|
245
|
+
score,
|
|
246
|
+
inventory: {
|
|
247
|
+
functions: inventory.filter((a) => a.type === "function").length,
|
|
248
|
+
classes: inventory.filter((a) => a.type === "class").length,
|
|
249
|
+
},
|
|
250
|
+
summary: { high: highCount, medium: medCount, total: allIssues.length },
|
|
251
|
+
timestamp: new Date().toISOString(),
|
|
252
|
+
}, null, 2));
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
const badge = score >= 80 ? "✅ CONTEXT-AWARE" : score >= 50 ? "⚠️ BLIND SPOTS" : "❌ REINVENTING";
|
|
256
|
+
console.log(`\n Context Blind: ${badge} (${score}/100)\n ─────────────────────────────`);
|
|
257
|
+
console.log(` Project inventory: ${inventory.filter((a) => a.type === "function").length} functions, ${inventory.filter((a) => a.type === "class").length} classes`);
|
|
258
|
+
if (allIssues.length === 0) {
|
|
259
|
+
console.log(" No reinvention detected.\n");
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
for (const issue of allIssues.slice(0, 25)) {
|
|
263
|
+
const icon = issue.severity === "high" ? "🔴" : issue.severity === "medium" ? "🟡" : "🔵";
|
|
264
|
+
console.log(` ${icon} ${issue.issue}`);
|
|
265
|
+
console.log(` ${issue.file}:${issue.line}`);
|
|
266
|
+
console.log(` ${issue.detail}`);
|
|
267
|
+
}
|
|
268
|
+
if (allIssues.length > 25)
|
|
269
|
+
console.log(` ... and ${allIssues.length - 25} more`);
|
|
270
|
+
console.log(`\n Total: ${allIssues.length} | High: ${highCount} | Medium: ${medCount} | Score: ${score}/100\n`);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
//# sourceMappingURL=context-blind.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-blind.js","sourceRoot":"","sources":["../../src/commands/context-blind.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"}
|