@kevinrabun/judges 3.90.0 → 3.92.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 (78) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +126 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/finding-auto-group.d.ts +5 -0
  6. package/dist/commands/finding-auto-group.d.ts.map +1 -0
  7. package/dist/commands/finding-auto-group.js +109 -0
  8. package/dist/commands/finding-auto-group.js.map +1 -0
  9. package/dist/commands/finding-blast-radius.d.ts +5 -0
  10. package/dist/commands/finding-blast-radius.d.ts.map +1 -0
  11. package/dist/commands/finding-blast-radius.js +92 -0
  12. package/dist/commands/finding-blast-radius.js.map +1 -0
  13. package/dist/commands/finding-cross-ref.d.ts +5 -0
  14. package/dist/commands/finding-cross-ref.d.ts.map +1 -0
  15. package/dist/commands/finding-cross-ref.js +99 -0
  16. package/dist/commands/finding-cross-ref.js.map +1 -0
  17. package/dist/commands/finding-hotspot-map.d.ts +5 -0
  18. package/dist/commands/finding-hotspot-map.d.ts.map +1 -0
  19. package/dist/commands/finding-hotspot-map.js +107 -0
  20. package/dist/commands/finding-hotspot-map.js.map +1 -0
  21. package/dist/commands/finding-metadata-enrich.d.ts +5 -0
  22. package/dist/commands/finding-metadata-enrich.d.ts.map +1 -0
  23. package/dist/commands/finding-metadata-enrich.js +93 -0
  24. package/dist/commands/finding-metadata-enrich.js.map +1 -0
  25. package/dist/commands/finding-pattern-detect.d.ts +5 -0
  26. package/dist/commands/finding-pattern-detect.d.ts.map +1 -0
  27. package/dist/commands/finding-pattern-detect.js +128 -0
  28. package/dist/commands/finding-pattern-detect.js.map +1 -0
  29. package/dist/commands/finding-suppression-list.d.ts +5 -0
  30. package/dist/commands/finding-suppression-list.d.ts.map +1 -0
  31. package/dist/commands/finding-suppression-list.js +120 -0
  32. package/dist/commands/finding-suppression-list.js.map +1 -0
  33. package/dist/commands/review-annotation-export.d.ts +5 -0
  34. package/dist/commands/review-annotation-export.d.ts.map +1 -0
  35. package/dist/commands/review-annotation-export.js +106 -0
  36. package/dist/commands/review-annotation-export.js.map +1 -0
  37. package/dist/commands/review-cache-warm.d.ts +5 -0
  38. package/dist/commands/review-cache-warm.d.ts.map +1 -0
  39. package/dist/commands/review-cache-warm.js +71 -0
  40. package/dist/commands/review-cache-warm.js.map +1 -0
  41. package/dist/commands/review-ci-gate.d.ts +5 -0
  42. package/dist/commands/review-ci-gate.d.ts.map +1 -0
  43. package/dist/commands/review-ci-gate.js +115 -0
  44. package/dist/commands/review-ci-gate.js.map +1 -0
  45. package/dist/commands/review-coverage-gap.d.ts +5 -0
  46. package/dist/commands/review-coverage-gap.d.ts.map +1 -0
  47. package/dist/commands/review-coverage-gap.js +121 -0
  48. package/dist/commands/review-coverage-gap.js.map +1 -0
  49. package/dist/commands/review-feedback-loop.d.ts +5 -0
  50. package/dist/commands/review-feedback-loop.d.ts.map +1 -0
  51. package/dist/commands/review-feedback-loop.js +114 -0
  52. package/dist/commands/review-feedback-loop.js.map +1 -0
  53. package/dist/commands/review-merge-config.d.ts +5 -0
  54. package/dist/commands/review-merge-config.d.ts.map +1 -0
  55. package/dist/commands/review-merge-config.js +120 -0
  56. package/dist/commands/review-merge-config.js.map +1 -0
  57. package/dist/commands/review-onboard-wizard.d.ts +5 -0
  58. package/dist/commands/review-onboard-wizard.d.ts.map +1 -0
  59. package/dist/commands/review-onboard-wizard.js +93 -0
  60. package/dist/commands/review-onboard-wizard.js.map +1 -0
  61. package/dist/commands/review-parallel-run.d.ts +5 -0
  62. package/dist/commands/review-parallel-run.d.ts.map +1 -0
  63. package/dist/commands/review-parallel-run.js +117 -0
  64. package/dist/commands/review-parallel-run.js.map +1 -0
  65. package/dist/commands/review-plugin-status.d.ts +5 -0
  66. package/dist/commands/review-plugin-status.d.ts.map +1 -0
  67. package/dist/commands/review-plugin-status.js +54 -0
  68. package/dist/commands/review-plugin-status.js.map +1 -0
  69. package/dist/commands/review-quality-score.d.ts +5 -0
  70. package/dist/commands/review-quality-score.d.ts.map +1 -0
  71. package/dist/commands/review-quality-score.js +128 -0
  72. package/dist/commands/review-quality-score.js.map +1 -0
  73. package/dist/commands/review-team-stats.d.ts +5 -0
  74. package/dist/commands/review-team-stats.d.ts.map +1 -0
  75. package/dist/commands/review-team-stats.js +98 -0
  76. package/dist/commands/review-team-stats.js.map +1 -0
  77. package/package.json +1 -1
  78. package/server.json +2 -2
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Finding-auto-group — Auto-group related findings into logical categories.
3
+ */
4
+ export declare function runFindingAutoGroup(argv: string[]): void;
5
+ //# sourceMappingURL=finding-auto-group.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-auto-group.d.ts","sourceRoot":"","sources":["../../src/commands/finding-auto-group.ts"],"names":[],"mappings":"AAAA;;GAEG;AAmEH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA8DxD"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Finding-auto-group — Auto-group related findings into logical categories.
3
+ */
4
+ import { readFileSync, existsSync } from "fs";
5
+ // ─── Analysis ───────────────────────────────────────────────────────────────
6
+ const CATEGORY_PATTERNS = [
7
+ { name: "Security", keywords: ["auth", "inject", "xss", "csrf", "vuln", "secret", "crypt", "sanitiz"] },
8
+ { name: "Performance", keywords: ["perf", "optim", "cache", "memory", "leak", "slow", "latency"] },
9
+ { name: "Reliability", keywords: ["error", "exception", "null", "undefined", "crash", "race"] },
10
+ { name: "Style", keywords: ["naming", "format", "indent", "whitespace", "convention", "lint"] },
11
+ { name: "Complexity", keywords: ["complex", "cyclomatic", "nesting", "depth", "refactor"] },
12
+ { name: "API", keywords: ["api", "endpoint", "route", "request", "response", "rest", "graphql"] },
13
+ { name: "Data", keywords: ["data", "schema", "valid", "type", "model", "serial"] },
14
+ ];
15
+ function categorize(ruleId, title) {
16
+ const combined = `${ruleId} ${title}`.toLowerCase();
17
+ for (const cat of CATEGORY_PATTERNS) {
18
+ if (cat.keywords.some((kw) => combined.includes(kw))) {
19
+ return cat.name;
20
+ }
21
+ }
22
+ return "Other";
23
+ }
24
+ function groupFindings(verdict) {
25
+ const groups = new Map();
26
+ for (const f of verdict.findings) {
27
+ const category = categorize(f.ruleId, f.title);
28
+ const existing = groups.get(category);
29
+ if (existing) {
30
+ existing.count++;
31
+ const sev = (f.severity || "medium").toLowerCase();
32
+ existing.sevBreakdown[sev] = (existing.sevBreakdown[sev] || 0) + 1;
33
+ if (!existing.ruleIds.includes(f.ruleId))
34
+ existing.ruleIds.push(f.ruleId);
35
+ if (existing.titles.length < 5)
36
+ existing.titles.push(f.title);
37
+ }
38
+ else {
39
+ const sev = (f.severity || "medium").toLowerCase();
40
+ groups.set(category, {
41
+ category,
42
+ count: 1,
43
+ sevBreakdown: { [sev]: 1 },
44
+ ruleIds: [f.ruleId],
45
+ titles: [f.title],
46
+ });
47
+ }
48
+ }
49
+ return [...groups.values()].sort((a, b) => b.count - a.count);
50
+ }
51
+ // ─── CLI ────────────────────────────────────────────────────────────────────
52
+ export function runFindingAutoGroup(argv) {
53
+ const fileIdx = argv.indexOf("--file");
54
+ const formatIdx = argv.indexOf("--format");
55
+ const filePath = fileIdx >= 0 ? argv[fileIdx + 1] : undefined;
56
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
57
+ if (argv.includes("--help") || argv.includes("-h")) {
58
+ console.log(`
59
+ judges finding-auto-group — Auto-group findings into categories
60
+
61
+ Usage:
62
+ judges finding-auto-group --file <verdict.json> [--format table|json]
63
+
64
+ Options:
65
+ --file <path> Path to verdict JSON file (required)
66
+ --format <fmt> Output format: table (default), json
67
+ --help, -h Show this help
68
+ `);
69
+ return;
70
+ }
71
+ if (!filePath) {
72
+ console.error("Error: --file required");
73
+ process.exitCode = 1;
74
+ return;
75
+ }
76
+ if (!existsSync(filePath)) {
77
+ console.error(`Error: not found: ${filePath}`);
78
+ process.exitCode = 1;
79
+ return;
80
+ }
81
+ let verdict;
82
+ try {
83
+ verdict = JSON.parse(readFileSync(filePath, "utf-8"));
84
+ }
85
+ catch {
86
+ console.error("Error: invalid JSON");
87
+ process.exitCode = 1;
88
+ return;
89
+ }
90
+ const groups = groupFindings(verdict);
91
+ if (format === "json") {
92
+ console.log(JSON.stringify(groups, null, 2));
93
+ return;
94
+ }
95
+ console.log(`\nFinding Groups (${groups.length} categories)`);
96
+ console.log("═".repeat(70));
97
+ console.log(`${"Category".padEnd(16)} ${"Count".padEnd(8)} ${"Severities".padEnd(26)} Rules`);
98
+ console.log("─".repeat(70));
99
+ for (const g of groups) {
100
+ const sevStr = Object.entries(g.sevBreakdown)
101
+ .map(([s, c]) => `${s}:${c}`)
102
+ .join(", ");
103
+ const sevDisplay = sevStr.length > 24 ? sevStr.slice(0, 24) + "…" : sevStr;
104
+ const ruleStr = g.ruleIds.slice(0, 3).join(", ");
105
+ console.log(`${g.category.padEnd(16)} ${String(g.count).padEnd(8)} ${sevDisplay.padEnd(26)} ${ruleStr}`);
106
+ }
107
+ console.log("═".repeat(70));
108
+ }
109
+ //# sourceMappingURL=finding-auto-group.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-auto-group.js","sourceRoot":"","sources":["../../src/commands/finding-auto-group.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Finding-blast-radius — Estimate the blast radius of findings.
3
+ */
4
+ export declare function runFindingBlastRadius(argv: string[]): void;
5
+ //# sourceMappingURL=finding-blast-radius.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-blast-radius.d.ts","sourceRoot":"","sources":["../../src/commands/finding-blast-radius.ts"],"names":[],"mappings":"AAAA;;GAEG;AAsDH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAkE1D"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Finding-blast-radius — Estimate the blast radius of findings.
3
+ */
4
+ import { readFileSync, existsSync } from "fs";
5
+ // ─── Analysis ───────────────────────────────────────────────────────────────
6
+ function estimateBlastRadius(verdict) {
7
+ const entries = [];
8
+ for (const f of verdict.findings) {
9
+ const lines = f.lineNumbers || [];
10
+ const lineSpan = lines.length > 1 ? lines[lines.length - 1] - lines[0] + 1 : lines.length;
11
+ const sev = (f.severity || "medium").toLowerCase();
12
+ const sevWeight = sev === "critical" ? 4 : sev === "high" ? 3 : sev === "medium" ? 2 : 1;
13
+ let radius = "contained";
14
+ if (lineSpan > 50 || sevWeight >= 3) {
15
+ radius = "widespread";
16
+ }
17
+ else if (lineSpan > 10 || sevWeight >= 2) {
18
+ radius = "moderate";
19
+ }
20
+ const riskScore = sevWeight * Math.max(1, Math.ceil(lineSpan / 10));
21
+ entries.push({
22
+ ruleId: f.ruleId,
23
+ title: f.title,
24
+ severity: sev,
25
+ lineSpan,
26
+ affectedLines: lines,
27
+ radius,
28
+ riskScore,
29
+ });
30
+ }
31
+ return entries.sort((a, b) => b.riskScore - a.riskScore);
32
+ }
33
+ // ─── CLI ────────────────────────────────────────────────────────────────────
34
+ export function runFindingBlastRadius(argv) {
35
+ const fileIdx = argv.indexOf("--file");
36
+ const formatIdx = argv.indexOf("--format");
37
+ const filePath = fileIdx >= 0 ? argv[fileIdx + 1] : undefined;
38
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
39
+ if (argv.includes("--help") || argv.includes("-h")) {
40
+ console.log(`
41
+ judges finding-blast-radius — Estimate finding blast radius
42
+
43
+ Usage:
44
+ judges finding-blast-radius --file <verdict.json> [--format table|json]
45
+
46
+ Options:
47
+ --file <path> Path to verdict JSON file (required)
48
+ --format <fmt> Output format: table (default), json
49
+ --help, -h Show this help
50
+ `);
51
+ return;
52
+ }
53
+ if (!filePath) {
54
+ console.error("Error: --file required");
55
+ process.exitCode = 1;
56
+ return;
57
+ }
58
+ if (!existsSync(filePath)) {
59
+ console.error(`Error: not found: ${filePath}`);
60
+ process.exitCode = 1;
61
+ return;
62
+ }
63
+ let verdict;
64
+ try {
65
+ verdict = JSON.parse(readFileSync(filePath, "utf-8"));
66
+ }
67
+ catch {
68
+ console.error("Error: invalid JSON");
69
+ process.exitCode = 1;
70
+ return;
71
+ }
72
+ const entries = estimateBlastRadius(verdict);
73
+ if (format === "json") {
74
+ console.log(JSON.stringify(entries, null, 2));
75
+ return;
76
+ }
77
+ console.log(`\nBlast Radius Analysis (${entries.length} findings)`);
78
+ console.log("═".repeat(70));
79
+ console.log(`${"Rule".padEnd(20)} ${"Severity".padEnd(10)} ${"Span".padEnd(8)} ${"Radius".padEnd(14)} Risk`);
80
+ console.log("─".repeat(70));
81
+ for (const e of entries) {
82
+ const rule = e.ruleId.length > 18 ? e.ruleId.slice(0, 18) + "…" : e.ruleId;
83
+ console.log(`${rule.padEnd(20)} ${e.severity.padEnd(10)} ${String(e.lineSpan).padEnd(8)} ${e.radius.padEnd(14)} ${e.riskScore}`);
84
+ }
85
+ const widespread = entries.filter((e) => e.radius === "widespread").length;
86
+ const moderate = entries.filter((e) => e.radius === "moderate").length;
87
+ const contained = entries.filter((e) => e.radius === "contained").length;
88
+ console.log("─".repeat(70));
89
+ console.log(` Widespread: ${widespread} | Moderate: ${moderate} | Contained: ${contained}`);
90
+ console.log("═".repeat(70));
91
+ }
92
+ //# sourceMappingURL=finding-blast-radius.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-blast-radius.js","sourceRoot":"","sources":["../../src/commands/finding-blast-radius.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Finding-cross-ref — Cross-reference findings across multiple reviews.
3
+ */
4
+ export declare function runFindingCrossRef(argv: string[]): void;
5
+ //# sourceMappingURL=finding-cross-ref.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-cross-ref.d.ts","sourceRoot":"","sources":["../../src/commands/finding-cross-ref.ts"],"names":[],"mappings":"AAAA;;GAEG;AA4CH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA8EvD"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Finding-cross-ref — Cross-reference findings across multiple reviews.
3
+ */
4
+ import { readFileSync, existsSync, readdirSync } from "fs";
5
+ // ─── Analysis ───────────────────────────────────────────────────────────────
6
+ function crossReference(verdicts) {
7
+ const ruleMap = new Map();
8
+ for (const { name, verdict } of verdicts) {
9
+ for (const f of verdict.findings) {
10
+ const existing = ruleMap.get(f.ruleId);
11
+ if (existing) {
12
+ existing.files.add(name);
13
+ }
14
+ else {
15
+ ruleMap.set(f.ruleId, { title: f.title, files: new Set([name]) });
16
+ }
17
+ }
18
+ }
19
+ return [...ruleMap.entries()]
20
+ .map(([ruleId, data]) => ({
21
+ ruleId,
22
+ title: data.title,
23
+ occurrences: data.files.size,
24
+ files: [...data.files],
25
+ persistent: data.files.size === verdicts.length,
26
+ }))
27
+ .sort((a, b) => b.occurrences - a.occurrences);
28
+ }
29
+ // ─── CLI ────────────────────────────────────────────────────────────────────
30
+ export function runFindingCrossRef(argv) {
31
+ const dirIdx = argv.indexOf("--dir");
32
+ const formatIdx = argv.indexOf("--format");
33
+ const persistentOnly = argv.includes("--persistent");
34
+ const dirPath = dirIdx >= 0 ? argv[dirIdx + 1] : undefined;
35
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
36
+ if (argv.includes("--help") || argv.includes("-h")) {
37
+ console.log(`
38
+ judges finding-cross-ref — Cross-reference findings across reviews
39
+
40
+ Usage:
41
+ judges finding-cross-ref --dir <verdicts-dir> [--persistent]
42
+ [--format table|json]
43
+
44
+ Options:
45
+ --dir <path> Directory of verdict JSON files (required)
46
+ --persistent Show only findings present in all reviews
47
+ --format <fmt> Output format: table (default), json
48
+ --help, -h Show this help
49
+ `);
50
+ return;
51
+ }
52
+ if (!dirPath) {
53
+ console.error("Error: --dir required");
54
+ process.exitCode = 1;
55
+ return;
56
+ }
57
+ if (!existsSync(dirPath)) {
58
+ console.error(`Error: not found: ${dirPath}`);
59
+ process.exitCode = 1;
60
+ return;
61
+ }
62
+ const files = readdirSync(dirPath).filter((f) => f.endsWith(".json"));
63
+ const verdicts = [];
64
+ for (const file of files) {
65
+ try {
66
+ verdicts.push({
67
+ name: file,
68
+ verdict: JSON.parse(readFileSync(`${dirPath}/${file}`, "utf-8")),
69
+ });
70
+ }
71
+ catch {
72
+ // skip
73
+ }
74
+ }
75
+ if (verdicts.length === 0) {
76
+ console.error("Error: no valid verdict files found");
77
+ process.exitCode = 1;
78
+ return;
79
+ }
80
+ let refs = crossReference(verdicts);
81
+ if (persistentOnly) {
82
+ refs = refs.filter((r) => r.persistent);
83
+ }
84
+ if (format === "json") {
85
+ console.log(JSON.stringify(refs, null, 2));
86
+ return;
87
+ }
88
+ console.log(`\nCross-Reference (${refs.length} rules across ${verdicts.length} reviews)`);
89
+ console.log("═".repeat(70));
90
+ console.log(`${"Rule".padEnd(22)} ${"Occurrences".padEnd(14)} ${"Persistent".padEnd(12)} Title`);
91
+ console.log("─".repeat(70));
92
+ for (const r of refs.slice(0, 20)) {
93
+ const rule = r.ruleId.length > 20 ? r.ruleId.slice(0, 20) + "…" : r.ruleId;
94
+ const title = r.title.length > 20 ? r.title.slice(0, 20) + "…" : r.title;
95
+ console.log(`${rule.padEnd(22)} ${String(r.occurrences).padEnd(14)} ${(r.persistent ? "yes" : "no").padEnd(12)} ${title}`);
96
+ }
97
+ console.log("═".repeat(70));
98
+ }
99
+ //# sourceMappingURL=finding-cross-ref.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-cross-ref.js","sourceRoot":"","sources":["../../src/commands/finding-cross-ref.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Finding-hotspot-map — Identify code hotspots with the most findings.
3
+ */
4
+ export declare function runFindingHotspotMap(argv: string[]): void;
5
+ //# sourceMappingURL=finding-hotspot-map.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-hotspot-map.d.ts","sourceRoot":"","sources":["../../src/commands/finding-hotspot-map.ts"],"names":[],"mappings":"AAAA;;GAEG;AAyDH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAyEzD"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Finding-hotspot-map — Identify code hotspots with the most findings.
3
+ */
4
+ import { readFileSync, existsSync } from "fs";
5
+ // ─── Analysis ───────────────────────────────────────────────────────────────
6
+ function findHotspots(verdict, bucketSize) {
7
+ const buckets = new Map();
8
+ for (const f of verdict.findings) {
9
+ const lines = f.lineNumbers || [];
10
+ if (lines.length === 0)
11
+ continue;
12
+ const bucket = Math.floor(lines[0] / bucketSize) * bucketSize;
13
+ const existing = buckets.get(bucket);
14
+ if (existing) {
15
+ existing.findings.push(f);
16
+ }
17
+ else {
18
+ buckets.set(bucket, { findings: [f] });
19
+ }
20
+ }
21
+ return [...buckets.entries()]
22
+ .map(([start, data]) => {
23
+ const severities = {};
24
+ const ruleIds = [];
25
+ for (const f of data.findings) {
26
+ const sev = (f.severity || "medium").toLowerCase();
27
+ severities[sev] = (severities[sev] || 0) + 1;
28
+ if (!ruleIds.includes(f.ruleId)) {
29
+ ruleIds.push(f.ruleId);
30
+ }
31
+ }
32
+ return {
33
+ lineRange: `${start + 1}-${start + bucketSize}`,
34
+ findingCount: data.findings.length,
35
+ severities,
36
+ ruleIds,
37
+ };
38
+ })
39
+ .sort((a, b) => b.findingCount - a.findingCount);
40
+ }
41
+ // ─── CLI ────────────────────────────────────────────────────────────────────
42
+ export function runFindingHotspotMap(argv) {
43
+ const fileIdx = argv.indexOf("--file");
44
+ const bucketIdx = argv.indexOf("--bucket");
45
+ const formatIdx = argv.indexOf("--format");
46
+ const filePath = fileIdx >= 0 ? argv[fileIdx + 1] : undefined;
47
+ const bucketSize = bucketIdx >= 0 ? parseInt(argv[bucketIdx + 1], 10) : 20;
48
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
49
+ if (argv.includes("--help") || argv.includes("-h")) {
50
+ console.log(`
51
+ judges finding-hotspot-map — Identify code hotspots
52
+
53
+ Usage:
54
+ judges finding-hotspot-map --file <verdict.json> [--bucket <size>]
55
+ [--format table|json]
56
+
57
+ Options:
58
+ --file <path> Path to verdict JSON file (required)
59
+ --bucket <size> Line bucket size (default: 20)
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: 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 hotspots = findHotspots(verdict, bucketSize);
85
+ if (format === "json") {
86
+ console.log(JSON.stringify(hotspots, null, 2));
87
+ return;
88
+ }
89
+ console.log(`\nCode Hotspot Map (bucket size: ${bucketSize} lines)`);
90
+ console.log("═".repeat(70));
91
+ console.log(`${"Line Range".padEnd(14)} ${"Findings".padEnd(10)} ${"Severities".padEnd(25)} Rules`);
92
+ console.log("─".repeat(70));
93
+ for (const h of hotspots.slice(0, 15)) {
94
+ const sevStr = Object.entries(h.severities)
95
+ .map(([s, c]) => `${s}:${c}`)
96
+ .join(", ");
97
+ const sevDisplay = sevStr.length > 23 ? sevStr.slice(0, 23) + "…" : sevStr;
98
+ const ruleStr = h.ruleIds.slice(0, 3).join(", ");
99
+ const ruleDisplay = ruleStr.length > 20 ? ruleStr.slice(0, 20) + "…" : ruleStr;
100
+ console.log(`${h.lineRange.padEnd(14)} ${String(h.findingCount).padEnd(10)} ${sevDisplay.padEnd(25)} ${ruleDisplay}`);
101
+ }
102
+ if (hotspots.length > 15) {
103
+ console.log(` ... +${hotspots.length - 15} more hotspots`);
104
+ }
105
+ console.log("═".repeat(70));
106
+ }
107
+ //# sourceMappingURL=finding-hotspot-map.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-hotspot-map.js","sourceRoot":"","sources":["../../src/commands/finding-hotspot-map.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Finding-metadata-enrich — Enrich findings with additional metadata.
3
+ */
4
+ export declare function runFindingMetadataEnrich(argv: string[]): void;
5
+ //# sourceMappingURL=finding-metadata-enrich.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-metadata-enrich.d.ts","sourceRoot":"","sources":["../../src/commands/finding-metadata-enrich.ts"],"names":[],"mappings":"AAAA;;GAEG;AAmDH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAuE7D"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Finding-metadata-enrich — Enrich findings with additional metadata.
3
+ */
4
+ import { readFileSync, existsSync } from "fs";
5
+ import { defaultRegistry } from "../judge-registry.js";
6
+ // ─── Analysis ───────────────────────────────────────────────────────────────
7
+ function enrichFindings(verdict) {
8
+ const judges = defaultRegistry.getJudges();
9
+ return verdict.findings.map((f) => {
10
+ const judge = judges.find((j) => f.ruleId.startsWith(j.rulePrefix));
11
+ return {
12
+ ruleId: f.ruleId,
13
+ title: f.title,
14
+ severity: (f.severity || "medium").toLowerCase(),
15
+ judge: judge ? judge.id : "unknown",
16
+ domain: judge ? judge.domain : "unknown",
17
+ hasRecommendation: f.recommendation.length > 0,
18
+ hasPatch: f.patch !== undefined && f.patch !== null,
19
+ lineCount: (f.lineNumbers || []).length,
20
+ confidenceLevel: f.confidence !== undefined && f.confidence !== null
21
+ ? f.confidence > 0.8
22
+ ? "high"
23
+ : f.confidence > 0.5
24
+ ? "medium"
25
+ : "low"
26
+ : "unknown",
27
+ };
28
+ });
29
+ }
30
+ // ─── CLI ────────────────────────────────────────────────────────────────────
31
+ export function runFindingMetadataEnrich(argv) {
32
+ const fileIdx = argv.indexOf("--file");
33
+ const filterIdx = argv.indexOf("--domain");
34
+ const formatIdx = argv.indexOf("--format");
35
+ const filePath = fileIdx >= 0 ? argv[fileIdx + 1] : undefined;
36
+ const domainFilter = filterIdx >= 0 ? argv[filterIdx + 1] : undefined;
37
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
38
+ if (argv.includes("--help") || argv.includes("-h")) {
39
+ console.log(`
40
+ judges finding-metadata-enrich — Enrich findings with metadata
41
+
42
+ Usage:
43
+ judges finding-metadata-enrich --file <verdict.json> [--domain <filter>]
44
+ [--format table|json]
45
+
46
+ Options:
47
+ --file <path> Path to verdict JSON file (required)
48
+ --domain <name> Filter by judge domain
49
+ --format <fmt> Output format: table (default), json
50
+ --help, -h Show this help
51
+ `);
52
+ return;
53
+ }
54
+ if (!filePath) {
55
+ console.error("Error: --file required");
56
+ process.exitCode = 1;
57
+ return;
58
+ }
59
+ if (!existsSync(filePath)) {
60
+ console.error(`Error: not found: ${filePath}`);
61
+ process.exitCode = 1;
62
+ return;
63
+ }
64
+ let verdict;
65
+ try {
66
+ verdict = JSON.parse(readFileSync(filePath, "utf-8"));
67
+ }
68
+ catch {
69
+ console.error("Error: invalid JSON");
70
+ process.exitCode = 1;
71
+ return;
72
+ }
73
+ let enriched = enrichFindings(verdict);
74
+ if (domainFilter) {
75
+ enriched = enriched.filter((e) => e.domain.toLowerCase().includes(domainFilter.toLowerCase()));
76
+ }
77
+ if (format === "json") {
78
+ console.log(JSON.stringify(enriched, null, 2));
79
+ return;
80
+ }
81
+ console.log(`\nEnriched Findings (${enriched.length})`);
82
+ console.log("═".repeat(80));
83
+ console.log(`${"Rule".padEnd(18)} ${"Severity".padEnd(10)} ${"Judge".padEnd(14)} ${"Domain".padEnd(12)} ${"Conf".padEnd(8)} Patch`);
84
+ console.log("─".repeat(80));
85
+ for (const e of enriched) {
86
+ const rule = e.ruleId.length > 16 ? e.ruleId.slice(0, 16) + "…" : e.ruleId;
87
+ const judge = e.judge.length > 12 ? e.judge.slice(0, 12) + "…" : e.judge;
88
+ const domain = e.domain.length > 10 ? e.domain.slice(0, 10) + "…" : e.domain;
89
+ console.log(`${rule.padEnd(18)} ${e.severity.padEnd(10)} ${judge.padEnd(14)} ${domain.padEnd(12)} ${e.confidenceLevel.padEnd(8)} ${e.hasPatch ? "yes" : "no"}`);
90
+ }
91
+ console.log("═".repeat(80));
92
+ }
93
+ //# sourceMappingURL=finding-metadata-enrich.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-metadata-enrich.js","sourceRoot":"","sources":["../../src/commands/finding-metadata-enrich.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Finding-pattern-detect — Detect recurring finding patterns across reviews.
3
+ */
4
+ export declare function runFindingPatternDetect(argv: string[]): void;
5
+ //# sourceMappingURL=finding-pattern-detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-pattern-detect.d.ts","sourceRoot":"","sources":["../../src/commands/finding-pattern-detect.ts"],"names":[],"mappings":"AAAA;;GAEG;AA+EH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA0E5D"}