@kevinrabun/judges 3.62.0 → 3.63.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 (38) 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/finding-group.d.ts +16 -0
  6. package/dist/commands/finding-group.d.ts.map +1 -0
  7. package/dist/commands/finding-group.js +165 -0
  8. package/dist/commands/finding-group.js.map +1 -0
  9. package/dist/commands/ignore-list.d.ts +19 -0
  10. package/dist/commands/ignore-list.d.ts.map +1 -0
  11. package/dist/commands/ignore-list.js +166 -0
  12. package/dist/commands/ignore-list.js.map +1 -0
  13. package/dist/commands/incremental-review.d.ts +5 -0
  14. package/dist/commands/incremental-review.d.ts.map +1 -0
  15. package/dist/commands/incremental-review.js +240 -0
  16. package/dist/commands/incremental-review.js.map +1 -0
  17. package/dist/commands/review-cache.d.ts +23 -0
  18. package/dist/commands/review-cache.d.ts.map +1 -0
  19. package/dist/commands/review-cache.js +135 -0
  20. package/dist/commands/review-cache.js.map +1 -0
  21. package/dist/commands/review-log.d.ts +23 -0
  22. package/dist/commands/review-log.d.ts.map +1 -0
  23. package/dist/commands/review-log.js +165 -0
  24. package/dist/commands/review-log.js.map +1 -0
  25. package/dist/commands/review-summary.d.ts +5 -0
  26. package/dist/commands/review-summary.d.ts.map +1 -0
  27. package/dist/commands/review-summary.js +175 -0
  28. package/dist/commands/review-summary.js.map +1 -0
  29. package/dist/commands/rule-test.d.ts +5 -0
  30. package/dist/commands/rule-test.d.ts.map +1 -0
  31. package/dist/commands/rule-test.js +216 -0
  32. package/dist/commands/rule-test.js.map +1 -0
  33. package/dist/commands/team-config.d.ts +5 -0
  34. package/dist/commands/team-config.d.ts.map +1 -0
  35. package/dist/commands/team-config.js +235 -0
  36. package/dist/commands/team-config.js.map +1 -0
  37. package/package.json +1 -1
  38. package/server.json +2 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-cache.d.ts","sourceRoot":"","sources":["../../src/commands/review-cache.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,UAAU,YAAY;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACjE;AAiBD,iBAAS,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEzC;AAMD,iBAAS,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAezE;AAED,iBAAS,SAAS,CAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,GAC9D,IAAI,CAaN;AA2CD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAgDnD;AAGD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Review-cache — Cache review results to avoid re-analyzing unchanged files.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, unlinkSync } from "fs";
5
+ import { join } from "path";
6
+ import { createHash } from "crypto";
7
+ // ─── Cache operations ──────────────────────────────────────────────────────
8
+ function getCacheDir() {
9
+ return join(".", ".judges", "review-cache");
10
+ }
11
+ function hashFile(content) {
12
+ return createHash("sha256").update(content).digest("hex").slice(0, 16);
13
+ }
14
+ function cacheKey(filePath) {
15
+ return createHash("sha256").update(filePath).digest("hex").slice(0, 16);
16
+ }
17
+ function getCached(filePath, content) {
18
+ const dir = getCacheDir();
19
+ const key = cacheKey(filePath);
20
+ const cachePath = join(dir, `${key}.json`);
21
+ if (!existsSync(cachePath))
22
+ return null;
23
+ try {
24
+ const cached = JSON.parse(readFileSync(cachePath, "utf-8"));
25
+ const currentHash = hashFile(content);
26
+ if (cached.fileHash === currentHash)
27
+ return cached;
28
+ return null; // File changed, cache invalid
29
+ }
30
+ catch {
31
+ return null;
32
+ }
33
+ }
34
+ function setCached(filePath, content, findings) {
35
+ const dir = getCacheDir();
36
+ if (!existsSync(dir))
37
+ mkdirSync(dir, { recursive: true });
38
+ const key = cacheKey(filePath);
39
+ const result = {
40
+ fileHash: hashFile(content),
41
+ timestamp: new Date().toISOString(),
42
+ findingCount: findings.length,
43
+ findings,
44
+ };
45
+ writeFileSync(join(dir, `${key}.json`), JSON.stringify(result), "utf-8");
46
+ }
47
+ function getCacheStats() {
48
+ const dir = getCacheDir();
49
+ if (!existsSync(dir))
50
+ return { entries: 0, hits: 0, misses: 0, sizeBytes: 0, oldestEntry: "", newestEntry: "" };
51
+ const files = readdirSync(dir).filter((f) => f.endsWith(".json"));
52
+ let totalSize = 0;
53
+ let oldest = "";
54
+ let newest = "";
55
+ for (const f of files) {
56
+ try {
57
+ const content = readFileSync(join(dir, f), "utf-8");
58
+ totalSize += content.length;
59
+ const parsed = JSON.parse(content);
60
+ if (!oldest || parsed.timestamp < oldest)
61
+ oldest = parsed.timestamp;
62
+ if (!newest || parsed.timestamp > newest)
63
+ newest = parsed.timestamp;
64
+ }
65
+ catch {
66
+ // skip
67
+ }
68
+ }
69
+ return { entries: files.length, hits: 0, misses: 0, sizeBytes: totalSize, oldestEntry: oldest, newestEntry: newest };
70
+ }
71
+ function clearCache() {
72
+ const dir = getCacheDir();
73
+ if (!existsSync(dir))
74
+ return 0;
75
+ const files = readdirSync(dir).filter((f) => f.endsWith(".json"));
76
+ for (const f of files) {
77
+ try {
78
+ unlinkSync(join(dir, f));
79
+ }
80
+ catch {
81
+ // skip
82
+ }
83
+ }
84
+ return files.length;
85
+ }
86
+ // ─── CLI ────────────────────────────────────────────────────────────────────
87
+ export function runReviewCache(argv) {
88
+ if (argv.includes("--help") || argv.includes("-h")) {
89
+ console.log(`
90
+ judges review-cache — Manage review result cache
91
+
92
+ Usage:
93
+ judges review-cache stats Show cache statistics
94
+ judges review-cache clear Clear all cached results
95
+ judges review-cache --format json JSON output
96
+
97
+ Subcommands:
98
+ stats Show cache statistics
99
+ clear Clear all cached results
100
+
101
+ Options:
102
+ --format json JSON output
103
+ --help, -h Show this help
104
+
105
+ Review results are cached in .judges/review-cache/ based on file content
106
+ hashes. When a file hasn't changed, cached results are reused for faster
107
+ subsequent reviews.
108
+ `);
109
+ return;
110
+ }
111
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
112
+ const subcommand = argv.find((a) => !a.startsWith("-") && a !== "review-cache") || "stats";
113
+ if (subcommand === "clear") {
114
+ const count = clearCache();
115
+ console.log(`Cleared ${count} cached review result(s).`);
116
+ return;
117
+ }
118
+ // Stats
119
+ const stats = getCacheStats();
120
+ if (format === "json") {
121
+ console.log(JSON.stringify(stats, null, 2));
122
+ return;
123
+ }
124
+ console.log(`\n Review Cache\n ─────────────────────────────`);
125
+ console.log(` Entries: ${stats.entries}`);
126
+ console.log(` Size: ${Math.round(stats.sizeBytes / 1024)} KB`);
127
+ if (stats.oldestEntry)
128
+ console.log(` Oldest: ${stats.oldestEntry.slice(0, 10)}`);
129
+ if (stats.newestEntry)
130
+ console.log(` Newest: ${stats.newestEntry.slice(0, 10)}`);
131
+ console.log();
132
+ }
133
+ // Export helpers for use by other commands
134
+ export { getCached, setCached, hashFile };
135
+ //# sourceMappingURL=review-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-cache.js","sourceRoot":"","sources":["../../src/commands/review-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Review-log — Structured audit log of all review actions for compliance.
3
+ */
4
+ interface ReviewLogEntry {
5
+ timestamp: string;
6
+ action: string;
7
+ command: string;
8
+ filesReviewed: number;
9
+ findingsCount: number;
10
+ severity: {
11
+ critical: number;
12
+ high: number;
13
+ medium: number;
14
+ low: number;
15
+ };
16
+ duration: number;
17
+ user: string;
18
+ commit: string;
19
+ }
20
+ declare function appendLog(entry: ReviewLogEntry): void;
21
+ export declare function runReviewLog(argv: string[]): void;
22
+ export { appendLog, ReviewLogEntry };
23
+ //# sourceMappingURL=review-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-log.d.ts","sourceRoot":"","sources":["../../src/commands/review-log.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,UAAU,cAAc;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1E,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAwBD,iBAAS,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAK9C;AA2DD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAuGjD;AAGD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Review-log — Structured audit log of all review actions for compliance.
3
+ */
4
+ import { readFileSync, existsSync, mkdirSync, appendFileSync, readdirSync } from "fs";
5
+ import { join } from "path";
6
+ // ─── Helpers ────────────────────────────────────────────────────────────────
7
+ function getLogDir() {
8
+ return join(".", ".judges", "logs");
9
+ }
10
+ function getLogFile() {
11
+ const dir = getLogDir();
12
+ const date = new Date().toISOString().slice(0, 7); // YYYY-MM
13
+ return join(dir, `review-log-${date}.jsonl`);
14
+ }
15
+ function appendLog(entry) {
16
+ const dir = getLogDir();
17
+ if (!existsSync(dir))
18
+ mkdirSync(dir, { recursive: true });
19
+ const logFile = getLogFile();
20
+ appendFileSync(logFile, JSON.stringify(entry) + "\n", "utf-8");
21
+ }
22
+ function readAllLogs() {
23
+ const dir = getLogDir();
24
+ if (!existsSync(dir))
25
+ return [];
26
+ const entries = [];
27
+ const files = readdirSync(dir).filter((f) => f.endsWith(".jsonl")).sort();
28
+ for (const f of files) {
29
+ try {
30
+ const content = readFileSync(join(dir, f), "utf-8");
31
+ const lines = content.split("\n").filter((l) => l.trim());
32
+ for (const line of lines) {
33
+ try {
34
+ entries.push(JSON.parse(line));
35
+ }
36
+ catch {
37
+ // skip invalid lines
38
+ }
39
+ }
40
+ }
41
+ catch {
42
+ // skip unreadable files
43
+ }
44
+ }
45
+ return entries;
46
+ }
47
+ function summarizeLogs(entries) {
48
+ if (entries.length === 0) {
49
+ return {
50
+ totalEntries: 0,
51
+ recentEntries: [],
52
+ totalFilesReviewed: 0,
53
+ totalFindings: 0,
54
+ averageDuration: 0,
55
+ firstEntry: "",
56
+ lastEntry: "",
57
+ };
58
+ }
59
+ const sorted = [...entries].sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
60
+ const totalFiles = entries.reduce((s, e) => s + e.filesReviewed, 0);
61
+ const totalFindings = entries.reduce((s, e) => s + e.findingsCount, 0);
62
+ const totalDuration = entries.reduce((s, e) => s + e.duration, 0);
63
+ return {
64
+ totalEntries: entries.length,
65
+ recentEntries: sorted.slice(-10),
66
+ totalFilesReviewed: totalFiles,
67
+ totalFindings,
68
+ averageDuration: Math.round(totalDuration / entries.length),
69
+ firstEntry: sorted[0].timestamp,
70
+ lastEntry: sorted[sorted.length - 1].timestamp,
71
+ };
72
+ }
73
+ // ─── CLI ────────────────────────────────────────────────────────────────────
74
+ export function runReviewLog(argv) {
75
+ if (argv.includes("--help") || argv.includes("-h")) {
76
+ console.log(`
77
+ judges review-log — Structured audit log of review actions
78
+
79
+ Usage:
80
+ judges review-log show Show log summary
81
+ judges review-log record --command eval --files 10 --findings 5
82
+ judges review-log export Export all logs as JSON
83
+ judges review-log --format json JSON output
84
+
85
+ Subcommands:
86
+ show Show log summary and recent entries
87
+ record Record a review action to the log
88
+ export Export complete log as JSON
89
+
90
+ Record Options:
91
+ --command <name> Command that was run
92
+ --files <n> Number of files reviewed
93
+ --findings <n> Number of findings
94
+ --critical <n> Critical findings count
95
+ --high <n> High findings count
96
+ --medium <n> Medium findings count
97
+ --low <n> Low findings count
98
+ --duration <ms> Duration in milliseconds
99
+ --commit <hash> Associated commit
100
+
101
+ Logs are stored locally in .judges/logs/ as monthly JSONL files.
102
+ `);
103
+ return;
104
+ }
105
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
106
+ const subcommand = argv.find((a) => !a.startsWith("-") && a !== "review-log") || "show";
107
+ if (subcommand === "record") {
108
+ const getNum = (flag) => {
109
+ const val = argv.find((_a, i) => argv[i - 1] === flag);
110
+ return val ? parseInt(val, 10) : 0;
111
+ };
112
+ const getStr = (flag) => {
113
+ return argv.find((_a, i) => argv[i - 1] === flag) || "";
114
+ };
115
+ const entry = {
116
+ timestamp: new Date().toISOString(),
117
+ action: "review",
118
+ command: getStr("--command") || "unknown",
119
+ filesReviewed: getNum("--files"),
120
+ findingsCount: getNum("--findings"),
121
+ severity: {
122
+ critical: getNum("--critical"),
123
+ high: getNum("--high"),
124
+ medium: getNum("--medium"),
125
+ low: getNum("--low"),
126
+ },
127
+ duration: getNum("--duration"),
128
+ user: process.env.USER || process.env.USERNAME || "unknown",
129
+ commit: getStr("--commit"),
130
+ };
131
+ appendLog(entry);
132
+ console.log(`Logged review action: ${entry.command} (${entry.findingsCount} findings, ${entry.filesReviewed} files).`);
133
+ return;
134
+ }
135
+ if (subcommand === "export") {
136
+ const entries = readAllLogs();
137
+ console.log(JSON.stringify(entries, null, 2));
138
+ return;
139
+ }
140
+ // Show
141
+ const entries = readAllLogs();
142
+ const summary = summarizeLogs(entries);
143
+ if (format === "json") {
144
+ console.log(JSON.stringify(summary, null, 2));
145
+ return;
146
+ }
147
+ console.log(`\n Review Log\n ─────────────────────────────`);
148
+ console.log(` Total entries: ${summary.totalEntries}`);
149
+ console.log(` Total files reviewed: ${summary.totalFilesReviewed}`);
150
+ console.log(` Total findings: ${summary.totalFindings}`);
151
+ console.log(` Average duration: ${summary.averageDuration}ms`);
152
+ if (summary.firstEntry) {
153
+ console.log(` Period: ${summary.firstEntry.slice(0, 10)} to ${summary.lastEntry.slice(0, 10)}`);
154
+ }
155
+ if (summary.recentEntries.length > 0) {
156
+ console.log("\n Recent entries:");
157
+ for (const e of summary.recentEntries) {
158
+ console.log(` ${e.timestamp.slice(0, 19)} ${e.command} — ${e.findingsCount} findings, ${e.filesReviewed} files, ${e.duration}ms`);
159
+ }
160
+ }
161
+ console.log();
162
+ }
163
+ // Export for use by other commands
164
+ export { appendLog };
165
+ //# sourceMappingURL=review-log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-log.js","sourceRoot":"","sources":["../../src/commands/review-log.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-summary — Generate PR-ready review summaries with key metrics.
3
+ */
4
+ export declare function runReviewSummary(argv: string[]): void;
5
+ //# sourceMappingURL=review-summary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-summary.d.ts","sourceRoot":"","sources":["../../src/commands/review-summary.ts"],"names":[],"mappings":"AAAA;;GAEG;AAiIH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAqFrD"}
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Review-summary — Generate PR-ready review summaries with key metrics.
3
+ */
4
+ import { readFileSync } from "fs";
5
+ // ─── Metrics extraction ─────────────────────────────────────────────────────
6
+ function extractMetrics(verdict) {
7
+ const findings = verdict.findings || [];
8
+ const severityCounts = { critical: 0, high: 0, medium: 0, low: 0 };
9
+ const ruleCounts = new Map();
10
+ for (const f of findings) {
11
+ const sev = f.severity || "low";
12
+ severityCounts[sev] = (severityCounts[sev] || 0) + 1;
13
+ const rid = f.ruleId || "unknown";
14
+ ruleCounts.set(rid, (ruleCounts.get(rid) || 0) + 1);
15
+ }
16
+ const topRules = [...ruleCounts.entries()]
17
+ .sort((a, b) => b[1] - a[1])
18
+ .slice(0, 5)
19
+ .map(([ruleId, count]) => ({ ruleId, count }));
20
+ return {
21
+ totalFindings: findings.length,
22
+ criticalCount: severityCounts["critical"],
23
+ highCount: severityCounts["high"],
24
+ mediumCount: severityCounts["medium"],
25
+ lowCount: severityCounts["low"],
26
+ judgeCount: verdict.evaluations?.length || 0,
27
+ overallScore: verdict.overallScore ?? 0,
28
+ overallVerdict: verdict.overallVerdict || "unknown",
29
+ topRules,
30
+ };
31
+ }
32
+ // ─── Formatters ─────────────────────────────────────────────────────────────
33
+ function severityEmoji(count, level) {
34
+ if (count === 0)
35
+ return `✅ 0 ${level}`;
36
+ if (level === "critical")
37
+ return `🔴 ${count} ${level}`;
38
+ if (level === "high")
39
+ return `🟠 ${count} ${level}`;
40
+ if (level === "medium")
41
+ return `🟡 ${count} ${level}`;
42
+ return `🔵 ${count} ${level}`;
43
+ }
44
+ function verdictEmoji(verdict) {
45
+ const map = {
46
+ pass: "✅ PASS",
47
+ fail: "❌ FAIL",
48
+ warning: "⚠️ WARNING",
49
+ };
50
+ return map[verdict] || verdict.toUpperCase();
51
+ }
52
+ function formatMarkdown(metrics) {
53
+ const lines = [];
54
+ lines.push(`## Judges Review Summary`);
55
+ lines.push(``);
56
+ lines.push(`**Verdict:** ${verdictEmoji(metrics.overallVerdict)} | **Score:** ${metrics.overallScore}/100 | **Judges:** ${metrics.judgeCount}`);
57
+ lines.push(``);
58
+ lines.push(`| Severity | Count |`);
59
+ lines.push(`|----------|-------|`);
60
+ lines.push(`| ${severityEmoji(metrics.criticalCount, "critical")} | ${metrics.criticalCount} |`);
61
+ lines.push(`| ${severityEmoji(metrics.highCount, "high")} | ${metrics.highCount} |`);
62
+ lines.push(`| ${severityEmoji(metrics.mediumCount, "medium")} | ${metrics.mediumCount} |`);
63
+ lines.push(`| ${severityEmoji(metrics.lowCount, "low")} | ${metrics.lowCount} |`);
64
+ lines.push(`| **Total** | **${metrics.totalFindings}** |`);
65
+ if (metrics.topRules.length > 0) {
66
+ lines.push(``);
67
+ lines.push(`**Top Rules:**`);
68
+ for (const r of metrics.topRules) {
69
+ lines.push(`- \`${r.ruleId}\` (${r.count})`);
70
+ }
71
+ }
72
+ lines.push(``);
73
+ lines.push(`---`);
74
+ lines.push(`*Generated by [Judges Panel](https://github.com/KevinRabun/judges)*`);
75
+ return lines.join("\n");
76
+ }
77
+ function formatSlack(metrics) {
78
+ const lines = [];
79
+ lines.push(`*Judges Review Summary*`);
80
+ lines.push(`Verdict: ${verdictEmoji(metrics.overallVerdict)} | Score: ${metrics.overallScore}/100 | Judges: ${metrics.judgeCount}`);
81
+ lines.push(``);
82
+ lines.push(`${severityEmoji(metrics.criticalCount, "critical")} | ${severityEmoji(metrics.highCount, "high")} | ${severityEmoji(metrics.mediumCount, "medium")} | ${severityEmoji(metrics.lowCount, "low")}`);
83
+ lines.push(`Total: ${metrics.totalFindings} findings`);
84
+ if (metrics.topRules.length > 0) {
85
+ lines.push(``);
86
+ lines.push(`Top rules: ${metrics.topRules.map((r) => `${r.ruleId} (${r.count})`).join(", ")}`);
87
+ }
88
+ return lines.join("\n");
89
+ }
90
+ function formatOneLiner(metrics) {
91
+ return `${verdictEmoji(metrics.overallVerdict)} Score: ${metrics.overallScore}/100 | ${metrics.totalFindings} findings (${metrics.criticalCount}C/${metrics.highCount}H/${metrics.mediumCount}M/${metrics.lowCount}L) | ${metrics.judgeCount} judges`;
92
+ }
93
+ // ─── CLI ────────────────────────────────────────────────────────────────────
94
+ export function runReviewSummary(argv) {
95
+ if (argv.includes("--help") || argv.includes("-h")) {
96
+ console.log(`
97
+ judges review-summary — Generate PR-ready review summary
98
+
99
+ Usage:
100
+ judges review-summary --input verdict.json
101
+ judges review-summary --input verdict.json --style markdown
102
+ judges review-summary --input verdict.json --style slack
103
+ judges review-summary --format json
104
+
105
+ Options:
106
+ --input <file> JSON file with TribunalVerdict (required)
107
+ --style <type> Output style: text, markdown, slack, oneliner (default: text)
108
+ --format json Raw JSON metrics output
109
+ --help, -h Show this help
110
+
111
+ Styles:
112
+ text Plain text summary (default)
113
+ markdown GitHub PR description format
114
+ slack Slack message format
115
+ oneliner Single-line summary
116
+
117
+ Generates a concise, copy-pasteable review summary suitable for
118
+ PR descriptions, Slack messages, or CI logs.
119
+ `);
120
+ return;
121
+ }
122
+ const inputPath = argv.find((_a, i) => argv[i - 1] === "--input");
123
+ const style = argv.find((_a, i) => argv[i - 1] === "--style") || "text";
124
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
125
+ if (!inputPath) {
126
+ console.error("Error: --input is required. Provide a JSON verdict file.");
127
+ process.exitCode = 1;
128
+ return;
129
+ }
130
+ let verdict;
131
+ try {
132
+ const raw = readFileSync(inputPath, "utf-8");
133
+ verdict = JSON.parse(raw);
134
+ }
135
+ catch {
136
+ console.error(`Error: Cannot read or parse ${inputPath}`);
137
+ process.exitCode = 1;
138
+ return;
139
+ }
140
+ const metrics = extractMetrics(verdict);
141
+ if (format === "json") {
142
+ console.log(JSON.stringify(metrics, null, 2));
143
+ return;
144
+ }
145
+ switch (style) {
146
+ case "markdown":
147
+ console.log(formatMarkdown(metrics));
148
+ break;
149
+ case "slack":
150
+ console.log(formatSlack(metrics));
151
+ break;
152
+ case "oneliner":
153
+ console.log(formatOneLiner(metrics));
154
+ break;
155
+ default:
156
+ console.log(`\n Review Summary\n ─────────────────────────────`);
157
+ console.log(` Verdict: ${verdictEmoji(metrics.overallVerdict)}`);
158
+ console.log(` Score: ${metrics.overallScore}/100`);
159
+ console.log(` Judges: ${metrics.judgeCount}`);
160
+ console.log(` Total findings: ${metrics.totalFindings}`);
161
+ console.log(` ${severityEmoji(metrics.criticalCount, "critical")}`);
162
+ console.log(` ${severityEmoji(metrics.highCount, "high")}`);
163
+ console.log(` ${severityEmoji(metrics.mediumCount, "medium")}`);
164
+ console.log(` ${severityEmoji(metrics.lowCount, "low")}`);
165
+ if (metrics.topRules.length > 0) {
166
+ console.log(`\n Top Rules:`);
167
+ for (const r of metrics.topRules) {
168
+ console.log(` ${r.ruleId} (${r.count})`);
169
+ }
170
+ }
171
+ console.log();
172
+ break;
173
+ }
174
+ }
175
+ //# sourceMappingURL=review-summary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-summary.js","sourceRoot":"","sources":["../../src/commands/review-summary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Rule-test — Test custom rules against sample code before deployment.
3
+ */
4
+ export declare function runRuleTest(argv: string[]): void;
5
+ //# sourceMappingURL=rule-test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-test.d.ts","sourceRoot":"","sources":["../../src/commands/rule-test.ts"],"names":[],"mappings":"AAAA;;GAEG;AA6HH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAsIhD"}