@kevinrabun/judges 3.109.0 → 3.111.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-priority.d.ts +2 -0
  6. package/dist/commands/finding-auto-priority.d.ts.map +1 -0
  7. package/dist/commands/finding-auto-priority.js +101 -0
  8. package/dist/commands/finding-auto-priority.js.map +1 -0
  9. package/dist/commands/finding-cluster-summary.d.ts +2 -0
  10. package/dist/commands/finding-cluster-summary.d.ts.map +1 -0
  11. package/dist/commands/finding-cluster-summary.js +86 -0
  12. package/dist/commands/finding-cluster-summary.js.map +1 -0
  13. package/dist/commands/finding-context-link.d.ts +2 -0
  14. package/dist/commands/finding-context-link.d.ts.map +1 -0
  15. package/dist/commands/finding-context-link.js +95 -0
  16. package/dist/commands/finding-context-link.js.map +1 -0
  17. package/dist/commands/finding-dependency-impact.d.ts +2 -0
  18. package/dist/commands/finding-dependency-impact.d.ts.map +1 -0
  19. package/dist/commands/finding-dependency-impact.js +98 -0
  20. package/dist/commands/finding-dependency-impact.js.map +1 -0
  21. package/dist/commands/finding-effort-rank.d.ts +2 -0
  22. package/dist/commands/finding-effort-rank.d.ts.map +1 -0
  23. package/dist/commands/finding-effort-rank.js +94 -0
  24. package/dist/commands/finding-effort-rank.js.map +1 -0
  25. package/dist/commands/finding-fix-chain.d.ts +2 -0
  26. package/dist/commands/finding-fix-chain.d.ts.map +1 -0
  27. package/dist/commands/finding-fix-chain.js +79 -0
  28. package/dist/commands/finding-fix-chain.js.map +1 -0
  29. package/dist/commands/finding-owner-notify.d.ts +2 -0
  30. package/dist/commands/finding-owner-notify.d.ts.map +1 -0
  31. package/dist/commands/finding-owner-notify.js +122 -0
  32. package/dist/commands/finding-owner-notify.js.map +1 -0
  33. package/dist/commands/finding-patch-chain.d.ts +2 -0
  34. package/dist/commands/finding-patch-chain.d.ts.map +1 -0
  35. package/dist/commands/finding-patch-chain.js +91 -0
  36. package/dist/commands/finding-patch-chain.js.map +1 -0
  37. package/dist/commands/finding-resolution-workflow.d.ts +2 -0
  38. package/dist/commands/finding-resolution-workflow.d.ts.map +1 -0
  39. package/dist/commands/finding-resolution-workflow.js +92 -0
  40. package/dist/commands/finding-resolution-workflow.js.map +1 -0
  41. package/dist/commands/finding-risk-label.d.ts +2 -0
  42. package/dist/commands/finding-risk-label.d.ts.map +1 -0
  43. package/dist/commands/finding-risk-label.js +73 -0
  44. package/dist/commands/finding-risk-label.js.map +1 -0
  45. package/dist/commands/review-config-health.d.ts +2 -0
  46. package/dist/commands/review-config-health.d.ts.map +1 -0
  47. package/dist/commands/review-config-health.js +173 -0
  48. package/dist/commands/review-config-health.js.map +1 -0
  49. package/dist/commands/review-engagement-score.d.ts +2 -0
  50. package/dist/commands/review-engagement-score.d.ts.map +1 -0
  51. package/dist/commands/review-engagement-score.js +112 -0
  52. package/dist/commands/review-engagement-score.js.map +1 -0
  53. package/dist/commands/review-feedback-summary.d.ts +2 -0
  54. package/dist/commands/review-feedback-summary.d.ts.map +1 -0
  55. package/dist/commands/review-feedback-summary.js +131 -0
  56. package/dist/commands/review-feedback-summary.js.map +1 -0
  57. package/dist/commands/review-mentor-suggest.d.ts +2 -0
  58. package/dist/commands/review-mentor-suggest.d.ts.map +1 -0
  59. package/dist/commands/review-mentor-suggest.js +113 -0
  60. package/dist/commands/review-mentor-suggest.js.map +1 -0
  61. package/dist/commands/review-progress-report.d.ts +2 -0
  62. package/dist/commands/review-progress-report.d.ts.map +1 -0
  63. package/dist/commands/review-progress-report.js +96 -0
  64. package/dist/commands/review-progress-report.js.map +1 -0
  65. package/dist/commands/review-quality-baseline.d.ts +2 -0
  66. package/dist/commands/review-quality-baseline.d.ts.map +1 -0
  67. package/dist/commands/review-quality-baseline.js +135 -0
  68. package/dist/commands/review-quality-baseline.js.map +1 -0
  69. package/dist/commands/review-retrospective.d.ts +2 -0
  70. package/dist/commands/review-retrospective.d.ts.map +1 -0
  71. package/dist/commands/review-retrospective.js +119 -0
  72. package/dist/commands/review-retrospective.js.map +1 -0
  73. package/dist/commands/review-team-velocity.d.ts +2 -0
  74. package/dist/commands/review-team-velocity.d.ts.map +1 -0
  75. package/dist/commands/review-team-velocity.js +104 -0
  76. package/dist/commands/review-team-velocity.js.map +1 -0
  77. package/package.json +1 -1
  78. package/server.json +2 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-fix-chain.js","sourceRoot":"","sources":["../../src/commands/finding-fix-chain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function runFindingOwnerNotify(argv: string[]): void;
2
+ //# sourceMappingURL=finding-owner-notify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-owner-notify.d.ts","sourceRoot":"","sources":["../../src/commands/finding-owner-notify.ts"],"names":[],"mappings":"AAgGA,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAyD1D"}
@@ -0,0 +1,122 @@
1
+ import { readFileSync, existsSync } from "fs";
2
+ import { join } from "path";
3
+ function loadOwnerMappings(mappingPath) {
4
+ if (!existsSync(mappingPath))
5
+ return [];
6
+ try {
7
+ const content = readFileSync(mappingPath, "utf-8");
8
+ // Support simple JSON format: [{ "pattern": "auth", "owners": ["@alice"] }]
9
+ return JSON.parse(content);
10
+ }
11
+ catch {
12
+ // Try CODEOWNERS-like format: pattern @owner1 @owner2
13
+ const lines = readFileSync(mappingPath, "utf-8").split("\n");
14
+ const mappings = [];
15
+ for (const line of lines) {
16
+ const trimmed = line.trim();
17
+ if (!trimmed || trimmed.startsWith("#"))
18
+ continue;
19
+ const parts = trimmed.split(/\s+/);
20
+ if (parts.length >= 2) {
21
+ mappings.push({ pattern: parts[0], owners: parts.slice(1) });
22
+ }
23
+ }
24
+ return mappings;
25
+ }
26
+ }
27
+ const SEVERITY_RANK = { critical: 5, high: 4, medium: 3, low: 2, info: 1 };
28
+ function rankToSev(rank) {
29
+ if (rank >= 5)
30
+ return "critical";
31
+ if (rank >= 4)
32
+ return "high";
33
+ if (rank >= 3)
34
+ return "medium";
35
+ if (rank >= 2)
36
+ return "low";
37
+ return "info";
38
+ }
39
+ function buildNotifications(verdict, mappings) {
40
+ const ownerMap = new Map();
41
+ for (const f of verdict.findings ?? []) {
42
+ const ruleIdLower = f.ruleId.toLowerCase();
43
+ const titleLower = f.title.toLowerCase();
44
+ let matched = false;
45
+ for (const mapping of mappings) {
46
+ if (ruleIdLower.includes(mapping.pattern.toLowerCase()) || titleLower.includes(mapping.pattern.toLowerCase())) {
47
+ for (const owner of mapping.owners) {
48
+ const entry = ownerMap.get(owner) ?? { findings: [], maxRank: 0 };
49
+ entry.findings.push({ ruleId: f.ruleId, title: f.title, severity: f.severity });
50
+ entry.maxRank = Math.max(entry.maxRank, SEVERITY_RANK[f.severity] ?? 0);
51
+ ownerMap.set(owner, entry);
52
+ }
53
+ matched = true;
54
+ break;
55
+ }
56
+ }
57
+ if (!matched) {
58
+ const entry = ownerMap.get("unassigned") ?? { findings: [], maxRank: 0 };
59
+ entry.findings.push({ ruleId: f.ruleId, title: f.title, severity: f.severity });
60
+ entry.maxRank = Math.max(entry.maxRank, SEVERITY_RANK[f.severity] ?? 0);
61
+ ownerMap.set("unassigned", entry);
62
+ }
63
+ }
64
+ const results = [];
65
+ for (const [owner, data] of ownerMap) {
66
+ results.push({
67
+ owner,
68
+ findings: data.findings,
69
+ highestSeverity: rankToSev(data.maxRank),
70
+ });
71
+ }
72
+ results.sort((a, b) => (SEVERITY_RANK[b.highestSeverity] ?? 0) - (SEVERITY_RANK[a.highestSeverity] ?? 0));
73
+ return results;
74
+ }
75
+ export function runFindingOwnerNotify(argv) {
76
+ if (argv.includes("--help") || argv.includes("-h")) {
77
+ console.log(`Usage: judges finding-owner-notify [options]
78
+
79
+ Generate ownership-based notification lists for findings.
80
+
81
+ Options:
82
+ --report <path> Path to verdict JSON
83
+ --owners <path> Path to owner mapping file (JSON or CODEOWNERS format)
84
+ --format <fmt> Output format: table (default) or json
85
+ -h, --help Show this help message`);
86
+ return;
87
+ }
88
+ const formatIdx = argv.indexOf("--format");
89
+ const format = formatIdx !== -1 && argv[formatIdx + 1] ? argv[formatIdx + 1] : "table";
90
+ const reportIdx = argv.indexOf("--report");
91
+ const reportPath = reportIdx !== -1 && argv[reportIdx + 1]
92
+ ? join(process.cwd(), argv[reportIdx + 1])
93
+ : join(process.cwd(), ".judges", "last-verdict.json");
94
+ const ownersIdx = argv.indexOf("--owners");
95
+ const ownersPath = ownersIdx !== -1 && argv[ownersIdx + 1]
96
+ ? join(process.cwd(), argv[ownersIdx + 1])
97
+ : join(process.cwd(), ".judges", "owners.json");
98
+ if (!existsSync(reportPath)) {
99
+ console.log(`No report found at: ${reportPath}`);
100
+ return;
101
+ }
102
+ const data = JSON.parse(readFileSync(reportPath, "utf-8"));
103
+ const mappings = loadOwnerMappings(ownersPath);
104
+ const notifications = buildNotifications(data, mappings);
105
+ if (format === "json") {
106
+ console.log(JSON.stringify(notifications, null, 2));
107
+ return;
108
+ }
109
+ console.log(`\n=== Owner Notifications (${notifications.length} owners) ===\n`);
110
+ if (notifications.length === 0) {
111
+ console.log("No findings to notify about.");
112
+ return;
113
+ }
114
+ for (const n of notifications) {
115
+ console.log(` ${n.owner} (${n.findings.length} findings, highest: ${n.highestSeverity})`);
116
+ for (const f of n.findings) {
117
+ console.log(` [${f.severity.toUpperCase()}] ${f.ruleId}: ${f.title}`);
118
+ }
119
+ console.log();
120
+ }
121
+ }
122
+ //# sourceMappingURL=finding-owner-notify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-owner-notify.js","sourceRoot":"","sources":["../../src/commands/finding-owner-notify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAoB5B,SAAS,iBAAiB,CAAC,WAAmB;IAC5C,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,EAAE,CAAC;IAExC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACnD,4EAA4E;QAC5E,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAmB,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,sDAAsD;QACtD,MAAM,KAAK,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7D,MAAM,QAAQ,GAAmB,EAAE,CAAC;QACpC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;gBAAE,SAAS;YAClD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACnC,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;gBACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC;AAED,MAAM,aAAa,GAA2B,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AAEnG,SAAS,SAAS,CAAC,IAAY;IAC7B,IAAI,IAAI,IAAI,CAAC;QAAE,OAAO,UAAU,CAAC;IACjC,IAAI,IAAI,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC;IAC7B,IAAI,IAAI,IAAI,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC/B,IAAI,IAAI,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5B,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAwB,EAAE,QAAwB;IAC5E,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAwE,CAAC;IAEjG,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;QACvC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QAC3C,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QACzC,IAAI,OAAO,GAAG,KAAK,CAAC;QAEpB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;gBAC9G,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;oBACnC,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;oBAClE,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;oBAChF,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;oBACxE,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;gBAC7B,CAAC;gBACD,OAAO,GAAG,IAAI,CAAC;gBACf,MAAM;YACR,CAAC;QACH,CAAC;QAED,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;YACzE,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YAChF,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;YACxE,QAAQ,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAwB,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,QAAQ,EAAE,CAAC;QACrC,OAAO,CAAC,IAAI,CAAC;YACX,KAAK;YACL,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,eAAe,EAAE,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC;SACzC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1G,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,IAAc;IAClD,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC;;;;;;;;8CAQ8B,CAAC,CAAC;QAC5C,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,SAAS,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAEvF,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,UAAU,GACd,SAAS,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QACrC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;QAC1C,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,mBAAmB,CAAC,CAAC;IAE1D,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,UAAU,GACd,SAAS,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QACrC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;QAC1C,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;IAEpD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,uBAAuB,UAAU,EAAE,CAAC,CAAC;QACjD,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAoB,CAAC;IAC9E,MAAM,QAAQ,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAC;IAC/C,MAAM,aAAa,GAAG,kBAAkB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAEzD,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACpD,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,8BAA8B,aAAa,CAAC,MAAM,gBAAgB,CAAC,CAAC;IAEhF,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;QAC5C,OAAO;IACT,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,aAAa,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,uBAAuB,CAAC,CAAC,eAAe,GAAG,CAAC,CAAC;QAC3F,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QAC3E,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function runFindingPatchChain(argv: string[]): void;
2
+ //# sourceMappingURL=finding-patch-chain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-patch-chain.d.ts","sourceRoot":"","sources":["../../src/commands/finding-patch-chain.ts"],"names":[],"mappings":"AA2EA,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAsDzD"}
@@ -0,0 +1,91 @@
1
+ import { readFileSync, existsSync } from "fs";
2
+ import { join } from "path";
3
+ function buildPatchChains(verdict) {
4
+ const findings = verdict.findings ?? [];
5
+ const withPatches = [];
6
+ const withoutPatches = [];
7
+ for (const f of findings) {
8
+ const entry = {
9
+ ruleId: f.ruleId,
10
+ title: f.title,
11
+ severity: f.severity,
12
+ hasPatch: f.patch !== undefined && f.patch !== null,
13
+ patchPreview: f.patch !== undefined && f.patch !== null ? String(f.patch).slice(0, 80) : "",
14
+ lineNumbers: f.lineNumbers ?? [],
15
+ };
16
+ if (entry.hasPatch)
17
+ withPatches.push(entry);
18
+ else
19
+ withoutPatches.push(entry);
20
+ }
21
+ // Sort patches by line number (earliest first) for safe application order
22
+ withPatches.sort((a, b) => {
23
+ const aFirst = a.lineNumbers.length > 0 ? a.lineNumbers[0] : Infinity;
24
+ const bFirst = b.lineNumbers.length > 0 ? b.lineNumbers[0] : Infinity;
25
+ return bFirst - aFirst; // Apply from bottom up to avoid line shifts
26
+ });
27
+ const groups = [];
28
+ if (withPatches.length > 0) {
29
+ groups.push({
30
+ groupId: 1,
31
+ label: "Patchable findings (apply bottom-up)",
32
+ entries: withPatches,
33
+ applyOrder: "Apply from highest line number to lowest to avoid line shifts",
34
+ });
35
+ }
36
+ if (withoutPatches.length > 0) {
37
+ groups.push({
38
+ groupId: groups.length + 1,
39
+ label: "Manual fixes required",
40
+ entries: withoutPatches,
41
+ applyOrder: "Fix in any order — no auto-patches available",
42
+ });
43
+ }
44
+ return groups;
45
+ }
46
+ export function runFindingPatchChain(argv) {
47
+ if (argv.includes("--help") || argv.includes("-h")) {
48
+ console.log(`Usage: judges finding-patch-chain [options]
49
+
50
+ Link and order patches across findings for safe application.
51
+
52
+ Options:
53
+ --report <path> Path to verdict JSON
54
+ --format <fmt> Output format: table (default) or json
55
+ -h, --help Show this help message`);
56
+ return;
57
+ }
58
+ const formatIdx = argv.indexOf("--format");
59
+ const format = formatIdx !== -1 && argv[formatIdx + 1] ? argv[formatIdx + 1] : "table";
60
+ const reportIdx = argv.indexOf("--report");
61
+ const reportPath = reportIdx !== -1 && argv[reportIdx + 1]
62
+ ? join(process.cwd(), argv[reportIdx + 1])
63
+ : join(process.cwd(), ".judges", "last-verdict.json");
64
+ if (!existsSync(reportPath)) {
65
+ console.log(`No report found at: ${reportPath}`);
66
+ return;
67
+ }
68
+ const data = JSON.parse(readFileSync(reportPath, "utf-8"));
69
+ const groups = buildPatchChains(data);
70
+ if (format === "json") {
71
+ console.log(JSON.stringify(groups, null, 2));
72
+ return;
73
+ }
74
+ const totalPatched = groups.filter((g) => g.label.includes("Patchable")).reduce((s, g) => s + g.entries.length, 0);
75
+ const totalManual = groups.filter((g) => g.label.includes("Manual")).reduce((s, g) => s + g.entries.length, 0);
76
+ console.log(`\n=== Patch Chain (${totalPatched} patchable, ${totalManual} manual) ===\n`);
77
+ for (const group of groups) {
78
+ console.log(` Group #${group.groupId}: ${group.label}`);
79
+ console.log(` Order: ${group.applyOrder}\n`);
80
+ for (const e of group.entries) {
81
+ const lines = e.lineNumbers.length > 0 ? ` (L${e.lineNumbers.join(",")})` : "";
82
+ console.log(` [${e.severity.toUpperCase()}] ${e.ruleId}${lines}`);
83
+ console.log(` ${e.title}`);
84
+ if (e.patchPreview) {
85
+ console.log(` Patch: ${e.patchPreview}...`);
86
+ }
87
+ }
88
+ console.log();
89
+ }
90
+ }
91
+ //# sourceMappingURL=finding-patch-chain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-patch-chain.js","sourceRoot":"","sources":["../../src/commands/finding-patch-chain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function runFindingResolutionWorkflow(argv: string[]): void;
2
+ //# sourceMappingURL=finding-resolution-workflow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-resolution-workflow.d.ts","sourceRoot":"","sources":["../../src/commands/finding-resolution-workflow.ts"],"names":[],"mappings":"AA+EA,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA6CjE"}
@@ -0,0 +1,92 @@
1
+ import { readFileSync, existsSync } from "fs";
2
+ import { join } from "path";
3
+ const WORKFLOWS = {
4
+ critical: [
5
+ { step: 1, action: "Acknowledge finding and assign owner", required: true },
6
+ { step: 2, action: "Create incident ticket", required: true },
7
+ { step: 3, action: "Analyze root cause", required: true },
8
+ { step: 4, action: "Implement fix", required: true },
9
+ { step: 5, action: "Peer review the fix", required: true },
10
+ { step: 6, action: "Run regression tests", required: true },
11
+ { step: 7, action: "Deploy hotfix", required: true },
12
+ { step: 8, action: "Post-mortem review", required: false },
13
+ ],
14
+ high: [
15
+ { step: 1, action: "Assign to sprint backlog", required: true },
16
+ { step: 2, action: "Analyze root cause", required: true },
17
+ { step: 3, action: "Implement fix", required: true },
18
+ { step: 4, action: "Code review", required: true },
19
+ { step: 5, action: "Run tests", required: true },
20
+ { step: 6, action: "Deploy in next release", required: true },
21
+ ],
22
+ medium: [
23
+ { step: 1, action: "Add to backlog", required: true },
24
+ { step: 2, action: "Fix during regular development", required: true },
25
+ { step: 3, action: "Verify fix", required: true },
26
+ { step: 4, action: "Update documentation if needed", required: false },
27
+ ],
28
+ low: [
29
+ { step: 1, action: "Log for future cleanup", required: true },
30
+ { step: 2, action: "Fix during refactoring", required: false },
31
+ { step: 3, action: "Verify after fix", required: false },
32
+ ],
33
+ info: [
34
+ { step: 1, action: "Review and acknowledge", required: true },
35
+ { step: 2, action: "Address if convenient", required: false },
36
+ ],
37
+ };
38
+ function generateWorkflows(verdict) {
39
+ const results = [];
40
+ for (const f of verdict.findings ?? []) {
41
+ const steps = WORKFLOWS[f.severity] ?? WORKFLOWS["medium"];
42
+ results.push({
43
+ ruleId: f.ruleId,
44
+ title: f.title,
45
+ severity: f.severity,
46
+ workflow: `${f.severity}-resolution`,
47
+ steps,
48
+ });
49
+ }
50
+ const severityOrder = { critical: 5, high: 4, medium: 3, low: 2, info: 1 };
51
+ results.sort((a, b) => (severityOrder[b.severity] ?? 0) - (severityOrder[a.severity] ?? 0));
52
+ return results;
53
+ }
54
+ export function runFindingResolutionWorkflow(argv) {
55
+ if (argv.includes("--help") || argv.includes("-h")) {
56
+ console.log(`Usage: judges finding-resolution-workflow [options]
57
+
58
+ Generate resolution workflows for findings.
59
+
60
+ Options:
61
+ --report <path> Path to verdict JSON
62
+ --format <fmt> Output format: table (default) or json
63
+ -h, --help Show this help message`);
64
+ return;
65
+ }
66
+ const formatIdx = argv.indexOf("--format");
67
+ const format = formatIdx !== -1 && argv[formatIdx + 1] ? argv[formatIdx + 1] : "table";
68
+ const reportIdx = argv.indexOf("--report");
69
+ const reportPath = reportIdx !== -1 && argv[reportIdx + 1]
70
+ ? join(process.cwd(), argv[reportIdx + 1])
71
+ : join(process.cwd(), ".judges", "last-verdict.json");
72
+ if (!existsSync(reportPath)) {
73
+ console.log(`No report found at: ${reportPath}`);
74
+ return;
75
+ }
76
+ const data = JSON.parse(readFileSync(reportPath, "utf-8"));
77
+ const workflows = generateWorkflows(data);
78
+ if (format === "json") {
79
+ console.log(JSON.stringify(workflows, null, 2));
80
+ return;
81
+ }
82
+ console.log(`\n=== Resolution Workflows (${workflows.length} findings) ===\n`);
83
+ for (const wf of workflows) {
84
+ console.log(` [${wf.severity.toUpperCase()}] ${wf.ruleId}: ${wf.title}`);
85
+ for (const s of wf.steps) {
86
+ const req = s.required ? "*" : " ";
87
+ console.log(` ${req} ${s.step}. ${s.action}`);
88
+ }
89
+ console.log();
90
+ }
91
+ }
92
+ //# sourceMappingURL=finding-resolution-workflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-resolution-workflow.js","sourceRoot":"","sources":["../../src/commands/finding-resolution-workflow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function runFindingRiskLabel(argv: string[]): void;
2
+ //# sourceMappingURL=finding-risk-label.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-risk-label.d.ts","sourceRoot":"","sources":["../../src/commands/finding-risk-label.ts"],"names":[],"mappings":"AAuDA,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAiDxD"}
@@ -0,0 +1,73 @@
1
+ import { readFileSync, existsSync } from "fs";
2
+ import { join } from "path";
3
+ const RISK_PATTERNS = {
4
+ exploitable: ["injection", "xss", "rce", "deserialization", "ssrf", "command"],
5
+ "data-loss": ["leak", "exposure", "pii", "secret", "credential", "token"],
6
+ compliance: ["audit", "log", "gdpr", "hipaa", "pci", "compliance", "license"],
7
+ operational: ["perf", "memory", "timeout", "resource", "deadlock", "crash"],
8
+ reputational: ["quality", "smell", "complexity", "dead-code", "duplicate"],
9
+ };
10
+ function labelFindings(verdict) {
11
+ const results = [];
12
+ for (const f of verdict.findings ?? []) {
13
+ const combined = (f.ruleId + " " + f.title).toLowerCase();
14
+ const labels = [];
15
+ for (const [category, patterns] of Object.entries(RISK_PATTERNS)) {
16
+ for (const pattern of patterns) {
17
+ if (combined.includes(pattern)) {
18
+ labels.push(category);
19
+ break;
20
+ }
21
+ }
22
+ }
23
+ // High/critical severity without specific match gets "operational"
24
+ if (labels.length === 0 && (f.severity === "critical" || f.severity === "high")) {
25
+ labels.push("operational");
26
+ }
27
+ results.push({ ruleId: f.ruleId, title: f.title, severity: f.severity, riskLabels: labels });
28
+ }
29
+ results.sort((a, b) => b.riskLabels.length - a.riskLabels.length);
30
+ return results;
31
+ }
32
+ export function runFindingRiskLabel(argv) {
33
+ if (argv.includes("--help") || argv.includes("-h")) {
34
+ console.log(`Usage: judges finding-risk-label [options]
35
+
36
+ Label findings with risk categories.
37
+
38
+ Options:
39
+ --report <path> Path to verdict JSON
40
+ --format <fmt> Output format: table (default) or json
41
+ -h, --help Show this help message`);
42
+ return;
43
+ }
44
+ const formatIdx = argv.indexOf("--format");
45
+ const format = formatIdx !== -1 && argv[formatIdx + 1] ? argv[formatIdx + 1] : "table";
46
+ const reportIdx = argv.indexOf("--report");
47
+ const reportPath = reportIdx !== -1 && argv[reportIdx + 1]
48
+ ? join(process.cwd(), argv[reportIdx + 1])
49
+ : join(process.cwd(), ".judges", "last-verdict.json");
50
+ if (!existsSync(reportPath)) {
51
+ console.log(`No report found at: ${reportPath}`);
52
+ return;
53
+ }
54
+ const data = JSON.parse(readFileSync(reportPath, "utf-8"));
55
+ const labeled = labelFindings(data);
56
+ if (format === "json") {
57
+ console.log(JSON.stringify(labeled, null, 2));
58
+ return;
59
+ }
60
+ const withLabels = labeled.filter((l) => l.riskLabels.length > 0);
61
+ console.log(`\n=== Risk Labels (${withLabels.length} labeled of ${labeled.length} findings) ===\n`);
62
+ if (withLabels.length === 0) {
63
+ console.log("No risk labels matched.");
64
+ return;
65
+ }
66
+ for (const entry of withLabels) {
67
+ console.log(` ${entry.severity.toUpperCase().padEnd(9)} ${entry.ruleId}`);
68
+ console.log(` ${entry.title}`);
69
+ console.log(` Labels: ${entry.riskLabels.join(", ")}`);
70
+ console.log();
71
+ }
72
+ }
73
+ //# sourceMappingURL=finding-risk-label.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-risk-label.js","sourceRoot":"","sources":["../../src/commands/finding-risk-label.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function runReviewConfigHealth(argv: string[]): void;
2
+ //# sourceMappingURL=review-config-health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-config-health.d.ts","sourceRoot":"","sources":["../../src/commands/review-config-health.ts"],"names":[],"mappings":"AA6JA,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAuC1D"}
@@ -0,0 +1,173 @@
1
+ import { readFileSync, existsSync } from "fs";
2
+ import { join } from "path";
3
+ function assessHealth(projectDir) {
4
+ const checks = [];
5
+ // Check for config file
6
+ const configPaths = [".judgesrc", ".judgesrc.json", "judges.config.json"];
7
+ const foundConfig = configPaths.find((p) => existsSync(join(projectDir, p)));
8
+ if (!foundConfig) {
9
+ checks.push({
10
+ check: "Config file",
11
+ status: "error",
12
+ detail: "No configuration file found",
13
+ suggestion: "Run `judges init` to create a configuration file",
14
+ });
15
+ }
16
+ else {
17
+ try {
18
+ const raw = readFileSync(join(projectDir, foundConfig), "utf-8");
19
+ const cfg = JSON.parse(raw);
20
+ checks.push({
21
+ check: "Config file",
22
+ status: "healthy",
23
+ detail: `Found ${foundConfig}`,
24
+ suggestion: "",
25
+ });
26
+ // Check preset
27
+ if (!cfg["preset"]) {
28
+ checks.push({
29
+ check: "Preset configured",
30
+ status: "warning",
31
+ detail: "No preset defined",
32
+ suggestion: "Add a preset like 'security', 'quality', or 'full' for optimized defaults",
33
+ });
34
+ }
35
+ else {
36
+ checks.push({
37
+ check: "Preset configured",
38
+ status: "healthy",
39
+ detail: `Preset: ${String(cfg["preset"])}`,
40
+ suggestion: "",
41
+ });
42
+ }
43
+ // Check minSeverity
44
+ if (!cfg["minSeverity"]) {
45
+ checks.push({
46
+ check: "Minimum severity",
47
+ status: "warning",
48
+ detail: "No minSeverity set — all severities reported",
49
+ suggestion: "Set minSeverity to 'low' or 'medium' to reduce noise",
50
+ });
51
+ }
52
+ else {
53
+ checks.push({
54
+ check: "Minimum severity",
55
+ status: "healthy",
56
+ detail: `minSeverity: ${String(cfg["minSeverity"])}`,
57
+ suggestion: "",
58
+ });
59
+ }
60
+ // Check disabled judges
61
+ const disabled = cfg["disabledJudges"];
62
+ if (Array.isArray(disabled) && disabled.length > 5) {
63
+ checks.push({
64
+ check: "Disabled judges",
65
+ status: "warning",
66
+ detail: `${disabled.length} judges disabled`,
67
+ suggestion: "Consider using a different preset instead of disabling many judges",
68
+ });
69
+ }
70
+ else {
71
+ checks.push({
72
+ check: "Disabled judges",
73
+ status: "healthy",
74
+ detail: Array.isArray(disabled) ? `${disabled.length} disabled` : "None disabled",
75
+ suggestion: "",
76
+ });
77
+ }
78
+ // Check rule overrides
79
+ const overrides = cfg["ruleOverrides"];
80
+ if (overrides && typeof overrides === "object") {
81
+ const count = Object.keys(overrides).length;
82
+ checks.push({
83
+ check: "Rule overrides",
84
+ status: count > 20 ? "warning" : "healthy",
85
+ detail: `${count} rule overrides`,
86
+ suggestion: count > 20 ? "Many overrides — consider adjusting preset instead" : "",
87
+ });
88
+ }
89
+ }
90
+ catch {
91
+ checks.push({
92
+ check: "Config parseable",
93
+ status: "error",
94
+ detail: `Config file ${foundConfig} has syntax errors`,
95
+ suggestion: "Fix JSON syntax in the config file",
96
+ });
97
+ }
98
+ }
99
+ // Check .judges directory
100
+ const judgesDir = join(projectDir, ".judges");
101
+ if (!existsSync(judgesDir)) {
102
+ checks.push({
103
+ check: "Judges directory",
104
+ status: "warning",
105
+ detail: "No .judges directory found",
106
+ suggestion: "Run a review to create the .judges directory with results",
107
+ });
108
+ }
109
+ else {
110
+ checks.push({
111
+ check: "Judges directory",
112
+ status: "healthy",
113
+ detail: ".judges directory exists",
114
+ suggestion: "",
115
+ });
116
+ }
117
+ // Check .gitignore includes .judges
118
+ const gitignorePath = join(projectDir, ".gitignore");
119
+ if (existsSync(gitignorePath)) {
120
+ const gitignore = readFileSync(gitignorePath, "utf-8");
121
+ if (!gitignore.includes(".judges")) {
122
+ checks.push({
123
+ check: "Gitignore",
124
+ status: "warning",
125
+ detail: ".judges not in .gitignore",
126
+ suggestion: "Add .judges/ to .gitignore to avoid committing review artifacts",
127
+ });
128
+ }
129
+ else {
130
+ checks.push({
131
+ check: "Gitignore",
132
+ status: "healthy",
133
+ detail: ".judges directory excluded from git",
134
+ suggestion: "",
135
+ });
136
+ }
137
+ }
138
+ return checks;
139
+ }
140
+ export function runReviewConfigHealth(argv) {
141
+ if (argv.includes("--help") || argv.includes("-h")) {
142
+ console.log(`Usage: judges review-config-health [options]
143
+
144
+ Assess configuration health and suggest improvements.
145
+
146
+ Options:
147
+ --dir <path> Project directory (default: current)
148
+ --format <fmt> Output format: table (default) or json
149
+ -h, --help Show this help message`);
150
+ return;
151
+ }
152
+ const formatIdx = argv.indexOf("--format");
153
+ const format = formatIdx !== -1 && argv[formatIdx + 1] ? argv[formatIdx + 1] : "table";
154
+ const dirIdx = argv.indexOf("--dir");
155
+ const projectDir = dirIdx !== -1 && argv[dirIdx + 1] ? join(process.cwd(), argv[dirIdx + 1]) : process.cwd();
156
+ const checks = assessHealth(projectDir);
157
+ if (format === "json") {
158
+ console.log(JSON.stringify(checks, null, 2));
159
+ return;
160
+ }
161
+ const errors = checks.filter((c) => c.status === "error").length;
162
+ const warnings = checks.filter((c) => c.status === "warning").length;
163
+ const healthy = checks.filter((c) => c.status === "healthy").length;
164
+ console.log(`\n=== Config Health (${healthy} healthy, ${warnings} warnings, ${errors} errors) ===\n`);
165
+ for (const c of checks) {
166
+ const icon = c.status === "healthy" ? "✓" : c.status === "warning" ? "!" : "✗";
167
+ console.log(` ${icon} ${c.check}: ${c.detail}`);
168
+ if (c.suggestion) {
169
+ console.log(` → ${c.suggestion}`);
170
+ }
171
+ }
172
+ }
173
+ //# sourceMappingURL=review-config-health.js.map