@kevinrabun/judges 3.61.0 → 3.62.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 (42) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +56 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/batch-review.d.ts +5 -0
  6. package/dist/commands/batch-review.d.ts.map +1 -0
  7. package/dist/commands/batch-review.js +181 -0
  8. package/dist/commands/batch-review.js.map +1 -0
  9. package/dist/commands/custom-rule.d.ts +5 -0
  10. package/dist/commands/custom-rule.d.ts.map +1 -0
  11. package/dist/commands/custom-rule.js +211 -0
  12. package/dist/commands/custom-rule.js.map +1 -0
  13. package/dist/commands/diff-review.d.ts +5 -0
  14. package/dist/commands/diff-review.d.ts.map +1 -0
  15. package/dist/commands/diff-review.js +191 -0
  16. package/dist/commands/diff-review.js.map +1 -0
  17. package/dist/commands/focus-area.d.ts +6 -0
  18. package/dist/commands/focus-area.d.ts.map +1 -0
  19. package/dist/commands/focus-area.js +193 -0
  20. package/dist/commands/focus-area.js.map +1 -0
  21. package/dist/commands/review-compare.d.ts +5 -0
  22. package/dist/commands/review-compare.d.ts.map +1 -0
  23. package/dist/commands/review-compare.js +201 -0
  24. package/dist/commands/review-compare.js.map +1 -0
  25. package/dist/commands/review-explain.d.ts +6 -0
  26. package/dist/commands/review-explain.d.ts.map +1 -0
  27. package/dist/commands/review-explain.js +195 -0
  28. package/dist/commands/review-explain.js.map +1 -0
  29. package/dist/commands/review-gate.d.ts +5 -0
  30. package/dist/commands/review-gate.d.ts.map +1 -0
  31. package/dist/commands/review-gate.js +213 -0
  32. package/dist/commands/review-gate.js.map +1 -0
  33. package/dist/commands/severity-tune.d.ts +5 -0
  34. package/dist/commands/severity-tune.d.ts.map +1 -0
  35. package/dist/commands/severity-tune.js +209 -0
  36. package/dist/commands/severity-tune.js.map +1 -0
  37. package/dist/commands/trend-report.d.ts +5 -0
  38. package/dist/commands/trend-report.d.ts.map +1 -0
  39. package/dist/commands/trend-report.js +149 -0
  40. package/dist/commands/trend-report.js.map +1 -0
  41. package/package.json +1 -1
  42. package/server.json +2 -2
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Batch-review — Parallel review of multiple files with aggregated results.
3
+ */
4
+ import { readFileSync, readdirSync, statSync } from "fs";
5
+ import { join, extname, relative } from "path";
6
+ // ─── Patterns ──────────────────────────────────────────────────────────────
7
+ const BATCH_PATTERNS = [
8
+ {
9
+ name: "hardcoded-secret",
10
+ severity: "critical",
11
+ regex: /(?:password|secret|api_key|token)\s*[:=]\s*["'][^"']{8,}/i,
12
+ },
13
+ { name: "eval-usage", severity: "critical", regex: /\beval\s*\(/ },
14
+ { name: "sql-concat", severity: "critical", regex: /(?:query|execute)\s*\(\s*["'`].*\+/ },
15
+ { name: "xss-risk", severity: "high", regex: /innerHTML\s*=|document\.write\s*\(/ },
16
+ { name: "command-injection", severity: "critical", regex: /exec(?:Sync)?\s*\(\s*`[^`]*\$\{/ },
17
+ { name: "empty-catch", severity: "medium", regex: /catch\s*\([^)]*\)\s*\{\s*\}/ },
18
+ { name: "any-type", severity: "medium", regex: /:\s*any\b/ },
19
+ { name: "unsafe-regex", severity: "high", regex: /new\s+RegExp\s*\([^)]*\+/ },
20
+ { name: "deprecated-api", severity: "medium", regex: /new\s+Buffer\s*\(|\.substr\s*\(/ },
21
+ { name: "console-log", severity: "low", regex: /console\.log\s*\(/ },
22
+ { name: "todo-fixme", severity: "low", regex: /\/\/\s*(?:TODO|FIXME|HACK)\b/i },
23
+ ];
24
+ // ─── Helpers ────────────────────────────────────────────────────────────────
25
+ function collectSourceFiles(dir) {
26
+ const exts = new Set([".ts", ".js", ".tsx", ".jsx", ".py", ".java", ".go", ".rs", ".cs", ".rb", ".php"]);
27
+ const files = [];
28
+ const skipDirs = new Set(["node_modules", ".git", "dist", "build", "coverage", ".next"]);
29
+ function walk(d) {
30
+ let entries;
31
+ try {
32
+ entries = readdirSync(d);
33
+ }
34
+ catch {
35
+ return;
36
+ }
37
+ for (const name of entries) {
38
+ if (skipDirs.has(name))
39
+ continue;
40
+ const full = join(d, name);
41
+ try {
42
+ const st = statSync(full);
43
+ if (st.isDirectory())
44
+ walk(full);
45
+ else if (exts.has(extname(name)))
46
+ files.push(full);
47
+ }
48
+ catch {
49
+ // skip
50
+ }
51
+ }
52
+ }
53
+ walk(dir);
54
+ return files;
55
+ }
56
+ function reviewFile(filePath, baseDir, failSeverity) {
57
+ const relPath = relative(baseDir, filePath);
58
+ const findings = [];
59
+ let content;
60
+ try {
61
+ content = readFileSync(filePath, "utf-8");
62
+ }
63
+ catch {
64
+ return { file: relPath, findings: [], passed: true };
65
+ }
66
+ const lines = content.split("\n");
67
+ for (let i = 0; i < lines.length; i++) {
68
+ for (const pat of BATCH_PATTERNS) {
69
+ if (pat.regex.test(lines[i])) {
70
+ findings.push({
71
+ pattern: pat.name,
72
+ severity: pat.severity,
73
+ line: i + 1,
74
+ content: lines[i].trim().slice(0, 100),
75
+ });
76
+ }
77
+ }
78
+ }
79
+ const severityRank = { critical: 4, high: 3, medium: 2, low: 1 };
80
+ const threshold = severityRank[failSeverity] || 2;
81
+ const hasFailing = findings.some((f) => (severityRank[f.severity] || 0) >= threshold);
82
+ return { file: relPath, findings, passed: !hasFailing };
83
+ }
84
+ // ─── CLI ────────────────────────────────────────────────────────────────────
85
+ export function runBatchReview(argv) {
86
+ if (argv.includes("--help") || argv.includes("-h")) {
87
+ console.log(`
88
+ judges batch-review — Review multiple files with aggregated results
89
+
90
+ Usage:
91
+ judges batch-review [dir] Review all source files
92
+ judges batch-review --fail-on medium Set failure threshold
93
+ judges batch-review --format json JSON output
94
+ judges batch-review --summary Show only summary
95
+
96
+ Options:
97
+ [dir] Target directory (default: .)
98
+ --fail-on <severity> Fail threshold: critical/high/medium/low (default: medium)
99
+ --summary Summary only, no per-file details
100
+ --format json JSON output
101
+ --help, -h Show this help
102
+
103
+ Reviews all source files in a directory and aggregates results. Each file
104
+ gets a pass/fail based on the severity threshold. Exit code 1 if any file fails.
105
+ `);
106
+ return;
107
+ }
108
+ const start = Date.now();
109
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
110
+ const failSeverity = argv.find((_a, i) => argv[i - 1] === "--fail-on") || "medium";
111
+ const summaryOnly = argv.includes("--summary");
112
+ const dir = argv.find((a) => !a.startsWith("-") &&
113
+ a !== "batch-review" &&
114
+ argv[argv.indexOf(a) - 1] !== "--format" &&
115
+ argv[argv.indexOf(a) - 1] !== "--fail-on") || ".";
116
+ const files = collectSourceFiles(dir);
117
+ if (files.length === 0) {
118
+ console.log("No source files found.");
119
+ return;
120
+ }
121
+ const fileResults = files.map((f) => reviewFile(f, dir, failSeverity));
122
+ const duration = Date.now() - start;
123
+ const counts = { critical: 0, high: 0, medium: 0, low: 0 };
124
+ let totalFindings = 0;
125
+ for (const fr of fileResults) {
126
+ for (const f of fr.findings) {
127
+ totalFindings++;
128
+ if (f.severity === "critical")
129
+ counts.critical++;
130
+ else if (f.severity === "high")
131
+ counts.high++;
132
+ else if (f.severity === "medium")
133
+ counts.medium++;
134
+ else
135
+ counts.low++;
136
+ }
137
+ }
138
+ const passedFiles = fileResults.filter((r) => r.passed).length;
139
+ const failedFiles = fileResults.filter((r) => !r.passed).length;
140
+ const result = {
141
+ totalFiles: files.length,
142
+ passedFiles,
143
+ failedFiles,
144
+ totalFindings,
145
+ counts,
146
+ fileResults: summaryOnly ? [] : fileResults.filter((r) => r.findings.length > 0),
147
+ duration,
148
+ };
149
+ if (format === "json") {
150
+ console.log(JSON.stringify(result, null, 2));
151
+ if (failedFiles > 0)
152
+ process.exitCode = 1;
153
+ return;
154
+ }
155
+ const icon = failedFiles === 0 ? "✅" : "❌";
156
+ console.log(`\n Batch Review: ${icon}\n ─────────────────────────────`);
157
+ console.log(` Files: ${passedFiles} passed, ${failedFiles} failed (${files.length} total)`);
158
+ console.log(` Findings: ${totalFindings} (C:${counts.critical} H:${counts.high} M:${counts.medium} L:${counts.low})`);
159
+ console.log(` Duration: ${duration}ms`);
160
+ console.log(` Fail threshold: ${failSeverity}`);
161
+ if (!summaryOnly) {
162
+ const failedResults = fileResults.filter((r) => !r.passed);
163
+ if (failedResults.length > 0) {
164
+ console.log("\n Failed files:");
165
+ for (const fr of failedResults.slice(0, 20)) {
166
+ console.log(` ❌ ${fr.file} (${fr.findings.length} findings)`);
167
+ for (const f of fr.findings.slice(0, 5)) {
168
+ console.log(` [${f.severity}] ${f.pattern} L${f.line}`);
169
+ }
170
+ if (fr.findings.length > 5)
171
+ console.log(` ... +${fr.findings.length - 5} more`);
172
+ }
173
+ if (failedResults.length > 20)
174
+ console.log(` ... +${failedResults.length - 20} more files`);
175
+ }
176
+ }
177
+ console.log();
178
+ if (failedFiles > 0)
179
+ process.exitCode = 1;
180
+ }
181
+ //# sourceMappingURL=batch-review.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch-review.js","sourceRoot":"","sources":["../../src/commands/batch-review.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Custom-rule — Load and run user-defined custom review rules from local config.
3
+ */
4
+ export declare function runCustomRule(argv: string[]): void;
5
+ //# sourceMappingURL=custom-rule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-rule.d.ts","sourceRoot":"","sources":["../../src/commands/custom-rule.ts"],"names":[],"mappings":"AAAA;;GAEG;AAuKH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAoFlD"}
@@ -0,0 +1,211 @@
1
+ /**
2
+ * Custom-rule — Load and run user-defined custom review rules from local config.
3
+ */
4
+ import { readFileSync, existsSync, writeFileSync, readdirSync, statSync } from "fs";
5
+ import { join, extname } from "path";
6
+ // ─── Rule loading ──────────────────────────────────────────────────────────
7
+ function loadCustomRules(configPath) {
8
+ if (!existsSync(configPath))
9
+ return [];
10
+ try {
11
+ const raw = JSON.parse(readFileSync(configPath, "utf-8"));
12
+ if (Array.isArray(raw.rules)) {
13
+ return raw.rules.filter((r) => r.id && r.pattern);
14
+ }
15
+ return [];
16
+ }
17
+ catch {
18
+ return [];
19
+ }
20
+ }
21
+ function defaultRulesTemplate() {
22
+ return {
23
+ rules: [
24
+ {
25
+ id: "no-fixme",
26
+ description: "Disallow FIXME comments in production code",
27
+ severity: "medium",
28
+ pattern: "//\\s*FIXME\\b",
29
+ fileTypes: [".ts", ".js", ".tsx", ".jsx"],
30
+ message: "FIXME comment found — resolve before merging",
31
+ },
32
+ {
33
+ id: "no-console-error",
34
+ description: "Disallow console.error in production code",
35
+ severity: "low",
36
+ pattern: "console\\.error\\s*\\(",
37
+ fileTypes: [".ts", ".js"],
38
+ message: "Use a structured logger instead of console.error",
39
+ },
40
+ {
41
+ id: "no-any-cast",
42
+ description: "Disallow 'as any' type casts",
43
+ severity: "medium",
44
+ pattern: "as\\s+any\\b",
45
+ fileTypes: [".ts", ".tsx"],
46
+ message: "Avoid 'as any' — use proper type assertions or generics",
47
+ },
48
+ ],
49
+ };
50
+ }
51
+ // ─── File collection ───────────────────────────────────────────────────────
52
+ function collectSourceFiles(dir, fileTypes) {
53
+ const files = [];
54
+ const skipDirs = new Set(["node_modules", ".git", "dist", "build", "coverage"]);
55
+ function walk(d) {
56
+ let entries;
57
+ try {
58
+ entries = readdirSync(d);
59
+ }
60
+ catch {
61
+ return;
62
+ }
63
+ for (const name of entries) {
64
+ if (skipDirs.has(name))
65
+ continue;
66
+ const full = join(d, name);
67
+ try {
68
+ const st = statSync(full);
69
+ if (st.isDirectory())
70
+ walk(full);
71
+ else if (fileTypes.has(extname(name)))
72
+ files.push(full);
73
+ }
74
+ catch {
75
+ // skip
76
+ }
77
+ }
78
+ }
79
+ walk(dir);
80
+ return files;
81
+ }
82
+ // ─── Analysis ──────────────────────────────────────────────────────────────
83
+ function runCustomRules(rules, dir) {
84
+ // Collect all relevant file types
85
+ const allFileTypes = new Set();
86
+ for (const rule of rules) {
87
+ for (const ft of rule.fileTypes)
88
+ allFileTypes.add(ft);
89
+ }
90
+ const files = collectSourceFiles(dir, allFileTypes);
91
+ const matches = [];
92
+ for (const filePath of files) {
93
+ const ext = extname(filePath);
94
+ let content;
95
+ try {
96
+ content = readFileSync(filePath, "utf-8");
97
+ }
98
+ catch {
99
+ continue;
100
+ }
101
+ const lines = content.split("\n");
102
+ for (const rule of rules) {
103
+ if (!rule.fileTypes.includes(ext))
104
+ continue;
105
+ let regex;
106
+ try {
107
+ regex = new RegExp(rule.pattern, "i");
108
+ }
109
+ catch {
110
+ continue;
111
+ }
112
+ for (let i = 0; i < lines.length; i++) {
113
+ if (regex.test(lines[i])) {
114
+ matches.push({
115
+ ruleId: rule.id,
116
+ severity: rule.severity || "medium",
117
+ message: rule.message || rule.description,
118
+ file: filePath,
119
+ line: i + 1,
120
+ content: lines[i].trim().slice(0, 100),
121
+ });
122
+ }
123
+ }
124
+ }
125
+ }
126
+ const counts = { critical: 0, high: 0, medium: 0, low: 0, total: matches.length };
127
+ for (const m of matches) {
128
+ if (m.severity === "critical")
129
+ counts.critical++;
130
+ else if (m.severity === "high")
131
+ counts.high++;
132
+ else if (m.severity === "medium")
133
+ counts.medium++;
134
+ else
135
+ counts.low++;
136
+ }
137
+ return { rulesLoaded: rules.length, filesScanned: files.length, matches, counts };
138
+ }
139
+ // ─── CLI ────────────────────────────────────────────────────────────────────
140
+ export function runCustomRule(argv) {
141
+ if (argv.includes("--help") || argv.includes("-h")) {
142
+ console.log(`
143
+ judges custom-rule — Load and run user-defined custom review rules
144
+
145
+ Usage:
146
+ judges custom-rule [dir] Run custom rules on directory
147
+ judges custom-rule init Create template custom-rules.json
148
+ judges custom-rule --config rules.json Use specific config file
149
+ judges custom-rule --format json JSON output
150
+
151
+ Options:
152
+ [dir] Target directory (default: .)
153
+ init Create a template custom-rules.json
154
+ --config <path> Path to custom rules file (default: custom-rules.json)
155
+ --format json JSON output
156
+ --help, -h Show this help
157
+
158
+ Custom rules are defined in a JSON file with pattern (regex), severity,
159
+ file types, and a message. Rules are applied to matching files locally.
160
+ `);
161
+ return;
162
+ }
163
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
164
+ const configPath = argv.find((_a, i) => argv[i - 1] === "--config") || "custom-rules.json";
165
+ // Check for init subcommand
166
+ const hasInit = argv.some((a) => a === "init" && !argv[argv.indexOf(a) - 1]?.startsWith("--"));
167
+ if (hasInit) {
168
+ if (existsSync(configPath)) {
169
+ console.error(`Error: ${configPath} already exists.`);
170
+ process.exitCode = 1;
171
+ return;
172
+ }
173
+ writeFileSync(configPath, JSON.stringify(defaultRulesTemplate(), null, 2), "utf-8");
174
+ console.log(`Created ${configPath} with example rules. Edit to add your own.`);
175
+ return;
176
+ }
177
+ const dir = argv.find((a) => !a.startsWith("-") &&
178
+ a !== "custom-rule" &&
179
+ a !== "init" &&
180
+ argv[argv.indexOf(a) - 1] !== "--format" &&
181
+ argv[argv.indexOf(a) - 1] !== "--config") || ".";
182
+ const rules = loadCustomRules(configPath);
183
+ if (rules.length === 0) {
184
+ console.log(`No custom rules found in ${configPath}. Run 'judges custom-rule init' to create a template.`);
185
+ return;
186
+ }
187
+ const result = runCustomRules(rules, dir);
188
+ if (format === "json") {
189
+ console.log(JSON.stringify(result, null, 2));
190
+ return;
191
+ }
192
+ console.log(`\n Custom Rule Review\n ─────────────────────────────`);
193
+ console.log(` Rules loaded: ${result.rulesLoaded}`);
194
+ console.log(` Files scanned: ${result.filesScanned}`);
195
+ console.log(` Matches: ${result.counts.total} (C:${result.counts.critical} H:${result.counts.high} M:${result.counts.medium} L:${result.counts.low})`);
196
+ if (result.matches.length > 0) {
197
+ console.log("\n Matches:");
198
+ for (const m of result.matches.slice(0, 30)) {
199
+ const sevIcon = m.severity === "critical" ? "🔴" : m.severity === "high" ? "🟠" : m.severity === "medium" ? "🟡" : "🔵";
200
+ console.log(` ${sevIcon} [${m.ruleId}] ${m.message}`);
201
+ console.log(` ${m.file}:${m.line}`);
202
+ }
203
+ if (result.matches.length > 30)
204
+ console.log(` ... +${result.matches.length - 30} more`);
205
+ }
206
+ else {
207
+ console.log("\n ✅ No custom rule violations found.");
208
+ }
209
+ console.log();
210
+ }
211
+ //# sourceMappingURL=custom-rule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-rule.js","sourceRoot":"","sources":["../../src/commands/custom-rule.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Diff-review — Review only changed lines in a diff/patch rather than full files.
3
+ */
4
+ export declare function runDiffReview(argv: string[]): void;
5
+ //# sourceMappingURL=diff-review.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-review.d.ts","sourceRoot":"","sources":["../../src/commands/diff-review.ts"],"names":[],"mappings":"AAAA;;GAEG;AAiJH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAuFlD"}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Diff-review — Review only changed lines in a diff/patch rather than full files.
3
+ */
4
+ import { readFileSync } from "fs";
5
+ import { execSync } from "child_process";
6
+ // ─── Patterns ──────────────────────────────────────────────────────────────
7
+ const DIFF_PATTERNS = [
8
+ {
9
+ name: "hardcoded-secret",
10
+ severity: "critical",
11
+ regex: /(?:password|secret|api_key|token)\s*[:=]\s*["'][^"']{8,}/i,
12
+ },
13
+ { name: "eval-usage", severity: "critical", regex: /\beval\s*\(/ },
14
+ { name: "sql-concat", severity: "critical", regex: /(?:query|execute)\s*\(\s*["'`].*\+/ },
15
+ { name: "xss-risk", severity: "high", regex: /innerHTML\s*=|document\.write\s*\(/ },
16
+ { name: "command-injection", severity: "critical", regex: /exec(?:Sync)?\s*\(\s*`[^`]*\$\{/ },
17
+ { name: "empty-catch", severity: "medium", regex: /catch\s*\([^)]*\)\s*\{\s*\}/ },
18
+ { name: "any-type", severity: "medium", regex: /:\s*any\b/ },
19
+ { name: "unsafe-regex", severity: "high", regex: /new\s+RegExp\s*\([^)]*\+/ },
20
+ { name: "missing-await", severity: "high", regex: /(?:return|=)\s+(?!await\b)[a-zA-Z]+\.(then|catch)\s*\(/ },
21
+ { name: "deprecated-api", severity: "medium", regex: /new\s+Buffer\s*\(|\.substr\s*\(/ },
22
+ { name: "console-log", severity: "low", regex: /console\.log\s*\(/ },
23
+ { name: "todo-fixme", severity: "low", regex: /\/\/\s*(?:TODO|FIXME|HACK)\b/i },
24
+ ];
25
+ // ─── Diff parsing ──────────────────────────────────────────────────────────
26
+ function parseDiff(diffText) {
27
+ const hunks = [];
28
+ const lines = diffText.split("\n");
29
+ let currentFile = "";
30
+ let hunkStart = 0;
31
+ let hunkLines = [];
32
+ let lineNum = 0;
33
+ for (const line of lines) {
34
+ // Detect file header
35
+ const fileMatch = /^\+\+\+\s+b\/(.+)/.exec(line);
36
+ if (fileMatch) {
37
+ currentFile = fileMatch[1];
38
+ continue;
39
+ }
40
+ // Detect hunk header
41
+ const hunkMatch = /^@@\s+-\d+(?:,\d+)?\s+\+(\d+)(?:,(\d+))?\s+@@/.exec(line);
42
+ if (hunkMatch) {
43
+ // Save previous hunk
44
+ if (hunkLines.length > 0 && currentFile) {
45
+ hunks.push({
46
+ file: currentFile,
47
+ startLine: hunkStart,
48
+ lineCount: hunkLines.length,
49
+ content: hunkLines.join("\n"),
50
+ });
51
+ }
52
+ hunkStart = parseInt(hunkMatch[1], 10);
53
+ lineNum = hunkStart;
54
+ hunkLines = [];
55
+ continue;
56
+ }
57
+ // Only analyze added lines (starting with +)
58
+ if (line.startsWith("+") && !line.startsWith("+++")) {
59
+ hunkLines.push(`${lineNum}:${line.slice(1)}`);
60
+ lineNum++;
61
+ }
62
+ else if (!line.startsWith("-")) {
63
+ lineNum++;
64
+ }
65
+ }
66
+ // Save last hunk
67
+ if (hunkLines.length > 0 && currentFile) {
68
+ hunks.push({ file: currentFile, startLine: hunkStart, lineCount: hunkLines.length, content: hunkLines.join("\n") });
69
+ }
70
+ return hunks;
71
+ }
72
+ function analyzeHunks(hunks) {
73
+ const findings = [];
74
+ let totalLines = 0;
75
+ for (const hunk of hunks) {
76
+ const lines = hunk.content.split("\n");
77
+ totalLines += lines.length;
78
+ for (const line of lines) {
79
+ const lineMatch = /^(\d+):(.*)/.exec(line);
80
+ if (!lineMatch)
81
+ continue;
82
+ const lineNum = parseInt(lineMatch[1], 10);
83
+ const lineContent = lineMatch[2];
84
+ for (const pat of DIFF_PATTERNS) {
85
+ if (pat.regex.test(lineContent)) {
86
+ findings.push({
87
+ pattern: pat.name,
88
+ severity: pat.severity,
89
+ file: hunk.file,
90
+ line: lineNum,
91
+ content: lineContent.trim(),
92
+ });
93
+ }
94
+ }
95
+ }
96
+ }
97
+ const counts = { critical: 0, high: 0, medium: 0, low: 0, total: findings.length };
98
+ for (const f of findings) {
99
+ if (f.severity === "critical")
100
+ counts.critical++;
101
+ else if (f.severity === "high")
102
+ counts.high++;
103
+ else if (f.severity === "medium")
104
+ counts.medium++;
105
+ else
106
+ counts.low++;
107
+ }
108
+ return { hunksAnalyzed: hunks.length, linesAnalyzed: totalLines, findings, counts };
109
+ }
110
+ // ─── CLI ────────────────────────────────────────────────────────────────────
111
+ export function runDiffReview(argv) {
112
+ if (argv.includes("--help") || argv.includes("-h")) {
113
+ console.log(`
114
+ judges diff-review — Review only changed lines in a diff
115
+
116
+ Usage:
117
+ judges diff-review Review staged changes (git diff --cached)
118
+ judges diff-review --base main Review changes vs a branch
119
+ judges diff-review --file patch.diff Review a diff file
120
+ judges diff-review --format json JSON output
121
+
122
+ Options:
123
+ --base <ref> Compare against branch/commit (default: staged changes)
124
+ --file <path> Read diff from a file instead of git
125
+ --format json JSON output
126
+ --help, -h Show this help
127
+
128
+ Focuses review effort on only the changed lines, providing faster and
129
+ more relevant feedback for pull requests and commits.
130
+ `);
131
+ return;
132
+ }
133
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
134
+ const base = argv.find((_a, i) => argv[i - 1] === "--base");
135
+ const diffFile = argv.find((_a, i) => argv[i - 1] === "--file");
136
+ let diffText;
137
+ if (diffFile) {
138
+ try {
139
+ diffText = readFileSync(diffFile, "utf-8");
140
+ }
141
+ catch {
142
+ console.error(`Error: Cannot read diff file '${diffFile}'.`);
143
+ process.exitCode = 1;
144
+ return;
145
+ }
146
+ }
147
+ else {
148
+ try {
149
+ const gitCmd = base ? `git diff ${base}...HEAD` : "git diff --cached";
150
+ diffText = execSync(gitCmd, {
151
+ stdio: ["pipe", "pipe", "pipe"],
152
+ timeout: 15000,
153
+ maxBuffer: 10 * 1024 * 1024,
154
+ }).toString();
155
+ }
156
+ catch {
157
+ console.error("Error: Failed to get git diff. Are you in a git repository?");
158
+ process.exitCode = 1;
159
+ return;
160
+ }
161
+ }
162
+ if (!diffText.trim()) {
163
+ console.log("No changes to review.");
164
+ return;
165
+ }
166
+ const hunks = parseDiff(diffText);
167
+ const result = analyzeHunks(hunks);
168
+ if (format === "json") {
169
+ console.log(JSON.stringify(result, null, 2));
170
+ return;
171
+ }
172
+ console.log(`\n Diff Review\n ─────────────────────────────`);
173
+ console.log(` Hunks analyzed: ${result.hunksAnalyzed}`);
174
+ console.log(` Lines analyzed: ${result.linesAnalyzed}`);
175
+ console.log(` Findings: ${result.counts.total} (C:${result.counts.critical} H:${result.counts.high} M:${result.counts.medium} L:${result.counts.low})`);
176
+ if (result.findings.length > 0) {
177
+ console.log("\n Findings in changed code:");
178
+ for (const f of result.findings.slice(0, 30)) {
179
+ const sevIcon = f.severity === "critical" ? "🔴" : f.severity === "high" ? "🟠" : f.severity === "medium" ? "🟡" : "🔵";
180
+ console.log(` ${sevIcon} [${f.severity}] ${f.pattern} — ${f.file}:${f.line}`);
181
+ }
182
+ if (result.findings.length > 30) {
183
+ console.log(` ... and ${result.findings.length - 30} more`);
184
+ }
185
+ }
186
+ else {
187
+ console.log("\n ✅ No issues found in changed code.");
188
+ }
189
+ console.log();
190
+ }
191
+ //# sourceMappingURL=diff-review.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-review.js","sourceRoot":"","sources":["../../src/commands/diff-review.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Focus-area — Identify high-risk areas that need the most review attention
3
+ * based on code complexity and pattern density.
4
+ */
5
+ export declare function runFocusArea(argv: string[]): void;
6
+ //# sourceMappingURL=focus-area.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"focus-area.d.ts","sourceRoot":"","sources":["../../src/commands/focus-area.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAsKH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAoEjD"}