@kevinrabun/judges 3.67.0 → 3.69.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 +17 -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/finding-cluster.d.ts +5 -0
  6. package/dist/commands/finding-cluster.d.ts.map +1 -0
  7. package/dist/commands/finding-cluster.js +158 -0
  8. package/dist/commands/finding-cluster.js.map +1 -0
  9. package/dist/commands/finding-fix-rate.d.ts +5 -0
  10. package/dist/commands/finding-fix-rate.d.ts.map +1 -0
  11. package/dist/commands/finding-fix-rate.js +142 -0
  12. package/dist/commands/finding-fix-rate.js.map +1 -0
  13. package/dist/commands/finding-hotspot.d.ts +5 -0
  14. package/dist/commands/finding-hotspot.d.ts.map +1 -0
  15. package/dist/commands/finding-hotspot.js +116 -0
  16. package/dist/commands/finding-hotspot.js.map +1 -0
  17. package/dist/commands/finding-recurrence.d.ts +5 -0
  18. package/dist/commands/finding-recurrence.d.ts.map +1 -0
  19. package/dist/commands/finding-recurrence.js +136 -0
  20. package/dist/commands/finding-recurrence.js.map +1 -0
  21. package/dist/commands/review-ab-test.d.ts +5 -0
  22. package/dist/commands/review-ab-test.d.ts.map +1 -0
  23. package/dist/commands/review-ab-test.js +225 -0
  24. package/dist/commands/review-ab-test.js.map +1 -0
  25. package/dist/commands/review-audit-log.d.ts +5 -0
  26. package/dist/commands/review-audit-log.d.ts.map +1 -0
  27. package/dist/commands/review-audit-log.js +140 -0
  28. package/dist/commands/review-audit-log.js.map +1 -0
  29. package/dist/commands/review-badge.d.ts +5 -0
  30. package/dist/commands/review-badge.d.ts.map +1 -0
  31. package/dist/commands/review-badge.js +153 -0
  32. package/dist/commands/review-badge.js.map +1 -0
  33. package/dist/commands/review-benchmark-self.d.ts +5 -0
  34. package/dist/commands/review-benchmark-self.d.ts.map +1 -0
  35. package/dist/commands/review-benchmark-self.js +141 -0
  36. package/dist/commands/review-benchmark-self.js.map +1 -0
  37. package/dist/commands/review-changelog-gen.d.ts +5 -0
  38. package/dist/commands/review-changelog-gen.d.ts.map +1 -0
  39. package/dist/commands/review-changelog-gen.js +118 -0
  40. package/dist/commands/review-changelog-gen.js.map +1 -0
  41. package/dist/commands/review-integration.d.ts +5 -0
  42. package/dist/commands/review-integration.d.ts.map +1 -0
  43. package/dist/commands/review-integration.js +237 -0
  44. package/dist/commands/review-integration.js.map +1 -0
  45. package/dist/commands/review-milestone.d.ts +5 -0
  46. package/dist/commands/review-milestone.d.ts.map +1 -0
  47. package/dist/commands/review-milestone.js +137 -0
  48. package/dist/commands/review-milestone.js.map +1 -0
  49. package/dist/commands/review-report-pdf.d.ts +5 -0
  50. package/dist/commands/review-report-pdf.d.ts.map +1 -0
  51. package/dist/commands/review-report-pdf.js +164 -0
  52. package/dist/commands/review-report-pdf.js.map +1 -0
  53. package/dist/commands/review-risk-score.d.ts +5 -0
  54. package/dist/commands/review-risk-score.d.ts.map +1 -0
  55. package/dist/commands/review-risk-score.js +157 -0
  56. package/dist/commands/review-risk-score.js.map +1 -0
  57. package/dist/commands/review-sandbox.d.ts +5 -0
  58. package/dist/commands/review-sandbox.d.ts.map +1 -0
  59. package/dist/commands/review-sandbox.js +192 -0
  60. package/dist/commands/review-sandbox.js.map +1 -0
  61. package/dist/commands/review-standup.d.ts +5 -0
  62. package/dist/commands/review-standup.d.ts.map +1 -0
  63. package/dist/commands/review-standup.js +96 -0
  64. package/dist/commands/review-standup.js.map +1 -0
  65. package/dist/commands/review-streak.d.ts +5 -0
  66. package/dist/commands/review-streak.d.ts.map +1 -0
  67. package/dist/commands/review-streak.js +151 -0
  68. package/dist/commands/review-streak.js.map +1 -0
  69. package/package.json +1 -1
  70. package/server.json +2 -2
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Finding-cluster — Cluster related findings by similarity to reveal systemic AI patterns.
3
+ */
4
+ import { readFileSync, existsSync } from "fs";
5
+ // ─── Clustering ─────────────────────────────────────────────────────────────
6
+ function clusterFindings(findings) {
7
+ const groups = new Map();
8
+ for (const f of findings) {
9
+ const key = (f.ruleId || "UNKNOWN").split("-")[0];
10
+ const list = groups.get(key) || [];
11
+ list.push(f);
12
+ groups.set(key, list);
13
+ }
14
+ const clusters = [];
15
+ let id = 1;
16
+ for (const [prefix, members] of groups) {
17
+ // Sub-cluster by severity
18
+ const sevGroups = new Map();
19
+ for (const m of members) {
20
+ const sev = String(m.severity || "medium");
21
+ const list = sevGroups.get(sev) || [];
22
+ list.push(m);
23
+ sevGroups.set(sev, list);
24
+ }
25
+ for (const [sev, sevMembers] of sevGroups) {
26
+ clusters.push({
27
+ id: id++,
28
+ label: `${prefix} — ${sev} findings`,
29
+ ruleId: prefix,
30
+ severity: sev,
31
+ count: sevMembers.length,
32
+ findings: sevMembers.map((f) => ({
33
+ title: f.title || "",
34
+ ruleId: f.ruleId || "",
35
+ severity: String(f.severity || "medium"),
36
+ })),
37
+ });
38
+ }
39
+ }
40
+ clusters.sort((a, b) => b.count - a.count);
41
+ return clusters;
42
+ }
43
+ // ─── Similarity ─────────────────────────────────────────────────────────────
44
+ function tokenize(text) {
45
+ return new Set(text
46
+ .toLowerCase()
47
+ .split(/[\s\-_.,;:!?()[\]{}]+/)
48
+ .filter((t) => t.length > 2));
49
+ }
50
+ function jaccardSimilarity(a, b) {
51
+ let intersection = 0;
52
+ for (const token of a) {
53
+ if (b.has(token))
54
+ intersection++;
55
+ }
56
+ const union = a.size + b.size - intersection;
57
+ return union === 0 ? 0 : intersection / union;
58
+ }
59
+ function findSimilarPairs(findings, threshold) {
60
+ const pairs = [];
61
+ for (let i = 0; i < findings.length; i++) {
62
+ const tokensA = tokenize([findings[i].title || "", findings[i].description || ""].join(" "));
63
+ for (let j = i + 1; j < findings.length; j++) {
64
+ const tokensB = tokenize([findings[j].title || "", findings[j].description || ""].join(" "));
65
+ const sim = jaccardSimilarity(tokensA, tokensB);
66
+ if (sim >= threshold) {
67
+ pairs.push({ a: findings[i].title || `Finding ${i}`, b: findings[j].title || `Finding ${j}`, similarity: sim });
68
+ }
69
+ }
70
+ }
71
+ pairs.sort((a, b) => b.similarity - a.similarity);
72
+ return pairs;
73
+ }
74
+ // ─── CLI ────────────────────────────────────────────────────────────────────
75
+ export function runFindingCluster(argv) {
76
+ if (argv.includes("--help") || argv.includes("-h")) {
77
+ console.log(`
78
+ judges finding-cluster — Cluster related findings to reveal systemic patterns
79
+
80
+ Usage:
81
+ judges finding-cluster --file verdict.json Cluster findings from verdict
82
+ judges finding-cluster --file v.json --similar Show similar finding pairs
83
+ judges finding-cluster --file v.json --top 5 Show top N clusters
84
+
85
+ Options:
86
+ --file <path> Verdict JSON file
87
+ --similar Show similar finding pairs
88
+ --threshold <n> Similarity threshold 0-1 (default: 0.3)
89
+ --top <n> Show top N clusters (default: all)
90
+ --format json JSON output
91
+ --help, -h Show this help
92
+
93
+ Identifies recurring patterns in AI-generated code findings.
94
+ `);
95
+ return;
96
+ }
97
+ const file = argv.find((_a, i) => argv[i - 1] === "--file");
98
+ if (!file || !existsSync(file)) {
99
+ console.error("Error: --file with valid verdict JSON is required.");
100
+ process.exitCode = 1;
101
+ return;
102
+ }
103
+ let verdict;
104
+ try {
105
+ verdict = JSON.parse(readFileSync(file, "utf-8"));
106
+ }
107
+ catch {
108
+ console.error("Error: Failed to parse verdict file.");
109
+ process.exitCode = 1;
110
+ return;
111
+ }
112
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
113
+ const topN = parseInt(argv.find((_a, i) => argv[i - 1] === "--top") || "0", 10);
114
+ if (argv.includes("--similar")) {
115
+ const threshold = parseFloat(argv.find((_a, i) => argv[i - 1] === "--threshold") || "0.3");
116
+ const pairs = findSimilarPairs(verdict.findings || [], threshold);
117
+ if (format === "json") {
118
+ console.log(JSON.stringify(pairs, null, 2));
119
+ return;
120
+ }
121
+ if (pairs.length === 0) {
122
+ console.log("No similar finding pairs found above threshold.");
123
+ return;
124
+ }
125
+ console.log("\nSimilar Finding Pairs:");
126
+ console.log("─".repeat(70));
127
+ for (const p of pairs.slice(0, 20)) {
128
+ console.log(` ${(p.similarity * 100).toFixed(0)}% "${p.a}" ↔ "${p.b}"`);
129
+ }
130
+ console.log("─".repeat(70));
131
+ return;
132
+ }
133
+ let clusters = clusterFindings(verdict.findings || []);
134
+ if (topN > 0)
135
+ clusters = clusters.slice(0, topN);
136
+ if (format === "json") {
137
+ console.log(JSON.stringify(clusters, null, 2));
138
+ return;
139
+ }
140
+ if (clusters.length === 0) {
141
+ console.log("No findings to cluster.");
142
+ return;
143
+ }
144
+ console.log("\nFinding Clusters:");
145
+ console.log("─".repeat(60));
146
+ for (const c of clusters) {
147
+ console.log(` Cluster #${c.id}: ${c.label} (${c.count} findings)`);
148
+ for (const m of c.findings.slice(0, 5)) {
149
+ console.log(` - [${m.ruleId}] ${m.title}`);
150
+ }
151
+ if (c.findings.length > 5)
152
+ console.log(` ... and ${c.findings.length - 5} more`);
153
+ console.log();
154
+ }
155
+ console.log("─".repeat(60));
156
+ console.log(`Total: ${clusters.length} cluster(s), ${(verdict.findings || []).length} finding(s)`);
157
+ }
158
+ //# sourceMappingURL=finding-cluster.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-cluster.js","sourceRoot":"","sources":["../../src/commands/finding-cluster.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Finding-fix-rate — Track how quickly findings are being resolved over time.
3
+ */
4
+ export declare function runFindingFixRate(argv: string[]): void;
5
+ //# sourceMappingURL=finding-fix-rate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-fix-rate.d.ts","sourceRoot":"","sources":["../../src/commands/finding-fix-rate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAwCH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAuItD"}
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Finding-fix-rate — Track how quickly findings are being resolved over time.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { join, dirname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const FIX_RATE_FILE = join(".judges", "fix-rate.json");
8
+ function loadStore() {
9
+ if (!existsSync(FIX_RATE_FILE))
10
+ return { version: "1.0.0", events: [] };
11
+ try {
12
+ return JSON.parse(readFileSync(FIX_RATE_FILE, "utf-8"));
13
+ }
14
+ catch {
15
+ return { version: "1.0.0", events: [] };
16
+ }
17
+ }
18
+ function saveStore(store) {
19
+ mkdirSync(dirname(FIX_RATE_FILE), { recursive: true });
20
+ writeFileSync(FIX_RATE_FILE, JSON.stringify(store, null, 2), "utf-8");
21
+ }
22
+ // ─── CLI ────────────────────────────────────────────────────────────────────
23
+ export function runFindingFixRate(argv) {
24
+ if (argv.includes("--help") || argv.includes("-h")) {
25
+ console.log(`
26
+ judges finding-fix-rate — Track finding resolution speed
27
+
28
+ Usage:
29
+ judges finding-fix-rate show Show fix rate metrics
30
+ judges finding-fix-rate record --rule SEC-001 --severity high --days 3
31
+ judges finding-fix-rate trend Show trend over time
32
+ judges finding-fix-rate clear Clear all data
33
+
34
+ Subcommands:
35
+ show Show fix rate summary
36
+ record Record a fix event
37
+ trend Show fix rate trends
38
+ clear Clear all data
39
+
40
+ Options:
41
+ --rule <ruleId> Rule ID of the fixed finding
42
+ --severity <level> Severity (critical, high, medium, low)
43
+ --days <n> Days to fix
44
+ --last <n> Show last N events (default: 20)
45
+ --format json JSON output
46
+ --help, -h Show this help
47
+
48
+ Tracks how quickly findings are resolved. Data in .judges/fix-rate.json.
49
+ `);
50
+ return;
51
+ }
52
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
53
+ const subcommand = argv.find((a) => ["show", "record", "trend", "clear"].includes(a)) || "show";
54
+ const store = loadStore();
55
+ if (subcommand === "record") {
56
+ const ruleId = argv.find((_a, i) => argv[i - 1] === "--rule") || "UNKNOWN";
57
+ const severity = argv.find((_a, i) => argv[i - 1] === "--severity") || "medium";
58
+ const days = parseInt(argv.find((_a, i) => argv[i - 1] === "--days") || "1", 10);
59
+ const now = new Date();
60
+ const foundDate = new Date(now.getTime() - days * 86400000);
61
+ store.events.push({
62
+ ruleId,
63
+ severity,
64
+ foundAt: foundDate.toISOString(),
65
+ fixedAt: now.toISOString(),
66
+ daysToFix: days,
67
+ });
68
+ saveStore(store);
69
+ console.log(`Recorded fix: ${ruleId} (${severity}) resolved in ${days} day(s).`);
70
+ return;
71
+ }
72
+ if (subcommand === "clear") {
73
+ saveStore({ version: "1.0.0", events: [] });
74
+ console.log("Fix rate data cleared.");
75
+ return;
76
+ }
77
+ if (subcommand === "trend") {
78
+ if (store.events.length === 0) {
79
+ console.log("No fix events recorded yet.");
80
+ return;
81
+ }
82
+ // Group by month
83
+ const monthly = new Map();
84
+ for (const e of store.events) {
85
+ const month = e.fixedAt.slice(0, 7);
86
+ const list = monthly.get(month) || [];
87
+ list.push(e.daysToFix);
88
+ monthly.set(month, list);
89
+ }
90
+ if (format === "json") {
91
+ const trend = [...monthly.entries()].map(([month, days]) => ({
92
+ month,
93
+ avgDays: days.reduce((s, d) => s + d, 0) / days.length,
94
+ fixes: days.length,
95
+ }));
96
+ console.log(JSON.stringify(trend, null, 2));
97
+ return;
98
+ }
99
+ console.log("\nFix Rate Trend:");
100
+ console.log("─".repeat(50));
101
+ for (const [month, days] of monthly) {
102
+ const avg = days.reduce((s, d) => s + d, 0) / days.length;
103
+ const bar = "█".repeat(Math.min(Math.round(avg), 30));
104
+ console.log(` ${month} avg ${avg.toFixed(1)}d (${days.length} fixes) ${bar}`);
105
+ }
106
+ console.log("─".repeat(50));
107
+ return;
108
+ }
109
+ // show
110
+ if (store.events.length === 0) {
111
+ console.log("No fix events recorded. Use 'judges finding-fix-rate record' to track fixes.");
112
+ return;
113
+ }
114
+ const avgDays = store.events.reduce((s, e) => s + e.daysToFix, 0) / store.events.length;
115
+ const criticals = store.events.filter((e) => e.severity === "critical");
116
+ const avgCriticalDays = criticals.length > 0 ? criticals.reduce((s, e) => s + e.daysToFix, 0) / criticals.length : 0;
117
+ if (format === "json") {
118
+ console.log(JSON.stringify({
119
+ totalFixes: store.events.length,
120
+ avgDaysToFix: avgDays,
121
+ avgCriticalDaysToFix: avgCriticalDays,
122
+ bySeverity: {
123
+ critical: criticals.length,
124
+ high: store.events.filter((e) => e.severity === "high").length,
125
+ medium: store.events.filter((e) => e.severity === "medium").length,
126
+ low: store.events.filter((e) => e.severity === "low").length,
127
+ },
128
+ }, null, 2));
129
+ return;
130
+ }
131
+ console.log("\nFix Rate Summary:");
132
+ console.log("─".repeat(40));
133
+ console.log(` Total fixes: ${store.events.length}`);
134
+ console.log(` Avg days to fix: ${avgDays.toFixed(1)}`);
135
+ console.log(` Avg critical fix time: ${avgCriticalDays > 0 ? avgCriticalDays.toFixed(1) + "d" : "N/A"}`);
136
+ console.log(` Critical fixes: ${criticals.length}`);
137
+ console.log(` High fixes: ${store.events.filter((e) => e.severity === "high").length}`);
138
+ console.log(` Medium fixes: ${store.events.filter((e) => e.severity === "medium").length}`);
139
+ console.log(` Low fixes: ${store.events.filter((e) => e.severity === "low").length}`);
140
+ console.log("─".repeat(40));
141
+ }
142
+ //# sourceMappingURL=finding-fix-rate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-fix-rate.js","sourceRoot":"","sources":["../../src/commands/finding-fix-rate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Finding-hotspot — Identify files and directories with highest finding density.
3
+ */
4
+ export declare function runFindingHotspot(argv: string[]): void;
5
+ //# sourceMappingURL=finding-hotspot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-hotspot.d.ts","sourceRoot":"","sources":["../../src/commands/finding-hotspot.ts"],"names":[],"mappings":"AAAA;;GAEG;AA+DH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAyEtD"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Finding-hotspot — Identify files and directories with highest finding density.
3
+ */
4
+ import { readFileSync, existsSync } from "fs";
5
+ // ─── Analysis ───────────────────────────────────────────────────────────────
6
+ function analyzeHotspots(verdicts) {
7
+ const fileMap = new Map();
8
+ for (const v of verdicts) {
9
+ for (const f of v.findings || []) {
10
+ // Use ruleId prefix as a proxy for file grouping since Finding has no file property
11
+ const key = f.ruleId ? f.ruleId.split("-")[0] : "UNKNOWN";
12
+ const entry = fileMap.get(key) || { findings: 0, criticals: 0, highs: 0, rules: new Set() };
13
+ entry.findings++;
14
+ if (f.severity === "critical")
15
+ entry.criticals++;
16
+ if (f.severity === "high")
17
+ entry.highs++;
18
+ if (f.ruleId)
19
+ entry.rules.add(f.ruleId);
20
+ fileMap.set(key, entry);
21
+ }
22
+ }
23
+ const hotspots = [];
24
+ for (const [path, data] of fileMap) {
25
+ hotspots.push({
26
+ path,
27
+ findingCount: data.findings,
28
+ criticalCount: data.criticals,
29
+ highCount: data.highs,
30
+ ruleIds: [...data.rules],
31
+ });
32
+ }
33
+ hotspots.sort((a, b) => b.findingCount - a.findingCount);
34
+ return hotspots;
35
+ }
36
+ function analyzeFromFiles(files) {
37
+ const verdicts = [];
38
+ for (const file of files) {
39
+ if (!existsSync(file))
40
+ continue;
41
+ try {
42
+ verdicts.push(JSON.parse(readFileSync(file, "utf-8")));
43
+ }
44
+ catch {
45
+ /* skip invalid */
46
+ }
47
+ }
48
+ return analyzeHotspots(verdicts);
49
+ }
50
+ // ─── CLI ────────────────────────────────────────────────────────────────────
51
+ export function runFindingHotspot(argv) {
52
+ if (argv.includes("--help") || argv.includes("-h")) {
53
+ console.log(`
54
+ judges finding-hotspot — Identify areas with highest finding density
55
+
56
+ Usage:
57
+ judges finding-hotspot --file verdict.json Analyze single verdict
58
+ judges finding-hotspot --files v1.json,v2.json Analyze multiple verdicts
59
+ judges finding-hotspot --file v.json --top 5 Show top N hotspots
60
+ judges finding-hotspot --file v.json --critical Show only critical hotspots
61
+
62
+ Options:
63
+ --file <path> Single verdict JSON file
64
+ --files <paths> Comma-separated verdict files
65
+ --top <n> Show top N hotspots (default: all)
66
+ --critical Only show areas with critical findings
67
+ --format json JSON output
68
+ --help, -h Show this help
69
+
70
+ Identifies rule categories and areas that consistently produce the most findings.
71
+ `);
72
+ return;
73
+ }
74
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
75
+ const topN = parseInt(argv.find((_a, i) => argv[i - 1] === "--top") || "0", 10);
76
+ const criticalOnly = argv.includes("--critical");
77
+ const singleFile = argv.find((_a, i) => argv[i - 1] === "--file");
78
+ const multiFiles = argv.find((_a, i) => argv[i - 1] === "--files");
79
+ const files = [];
80
+ if (singleFile)
81
+ files.push(singleFile);
82
+ if (multiFiles)
83
+ files.push(...multiFiles.split(",").map((f) => f.trim()));
84
+ if (files.length === 0) {
85
+ console.error("Error: --file or --files is required.");
86
+ process.exitCode = 1;
87
+ return;
88
+ }
89
+ let hotspots = analyzeFromFiles(files);
90
+ if (criticalOnly) {
91
+ hotspots = hotspots.filter((h) => h.criticalCount > 0);
92
+ }
93
+ if (topN > 0) {
94
+ hotspots = hotspots.slice(0, topN);
95
+ }
96
+ if (format === "json") {
97
+ console.log(JSON.stringify(hotspots, null, 2));
98
+ return;
99
+ }
100
+ if (hotspots.length === 0) {
101
+ console.log("No hotspots found.");
102
+ return;
103
+ }
104
+ console.log("\nFinding Hotspots:");
105
+ console.log("─".repeat(70));
106
+ console.log(" Category Findings Critical High Rules");
107
+ console.log("─".repeat(70));
108
+ for (const h of hotspots) {
109
+ console.log(` ${h.path.padEnd(16)} ${String(h.findingCount).padEnd(10)} ${String(h.criticalCount).padEnd(10)} ${String(h.highCount).padEnd(8)} ${h.ruleIds.slice(0, 3).join(", ")}${h.ruleIds.length > 3 ? ` +${h.ruleIds.length - 3}` : ""}`);
110
+ }
111
+ console.log("─".repeat(70));
112
+ const totalFindings = hotspots.reduce((s, h) => s + h.findingCount, 0);
113
+ const totalCriticals = hotspots.reduce((s, h) => s + h.criticalCount, 0);
114
+ console.log(` Total: ${totalFindings} findings, ${totalCriticals} critical across ${hotspots.length} hotspot(s)`);
115
+ }
116
+ //# sourceMappingURL=finding-hotspot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-hotspot.js","sourceRoot":"","sources":["../../src/commands/finding-hotspot.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAa9C,+EAA+E;AAE/E,SAAS,eAAe,CAAC,QAA2B;IAClD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAsF,CAAC;IAE9G,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;YACjC,oFAAoF;YACpF,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAC1D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,GAAG,EAAU,EAAE,CAAC;YACpG,KAAK,CAAC,QAAQ,EAAE,CAAC;YACjB,IAAI,CAAC,CAAC,QAAQ,KAAK,UAAU;gBAAE,KAAK,CAAC,SAAS,EAAE,CAAC;YACjD,IAAI,CAAC,CAAC,QAAQ,KAAK,MAAM;gBAAE,KAAK,CAAC,KAAK,EAAE,CAAC;YACzC,IAAI,CAAC,CAAC,MAAM;gBAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YACxC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,OAAO,EAAE,CAAC;QACnC,QAAQ,CAAC,IAAI,CAAC;YACZ,IAAI;YACJ,YAAY,EAAE,IAAI,CAAC,QAAQ;YAC3B,aAAa,EAAE,IAAI,CAAC,SAAS;YAC7B,SAAS,EAAE,IAAI,CAAC,KAAK;YACrB,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;SACzB,CAAC,CAAC;IACL,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC;IACzD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAe;IACvC,MAAM,QAAQ,GAAsB,EAAE,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,SAAS;QAChC,IAAI,CAAC;YACH,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAoB,CAAC,CAAC;QAC5E,CAAC;QAAC,MAAM,CAAC;YACP,kBAAkB;QACpB,CAAC;IACH,CAAC;IACD,OAAO,eAAe,CAAC,QAAQ,CAAC,CAAC;AACnC,CAAC;AAED,+EAA+E;AAE/E,MAAM,UAAU,iBAAiB,CAAC,IAAc;IAC9C,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;CAkBf,CAAC,CAAC;QACC,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,UAAU,CAAC,IAAI,MAAM,CAAC;IAC1F,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;IAChG,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAEjD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC;IAClF,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;IAEnF,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,UAAU;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACvC,IAAI,UAAU;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAE1E,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;QACvD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,IAAI,QAAQ,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAEvC,IAAI,YAAY,EAAE,CAAC;QACjB,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QACb,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/C,OAAO;IACT,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAClC,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;IACnE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACnO,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;IACvE,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;IACzE,OAAO,CAAC,GAAG,CAAC,YAAY,aAAa,cAAc,cAAc,oBAAoB,QAAQ,CAAC,MAAM,aAAa,CAAC,CAAC;AACrH,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Finding-recurrence — Track findings that keep coming back after being fixed.
3
+ */
4
+ export declare function runFindingRecurrence(argv: string[]): void;
5
+ //# sourceMappingURL=finding-recurrence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-recurrence.d.ts","sourceRoot":"","sources":["../../src/commands/finding-recurrence.ts"],"names":[],"mappings":"AAAA;;GAEG;AA+CH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAsHzD"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Finding-recurrence — Track findings that keep coming back after being fixed.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { join, dirname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const RECURRENCE_FILE = join(".judges", "finding-recurrence.json");
8
+ function loadStore() {
9
+ if (!existsSync(RECURRENCE_FILE))
10
+ return { version: "1.0.0", records: [] };
11
+ try {
12
+ return JSON.parse(readFileSync(RECURRENCE_FILE, "utf-8"));
13
+ }
14
+ catch {
15
+ return { version: "1.0.0", records: [] };
16
+ }
17
+ }
18
+ function saveStore(store) {
19
+ mkdirSync(dirname(RECURRENCE_FILE), { recursive: true });
20
+ writeFileSync(RECURRENCE_FILE, JSON.stringify(store, null, 2), "utf-8");
21
+ }
22
+ function fingerprint(f) {
23
+ return [f.ruleId || "", f.title || "", String(f.severity || "")].join("|").toLowerCase();
24
+ }
25
+ // ─── CLI ────────────────────────────────────────────────────────────────────
26
+ export function runFindingRecurrence(argv) {
27
+ if (argv.includes("--help") || argv.includes("-h")) {
28
+ console.log(`
29
+ judges finding-recurrence — Track recurring findings
30
+
31
+ Usage:
32
+ judges finding-recurrence update --file verdict.json Update records
33
+ judges finding-recurrence show Show recurring findings
34
+ judges finding-recurrence show --min 3 Show findings with 3+ occurrences
35
+ judges finding-recurrence clear Clear all data
36
+
37
+ Subcommands:
38
+ update Update recurrence records from verdict
39
+ show Show recurring findings
40
+ clear Clear all data
41
+
42
+ Options:
43
+ --file <path> Verdict JSON file (for update)
44
+ --min <n> Minimum occurrences to show (default: 2)
45
+ --format json JSON output
46
+ --help, -h Show this help
47
+
48
+ Tracks findings that keep reappearing. Data in .judges/finding-recurrence.json.
49
+ `);
50
+ return;
51
+ }
52
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
53
+ const subcommand = argv.find((a) => ["update", "show", "clear"].includes(a)) || "show";
54
+ const store = loadStore();
55
+ if (subcommand === "update") {
56
+ const file = argv.find((_a, i) => argv[i - 1] === "--file");
57
+ if (!file || !existsSync(file)) {
58
+ console.error("Error: --file with valid verdict JSON is required.");
59
+ process.exitCode = 1;
60
+ return;
61
+ }
62
+ let verdict;
63
+ try {
64
+ verdict = JSON.parse(readFileSync(file, "utf-8"));
65
+ }
66
+ catch {
67
+ console.error("Error: Failed to parse verdict file.");
68
+ process.exitCode = 1;
69
+ return;
70
+ }
71
+ const now = new Date().toISOString();
72
+ const seenFingerprints = new Set();
73
+ let newCount = 0;
74
+ let recurCount = 0;
75
+ for (const f of verdict.findings || []) {
76
+ const fp = fingerprint(f);
77
+ seenFingerprints.add(fp);
78
+ const existing = store.records.find((r) => r.fingerprint === fp);
79
+ if (existing) {
80
+ existing.occurrences++;
81
+ existing.lastSeen = now;
82
+ recurCount++;
83
+ }
84
+ else {
85
+ store.records.push({
86
+ fingerprint: fp,
87
+ ruleId: f.ruleId || "",
88
+ title: f.title || "",
89
+ occurrences: 1,
90
+ firstSeen: now,
91
+ lastSeen: now,
92
+ resolvedCount: 0,
93
+ });
94
+ newCount++;
95
+ }
96
+ }
97
+ // Mark resolved findings
98
+ for (const r of store.records) {
99
+ if (!seenFingerprints.has(r.fingerprint) && r.occurrences > 0) {
100
+ r.resolvedCount++;
101
+ }
102
+ }
103
+ saveStore(store);
104
+ console.log(`Updated: ${newCount} new, ${recurCount} recurring findings tracked.`);
105
+ return;
106
+ }
107
+ if (subcommand === "clear") {
108
+ saveStore({ version: "1.0.0", records: [] });
109
+ console.log("Recurrence data cleared.");
110
+ return;
111
+ }
112
+ // show
113
+ const minOccurrences = parseInt(argv.find((_a, i) => argv[i - 1] === "--min") || "2", 10);
114
+ const recurring = store.records.filter((r) => r.occurrences >= minOccurrences);
115
+ recurring.sort((a, b) => b.occurrences - a.occurrences);
116
+ if (format === "json") {
117
+ console.log(JSON.stringify(recurring, null, 2));
118
+ return;
119
+ }
120
+ if (recurring.length === 0) {
121
+ console.log(`No findings with ${minOccurrences}+ occurrences.`);
122
+ return;
123
+ }
124
+ console.log(`\nRecurring Findings (${minOccurrences}+ occurrences):`);
125
+ console.log("─".repeat(70));
126
+ console.log(" Occurrences Rule Title");
127
+ console.log("─".repeat(70));
128
+ for (const r of recurring.slice(0, 30)) {
129
+ console.log(` ${String(r.occurrences).padEnd(12)} ${(r.ruleId || "-").padEnd(13)} ${r.title.slice(0, 40)}`);
130
+ }
131
+ console.log("─".repeat(70));
132
+ console.log(` ${recurring.length} recurring finding(s) found`);
133
+ if (recurring.length > 30)
134
+ console.log(` (showing top 30 of ${recurring.length})`);
135
+ }
136
+ //# sourceMappingURL=finding-recurrence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-recurrence.js","sourceRoot":"","sources":["../../src/commands/finding-recurrence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-ab-test — A/B test review configurations to find optimal settings.
3
+ */
4
+ export declare function runReviewAbTest(argv: string[]): void;
5
+ //# sourceMappingURL=review-ab-test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-ab-test.d.ts","sourceRoot":"","sources":["../../src/commands/review-ab-test.ts"],"names":[],"mappings":"AAAA;;GAEG;AAiEH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAwNpD"}