@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,5 @@
1
+ /**
2
+ * Review-gate — CI/CD quality gate with configurable pass/fail thresholds.
3
+ */
4
+ export declare function runReviewGate(argv: string[]): void;
5
+ //# sourceMappingURL=review-gate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-gate.d.ts","sourceRoot":"","sources":["../../src/commands/review-gate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAoKH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAoFlD"}
@@ -0,0 +1,213 @@
1
+ /**
2
+ * Review-gate — CI/CD quality gate with configurable pass/fail thresholds.
3
+ */
4
+ import { readFileSync, readdirSync, statSync } from "fs";
5
+ import { join, extname } from "path";
6
+ // ─── Default thresholds ────────────────────────────────────────────────────
7
+ function defaultConfig() {
8
+ return {
9
+ maxCritical: 0,
10
+ maxHigh: 5,
11
+ maxTotal: 25,
12
+ blockOnSecurityFindings: true,
13
+ };
14
+ }
15
+ // ─── Patterns ──────────────────────────────────────────────────────────────
16
+ const GATE_PATTERNS = [
17
+ {
18
+ name: "hardcoded-secret",
19
+ severity: "critical",
20
+ regex: /(?:password|secret|api_key|token)\s*[:=]\s*["'][^"']{8,}/i,
21
+ security: true,
22
+ },
23
+ { name: "eval-usage", severity: "critical", regex: /\beval\s*\(/, security: true },
24
+ { name: "sql-injection", severity: "critical", regex: /(?:query|execute)\s*\(\s*["'`].*\+/, security: true },
25
+ { name: "xss-risk", severity: "high", regex: /innerHTML\s*=|\.html\s*\(|document\.write\s*\(/, security: true },
26
+ {
27
+ name: "unsafe-deserialization",
28
+ severity: "critical",
29
+ regex: /JSON\.parse\s*\(\s*(?:req|request|body|params|query)\b/,
30
+ security: true,
31
+ },
32
+ {
33
+ name: "command-injection",
34
+ severity: "critical",
35
+ regex: /exec(?:Sync)?\s*\(\s*(?:`[^`]*\$\{|["'][^"']*\+)/,
36
+ security: true,
37
+ },
38
+ {
39
+ name: "path-traversal",
40
+ severity: "high",
41
+ regex: /(?:readFile|writeFile|createReadStream)\s*\([^)]*(?:req|params|query)/,
42
+ security: true,
43
+ },
44
+ { name: "empty-catch", severity: "medium", regex: /catch\s*\([^)]*\)\s*\{\s*\}/, security: false },
45
+ { name: "any-type", severity: "low", regex: /:\s*any\b/, security: false },
46
+ { name: "console-log", severity: "low", regex: /console\.log\s*\(/, security: false },
47
+ { name: "deprecated-api", severity: "medium", regex: /new\s+Buffer\s*\(|\.substr\s*\(/, security: false },
48
+ { name: "todo-in-code", severity: "low", regex: /\/\/\s*(?:TODO|FIXME|HACK)\b/i, security: false },
49
+ ];
50
+ // ─── Helpers ────────────────────────────────────────────────────────────────
51
+ function collectSourceFiles(dir) {
52
+ const exts = new Set([".ts", ".js", ".tsx", ".jsx", ".py", ".java", ".go", ".rs", ".cs"]);
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 (exts.has(extname(name)))
72
+ files.push(full);
73
+ }
74
+ catch {
75
+ // skip
76
+ }
77
+ }
78
+ }
79
+ walk(dir);
80
+ return files;
81
+ }
82
+ function runGate(files, config) {
83
+ const findings = [];
84
+ for (const filePath of files) {
85
+ let content;
86
+ try {
87
+ content = readFileSync(filePath, "utf-8");
88
+ }
89
+ catch {
90
+ continue;
91
+ }
92
+ const lines = content.split("\n");
93
+ for (let i = 0; i < lines.length; i++) {
94
+ for (const pat of GATE_PATTERNS) {
95
+ if (pat.regex.test(lines[i])) {
96
+ findings.push({ pattern: pat.name, severity: pat.severity, file: filePath, line: i + 1 });
97
+ }
98
+ }
99
+ }
100
+ }
101
+ const counts = { critical: 0, high: 0, medium: 0, low: 0, total: findings.length };
102
+ for (const f of findings) {
103
+ if (f.severity === "critical")
104
+ counts.critical++;
105
+ else if (f.severity === "high")
106
+ counts.high++;
107
+ else if (f.severity === "medium")
108
+ counts.medium++;
109
+ else
110
+ counts.low++;
111
+ }
112
+ const failReasons = [];
113
+ if (counts.critical > config.maxCritical) {
114
+ failReasons.push(`Critical findings (${counts.critical}) exceed threshold (${config.maxCritical})`);
115
+ }
116
+ if (counts.high > config.maxHigh) {
117
+ failReasons.push(`High findings (${counts.high}) exceed threshold (${config.maxHigh})`);
118
+ }
119
+ if (counts.total > config.maxTotal) {
120
+ failReasons.push(`Total findings (${counts.total}) exceed threshold (${config.maxTotal})`);
121
+ }
122
+ if (config.blockOnSecurityFindings) {
123
+ const securityFindings = findings.filter((f) => GATE_PATTERNS.find((p) => p.name === f.pattern && p.security));
124
+ if (securityFindings.length > 0) {
125
+ failReasons.push(`${securityFindings.length} security-related findings detected`);
126
+ }
127
+ }
128
+ return {
129
+ passed: failReasons.length === 0,
130
+ findings,
131
+ counts,
132
+ thresholds: config,
133
+ failReasons,
134
+ };
135
+ }
136
+ // ─── CLI ────────────────────────────────────────────────────────────────────
137
+ export function runReviewGate(argv) {
138
+ if (argv.includes("--help") || argv.includes("-h")) {
139
+ console.log(`
140
+ judges review-gate — CI/CD quality gate with configurable thresholds
141
+
142
+ Usage:
143
+ judges review-gate [dir] Run quality gate check
144
+ judges review-gate --max-critical 0 Set critical threshold
145
+ judges review-gate --max-high 3 Set high threshold
146
+ judges review-gate --max-total 20 Set total threshold
147
+ judges review-gate --format json JSON output
148
+
149
+ Options:
150
+ [dir] Target directory (default: .)
151
+ --max-critical <n> Max critical findings (default: 0)
152
+ --max-high <n> Max high findings (default: 5)
153
+ --max-total <n> Max total findings (default: 25)
154
+ --no-block-security Don't fail on security findings
155
+ --format json JSON output
156
+ --help, -h Show this help
157
+
158
+ Exit code 1 if gate fails. Designed for CI/CD pipeline integration.
159
+ `);
160
+ return;
161
+ }
162
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
163
+ const dir = argv.find((a) => !a.startsWith("-") &&
164
+ a !== "review-gate" &&
165
+ argv[argv.indexOf(a) - 1] !== "--format" &&
166
+ argv[argv.indexOf(a) - 1] !== "--max-critical" &&
167
+ argv[argv.indexOf(a) - 1] !== "--max-high" &&
168
+ argv[argv.indexOf(a) - 1] !== "--max-total") || ".";
169
+ const config = defaultConfig();
170
+ const getNum = (flag, fallback) => {
171
+ const val = argv.find((_a, i) => argv[i - 1] === flag);
172
+ return val ? parseInt(val, 10) : fallback;
173
+ };
174
+ config.maxCritical = getNum("--max-critical", config.maxCritical);
175
+ config.maxHigh = getNum("--max-high", config.maxHigh);
176
+ config.maxTotal = getNum("--max-total", config.maxTotal);
177
+ if (argv.includes("--no-block-security"))
178
+ config.blockOnSecurityFindings = false;
179
+ const files = collectSourceFiles(dir);
180
+ const result = runGate(files, config);
181
+ if (format === "json") {
182
+ console.log(JSON.stringify(result, null, 2));
183
+ if (!result.passed)
184
+ process.exitCode = 1;
185
+ return;
186
+ }
187
+ const icon = result.passed ? "✅" : "❌";
188
+ console.log(`\n Quality Gate: ${icon} ${result.passed ? "PASSED" : "FAILED"}\n ─────────────────────────────`);
189
+ console.log(` Files scanned: ${files.length}`);
190
+ console.log(` Total findings: ${result.counts.total}`);
191
+ console.log(` Critical: ${result.counts.critical}/${config.maxCritical} High: ${result.counts.high}/${config.maxHigh} Total: ${result.counts.total}/${config.maxTotal}`);
192
+ if (result.failReasons.length > 0) {
193
+ console.log("\n Fail reasons:");
194
+ for (const reason of result.failReasons)
195
+ console.log(` ❌ ${reason}`);
196
+ }
197
+ if (result.findings.length > 0 && result.findings.length <= 20) {
198
+ console.log("\n Findings:");
199
+ for (const f of result.findings) {
200
+ console.log(` [${f.severity}] ${f.pattern} — ${f.file}:${f.line}`);
201
+ }
202
+ }
203
+ else if (result.findings.length > 20) {
204
+ console.log(`\n Showing first 20 of ${result.findings.length} findings:`);
205
+ for (const f of result.findings.slice(0, 20)) {
206
+ console.log(` [${f.severity}] ${f.pattern} — ${f.file}:${f.line}`);
207
+ }
208
+ }
209
+ console.log();
210
+ if (!result.passed)
211
+ process.exitCode = 1;
212
+ }
213
+ //# sourceMappingURL=review-gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-gate.js","sourceRoot":"","sources":["../../src/commands/review-gate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Severity-tune — Auto-calibrate severity levels based on project patterns.
3
+ */
4
+ export declare function runSeverityTune(argv: string[]): void;
5
+ //# sourceMappingURL=severity-tune.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"severity-tune.d.ts","sourceRoot":"","sources":["../../src/commands/severity-tune.ts"],"names":[],"mappings":"AAAA;;GAEG;AA+LH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAqDpD"}
@@ -0,0 +1,209 @@
1
+ /**
2
+ * Severity-tune — Auto-calibrate severity levels based on project patterns.
3
+ */
4
+ import { readFileSync, readdirSync, statSync } from "fs";
5
+ import { join, extname } from "path";
6
+ // ─── Patterns with default severity ────────────────────────────────────────
7
+ const TUNE_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
+ { name: "magic-number", severity: "low", regex: /(?:if|return|===?)\s*(?<!\w)\d{3,}(?!\w)/ },
24
+ { name: "long-line", severity: "low", regex: /^.{200,}$/ },
25
+ { name: "nested-ternary", severity: "medium", regex: /[?][^:]*[?]/ },
26
+ { name: "god-function", severity: "medium", regex: /^(?:export\s+)?(?:async\s+)?function\s+\w+/ },
27
+ ];
28
+ // ─── Helpers ────────────────────────────────────────────────────────────────
29
+ function collectSourceFiles(dir) {
30
+ const exts = new Set([".ts", ".js", ".tsx", ".jsx", ".py", ".java", ".go", ".rs", ".cs"]);
31
+ const files = [];
32
+ const skipDirs = new Set(["node_modules", ".git", "dist", "build", "coverage"]);
33
+ function walk(d) {
34
+ let entries;
35
+ try {
36
+ entries = readdirSync(d);
37
+ }
38
+ catch {
39
+ return;
40
+ }
41
+ for (const name of entries) {
42
+ if (skipDirs.has(name))
43
+ continue;
44
+ const full = join(d, name);
45
+ try {
46
+ const st = statSync(full);
47
+ if (st.isDirectory())
48
+ walk(full);
49
+ else if (exts.has(extname(name)))
50
+ files.push(full);
51
+ }
52
+ catch {
53
+ // skip
54
+ }
55
+ }
56
+ }
57
+ walk(dir);
58
+ return files;
59
+ }
60
+ function analyzeSeverity(files) {
61
+ const patternData = new Map();
62
+ for (const pat of TUNE_PATTERNS) {
63
+ patternData.set(pat.name, { occurrences: 0, files: new Set(), severity: pat.severity });
64
+ }
65
+ for (const filePath of files) {
66
+ let content;
67
+ try {
68
+ content = readFileSync(filePath, "utf-8");
69
+ }
70
+ catch {
71
+ continue;
72
+ }
73
+ const lines = content.split("\n");
74
+ for (const pat of TUNE_PATTERNS) {
75
+ // Special handling for god-function: count functions > 80 lines
76
+ if (pat.name === "god-function") {
77
+ let funcCount = 0;
78
+ let inFunc = false;
79
+ let braceDepth = 0;
80
+ let funcLines = 0;
81
+ for (const line of lines) {
82
+ if (pat.regex.test(line) && !inFunc) {
83
+ inFunc = true;
84
+ braceDepth = 0;
85
+ funcLines = 0;
86
+ }
87
+ if (inFunc) {
88
+ funcLines++;
89
+ braceDepth += (line.match(/\{/g) || []).length;
90
+ braceDepth -= (line.match(/\}/g) || []).length;
91
+ if (braceDepth <= 0 && funcLines > 1) {
92
+ if (funcLines > 80)
93
+ funcCount++;
94
+ inFunc = false;
95
+ }
96
+ }
97
+ }
98
+ if (funcCount > 0) {
99
+ const data = patternData.get(pat.name);
100
+ data.occurrences += funcCount;
101
+ data.files.add(filePath);
102
+ }
103
+ continue;
104
+ }
105
+ let hitCount = 0;
106
+ for (const line of lines) {
107
+ if (pat.regex.test(line))
108
+ hitCount++;
109
+ }
110
+ if (hitCount > 0) {
111
+ const data = patternData.get(pat.name);
112
+ data.occurrences += hitCount;
113
+ data.files.add(filePath);
114
+ }
115
+ }
116
+ }
117
+ // Generate tuning recommendations
118
+ const recommendations = [];
119
+ const fileCount = files.length;
120
+ for (const [name, data] of patternData) {
121
+ if (data.occurrences === 0)
122
+ continue;
123
+ const filePercent = fileCount > 0 ? (data.files.size / fileCount) * 100 : 0;
124
+ let suggestedSeverity = data.severity;
125
+ let reason = "Current severity is appropriate";
126
+ // If a pattern appears in >50% of files, it may be a team convention — consider lowering severity
127
+ if (filePercent > 50 && data.severity !== "low") {
128
+ suggestedSeverity = data.severity === "critical" ? "high" : data.severity === "high" ? "medium" : "low";
129
+ reason = `Appears in ${Math.round(filePercent)}% of files — may be a project norm. Consider lowering severity.`;
130
+ }
131
+ // If a critical/high pattern appears very rarely, keep it — it's genuinely concerning
132
+ else if (data.occurrences <= 2 && (data.severity === "critical" || data.severity === "high")) {
133
+ reason = "Rare occurrence — keep current severity to catch regressions";
134
+ }
135
+ // If low-severity pattern is pervasive, suggest ignoring
136
+ else if (data.severity === "low" && data.occurrences > 100) {
137
+ suggestedSeverity = "info";
138
+ reason = `${data.occurrences} occurrences — consider ignoring to reduce noise`;
139
+ }
140
+ if (suggestedSeverity !== data.severity) {
141
+ recommendations.push({
142
+ pattern: name,
143
+ currentSeverity: data.severity,
144
+ occurrences: data.occurrences,
145
+ filesAffected: data.files.size,
146
+ suggestedSeverity,
147
+ reason,
148
+ });
149
+ }
150
+ }
151
+ recommendations.sort((a, b) => b.occurrences - a.occurrences);
152
+ const summary = recommendations.length === 0
153
+ ? "All severity levels appear well-calibrated for this project."
154
+ : `${recommendations.length} severity adjustments recommended to reduce noise and improve signal.`;
155
+ return {
156
+ filesScanned: files.length,
157
+ patternsAnalyzed: TUNE_PATTERNS.length,
158
+ tuningRecommendations: recommendations,
159
+ summary,
160
+ };
161
+ }
162
+ // ─── CLI ────────────────────────────────────────────────────────────────────
163
+ export function runSeverityTune(argv) {
164
+ if (argv.includes("--help") || argv.includes("-h")) {
165
+ console.log(`
166
+ judges severity-tune — Auto-calibrate severity levels for your project
167
+
168
+ Usage:
169
+ judges severity-tune [dir] Analyze and recommend adjustments
170
+ judges severity-tune --format json JSON output
171
+
172
+ Options:
173
+ [dir] Target directory (default: .)
174
+ --format json JSON output
175
+ --help, -h Show this help
176
+
177
+ Analyzes your codebase to determine if default severity levels match your
178
+ project's patterns. Recommends adjustments to reduce alert fatigue for
179
+ pervasive patterns while maintaining sensitivity for genuine issues.
180
+ `);
181
+ return;
182
+ }
183
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
184
+ const dir = argv.find((a) => !a.startsWith("-") && a !== "severity-tune" && argv[argv.indexOf(a) - 1] !== "--format") || ".";
185
+ const files = collectSourceFiles(dir);
186
+ if (files.length === 0) {
187
+ console.log("No source files found.");
188
+ return;
189
+ }
190
+ const result = analyzeSeverity(files);
191
+ if (format === "json") {
192
+ console.log(JSON.stringify(result, null, 2));
193
+ return;
194
+ }
195
+ console.log(`\n Severity Tune\n ─────────────────────────────`);
196
+ console.log(` Files scanned: ${result.filesScanned}`);
197
+ console.log(` Patterns analyzed: ${result.patternsAnalyzed}`);
198
+ console.log(`\n 💡 ${result.summary}`);
199
+ if (result.tuningRecommendations.length > 0) {
200
+ console.log("\n Recommendations:");
201
+ for (const rec of result.tuningRecommendations) {
202
+ console.log(`\n ${rec.pattern}: ${rec.currentSeverity} → ${rec.suggestedSeverity}`);
203
+ console.log(` ${rec.occurrences} occurrences in ${rec.filesAffected} files`);
204
+ console.log(` ${rec.reason}`);
205
+ }
206
+ }
207
+ console.log();
208
+ }
209
+ //# sourceMappingURL=severity-tune.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"severity-tune.js","sourceRoot":"","sources":["../../src/commands/severity-tune.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Trend-report — Track finding trends over time to show improvement trajectory.
3
+ */
4
+ export declare function runTrendReport(argv: string[]): void;
5
+ //# sourceMappingURL=trend-report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trend-report.d.ts","sourceRoot":"","sources":["../../src/commands/trend-report.ts"],"names":[],"mappings":"AAAA;;GAEG;AAwFH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA4GnD"}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Trend-report — Track finding trends over time to show improvement trajectory.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { join } from "path";
6
+ // ─── Helpers ────────────────────────────────────────────────────────────────
7
+ function getTrendDir() {
8
+ return join(".", ".judges", "trends");
9
+ }
10
+ function loadSnapshots() {
11
+ const dir = getTrendDir();
12
+ const indexPath = join(dir, "trend-index.json");
13
+ if (!existsSync(indexPath))
14
+ return [];
15
+ try {
16
+ return JSON.parse(readFileSync(indexPath, "utf-8"));
17
+ }
18
+ catch {
19
+ return [];
20
+ }
21
+ }
22
+ function saveSnapshots(snapshots) {
23
+ const dir = getTrendDir();
24
+ if (!existsSync(dir))
25
+ mkdirSync(dir, { recursive: true });
26
+ writeFileSync(join(dir, "trend-index.json"), JSON.stringify(snapshots, null, 2), "utf-8");
27
+ }
28
+ function computeTrend(snapshots) {
29
+ if (snapshots.length === 0) {
30
+ return {
31
+ snapshots: [],
32
+ trend: "stable",
33
+ changePercent: 0,
34
+ averageFindings: 0,
35
+ bestSnapshot: null,
36
+ worstSnapshot: null,
37
+ };
38
+ }
39
+ const sorted = [...snapshots].sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
40
+ const totalSum = sorted.reduce((s, snap) => s + snap.totalFindings, 0);
41
+ const avg = Math.round(totalSum / sorted.length);
42
+ const best = sorted.reduce((b, s) => (s.totalFindings < b.totalFindings ? s : b), sorted[0]);
43
+ const worst = sorted.reduce((w, s) => (s.totalFindings > w.totalFindings ? s : w), sorted[0]);
44
+ let trend = "stable";
45
+ let changePercent = 0;
46
+ if (sorted.length >= 2) {
47
+ const first = sorted[0].totalFindings;
48
+ const last = sorted[sorted.length - 1].totalFindings;
49
+ if (first > 0) {
50
+ changePercent = Math.round(((last - first) / first) * 100);
51
+ }
52
+ if (changePercent < -10)
53
+ trend = "improving";
54
+ else if (changePercent > 10)
55
+ trend = "degrading";
56
+ }
57
+ return { snapshots: sorted, trend, changePercent, averageFindings: avg, bestSnapshot: best, worstSnapshot: worst };
58
+ }
59
+ // ─── CLI ────────────────────────────────────────────────────────────────────
60
+ export function runTrendReport(argv) {
61
+ if (argv.includes("--help") || argv.includes("-h")) {
62
+ console.log(`
63
+ judges trend-report — Track finding trends over time
64
+
65
+ Usage:
66
+ judges trend-report record --total 15 --critical 1 --high 3 --medium 6 --low 5 --files 42
67
+ judges trend-report show Show trend analysis
68
+ judges trend-report show --format json JSON output
69
+
70
+ Subcommands:
71
+ record Record a snapshot of current findings
72
+ show Analyze and display trend data
73
+
74
+ Record Options:
75
+ --total <n> Total findings count
76
+ --critical <n> Critical severity count
77
+ --high <n> High severity count
78
+ --medium <n> Medium severity count
79
+ --low <n> Low severity count
80
+ --files <n> Files scanned count
81
+ --commit <hash> Associated commit hash
82
+
83
+ Show Options:
84
+ --format json JSON output
85
+ --help, -h Show this help
86
+
87
+ Snapshots are stored locally in .judges/trends/.
88
+ `);
89
+ return;
90
+ }
91
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
92
+ const subcommand = argv.find((a) => !a.startsWith("-") && a !== "trend-report") || "show";
93
+ if (subcommand === "record") {
94
+ const getNum = (flag) => {
95
+ const val = argv.find((_a, i) => argv[i - 1] === flag);
96
+ return val ? parseInt(val, 10) : 0;
97
+ };
98
+ const total = getNum("--total");
99
+ const critical = getNum("--critical");
100
+ const high = getNum("--high");
101
+ const medium = getNum("--medium");
102
+ const low = getNum("--low");
103
+ const filesScanned = getNum("--files");
104
+ const commit = argv.find((_a, i) => argv[i - 1] === "--commit") || "unknown";
105
+ const snapshot = {
106
+ timestamp: new Date().toISOString(),
107
+ commit,
108
+ totalFindings: total,
109
+ critical,
110
+ high,
111
+ medium,
112
+ low,
113
+ filesScanned,
114
+ findingsPerFile: filesScanned > 0 ? Math.round((total / filesScanned) * 100) / 100 : 0,
115
+ };
116
+ const snapshots = loadSnapshots();
117
+ snapshots.push(snapshot);
118
+ saveSnapshots(snapshots);
119
+ console.log(`Recorded snapshot: ${total} findings across ${filesScanned} files.`);
120
+ return;
121
+ }
122
+ // Show
123
+ const snapshots = loadSnapshots();
124
+ const report = computeTrend(snapshots);
125
+ if (format === "json") {
126
+ console.log(JSON.stringify(report, null, 2));
127
+ return;
128
+ }
129
+ console.log(`\n Trend Report\n ─────────────────────────────`);
130
+ console.log(` Snapshots: ${report.snapshots.length}`);
131
+ console.log(` Average findings: ${report.averageFindings}`);
132
+ const trendIcon = report.trend === "improving" ? "📉" : report.trend === "degrading" ? "📈" : "➡️";
133
+ console.log(` Trend: ${trendIcon} ${report.trend} (${report.changePercent > 0 ? "+" : ""}${report.changePercent}%)`);
134
+ if (report.bestSnapshot) {
135
+ console.log(`\n Best: ${report.bestSnapshot.totalFindings} findings (${report.bestSnapshot.timestamp.slice(0, 10)})`);
136
+ }
137
+ if (report.worstSnapshot) {
138
+ console.log(` Worst: ${report.worstSnapshot.totalFindings} findings (${report.worstSnapshot.timestamp.slice(0, 10)})`);
139
+ }
140
+ if (report.snapshots.length > 0) {
141
+ console.log("\n Recent snapshots:");
142
+ const recent = report.snapshots.slice(-5);
143
+ for (const snap of recent) {
144
+ console.log(` ${snap.timestamp.slice(0, 10)} ${snap.totalFindings} findings (C:${snap.critical} H:${snap.high} M:${snap.medium} L:${snap.low})`);
145
+ }
146
+ }
147
+ console.log();
148
+ }
149
+ //# sourceMappingURL=trend-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trend-report.js","sourceRoot":"","sources":["../../src/commands/trend-report.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kevinrabun/judges",
3
- "version": "3.61.0",
3
+ "version": "3.62.0",
4
4
  "description": "45 specialized judges that evaluate AI-generated code for security, cost, and quality.",
5
5
  "mcpName": "io.github.KevinRabun/judges",
6
6
  "type": "module",