@kevinrabun/judges 3.86.0 → 3.88.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 +32 -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-age-analysis.d.ts +5 -0
  6. package/dist/commands/finding-age-analysis.d.ts.map +1 -0
  7. package/dist/commands/finding-age-analysis.js +145 -0
  8. package/dist/commands/finding-age-analysis.js.map +1 -0
  9. package/dist/commands/finding-code-smell.d.ts +5 -0
  10. package/dist/commands/finding-code-smell.d.ts.map +1 -0
  11. package/dist/commands/finding-code-smell.js +114 -0
  12. package/dist/commands/finding-code-smell.js.map +1 -0
  13. package/dist/commands/finding-correlation.d.ts +5 -0
  14. package/dist/commands/finding-correlation.d.ts.map +1 -0
  15. package/dist/commands/finding-correlation.js +104 -0
  16. package/dist/commands/finding-correlation.js.map +1 -0
  17. package/dist/commands/finding-dependency-tree.d.ts +5 -0
  18. package/dist/commands/finding-dependency-tree.d.ts.map +1 -0
  19. package/dist/commands/finding-dependency-tree.js +117 -0
  20. package/dist/commands/finding-dependency-tree.js.map +1 -0
  21. package/dist/commands/finding-owner-assign.d.ts +5 -0
  22. package/dist/commands/finding-owner-assign.d.ts.map +1 -0
  23. package/dist/commands/finding-owner-assign.js +134 -0
  24. package/dist/commands/finding-owner-assign.js.map +1 -0
  25. package/dist/commands/finding-pattern-library.d.ts +5 -0
  26. package/dist/commands/finding-pattern-library.d.ts.map +1 -0
  27. package/dist/commands/finding-pattern-library.js +146 -0
  28. package/dist/commands/finding-pattern-library.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-suppression-audit.d.ts +5 -0
  38. package/dist/commands/finding-suppression-audit.d.ts.map +1 -0
  39. package/dist/commands/finding-suppression-audit.js +138 -0
  40. package/dist/commands/finding-suppression-audit.js.map +1 -0
  41. package/dist/commands/review-ci-integration.d.ts +5 -0
  42. package/dist/commands/review-ci-integration.d.ts.map +1 -0
  43. package/dist/commands/review-ci-integration.js +126 -0
  44. package/dist/commands/review-ci-integration.js.map +1 -0
  45. package/dist/commands/review-comparative.d.ts +5 -0
  46. package/dist/commands/review-comparative.d.ts.map +1 -0
  47. package/dist/commands/review-comparative.js +150 -0
  48. package/dist/commands/review-comparative.js.map +1 -0
  49. package/dist/commands/review-custom-rule.d.ts +5 -0
  50. package/dist/commands/review-custom-rule.d.ts.map +1 -0
  51. package/dist/commands/review-custom-rule.js +170 -0
  52. package/dist/commands/review-custom-rule.js.map +1 -0
  53. package/dist/commands/review-lock-file.d.ts +5 -0
  54. package/dist/commands/review-lock-file.d.ts.map +1 -0
  55. package/dist/commands/review-lock-file.js +154 -0
  56. package/dist/commands/review-lock-file.js.map +1 -0
  57. package/dist/commands/review-notification.d.ts +5 -0
  58. package/dist/commands/review-notification.d.ts.map +1 -0
  59. package/dist/commands/review-notification.js +127 -0
  60. package/dist/commands/review-notification.js.map +1 -0
  61. package/dist/commands/review-plugin-list.d.ts +5 -0
  62. package/dist/commands/review-plugin-list.d.ts.map +1 -0
  63. package/dist/commands/review-plugin-list.js +100 -0
  64. package/dist/commands/review-plugin-list.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-template-export.d.ts +5 -0
  70. package/dist/commands/review-template-export.d.ts.map +1 -0
  71. package/dist/commands/review-template-export.js +147 -0
  72. package/dist/commands/review-template-export.js.map +1 -0
  73. package/dist/commands/review-token-budget.d.ts +5 -0
  74. package/dist/commands/review-token-budget.d.ts.map +1 -0
  75. package/dist/commands/review-token-budget.js +118 -0
  76. package/dist/commands/review-token-budget.js.map +1 -0
  77. package/package.json +1 -1
  78. package/server.json +2 -2
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Finding-owner-assign — Assign ownership of findings based on configurable rules.
3
+ */
4
+ import { readFileSync, existsSync, writeFileSync } from "fs";
5
+ // ─── Helpers ────────────────────────────────────────────────────────────────
6
+ function loadOwnerRules(configPath) {
7
+ if (!existsSync(configPath))
8
+ return [];
9
+ try {
10
+ const data = JSON.parse(readFileSync(configPath, "utf-8"));
11
+ if (Array.isArray(data.rules)) {
12
+ return data.rules;
13
+ }
14
+ return [];
15
+ }
16
+ catch {
17
+ return [];
18
+ }
19
+ }
20
+ function assignOwners(verdict, rules) {
21
+ const assignments = [];
22
+ for (const f of verdict.findings) {
23
+ let owner = "unassigned";
24
+ let matchedPattern = "";
25
+ for (const rule of rules) {
26
+ const ruleIdLower = f.ruleId.toLowerCase();
27
+ const titleLower = f.title.toLowerCase();
28
+ const patLower = rule.pattern.toLowerCase();
29
+ if (ruleIdLower.includes(patLower) || titleLower.includes(patLower)) {
30
+ owner = rule.owner;
31
+ matchedPattern = rule.pattern;
32
+ break;
33
+ }
34
+ }
35
+ // fallback: assign by severity
36
+ if (owner === "unassigned") {
37
+ const sev = (f.severity || "medium").toLowerCase();
38
+ if (sev === "critical" || sev === "high") {
39
+ owner = "security-team";
40
+ matchedPattern = `severity:${sev}`;
41
+ }
42
+ }
43
+ assignments.push({
44
+ ruleId: f.ruleId,
45
+ title: f.title,
46
+ severity: (f.severity || "medium").toLowerCase(),
47
+ owner,
48
+ matchedPattern,
49
+ });
50
+ }
51
+ return assignments;
52
+ }
53
+ // ─── CLI ────────────────────────────────────────────────────────────────────
54
+ export function runFindingOwnerAssign(argv) {
55
+ const fileIdx = argv.indexOf("--file");
56
+ const configIdx = argv.indexOf("--config");
57
+ const formatIdx = argv.indexOf("--format");
58
+ const outIdx = argv.indexOf("--output");
59
+ const filePath = fileIdx >= 0 ? argv[fileIdx + 1] : undefined;
60
+ const configPath = configIdx >= 0 ? argv[configIdx + 1] : ".judges-owners.json";
61
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
62
+ const outputPath = outIdx >= 0 ? argv[outIdx + 1] : undefined;
63
+ if (argv.includes("--help") || argv.includes("-h")) {
64
+ console.log(`
65
+ judges finding-owner-assign — Assign finding owners
66
+
67
+ Usage:
68
+ judges finding-owner-assign --file <verdict.json> [--config <owners.json>]
69
+ [--format table|json] [--output <file>]
70
+
71
+ Options:
72
+ --file <path> Path to verdict JSON file (required)
73
+ --config <path> Owner rules config (default: .judges-owners.json)
74
+ --format <fmt> Output format: table (default), json
75
+ --output <path> Write assignments to file
76
+ --help, -h Show this help
77
+
78
+ Config format:
79
+ { "rules": [{ "pattern": "AUTH", "owner": "security-team" }] }
80
+ `);
81
+ return;
82
+ }
83
+ if (!filePath) {
84
+ console.error("Error: --file required");
85
+ process.exitCode = 1;
86
+ return;
87
+ }
88
+ if (!existsSync(filePath)) {
89
+ console.error(`Error: not found: ${filePath}`);
90
+ process.exitCode = 1;
91
+ return;
92
+ }
93
+ let verdict;
94
+ try {
95
+ verdict = JSON.parse(readFileSync(filePath, "utf-8"));
96
+ }
97
+ catch {
98
+ console.error("Error: invalid JSON");
99
+ process.exitCode = 1;
100
+ return;
101
+ }
102
+ const rules = loadOwnerRules(configPath);
103
+ const assignments = assignOwners(verdict, rules);
104
+ if (outputPath) {
105
+ writeFileSync(outputPath, JSON.stringify(assignments, null, 2));
106
+ console.log(`Wrote ${assignments.length} assignments to ${outputPath}`);
107
+ return;
108
+ }
109
+ if (format === "json") {
110
+ console.log(JSON.stringify(assignments, null, 2));
111
+ return;
112
+ }
113
+ // group by owner
114
+ const byOwner = new Map();
115
+ for (const a of assignments) {
116
+ const arr = byOwner.get(a.owner) || [];
117
+ arr.push(a);
118
+ byOwner.set(a.owner, arr);
119
+ }
120
+ console.log(`\nFinding Owner Assignments (${assignments.length} findings)`);
121
+ console.log("═".repeat(75));
122
+ for (const [owner, items] of byOwner) {
123
+ console.log(`\n Owner: ${owner} (${items.length} findings)`);
124
+ console.log(" " + "─".repeat(70));
125
+ console.log(` ${"Rule".padEnd(20)} ${"Severity".padEnd(10)} Title`);
126
+ for (const a of items) {
127
+ const rule = a.ruleId.length > 18 ? a.ruleId.slice(0, 18) + "…" : a.ruleId;
128
+ const title = a.title.length > 35 ? a.title.slice(0, 35) + "…" : a.title;
129
+ console.log(` ${rule.padEnd(20)} ${a.severity.padEnd(10)} ${title}`);
130
+ }
131
+ }
132
+ console.log("\n" + "═".repeat(75));
133
+ }
134
+ //# sourceMappingURL=finding-owner-assign.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-owner-assign.js","sourceRoot":"","sources":["../../src/commands/finding-owner-assign.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAkB7D,+EAA+E;AAE/E,SAAS,cAAc,CAAC,UAAkB;IACxC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,EAAE,CAAC;IACvC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;QAC3D,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC,KAAoB,CAAC;QACnC,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,OAAwB,EAAE,KAAkB;IAChE,MAAM,WAAW,GAAsB,EAAE,CAAC;IAE1C,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACjC,IAAI,KAAK,GAAG,YAAY,CAAC;QACzB,IAAI,cAAc,GAAG,EAAE,CAAC;QAExB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YAC3C,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;YACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;YAE5C,IAAI,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACpE,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;gBACnB,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC;gBAC9B,MAAM;YACR,CAAC;QACH,CAAC;QAED,+BAA+B;QAC/B,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;YAC3B,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,IAAI,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;YACnD,IAAI,GAAG,KAAK,UAAU,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;gBACzC,KAAK,GAAG,eAAe,CAAC;gBACxB,cAAc,GAAG,YAAY,GAAG,EAAE,CAAC;YACrC,CAAC;QACH,CAAC;QAED,WAAW,CAAC,IAAI,CAAC;YACf,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,QAAQ,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,QAAQ,CAAC,CAAC,WAAW,EAAE;YAChD,KAAK;YACL,cAAc;SACf,CAAC,CAAC;IACL,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,+EAA+E;AAE/E,MAAM,UAAU,qBAAqB,CAAC,IAAc;IAClD,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,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACxC,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,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC;IAChF,MAAM,MAAM,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAC9D,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE9D,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;CAgBf,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,KAAK,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IACzC,MAAM,WAAW,GAAG,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAEjD,IAAI,UAAU,EAAE,CAAC;QACf,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAChE,OAAO,CAAC,GAAG,CAAC,SAAS,WAAW,CAAC,MAAM,mBAAmB,UAAU,EAAE,CAAC,CAAC;QACxE,OAAO;IACT,CAAC;IAED,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAClD,OAAO;IACT,CAAC;IAED,iBAAiB;IACjB,MAAM,OAAO,GAAG,IAAI,GAAG,EAA6B,CAAC;IACrD,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACvC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,gCAAgC,WAAW,CAAC,MAAM,YAAY,CAAC,CAAC;IAC5E,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAE5B,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,KAAK,KAAK,CAAC,MAAM,YAAY,CAAC,CAAC;QAC9D,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;QAErE,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YAC3E,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;YACzE,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AACrC,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Finding-pattern-library — Manage a local library of finding patterns for reuse.
3
+ */
4
+ export declare function runFindingPatternLibrary(argv: string[]): void;
5
+ //# sourceMappingURL=finding-pattern-library.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-pattern-library.d.ts","sourceRoot":"","sources":["../../src/commands/finding-pattern-library.ts"],"names":[],"mappings":"AAAA;;GAEG;AA0EH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA6G7D"}
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Finding-pattern-library — Manage a local library of finding patterns for reuse.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { dirname } from "path";
6
+ // ─── Helpers ────────────────────────────────────────────────────────────────
7
+ function loadLibrary(libPath) {
8
+ if (!existsSync(libPath)) {
9
+ return { version: 1, patterns: [] };
10
+ }
11
+ try {
12
+ return JSON.parse(readFileSync(libPath, "utf-8"));
13
+ }
14
+ catch {
15
+ return { version: 1, patterns: [] };
16
+ }
17
+ }
18
+ function saveLibrary(libPath, lib) {
19
+ const dir = dirname(libPath);
20
+ if (!existsSync(dir)) {
21
+ mkdirSync(dir, { recursive: true });
22
+ }
23
+ writeFileSync(libPath, JSON.stringify(lib, null, 2));
24
+ }
25
+ function importPatterns(lib, verdict) {
26
+ const now = new Date().toISOString();
27
+ let added = 0;
28
+ for (const f of verdict.findings) {
29
+ const existing = lib.patterns.find((p) => p.ruleId === f.ruleId);
30
+ if (existing) {
31
+ existing.occurrences++;
32
+ existing.lastSeen = now;
33
+ }
34
+ else {
35
+ lib.patterns.push({
36
+ ruleId: f.ruleId,
37
+ title: f.title,
38
+ severity: (f.severity || "medium").toLowerCase(),
39
+ description: f.description,
40
+ recommendation: f.recommendation,
41
+ occurrences: 1,
42
+ firstSeen: now,
43
+ lastSeen: now,
44
+ });
45
+ added++;
46
+ }
47
+ }
48
+ return added;
49
+ }
50
+ // ─── CLI ────────────────────────────────────────────────────────────────────
51
+ export function runFindingPatternLibrary(argv) {
52
+ const actionIdx = argv.indexOf("--action");
53
+ const fileIdx = argv.indexOf("--file");
54
+ const libIdx = argv.indexOf("--library");
55
+ const formatIdx = argv.indexOf("--format");
56
+ const searchIdx = argv.indexOf("--search");
57
+ const action = actionIdx >= 0 ? argv[actionIdx + 1] : "list";
58
+ const filePath = fileIdx >= 0 ? argv[fileIdx + 1] : undefined;
59
+ const libPath = libIdx >= 0 ? argv[libIdx + 1] : ".judges-patterns.json";
60
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
61
+ const searchTerm = searchIdx >= 0 ? argv[searchIdx + 1] : undefined;
62
+ if (argv.includes("--help") || argv.includes("-h")) {
63
+ console.log(`
64
+ judges finding-pattern-library — Manage finding pattern library
65
+
66
+ Usage:
67
+ judges finding-pattern-library --action <action> [options]
68
+
69
+ Actions:
70
+ list List patterns in library (default)
71
+ import Import patterns from verdict file
72
+ search Search patterns by keyword
73
+
74
+ Options:
75
+ --action <act> Action: list, import, search
76
+ --file <path> Verdict JSON file (required for import)
77
+ --library <path> Library file (default: .judges-patterns.json)
78
+ --search <term> Search term (for search action)
79
+ --format <fmt> Output format: table (default), json
80
+ --help, -h Show this help
81
+ `);
82
+ return;
83
+ }
84
+ const lib = loadLibrary(libPath);
85
+ if (action === "import") {
86
+ if (!filePath) {
87
+ console.error("Error: --file required for import");
88
+ process.exitCode = 1;
89
+ return;
90
+ }
91
+ if (!existsSync(filePath)) {
92
+ console.error(`Error: not found: ${filePath}`);
93
+ process.exitCode = 1;
94
+ return;
95
+ }
96
+ let verdict;
97
+ try {
98
+ verdict = JSON.parse(readFileSync(filePath, "utf-8"));
99
+ }
100
+ catch {
101
+ console.error("Error: invalid JSON");
102
+ process.exitCode = 1;
103
+ return;
104
+ }
105
+ const added = importPatterns(lib, verdict);
106
+ saveLibrary(libPath, lib);
107
+ console.log(`Imported ${added} new patterns (${lib.patterns.length} total in library)`);
108
+ return;
109
+ }
110
+ if (action === "search") {
111
+ const term = (searchTerm || "").toLowerCase();
112
+ const matches = lib.patterns.filter((p) => p.ruleId.toLowerCase().includes(term) ||
113
+ p.title.toLowerCase().includes(term) ||
114
+ p.description.toLowerCase().includes(term));
115
+ if (format === "json") {
116
+ console.log(JSON.stringify(matches, null, 2));
117
+ return;
118
+ }
119
+ console.log(`\nPattern Search: "${searchTerm}" (${matches.length} matches)`);
120
+ console.log("═".repeat(70));
121
+ for (const p of matches) {
122
+ console.log(` ${p.ruleId.padEnd(20)} ${p.title}`);
123
+ console.log(` Severity: ${p.severity} | Occurrences: ${p.occurrences}`);
124
+ }
125
+ console.log("═".repeat(70));
126
+ return;
127
+ }
128
+ // default: list
129
+ if (format === "json") {
130
+ console.log(JSON.stringify(lib, null, 2));
131
+ return;
132
+ }
133
+ console.log(`\nPattern Library (${lib.patterns.length} patterns)`);
134
+ console.log("═".repeat(75));
135
+ console.log(`${"Rule".padEnd(20)} ${"Severity".padEnd(10)} ${"Seen".padEnd(6)} ${"Last Seen".padEnd(22)} Title`);
136
+ console.log("─".repeat(75));
137
+ const sorted = [...lib.patterns].sort((a, b) => b.occurrences - a.occurrences);
138
+ for (const p of sorted) {
139
+ const rule = p.ruleId.length > 18 ? p.ruleId.slice(0, 18) + "…" : p.ruleId;
140
+ const title = p.title.length > 20 ? p.title.slice(0, 20) + "…" : p.title;
141
+ const lastSeen = p.lastSeen.slice(0, 19);
142
+ console.log(`${rule.padEnd(20)} ${p.severity.padEnd(10)} ${String(p.occurrences).padEnd(6)} ${lastSeen.padEnd(22)} ${title}`);
143
+ }
144
+ console.log("═".repeat(75));
145
+ }
146
+ //# sourceMappingURL=finding-pattern-library.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-pattern-library.js","sourceRoot":"","sources":["../../src/commands/finding-pattern-library.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Finding-related-rules — Find rules related to a given rule ID.
3
+ */
4
+ export declare function runFindingRelatedRules(argv: string[]): void;
5
+ //# sourceMappingURL=finding-related-rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-related-rules.d.ts","sourceRoot":"","sources":["../../src/commands/finding-related-rules.ts"],"names":[],"mappings":"AAAA;;GAEG;AAkHH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAoE3D"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Finding-related-rules — Find rules related to a given rule ID.
3
+ */
4
+ import { readFileSync, existsSync } from "fs";
5
+ import { defaultRegistry } from "../judge-registry.js";
6
+ // ─── Helpers ────────────────────────────────────────────────────────────────
7
+ function tokenize(text) {
8
+ return new Set(text
9
+ .toLowerCase()
10
+ .replace(/[^a-z0-9\s]/g, " ")
11
+ .split(/\s+/)
12
+ .filter((w) => w.length > 2));
13
+ }
14
+ function titleSimilarity(a, b) {
15
+ const ta = tokenize(a);
16
+ const tb = tokenize(b);
17
+ if (ta.size === 0 || tb.size === 0)
18
+ return 0;
19
+ let overlap = 0;
20
+ for (const w of ta) {
21
+ if (tb.has(w))
22
+ overlap++;
23
+ }
24
+ return overlap / Math.max(ta.size, tb.size);
25
+ }
26
+ // ─── Analysis ───────────────────────────────────────────────────────────────
27
+ function findRelated(verdict, targetRule) {
28
+ const target = verdict.findings.find((f) => f.ruleId === targetRule);
29
+ if (!target)
30
+ return [];
31
+ const targetPrefix = targetRule.replace(/-\d+$/, "");
32
+ const judges = defaultRegistry.getJudges();
33
+ const targetJudge = judges.find((j) => targetRule.startsWith(j.rulePrefix));
34
+ const results = [];
35
+ const seen = new Set();
36
+ for (const f of verdict.findings) {
37
+ if (f.ruleId === targetRule || seen.has(f.ruleId))
38
+ continue;
39
+ seen.add(f.ruleId);
40
+ const prefix = f.ruleId.replace(/-\d+$/, "");
41
+ const fJudge = judges.find((j) => f.ruleId.startsWith(j.rulePrefix));
42
+ // same judge
43
+ if (targetJudge !== undefined && fJudge !== undefined && targetJudge.id === fJudge.id) {
44
+ results.push({
45
+ ruleId: f.ruleId,
46
+ title: f.title,
47
+ severity: (f.severity || "medium").toLowerCase(),
48
+ relatedness: "same-judge",
49
+ score: 0.8,
50
+ });
51
+ continue;
52
+ }
53
+ // same prefix
54
+ if (prefix === targetPrefix) {
55
+ results.push({
56
+ ruleId: f.ruleId,
57
+ title: f.title,
58
+ severity: (f.severity || "medium").toLowerCase(),
59
+ relatedness: "same-judge",
60
+ score: 0.9,
61
+ });
62
+ continue;
63
+ }
64
+ // title similarity
65
+ const sim = titleSimilarity(target.title, f.title);
66
+ if (sim >= 0.3) {
67
+ results.push({
68
+ ruleId: f.ruleId,
69
+ title: f.title,
70
+ severity: (f.severity || "medium").toLowerCase(),
71
+ relatedness: "similar-title",
72
+ score: sim,
73
+ });
74
+ continue;
75
+ }
76
+ // same severity as co-occurring
77
+ if ((f.severity || "medium").toLowerCase() === (target.severity || "medium").toLowerCase()) {
78
+ results.push({
79
+ ruleId: f.ruleId,
80
+ title: f.title,
81
+ severity: (f.severity || "medium").toLowerCase(),
82
+ relatedness: "co-occurring",
83
+ score: 0.3,
84
+ });
85
+ }
86
+ }
87
+ results.sort((a, b) => b.score - a.score);
88
+ return results;
89
+ }
90
+ // ─── CLI ────────────────────────────────────────────────────────────────────
91
+ export function runFindingRelatedRules(argv) {
92
+ const fileIdx = argv.indexOf("--file");
93
+ const ruleIdx = argv.indexOf("--rule");
94
+ const formatIdx = argv.indexOf("--format");
95
+ const limitIdx = argv.indexOf("--limit");
96
+ const filePath = fileIdx >= 0 ? argv[fileIdx + 1] : undefined;
97
+ const ruleId = ruleIdx >= 0 ? argv[ruleIdx + 1] : undefined;
98
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "table";
99
+ const limit = limitIdx >= 0 ? parseInt(argv[limitIdx + 1], 10) : 20;
100
+ if (argv.includes("--help") || argv.includes("-h")) {
101
+ console.log(`
102
+ judges finding-related-rules — Find related rules
103
+
104
+ Usage:
105
+ judges finding-related-rules --file <verdict.json> --rule <RULE-ID>
106
+ [--format table|json] [--limit <n>]
107
+
108
+ Options:
109
+ --file <path> Path to verdict JSON file (required)
110
+ --rule <id> Target rule ID (required)
111
+ --format <fmt> Output format: table (default), json
112
+ --limit <n> Max results (default: 20)
113
+ --help, -h Show this help
114
+ `);
115
+ return;
116
+ }
117
+ if (!filePath || !ruleId) {
118
+ console.error("Error: --file and --rule required");
119
+ process.exitCode = 1;
120
+ return;
121
+ }
122
+ if (!existsSync(filePath)) {
123
+ console.error(`Error: not found: ${filePath}`);
124
+ process.exitCode = 1;
125
+ return;
126
+ }
127
+ let verdict;
128
+ try {
129
+ verdict = JSON.parse(readFileSync(filePath, "utf-8"));
130
+ }
131
+ catch {
132
+ console.error("Error: invalid JSON");
133
+ process.exitCode = 1;
134
+ return;
135
+ }
136
+ const results = findRelated(verdict, ruleId).slice(0, limit);
137
+ if (format === "json") {
138
+ console.log(JSON.stringify(results, null, 2));
139
+ return;
140
+ }
141
+ console.log(`\nRelated Rules for ${ruleId} (${results.length} found)`);
142
+ console.log("═".repeat(75));
143
+ console.log(`${"Rule".padEnd(20)} ${"Relatedness".padEnd(16)} ${"Score".padEnd(8)} ${"Severity".padEnd(10)} Title`);
144
+ console.log("─".repeat(75));
145
+ for (const r of results) {
146
+ const rule = r.ruleId.length > 18 ? r.ruleId.slice(0, 18) + "…" : r.ruleId;
147
+ const title = r.title.length > 25 ? r.title.slice(0, 25) + "…" : r.title;
148
+ console.log(`${rule.padEnd(20)} ${r.relatedness.padEnd(16)} ${r.score.toFixed(2).padEnd(8)} ${r.severity.padEnd(10)} ${title}`);
149
+ }
150
+ console.log("═".repeat(75));
151
+ }
152
+ //# sourceMappingURL=finding-related-rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-related-rules.js","sourceRoot":"","sources":["../../src/commands/finding-related-rules.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Finding-rule-explain — Explain rules in detail with examples and remediation.
3
+ */
4
+ export declare function runFindingRuleExplain(argv: string[]): void;
5
+ //# sourceMappingURL=finding-rule-explain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-rule-explain.d.ts","sourceRoot":"","sources":["../../src/commands/finding-rule-explain.ts"],"names":[],"mappings":"AAAA;;GAEG;AA+EH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA8F1D"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Finding-rule-explain — Explain rules in detail with examples and remediation.
3
+ */
4
+ import { readFileSync, existsSync } from "fs";
5
+ import { defaultRegistry } from "../judge-registry.js";
6
+ // ─── Analysis ───────────────────────────────────────────────────────────────
7
+ function explainRules(verdict, targetRule) {
8
+ const judges = defaultRegistry.getJudges();
9
+ const explanations = [];
10
+ const ruleMap = new Map();
11
+ for (const f of verdict.findings) {
12
+ if (targetRule !== undefined && f.ruleId !== targetRule)
13
+ continue;
14
+ const existing = ruleMap.get(f.ruleId);
15
+ if (existing) {
16
+ existing.occurrences++;
17
+ const lines = f.lineNumbers || [];
18
+ for (const ln of lines) {
19
+ if (!existing.affectedLines.includes(ln)) {
20
+ existing.affectedLines.push(ln);
21
+ }
22
+ }
23
+ continue;
24
+ }
25
+ // find the judge for this rule
26
+ let judgeName = "unknown";
27
+ let domain = "unknown";
28
+ for (const j of judges) {
29
+ if (f.ruleId.startsWith(j.rulePrefix)) {
30
+ judgeName = j.name;
31
+ domain = j.domain;
32
+ break;
33
+ }
34
+ }
35
+ const explanation = {
36
+ ruleId: f.ruleId,
37
+ title: f.title,
38
+ severity: (f.severity || "medium").toLowerCase(),
39
+ judge: judgeName,
40
+ domain,
41
+ description: f.description,
42
+ recommendation: f.recommendation,
43
+ occurrences: 1,
44
+ affectedLines: [...(f.lineNumbers || [])],
45
+ };
46
+ ruleMap.set(f.ruleId, explanation);
47
+ explanations.push(explanation);
48
+ }
49
+ explanations.sort((a, b) => {
50
+ const sevOrder = { critical: 0, high: 1, medium: 2, low: 3, info: 4 };
51
+ return (sevOrder[a.severity] || 3) - (sevOrder[b.severity] || 3);
52
+ });
53
+ return explanations;
54
+ }
55
+ // ─── CLI ────────────────────────────────────────────────────────────────────
56
+ export function runFindingRuleExplain(argv) {
57
+ const fileIdx = argv.indexOf("--file");
58
+ const ruleIdx = argv.indexOf("--rule");
59
+ const formatIdx = argv.indexOf("--format");
60
+ const filePath = fileIdx >= 0 ? argv[fileIdx + 1] : undefined;
61
+ const targetRule = ruleIdx >= 0 ? argv[ruleIdx + 1] : undefined;
62
+ const format = formatIdx >= 0 ? argv[formatIdx + 1] : "detail";
63
+ if (argv.includes("--help") || argv.includes("-h")) {
64
+ console.log(`
65
+ judges finding-rule-explain — Explain rules in detail
66
+
67
+ Usage:
68
+ judges finding-rule-explain --file <verdict.json> [--rule <RULE-ID>]
69
+ [--format detail|table|json]
70
+
71
+ Options:
72
+ --file <path> Path to verdict JSON file (required)
73
+ --rule <id> Explain a specific rule ID
74
+ --format <fmt> Output format: detail (default), table, json
75
+ --help, -h Show this help
76
+ `);
77
+ return;
78
+ }
79
+ if (!filePath) {
80
+ console.error("Error: --file required");
81
+ process.exitCode = 1;
82
+ return;
83
+ }
84
+ if (!existsSync(filePath)) {
85
+ console.error(`Error: not found: ${filePath}`);
86
+ process.exitCode = 1;
87
+ return;
88
+ }
89
+ let verdict;
90
+ try {
91
+ verdict = JSON.parse(readFileSync(filePath, "utf-8"));
92
+ }
93
+ catch {
94
+ console.error("Error: invalid JSON");
95
+ process.exitCode = 1;
96
+ return;
97
+ }
98
+ const explanations = explainRules(verdict, targetRule);
99
+ if (explanations.length === 0) {
100
+ console.log(targetRule ? `No findings for rule: ${targetRule}` : "No findings to explain");
101
+ return;
102
+ }
103
+ if (format === "json") {
104
+ console.log(JSON.stringify(explanations, null, 2));
105
+ return;
106
+ }
107
+ if (format === "table") {
108
+ console.log(`\nRule Explanations (${explanations.length} rules)`);
109
+ console.log("═".repeat(80));
110
+ console.log(`${"Rule".padEnd(18)} ${"Severity".padEnd(10)} ${"Judge".padEnd(22)} ${"Occurs".padEnd(8)} Title`);
111
+ console.log("─".repeat(80));
112
+ for (const e of explanations) {
113
+ const rule = e.ruleId.length > 16 ? e.ruleId.slice(0, 16) + "…" : e.ruleId;
114
+ const judge = e.judge.length > 20 ? e.judge.slice(0, 20) + "…" : e.judge;
115
+ const title = e.title.length > 25 ? e.title.slice(0, 25) + "…" : e.title;
116
+ console.log(`${rule.padEnd(18)} ${e.severity.padEnd(10)} ${judge.padEnd(22)} ${String(e.occurrences).padEnd(8)} ${title}`);
117
+ }
118
+ console.log("═".repeat(80));
119
+ return;
120
+ }
121
+ // detail format
122
+ for (const e of explanations) {
123
+ console.log(`\n${"═".repeat(70)}`);
124
+ console.log(` Rule: ${e.ruleId}`);
125
+ console.log(` Title: ${e.title}`);
126
+ console.log(` Severity: ${e.severity.toUpperCase()}`);
127
+ console.log(` Judge: ${e.judge}`);
128
+ console.log(` Domain: ${e.domain}`);
129
+ console.log(` Occurrences: ${e.occurrences}`);
130
+ if (e.affectedLines.length > 0) {
131
+ console.log(` Lines: ${e.affectedLines.join(", ")}`);
132
+ }
133
+ console.log(`${"─".repeat(70)}`);
134
+ console.log(` Description:`);
135
+ console.log(` ${e.description}`);
136
+ console.log(` Recommendation:`);
137
+ console.log(` ${e.recommendation}`);
138
+ }
139
+ console.log(`\n${"═".repeat(70)}`);
140
+ }
141
+ //# sourceMappingURL=finding-rule-explain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-rule-explain.js","sourceRoot":"","sources":["../../src/commands/finding-rule-explain.ts"],"names":[],"mappings":"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"}