@kevinrabun/judges 3.71.0 → 3.73.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 +24 -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-deduplicate.d.ts +5 -0
  6. package/dist/commands/finding-deduplicate.d.ts.map +1 -0
  7. package/dist/commands/finding-deduplicate.js +142 -0
  8. package/dist/commands/finding-deduplicate.js.map +1 -0
  9. package/dist/commands/finding-false-positive.d.ts +5 -0
  10. package/dist/commands/finding-false-positive.d.ts.map +1 -0
  11. package/dist/commands/finding-false-positive.js +135 -0
  12. package/dist/commands/finding-false-positive.js.map +1 -0
  13. package/dist/commands/finding-link.d.ts +5 -0
  14. package/dist/commands/finding-link.d.ts.map +1 -0
  15. package/dist/commands/finding-link.js +129 -0
  16. package/dist/commands/finding-link.js.map +1 -0
  17. package/dist/commands/finding-severity-override.d.ts +5 -0
  18. package/dist/commands/finding-severity-override.d.ts.map +1 -0
  19. package/dist/commands/finding-severity-override.js +132 -0
  20. package/dist/commands/finding-severity-override.js.map +1 -0
  21. package/dist/commands/review-approval.d.ts +5 -0
  22. package/dist/commands/review-approval.d.ts.map +1 -0
  23. package/dist/commands/review-approval.js +134 -0
  24. package/dist/commands/review-approval.js.map +1 -0
  25. package/dist/commands/review-bulk-action.d.ts +5 -0
  26. package/dist/commands/review-bulk-action.d.ts.map +1 -0
  27. package/dist/commands/review-bulk-action.js +110 -0
  28. package/dist/commands/review-bulk-action.js.map +1 -0
  29. package/dist/commands/review-compare-version.d.ts +5 -0
  30. package/dist/commands/review-compare-version.d.ts.map +1 -0
  31. package/dist/commands/review-compare-version.js +109 -0
  32. package/dist/commands/review-compare-version.js.map +1 -0
  33. package/dist/commands/review-config-export.d.ts +5 -0
  34. package/dist/commands/review-config-export.d.ts.map +1 -0
  35. package/dist/commands/review-config-export.js +125 -0
  36. package/dist/commands/review-config-export.js.map +1 -0
  37. package/dist/commands/review-depth.d.ts +5 -0
  38. package/dist/commands/review-depth.d.ts.map +1 -0
  39. package/dist/commands/review-depth.js +143 -0
  40. package/dist/commands/review-depth.js.map +1 -0
  41. package/dist/commands/review-feedback.d.ts +5 -0
  42. package/dist/commands/review-feedback.d.ts.map +1 -0
  43. package/dist/commands/review-feedback.js +146 -0
  44. package/dist/commands/review-feedback.js.map +1 -0
  45. package/dist/commands/review-ignore-path.d.ts +5 -0
  46. package/dist/commands/review-ignore-path.d.ts.map +1 -0
  47. package/dist/commands/review-ignore-path.js +148 -0
  48. package/dist/commands/review-ignore-path.js.map +1 -0
  49. package/dist/commands/review-pr-comment.d.ts +5 -0
  50. package/dist/commands/review-pr-comment.d.ts.map +1 -0
  51. package/dist/commands/review-pr-comment.js +107 -0
  52. package/dist/commands/review-pr-comment.js.map +1 -0
  53. package/dist/commands/review-retry.d.ts +5 -0
  54. package/dist/commands/review-retry.d.ts.map +1 -0
  55. package/dist/commands/review-retry.js +92 -0
  56. package/dist/commands/review-retry.js.map +1 -0
  57. package/dist/commands/review-score-history.d.ts +5 -0
  58. package/dist/commands/review-score-history.d.ts.map +1 -0
  59. package/dist/commands/review-score-history.js +138 -0
  60. package/dist/commands/review-score-history.js.map +1 -0
  61. package/dist/commands/review-session.d.ts +5 -0
  62. package/dist/commands/review-session.d.ts.map +1 -0
  63. package/dist/commands/review-session.js +151 -0
  64. package/dist/commands/review-session.js.map +1 -0
  65. package/dist/commands/review-summary-email.d.ts +5 -0
  66. package/dist/commands/review-summary-email.d.ts.map +1 -0
  67. package/dist/commands/review-summary-email.js +103 -0
  68. package/dist/commands/review-summary-email.js.map +1 -0
  69. package/package.json +1 -1
  70. package/server.json +2 -2
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Review-retry — Retry failed or incomplete reviews.
3
+ */
4
+ import { readFileSync, existsSync, readdirSync } from "fs";
5
+ // ─── CLI ────────────────────────────────────────────────────────────────────
6
+ export function runReviewRetry(argv) {
7
+ if (argv.includes("--help") || argv.includes("-h")) {
8
+ console.log(`
9
+ judges review-retry — Retry failed or incomplete reviews
10
+
11
+ Usage:
12
+ judges review-retry Show retry candidates
13
+ judges review-retry scan Scan for failed reviews
14
+ judges review-retry list List retry candidates
15
+ judges review-retry clear Clear retry state
16
+
17
+ Subcommands:
18
+ (default) Show retry candidates
19
+ scan Scan for reviews that need retry
20
+ list List candidates with details
21
+ clear Clear retry state
22
+
23
+ Options:
24
+ --threshold <n> Score threshold for retry (default: 5)
25
+ --dir <path> Override results directory
26
+ --format json JSON output
27
+ --help, -h Show this help
28
+
29
+ Detects reviews that scored below threshold or had errors.
30
+ `);
31
+ return;
32
+ }
33
+ const subcommand = argv.find((a) => ["scan", "list", "clear"].includes(a));
34
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
35
+ const threshold = parseFloat(argv.find((_a, i) => argv[i - 1] === "--threshold") || "5");
36
+ const dir = argv.find((_a, i) => argv[i - 1] === "--dir") || ".judges/results";
37
+ if (subcommand === "clear") {
38
+ console.log("Retry state cleared.");
39
+ return;
40
+ }
41
+ // Scan for candidates
42
+ const candidates = [];
43
+ if (existsSync(dir)) {
44
+ try {
45
+ const files = readdirSync(dir);
46
+ for (const f of files) {
47
+ if (!String(f).endsWith(".json"))
48
+ continue;
49
+ try {
50
+ const content = JSON.parse(readFileSync(`${dir}/${String(f)}`, "utf-8"));
51
+ const score = typeof content.overallScore === "number" ? content.overallScore : 0;
52
+ const status = score < threshold ? "below-threshold" : "ok";
53
+ if (status === "below-threshold") {
54
+ candidates.push({
55
+ file: String(f),
56
+ lastReview: content.timestamp || "unknown",
57
+ status,
58
+ score,
59
+ });
60
+ }
61
+ }
62
+ catch {
63
+ candidates.push({
64
+ file: String(f),
65
+ lastReview: "unknown",
66
+ status: "parse-error",
67
+ score: 0,
68
+ });
69
+ }
70
+ }
71
+ }
72
+ catch {
73
+ // Directory not readable
74
+ }
75
+ }
76
+ if (format === "json") {
77
+ console.log(JSON.stringify({ threshold, candidates }, null, 2));
78
+ return;
79
+ }
80
+ if (candidates.length === 0) {
81
+ console.log(`No retry candidates (threshold: ${threshold}).`);
82
+ return;
83
+ }
84
+ console.log(`\nRetry Candidates (score < ${threshold}):`);
85
+ console.log("─".repeat(60));
86
+ for (const c of candidates) {
87
+ console.log(` ${c.file} score=${c.score.toFixed(1)} status=${c.status}`);
88
+ }
89
+ console.log("─".repeat(60));
90
+ console.log(`\n${candidates.length} review(s) eligible for retry.`);
91
+ }
92
+ //# sourceMappingURL=review-retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-retry.js","sourceRoot":"","sources":["../../src/commands/review-retry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-score-history — Track review scores over time.
3
+ */
4
+ export declare function runReviewScoreHistory(argv: string[]): void;
5
+ //# sourceMappingURL=review-score-history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-score-history.d.ts","sourceRoot":"","sources":["../../src/commands/review-score-history.ts"],"names":[],"mappings":"AAAA;;GAEG;AA+EH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAoG1D"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Review-score-history — Track review scores over time.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { join, dirname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const SCORE_FILE = join(".judges", "score-history.json");
8
+ function loadStore() {
9
+ if (!existsSync(SCORE_FILE))
10
+ return { version: "1.0.0", entries: [] };
11
+ try {
12
+ return JSON.parse(readFileSync(SCORE_FILE, "utf-8"));
13
+ }
14
+ catch {
15
+ return { version: "1.0.0", entries: [] };
16
+ }
17
+ }
18
+ function saveStore(store) {
19
+ mkdirSync(dirname(SCORE_FILE), { recursive: true });
20
+ writeFileSync(SCORE_FILE, JSON.stringify(store, null, 2), "utf-8");
21
+ }
22
+ // ─── Trend Calculation ──────────────────────────────────────────────────────
23
+ function calculateTrend(entries) {
24
+ if (entries.length === 0) {
25
+ return { direction: "stable", avgScore: 0, minScore: 0, maxScore: 0, recentAvg: 0, totalEntries: 0 };
26
+ }
27
+ const scores = entries.map((e) => e.score);
28
+ const avgScore = scores.reduce((a, b) => a + b, 0) / scores.length;
29
+ const minScore = Math.min(...scores);
30
+ const maxScore = Math.max(...scores);
31
+ const recentCount = Math.min(5, entries.length);
32
+ const recentScores = entries.slice(-recentCount).map((e) => e.score);
33
+ const recentAvg = recentScores.reduce((a, b) => a + b, 0) / recentScores.length;
34
+ let direction = "stable";
35
+ if (entries.length >= 3) {
36
+ const oldAvg = entries.slice(0, Math.floor(entries.length / 2)).reduce((s, e) => s + e.score, 0) /
37
+ Math.floor(entries.length / 2);
38
+ const newAvg = entries.slice(Math.floor(entries.length / 2)).reduce((s, e) => s + e.score, 0) /
39
+ (entries.length - Math.floor(entries.length / 2));
40
+ if (newAvg - oldAvg > 0.5)
41
+ direction = "improving";
42
+ else if (oldAvg - newAvg > 0.5)
43
+ direction = "declining";
44
+ }
45
+ return { direction, avgScore, minScore, maxScore, recentAvg, totalEntries: entries.length };
46
+ }
47
+ // ─── CLI ────────────────────────────────────────────────────────────────────
48
+ export function runReviewScoreHistory(argv) {
49
+ if (argv.includes("--help") || argv.includes("-h")) {
50
+ console.log(`
51
+ judges review-score-history — Track review scores over time
52
+
53
+ Usage:
54
+ judges review-score-history Show score trend
55
+ judges review-score-history add --score 8.5 --source "sprint-42"
56
+ judges review-score-history list
57
+ judges review-score-history clear
58
+
59
+ Subcommands:
60
+ (default) Show score trend analysis
61
+ add Add a score entry
62
+ list List all entries
63
+ clear Clear score history
64
+
65
+ Options:
66
+ --score <n> Review score
67
+ --source <text> Source description
68
+ --findings <n> Number of findings
69
+ --format json JSON output
70
+ --help, -h Show this help
71
+
72
+ Score history stored in .judges/score-history.json.
73
+ `);
74
+ return;
75
+ }
76
+ const subcommand = argv.find((a) => ["add", "list", "clear"].includes(a));
77
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
78
+ const store = loadStore();
79
+ if (subcommand === "add") {
80
+ const score = parseFloat(argv.find((_a, i) => argv[i - 1] === "--score") || "0");
81
+ const source = argv.find((_a, i) => argv[i - 1] === "--source") || "";
82
+ const findings = parseInt(argv.find((_a, i) => argv[i - 1] === "--findings") || "0", 10);
83
+ store.entries.push({ date: new Date().toISOString(), score, findingCount: findings, source });
84
+ saveStore(store);
85
+ console.log(`Added score ${score.toFixed(1)} to history.`);
86
+ return;
87
+ }
88
+ if (subcommand === "clear") {
89
+ saveStore({ version: "1.0.0", entries: [] });
90
+ console.log("Score history cleared.");
91
+ return;
92
+ }
93
+ if (subcommand === "list") {
94
+ if (store.entries.length === 0) {
95
+ console.log("No score entries.");
96
+ return;
97
+ }
98
+ if (format === "json") {
99
+ console.log(JSON.stringify(store.entries, null, 2));
100
+ return;
101
+ }
102
+ console.log("\nScore History:");
103
+ console.log("─".repeat(60));
104
+ for (const e of store.entries) {
105
+ console.log(` ${e.date.slice(0, 10)} score=${e.score.toFixed(1)} findings=${e.findingCount} ${e.source}`);
106
+ }
107
+ console.log("─".repeat(60));
108
+ return;
109
+ }
110
+ // Default: show trend
111
+ if (store.entries.length === 0) {
112
+ console.log("No score data. Use 'judges review-score-history add' to start tracking.");
113
+ return;
114
+ }
115
+ const trend = calculateTrend(store.entries);
116
+ if (format === "json") {
117
+ console.log(JSON.stringify(trend, null, 2));
118
+ return;
119
+ }
120
+ const directionIcon = trend.direction === "improving" ? "↗" : trend.direction === "declining" ? "↘" : "→";
121
+ console.log("\nScore Trend Analysis:");
122
+ console.log("═".repeat(50));
123
+ console.log(` Direction: ${trend.direction} ${directionIcon}`);
124
+ console.log(` Avg Score: ${trend.avgScore.toFixed(1)} Recent Avg: ${trend.recentAvg.toFixed(1)}`);
125
+ console.log(` Min: ${trend.minScore.toFixed(1)} Max: ${trend.maxScore.toFixed(1)}`);
126
+ console.log(` Total entries: ${trend.totalEntries}`);
127
+ console.log("═".repeat(50));
128
+ // Simple sparkline
129
+ const last10 = store.entries.slice(-10);
130
+ if (last10.length > 1) {
131
+ console.log("\n Recent scores:");
132
+ for (const e of last10) {
133
+ const bar = "█".repeat(Math.round(e.score));
134
+ console.log(` ${e.date.slice(0, 10)} ${bar} ${e.score.toFixed(1)}`);
135
+ }
136
+ }
137
+ }
138
+ //# sourceMappingURL=review-score-history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-score-history.js","sourceRoot":"","sources":["../../src/commands/review-score-history.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-session — Group reviews into named sessions for project phases.
3
+ */
4
+ export declare function runReviewSession(argv: string[]): void;
5
+ //# sourceMappingURL=review-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-session.d.ts","sourceRoot":"","sources":["../../src/commands/review-session.ts"],"names":[],"mappings":"AAAA;;GAEG;AA8CH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAsIrD"}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Review-session — Group reviews into named sessions for project phases.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { dirname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const SESSION_FILE = ".judges/sessions.json";
8
+ function loadStore() {
9
+ if (!existsSync(SESSION_FILE))
10
+ return { version: "1.0.0", sessions: [] };
11
+ try {
12
+ return JSON.parse(readFileSync(SESSION_FILE, "utf-8"));
13
+ }
14
+ catch {
15
+ return { version: "1.0.0", sessions: [] };
16
+ }
17
+ }
18
+ function saveStore(store) {
19
+ mkdirSync(dirname(SESSION_FILE), { recursive: true });
20
+ writeFileSync(SESSION_FILE, JSON.stringify(store, null, 2), "utf-8");
21
+ }
22
+ function generateId() {
23
+ return `ses-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
24
+ }
25
+ // ─── CLI ────────────────────────────────────────────────────────────────────
26
+ export function runReviewSession(argv) {
27
+ if (argv.includes("--help") || argv.includes("-h")) {
28
+ console.log(`
29
+ judges review-session — Group reviews into named sessions
30
+
31
+ Usage:
32
+ judges review-session start --name "sprint-42"
33
+ judges review-session end
34
+ judges review-session log --reviews 5 --findings 12
35
+ judges review-session list
36
+ judges review-session show --id <id>
37
+ judges review-session clear
38
+
39
+ Subcommands:
40
+ start Start a new session
41
+ end End the active session
42
+ log Log review activity to active session
43
+ list List all sessions
44
+ show Show session details
45
+ clear Clear all sessions
46
+
47
+ Options:
48
+ --name <text> Session name
49
+ --id <id> Session ID
50
+ --reviews <n> Number of reviews to log
51
+ --findings <n> Number of findings to log
52
+ --format json JSON output
53
+ --help, -h Show this help
54
+
55
+ Sessions stored in .judges/sessions.json.
56
+ `);
57
+ return;
58
+ }
59
+ const subcommand = argv.find((a) => ["start", "end", "log", "list", "show", "clear"].includes(a));
60
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
61
+ const store = loadStore();
62
+ if (subcommand === "start") {
63
+ const name = argv.find((_a, i) => argv[i - 1] === "--name") || `session-${store.sessions.length + 1}`;
64
+ // Close any active session
65
+ for (const s of store.sessions) {
66
+ if (s.status === "active") {
67
+ s.status = "closed";
68
+ s.endedAt = new Date().toISOString();
69
+ }
70
+ }
71
+ const session = {
72
+ id: generateId(),
73
+ name,
74
+ startedAt: new Date().toISOString(),
75
+ endedAt: "",
76
+ reviewCount: 0,
77
+ findingCount: 0,
78
+ status: "active",
79
+ };
80
+ store.sessions.push(session);
81
+ saveStore(store);
82
+ console.log(`Session started: "${name}" (${session.id})`);
83
+ return;
84
+ }
85
+ if (subcommand === "end") {
86
+ const active = store.sessions.find((s) => s.status === "active");
87
+ if (!active) {
88
+ console.log("No active session.");
89
+ return;
90
+ }
91
+ active.status = "closed";
92
+ active.endedAt = new Date().toISOString();
93
+ saveStore(store);
94
+ console.log(`Session ended: "${active.name}" — ${active.reviewCount} reviews, ${active.findingCount} findings.`);
95
+ return;
96
+ }
97
+ if (subcommand === "log") {
98
+ const active = store.sessions.find((s) => s.status === "active");
99
+ if (!active) {
100
+ console.log("No active session. Start one with 'judges review-session start'.");
101
+ return;
102
+ }
103
+ const reviews = parseInt(argv.find((_a, i) => argv[i - 1] === "--reviews") || "1", 10);
104
+ const findings = parseInt(argv.find((_a, i) => argv[i - 1] === "--findings") || "0", 10);
105
+ active.reviewCount += reviews;
106
+ active.findingCount += findings;
107
+ saveStore(store);
108
+ console.log(`Logged to "${active.name}": +${reviews} reviews, +${findings} findings.`);
109
+ return;
110
+ }
111
+ if (subcommand === "show") {
112
+ const id = argv.find((_a, i) => argv[i - 1] === "--id") || "";
113
+ const session = store.sessions.find((s) => s.id === id);
114
+ if (!session) {
115
+ console.log(`Session ${id} not found.`);
116
+ return;
117
+ }
118
+ if (format === "json") {
119
+ console.log(JSON.stringify(session, null, 2));
120
+ return;
121
+ }
122
+ console.log(`\nSession: ${session.name} (${session.id})`);
123
+ console.log(` Status: ${session.status}`);
124
+ console.log(` Started: ${session.startedAt}`);
125
+ console.log(` Ended: ${session.endedAt || "(active)"}`);
126
+ console.log(` Reviews: ${session.reviewCount} Findings: ${session.findingCount}`);
127
+ return;
128
+ }
129
+ if (subcommand === "clear") {
130
+ saveStore({ version: "1.0.0", sessions: [] });
131
+ console.log("Sessions cleared.");
132
+ return;
133
+ }
134
+ // Default: list
135
+ if (store.sessions.length === 0) {
136
+ console.log("No sessions. Start one with 'judges review-session start'.");
137
+ return;
138
+ }
139
+ if (format === "json") {
140
+ console.log(JSON.stringify(store.sessions, null, 2));
141
+ return;
142
+ }
143
+ console.log("\nReview Sessions:");
144
+ console.log("─".repeat(60));
145
+ for (const s of store.sessions) {
146
+ const status = s.status === "active" ? "[ACTIVE]" : "[closed]";
147
+ console.log(` ${s.id} ${status} "${s.name}" reviews=${s.reviewCount} findings=${s.findingCount}`);
148
+ }
149
+ console.log("─".repeat(60));
150
+ }
151
+ //# sourceMappingURL=review-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-session.js","sourceRoot":"","sources":["../../src/commands/review-session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-summary-email — Generate email-ready review summaries.
3
+ */
4
+ export declare function runReviewSummaryEmail(argv: string[]): void;
5
+ //# sourceMappingURL=review-summary-email.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-summary-email.d.ts","sourceRoot":"","sources":["../../src/commands/review-summary-email.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAiH1D"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Review-summary-email — Generate email-ready review summaries.
3
+ */
4
+ import { readFileSync, existsSync } from "fs";
5
+ // ─── CLI ────────────────────────────────────────────────────────────────────
6
+ export function runReviewSummaryEmail(argv) {
7
+ if (argv.includes("--help") || argv.includes("-h")) {
8
+ console.log(`
9
+ judges review-summary-email — Generate email-ready review summaries
10
+
11
+ Usage:
12
+ judges review-summary-email --file results.json
13
+ judges review-summary-email --file results.json --to team@example.com
14
+ judges review-summary-email --file results.json --format json
15
+
16
+ Options:
17
+ --file <path> Path to review result JSON
18
+ --to <email> Recipient (included in subject line, not sent)
19
+ --subject <text> Custom subject line
20
+ --format json JSON output
21
+ --help, -h Show this help
22
+
23
+ Generates a formatted text suitable for copy-paste into email.
24
+ Does NOT send email — output is local only.
25
+ `);
26
+ return;
27
+ }
28
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
29
+ const filePath = argv.find((_a, i) => argv[i - 1] === "--file") || "";
30
+ const to = argv.find((_a, i) => argv[i - 1] === "--to") || "";
31
+ const customSubject = argv.find((_a, i) => argv[i - 1] === "--subject") || "";
32
+ if (!filePath) {
33
+ console.log("Specify --file <path> to a review result JSON.");
34
+ return;
35
+ }
36
+ if (!existsSync(filePath)) {
37
+ console.log(`File not found: ${filePath}`);
38
+ return;
39
+ }
40
+ let data;
41
+ try {
42
+ data = JSON.parse(readFileSync(filePath, "utf-8"));
43
+ }
44
+ catch {
45
+ console.log(`Failed to parse: ${filePath}`);
46
+ return;
47
+ }
48
+ const score = typeof data.overallScore === "number" ? data.overallScore : 0;
49
+ const verdict = typeof data.overallVerdict === "string" ? data.overallVerdict : "unknown";
50
+ const summary = typeof data.summary === "string" ? data.summary : "";
51
+ const criticalCount = typeof data.criticalCount === "number" ? data.criticalCount : 0;
52
+ const highCount = typeof data.highCount === "number" ? data.highCount : 0;
53
+ const findings = Array.isArray(data.findings) ? data.findings : [];
54
+ const timestamp = typeof data.timestamp === "string" ? data.timestamp : new Date().toISOString();
55
+ const subject = customSubject || `Code Review Report — Score ${score.toFixed(1)}/10 (${verdict})`;
56
+ if (format === "json") {
57
+ console.log(JSON.stringify({
58
+ to,
59
+ subject,
60
+ body: { score, verdict, summary, criticalCount, highCount, findingCount: findings.length, timestamp },
61
+ }, null, 2));
62
+ return;
63
+ }
64
+ // Generate email text
65
+ const lines = [];
66
+ lines.push("─".repeat(60));
67
+ if (to)
68
+ lines.push(`To: ${to}`);
69
+ lines.push(`Subject: ${subject}`);
70
+ lines.push(`Date: ${timestamp.slice(0, 10)}`);
71
+ lines.push("─".repeat(60));
72
+ lines.push("");
73
+ lines.push("CODE REVIEW SUMMARY");
74
+ lines.push("═".repeat(40));
75
+ lines.push(`Score: ${score.toFixed(1)} / 10`);
76
+ lines.push(`Verdict: ${verdict.toUpperCase()}`);
77
+ lines.push(`Findings: ${findings.length} total (${criticalCount} critical, ${highCount} high)`);
78
+ lines.push("");
79
+ if (summary) {
80
+ lines.push("Overview:");
81
+ lines.push(` ${summary}`);
82
+ lines.push("");
83
+ }
84
+ if (findings.length > 0) {
85
+ lines.push("Top Findings:");
86
+ const top = findings.slice(0, 5);
87
+ for (const f of top) {
88
+ const sev = typeof f === "object" && f && "severity" in f ? String(f.severity) : "?";
89
+ const title = typeof f === "object" && f && "title" in f ? String(f.title) : "untitled";
90
+ const rule = typeof f === "object" && f && "ruleId" in f ? String(f.ruleId) : "";
91
+ lines.push(` [${sev.toUpperCase()}] ${rule} — ${title}`);
92
+ }
93
+ if (findings.length > 5) {
94
+ lines.push(` ... and ${findings.length - 5} more findings`);
95
+ }
96
+ lines.push("");
97
+ }
98
+ lines.push("─".repeat(60));
99
+ lines.push("Generated by Judges Panel — https://github.com/KevinRabun/judges");
100
+ lines.push("─".repeat(60));
101
+ console.log(lines.join("\n"));
102
+ }
103
+ //# sourceMappingURL=review-summary-email.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-summary-email.js","sourceRoot":"","sources":["../../src/commands/review-summary-email.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.71.0",
3
+ "version": "3.73.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",
package/server.json CHANGED
@@ -7,12 +7,12 @@
7
7
  "url": "https://github.com/kevinrabun/judges",
8
8
  "source": "github"
9
9
  },
10
- "version": "3.71.0",
10
+ "version": "3.73.0",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "identifier": "@kevinrabun/judges",
15
- "version": "3.71.0",
15
+ "version": "3.73.0",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  }