@kevinrabun/judges 3.57.0 → 3.59.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/api-misuse.d.ts +5 -0
- package/dist/commands/api-misuse.d.ts.map +1 -0
- package/dist/commands/api-misuse.js +261 -0
- package/dist/commands/api-misuse.js.map +1 -0
- package/dist/commands/assertion-density.d.ts +5 -0
- package/dist/commands/assertion-density.d.ts.map +1 -0
- package/dist/commands/assertion-density.js +264 -0
- package/dist/commands/assertion-density.js.map +1 -0
- package/dist/commands/async-safety.d.ts +5 -0
- package/dist/commands/async-safety.d.ts.map +1 -0
- package/dist/commands/async-safety.js +267 -0
- package/dist/commands/async-safety.js.map +1 -0
- package/dist/commands/clone-detect.d.ts +5 -0
- package/dist/commands/clone-detect.d.ts.map +1 -0
- package/dist/commands/clone-detect.js +233 -0
- package/dist/commands/clone-detect.js.map +1 -0
- package/dist/commands/completion-audit.d.ts +5 -0
- package/dist/commands/completion-audit.d.ts.map +1 -0
- package/dist/commands/completion-audit.js +297 -0
- package/dist/commands/completion-audit.js.map +1 -0
- package/dist/commands/contract-verify.d.ts +5 -0
- package/dist/commands/contract-verify.d.ts.map +1 -0
- package/dist/commands/contract-verify.js +317 -0
- package/dist/commands/contract-verify.js.map +1 -0
- package/dist/commands/cross-file-consistency.d.ts +5 -0
- package/dist/commands/cross-file-consistency.d.ts.map +1 -0
- package/dist/commands/cross-file-consistency.js +255 -0
- package/dist/commands/cross-file-consistency.js.map +1 -0
- package/dist/commands/dead-code-detect.d.ts +5 -0
- package/dist/commands/dead-code-detect.d.ts.map +1 -0
- package/dist/commands/dead-code-detect.js +256 -0
- package/dist/commands/dead-code-detect.js.map +1 -0
- package/dist/commands/encoding-safety.d.ts +5 -0
- package/dist/commands/encoding-safety.d.ts.map +1 -0
- package/dist/commands/encoding-safety.js +276 -0
- package/dist/commands/encoding-safety.js.map +1 -0
- package/dist/commands/example-leak.d.ts +5 -0
- package/dist/commands/example-leak.d.ts.map +1 -0
- package/dist/commands/example-leak.js +233 -0
- package/dist/commands/example-leak.js.map +1 -0
- package/dist/commands/input-guard.d.ts +5 -0
- package/dist/commands/input-guard.d.ts.map +1 -0
- package/dist/commands/input-guard.js +256 -0
- package/dist/commands/input-guard.js.map +1 -0
- package/dist/commands/logic-lint.d.ts +5 -0
- package/dist/commands/logic-lint.d.ts.map +1 -0
- package/dist/commands/logic-lint.js +256 -0
- package/dist/commands/logic-lint.js.map +1 -0
- package/dist/commands/phantom-import.d.ts +5 -0
- package/dist/commands/phantom-import.d.ts.map +1 -0
- package/dist/commands/phantom-import.js +261 -0
- package/dist/commands/phantom-import.js.map +1 -0
- package/dist/commands/review-focus.d.ts +5 -0
- package/dist/commands/review-focus.d.ts.map +1 -0
- package/dist/commands/review-focus.js +197 -0
- package/dist/commands/review-focus.js.map +1 -0
- package/dist/commands/spec-conform.d.ts +5 -0
- package/dist/commands/spec-conform.d.ts.map +1 -0
- package/dist/commands/spec-conform.js +305 -0
- package/dist/commands/spec-conform.js.map +1 -0
- package/dist/commands/state-integrity.d.ts +5 -0
- package/dist/commands/state-integrity.d.ts.map +1 -0
- package/dist/commands/state-integrity.js +284 -0
- package/dist/commands/state-integrity.js.map +1 -0
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phantom import — detect hallucinated imports, non-existent modules, and wrong export names.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, readdirSync, statSync, existsSync } from "fs";
|
|
5
|
+
import { join, extname, dirname, resolve } 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
|
+
// ─── Exports Index ──────────────────────────────────────────────────────────
|
|
41
|
+
function buildExportsMap(files) {
|
|
42
|
+
const exports = new Map();
|
|
43
|
+
for (const filepath of files) {
|
|
44
|
+
let content;
|
|
45
|
+
try {
|
|
46
|
+
content = readFileSync(filepath, "utf-8");
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const names = new Set();
|
|
52
|
+
// export function/class/const/let/var/type/interface/enum
|
|
53
|
+
for (const m of content.matchAll(/export\s+(?:default\s+)?(?:function|class|const|let|var|type|interface|enum)\s+(\w+)/g)) {
|
|
54
|
+
names.add(m[1]);
|
|
55
|
+
}
|
|
56
|
+
// export { ... }
|
|
57
|
+
for (const m of content.matchAll(/export\s*\{([^}]+)\}/g)) {
|
|
58
|
+
for (const name of m[1].split(",")) {
|
|
59
|
+
const cleaned = name
|
|
60
|
+
.trim()
|
|
61
|
+
.split(/\s+as\s+/)[0]
|
|
62
|
+
.trim();
|
|
63
|
+
if (cleaned)
|
|
64
|
+
names.add(cleaned);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// export default
|
|
68
|
+
if (/export\s+default\s/.test(content))
|
|
69
|
+
names.add("default");
|
|
70
|
+
exports.set(filepath, names);
|
|
71
|
+
}
|
|
72
|
+
return exports;
|
|
73
|
+
}
|
|
74
|
+
// ─── Analysis ───────────────────────────────────────────────────────────────
|
|
75
|
+
function analyzeFile(filepath, exportsMap, projectDir) {
|
|
76
|
+
const issues = [];
|
|
77
|
+
let content;
|
|
78
|
+
try {
|
|
79
|
+
content = readFileSync(filepath, "utf-8");
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return issues;
|
|
83
|
+
}
|
|
84
|
+
const lines = content.split("\n");
|
|
85
|
+
for (let i = 0; i < lines.length; i++) {
|
|
86
|
+
const line = lines[i];
|
|
87
|
+
// import from relative path
|
|
88
|
+
const relImport = line.match(/import\s+(?:\{[^}]*\}|[\w*]+(?:\s*,\s*\{[^}]*\})?)\s+from\s+['"](\.[^'"]+)['"]/);
|
|
89
|
+
if (relImport) {
|
|
90
|
+
const importPath = relImport[1];
|
|
91
|
+
const dir = dirname(filepath);
|
|
92
|
+
const candidates = [
|
|
93
|
+
resolve(dir, importPath),
|
|
94
|
+
resolve(dir, importPath + ".ts"),
|
|
95
|
+
resolve(dir, importPath + ".tsx"),
|
|
96
|
+
resolve(dir, importPath + ".js"),
|
|
97
|
+
resolve(dir, importPath + ".jsx"),
|
|
98
|
+
resolve(dir, importPath, "index.ts"),
|
|
99
|
+
resolve(dir, importPath, "index.js"),
|
|
100
|
+
];
|
|
101
|
+
const resolved = candidates.find((c) => existsSync(c));
|
|
102
|
+
if (!resolved) {
|
|
103
|
+
issues.push({
|
|
104
|
+
file: filepath,
|
|
105
|
+
line: i + 1,
|
|
106
|
+
issue: "Import resolves to non-existent file",
|
|
107
|
+
severity: "high",
|
|
108
|
+
detail: `\`${importPath}\` does not exist — AI may have hallucinated this module path`,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Check named imports exist in target
|
|
113
|
+
const namedMatch = line.match(/import\s*\{([^}]+)\}\s*from/);
|
|
114
|
+
if (namedMatch) {
|
|
115
|
+
const targetExports = exportsMap.get(resolved);
|
|
116
|
+
if (targetExports) {
|
|
117
|
+
const imported = namedMatch[1]
|
|
118
|
+
.split(",")
|
|
119
|
+
.map((n) => n
|
|
120
|
+
.trim()
|
|
121
|
+
.split(/\s+as\s+/)[0]
|
|
122
|
+
.trim())
|
|
123
|
+
.filter(Boolean);
|
|
124
|
+
for (const name of imported) {
|
|
125
|
+
if (!targetExports.has(name)) {
|
|
126
|
+
issues.push({
|
|
127
|
+
file: filepath,
|
|
128
|
+
line: i + 1,
|
|
129
|
+
issue: "Named import does not exist in target",
|
|
130
|
+
severity: "high",
|
|
131
|
+
detail: `\`${name}\` is not exported from \`${importPath}\` — may be a hallucinated export name`,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Common hallucinated npm packages (AI often invents package names)
|
|
140
|
+
const npmImport = line.match(/import\s+.*\s+from\s+['"]([a-z@][a-z0-9./_-]*)['"]/);
|
|
141
|
+
if (npmImport && !npmImport[1].startsWith(".")) {
|
|
142
|
+
const pkg = npmImport[1]
|
|
143
|
+
.split("/")
|
|
144
|
+
.slice(0, npmImport[1].startsWith("@") ? 2 : 1)
|
|
145
|
+
.join("/");
|
|
146
|
+
// Check if package exists in node_modules
|
|
147
|
+
const nmPath = join(projectDir, "node_modules", pkg);
|
|
148
|
+
if (!existsSync(nmPath)) {
|
|
149
|
+
// Check if it's in package.json
|
|
150
|
+
try {
|
|
151
|
+
const pkgJson = JSON.parse(readFileSync(join(projectDir, "package.json"), "utf-8"));
|
|
152
|
+
const allDeps = { ...pkgJson.dependencies, ...pkgJson.devDependencies, ...pkgJson.peerDependencies };
|
|
153
|
+
if (!allDeps[pkg]) {
|
|
154
|
+
issues.push({
|
|
155
|
+
file: filepath,
|
|
156
|
+
line: i + 1,
|
|
157
|
+
issue: "Import from uninstalled package",
|
|
158
|
+
severity: "high",
|
|
159
|
+
detail: `\`${pkg}\` is not in package.json or node_modules — may be a hallucinated package`,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
/* skip */
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// require() of non-existent relative path
|
|
169
|
+
const requireMatch = line.match(/require\s*\(\s*['"](\.[^'"]+)['"]\s*\)/);
|
|
170
|
+
if (requireMatch) {
|
|
171
|
+
const reqPath = requireMatch[1];
|
|
172
|
+
const dir = dirname(filepath);
|
|
173
|
+
const candidates = [
|
|
174
|
+
resolve(dir, reqPath),
|
|
175
|
+
resolve(dir, reqPath + ".ts"),
|
|
176
|
+
resolve(dir, reqPath + ".js"),
|
|
177
|
+
resolve(dir, reqPath + ".json"),
|
|
178
|
+
resolve(dir, reqPath, "index.js"),
|
|
179
|
+
];
|
|
180
|
+
if (!candidates.some((c) => existsSync(c))) {
|
|
181
|
+
issues.push({
|
|
182
|
+
file: filepath,
|
|
183
|
+
line: i + 1,
|
|
184
|
+
issue: "require() of non-existent module",
|
|
185
|
+
severity: "high",
|
|
186
|
+
detail: `\`${reqPath}\` does not resolve to any file — may be hallucinated`,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// Importing from deprecated / removed Node.js APIs
|
|
191
|
+
const deprecatedImport = line.match(/(?:import|require)\s*(?:\(?\s*['"])(sys|_linklist|constants|punycode|domain|v8\/tools|node:sys)['"](?:\))?/);
|
|
192
|
+
if (deprecatedImport) {
|
|
193
|
+
issues.push({
|
|
194
|
+
file: filepath,
|
|
195
|
+
line: i + 1,
|
|
196
|
+
issue: "Import of deprecated Node.js module",
|
|
197
|
+
severity: "medium",
|
|
198
|
+
detail: `\`${deprecatedImport[1]}\` is deprecated or removed — AI may be referencing outdated API`,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return issues;
|
|
203
|
+
}
|
|
204
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
205
|
+
export function runPhantomImport(argv) {
|
|
206
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
207
|
+
console.log(`
|
|
208
|
+
judges phantom-import — Detect hallucinated imports and non-existent modules
|
|
209
|
+
|
|
210
|
+
Usage:
|
|
211
|
+
judges phantom-import [dir]
|
|
212
|
+
judges phantom-import src/ --format json
|
|
213
|
+
|
|
214
|
+
Options:
|
|
215
|
+
[dir] Directory to scan (default: .)
|
|
216
|
+
--format json JSON output
|
|
217
|
+
--help, -h Show this help
|
|
218
|
+
|
|
219
|
+
Checks: non-existent relative imports, hallucinated named exports, uninstalled packages,
|
|
220
|
+
deprecated Node.js modules, require() of missing files.
|
|
221
|
+
`);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
225
|
+
const dir = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0) || ".";
|
|
226
|
+
const projectDir = resolve(dir);
|
|
227
|
+
const files = collectFiles(dir);
|
|
228
|
+
const exportsMap = buildExportsMap(files);
|
|
229
|
+
const allIssues = [];
|
|
230
|
+
for (const f of files)
|
|
231
|
+
allIssues.push(...analyzeFile(f, exportsMap, projectDir));
|
|
232
|
+
const highCount = allIssues.filter((i) => i.severity === "high").length;
|
|
233
|
+
const medCount = allIssues.filter((i) => i.severity === "medium").length;
|
|
234
|
+
const score = Math.max(0, 100 - highCount * 15 - medCount * 5);
|
|
235
|
+
if (format === "json") {
|
|
236
|
+
console.log(JSON.stringify({
|
|
237
|
+
issues: allIssues,
|
|
238
|
+
score,
|
|
239
|
+
summary: { high: highCount, medium: medCount, total: allIssues.length },
|
|
240
|
+
timestamp: new Date().toISOString(),
|
|
241
|
+
}, null, 2));
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
const badge = score >= 80 ? "✅ CLEAN" : score >= 50 ? "⚠️ SUSPECT" : "❌ PHANTOMS";
|
|
245
|
+
console.log(`\n Phantom Import: ${badge} (${score}/100)\n ─────────────────────────────`);
|
|
246
|
+
if (allIssues.length === 0) {
|
|
247
|
+
console.log(" No phantom imports detected.\n");
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
for (const issue of allIssues.slice(0, 25)) {
|
|
251
|
+
const icon = issue.severity === "high" ? "🔴" : issue.severity === "medium" ? "🟡" : "🔵";
|
|
252
|
+
console.log(` ${icon} ${issue.issue}`);
|
|
253
|
+
console.log(` ${issue.file}:${issue.line}`);
|
|
254
|
+
console.log(` ${issue.detail}`);
|
|
255
|
+
}
|
|
256
|
+
if (allIssues.length > 25)
|
|
257
|
+
console.log(` ... and ${allIssues.length - 25} more`);
|
|
258
|
+
console.log(`\n Total: ${allIssues.length} | High: ${highCount} | Medium: ${medCount} | Score: ${score}/100\n`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
//# sourceMappingURL=phantom-import.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phantom-import.js","sourceRoot":"","sources":["../../src/commands/phantom-import.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-focus.d.ts","sourceRoot":"","sources":["../../src/commands/review-focus.ts"],"names":[],"mappings":"AAAA;;GAEG;AA6JH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAuEnD"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Review focus — prioritize review attention for AI-generated changes.
|
|
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", ".py", ".java", ".go", ".rs", ".cs"]);
|
|
8
|
+
function collectFiles(dir, max = 300) {
|
|
9
|
+
const files = [];
|
|
10
|
+
function walk(d) {
|
|
11
|
+
if (files.length >= max)
|
|
12
|
+
return;
|
|
13
|
+
let entries;
|
|
14
|
+
try {
|
|
15
|
+
entries = readdirSync(d);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
for (const e of entries) {
|
|
21
|
+
if (files.length >= max)
|
|
22
|
+
return;
|
|
23
|
+
if (e.startsWith(".") || e === "node_modules" || e === "dist" || e === "build")
|
|
24
|
+
continue;
|
|
25
|
+
const full = join(d, e);
|
|
26
|
+
try {
|
|
27
|
+
if (statSync(full).isDirectory())
|
|
28
|
+
walk(full);
|
|
29
|
+
else if (CODE_EXTS.has(extname(full)))
|
|
30
|
+
files.push(full);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
/* skip */
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
walk(dir);
|
|
38
|
+
return files;
|
|
39
|
+
}
|
|
40
|
+
// ─── Risk Analysis ──────────────────────────────────────────────────────────
|
|
41
|
+
function analyzeFileRisk(filepath) {
|
|
42
|
+
let content;
|
|
43
|
+
try {
|
|
44
|
+
content = readFileSync(filepath, "utf-8");
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return { file: filepath, priority: "low", score: 0, reasons: ["Could not read file"] };
|
|
48
|
+
}
|
|
49
|
+
const reasons = [];
|
|
50
|
+
let riskScore = 0;
|
|
51
|
+
const fname = basename(filepath).toLowerCase();
|
|
52
|
+
// Security-sensitive patterns
|
|
53
|
+
if (/(?:auth|login|session|token|jwt|oauth|password|credential|secret|crypto|encrypt|decrypt|hash)/i.test(fname)) {
|
|
54
|
+
riskScore += 30;
|
|
55
|
+
reasons.push("Security-sensitive filename");
|
|
56
|
+
}
|
|
57
|
+
if (/(?:sql|exec|spawn|eval|innerHTML|dangerouslySetInnerHTML)/.test(content)) {
|
|
58
|
+
riskScore += 25;
|
|
59
|
+
reasons.push("Contains dangerous operations (sql/exec/eval/innerHTML)");
|
|
60
|
+
}
|
|
61
|
+
// Data mutation
|
|
62
|
+
if (/(?:DELETE|INSERT|UPDATE|DROP|TRUNCATE)\s/i.test(content)) {
|
|
63
|
+
riskScore += 20;
|
|
64
|
+
reasons.push("Contains data mutation SQL statements");
|
|
65
|
+
}
|
|
66
|
+
// Payment/financial
|
|
67
|
+
if (/(?:payment|billing|invoice|charge|refund|stripe|paypal|transaction)/i.test(content)) {
|
|
68
|
+
riskScore += 25;
|
|
69
|
+
reasons.push("Payment/financial logic");
|
|
70
|
+
}
|
|
71
|
+
// External API calls
|
|
72
|
+
const apiCallCount = (content.match(/(?:fetch|axios|http\.(?:get|post|put|delete)|request\()/g) || []).length;
|
|
73
|
+
if (apiCallCount > 0) {
|
|
74
|
+
riskScore += apiCallCount * 5;
|
|
75
|
+
reasons.push(`${apiCallCount} external API calls`);
|
|
76
|
+
}
|
|
77
|
+
// Complexity indicators
|
|
78
|
+
const lines = content.split("\n");
|
|
79
|
+
const lineCount = lines.length;
|
|
80
|
+
if (lineCount > 300) {
|
|
81
|
+
riskScore += 10;
|
|
82
|
+
reasons.push(`Large file (${lineCount} lines)`);
|
|
83
|
+
}
|
|
84
|
+
// Deep nesting
|
|
85
|
+
let maxDepth = 0;
|
|
86
|
+
let depth = 0;
|
|
87
|
+
for (const line of lines) {
|
|
88
|
+
for (const ch of line) {
|
|
89
|
+
if (ch === "{")
|
|
90
|
+
depth++;
|
|
91
|
+
if (ch === "}")
|
|
92
|
+
depth--;
|
|
93
|
+
if (depth > maxDepth)
|
|
94
|
+
maxDepth = depth;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (maxDepth > 5) {
|
|
98
|
+
riskScore += 10;
|
|
99
|
+
reasons.push(`Deep nesting (${maxDepth} levels)`);
|
|
100
|
+
}
|
|
101
|
+
// Error handling density
|
|
102
|
+
const tryCatchCount = (content.match(/try\s*\{/g) || []).length;
|
|
103
|
+
const funcCount = (content.match(/(?:function|=>)\s*[({]/g) || []).length;
|
|
104
|
+
if (funcCount > 3 && tryCatchCount < funcCount * 0.2) {
|
|
105
|
+
riskScore += 5;
|
|
106
|
+
reasons.push("Low error handling coverage");
|
|
107
|
+
}
|
|
108
|
+
// State management
|
|
109
|
+
if (/(?:useState|useReducer|createStore|createSlice|vuex|pinia)/i.test(content)) {
|
|
110
|
+
riskScore += 10;
|
|
111
|
+
reasons.push("Contains state management logic");
|
|
112
|
+
}
|
|
113
|
+
// Database operations
|
|
114
|
+
if (/(?:prisma|sequelize|typeorm|mongoose|knex|drizzle|\.query\(|\.execute\()/i.test(content)) {
|
|
115
|
+
riskScore += 15;
|
|
116
|
+
reasons.push("Database operations");
|
|
117
|
+
}
|
|
118
|
+
// Middleware / interceptors
|
|
119
|
+
if (/(?:middleware|interceptor|guard|pipe|filter)/i.test(fname)) {
|
|
120
|
+
riskScore += 15;
|
|
121
|
+
reasons.push("Middleware/interceptor (cross-cutting concern)");
|
|
122
|
+
}
|
|
123
|
+
// Route definitions
|
|
124
|
+
const routeCount = (content.match(/\.(get|post|put|patch|delete|use)\s*\(\s*['"]?\//g) || []).length;
|
|
125
|
+
if (routeCount > 0) {
|
|
126
|
+
riskScore += routeCount * 3;
|
|
127
|
+
reasons.push(`${routeCount} route definitions`);
|
|
128
|
+
}
|
|
129
|
+
// Configuration / environment
|
|
130
|
+
if (/(?:config|env|settings|options)/i.test(fname)) {
|
|
131
|
+
riskScore += 10;
|
|
132
|
+
reasons.push("Configuration file");
|
|
133
|
+
}
|
|
134
|
+
const priority = riskScore >= 50 ? "critical" : riskScore >= 30 ? "high" : riskScore >= 15 ? "medium" : "low";
|
|
135
|
+
return { file: filepath, priority, score: Math.min(100, riskScore), reasons };
|
|
136
|
+
}
|
|
137
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
138
|
+
export function runReviewFocus(argv) {
|
|
139
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
140
|
+
console.log(`
|
|
141
|
+
judges review-focus — Prioritize review attention for AI-generated changes
|
|
142
|
+
|
|
143
|
+
Usage:
|
|
144
|
+
judges review-focus [dir]
|
|
145
|
+
judges review-focus src/ --format json
|
|
146
|
+
|
|
147
|
+
Options:
|
|
148
|
+
[dir] Directory to scan (default: .)
|
|
149
|
+
--format json JSON output
|
|
150
|
+
--top N Show only top N files (default: 15)
|
|
151
|
+
--help, -h Show this help
|
|
152
|
+
|
|
153
|
+
Risk signals: security-sensitive files, dangerous operations, data mutation,
|
|
154
|
+
payment logic, external APIs, deep nesting, state management, database ops,
|
|
155
|
+
middleware, route definitions, configuration.
|
|
156
|
+
`);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
160
|
+
const dir = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0) || ".";
|
|
161
|
+
const topN = parseInt(argv.find((_a, i) => argv[i - 1] === "--top") || "15", 10);
|
|
162
|
+
const files = collectFiles(dir);
|
|
163
|
+
const allItems = files
|
|
164
|
+
.map((f) => analyzeFileRisk(f))
|
|
165
|
+
.filter((i) => i.score > 0)
|
|
166
|
+
.sort((a, b) => b.score - a.score);
|
|
167
|
+
if (format === "json") {
|
|
168
|
+
console.log(JSON.stringify({
|
|
169
|
+
items: allItems.slice(0, topN),
|
|
170
|
+
totalFiles: files.length,
|
|
171
|
+
scoredFiles: allItems.length,
|
|
172
|
+
timestamp: new Date().toISOString(),
|
|
173
|
+
}, null, 2));
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
console.log(`\n Review Focus — Top ${Math.min(topN, allItems.length)} of ${files.length} files\n ─────────────────────────────`);
|
|
177
|
+
if (allItems.length === 0) {
|
|
178
|
+
console.log(" No high-risk files detected.\n");
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
for (const item of allItems.slice(0, topN)) {
|
|
182
|
+
const icon = item.priority === "critical"
|
|
183
|
+
? "🔴"
|
|
184
|
+
: item.priority === "high"
|
|
185
|
+
? "🟠"
|
|
186
|
+
: item.priority === "medium"
|
|
187
|
+
? "🟡"
|
|
188
|
+
: "🔵";
|
|
189
|
+
console.log(` ${icon} [${item.score}] ${item.file}`);
|
|
190
|
+
console.log(` ${item.reasons.join(" | ")}`);
|
|
191
|
+
}
|
|
192
|
+
const critCount = allItems.filter((i) => i.priority === "critical").length;
|
|
193
|
+
const highCount = allItems.filter((i) => i.priority === "high").length;
|
|
194
|
+
console.log(`\n Critical: ${critCount} | High: ${highCount} | Total scored: ${allItems.length}/${files.length}\n`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=review-focus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-focus.js","sourceRoot":"","sources":["../../src/commands/review-focus.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec-conform.d.ts","sourceRoot":"","sources":["../../src/commands/spec-conform.ts"],"names":[],"mappings":"AAAA;;GAEG;AA6RH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAkEnD"}
|