@kevinrabun/judges 3.90.0 → 3.91.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-blast-radius.d.ts +5 -0
  6. package/dist/commands/finding-blast-radius.d.ts.map +1 -0
  7. package/dist/commands/finding-blast-radius.js +92 -0
  8. package/dist/commands/finding-blast-radius.js.map +1 -0
  9. package/dist/commands/finding-hotspot-map.d.ts +5 -0
  10. package/dist/commands/finding-hotspot-map.d.ts.map +1 -0
  11. package/dist/commands/finding-hotspot-map.js +107 -0
  12. package/dist/commands/finding-hotspot-map.js.map +1 -0
  13. package/dist/commands/finding-metadata-enrich.d.ts +5 -0
  14. package/dist/commands/finding-metadata-enrich.d.ts.map +1 -0
  15. package/dist/commands/finding-metadata-enrich.js +93 -0
  16. package/dist/commands/finding-metadata-enrich.js.map +1 -0
  17. package/dist/commands/review-annotation-export.d.ts +5 -0
  18. package/dist/commands/review-annotation-export.d.ts.map +1 -0
  19. package/dist/commands/review-annotation-export.js +106 -0
  20. package/dist/commands/review-annotation-export.js.map +1 -0
  21. package/dist/commands/review-cache-warm.d.ts +5 -0
  22. package/dist/commands/review-cache-warm.d.ts.map +1 -0
  23. package/dist/commands/review-cache-warm.js +71 -0
  24. package/dist/commands/review-cache-warm.js.map +1 -0
  25. package/dist/commands/review-merge-config.d.ts +5 -0
  26. package/dist/commands/review-merge-config.d.ts.map +1 -0
  27. package/dist/commands/review-merge-config.js +120 -0
  28. package/dist/commands/review-merge-config.js.map +1 -0
  29. package/dist/commands/review-onboard-wizard.d.ts +5 -0
  30. package/dist/commands/review-onboard-wizard.d.ts.map +1 -0
  31. package/dist/commands/review-onboard-wizard.js +93 -0
  32. package/dist/commands/review-onboard-wizard.js.map +1 -0
  33. package/dist/commands/review-parallel-run.d.ts +5 -0
  34. package/dist/commands/review-parallel-run.d.ts.map +1 -0
  35. package/dist/commands/review-parallel-run.js +117 -0
  36. package/dist/commands/review-parallel-run.js.map +1 -0
  37. package/dist/commands/review-quality-score.d.ts +5 -0
  38. package/dist/commands/review-quality-score.d.ts.map +1 -0
  39. package/dist/commands/review-quality-score.js +128 -0
  40. package/dist/commands/review-quality-score.js.map +1 -0
  41. package/package.json +1 -1
  42. package/server.json +2 -2
@@ -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-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":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAY9C,+EAA+E;AAE/E,SAAS,YAAY,CAAC,OAAwB,EAAE,UAAkB;IAChE,MAAM,OAAO,GAAG,IAAI,GAAG,EAAiD,CAAC;IAEzE,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC;QAClC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAEjC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,GAAG,UAAU,CAAC;QAC9D,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACrC,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;SAC1B,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE;QACrB,MAAM,UAAU,GAA2B,EAAE,CAAC;QAC9C,MAAM,OAAO,GAAa,EAAE,CAAC;QAE7B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC9B,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,IAAI,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;YACnD,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YAC7C,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;gBAChC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;QAED,OAAO;YACL,SAAS,EAAE,GAAG,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,UAAU,EAAE;YAC/C,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM;YAClC,UAAU;YACV,OAAO;SACR,CAAC;IACJ,CAAC,CAAC;SACD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC;AACrD,CAAC;AAED,+EAA+E;AAE/E,MAAM,UAAU,oBAAoB,CAAC,IAAc;IACjD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9D,MAAM,UAAU,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3E,MAAM,MAAM,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAE9D,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;CAYf,CAAC,CAAC;QACC,OAAO;IACT,CAAC;IAED,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;QACxC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,qBAAqB,QAAQ,EAAE,CAAC,CAAC;QAC/C,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,IAAI,OAAwB,CAAC;IAC7B,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACrC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAEnD,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/C,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,oCAAoC,UAAU,SAAS,CAAC,CAAC;IACrE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,OAAO,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;IACpG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAE5B,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;QACtC,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;aACxC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;aAC5B,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;QAC3E,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;QAC/E,OAAO,CAAC,GAAG,CACT,GAAG,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,WAAW,EAAE,CACzG,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,UAAU,QAAQ,CAAC,MAAM,GAAG,EAAE,gBAAgB,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AAC9B,CAAC"}
@@ -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
+ * Review-annotation-export — Export review findings as code annotations.
3
+ */
4
+ export declare function runReviewAnnotationExport(argv: string[]): void;
5
+ //# sourceMappingURL=review-annotation-export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-annotation-export.d.ts","sourceRoot":"","sources":["../../src/commands/review-annotation-export.ts"],"names":[],"mappings":"AAAA;;GAEG;AAiEH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA+D9D"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Review-annotation-export — Export review findings as code annotations.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync } from "fs";
5
+ // ─── Analysis ───────────────────────────────────────────────────────────────
6
+ function toAnnotations(verdict) {
7
+ const annotations = [];
8
+ for (const f of verdict.findings) {
9
+ const lines = f.lineNumbers || [];
10
+ const sev = (f.severity || "medium").toLowerCase();
11
+ const type = sev === "critical" || sev === "high" ? "error" : sev === "medium" ? "warning" : "notice";
12
+ if (lines.length === 0) {
13
+ annotations.push({
14
+ type,
15
+ ruleId: f.ruleId,
16
+ title: f.title,
17
+ message: `${f.description}\n\nRecommendation: ${f.recommendation}`,
18
+ line: 1,
19
+ });
20
+ }
21
+ else {
22
+ annotations.push({
23
+ type,
24
+ ruleId: f.ruleId,
25
+ title: f.title,
26
+ message: `${f.description}\n\nRecommendation: ${f.recommendation}`,
27
+ line: lines[0],
28
+ endLine: lines.length > 1 ? lines[lines.length - 1] : undefined,
29
+ });
30
+ }
31
+ }
32
+ return annotations;
33
+ }
34
+ function toGitHubFormat(annotations) {
35
+ return annotations
36
+ .map((a) => {
37
+ const lineRef = a.endLine ? `line=${a.line},endLine=${a.endLine}` : `line=${a.line}`;
38
+ return `::${a.type} ${lineRef},title=${a.ruleId}: ${a.title}::${a.message.replace(/\n/g, "%0A")}`;
39
+ })
40
+ .join("\n");
41
+ }
42
+ function toInlineComments(annotations) {
43
+ return annotations.map((a) => `// [${a.type.toUpperCase()}] L${a.line}: ${a.ruleId} — ${a.title}`).join("\n");
44
+ }
45
+ // ─── CLI ────────────────────────────────────────────────────────────────────
46
+ export function runReviewAnnotationExport(argv) {
47
+ const fileIdx = argv.indexOf("--file");
48
+ const outputIdx = argv.indexOf("--output");
49
+ const formatIdx = argv.indexOf("--format");
50
+ const filePath = fileIdx >= 0 ? argv[fileIdx + 1] : undefined;
51
+ const outputPath = outputIdx >= 0 ? argv[outputIdx + 1] : undefined;
52
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "github";
53
+ if (argv.includes("--help") || argv.includes("-h")) {
54
+ console.log(`
55
+ judges review-annotation-export — Export findings as annotations
56
+
57
+ Usage:
58
+ judges review-annotation-export --file <verdict.json> [--output <file>]
59
+ [--format github|inline|json]
60
+
61
+ Options:
62
+ --file <path> Path to verdict JSON file (required)
63
+ --output <path> Write annotations to file
64
+ --format <fmt> Format: github (default), inline, json
65
+ --help, -h Show this help
66
+ `);
67
+ return;
68
+ }
69
+ if (!filePath) {
70
+ console.error("Error: --file required");
71
+ process.exitCode = 1;
72
+ return;
73
+ }
74
+ if (!existsSync(filePath)) {
75
+ console.error(`Error: not found: ${filePath}`);
76
+ process.exitCode = 1;
77
+ return;
78
+ }
79
+ let verdict;
80
+ try {
81
+ verdict = JSON.parse(readFileSync(filePath, "utf-8"));
82
+ }
83
+ catch {
84
+ console.error("Error: invalid JSON");
85
+ process.exitCode = 1;
86
+ return;
87
+ }
88
+ const annotations = toAnnotations(verdict);
89
+ let output;
90
+ if (format === "json") {
91
+ output = JSON.stringify(annotations, null, 2);
92
+ }
93
+ else if (format === "inline") {
94
+ output = toInlineComments(annotations);
95
+ }
96
+ else {
97
+ output = toGitHubFormat(annotations);
98
+ }
99
+ if (outputPath) {
100
+ writeFileSync(outputPath, output);
101
+ console.log(`Annotations written to ${outputPath} (${annotations.length} annotations)`);
102
+ return;
103
+ }
104
+ console.log(output);
105
+ }
106
+ //# sourceMappingURL=review-annotation-export.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-annotation-export.js","sourceRoot":"","sources":["../../src/commands/review-annotation-export.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-cache-warm — Pre-warm the review cache for faster subsequent runs.
3
+ */
4
+ export declare function runReviewCacheWarm(argv: string[]): void;
5
+ //# sourceMappingURL=review-cache-warm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-cache-warm.d.ts","sourceRoot":"","sources":["../../src/commands/review-cache-warm.ts"],"names":[],"mappings":"AAAA;;GAEG;AAmDH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAuCvD"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Review-cache-warm — Pre-warm the review cache for faster subsequent runs.
3
+ */
4
+ import { existsSync, readdirSync, mkdirSync } from "fs";
5
+ import { DiskCache } from "../disk-cache.js";
6
+ import { defaultRegistry } from "../judge-registry.js";
7
+ // ─── Logic ──────────────────────────────────────────────────────────────────
8
+ function warmCache(sourceDir, cacheDir) {
9
+ const judges = defaultRegistry.getJudges();
10
+ const extensions = new Set();
11
+ let warmedEntries = 0;
12
+ if (!existsSync(cacheDir)) {
13
+ mkdirSync(cacheDir, { recursive: true });
14
+ }
15
+ const cache = new DiskCache({ cacheDir });
16
+ if (existsSync(sourceDir)) {
17
+ const files = readdirSync(sourceDir);
18
+ for (const file of files) {
19
+ const ext = file.split(".").pop() || "";
20
+ extensions.add(ext);
21
+ // create a cache entry for each file to pre-warm
22
+ const key = `warm-${file}`;
23
+ cache.set(key, { warmed: true, timestamp: new Date().toISOString() });
24
+ warmedEntries++;
25
+ }
26
+ }
27
+ return {
28
+ cacheDir,
29
+ judgeCount: judges.length,
30
+ warmedEntries,
31
+ languages: [...extensions],
32
+ };
33
+ }
34
+ // ─── CLI ────────────────────────────────────────────────────────────────────
35
+ export function runReviewCacheWarm(argv) {
36
+ const dirIdx = argv.indexOf("--dir");
37
+ const cacheIdx = argv.indexOf("--cache-dir");
38
+ const formatIdx = argv.indexOf("--format");
39
+ const dirPath = dirIdx >= 0 ? argv[dirIdx + 1] : ".";
40
+ const cacheDir = cacheIdx >= 0 ? argv[cacheIdx + 1] : ".judges-cache";
41
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
42
+ if (argv.includes("--help") || argv.includes("-h")) {
43
+ console.log(`
44
+ judges review-cache-warm — Pre-warm review cache
45
+
46
+ Usage:
47
+ judges review-cache-warm [--dir <source-dir>] [--cache-dir <path>]
48
+ [--format table|json]
49
+
50
+ Options:
51
+ --dir <path> Source directory to scan (default: .)
52
+ --cache-dir <path> Cache directory (default: .judges-cache)
53
+ --format <fmt> Output format: table (default), json
54
+ --help, -h Show this help
55
+ `);
56
+ return;
57
+ }
58
+ const status = warmCache(dirPath, cacheDir);
59
+ if (format === "json") {
60
+ console.log(JSON.stringify(status, null, 2));
61
+ return;
62
+ }
63
+ console.log(`\nCache Warm Status`);
64
+ console.log("═".repeat(50));
65
+ console.log(` Cache Dir: ${status.cacheDir}`);
66
+ console.log(` Judges: ${status.judgeCount}`);
67
+ console.log(` Warmed Entries: ${status.warmedEntries}`);
68
+ console.log(` Languages: ${status.languages.join(", ") || "—"}`);
69
+ console.log("═".repeat(50));
70
+ }
71
+ //# sourceMappingURL=review-cache-warm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-cache-warm.js","sourceRoot":"","sources":["../../src/commands/review-cache-warm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-merge-config — Merge multiple Judges configuration files.
3
+ */
4
+ export declare function runReviewMergeConfig(argv: string[]): void;
5
+ //# sourceMappingURL=review-merge-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-merge-config.d.ts","sourceRoot":"","sources":["../../src/commands/review-merge-config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAoEH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA0EzD"}