@kevinrabun/judges 3.81.0 → 3.82.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +63 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/finding-age-tracker.d.ts +8 -0
  6. package/dist/commands/finding-age-tracker.d.ts.map +1 -0
  7. package/dist/commands/finding-age-tracker.js +153 -0
  8. package/dist/commands/finding-age-tracker.js.map +1 -0
  9. package/dist/commands/finding-duplicate-rule.d.ts +5 -0
  10. package/dist/commands/finding-duplicate-rule.d.ts.map +1 -0
  11. package/dist/commands/finding-duplicate-rule.js +104 -0
  12. package/dist/commands/finding-duplicate-rule.js.map +1 -0
  13. package/dist/commands/finding-line-blame.d.ts +8 -0
  14. package/dist/commands/finding-line-blame.d.ts.map +1 -0
  15. package/dist/commands/finding-line-blame.js +133 -0
  16. package/dist/commands/finding-line-blame.js.map +1 -0
  17. package/dist/commands/finding-summary-digest.d.ts +8 -0
  18. package/dist/commands/finding-summary-digest.d.ts.map +1 -0
  19. package/dist/commands/finding-summary-digest.js +146 -0
  20. package/dist/commands/finding-summary-digest.js.map +1 -0
  21. package/dist/commands/review-code-owner.d.ts +8 -0
  22. package/dist/commands/review-code-owner.d.ts.map +1 -0
  23. package/dist/commands/review-code-owner.js +165 -0
  24. package/dist/commands/review-code-owner.js.map +1 -0
  25. package/dist/commands/review-export-pdf.d.ts +8 -0
  26. package/dist/commands/review-export-pdf.d.ts.map +1 -0
  27. package/dist/commands/review-export-pdf.js +132 -0
  28. package/dist/commands/review-export-pdf.js.map +1 -0
  29. package/dist/commands/review-parallel-files.d.ts +8 -0
  30. package/dist/commands/review-parallel-files.d.ts.map +1 -0
  31. package/dist/commands/review-parallel-files.js +135 -0
  32. package/dist/commands/review-parallel-files.js.map +1 -0
  33. package/dist/commands/review-scope-lock.d.ts +8 -0
  34. package/dist/commands/review-scope-lock.d.ts.map +1 -0
  35. package/dist/commands/review-scope-lock.js +139 -0
  36. package/dist/commands/review-scope-lock.js.map +1 -0
  37. package/dist/commands/review-watch-mode.d.ts +8 -0
  38. package/dist/commands/review-watch-mode.d.ts.map +1 -0
  39. package/dist/commands/review-watch-mode.js +133 -0
  40. package/dist/commands/review-watch-mode.js.map +1 -0
  41. package/package.json +1 -1
  42. package/server.json +2 -2
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Finding-age-tracker — Track the age of findings over time.
3
+ *
4
+ * Records when findings first appear and tracks their age,
5
+ * helping prioritize long-standing issues.
6
+ */
7
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
8
+ import { dirname, join } from "path";
9
+ // ─── Helpers ────────────────────────────────────────────────────────────────
10
+ function ageFile() {
11
+ return join(process.cwd(), ".judges", "finding-ages.json");
12
+ }
13
+ function loadAges() {
14
+ const f = ageFile();
15
+ if (!existsSync(f))
16
+ return [];
17
+ try {
18
+ return JSON.parse(readFileSync(f, "utf-8"));
19
+ }
20
+ catch {
21
+ return [];
22
+ }
23
+ }
24
+ function saveAges(ages) {
25
+ const f = ageFile();
26
+ const d = dirname(f);
27
+ if (!existsSync(d))
28
+ mkdirSync(d, { recursive: true });
29
+ writeFileSync(f, JSON.stringify(ages, null, 2));
30
+ }
31
+ function daysBetween(d1, d2) {
32
+ const ms = new Date(d2).getTime() - new Date(d1).getTime();
33
+ return Math.floor(ms / (1000 * 60 * 60 * 24));
34
+ }
35
+ function ageLabel(days) {
36
+ if (days === 0)
37
+ return "new";
38
+ if (days <= 7)
39
+ return `${days}d`;
40
+ if (days <= 30)
41
+ return `${Math.floor(days / 7)}w`;
42
+ return `${Math.floor(days / 30)}mo`;
43
+ }
44
+ // ─── CLI ────────────────────────────────────────────────────────────────────
45
+ export function runFindingAgeTracker(argv) {
46
+ const sub = argv[0];
47
+ if (!sub || sub === "--help" || sub === "-h") {
48
+ console.log(`
49
+ judges finding-age-tracker — Track finding ages
50
+
51
+ Usage:
52
+ judges finding-age-tracker update --file <verdict.json>
53
+ judges finding-age-tracker show [--min-age <days>] [--format table|json]
54
+ judges finding-age-tracker clear
55
+
56
+ Options:
57
+ --file <path> Verdict JSON to record (for update)
58
+ --min-age <days> Show only findings older than N days
59
+ --format <fmt> Output format: table (default), json
60
+ --help, -h Show this help
61
+ `);
62
+ return;
63
+ }
64
+ if (sub === "update") {
65
+ const fileIdx = argv.indexOf("--file");
66
+ const filePath = fileIdx >= 0 ? argv[fileIdx + 1] : undefined;
67
+ if (!filePath) {
68
+ console.error("Error: --file required");
69
+ process.exitCode = 1;
70
+ return;
71
+ }
72
+ if (!existsSync(filePath)) {
73
+ console.error(`Error: file not found: ${filePath}`);
74
+ process.exitCode = 1;
75
+ return;
76
+ }
77
+ let verdict;
78
+ try {
79
+ verdict = JSON.parse(readFileSync(filePath, "utf-8"));
80
+ }
81
+ catch {
82
+ console.error("Error: invalid JSON");
83
+ process.exitCode = 1;
84
+ return;
85
+ }
86
+ const ages = loadAges();
87
+ const now = new Date().toISOString();
88
+ const ageMap = new Map(ages.map((a) => [`${a.ruleId}:${a.title}`, a]));
89
+ for (const f of verdict.findings) {
90
+ const key = `${f.ruleId}:${f.title}`;
91
+ const existing = ageMap.get(key);
92
+ if (existing) {
93
+ existing.lastSeen = now;
94
+ existing.occurrences++;
95
+ }
96
+ else {
97
+ ageMap.set(key, {
98
+ ruleId: f.ruleId,
99
+ title: f.title,
100
+ firstSeen: now,
101
+ lastSeen: now,
102
+ occurrences: 1,
103
+ });
104
+ }
105
+ }
106
+ saveAges([...ageMap.values()]);
107
+ console.log(`Updated: ${verdict.findings.length} findings recorded (${ageMap.size} total tracked)`);
108
+ }
109
+ else if (sub === "show") {
110
+ const minAgeIdx = argv.indexOf("--min-age");
111
+ const formatIdx = argv.indexOf("--format");
112
+ const minAge = minAgeIdx >= 0 ? parseInt(argv[minAgeIdx + 1], 10) : 0;
113
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
114
+ const ages = loadAges();
115
+ if (ages.length === 0) {
116
+ console.log("No age data recorded. Run 'update' first.");
117
+ return;
118
+ }
119
+ const now = new Date().toISOString();
120
+ const filtered = ages
121
+ .map((a) => ({ ...a, ageDays: daysBetween(a.firstSeen, now) }))
122
+ .filter((a) => a.ageDays >= minAge)
123
+ .sort((a, b) => b.ageDays - a.ageDays);
124
+ if (format === "json") {
125
+ console.log(JSON.stringify(filtered, null, 2));
126
+ return;
127
+ }
128
+ console.log(`\nFinding Age Tracker (${filtered.length} findings)`);
129
+ console.log("═".repeat(70));
130
+ console.log(`${"Age".padEnd(8)} ${"Seen".padEnd(6)} ${"Rule".padEnd(25)} Title`);
131
+ console.log("─".repeat(70));
132
+ for (const a of filtered) {
133
+ const age = ageLabel(a.ageDays).padEnd(8);
134
+ const seen = String(a.occurrences).padEnd(6);
135
+ const rule = a.ruleId.length > 23 ? a.ruleId.slice(0, 23) + "…" : a.ruleId;
136
+ const title = a.title.length > 25 ? a.title.slice(0, 25) + "…" : a.title;
137
+ console.log(`${age} ${seen} ${rule.padEnd(25)} ${title}`);
138
+ }
139
+ console.log("─".repeat(70));
140
+ const avgAge = filtered.length > 0 ? (filtered.reduce((s, a) => s + a.ageDays, 0) / filtered.length).toFixed(1) : "0";
141
+ console.log(`Average age: ${avgAge} days`);
142
+ console.log("═".repeat(70));
143
+ }
144
+ else if (sub === "clear") {
145
+ saveAges([]);
146
+ console.log("Finding age data cleared.");
147
+ }
148
+ else {
149
+ console.error(`Unknown subcommand: ${sub}. Use --help for usage.`);
150
+ process.exitCode = 1;
151
+ }
152
+ }
153
+ //# sourceMappingURL=finding-age-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-age-tracker.js","sourceRoot":"","sources":["../../src/commands/finding-age-tracker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Finding-duplicate-rule — Detect duplicate or overlapping rules in findings.
3
+ */
4
+ export declare function runFindingDuplicateRule(argv: string[]): void;
5
+ //# sourceMappingURL=finding-duplicate-rule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-duplicate-rule.d.ts","sourceRoot":"","sources":["../../src/commands/finding-duplicate-rule.ts"],"names":[],"mappings":"AAAA;;GAEG;AA4DH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAiE5D"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Finding-duplicate-rule — Detect duplicate or overlapping rules in findings.
3
+ */
4
+ import { readFileSync, existsSync } from "fs";
5
+ // ─── Helpers ────────────────────────────────────────────────────────────────
6
+ function detectDuplicates(verdict) {
7
+ const groups = new Map();
8
+ for (const f of verdict.findings) {
9
+ // Group by normalized title (lowercase, trimmed)
10
+ const key = f.title.toLowerCase().trim();
11
+ const group = groups.get(key) || { key, count: 0, ruleIds: [], titles: [], lineOverlap: false };
12
+ group.count++;
13
+ if (!group.ruleIds.includes(f.ruleId))
14
+ group.ruleIds.push(f.ruleId);
15
+ if (!group.titles.includes(f.title))
16
+ group.titles.push(f.title);
17
+ groups.set(key, group);
18
+ }
19
+ // Check for line number overlaps between different rule IDs
20
+ const lineMap = new Map();
21
+ for (const f of verdict.findings) {
22
+ if (f.lineNumbers) {
23
+ for (const ln of f.lineNumbers) {
24
+ const rules = lineMap.get(ln) || [];
25
+ if (!rules.includes(f.ruleId))
26
+ rules.push(f.ruleId);
27
+ lineMap.set(ln, rules);
28
+ }
29
+ }
30
+ }
31
+ // Flag groups where multiple rules point to same lines
32
+ for (const [_ln, rules] of lineMap) {
33
+ if (rules.length > 1) {
34
+ for (const [, group] of groups) {
35
+ if (rules.some((r) => group.ruleIds.includes(r))) {
36
+ group.lineOverlap = true;
37
+ }
38
+ }
39
+ }
40
+ }
41
+ return [...groups.values()]
42
+ .filter((g) => g.count > 1 || g.ruleIds.length > 1 || g.lineOverlap)
43
+ .sort((a, b) => b.count - a.count);
44
+ }
45
+ // ─── CLI ────────────────────────────────────────────────────────────────────
46
+ export function runFindingDuplicateRule(argv) {
47
+ const fileIdx = argv.indexOf("--file");
48
+ const formatIdx = argv.indexOf("--format");
49
+ const filePath = fileIdx >= 0 ? argv[fileIdx + 1] : undefined;
50
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
51
+ if (argv.includes("--help") || argv.includes("-h")) {
52
+ console.log(`
53
+ judges finding-duplicate-rule — Detect duplicate or overlapping rules
54
+
55
+ Usage:
56
+ judges finding-duplicate-rule --file <verdict.json> [--format table|json]
57
+
58
+ Options:
59
+ --file <path> Path to verdict JSON file (required)
60
+ --format <fmt> Output format: table (default), json
61
+ --help, -h Show this help
62
+ `);
63
+ return;
64
+ }
65
+ if (!filePath) {
66
+ console.error("Error: --file required");
67
+ process.exitCode = 1;
68
+ return;
69
+ }
70
+ if (!existsSync(filePath)) {
71
+ console.error(`Error: file not found: ${filePath}`);
72
+ process.exitCode = 1;
73
+ return;
74
+ }
75
+ let verdict;
76
+ try {
77
+ verdict = JSON.parse(readFileSync(filePath, "utf-8"));
78
+ }
79
+ catch {
80
+ console.error("Error: invalid JSON");
81
+ process.exitCode = 1;
82
+ return;
83
+ }
84
+ const duplicates = detectDuplicates(verdict);
85
+ if (format === "json") {
86
+ console.log(JSON.stringify(duplicates, null, 2));
87
+ return;
88
+ }
89
+ if (duplicates.length === 0) {
90
+ console.log("No duplicate or overlapping rules detected.");
91
+ return;
92
+ }
93
+ console.log(`\nDuplicate/Overlapping Rules (${duplicates.length} groups)`);
94
+ console.log("═".repeat(70));
95
+ for (const g of duplicates) {
96
+ const overlap = g.lineOverlap ? " [LINE OVERLAP]" : "";
97
+ console.log(`\n "${g.titles[0]}" × ${g.count}${overlap}`);
98
+ console.log(` Rules: ${g.ruleIds.join(", ")}`);
99
+ }
100
+ console.log("\n" + "═".repeat(70));
101
+ const totalDups = duplicates.reduce((s, g) => s + g.count - 1, 0);
102
+ console.log(`${totalDups} duplicate findings across ${duplicates.length} groups`);
103
+ }
104
+ //# sourceMappingURL=finding-duplicate-rule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-duplicate-rule.js","sourceRoot":"","sources":["../../src/commands/finding-duplicate-rule.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Finding-line-blame — Map findings to git blame information.
3
+ *
4
+ * Shows who last modified lines associated with findings,
5
+ * helping attribute findings to specific changes/authors.
6
+ */
7
+ export declare function runFindingLineBlame(argv: string[]): void;
8
+ //# sourceMappingURL=finding-line-blame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-line-blame.d.ts","sourceRoot":"","sources":["../../src/commands/finding-line-blame.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA2DH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAoGxD"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Finding-line-blame — Map findings to git blame information.
3
+ *
4
+ * Shows who last modified lines associated with findings,
5
+ * helping attribute findings to specific changes/authors.
6
+ */
7
+ import { readFileSync, existsSync } from "fs";
8
+ import { execSync } from "child_process";
9
+ // ─── Helpers ────────────────────────────────────────────────────────────────
10
+ function getBlameForLines(file, lines) {
11
+ const results = [];
12
+ for (const line of lines) {
13
+ try {
14
+ const output = execSync(`git blame -L ${line},${line} --porcelain "${file}"`, {
15
+ encoding: "utf-8",
16
+ stdio: ["pipe", "pipe", "pipe"],
17
+ });
18
+ let author = "unknown";
19
+ let date = "";
20
+ let commit = "";
21
+ for (const blameLine of output.split("\n")) {
22
+ if (blameLine.startsWith("author "))
23
+ author = blameLine.slice(7);
24
+ else if (blameLine.startsWith("author-time ")) {
25
+ const ts = parseInt(blameLine.slice(12), 10);
26
+ date = new Date(ts * 1000).toISOString().split("T")[0];
27
+ }
28
+ else if (/^[0-9a-f]{40}/.test(blameLine)) {
29
+ commit = blameLine.split(" ")[0].slice(0, 8);
30
+ }
31
+ }
32
+ results.push({ line, author, date, commit });
33
+ }
34
+ catch {
35
+ /* skip lines that can't be blamed */
36
+ }
37
+ }
38
+ return results;
39
+ }
40
+ // ─── CLI ────────────────────────────────────────────────────────────────────
41
+ export function runFindingLineBlame(argv) {
42
+ const verdictIdx = argv.indexOf("--verdict");
43
+ const fileIdx = argv.indexOf("--file");
44
+ const formatIdx = argv.indexOf("--format");
45
+ const verdictPath = verdictIdx >= 0 ? argv[verdictIdx + 1] : undefined;
46
+ const sourceFile = fileIdx >= 0 ? argv[fileIdx + 1] : undefined;
47
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
48
+ if (argv.includes("--help") || argv.includes("-h")) {
49
+ console.log(`
50
+ judges finding-line-blame — Map findings to git blame
51
+
52
+ Usage:
53
+ judges finding-line-blame --verdict <verdict.json> --file <source>
54
+ [--format table|json]
55
+
56
+ Options:
57
+ --verdict <path> Path to verdict JSON file (required)
58
+ --file <path> Source file to blame (required)
59
+ --format <fmt> Output format: table (default), json
60
+ --help, -h Show this help
61
+ `);
62
+ return;
63
+ }
64
+ if (!verdictPath || !sourceFile) {
65
+ console.error("Error: --verdict and --file required");
66
+ process.exitCode = 1;
67
+ return;
68
+ }
69
+ if (!existsSync(verdictPath)) {
70
+ console.error(`Error: verdict not found: ${verdictPath}`);
71
+ process.exitCode = 1;
72
+ return;
73
+ }
74
+ if (!existsSync(sourceFile)) {
75
+ console.error(`Error: file not found: ${sourceFile}`);
76
+ process.exitCode = 1;
77
+ return;
78
+ }
79
+ let verdict;
80
+ try {
81
+ verdict = JSON.parse(readFileSync(verdictPath, "utf-8"));
82
+ }
83
+ catch {
84
+ console.error("Error: invalid verdict JSON");
85
+ process.exitCode = 1;
86
+ return;
87
+ }
88
+ const results = [];
89
+ for (const f of verdict.findings) {
90
+ if (!f.lineNumbers || f.lineNumbers.length === 0)
91
+ continue;
92
+ const blameLines = getBlameForLines(sourceFile, f.lineNumbers);
93
+ if (blameLines.length > 0) {
94
+ results.push({
95
+ ruleId: f.ruleId,
96
+ title: f.title,
97
+ severity: f.severity || "medium",
98
+ blameLines,
99
+ });
100
+ }
101
+ }
102
+ if (format === "json") {
103
+ console.log(JSON.stringify(results, null, 2));
104
+ return;
105
+ }
106
+ if (results.length === 0) {
107
+ console.log("No blame data available for findings.");
108
+ return;
109
+ }
110
+ console.log(`\nFinding Line Blame — ${sourceFile}`);
111
+ console.log("═".repeat(70));
112
+ for (const r of results) {
113
+ console.log(`\n [${r.severity.toUpperCase()}] ${r.title}`);
114
+ console.log(` Rule: ${r.ruleId}`);
115
+ for (const b of r.blameLines) {
116
+ console.log(` L${b.line}: ${b.author} (${b.date}) ${b.commit}`);
117
+ }
118
+ }
119
+ // Author summary
120
+ const authorCounts = new Map();
121
+ for (const r of results) {
122
+ for (const b of r.blameLines) {
123
+ authorCounts.set(b.author, (authorCounts.get(b.author) || 0) + 1);
124
+ }
125
+ }
126
+ console.log("\n" + "─".repeat(70));
127
+ console.log("Author Summary:");
128
+ for (const [author, count] of [...authorCounts.entries()].sort((a, b) => b[1] - a[1])) {
129
+ console.log(` ${author}: ${count} finding line(s)`);
130
+ }
131
+ console.log("═".repeat(70));
132
+ }
133
+ //# sourceMappingURL=finding-line-blame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-line-blame.js","sourceRoot":"","sources":["../../src/commands/finding-line-blame.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Finding-summary-digest — Generate concise digests of finding summaries.
3
+ *
4
+ * Creates executive-style summaries of review results suitable for
5
+ * stakeholder communication and quick decision-making.
6
+ */
7
+ export declare function runFindingSummaryDigest(argv: string[]): void;
8
+ //# sourceMappingURL=finding-summary-digest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-summary-digest.d.ts","sourceRoot":"","sources":["../../src/commands/finding-summary-digest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAgGH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAmE5D"}
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Finding-summary-digest — Generate concise digests of finding summaries.
3
+ *
4
+ * Creates executive-style summaries of review results suitable for
5
+ * stakeholder communication and quick decision-making.
6
+ */
7
+ import { readFileSync, existsSync } from "fs";
8
+ // ─── Helpers ────────────────────────────────────────────────────────────────
9
+ function severityEmoji(severity) {
10
+ switch (severity.toLowerCase()) {
11
+ case "critical":
12
+ return "[CRIT]";
13
+ case "high":
14
+ return "[HIGH]";
15
+ case "medium":
16
+ return "[MED]";
17
+ case "low":
18
+ return "[LOW]";
19
+ default:
20
+ return "[INFO]";
21
+ }
22
+ }
23
+ function generateDigest(verdict) {
24
+ const lines = [];
25
+ const total = verdict.findings.length;
26
+ // Header
27
+ lines.push("REVIEW DIGEST");
28
+ lines.push("=".repeat(50));
29
+ // Status
30
+ const status = verdict.overallVerdict === "pass" ? "PASS" : "FAIL";
31
+ lines.push(`Status: ${status} | Score: ${verdict.overallScore} | Findings: ${total}`);
32
+ lines.push("");
33
+ // Severity distribution
34
+ const sevCounts = { critical: 0, high: 0, medium: 0, low: 0, info: 0 };
35
+ for (const f of verdict.findings) {
36
+ const sev = (f.severity || "medium").toLowerCase();
37
+ sevCounts[sev] = (sevCounts[sev] || 0) + 1;
38
+ }
39
+ lines.push("Severity Distribution:");
40
+ for (const [sev, count] of Object.entries(sevCounts)) {
41
+ if (count > 0) {
42
+ const bar = "█".repeat(Math.min(count, 20));
43
+ lines.push(` ${sev.padEnd(10)} ${bar} ${count}`);
44
+ }
45
+ }
46
+ lines.push("");
47
+ // Top findings by severity
48
+ const criticalAndHigh = verdict.findings
49
+ .filter((f) => ["critical", "high"].includes((f.severity || "medium").toLowerCase()))
50
+ .slice(0, 5);
51
+ if (criticalAndHigh.length > 0) {
52
+ lines.push("Priority Findings:");
53
+ for (const f of criticalAndHigh) {
54
+ lines.push(` ${severityEmoji(f.severity || "medium")} ${f.title}`);
55
+ if (f.recommendation) {
56
+ const rec = f.recommendation.length > 60 ? f.recommendation.slice(0, 60) + "…" : f.recommendation;
57
+ lines.push(` Fix: ${rec}`);
58
+ }
59
+ }
60
+ lines.push("");
61
+ }
62
+ // Rule coverage
63
+ const rules = new Set(verdict.findings.map((f) => f.ruleId));
64
+ lines.push(`Rules triggered: ${rules.size}`);
65
+ // Judge participation
66
+ if (verdict.evaluations && verdict.evaluations.length > 0) {
67
+ const passing = verdict.evaluations.filter((e) => e.verdict === "pass").length;
68
+ lines.push(`Judges: ${passing}/${verdict.evaluations.length} passing`);
69
+ }
70
+ lines.push("");
71
+ lines.push("=".repeat(50));
72
+ // Action items
73
+ if (sevCounts["critical"] > 0) {
74
+ lines.push(`ACTION REQUIRED: ${sevCounts["critical"]} critical finding(s) must be addressed before merge.`);
75
+ }
76
+ else if (sevCounts["high"] > 0) {
77
+ lines.push(`RECOMMENDED: Address ${sevCounts["high"]} high-severity finding(s) before merge.`);
78
+ }
79
+ else if (total > 0) {
80
+ lines.push(`ADVISORY: ${total} finding(s) for review. No blockers detected.`);
81
+ }
82
+ else {
83
+ lines.push("CLEAN: No findings detected.");
84
+ }
85
+ return lines.join("\n");
86
+ }
87
+ // ─── CLI ────────────────────────────────────────────────────────────────────
88
+ export function runFindingSummaryDigest(argv) {
89
+ const fileIdx = argv.indexOf("--file");
90
+ const formatIdx = argv.indexOf("--format");
91
+ const filePath = fileIdx >= 0 ? argv[fileIdx + 1] : undefined;
92
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "text";
93
+ if (argv.includes("--help") || argv.includes("-h")) {
94
+ console.log(`
95
+ judges finding-summary-digest — Generate concise finding digests
96
+
97
+ Usage:
98
+ judges finding-summary-digest --file <verdict.json> [--format text|json]
99
+
100
+ Options:
101
+ --file <path> Path to verdict JSON file (required)
102
+ --format <fmt> Output format: text (default), json
103
+ --help, -h Show this help
104
+ `);
105
+ return;
106
+ }
107
+ if (!filePath) {
108
+ console.error("Error: --file required");
109
+ process.exitCode = 1;
110
+ return;
111
+ }
112
+ if (!existsSync(filePath)) {
113
+ console.error(`Error: file not found: ${filePath}`);
114
+ process.exitCode = 1;
115
+ return;
116
+ }
117
+ let verdict;
118
+ try {
119
+ verdict = JSON.parse(readFileSync(filePath, "utf-8"));
120
+ }
121
+ catch {
122
+ console.error("Error: invalid JSON");
123
+ process.exitCode = 1;
124
+ return;
125
+ }
126
+ if (format === "json") {
127
+ const sevCounts = { critical: 0, high: 0, medium: 0, low: 0, info: 0 };
128
+ for (const f of verdict.findings) {
129
+ const sev = (f.severity || "medium").toLowerCase();
130
+ sevCounts[sev] = (sevCounts[sev] || 0) + 1;
131
+ }
132
+ console.log(JSON.stringify({
133
+ status: verdict.overallVerdict,
134
+ score: verdict.overallScore,
135
+ totalFindings: verdict.findings.length,
136
+ severityCounts: sevCounts,
137
+ rulesTriggered: new Set(verdict.findings.map((f) => f.ruleId)).size,
138
+ topFindings: verdict.findings
139
+ .slice(0, 5)
140
+ .map((f) => ({ title: f.title, severity: f.severity, ruleId: f.ruleId })),
141
+ }, null, 2));
142
+ return;
143
+ }
144
+ console.log(generateDigest(verdict));
145
+ }
146
+ //# sourceMappingURL=finding-summary-digest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-summary-digest.js","sourceRoot":"","sources":["../../src/commands/finding-summary-digest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Review-code-owner — Map findings to CODEOWNERS entries.
3
+ *
4
+ * Cross-references findings with CODEOWNERS file to identify
5
+ * responsible teams/individuals for each finding.
6
+ */
7
+ export declare function runReviewCodeOwner(argv: string[]): void;
8
+ //# sourceMappingURL=review-code-owner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-code-owner.d.ts","sourceRoot":"","sources":["../../src/commands/review-code-owner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAkEH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA0HvD"}