@kevinrabun/judges 3.66.0 → 3.68.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/config-lint.d.ts +5 -0
  6. package/dist/commands/config-lint.d.ts.map +1 -0
  7. package/dist/commands/config-lint.js +188 -0
  8. package/dist/commands/config-lint.js.map +1 -0
  9. package/dist/commands/finding-age.d.ts +5 -0
  10. package/dist/commands/finding-age.d.ts.map +1 -0
  11. package/dist/commands/finding-age.js +146 -0
  12. package/dist/commands/finding-age.js.map +1 -0
  13. package/dist/commands/finding-cluster.d.ts +5 -0
  14. package/dist/commands/finding-cluster.d.ts.map +1 -0
  15. package/dist/commands/finding-cluster.js +158 -0
  16. package/dist/commands/finding-cluster.js.map +1 -0
  17. package/dist/commands/finding-hotspot.d.ts +5 -0
  18. package/dist/commands/finding-hotspot.d.ts.map +1 -0
  19. package/dist/commands/finding-hotspot.js +116 -0
  20. package/dist/commands/finding-hotspot.js.map +1 -0
  21. package/dist/commands/finding-rank.d.ts +5 -0
  22. package/dist/commands/finding-rank.d.ts.map +1 -0
  23. package/dist/commands/finding-rank.js +139 -0
  24. package/dist/commands/finding-rank.js.map +1 -0
  25. package/dist/commands/review-ab-test.d.ts +5 -0
  26. package/dist/commands/review-ab-test.d.ts.map +1 -0
  27. package/dist/commands/review-ab-test.js +225 -0
  28. package/dist/commands/review-ab-test.js.map +1 -0
  29. package/dist/commands/review-audit-log.d.ts +5 -0
  30. package/dist/commands/review-audit-log.d.ts.map +1 -0
  31. package/dist/commands/review-audit-log.js +140 -0
  32. package/dist/commands/review-audit-log.js.map +1 -0
  33. package/dist/commands/review-badge.d.ts +5 -0
  34. package/dist/commands/review-badge.d.ts.map +1 -0
  35. package/dist/commands/review-badge.js +153 -0
  36. package/dist/commands/review-badge.js.map +1 -0
  37. package/dist/commands/review-dashboard.d.ts +5 -0
  38. package/dist/commands/review-dashboard.d.ts.map +1 -0
  39. package/dist/commands/review-dashboard.js +141 -0
  40. package/dist/commands/review-dashboard.js.map +1 -0
  41. package/dist/commands/review-diff-summary.d.ts +5 -0
  42. package/dist/commands/review-diff-summary.d.ts.map +1 -0
  43. package/dist/commands/review-diff-summary.js +155 -0
  44. package/dist/commands/review-diff-summary.js.map +1 -0
  45. package/dist/commands/review-integration.d.ts +5 -0
  46. package/dist/commands/review-integration.d.ts.map +1 -0
  47. package/dist/commands/review-integration.js +237 -0
  48. package/dist/commands/review-integration.js.map +1 -0
  49. package/dist/commands/review-notify.d.ts +5 -0
  50. package/dist/commands/review-notify.d.ts.map +1 -0
  51. package/dist/commands/review-notify.js +144 -0
  52. package/dist/commands/review-notify.js.map +1 -0
  53. package/dist/commands/review-offline.d.ts +5 -0
  54. package/dist/commands/review-offline.d.ts.map +1 -0
  55. package/dist/commands/review-offline.js +126 -0
  56. package/dist/commands/review-offline.js.map +1 -0
  57. package/dist/commands/review-quota.d.ts +5 -0
  58. package/dist/commands/review-quota.d.ts.map +1 -0
  59. package/dist/commands/review-quota.js +127 -0
  60. package/dist/commands/review-quota.js.map +1 -0
  61. package/dist/commands/review-sandbox.d.ts +5 -0
  62. package/dist/commands/review-sandbox.d.ts.map +1 -0
  63. package/dist/commands/review-sandbox.js +192 -0
  64. package/dist/commands/review-sandbox.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,140 @@
1
+ /**
2
+ * Review-audit-log — Comprehensive local audit log for compliance tracking.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { join, dirname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const LOG_FILE = join(".judges", "audit-log.json");
8
+ function loadLog() {
9
+ if (!existsSync(LOG_FILE))
10
+ return { version: "1.0.0", entries: [] };
11
+ try {
12
+ return JSON.parse(readFileSync(LOG_FILE, "utf-8"));
13
+ }
14
+ catch {
15
+ return { version: "1.0.0", entries: [] };
16
+ }
17
+ }
18
+ function saveLog(log) {
19
+ mkdirSync(dirname(LOG_FILE), { recursive: true });
20
+ writeFileSync(LOG_FILE, JSON.stringify(log, null, 2), "utf-8");
21
+ }
22
+ // ─── CLI ────────────────────────────────────────────────────────────────────
23
+ export function runReviewAuditLog(argv) {
24
+ if (argv.includes("--help") || argv.includes("-h")) {
25
+ console.log(`
26
+ judges review-audit-log — Comprehensive local audit log
27
+
28
+ Usage:
29
+ judges review-audit-log show Show recent audit entries
30
+ judges review-audit-log show --last 20 Show last N entries
31
+ judges review-audit-log record --action review Record an audit entry
32
+ judges review-audit-log search --action suppress Search by action
33
+ judges review-audit-log export --output log.csv Export to CSV
34
+ judges review-audit-log clear Clear audit log
35
+
36
+ Subcommands:
37
+ show Show audit entries
38
+ record Record a new entry
39
+ search Search entries
40
+ export Export log
41
+ clear Clear all entries
42
+
43
+ Options:
44
+ --action <type> Action type (review, suppress, approve, fix, configure, etc.)
45
+ --command <cmd> Command that was run
46
+ --result <text> Result description
47
+ --last <n> Show last N entries (default: 10)
48
+ --output <path> Export file path
49
+ --format json JSON output
50
+ --help, -h Show this help
51
+
52
+ Tracks all review actions locally for compliance and auditability.
53
+ Data stored in .judges/audit-log.json.
54
+ `);
55
+ return;
56
+ }
57
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
58
+ const subcommand = argv.find((a) => ["show", "record", "search", "export", "clear"].includes(a)) || "show";
59
+ const log = loadLog();
60
+ if (subcommand === "record") {
61
+ const action = argv.find((_a, i) => argv[i - 1] === "--action") || "unknown";
62
+ const command = argv.find((_a, i) => argv[i - 1] === "--command") || "";
63
+ const result = argv.find((_a, i) => argv[i - 1] === "--result") || "success";
64
+ const user = process.env.USER || process.env.USERNAME || "unknown";
65
+ const entry = {
66
+ timestamp: new Date().toISOString(),
67
+ action,
68
+ command,
69
+ user,
70
+ details: {},
71
+ result,
72
+ };
73
+ log.entries.push(entry);
74
+ saveLog(log);
75
+ console.log(`Audit entry recorded: ${action} by ${user}`);
76
+ return;
77
+ }
78
+ if (subcommand === "clear") {
79
+ saveLog({ version: "1.0.0", entries: [] });
80
+ console.log("Audit log cleared.");
81
+ return;
82
+ }
83
+ if (subcommand === "search") {
84
+ const action = argv.find((_a, i) => argv[i - 1] === "--action");
85
+ const filtered = action ? log.entries.filter((e) => e.action === action) : log.entries;
86
+ if (format === "json") {
87
+ console.log(JSON.stringify(filtered, null, 2));
88
+ return;
89
+ }
90
+ if (filtered.length === 0) {
91
+ console.log(`No entries found${action ? ` for action "${action}"` : ""}.`);
92
+ return;
93
+ }
94
+ console.log(`\nSearch Results (${filtered.length} entries):`);
95
+ console.log("─".repeat(80));
96
+ for (const e of filtered.slice(-20)) {
97
+ console.log(` ${e.timestamp} [${e.action}] ${e.command || "-"} → ${e.result} (${e.user})`);
98
+ }
99
+ console.log("─".repeat(80));
100
+ return;
101
+ }
102
+ if (subcommand === "export") {
103
+ const output = argv.find((_a, i) => argv[i - 1] === "--output");
104
+ if (!output) {
105
+ console.error("Error: --output is required for export.");
106
+ process.exitCode = 1;
107
+ return;
108
+ }
109
+ const header = "timestamp,action,command,user,result\n";
110
+ const rows = log.entries
111
+ .map((e) => `"${e.timestamp}","${e.action}","${e.command}","${e.user}","${e.result}"`)
112
+ .join("\n");
113
+ mkdirSync(dirname(output), { recursive: true });
114
+ writeFileSync(output, header + rows, "utf-8");
115
+ console.log(`Exported ${log.entries.length} entries to ${output}`);
116
+ return;
117
+ }
118
+ // show
119
+ const lastN = parseInt(argv.find((_a, i) => argv[i - 1] === "--last") || "10", 10);
120
+ const entries = log.entries.slice(-lastN);
121
+ if (format === "json") {
122
+ console.log(JSON.stringify(entries, null, 2));
123
+ return;
124
+ }
125
+ if (entries.length === 0) {
126
+ console.log("No audit entries recorded yet.");
127
+ return;
128
+ }
129
+ console.log(`\nAudit Log (last ${entries.length} of ${log.entries.length}):`);
130
+ console.log("─".repeat(80));
131
+ console.log(" Timestamp Action Command Result");
132
+ console.log("─".repeat(80));
133
+ for (const e of entries) {
134
+ const ts = e.timestamp.slice(0, 19).replace("T", " ");
135
+ console.log(` ${ts} ${e.action.padEnd(12)} ${(e.command || "-").padEnd(20)} ${e.result}`);
136
+ }
137
+ console.log("─".repeat(80));
138
+ console.log(` Total entries: ${log.entries.length}`);
139
+ }
140
+ //# sourceMappingURL=review-audit-log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-audit-log.js","sourceRoot":"","sources":["../../src/commands/review-audit-log.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-badge — Generate status badges for project READMEs.
3
+ */
4
+ export declare function runReviewBadge(argv: string[]): void;
5
+ //# sourceMappingURL=review-badge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-badge.d.ts","sourceRoot":"","sources":["../../src/commands/review-badge.ts"],"names":[],"mappings":"AAAA;;GAEG;AAwDH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAyGnD"}
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Review-badge — Generate status badges for project READMEs.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { dirname } from "path";
6
+ // ─── Badge Generation ───────────────────────────────────────────────────────
7
+ function scoreToGrade(score) {
8
+ if (score >= 9)
9
+ return "A+";
10
+ if (score >= 8)
11
+ return "A";
12
+ if (score >= 7)
13
+ return "B";
14
+ if (score >= 6)
15
+ return "C";
16
+ if (score >= 5)
17
+ return "D";
18
+ return "F";
19
+ }
20
+ function gradeColor(grade) {
21
+ if (grade.startsWith("A"))
22
+ return "brightgreen";
23
+ if (grade === "B")
24
+ return "green";
25
+ if (grade === "C")
26
+ return "yellow";
27
+ if (grade === "D")
28
+ return "orange";
29
+ return "red";
30
+ }
31
+ function generateMarkdownBadge(label, value, color) {
32
+ const encodedLabel = encodeURIComponent(label);
33
+ const encodedValue = encodeURIComponent(value);
34
+ return `![${label}](https://img.shields.io/badge/${encodedLabel}-${encodedValue}-${color})`;
35
+ }
36
+ function generateSvgBadge(label, value, color) {
37
+ const hexColors = {
38
+ brightgreen: "#4c1",
39
+ green: "#97CA00",
40
+ yellow: "#dfb317",
41
+ orange: "#fe7d37",
42
+ red: "#e05d44",
43
+ blue: "#007ec6",
44
+ lightgrey: "#9f9f9f",
45
+ };
46
+ const hex = hexColors[color] || hexColors.lightgrey;
47
+ const labelWidth = label.length * 7 + 10;
48
+ const valueWidth = value.length * 7 + 10;
49
+ const totalWidth = labelWidth + valueWidth;
50
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="${totalWidth}" height="20">
51
+ <rect width="${labelWidth}" height="20" fill="#555"/>
52
+ <rect x="${labelWidth}" width="${valueWidth}" height="20" fill="${hex}"/>
53
+ <text x="${labelWidth / 2}" y="14" fill="#fff" text-anchor="middle" font-family="sans-serif" font-size="11">${label}</text>
54
+ <text x="${labelWidth + valueWidth / 2}" y="14" fill="#fff" text-anchor="middle" font-family="sans-serif" font-size="11">${value}</text>
55
+ </svg>`;
56
+ }
57
+ // ─── CLI ────────────────────────────────────────────────────────────────────
58
+ export function runReviewBadge(argv) {
59
+ if (argv.includes("--help") || argv.includes("-h")) {
60
+ console.log(`
61
+ judges review-badge — Generate status badges for project READMEs
62
+
63
+ Usage:
64
+ judges review-badge --file verdict.json Generate badge from verdict
65
+ judges review-badge --score 8.5 Generate badge from score
66
+ judges review-badge --file v.json --output badge.svg Save SVG badge
67
+ judges review-badge --file v.json --markdown Output markdown badge syntax
68
+
69
+ Options:
70
+ --file <path> Verdict JSON file
71
+ --score <n> Direct score (0-10)
72
+ --output <path> Save badge to file (SVG format)
73
+ --markdown Output markdown badge syntax
74
+ --label <text> Custom badge label (default: "Judges Score")
75
+ --format json JSON output
76
+ --help, -h Show this help
77
+
78
+ Generate badges showing review score/grade for project visibility.
79
+ `);
80
+ return;
81
+ }
82
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
83
+ const label = argv.find((_a, i) => argv[i - 1] === "--label") || "Judges Score";
84
+ const output = argv.find((_a, i) => argv[i - 1] === "--output");
85
+ const scoreArg = argv.find((_a, i) => argv[i - 1] === "--score");
86
+ let score;
87
+ let criticals = 0;
88
+ let findings = 0;
89
+ if (scoreArg) {
90
+ score = parseFloat(scoreArg);
91
+ }
92
+ else {
93
+ const file = argv.find((_a, i) => argv[i - 1] === "--file");
94
+ if (!file || !existsSync(file)) {
95
+ console.error("Error: --file or --score is required.");
96
+ process.exitCode = 1;
97
+ return;
98
+ }
99
+ try {
100
+ const verdict = JSON.parse(readFileSync(file, "utf-8"));
101
+ score = verdict.overallScore || 0;
102
+ criticals = verdict.criticalCount || 0;
103
+ findings = (verdict.findings || []).length;
104
+ }
105
+ catch {
106
+ console.error("Error: Failed to parse verdict file.");
107
+ process.exitCode = 1;
108
+ return;
109
+ }
110
+ }
111
+ const grade = scoreToGrade(score);
112
+ const color = gradeColor(grade);
113
+ const value = `${grade} (${score.toFixed(1)})`;
114
+ if (output) {
115
+ const svg = generateSvgBadge(label, value, color);
116
+ mkdirSync(dirname(output), { recursive: true });
117
+ writeFileSync(output, svg, "utf-8");
118
+ console.log(`Badge saved to ${output}`);
119
+ return;
120
+ }
121
+ if (argv.includes("--markdown")) {
122
+ const md = generateMarkdownBadge(label, value, color);
123
+ console.log(md);
124
+ if (criticals > 0) {
125
+ console.log(generateMarkdownBadge("Critical Findings", String(criticals), "red"));
126
+ }
127
+ if (findings > 0) {
128
+ console.log(generateMarkdownBadge("Total Findings", String(findings), findings > 10 ? "orange" : "blue"));
129
+ }
130
+ return;
131
+ }
132
+ if (format === "json") {
133
+ console.log(JSON.stringify({
134
+ label,
135
+ value,
136
+ grade,
137
+ score,
138
+ color,
139
+ markdown: generateMarkdownBadge(label, value, color),
140
+ criticals,
141
+ findings,
142
+ }, null, 2));
143
+ return;
144
+ }
145
+ console.log(`\nBadge: ${label} — ${value}`);
146
+ console.log(`Grade: ${grade} Color: ${color}`);
147
+ console.log(`\nMarkdown:`);
148
+ console.log(` ${generateMarkdownBadge(label, value, color)}`);
149
+ if (criticals > 0)
150
+ console.log(` ${generateMarkdownBadge("Critical Findings", String(criticals), "red")}`);
151
+ console.log();
152
+ }
153
+ //# sourceMappingURL=review-badge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-badge.js","sourceRoot":"","sources":["../../src/commands/review-badge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-dashboard — Terminal-based dashboard summary of review health.
3
+ */
4
+ export declare function runReviewDashboard(argv: string[]): void;
5
+ //# sourceMappingURL=review-dashboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-dashboard.d.ts","sourceRoot":"","sources":["../../src/commands/review-dashboard.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAqJvD"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Review-dashboard — Terminal-based dashboard summary of review health.
3
+ */
4
+ import { readFileSync, existsSync, readdirSync } from "fs";
5
+ import { join } from "path";
6
+ // ─── CLI ────────────────────────────────────────────────────────────────────
7
+ export function runReviewDashboard(argv) {
8
+ if (argv.includes("--help") || argv.includes("-h")) {
9
+ console.log(`
10
+ judges review-dashboard — Terminal dashboard of review health
11
+
12
+ Usage:
13
+ judges review-dashboard Show dashboard
14
+ judges review-dashboard --dir ./results From verdict directory
15
+ judges review-dashboard --file verdict.json From single file
16
+ judges review-dashboard --format json JSON output
17
+
18
+ Options:
19
+ --file <path> Single verdict file
20
+ --dir <directory> Directory with verdict JSON files
21
+ --format json JSON output
22
+ --help, -h Show this help
23
+
24
+ Displays a summary dashboard with key metrics: score,
25
+ findings by severity, trends, and actionable insights.
26
+ `);
27
+ return;
28
+ }
29
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
30
+ const file = argv.find((_a, i) => argv[i - 1] === "--file");
31
+ const dir = argv.find((_a, i) => argv[i - 1] === "--dir");
32
+ const verdicts = [];
33
+ if (file && existsSync(file)) {
34
+ try {
35
+ verdicts.push(JSON.parse(readFileSync(file, "utf-8")));
36
+ }
37
+ catch {
38
+ /* skip */
39
+ }
40
+ }
41
+ if (dir && existsSync(dir)) {
42
+ try {
43
+ const entries = readdirSync(dir);
44
+ for (const entry of entries) {
45
+ if (typeof entry === "string" && entry.endsWith(".json")) {
46
+ try {
47
+ verdicts.push(JSON.parse(readFileSync(join(dir, entry), "utf-8")));
48
+ }
49
+ catch {
50
+ /* skip */
51
+ }
52
+ }
53
+ }
54
+ }
55
+ catch {
56
+ /* skip */
57
+ }
58
+ }
59
+ if (verdicts.length === 0) {
60
+ console.log("\n No verdict data found. Use --file or --dir to provide verdict JSON files.\n");
61
+ return;
62
+ }
63
+ // Compute metrics
64
+ const scores = verdicts.map((v) => v.overallScore || 0);
65
+ const avgScore = Math.round(scores.reduce((a, b) => a + b, 0) / scores.length);
66
+ const totalFindings = verdicts.reduce((sum, v) => sum + (v.findings || []).length, 0);
67
+ const severityCounts = {};
68
+ for (const v of verdicts) {
69
+ for (const f of v.findings || []) {
70
+ const sev = f.severity || "unknown";
71
+ severityCounts[sev] = (severityCounts[sev] || 0) + 1;
72
+ }
73
+ }
74
+ const criticalCount = severityCounts["critical"] || 0;
75
+ const highCount = severityCounts["high"] || 0;
76
+ const mediumCount = severityCounts["medium"] || 0;
77
+ const lowCount = severityCounts["low"] || 0;
78
+ const passCount = verdicts.filter((v) => v.overallVerdict === "pass").length;
79
+ const failCount = verdicts.filter((v) => v.overallVerdict === "fail").length;
80
+ const grade = avgScore >= 90 ? "A" : avgScore >= 80 ? "B" : avgScore >= 70 ? "C" : avgScore >= 60 ? "D" : "F";
81
+ if (format === "json") {
82
+ console.log(JSON.stringify({
83
+ reviewCount: verdicts.length,
84
+ avgScore,
85
+ grade,
86
+ totalFindings,
87
+ severityCounts,
88
+ passCount,
89
+ failCount,
90
+ }, null, 2));
91
+ return;
92
+ }
93
+ const barLen = Math.round((avgScore / 100) * 20);
94
+ const scoreBar = "█".repeat(barLen) + "░".repeat(20 - barLen);
95
+ console.log(`
96
+ ╔═══════════════════════════════════════════╗
97
+ ║ JUDGES REVIEW DASHBOARD ║
98
+ ╚═══════════════════════════════════════════╝
99
+
100
+ Score: ${scoreBar} ${avgScore}/100 (Grade ${grade})
101
+
102
+ ┌─────────────────────────────────────────┐
103
+ │ Reviews: ${String(verdicts.length).padEnd(6)} Pass: ${String(passCount).padEnd(6)} Fail: ${String(failCount).padEnd(4)}│
104
+ │ Findings: ${String(totalFindings).padEnd(30)}│
105
+ └─────────────────────────────────────────┘
106
+
107
+ Severity Distribution:
108
+ 🔴 Critical: ${"█".repeat(Math.min(criticalCount, 30))} ${criticalCount}
109
+ 🟠 High: ${"█".repeat(Math.min(highCount, 30))} ${highCount}
110
+ 🟡 Medium: ${"█".repeat(Math.min(mediumCount, 30))} ${mediumCount}
111
+ 🟢 Low: ${"█".repeat(Math.min(lowCount, 30))} ${lowCount}
112
+ `);
113
+ // Top rules
114
+ const ruleCounts = new Map();
115
+ for (const v of verdicts) {
116
+ for (const f of v.findings || []) {
117
+ const rule = f.ruleId || "unknown";
118
+ ruleCounts.set(rule, (ruleCounts.get(rule) || 0) + 1);
119
+ }
120
+ }
121
+ const topRules = [...ruleCounts.entries()].sort(([, a], [, b]) => b - a).slice(0, 5);
122
+ if (topRules.length > 0) {
123
+ console.log(" Top Rules:");
124
+ for (const [rule, count] of topRules) {
125
+ console.log(` ${rule.padEnd(30)} ${count} occurrence(s)`);
126
+ }
127
+ console.log();
128
+ }
129
+ // Insights
130
+ console.log(" Insights:");
131
+ if (criticalCount > 0)
132
+ console.log(` ⚠️ ${criticalCount} critical finding(s) require immediate attention`);
133
+ if (failCount > passCount)
134
+ console.log(" ⚠️ More reviews failing than passing — consider reviewing thresholds");
135
+ if (avgScore >= 80)
136
+ console.log(" ✅ Code quality is above target");
137
+ if (totalFindings === 0)
138
+ console.log(" ✅ Clean — no findings detected");
139
+ console.log();
140
+ }
141
+ //# sourceMappingURL=review-dashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-dashboard.js","sourceRoot":"","sources":["../../src/commands/review-dashboard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-diff-summary — Concise summary of changes and findings.
3
+ */
4
+ export declare function runReviewDiffSummary(argv: string[]): void;
5
+ //# sourceMappingURL=review-diff-summary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-diff-summary.d.ts","sourceRoot":"","sources":["../../src/commands/review-diff-summary.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAqLzD"}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Review-diff-summary — Concise summary of changes and findings.
3
+ */
4
+ import { readFileSync, existsSync } from "fs";
5
+ // ─── CLI ────────────────────────────────────────────────────────────────────
6
+ export function runReviewDiffSummary(argv) {
7
+ if (argv.includes("--help") || argv.includes("-h")) {
8
+ console.log(`
9
+ judges review-diff-summary — Concise summary of changes + findings
10
+
11
+ Usage:
12
+ judges review-diff-summary --file verdict.json
13
+ judges review-diff-summary --before before.json --after after.json
14
+ judges review-diff-summary --format json
15
+
16
+ Options:
17
+ --file <path> Single verdict to summarize
18
+ --before <path> Baseline verdict (before changes)
19
+ --after <path> Updated verdict (after changes)
20
+ --max-lines <n> Max summary lines (default: 20)
21
+ --format json JSON output
22
+ --help, -h Show this help
23
+
24
+ Generates a compact, PR-ready summary with key changes
25
+ and finding deltas. Ideal for commit messages or PR descriptions.
26
+ `);
27
+ return;
28
+ }
29
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
30
+ const file = argv.find((_a, i) => argv[i - 1] === "--file");
31
+ const beforeFile = argv.find((_a, i) => argv[i - 1] === "--before");
32
+ const afterFile = argv.find((_a, i) => argv[i - 1] === "--after");
33
+ const maxLines = parseInt(argv.find((_a, i) => argv[i - 1] === "--max-lines") || "20", 10);
34
+ // Comparison mode
35
+ if (beforeFile && afterFile) {
36
+ if (!existsSync(beforeFile) || !existsSync(afterFile)) {
37
+ console.error("Error: Both --before and --after files must exist.");
38
+ process.exitCode = 1;
39
+ return;
40
+ }
41
+ let before;
42
+ let after;
43
+ try {
44
+ before = JSON.parse(readFileSync(beforeFile, "utf-8"));
45
+ after = JSON.parse(readFileSync(afterFile, "utf-8"));
46
+ }
47
+ catch {
48
+ console.error("Error: Could not parse verdict files.");
49
+ process.exitCode = 1;
50
+ return;
51
+ }
52
+ const beforeFindings = before.findings || [];
53
+ const afterFindings = after.findings || [];
54
+ const scoreDelta = (after.overallScore || 0) - (before.overallScore || 0);
55
+ const findingsDelta = afterFindings.length - beforeFindings.length;
56
+ const beforeKeys = new Set(beforeFindings.map(fKey));
57
+ const afterKeys = new Set(afterFindings.map(fKey));
58
+ const resolved = beforeFindings.filter((f) => !afterKeys.has(fKey(f)));
59
+ const introduced = afterFindings.filter((f) => !beforeKeys.has(fKey(f)));
60
+ if (format === "json") {
61
+ console.log(JSON.stringify({
62
+ scoreBefore: before.overallScore || 0,
63
+ scoreAfter: after.overallScore || 0,
64
+ scoreDelta,
65
+ findingsBefore: beforeFindings.length,
66
+ findingsAfter: afterFindings.length,
67
+ findingsDelta,
68
+ resolved: resolved.length,
69
+ introduced: introduced.length,
70
+ }, null, 2));
71
+ return;
72
+ }
73
+ console.log(`\n Review Diff Summary\n ═════════════════════════════`);
74
+ console.log(` Score: ${before.overallScore || 0} → ${after.overallScore || 0} (${scoreDelta >= 0 ? "+" : ""}${scoreDelta})`);
75
+ console.log(` Findings: ${beforeFindings.length} → ${afterFindings.length} (${findingsDelta >= 0 ? "+" : ""}${findingsDelta})`);
76
+ console.log(` Resolved: ${resolved.length} ✅`);
77
+ console.log(` Introduced: ${introduced.length} ${introduced.length > 0 ? "🆕" : ""}`);
78
+ if (resolved.length > 0) {
79
+ console.log("\n Resolved:");
80
+ for (const f of resolved.slice(0, maxLines)) {
81
+ console.log(` ✅ [${(f.severity || "").toUpperCase()}] ${f.title || f.ruleId}`);
82
+ }
83
+ }
84
+ if (introduced.length > 0) {
85
+ console.log("\n Introduced:");
86
+ for (const f of introduced.slice(0, maxLines)) {
87
+ console.log(` 🆕 [${(f.severity || "").toUpperCase()}] ${f.title || f.ruleId}`);
88
+ }
89
+ }
90
+ console.log();
91
+ return;
92
+ }
93
+ // Single-file mode
94
+ if (!file) {
95
+ console.error("Error: --file or both --before and --after are required.");
96
+ process.exitCode = 1;
97
+ return;
98
+ }
99
+ if (!existsSync(file)) {
100
+ console.error(`Error: File not found: ${file}`);
101
+ process.exitCode = 1;
102
+ return;
103
+ }
104
+ let verdict;
105
+ try {
106
+ verdict = JSON.parse(readFileSync(file, "utf-8"));
107
+ }
108
+ catch {
109
+ console.error(`Error: Could not parse ${file}`);
110
+ process.exitCode = 1;
111
+ return;
112
+ }
113
+ const findings = verdict.findings || [];
114
+ const severityCounts = {};
115
+ for (const f of findings) {
116
+ const sev = f.severity || "unknown";
117
+ severityCounts[sev] = (severityCounts[sev] || 0) + 1;
118
+ }
119
+ if (format === "json") {
120
+ console.log(JSON.stringify({
121
+ score: verdict.overallScore || 0,
122
+ verdict: verdict.overallVerdict || "n/a",
123
+ totalFindings: findings.length,
124
+ severityCounts,
125
+ summary: verdict.summary || "",
126
+ }, null, 2));
127
+ return;
128
+ }
129
+ console.log(`\n Review Summary\n ─────────────────────────────`);
130
+ console.log(` Score: ${verdict.overallScore || 0}/100 | Verdict: ${verdict.overallVerdict || "n/a"} | Findings: ${findings.length}`);
131
+ const sevParts = [];
132
+ for (const [sev, count] of Object.entries(severityCounts)) {
133
+ sevParts.push(`${sev}: ${count}`);
134
+ }
135
+ if (sevParts.length > 0) {
136
+ console.log(` ${sevParts.join(" | ")}`);
137
+ }
138
+ if (verdict.summary) {
139
+ console.log(`\n ${verdict.summary}`);
140
+ }
141
+ if (findings.length > 0) {
142
+ console.log("\n Top findings:");
143
+ for (const f of findings.slice(0, Math.min(maxLines, findings.length))) {
144
+ console.log(` [${(f.severity || "").toUpperCase()}] ${f.title || f.ruleId}`);
145
+ }
146
+ if (findings.length > maxLines) {
147
+ console.log(` ... and ${findings.length - maxLines} more`);
148
+ }
149
+ }
150
+ console.log();
151
+ }
152
+ function fKey(f) {
153
+ return [f.ruleId || "", f.title || "", String(f.severity || "")].join("|").toLowerCase();
154
+ }
155
+ //# sourceMappingURL=review-diff-summary.js.map