@kevinrabun/judges 3.85.0 → 3.87.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 +29 -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-code-smell.d.ts +5 -0
  6. package/dist/commands/finding-code-smell.d.ts.map +1 -0
  7. package/dist/commands/finding-code-smell.js +114 -0
  8. package/dist/commands/finding-code-smell.js.map +1 -0
  9. package/dist/commands/finding-context-window.d.ts +5 -0
  10. package/dist/commands/finding-context-window.d.ts.map +1 -0
  11. package/dist/commands/finding-context-window.js +127 -0
  12. package/dist/commands/finding-context-window.js.map +1 -0
  13. package/dist/commands/finding-owner-assign.d.ts +5 -0
  14. package/dist/commands/finding-owner-assign.d.ts.map +1 -0
  15. package/dist/commands/finding-owner-assign.js +134 -0
  16. package/dist/commands/finding-owner-assign.js.map +1 -0
  17. package/dist/commands/finding-pattern-library.d.ts +5 -0
  18. package/dist/commands/finding-pattern-library.d.ts.map +1 -0
  19. package/dist/commands/finding-pattern-library.js +146 -0
  20. package/dist/commands/finding-pattern-library.js.map +1 -0
  21. package/dist/commands/finding-quality-gate.d.ts +5 -0
  22. package/dist/commands/finding-quality-gate.d.ts.map +1 -0
  23. package/dist/commands/finding-quality-gate.js +108 -0
  24. package/dist/commands/finding-quality-gate.js.map +1 -0
  25. package/dist/commands/finding-reachability.d.ts +5 -0
  26. package/dist/commands/finding-reachability.d.ts.map +1 -0
  27. package/dist/commands/finding-reachability.js +132 -0
  28. package/dist/commands/finding-reachability.js.map +1 -0
  29. package/dist/commands/finding-related-rules.d.ts +5 -0
  30. package/dist/commands/finding-related-rules.d.ts.map +1 -0
  31. package/dist/commands/finding-related-rules.js +152 -0
  32. package/dist/commands/finding-related-rules.js.map +1 -0
  33. package/dist/commands/finding-rule-explain.d.ts +5 -0
  34. package/dist/commands/finding-rule-explain.d.ts.map +1 -0
  35. package/dist/commands/finding-rule-explain.js +141 -0
  36. package/dist/commands/finding-rule-explain.js.map +1 -0
  37. package/dist/commands/finding-severity-dist.d.ts +5 -0
  38. package/dist/commands/finding-severity-dist.d.ts.map +1 -0
  39. package/dist/commands/finding-severity-dist.js +106 -0
  40. package/dist/commands/finding-severity-dist.js.map +1 -0
  41. package/dist/commands/review-ignore-pattern.d.ts +6 -0
  42. package/dist/commands/review-ignore-pattern.d.ts.map +1 -0
  43. package/dist/commands/review-ignore-pattern.js +140 -0
  44. package/dist/commands/review-ignore-pattern.js.map +1 -0
  45. package/dist/commands/review-lock-file.d.ts +5 -0
  46. package/dist/commands/review-lock-file.d.ts.map +1 -0
  47. package/dist/commands/review-lock-file.js +154 -0
  48. package/dist/commands/review-lock-file.js.map +1 -0
  49. package/dist/commands/review-merge-check.d.ts +5 -0
  50. package/dist/commands/review-merge-check.d.ts.map +1 -0
  51. package/dist/commands/review-merge-check.js +102 -0
  52. package/dist/commands/review-merge-check.js.map +1 -0
  53. package/dist/commands/review-plugin-config.d.ts +5 -0
  54. package/dist/commands/review-plugin-config.d.ts.map +1 -0
  55. package/dist/commands/review-plugin-config.js +168 -0
  56. package/dist/commands/review-plugin-config.js.map +1 -0
  57. package/dist/commands/review-plugin-list.d.ts +5 -0
  58. package/dist/commands/review-plugin-list.d.ts.map +1 -0
  59. package/dist/commands/review-plugin-list.js +100 -0
  60. package/dist/commands/review-plugin-list.js.map +1 -0
  61. package/dist/commands/review-report-merge.d.ts +5 -0
  62. package/dist/commands/review-report-merge.d.ts.map +1 -0
  63. package/dist/commands/review-report-merge.js +91 -0
  64. package/dist/commands/review-report-merge.js.map +1 -0
  65. package/dist/commands/review-status-badge.d.ts +5 -0
  66. package/dist/commands/review-status-badge.d.ts.map +1 -0
  67. package/dist/commands/review-status-badge.js +121 -0
  68. package/dist/commands/review-status-badge.js.map +1 -0
  69. package/dist/commands/review-token-budget.d.ts +5 -0
  70. package/dist/commands/review-token-budget.d.ts.map +1 -0
  71. package/dist/commands/review-token-budget.js +118 -0
  72. package/dist/commands/review-token-budget.js.map +1 -0
  73. package/dist/commands/review-workspace-scan.d.ts +5 -0
  74. package/dist/commands/review-workspace-scan.d.ts.map +1 -0
  75. package/dist/commands/review-workspace-scan.js +145 -0
  76. package/dist/commands/review-workspace-scan.js.map +1 -0
  77. package/package.json +1 -1
  78. package/server.json +2 -2
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Finding-severity-dist — Show severity distribution of findings.
3
+ */
4
+ import { readFileSync, existsSync } from "fs";
5
+ // ─── CLI ────────────────────────────────────────────────────────────────────
6
+ export function runFindingSeverityDist(argv) {
7
+ const fileIdx = argv.indexOf("--file");
8
+ const formatIdx = argv.indexOf("--format");
9
+ const filePath = fileIdx >= 0 ? argv[fileIdx + 1] : undefined;
10
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
11
+ if (argv.includes("--help") || argv.includes("-h")) {
12
+ console.log(`
13
+ judges finding-severity-dist — Show severity distribution
14
+
15
+ Usage:
16
+ judges finding-severity-dist --file <verdict.json> [--format table|json|chart]
17
+
18
+ Options:
19
+ --file <path> Path to verdict JSON file (required)
20
+ --format <fmt> Output format: table (default), json, chart
21
+ --help, -h Show this help
22
+ `);
23
+ return;
24
+ }
25
+ if (!filePath) {
26
+ console.error("Error: --file required");
27
+ process.exitCode = 1;
28
+ return;
29
+ }
30
+ if (!existsSync(filePath)) {
31
+ console.error(`Error: not found: ${filePath}`);
32
+ process.exitCode = 1;
33
+ return;
34
+ }
35
+ let verdict;
36
+ try {
37
+ verdict = JSON.parse(readFileSync(filePath, "utf-8"));
38
+ }
39
+ catch {
40
+ console.error("Error: invalid JSON");
41
+ process.exitCode = 1;
42
+ return;
43
+ }
44
+ if (verdict.findings.length === 0) {
45
+ console.log("No findings to analyze.");
46
+ return;
47
+ }
48
+ const counts = new Map();
49
+ const order = ["critical", "high", "medium", "low", "info"];
50
+ for (const f of verdict.findings) {
51
+ const sev = (f.severity || "medium").toLowerCase();
52
+ const entry = counts.get(sev) || { count: 0, rules: new Set() };
53
+ entry.count++;
54
+ entry.rules.add(f.ruleId);
55
+ counts.set(sev, entry);
56
+ }
57
+ const total = verdict.findings.length;
58
+ const buckets = order
59
+ .filter((s) => counts.has(s))
60
+ .map((s) => {
61
+ const entry = counts.get(s);
62
+ return {
63
+ severity: s,
64
+ count: entry.count,
65
+ percentage: Math.round((entry.count / total) * 1000) / 10,
66
+ rules: [...entry.rules],
67
+ };
68
+ });
69
+ // add any severities not in standard order
70
+ for (const [sev, entry] of counts) {
71
+ if (!order.includes(sev)) {
72
+ buckets.push({
73
+ severity: sev,
74
+ count: entry.count,
75
+ percentage: Math.round((entry.count / total) * 1000) / 10,
76
+ rules: [...entry.rules],
77
+ });
78
+ }
79
+ }
80
+ if (format === "json") {
81
+ console.log(JSON.stringify({ total, buckets }, null, 2));
82
+ return;
83
+ }
84
+ if (format === "chart") {
85
+ console.log(`\nSeverity Distribution (${total} findings)`);
86
+ console.log("═".repeat(55));
87
+ const maxCount = Math.max(...buckets.map((b) => b.count), 1);
88
+ for (const b of buckets) {
89
+ const barLen = Math.round((b.count / maxCount) * 30);
90
+ const bar = "█".repeat(barLen) + "░".repeat(30 - barLen);
91
+ console.log(`${b.severity.padEnd(10)} ${bar} ${b.count} (${b.percentage}%)`);
92
+ }
93
+ console.log("═".repeat(55));
94
+ return;
95
+ }
96
+ console.log(`\nSeverity Distribution (${total} findings)`);
97
+ console.log("═".repeat(60));
98
+ console.log(`${"Severity".padEnd(12)} ${"Count".padEnd(8)} ${"Pct".padEnd(8)} Rules`);
99
+ console.log("─".repeat(60));
100
+ for (const b of buckets) {
101
+ const rules = b.rules.length > 3 ? b.rules.slice(0, 3).join(", ") + ` +${b.rules.length - 3}` : b.rules.join(", ");
102
+ console.log(`${b.severity.padEnd(12)} ${String(b.count).padEnd(8)} ${(b.percentage + "%").padEnd(8)} ${rules}`);
103
+ }
104
+ console.log("═".repeat(60));
105
+ }
106
+ //# sourceMappingURL=finding-severity-dist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-severity-dist.js","sourceRoot":"","sources":["../../src/commands/finding-severity-dist.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAY9C,+EAA+E;AAE/E,MAAM,UAAU,sBAAsB,CAAC,IAAc;IACnD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACvC,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,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;;;;;;;;;;CAUf,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,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QACvC,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,GAAG,EAAiD,CAAC;IACxE,MAAM,KAAK,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAE5D,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,IAAI,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;QACnD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,GAAG,EAAU,EAAE,CAAC;QACxE,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAC1B,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACzB,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IACtC,MAAM,OAAO,GAAqB,KAAK;SACpC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SAC5B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC;QAC7B,OAAO;YACL,QAAQ,EAAE,CAAC;YACX,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE;YACzD,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;SACxB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEL,2CAA2C;IAC3C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;QAClC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,IAAI,CAAC;gBACX,QAAQ,EAAE,GAAG;gBACb,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE;gBACzD,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;aACxB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACzD,OAAO;IACT,CAAC;IAED,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,4BAA4B,KAAK,YAAY,CAAC,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7D,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;YACrD,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC;YACzD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC;QAC/E,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5B,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,4BAA4B,KAAK,YAAY,CAAC,CAAC;IAC3D,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,OAAO,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IACtF,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAE5B,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnH,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC;IAClH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Review-ignore-pattern — Manage file/path ignore patterns for reviews.
3
+ */
4
+ export declare function isIgnored(filePath: string): boolean;
5
+ export declare function runReviewIgnorePattern(argv: string[]): void;
6
+ //# sourceMappingURL=review-ignore-pattern.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-ignore-pattern.d.ts","sourceRoot":"","sources":["../../src/commands/review-ignore-pattern.ts"],"names":[],"mappings":"AAAA;;GAEG;AAwCH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAGnD;AAID,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAoH3D"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Review-ignore-pattern — Manage file/path ignore patterns for reviews.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ // ─── Helpers ────────────────────────────────────────────────────────────────
6
+ const CONFIG_PATH = ".judges/ignore-patterns.json";
7
+ function loadConfig() {
8
+ if (!existsSync(CONFIG_PATH)) {
9
+ return { version: 1, patterns: [], lastUpdated: new Date().toISOString() };
10
+ }
11
+ try {
12
+ return JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
13
+ }
14
+ catch {
15
+ return { version: 1, patterns: [], lastUpdated: new Date().toISOString() };
16
+ }
17
+ }
18
+ function saveConfig(config) {
19
+ const dir = CONFIG_PATH.substring(0, CONFIG_PATH.lastIndexOf("/"));
20
+ if (!existsSync(dir))
21
+ mkdirSync(dir, { recursive: true });
22
+ config.lastUpdated = new Date().toISOString();
23
+ writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
24
+ }
25
+ function matchesPattern(filePath, pattern) {
26
+ // simple glob: * matches any non-slash, ** matches anything
27
+ const regexStr = pattern.replace(/\./g, "\\.").replace(/\*\*/g, "§§").replace(/\*/g, "[^/]*").replace(/§§/g, ".*");
28
+ return new RegExp(`^${regexStr}$`).test(filePath) || new RegExp(regexStr).test(filePath);
29
+ }
30
+ export function isIgnored(filePath) {
31
+ const config = loadConfig();
32
+ return config.patterns.some((p) => matchesPattern(filePath, p));
33
+ }
34
+ // ─── CLI ────────────────────────────────────────────────────────────────────
35
+ export function runReviewIgnorePattern(argv) {
36
+ const sub = argv[0];
37
+ if (argv.includes("--help") || argv.includes("-h") || !sub) {
38
+ console.log(`
39
+ judges review-ignore-pattern — Manage review ignore patterns
40
+
41
+ Usage:
42
+ judges review-ignore-pattern add <pattern>
43
+ judges review-ignore-pattern remove <pattern>
44
+ judges review-ignore-pattern list [--format table|json]
45
+ judges review-ignore-pattern test <filepath>
46
+
47
+ Subcommands:
48
+ add Add an ignore pattern
49
+ remove Remove an ignore pattern
50
+ list List all patterns
51
+ test Test if a file matches any pattern
52
+
53
+ Examples:
54
+ judges review-ignore-pattern add "node_modules/**"
55
+ judges review-ignore-pattern add "*.test.ts"
56
+ judges review-ignore-pattern test "src/index.ts"
57
+
58
+ Options:
59
+ --format <fmt> Output format: table (default), json
60
+ --help, -h Show this help
61
+ `);
62
+ return;
63
+ }
64
+ const formatIdx = argv.indexOf("--format");
65
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
66
+ if (sub === "add") {
67
+ const pattern = argv[1];
68
+ if (!pattern) {
69
+ console.error("Error: pattern required");
70
+ process.exitCode = 1;
71
+ return;
72
+ }
73
+ const config = loadConfig();
74
+ if (config.patterns.includes(pattern)) {
75
+ console.log(`Pattern already exists: ${pattern}`);
76
+ return;
77
+ }
78
+ config.patterns.push(pattern);
79
+ saveConfig(config);
80
+ console.log(`Added pattern: ${pattern}`);
81
+ return;
82
+ }
83
+ if (sub === "remove") {
84
+ const pattern = argv[1];
85
+ if (!pattern) {
86
+ console.error("Error: pattern required");
87
+ process.exitCode = 1;
88
+ return;
89
+ }
90
+ const config = loadConfig();
91
+ const idx = config.patterns.indexOf(pattern);
92
+ if (idx < 0) {
93
+ console.error(`Pattern not found: ${pattern}`);
94
+ process.exitCode = 1;
95
+ return;
96
+ }
97
+ config.patterns.splice(idx, 1);
98
+ saveConfig(config);
99
+ console.log(`Removed pattern: ${pattern}`);
100
+ return;
101
+ }
102
+ if (sub === "list") {
103
+ const config = loadConfig();
104
+ if (config.patterns.length === 0) {
105
+ console.log("No ignore patterns configured.");
106
+ return;
107
+ }
108
+ if (format === "json") {
109
+ console.log(JSON.stringify(config, null, 2));
110
+ return;
111
+ }
112
+ console.log(`\nIgnore Patterns (${config.patterns.length})`);
113
+ console.log("═".repeat(50));
114
+ for (const p of config.patterns) {
115
+ console.log(` ${p}`);
116
+ }
117
+ console.log("═".repeat(50));
118
+ return;
119
+ }
120
+ if (sub === "test") {
121
+ const filePath = argv[1];
122
+ if (!filePath) {
123
+ console.error("Error: filepath required");
124
+ process.exitCode = 1;
125
+ return;
126
+ }
127
+ const config = loadConfig();
128
+ const matched = config.patterns.filter((p) => matchesPattern(filePath, p));
129
+ if (matched.length > 0) {
130
+ console.log(`${filePath} — IGNORED (matches: ${matched.join(", ")})`);
131
+ }
132
+ else {
133
+ console.log(`${filePath} — NOT ignored`);
134
+ }
135
+ return;
136
+ }
137
+ console.error(`Error: unknown subcommand: ${sub}`);
138
+ process.exitCode = 1;
139
+ }
140
+ //# sourceMappingURL=review-ignore-pattern.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-ignore-pattern.js","sourceRoot":"","sources":["../../src/commands/review-ignore-pattern.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-lock-file — Analyze lock files for security and consistency issues.
3
+ */
4
+ export declare function runReviewLockFile(argv: string[]): void;
5
+ //# sourceMappingURL=review-lock-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-lock-file.d.ts","sourceRoot":"","sources":["../../src/commands/review-lock-file.ts"],"names":[],"mappings":"AAAA;;GAEG;AAqHH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAmEtD"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Review-lock-file — Analyze lock files for security and consistency issues.
3
+ */
4
+ import { readFileSync, existsSync } from "fs";
5
+ // ─── Analysis ───────────────────────────────────────────────────────────────
6
+ function analyzeNpmLock(content) {
7
+ const issues = [];
8
+ let lockData;
9
+ try {
10
+ lockData = JSON.parse(content);
11
+ }
12
+ catch {
13
+ return [
14
+ { type: "integrity-missing", package: "(parse-error)", detail: "Invalid JSON in lock file", severity: "high" },
15
+ ];
16
+ }
17
+ const packages = (lockData.packages || lockData.dependencies || {});
18
+ for (const [name, info] of Object.entries(packages)) {
19
+ if (!name || name === "")
20
+ continue;
21
+ // check for missing integrity
22
+ if (info !== null && info !== undefined && !info.integrity && !name.startsWith("node_modules")) {
23
+ // Only flag actual packages, not the root
24
+ if (name !== "" && info.version !== undefined) {
25
+ issues.push({
26
+ type: "integrity-missing",
27
+ package: name,
28
+ detail: "No integrity hash — supply chain risk",
29
+ severity: "high",
30
+ });
31
+ }
32
+ }
33
+ // check for git dependencies
34
+ const resolved = String(info.resolved || "");
35
+ if (resolved.startsWith("git+") || resolved.startsWith("git://") || resolved.includes("github.com")) {
36
+ issues.push({
37
+ type: "git-dependency",
38
+ package: name,
39
+ detail: `Git dependency: ${resolved.slice(0, 60)}`,
40
+ severity: "medium",
41
+ });
42
+ }
43
+ // check for http (non-https) registry
44
+ if (resolved.startsWith("http://")) {
45
+ issues.push({
46
+ type: "http-registry",
47
+ package: name,
48
+ detail: "Uses HTTP instead of HTTPS — insecure transport",
49
+ severity: "high",
50
+ });
51
+ }
52
+ }
53
+ return issues;
54
+ }
55
+ function analyzeYarnLock(content) {
56
+ const issues = [];
57
+ const lines = content.split("\n");
58
+ let currentPkg = "";
59
+ for (const line of lines) {
60
+ if (line.startsWith('"') || (line.startsWith("@") && line.includes('"'))) {
61
+ currentPkg = line.replace(/[",:]/g, "").trim().split("@")[0] || line.replace(/[",:]/g, "").trim();
62
+ }
63
+ if (line.includes("resolved") && line.includes("http://")) {
64
+ issues.push({
65
+ type: "http-registry",
66
+ package: currentPkg,
67
+ detail: "Uses HTTP instead of HTTPS",
68
+ severity: "high",
69
+ });
70
+ }
71
+ if (line.includes("resolved") && (line.includes("github.com") || line.includes("git+"))) {
72
+ issues.push({
73
+ type: "git-dependency",
74
+ package: currentPkg,
75
+ detail: "Git dependency detected",
76
+ severity: "medium",
77
+ });
78
+ }
79
+ }
80
+ return issues;
81
+ }
82
+ function analyzeLockFile(filePath) {
83
+ const content = readFileSync(filePath, "utf-8");
84
+ if (filePath.endsWith("package-lock.json")) {
85
+ return analyzeNpmLock(content);
86
+ }
87
+ if (filePath.endsWith("yarn.lock")) {
88
+ return analyzeYarnLock(content);
89
+ }
90
+ return [{ type: "integrity-missing", package: "(unknown)", detail: "Unsupported lock file format", severity: "low" }];
91
+ }
92
+ // ─── CLI ────────────────────────────────────────────────────────────────────
93
+ export function runReviewLockFile(argv) {
94
+ const fileIdx = argv.indexOf("--file");
95
+ const formatIdx = argv.indexOf("--format");
96
+ const filePath = fileIdx >= 0 ? argv[fileIdx + 1] : undefined;
97
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
98
+ if (argv.includes("--help") || argv.includes("-h")) {
99
+ console.log(`
100
+ judges review-lock-file — Analyze lock files for security issues
101
+
102
+ Usage:
103
+ judges review-lock-file --file <lock-file> [--format table|json]
104
+
105
+ Options:
106
+ --file <path> Path to lock file (package-lock.json, yarn.lock)
107
+ --format <fmt> Output format: table (default), json
108
+ --help, -h Show this help
109
+
110
+ Checks:
111
+ - Missing integrity hashes
112
+ - HTTP (insecure) registries
113
+ - Git dependencies
114
+ - Registry mismatches
115
+ `);
116
+ return;
117
+ }
118
+ if (!filePath) {
119
+ console.error("Error: --file required");
120
+ process.exitCode = 1;
121
+ return;
122
+ }
123
+ if (!existsSync(filePath)) {
124
+ console.error(`Error: not found: ${filePath}`);
125
+ process.exitCode = 1;
126
+ return;
127
+ }
128
+ const issues = analyzeLockFile(filePath);
129
+ if (format === "json") {
130
+ console.log(JSON.stringify(issues, null, 2));
131
+ return;
132
+ }
133
+ const high = issues.filter((i) => i.severity === "high").length;
134
+ const medium = issues.filter((i) => i.severity === "medium").length;
135
+ const low = issues.filter((i) => i.severity === "low").length;
136
+ console.log(`\nLock File Analysis: ${filePath}`);
137
+ console.log("═".repeat(75));
138
+ console.log(` Issues: ${issues.length} (${high} high, ${medium} medium, ${low} low)`);
139
+ console.log("─".repeat(75));
140
+ if (issues.length === 0) {
141
+ console.log(" No issues found — lock file looks clean.");
142
+ }
143
+ else {
144
+ console.log(`${"Severity".padEnd(10)} ${"Type".padEnd(20)} ${"Package".padEnd(25)} Detail`);
145
+ console.log("─".repeat(75));
146
+ for (const issue of issues) {
147
+ const pkg = issue.package.length > 23 ? issue.package.slice(0, 23) + "…" : issue.package;
148
+ const detail = issue.detail.length > 30 ? issue.detail.slice(0, 30) + "…" : issue.detail;
149
+ console.log(`${issue.severity.padEnd(10)} ${issue.type.padEnd(20)} ${pkg.padEnd(25)} ${detail}`);
150
+ }
151
+ }
152
+ console.log("═".repeat(75));
153
+ }
154
+ //# sourceMappingURL=review-lock-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-lock-file.js","sourceRoot":"","sources":["../../src/commands/review-lock-file.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-merge-check — Pre-merge review validation.
3
+ */
4
+ export declare function runReviewMergeCheck(argv: string[]): void;
5
+ //# sourceMappingURL=review-merge-check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-merge-check.d.ts","sourceRoot":"","sources":["../../src/commands/review-merge-check.ts"],"names":[],"mappings":"AAAA;;GAEG;AAsBH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA6GxD"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Review-merge-check — Pre-merge review validation.
3
+ */
4
+ import { readFileSync, existsSync } from "fs";
5
+ // ─── CLI ────────────────────────────────────────────────────────────────────
6
+ export function runReviewMergeCheck(argv) {
7
+ const fileIdx = argv.indexOf("--file");
8
+ const strictIdx = argv.indexOf("--strict");
9
+ const formatIdx = argv.indexOf("--format");
10
+ const filePath = fileIdx >= 0 ? argv[fileIdx + 1] : undefined;
11
+ const strict = strictIdx >= 0;
12
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
13
+ if (argv.includes("--help") || argv.includes("-h")) {
14
+ console.log(`
15
+ judges review-merge-check — Pre-merge review validation
16
+
17
+ Usage:
18
+ judges review-merge-check --file <verdict.json> [--strict] [--format table|json]
19
+
20
+ Options:
21
+ --file <path> Path to verdict JSON file (required)
22
+ --strict Enable strict mode (no critical or high findings)
23
+ --format <fmt> Output format: table (default), json
24
+ --help, -h Show this help
25
+ `);
26
+ return;
27
+ }
28
+ if (!filePath) {
29
+ console.error("Error: --file required");
30
+ process.exitCode = 1;
31
+ return;
32
+ }
33
+ if (!existsSync(filePath)) {
34
+ console.error(`Error: not found: ${filePath}`);
35
+ process.exitCode = 1;
36
+ return;
37
+ }
38
+ let verdict;
39
+ try {
40
+ verdict = JSON.parse(readFileSync(filePath, "utf-8"));
41
+ }
42
+ catch {
43
+ console.error("Error: invalid JSON");
44
+ process.exitCode = 1;
45
+ return;
46
+ }
47
+ const checks = [];
48
+ // Check 1: No critical findings
49
+ checks.push({
50
+ name: "No critical findings",
51
+ passed: verdict.criticalCount === 0,
52
+ detail: verdict.criticalCount === 0 ? "No critical findings" : `${verdict.criticalCount} critical finding(s)`,
53
+ });
54
+ // Check 2: Score above threshold
55
+ const scoreThreshold = strict ? 70 : 40;
56
+ checks.push({
57
+ name: `Score ≥ ${scoreThreshold}`,
58
+ passed: verdict.overallScore >= scoreThreshold,
59
+ detail: `Score: ${verdict.overallScore}`,
60
+ });
61
+ // Check 3: Verdict is not fail (in unstrict mode)
62
+ checks.push({
63
+ name: "Verdict is not fail",
64
+ passed: verdict.overallVerdict !== "fail",
65
+ detail: `Verdict: ${verdict.overallVerdict}`,
66
+ });
67
+ // Check 4: (strict) No high findings
68
+ if (strict) {
69
+ checks.push({
70
+ name: "No high findings",
71
+ passed: verdict.highCount === 0,
72
+ detail: verdict.highCount === 0 ? "No high findings" : `${verdict.highCount} high finding(s)`,
73
+ });
74
+ }
75
+ // Check 5: (strict) Limited total findings
76
+ if (strict) {
77
+ checks.push({
78
+ name: "Total findings ≤ 10",
79
+ passed: verdict.findings.length <= 10,
80
+ detail: `${verdict.findings.length} total finding(s)`,
81
+ });
82
+ }
83
+ const canMerge = checks.every((c) => c.passed);
84
+ const result = { canMerge, checks, verdict: verdict.overallVerdict, score: verdict.overallScore };
85
+ if (format === "json") {
86
+ console.log(JSON.stringify(result, null, 2));
87
+ return;
88
+ }
89
+ console.log(`\nMerge Check Results${strict ? " (strict)" : ""}`);
90
+ console.log("═".repeat(55));
91
+ for (const c of checks) {
92
+ const icon = c.passed ? "PASS" : "FAIL";
93
+ console.log(` [${icon}] ${c.name}`);
94
+ console.log(` ${c.detail}`);
95
+ }
96
+ console.log("═".repeat(55));
97
+ console.log(`\nResult: ${canMerge ? "MERGE ALLOWED" : "MERGE BLOCKED"}`);
98
+ if (!canMerge) {
99
+ process.exitCode = 1;
100
+ }
101
+ }
102
+ //# sourceMappingURL=review-merge-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-merge-check.js","sourceRoot":"","sources":["../../src/commands/review-merge-check.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-plugin-config — View and manage plugin configuration.
3
+ */
4
+ export declare function runReviewPluginConfig(argv: string[]): void;
5
+ //# sourceMappingURL=review-plugin-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-plugin-config.d.ts","sourceRoot":"","sources":["../../src/commands/review-plugin-config.ts"],"names":[],"mappings":"AAAA;;GAEG;AA2CH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA0J1D"}