@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.
Files changed (70) hide show
  1. package/CHANGELOG.md +19 -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/adoption-track.d.ts +5 -0
  6. package/dist/commands/adoption-track.d.ts.map +1 -0
  7. package/dist/commands/adoption-track.js +247 -0
  8. package/dist/commands/adoption-track.js.map +1 -0
  9. package/dist/commands/ai-provenance.d.ts +5 -0
  10. package/dist/commands/ai-provenance.d.ts.map +1 -0
  11. package/dist/commands/ai-provenance.js +248 -0
  12. package/dist/commands/ai-provenance.js.map +1 -0
  13. package/dist/commands/blame-review.d.ts +5 -0
  14. package/dist/commands/blame-review.d.ts.map +1 -0
  15. package/dist/commands/blame-review.js +270 -0
  16. package/dist/commands/blame-review.js.map +1 -0
  17. package/dist/commands/context-blind.d.ts +5 -0
  18. package/dist/commands/context-blind.d.ts.map +1 -0
  19. package/dist/commands/context-blind.js +273 -0
  20. package/dist/commands/context-blind.js.map +1 -0
  21. package/dist/commands/evidence-chain.d.ts +5 -0
  22. package/dist/commands/evidence-chain.d.ts.map +1 -0
  23. package/dist/commands/evidence-chain.js +310 -0
  24. package/dist/commands/evidence-chain.js.map +1 -0
  25. package/dist/commands/finding-budget.d.ts +5 -0
  26. package/dist/commands/finding-budget.d.ts.map +1 -0
  27. package/dist/commands/finding-budget.js +233 -0
  28. package/dist/commands/finding-budget.js.map +1 -0
  29. package/dist/commands/hallucination-detect.d.ts +5 -0
  30. package/dist/commands/hallucination-detect.d.ts.map +1 -0
  31. package/dist/commands/hallucination-detect.js +351 -0
  32. package/dist/commands/hallucination-detect.js.map +1 -0
  33. package/dist/commands/merge-verdict.d.ts +5 -0
  34. package/dist/commands/merge-verdict.d.ts.map +1 -0
  35. package/dist/commands/merge-verdict.js +288 -0
  36. package/dist/commands/merge-verdict.js.map +1 -0
  37. package/dist/commands/over-abstraction.d.ts +5 -0
  38. package/dist/commands/over-abstraction.d.ts.map +1 -0
  39. package/dist/commands/over-abstraction.js +308 -0
  40. package/dist/commands/over-abstraction.js.map +1 -0
  41. package/dist/commands/quick-check.d.ts +5 -0
  42. package/dist/commands/quick-check.d.ts.map +1 -0
  43. package/dist/commands/quick-check.js +174 -0
  44. package/dist/commands/quick-check.js.map +1 -0
  45. package/dist/commands/review-contract.d.ts +5 -0
  46. package/dist/commands/review-contract.d.ts.map +1 -0
  47. package/dist/commands/review-contract.js +200 -0
  48. package/dist/commands/review-contract.js.map +1 -0
  49. package/dist/commands/review-digest.d.ts +5 -0
  50. package/dist/commands/review-digest.d.ts.map +1 -0
  51. package/dist/commands/review-digest.js +266 -0
  52. package/dist/commands/review-digest.js.map +1 -0
  53. package/dist/commands/review-handoff.d.ts +5 -0
  54. package/dist/commands/review-handoff.d.ts.map +1 -0
  55. package/dist/commands/review-handoff.js +209 -0
  56. package/dist/commands/review-handoff.js.map +1 -0
  57. package/dist/commands/review-receipt.d.ts +5 -0
  58. package/dist/commands/review-receipt.d.ts.map +1 -0
  59. package/dist/commands/review-receipt.js +221 -0
  60. package/dist/commands/review-receipt.js.map +1 -0
  61. package/dist/commands/security-theater.d.ts +5 -0
  62. package/dist/commands/security-theater.d.ts.map +1 -0
  63. package/dist/commands/security-theater.js +279 -0
  64. package/dist/commands/security-theater.js.map +1 -0
  65. package/dist/commands/stale-pattern.d.ts +5 -0
  66. package/dist/commands/stale-pattern.d.ts.map +1 -0
  67. package/dist/commands/stale-pattern.js +294 -0
  68. package/dist/commands/stale-pattern.js.map +1 -0
  69. package/package.json +1 -1
  70. package/server.json +2 -2
@@ -0,0 +1,270 @@
1
+ /**
2
+ * Blame-review — git-blame integrated historical finding attribution.
3
+ */
4
+ import { execSync } from "child_process";
5
+ import { readFileSync, readdirSync, statSync } from "fs";
6
+ import { join, extname } from "path";
7
+ // ─── Known patterns to detect ──────────────────────────────────────────────
8
+ const PATTERNS = [
9
+ {
10
+ name: "hardcoded-secret",
11
+ severity: "critical",
12
+ regex: /(?:password|secret|api_key|token)\s*[:=]\s*["'][^"']{8,}/i,
13
+ },
14
+ { name: "eval-usage", severity: "critical", regex: /\beval\s*\(/ },
15
+ { name: "sql-concat", severity: "critical", regex: /(?:query|execute)\s*\(\s*["'`].*\+/ },
16
+ { name: "empty-catch", severity: "medium", regex: /catch\s*\([^)]*\)\s*\{\s*\}/ },
17
+ { name: "console-log", severity: "low", regex: /console\.log\s*\(/ },
18
+ { name: "todo-fixme", severity: "low", regex: /\/\/\s*(?:TODO|FIXME|HACK|XXX)\b/i },
19
+ { name: "any-type", severity: "medium", regex: /:\s*any\b/ },
20
+ { name: "deprecated-api", severity: "medium", regex: /new\s+Buffer\s*\(|\.substr\s*\(|\.addListener\s*\(/i },
21
+ { name: "unsafe-regex", severity: "high", regex: /new\s+RegExp\s*\([^)]*\+/ },
22
+ { name: "missing-await", severity: "high", regex: /(?:return|=)\s+(?!await\b)[a-zA-Z]+\.(then|catch)\s*\(/ },
23
+ ];
24
+ // ─── Helpers ────────────────────────────────────────────────────────────────
25
+ function isGitRepo() {
26
+ try {
27
+ execSync("git rev-parse --is-inside-work-tree", { stdio: "pipe", timeout: 5000 });
28
+ return true;
29
+ }
30
+ catch {
31
+ return false;
32
+ }
33
+ }
34
+ function gitBlameFile(filePath, since) {
35
+ try {
36
+ const sinceArg = since ? ` --since="${since}"` : "";
37
+ const out = execSync(`git blame --line-porcelain${sinceArg} -- "${filePath}"`, {
38
+ stdio: ["pipe", "pipe", "pipe"],
39
+ timeout: 15000,
40
+ maxBuffer: 10 * 1024 * 1024,
41
+ }).toString();
42
+ const entries = [];
43
+ const lines = out.split("\n");
44
+ let commit = "";
45
+ let author = "";
46
+ let date = "";
47
+ let lineNum = 0;
48
+ for (const line of lines) {
49
+ const commitMatch = /^([0-9a-f]{40})\s+\d+\s+(\d+)/.exec(line);
50
+ if (commitMatch) {
51
+ commit = commitMatch[1];
52
+ lineNum = parseInt(commitMatch[2], 10);
53
+ continue;
54
+ }
55
+ if (line.startsWith("author ")) {
56
+ author = line.slice(7);
57
+ continue;
58
+ }
59
+ if (line.startsWith("author-time ")) {
60
+ const ts = parseInt(line.slice(12), 10);
61
+ date = new Date(ts * 1000).toISOString().slice(0, 10);
62
+ continue;
63
+ }
64
+ if (line.startsWith("\t")) {
65
+ entries.push({
66
+ commit: commit.slice(0, 8),
67
+ author,
68
+ date,
69
+ lineNumber: lineNum,
70
+ content: line.slice(1),
71
+ });
72
+ }
73
+ }
74
+ return entries;
75
+ }
76
+ catch {
77
+ return [];
78
+ }
79
+ }
80
+ function collectSourceFiles(dir) {
81
+ const exts = new Set([".ts", ".js", ".tsx", ".jsx", ".py", ".java", ".go", ".rs", ".cs", ".rb", ".php"]);
82
+ const files = [];
83
+ const skipDirs = new Set(["node_modules", ".git", "dist", "build", "coverage", ".next"]);
84
+ function walk(d) {
85
+ let entries;
86
+ try {
87
+ entries = readdirSync(d);
88
+ }
89
+ catch {
90
+ return;
91
+ }
92
+ for (const name of entries) {
93
+ if (skipDirs.has(name))
94
+ continue;
95
+ const full = join(d, name);
96
+ try {
97
+ const st = statSync(full);
98
+ if (st.isDirectory())
99
+ walk(full);
100
+ else if (exts.has(extname(name)))
101
+ files.push(full);
102
+ }
103
+ catch {
104
+ // skip inaccessible
105
+ }
106
+ }
107
+ }
108
+ walk(dir);
109
+ return files;
110
+ }
111
+ function daysBetween(dateStr) {
112
+ const then = new Date(dateStr).getTime();
113
+ const now = Date.now();
114
+ return Math.floor((now - then) / (1000 * 60 * 60 * 24));
115
+ }
116
+ // ─── Core analysis ─────────────────────────────────────────────────────────
117
+ function analyzeBlame(files, since, authorFilter) {
118
+ const attributions = [];
119
+ for (const filePath of files) {
120
+ let content;
121
+ try {
122
+ content = readFileSync(filePath, "utf-8");
123
+ }
124
+ catch {
125
+ continue;
126
+ }
127
+ const fileLines = content.split("\n");
128
+ // Quick pattern scan first
129
+ const lineHits = [];
130
+ for (let i = 0; i < fileLines.length; i++) {
131
+ for (const pat of PATTERNS) {
132
+ if (pat.regex.test(fileLines[i])) {
133
+ lineHits.push({ line: i + 1, pattern: pat.name, severity: pat.severity });
134
+ }
135
+ }
136
+ }
137
+ if (lineHits.length === 0)
138
+ continue;
139
+ // Get blame data
140
+ const blameEntries = gitBlameFile(filePath, since);
141
+ const blameByLine = new Map();
142
+ for (const entry of blameEntries) {
143
+ blameByLine.set(entry.lineNumber, entry);
144
+ }
145
+ for (const hit of lineHits) {
146
+ const blame = blameByLine.get(hit.line);
147
+ if (!blame)
148
+ continue;
149
+ if (authorFilter && blame.author !== authorFilter)
150
+ continue;
151
+ attributions.push({
152
+ finding: hit.pattern,
153
+ severity: hit.severity,
154
+ introducedBy: blame.commit,
155
+ author: blame.author,
156
+ date: blame.date,
157
+ lineNumber: hit.line,
158
+ ageInDays: daysBetween(blame.date),
159
+ });
160
+ }
161
+ }
162
+ // Build author summaries
163
+ const authorMap = new Map();
164
+ for (const attr of attributions) {
165
+ let summary = authorMap.get(attr.author);
166
+ if (!summary) {
167
+ summary = { author: attr.author, totalFindings: 0, critical: 0, high: 0, medium: 0, low: 0 };
168
+ authorMap.set(attr.author, summary);
169
+ }
170
+ summary.totalFindings++;
171
+ if (attr.severity === "critical")
172
+ summary.critical++;
173
+ else if (attr.severity === "high")
174
+ summary.high++;
175
+ else if (attr.severity === "medium")
176
+ summary.medium++;
177
+ else
178
+ summary.low++;
179
+ }
180
+ const sorted = [...attributions].sort((a, b) => b.ageInDays - a.ageInDays);
181
+ const totalAge = attributions.reduce((sum, a) => sum + a.ageInDays, 0);
182
+ return {
183
+ totalFindings: attributions.length,
184
+ attributions,
185
+ authorSummaries: [...authorMap.values()].sort((a, b) => b.totalFindings - a.totalFindings),
186
+ oldestFinding: sorted.length > 0 ? sorted[0] : null,
187
+ newestFinding: sorted.length > 0 ? sorted[sorted.length - 1] : null,
188
+ averageAgeDays: attributions.length > 0 ? Math.round(totalAge / attributions.length) : 0,
189
+ };
190
+ }
191
+ // ─── CLI ────────────────────────────────────────────────────────────────────
192
+ export function runBlameReview(argv) {
193
+ if (argv.includes("--help") || argv.includes("-h")) {
194
+ console.log(`
195
+ judges blame-review — Git-blame integrated finding attribution
196
+
197
+ Usage:
198
+ judges blame-review [dir] Analyze current directory
199
+ judges blame-review --since "3 months" Sprint-scoped analysis
200
+ judges blame-review --author "Jane" Author-focused coaching
201
+ judges blame-review --format json JSON output
202
+
203
+ Options:
204
+ [dir] Target directory (default: .)
205
+ --since <period> Only consider commits since period
206
+ --author <name> Filter to specific author
207
+ --format json JSON output
208
+ --help, -h Show this help
209
+
210
+ Attributes findings to the commits and authors that introduced them.
211
+ Shows tech debt accrual timeline and author coaching summaries.
212
+ `);
213
+ return;
214
+ }
215
+ if (!isGitRepo()) {
216
+ console.error("Error: Not inside a git repository.");
217
+ process.exitCode = 1;
218
+ return;
219
+ }
220
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
221
+ const since = argv.find((_a, i) => argv[i - 1] === "--since");
222
+ const authorFilter = argv.find((_a, i) => argv[i - 1] === "--author");
223
+ const dir = argv.find((a) => !a.startsWith("-") &&
224
+ argv.indexOf(a) > 0 &&
225
+ argv[argv.indexOf(a) - 1] !== "--format" &&
226
+ argv[argv.indexOf(a) - 1] !== "--since" &&
227
+ argv[argv.indexOf(a) - 1] !== "--author") || ".";
228
+ const files = collectSourceFiles(dir);
229
+ if (files.length === 0) {
230
+ console.log("No source files found.");
231
+ return;
232
+ }
233
+ const report = analyzeBlame(files, since, authorFilter);
234
+ if (format === "json") {
235
+ console.log(JSON.stringify(report, null, 2));
236
+ return;
237
+ }
238
+ console.log(`\n Blame Review\n ─────────────────────────────`);
239
+ console.log(` Files scanned: ${files.length}`);
240
+ console.log(` Findings attributed: ${report.totalFindings}`);
241
+ console.log(` Average age: ${report.averageAgeDays} days`);
242
+ if (report.oldestFinding) {
243
+ console.log(`\n Oldest finding:`);
244
+ console.log(` ${report.oldestFinding.finding} (${report.oldestFinding.severity}) — ${report.oldestFinding.date} by ${report.oldestFinding.author} (${report.oldestFinding.ageInDays} days)`);
245
+ }
246
+ if (report.newestFinding) {
247
+ console.log(`\n Newest finding:`);
248
+ console.log(` ${report.newestFinding.finding} (${report.newestFinding.severity}) — ${report.newestFinding.date} by ${report.newestFinding.author} (${report.newestFinding.ageInDays} days)`);
249
+ }
250
+ if (report.authorSummaries.length > 0) {
251
+ console.log(`\n Author Attribution:`);
252
+ for (const author of report.authorSummaries) {
253
+ const breakdown = [];
254
+ if (author.critical > 0)
255
+ breakdown.push(`${author.critical} critical`);
256
+ if (author.high > 0)
257
+ breakdown.push(`${author.high} high`);
258
+ if (author.medium > 0)
259
+ breakdown.push(`${author.medium} medium`);
260
+ if (author.low > 0)
261
+ breakdown.push(`${author.low} low`);
262
+ console.log(` ${author.author}: ${author.totalFindings} findings (${breakdown.join(", ")})`);
263
+ }
264
+ }
265
+ if (report.totalFindings === 0) {
266
+ console.log("\n ✅ No pattern-based findings detected in scanned files.");
267
+ }
268
+ console.log();
269
+ }
270
+ //# sourceMappingURL=blame-review.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blame-review.js","sourceRoot":"","sources":["../../src/commands/blame-review.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Context blind — flag when AI reinvents utilities already present in the codebase.
3
+ */
4
+ export declare function runContextBlind(argv: string[]): void;
5
+ //# sourceMappingURL=context-blind.d.ts.map
@@ -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,5 @@
1
+ /**
2
+ * Evidence-chain — traversable reasoning chain showing exactly why each finding was raised.
3
+ */
4
+ export declare function runEvidenceChain(argv: string[]): void;
5
+ //# sourceMappingURL=evidence-chain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence-chain.d.ts","sourceRoot":"","sources":["../../src/commands/evidence-chain.ts"],"names":[],"mappings":"AAAA;;GAEG;AAqRH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA2ErD"}