@kevinrabun/judges 3.62.0 → 3.64.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 (70) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +112 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/auto-approve.d.ts +5 -0
  6. package/dist/commands/auto-approve.d.ts.map +1 -0
  7. package/dist/commands/auto-approve.js +189 -0
  8. package/dist/commands/auto-approve.js.map +1 -0
  9. package/dist/commands/diff-explain.d.ts +5 -0
  10. package/dist/commands/diff-explain.d.ts.map +1 -0
  11. package/dist/commands/diff-explain.js +143 -0
  12. package/dist/commands/diff-explain.js.map +1 -0
  13. package/dist/commands/finding-group.d.ts +16 -0
  14. package/dist/commands/finding-group.d.ts.map +1 -0
  15. package/dist/commands/finding-group.js +165 -0
  16. package/dist/commands/finding-group.js.map +1 -0
  17. package/dist/commands/fix-suggest.d.ts +5 -0
  18. package/dist/commands/fix-suggest.d.ts.map +1 -0
  19. package/dist/commands/fix-suggest.js +172 -0
  20. package/dist/commands/fix-suggest.js.map +1 -0
  21. package/dist/commands/ignore-list.d.ts +19 -0
  22. package/dist/commands/ignore-list.d.ts.map +1 -0
  23. package/dist/commands/ignore-list.js +166 -0
  24. package/dist/commands/ignore-list.js.map +1 -0
  25. package/dist/commands/incremental-review.d.ts +5 -0
  26. package/dist/commands/incremental-review.d.ts.map +1 -0
  27. package/dist/commands/incremental-review.js +240 -0
  28. package/dist/commands/incremental-review.js.map +1 -0
  29. package/dist/commands/multi-lang-review.d.ts +5 -0
  30. package/dist/commands/multi-lang-review.d.ts.map +1 -0
  31. package/dist/commands/multi-lang-review.js +231 -0
  32. package/dist/commands/multi-lang-review.js.map +1 -0
  33. package/dist/commands/review-cache.d.ts +23 -0
  34. package/dist/commands/review-cache.d.ts.map +1 -0
  35. package/dist/commands/review-cache.js +135 -0
  36. package/dist/commands/review-cache.js.map +1 -0
  37. package/dist/commands/review-log.d.ts +23 -0
  38. package/dist/commands/review-log.d.ts.map +1 -0
  39. package/dist/commands/review-log.js +165 -0
  40. package/dist/commands/review-log.js.map +1 -0
  41. package/dist/commands/review-priority.d.ts +5 -0
  42. package/dist/commands/review-priority.d.ts.map +1 -0
  43. package/dist/commands/review-priority.js +158 -0
  44. package/dist/commands/review-priority.js.map +1 -0
  45. package/dist/commands/review-profile.d.ts +5 -0
  46. package/dist/commands/review-profile.d.ts.map +1 -0
  47. package/dist/commands/review-profile.js +169 -0
  48. package/dist/commands/review-profile.js.map +1 -0
  49. package/dist/commands/review-stats.d.ts +5 -0
  50. package/dist/commands/review-stats.d.ts.map +1 -0
  51. package/dist/commands/review-stats.js +176 -0
  52. package/dist/commands/review-stats.js.map +1 -0
  53. package/dist/commands/review-summary.d.ts +5 -0
  54. package/dist/commands/review-summary.d.ts.map +1 -0
  55. package/dist/commands/review-summary.js +175 -0
  56. package/dist/commands/review-summary.js.map +1 -0
  57. package/dist/commands/review-template.d.ts +5 -0
  58. package/dist/commands/review-template.d.ts.map +1 -0
  59. package/dist/commands/review-template.js +213 -0
  60. package/dist/commands/review-template.js.map +1 -0
  61. package/dist/commands/rule-test.d.ts +5 -0
  62. package/dist/commands/rule-test.d.ts.map +1 -0
  63. package/dist/commands/rule-test.js +216 -0
  64. package/dist/commands/rule-test.js.map +1 -0
  65. package/dist/commands/team-config.d.ts +5 -0
  66. package/dist/commands/team-config.d.ts.map +1 -0
  67. package/dist/commands/team-config.js +235 -0
  68. package/dist/commands/team-config.js.map +1 -0
  69. package/package.json +1 -1
  70. package/server.json +2 -2
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Review-priority — Smart finding prioritization by context and impact.
3
+ */
4
+ import { readFileSync } from "fs";
5
+ // ─── Scoring weights ────────────────────────────────────────────────────────
6
+ const SEVERITY_WEIGHTS = {
7
+ critical: 100,
8
+ high: 75,
9
+ medium: 40,
10
+ low: 15,
11
+ };
12
+ const CATEGORY_WEIGHTS = {
13
+ security: 30,
14
+ reliability: 20,
15
+ performance: 15,
16
+ "error-handling": 10,
17
+ maintainability: 5,
18
+ documentation: 2,
19
+ testing: 5,
20
+ };
21
+ function categorize(ruleId) {
22
+ if (/sql|inject|xss|csrf|traversal|auth|secret|crypt|ssrf|deserial|pii/i.test(ruleId))
23
+ return "security";
24
+ if (/error|exception|throw|catch|null|undefined/i.test(ruleId))
25
+ return "error-handling";
26
+ if (/perf|cache|memory|leak|optim/i.test(ruleId))
27
+ return "performance";
28
+ if (/reliab|race|concurr|deadlock|timeout/i.test(ruleId))
29
+ return "reliability";
30
+ if (/test|assert|mock|coverage/i.test(ruleId))
31
+ return "testing";
32
+ if (/doc|comment|jsdoc|readme/i.test(ruleId))
33
+ return "documentation";
34
+ return "maintainability";
35
+ }
36
+ // ─── Priority calculation ──────────────────────────────────────────────────
37
+ function calculatePriority(finding) {
38
+ const severity = finding.severity || "low";
39
+ let score = SEVERITY_WEIGHTS[severity] || 15;
40
+ const reasons = [];
41
+ reasons.push(`severity:${severity} (+${SEVERITY_WEIGHTS[severity] || 15})`);
42
+ // Category bonus
43
+ const category = categorize(finding.ruleId || "");
44
+ const catBonus = CATEGORY_WEIGHTS[category] || 0;
45
+ score += catBonus;
46
+ if (catBonus > 0)
47
+ reasons.push(`category:${category} (+${catBonus})`);
48
+ // Confidence bonus
49
+ if (finding.confidence && finding.confidence > 0.8) {
50
+ score += 10;
51
+ reasons.push("high-confidence (+10)");
52
+ }
53
+ // Has patch bonus (actionable)
54
+ if (finding.patch) {
55
+ score += 5;
56
+ reasons.push("has-patch (+5)");
57
+ }
58
+ return { score: Math.min(score, 200), reason: reasons.join(", ") };
59
+ }
60
+ function priorityLabel(score) {
61
+ if (score >= 100)
62
+ return "P0-CRITICAL";
63
+ if (score >= 75)
64
+ return "P1-HIGH";
65
+ if (score >= 40)
66
+ return "P2-MEDIUM";
67
+ return "P3-LOW";
68
+ }
69
+ // ─── CLI ────────────────────────────────────────────────────────────────────
70
+ export function runReviewPriority(argv) {
71
+ if (argv.includes("--help") || argv.includes("-h")) {
72
+ console.log(`
73
+ judges review-priority — Smart finding prioritization
74
+
75
+ Usage:
76
+ judges review-priority --input verdict.json
77
+ judges review-priority --input verdict.json --top 10
78
+ judges review-priority --input verdict.json --format json
79
+
80
+ Options:
81
+ --input <file> TribunalVerdict JSON file (required)
82
+ --top <n> Show only top N priority findings (default: all)
83
+ --min-score <n> Minimum priority score to show (default: 0)
84
+ --format json JSON output
85
+ --help, -h Show this help
86
+
87
+ Prioritizes findings based on severity, category (security > reliability
88
+ > performance > etc.), confidence level, and actionability (has patch).
89
+ Outputs a ranked list so developers fix the most impactful issues first.
90
+ `);
91
+ return;
92
+ }
93
+ const inputPath = argv.find((_a, i) => argv[i - 1] === "--input");
94
+ const topStr = argv.find((_a, i) => argv[i - 1] === "--top");
95
+ const minScoreStr = argv.find((_a, i) => argv[i - 1] === "--min-score");
96
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
97
+ if (!inputPath) {
98
+ console.error("Error: --input is required. Provide a verdict JSON file.");
99
+ process.exitCode = 1;
100
+ return;
101
+ }
102
+ let verdict;
103
+ try {
104
+ verdict = JSON.parse(readFileSync(inputPath, "utf-8"));
105
+ }
106
+ catch {
107
+ console.error(`Error: Cannot read or parse ${inputPath}`);
108
+ process.exitCode = 1;
109
+ return;
110
+ }
111
+ const findings = verdict.findings || [];
112
+ if (findings.length === 0) {
113
+ console.log("No findings to prioritize.");
114
+ return;
115
+ }
116
+ let prioritized = findings.map((f) => {
117
+ const { score, reason } = calculatePriority(f);
118
+ return {
119
+ rank: 0,
120
+ priority: priorityLabel(score),
121
+ score,
122
+ ruleId: f.ruleId || "unknown",
123
+ severity: f.severity || "low",
124
+ title: f.title,
125
+ reason,
126
+ };
127
+ });
128
+ // Sort by score descending
129
+ prioritized.sort((a, b) => b.score - a.score);
130
+ prioritized = prioritized.map((p, i) => ({ ...p, rank: i + 1 }));
131
+ // Apply filters
132
+ const minScore = minScoreStr ? parseInt(minScoreStr, 10) : 0;
133
+ if (minScore > 0) {
134
+ prioritized = prioritized.filter((p) => p.score >= minScore);
135
+ }
136
+ if (topStr) {
137
+ prioritized = prioritized.slice(0, parseInt(topStr, 10));
138
+ }
139
+ if (format === "json") {
140
+ console.log(JSON.stringify({ total: findings.length, shown: prioritized.length, findings: prioritized }, null, 2));
141
+ return;
142
+ }
143
+ console.log(`\n Prioritized Findings (${prioritized.length} of ${findings.length})\n ─────────────────────────────`);
144
+ const priorityIcons = {
145
+ "P0-CRITICAL": "🔴",
146
+ "P1-HIGH": "🟠",
147
+ "P2-MEDIUM": "🟡",
148
+ "P3-LOW": "🔵",
149
+ };
150
+ for (const p of prioritized) {
151
+ const icon = priorityIcons[p.priority] || "⬜";
152
+ console.log(`\n #${p.rank} ${icon} ${p.priority} (score: ${p.score})`);
153
+ console.log(` ${p.ruleId}: ${p.title}`);
154
+ console.log(` ${p.reason}`);
155
+ }
156
+ console.log();
157
+ }
158
+ //# sourceMappingURL=review-priority.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-priority.js","sourceRoot":"","sources":["../../src/commands/review-priority.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAelC,+EAA+E;AAE/E,MAAM,gBAAgB,GAA2B;IAC/C,QAAQ,EAAE,GAAG;IACb,IAAI,EAAE,EAAE;IACR,MAAM,EAAE,EAAE;IACV,GAAG,EAAE,EAAE;CACR,CAAC;AAEF,MAAM,gBAAgB,GAA2B;IAC/C,QAAQ,EAAE,EAAE;IACZ,WAAW,EAAE,EAAE;IACf,WAAW,EAAE,EAAE;IACf,gBAAgB,EAAE,EAAE;IACpB,eAAe,EAAE,CAAC;IAClB,aAAa,EAAE,CAAC;IAChB,OAAO,EAAE,CAAC;CACX,CAAC;AAEF,SAAS,UAAU,CAAC,MAAc;IAChC,IAAI,oEAAoE,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,UAAU,CAAC;IACzG,IAAI,6CAA6C,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,gBAAgB,CAAC;IACxF,IAAI,+BAA+B,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,aAAa,CAAC;IACvE,IAAI,uCAAuC,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,aAAa,CAAC;IAC/E,IAAI,4BAA4B,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IAChE,IAAI,2BAA2B,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,eAAe,CAAC;IACrE,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,8EAA8E;AAE9E,SAAS,iBAAiB,CAAC,OAAgB;IACzC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,KAAK,CAAC;IAC3C,IAAI,KAAK,GAAG,gBAAgB,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC7C,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,OAAO,CAAC,IAAI,CAAC,YAAY,QAAQ,MAAM,gBAAgB,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAE5E,iBAAiB;IACjB,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjD,KAAK,IAAI,QAAQ,CAAC;IAClB,IAAI,QAAQ,GAAG,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,YAAY,QAAQ,MAAM,QAAQ,GAAG,CAAC,CAAC;IAEtE,mBAAmB;IACnB,IAAI,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,UAAU,GAAG,GAAG,EAAE,CAAC;QACnD,KAAK,IAAI,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IACxC,CAAC;IAED,+BAA+B;IAC/B,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,KAAK,IAAI,CAAC,CAAC;QACX,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AACrE,CAAC;AAED,SAAS,aAAa,CAAC,KAAa;IAClC,IAAI,KAAK,IAAI,GAAG;QAAE,OAAO,aAAa,CAAC;IACvC,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,SAAS,CAAC;IAClC,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,WAAW,CAAC;IACpC,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,+EAA+E;AAE/E,MAAM,UAAU,iBAAiB,CAAC,IAAc;IAC9C,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;CAkBf,CAAC,CAAC;QACC,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;IAClF,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC;IAC7E,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,aAAa,CAAC,CAAC;IACxF,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,UAAU,CAAC,IAAI,MAAM,CAAC;IAE1F,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;QAC1E,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,SAAS,EAAE,OAAO,CAAC,CAAoB,CAAC;IAC5E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,+BAA+B,SAAS,EAAE,CAAC,CAAC;QAC1D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC;IACxC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAC1C,OAAO;IACT,CAAC;IAED,IAAI,WAAW,GAAyB,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACzD,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC;QAC/C,OAAO;YACL,IAAI,EAAE,CAAC;YACP,QAAQ,EAAE,aAAa,CAAC,KAAK,CAAC;YAC9B,KAAK;YACL,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,SAAS;YAC7B,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,KAAK;YAC7B,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,MAAM;SACP,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,2BAA2B;IAC3B,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAC9C,WAAW,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAEjE,gBAAgB;IAChB,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7D,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;QACjB,WAAW,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,QAAQ,CAAC,CAAC;IAC/D,CAAC;IACD,IAAI,MAAM,EAAE,CAAC;QACX,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACnH,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CACT,6BAA6B,WAAW,CAAC,MAAM,OAAO,QAAQ,CAAC,MAAM,oCAAoC,CAC1G,CAAC;IAEF,MAAM,aAAa,GAA2B;QAC5C,aAAa,EAAE,IAAI;QACnB,SAAS,EAAE,IAAI;QACf,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE,IAAI;KACf,CAAC;IAEF,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,CAAC,CAAC,QAAQ,YAAY,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;QAC1E,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,CAAC,GAAG,EAAE,CAAC;AAChB,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-profile — Per-developer review preferences stored locally.
3
+ */
4
+ export declare function runReviewProfile(argv: string[]): void;
5
+ //# sourceMappingURL=review-profile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-profile.d.ts","sourceRoot":"","sources":["../../src/commands/review-profile.ts"],"names":[],"mappings":"AAAA;;GAEG;AAyEH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAmIrD"}
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Review-profile — Per-developer review preferences stored locally.
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync } from "fs";
5
+ import { join, dirname } from "path";
6
+ // ─── Defaults ───────────────────────────────────────────────────────────────
7
+ const PROFILE_DIR = join(".judges", "profiles");
8
+ function defaultProfile(name) {
9
+ return {
10
+ version: "1.0.0",
11
+ name,
12
+ preferences: {
13
+ minSeverity: "low",
14
+ focusAreas: ["security", "reliability", "performance"],
15
+ ignoredRules: [],
16
+ outputFormat: "text",
17
+ verbosity: "normal",
18
+ autoFix: false,
19
+ showRecommendations: true,
20
+ },
21
+ history: {
22
+ totalReviews: 0,
23
+ lastReview: null,
24
+ favoriteJudges: [],
25
+ },
26
+ };
27
+ }
28
+ function profilePath(name) {
29
+ return join(PROFILE_DIR, `${name}.json`);
30
+ }
31
+ function loadProfile(name) {
32
+ const p = profilePath(name);
33
+ if (!existsSync(p))
34
+ return null;
35
+ try {
36
+ return JSON.parse(readFileSync(p, "utf-8"));
37
+ }
38
+ catch {
39
+ return null;
40
+ }
41
+ }
42
+ function saveProfile(profile) {
43
+ const p = profilePath(profile.name);
44
+ mkdirSync(dirname(p), { recursive: true });
45
+ writeFileSync(p, JSON.stringify(profile, null, 2), "utf-8");
46
+ }
47
+ // ─── CLI ────────────────────────────────────────────────────────────────────
48
+ export function runReviewProfile(argv) {
49
+ if (argv.includes("--help") || argv.includes("-h")) {
50
+ console.log(`
51
+ judges review-profile — Per-developer review preferences
52
+
53
+ Usage:
54
+ judges review-profile init --name alice Create profile
55
+ judges review-profile show --name alice Show profile
56
+ judges review-profile set --name alice --key minSeverity --value medium
57
+ judges review-profile list List all profiles
58
+ judges review-profile --format json JSON output
59
+
60
+ Subcommands:
61
+ init Create a new developer profile
62
+ show Display a profile
63
+ set Update a profile preference
64
+ list List all profiles
65
+
66
+ Options:
67
+ --name <name> Profile name (required for init/show/set)
68
+ --key <key> Preference key to set
69
+ --value <value> Preference value
70
+ --format json JSON output
71
+ --help, -h Show this help
72
+
73
+ Profiles store per-developer preferences locally in .judges/profiles/.
74
+ Each developer can customize severity thresholds, focus areas, output
75
+ format, and more without affecting team defaults.
76
+ `);
77
+ return;
78
+ }
79
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
80
+ const name = argv.find((_a, i) => argv[i - 1] === "--name");
81
+ const key = argv.find((_a, i) => argv[i - 1] === "--key");
82
+ const value = argv.find((_a, i) => argv[i - 1] === "--value");
83
+ const subcommand = argv.find((a) => ["init", "show", "set", "list"].includes(a)) || "show";
84
+ if (subcommand === "list") {
85
+ if (!existsSync(PROFILE_DIR)) {
86
+ console.log("No profiles found. Create one with: judges review-profile init --name <name>");
87
+ return;
88
+ }
89
+ const files = readdirSync(PROFILE_DIR);
90
+ const profiles = files.filter((f) => f.endsWith(".json")).map((f) => f.replace(".json", ""));
91
+ if (format === "json") {
92
+ console.log(JSON.stringify({ profiles }, null, 2));
93
+ return;
94
+ }
95
+ console.log(`\n Developer Profiles (${profiles.length})\n ─────────────────────────────`);
96
+ for (const p of profiles) {
97
+ const prof = loadProfile(p);
98
+ console.log(` 👤 ${p} — focus: ${prof?.preferences.focusAreas.join(", ") || "default"}`);
99
+ }
100
+ console.log();
101
+ return;
102
+ }
103
+ if (!name) {
104
+ console.error("Error: --name is required.");
105
+ process.exitCode = 1;
106
+ return;
107
+ }
108
+ if (subcommand === "init") {
109
+ if (loadProfile(name)) {
110
+ console.error(`Error: Profile '${name}' already exists.`);
111
+ process.exitCode = 1;
112
+ return;
113
+ }
114
+ const profile = defaultProfile(name);
115
+ saveProfile(profile);
116
+ console.log(`Created profile '${name}' in ${profilePath(name)}.`);
117
+ return;
118
+ }
119
+ const profile = loadProfile(name);
120
+ if (!profile) {
121
+ console.error(`Error: Profile '${name}' not found. Run: judges review-profile init --name ${name}`);
122
+ process.exitCode = 1;
123
+ return;
124
+ }
125
+ if (subcommand === "set") {
126
+ if (!key || !value) {
127
+ console.error("Error: --key and --value are required for set.");
128
+ process.exitCode = 1;
129
+ return;
130
+ }
131
+ const prefs = profile.preferences;
132
+ if (!(key in prefs)) {
133
+ console.error(`Error: Unknown preference key '${key}'. Valid keys: ${Object.keys(prefs).join(", ")}`);
134
+ process.exitCode = 1;
135
+ return;
136
+ }
137
+ if (key === "focusAreas" || key === "ignoredRules") {
138
+ prefs[key] = value.split(",").map((v) => v.trim());
139
+ }
140
+ else if (key === "autoFix" || key === "showRecommendations") {
141
+ prefs[key] = value === "true";
142
+ }
143
+ else {
144
+ prefs[key] = value;
145
+ }
146
+ saveProfile(profile);
147
+ console.log(`Updated ${name}.${key} = ${JSON.stringify(prefs[key])}`);
148
+ return;
149
+ }
150
+ // Show
151
+ if (format === "json") {
152
+ console.log(JSON.stringify(profile, null, 2));
153
+ return;
154
+ }
155
+ console.log(`\n Profile: ${profile.name}\n ─────────────────────────────`);
156
+ console.log(` Min severity: ${profile.preferences.minSeverity}`);
157
+ console.log(` Focus areas: ${profile.preferences.focusAreas.join(", ")}`);
158
+ console.log(` Output format: ${profile.preferences.outputFormat}`);
159
+ console.log(` Verbosity: ${profile.preferences.verbosity}`);
160
+ console.log(` Auto-fix: ${profile.preferences.autoFix}`);
161
+ console.log(` Show recommendations: ${profile.preferences.showRecommendations}`);
162
+ if (profile.preferences.ignoredRules.length > 0) {
163
+ console.log(` Ignored rules: ${profile.preferences.ignoredRules.join(", ")}`);
164
+ }
165
+ console.log(`\n Reviews: ${profile.history.totalReviews}`);
166
+ console.log(` Last review: ${profile.history.lastReview || "never"}`);
167
+ console.log();
168
+ }
169
+ //# sourceMappingURL=review-profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-profile.js","sourceRoot":"","sources":["../../src/commands/review-profile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-stats — Personal review statistics and improvement trends (local).
3
+ */
4
+ export declare function runReviewStats(argv: string[]): void;
5
+ //# sourceMappingURL=review-stats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-stats.d.ts","sourceRoot":"","sources":["../../src/commands/review-stats.ts"],"names":[],"mappings":"AAAA;;GAEG;AAmHH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAyGnD"}
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Review-stats — Personal review statistics and improvement trends (local).
3
+ */
4
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
5
+ import { join, dirname } from "path";
6
+ // ─── Storage ────────────────────────────────────────────────────────────────
7
+ const STATS_FILE = join(".judges", "stats", "review-stats.json");
8
+ function loadRecords() {
9
+ if (!existsSync(STATS_FILE))
10
+ return [];
11
+ try {
12
+ const data = JSON.parse(readFileSync(STATS_FILE, "utf-8"));
13
+ return (data.records || []);
14
+ }
15
+ catch {
16
+ return [];
17
+ }
18
+ }
19
+ function saveRecords(records) {
20
+ mkdirSync(dirname(STATS_FILE), { recursive: true });
21
+ writeFileSync(STATS_FILE, JSON.stringify({ version: "1.0.0", records }, null, 2), "utf-8");
22
+ }
23
+ // ─── Statistics calculation ─────────────────────────────────────────────────
24
+ function calculateStats(records) {
25
+ if (records.length === 0) {
26
+ return {
27
+ totalReviews: 0,
28
+ totalFilesReviewed: 0,
29
+ totalFindings: 0,
30
+ averageScore: 0,
31
+ averageFindings: 0,
32
+ improvementTrend: 0,
33
+ bestScore: 0,
34
+ worstScore: 0,
35
+ mostCommonVerdict: "none",
36
+ records: [],
37
+ };
38
+ }
39
+ const totalFindings = records.reduce((s, r) => s + r.totalFindings, 0);
40
+ const totalFiles = records.reduce((s, r) => s + r.filesReviewed, 0);
41
+ const scores = records.map((r) => r.score);
42
+ const avgScore = scores.reduce((s, v) => s + v, 0) / scores.length;
43
+ const avgFindings = totalFindings / records.length;
44
+ // Improvement trend: compare last 5 vs previous 5
45
+ let trend = 0;
46
+ if (records.length >= 10) {
47
+ const recent = records.slice(-5);
48
+ const previous = records.slice(-10, -5);
49
+ const recentAvg = recent.reduce((s, r) => s + r.score, 0) / 5;
50
+ const previousAvg = previous.reduce((s, r) => s + r.score, 0) / 5;
51
+ trend = recentAvg - previousAvg;
52
+ }
53
+ else if (records.length >= 4) {
54
+ const half = Math.floor(records.length / 2);
55
+ const recent = records.slice(half);
56
+ const previous = records.slice(0, half);
57
+ const recentAvg = recent.reduce((s, r) => s + r.score, 0) / recent.length;
58
+ const previousAvg = previous.reduce((s, r) => s + r.score, 0) / previous.length;
59
+ trend = recentAvg - previousAvg;
60
+ }
61
+ // Most common verdict
62
+ const verdictCounts = new Map();
63
+ for (const r of records) {
64
+ verdictCounts.set(r.verdict, (verdictCounts.get(r.verdict) || 0) + 1);
65
+ }
66
+ const mostCommon = [...verdictCounts.entries()].sort((a, b) => b[1] - a[1])[0]?.[0] || "none";
67
+ return {
68
+ totalReviews: records.length,
69
+ totalFilesReviewed: totalFiles,
70
+ totalFindings: totalFindings,
71
+ averageScore: Math.round(avgScore * 10) / 10,
72
+ averageFindings: Math.round(avgFindings * 10) / 10,
73
+ improvementTrend: Math.round(trend * 10) / 10,
74
+ bestScore: Math.max(...scores),
75
+ worstScore: Math.min(...scores),
76
+ mostCommonVerdict: mostCommon,
77
+ records,
78
+ };
79
+ }
80
+ // ─── CLI ────────────────────────────────────────────────────────────────────
81
+ export function runReviewStats(argv) {
82
+ if (argv.includes("--help") || argv.includes("-h")) {
83
+ console.log(`
84
+ judges review-stats — Personal review statistics
85
+
86
+ Usage:
87
+ judges review-stats Show statistics
88
+ judges review-stats record --score 85 --findings 3 --files 5
89
+ judges review-stats reset Clear all records
90
+ judges review-stats --format json JSON output
91
+
92
+ Subcommands:
93
+ show Display statistics (default)
94
+ record Record a review result
95
+ reset Clear all records
96
+
97
+ Options:
98
+ --score <n> Score to record (0-100)
99
+ --findings <n> Number of findings
100
+ --files <n> Number of files reviewed
101
+ --verdict <v> Verdict: pass, fail, warning
102
+ --critical <n> Critical findings count
103
+ --high <n> High findings count
104
+ --medium <n> Medium findings count
105
+ --low <n> Low findings count
106
+ --last <n> Show only last N records
107
+ --format json JSON output
108
+ --help, -h Show this help
109
+
110
+ Statistics are stored locally in .judges/stats/.
111
+ `);
112
+ return;
113
+ }
114
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
115
+ const subcommand = argv.find((a) => ["show", "record", "reset"].includes(a)) || "show";
116
+ if (subcommand === "reset") {
117
+ saveRecords([]);
118
+ console.log("Review statistics reset.");
119
+ return;
120
+ }
121
+ if (subcommand === "record") {
122
+ const scoreStr = argv.find((_a, i) => argv[i - 1] === "--score");
123
+ const findingsStr = argv.find((_a, i) => argv[i - 1] === "--findings");
124
+ const filesStr = argv.find((_a, i) => argv[i - 1] === "--files");
125
+ const verdict = argv.find((_a, i) => argv[i - 1] === "--verdict") || "pass";
126
+ const criticalStr = argv.find((_a, i) => argv[i - 1] === "--critical");
127
+ const highStr = argv.find((_a, i) => argv[i - 1] === "--high");
128
+ const mediumStr = argv.find((_a, i) => argv[i - 1] === "--medium");
129
+ const lowStr = argv.find((_a, i) => argv[i - 1] === "--low");
130
+ const record = {
131
+ timestamp: new Date().toISOString(),
132
+ filesReviewed: parseInt(filesStr || "1", 10),
133
+ totalFindings: parseInt(findingsStr || "0", 10),
134
+ critical: parseInt(criticalStr || "0", 10),
135
+ high: parseInt(highStr || "0", 10),
136
+ medium: parseInt(mediumStr || "0", 10),
137
+ low: parseInt(lowStr || "0", 10),
138
+ score: parseInt(scoreStr || "100", 10),
139
+ verdict,
140
+ };
141
+ const records = loadRecords();
142
+ records.push(record);
143
+ saveRecords(records);
144
+ console.log(`Recorded review #${records.length} (score: ${record.score}, findings: ${record.totalFindings}).`);
145
+ return;
146
+ }
147
+ // Show stats
148
+ const records = loadRecords();
149
+ const lastN = argv.find((_a, i) => argv[i - 1] === "--last");
150
+ const displayRecords = lastN ? records.slice(-parseInt(lastN, 10)) : records;
151
+ const stats = calculateStats(displayRecords);
152
+ if (format === "json") {
153
+ console.log(JSON.stringify({ ...stats, records: undefined }, null, 2));
154
+ return;
155
+ }
156
+ console.log(`\n Review Statistics\n ─────────────────────────────`);
157
+ console.log(` Total reviews: ${stats.totalReviews}`);
158
+ console.log(` Total files reviewed: ${stats.totalFilesReviewed}`);
159
+ console.log(` Total findings: ${stats.totalFindings}`);
160
+ console.log(` Average score: ${stats.averageScore}/100`);
161
+ console.log(` Average findings: ${stats.averageFindings}`);
162
+ console.log(` Best score: ${stats.bestScore}`);
163
+ console.log(` Worst score: ${stats.worstScore}`);
164
+ console.log(` Most common verdict: ${stats.mostCommonVerdict}`);
165
+ const trendIcon = stats.improvementTrend > 0 ? "📈" : stats.improvementTrend < 0 ? "📉" : "➡️";
166
+ console.log(` Improvement trend: ${trendIcon} ${stats.improvementTrend > 0 ? "+" : ""}${stats.improvementTrend}`);
167
+ if (displayRecords.length > 0) {
168
+ console.log(`\n Recent Reviews (last ${Math.min(5, displayRecords.length)}):`);
169
+ for (const r of displayRecords.slice(-5)) {
170
+ const icon = r.verdict === "pass" ? "✅" : r.verdict === "fail" ? "❌" : "⚠️";
171
+ console.log(` ${icon} ${r.timestamp.slice(0, 10)} — score: ${r.score}, findings: ${r.totalFindings}`);
172
+ }
173
+ }
174
+ console.log();
175
+ }
176
+ //# sourceMappingURL=review-stats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-stats.js","sourceRoot":"","sources":["../../src/commands/review-stats.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-summary — Generate PR-ready review summaries with key metrics.
3
+ */
4
+ export declare function runReviewSummary(argv: string[]): void;
5
+ //# sourceMappingURL=review-summary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-summary.d.ts","sourceRoot":"","sources":["../../src/commands/review-summary.ts"],"names":[],"mappings":"AAAA;;GAEG;AAiIH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAqFrD"}