@kevinrabun/judges 3.40.0 → 3.42.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 (94) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +133 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/auto-calibrate.d.ts +15 -0
  6. package/dist/commands/auto-calibrate.d.ts.map +1 -0
  7. package/dist/commands/auto-calibrate.js +107 -0
  8. package/dist/commands/auto-calibrate.js.map +1 -0
  9. package/dist/commands/auto-triage.d.ts +32 -0
  10. package/dist/commands/auto-triage.d.ts.map +1 -0
  11. package/dist/commands/auto-triage.js +126 -0
  12. package/dist/commands/auto-triage.js.map +1 -0
  13. package/dist/commands/config-migrate.d.ts +44 -0
  14. package/dist/commands/config-migrate.d.ts.map +1 -0
  15. package/dist/commands/config-migrate.js +241 -0
  16. package/dist/commands/config-migrate.js.map +1 -0
  17. package/dist/commands/coverage-map.d.ts +23 -0
  18. package/dist/commands/coverage-map.d.ts.map +1 -0
  19. package/dist/commands/coverage-map.js +223 -0
  20. package/dist/commands/coverage-map.js.map +1 -0
  21. package/dist/commands/dedup-report.d.ts +13 -0
  22. package/dist/commands/dedup-report.d.ts.map +1 -0
  23. package/dist/commands/dedup-report.js +138 -0
  24. package/dist/commands/dedup-report.js.map +1 -0
  25. package/dist/commands/dep-audit.d.ts +53 -0
  26. package/dist/commands/dep-audit.d.ts.map +1 -0
  27. package/dist/commands/dep-audit.js +278 -0
  28. package/dist/commands/dep-audit.js.map +1 -0
  29. package/dist/commands/deprecated.d.ts +48 -0
  30. package/dist/commands/deprecated.d.ts.map +1 -0
  31. package/dist/commands/deprecated.js +202 -0
  32. package/dist/commands/deprecated.js.map +1 -0
  33. package/dist/commands/diff-only.d.ts +34 -0
  34. package/dist/commands/diff-only.d.ts.map +1 -0
  35. package/dist/commands/diff-only.js +152 -0
  36. package/dist/commands/diff-only.js.map +1 -0
  37. package/dist/commands/fix-pr.d.ts +23 -0
  38. package/dist/commands/fix-pr.d.ts.map +1 -0
  39. package/dist/commands/fix-pr.js +323 -0
  40. package/dist/commands/fix-pr.js.map +1 -0
  41. package/dist/commands/group-findings.d.ts +23 -0
  42. package/dist/commands/group-findings.d.ts.map +1 -0
  43. package/dist/commands/group-findings.js +155 -0
  44. package/dist/commands/group-findings.js.map +1 -0
  45. package/dist/commands/interactive-fix.d.ts +23 -0
  46. package/dist/commands/interactive-fix.d.ts.map +1 -0
  47. package/dist/commands/interactive-fix.js +140 -0
  48. package/dist/commands/interactive-fix.js.map +1 -0
  49. package/dist/commands/monorepo.d.ts +38 -0
  50. package/dist/commands/monorepo.d.ts.map +1 -0
  51. package/dist/commands/monorepo.js +233 -0
  52. package/dist/commands/monorepo.js.map +1 -0
  53. package/dist/commands/notify.d.ts +79 -0
  54. package/dist/commands/notify.d.ts.map +1 -0
  55. package/dist/commands/notify.js +325 -0
  56. package/dist/commands/notify.js.map +1 -0
  57. package/dist/commands/pr-summary.d.ts +26 -0
  58. package/dist/commands/pr-summary.d.ts.map +1 -0
  59. package/dist/commands/pr-summary.js +188 -0
  60. package/dist/commands/pr-summary.js.map +1 -0
  61. package/dist/commands/profile.d.ts +38 -0
  62. package/dist/commands/profile.d.ts.map +1 -0
  63. package/dist/commands/profile.js +102 -0
  64. package/dist/commands/profile.js.map +1 -0
  65. package/dist/commands/quality-gate.d.ts +70 -0
  66. package/dist/commands/quality-gate.d.ts.map +1 -0
  67. package/dist/commands/quality-gate.js +264 -0
  68. package/dist/commands/quality-gate.js.map +1 -0
  69. package/dist/commands/smart-select.d.ts +27 -0
  70. package/dist/commands/smart-select.d.ts.map +1 -0
  71. package/dist/commands/smart-select.js +346 -0
  72. package/dist/commands/smart-select.js.map +1 -0
  73. package/dist/commands/upload.d.ts +14 -0
  74. package/dist/commands/upload.d.ts.map +1 -0
  75. package/dist/commands/upload.js +173 -0
  76. package/dist/commands/upload.js.map +1 -0
  77. package/dist/commands/validate-config.d.ts +17 -0
  78. package/dist/commands/validate-config.d.ts.map +1 -0
  79. package/dist/commands/validate-config.js +268 -0
  80. package/dist/commands/validate-config.js.map +1 -0
  81. package/dist/commands/warm-cache.d.ts +31 -0
  82. package/dist/commands/warm-cache.d.ts.map +1 -0
  83. package/dist/commands/warm-cache.js +166 -0
  84. package/dist/commands/warm-cache.js.map +1 -0
  85. package/dist/evaluators/framework-rules.d.ts +59 -0
  86. package/dist/evaluators/framework-rules.d.ts.map +1 -0
  87. package/dist/evaluators/framework-rules.js +292 -0
  88. package/dist/evaluators/framework-rules.js.map +1 -0
  89. package/dist/parallel.d.ts +53 -0
  90. package/dist/parallel.d.ts.map +1 -0
  91. package/dist/parallel.js +170 -0
  92. package/dist/parallel.js.map +1 -0
  93. package/package.json +1 -1
  94. package/server.json +2 -2
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Diff-only evaluation — evaluate only changed lines in a PR or git diff.
3
+ *
4
+ * Parses unified diff output to identify changed line ranges,
5
+ * then filters evaluation findings to only those touching changed code.
6
+ * This drastically reduces noise in CI review comments.
7
+ */
8
+ // ─── Diff Parsing ───────────────────────────────────────────────────────────
9
+ /**
10
+ * Parse a unified diff to extract changed file/line ranges.
11
+ * Handles both `git diff` and `git diff --cached` output.
12
+ */
13
+ export function parseDiff(diff) {
14
+ const hunks = [];
15
+ let currentFile = "";
16
+ for (const line of diff.split("\n")) {
17
+ // Match +++ b/path/to/file
18
+ const fileMatch = line.match(/^\+\+\+ b\/(.+)$/);
19
+ if (fileMatch) {
20
+ currentFile = fileMatch[1];
21
+ continue;
22
+ }
23
+ // Match @@ -old,count +new,count @@
24
+ const hunkMatch = line.match(/^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/);
25
+ if (hunkMatch && currentFile) {
26
+ hunks.push({
27
+ file: currentFile,
28
+ startLine: parseInt(hunkMatch[1], 10),
29
+ lineCount: parseInt(hunkMatch[2] || "1", 10),
30
+ });
31
+ }
32
+ }
33
+ return hunks;
34
+ }
35
+ /**
36
+ * Check whether a finding overlaps with any changed hunk.
37
+ */
38
+ function isInDiff(finding, hunks) {
39
+ const findingLine = finding.lineNumbers?.[0];
40
+ if (!findingLine)
41
+ return false;
42
+ return hunks.some((h) => {
43
+ return findingLine >= h.startLine && findingLine <= h.startLine + h.lineCount - 1;
44
+ });
45
+ }
46
+ /**
47
+ * Filter findings to only those touching changed lines.
48
+ */
49
+ export function filterByDiff(findings, diff) {
50
+ const hunks = parseDiff(diff);
51
+ const filtered = findings.filter((f) => isInDiff(f, hunks));
52
+ return {
53
+ original: findings.length,
54
+ filtered: filtered.length,
55
+ removed: findings.length - filtered.length,
56
+ findings: filtered,
57
+ };
58
+ }
59
+ /**
60
+ * Get the list of changed files from a diff.
61
+ */
62
+ export function getChangedFiles(diff) {
63
+ const files = new Set();
64
+ for (const line of diff.split("\n")) {
65
+ const match = line.match(/^\+\+\+ b\/(.+)$/);
66
+ if (match)
67
+ files.add(match[1]);
68
+ }
69
+ return [...files];
70
+ }
71
+ // ─── CLI ────────────────────────────────────────────────────────────────────
72
+ export async function runDiffOnly(argv) {
73
+ if (argv.includes("--help") || argv.includes("-h")) {
74
+ console.log(`
75
+ judges diff-only — Evaluate only changed lines in a PR or diff
76
+
77
+ Usage:
78
+ judges diff-only --base main Diff against main branch
79
+ judges diff-only --base HEAD~1 Diff against previous commit
80
+ judges diff-only --diff-file changes.patch Use a pre-generated diff
81
+
82
+ Options:
83
+ --base <ref> Git ref to diff against (default: main)
84
+ --diff-file <path> Pre-generated diff file
85
+ --input <path> JSON results to filter (default: run fresh eval)
86
+ --format json JSON output
87
+ --help, -h Show this help
88
+
89
+ The command diffs against the base ref, identifies changed lines,
90
+ and filters findings to only those touching changed code. This is
91
+ ideal for CI pipelines reviewing PRs.
92
+ `);
93
+ return;
94
+ }
95
+ const { readFileSync, existsSync } = await import("fs");
96
+ const { execSync } = await import("child_process");
97
+ let diff;
98
+ const diffFile = argv.find((_a, i) => argv[i - 1] === "--diff-file");
99
+ if (diffFile && existsSync(diffFile)) {
100
+ diff = readFileSync(diffFile, "utf-8");
101
+ }
102
+ else {
103
+ const base = argv.find((_a, i) => argv[i - 1] === "--base") || "main";
104
+ try {
105
+ diff = execSync(`git diff ${base}`, { encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 });
106
+ }
107
+ catch {
108
+ console.error(`Error: could not run git diff ${base}`);
109
+ process.exit(1);
110
+ }
111
+ }
112
+ const changedFiles = getChangedFiles(diff);
113
+ const hunks = parseDiff(diff);
114
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
115
+ const inputPath = argv.find((_a, i) => argv[i - 1] === "--input");
116
+ if (inputPath && existsSync(inputPath)) {
117
+ const data = JSON.parse(readFileSync(inputPath, "utf-8"));
118
+ const findings = data.evaluations
119
+ ? data.evaluations.flatMap((e) => e.findings || [])
120
+ : data.findings || data;
121
+ const result = filterByDiff(findings, diff);
122
+ if (format === "json") {
123
+ console.log(JSON.stringify(result, null, 2));
124
+ return;
125
+ }
126
+ console.log(`\n Diff-Only Filter Results\n`);
127
+ console.log(` Changed files: ${changedFiles.length}`);
128
+ console.log(` Changed hunks: ${hunks.length}`);
129
+ console.log(` Original findings: ${result.original}`);
130
+ console.log(` In diff: ${result.filtered}`);
131
+ console.log(` Filtered out: ${result.removed}\n`);
132
+ for (const f of result.findings) {
133
+ const loc = f.lineNumbers?.length ? `:${f.lineNumbers[0]}` : "";
134
+ console.log(` ${f.severity.padEnd(8)} ${f.ruleId}: ${f.title.slice(0, 80)}${loc}`);
135
+ }
136
+ console.log("");
137
+ return;
138
+ }
139
+ // Just show diff info without filtering
140
+ if (format === "json") {
141
+ console.log(JSON.stringify({ changedFiles, hunks, totalHunks: hunks.length }, null, 2));
142
+ return;
143
+ }
144
+ console.log(`\n Changed Files (${changedFiles.length}):\n`);
145
+ for (const f of changedFiles) {
146
+ const fileHunks = hunks.filter((h) => h.file === f);
147
+ const totalLines = fileHunks.reduce((s, h) => s + h.lineCount, 0);
148
+ console.log(` ${f} (${fileHunks.length} hunks, ${totalLines} lines)`);
149
+ }
150
+ console.log(`\n Run with --input <results.json> to filter findings.\n`);
151
+ }
152
+ //# sourceMappingURL=diff-only.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-only.js","sourceRoot":"","sources":["../../src/commands/diff-only.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * `judges fix-pr` — Create a GitHub PR with auto-fix patches.
3
+ *
4
+ * Evaluates files, collects findings with patches, applies them on a new branch,
5
+ * and opens a pull request — like Dependabot but for code quality.
6
+ *
7
+ * Usage:
8
+ * judges fix-pr src/ # Fix all files in src/
9
+ * judges fix-pr src/app.ts # Fix a single file
10
+ * judges fix-pr . --branch judges/auto-fix # Custom branch name
11
+ * judges fix-pr . --severity high # Only high+ fixes
12
+ * judges fix-pr . --dry-run # Preview without creating PR
13
+ *
14
+ * Requires: GITHUB_TOKEN or `gh` CLI authenticated.
15
+ */
16
+ export interface FixPrResult {
17
+ filesFixed: number;
18
+ patchesApplied: number;
19
+ branch: string;
20
+ prUrl?: string;
21
+ }
22
+ export declare function runFixPr(argv: string[]): Promise<void>;
23
+ //# sourceMappingURL=fix-pr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fix-pr.d.ts","sourceRoot":"","sources":["../../src/commands/fix-pr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAuHH,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA4N5D"}
@@ -0,0 +1,323 @@
1
+ /**
2
+ * `judges fix-pr` — Create a GitHub PR with auto-fix patches.
3
+ *
4
+ * Evaluates files, collects findings with patches, applies them on a new branch,
5
+ * and opens a pull request — like Dependabot but for code quality.
6
+ *
7
+ * Usage:
8
+ * judges fix-pr src/ # Fix all files in src/
9
+ * judges fix-pr src/app.ts # Fix a single file
10
+ * judges fix-pr . --branch judges/auto-fix # Custom branch name
11
+ * judges fix-pr . --severity high # Only high+ fixes
12
+ * judges fix-pr . --dry-run # Preview without creating PR
13
+ *
14
+ * Requires: GITHUB_TOKEN or `gh` CLI authenticated.
15
+ */
16
+ import { execFileSync, execSync } from "child_process";
17
+ import { readFileSync, writeFileSync, readdirSync, statSync } from "fs";
18
+ import { resolve, extname, relative, join } from "path";
19
+ import { tmpdir } from "os";
20
+ import { evaluateWithTribunal } from "../evaluators/index.js";
21
+ import { applyPatches } from "./fix.js";
22
+ // ─── Language Detection ─────────────────────────────────────────────────────
23
+ const EXT_TO_LANG = {
24
+ ".ts": "typescript",
25
+ ".tsx": "typescript",
26
+ ".js": "javascript",
27
+ ".jsx": "javascript",
28
+ ".mjs": "javascript",
29
+ ".cjs": "javascript",
30
+ ".py": "python",
31
+ ".rs": "rust",
32
+ ".go": "go",
33
+ ".java": "java",
34
+ ".cs": "csharp",
35
+ ".cpp": "cpp",
36
+ ".cc": "cpp",
37
+ ".h": "c",
38
+ ".hpp": "cpp",
39
+ };
40
+ const SUPPORTED_EXTENSIONS = new Set(Object.keys(EXT_TO_LANG));
41
+ function detectLanguage(filePath) {
42
+ const base = filePath.toLowerCase();
43
+ if (base.endsWith("dockerfile") || base.includes("dockerfile."))
44
+ return "dockerfile";
45
+ return EXT_TO_LANG[extname(base)] || "typescript";
46
+ }
47
+ // ─── File Collection ────────────────────────────────────────────────────────
48
+ function collectFiles(dir, maxFiles = 200) {
49
+ const files = [];
50
+ const stack = [resolve(dir)];
51
+ while (stack.length > 0 && files.length < maxFiles) {
52
+ const current = stack.pop();
53
+ let entries;
54
+ try {
55
+ entries = readdirSync(current);
56
+ }
57
+ catch {
58
+ continue;
59
+ }
60
+ for (const entry of entries) {
61
+ if (entry.startsWith(".") || entry === "node_modules" || entry === "dist" || entry === "build")
62
+ continue;
63
+ const fullPath = join(current, entry);
64
+ try {
65
+ const stat = statSync(fullPath);
66
+ if (stat.isDirectory()) {
67
+ stack.push(fullPath);
68
+ }
69
+ else if (SUPPORTED_EXTENSIONS.has(extname(entry).toLowerCase())) {
70
+ files.push(fullPath);
71
+ if (files.length >= maxFiles)
72
+ break;
73
+ }
74
+ }
75
+ catch {
76
+ continue;
77
+ }
78
+ }
79
+ }
80
+ return files;
81
+ }
82
+ // ─── GitHub Helpers ─────────────────────────────────────────────────────────
83
+ function getToken() {
84
+ return process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
85
+ }
86
+ function detectRepo() {
87
+ try {
88
+ const remote = execSync("git remote get-url origin", { encoding: "utf-8" }).trim();
89
+ const sshMatch = remote.match(/github\.com[:/]([^/]+\/[^/.]+)/);
90
+ if (sshMatch)
91
+ return sshMatch[1];
92
+ const httpsMatch = remote.match(/github\.com\/([^/]+\/[^/.]+)/);
93
+ if (httpsMatch)
94
+ return httpsMatch[1];
95
+ }
96
+ catch {
97
+ // Not a git repo
98
+ }
99
+ return undefined;
100
+ }
101
+ function getCurrentBranch() {
102
+ try {
103
+ return execSync("git rev-parse --abbrev-ref HEAD", { encoding: "utf-8" }).trim();
104
+ }
105
+ catch {
106
+ return "main";
107
+ }
108
+ }
109
+ function ghCliAvailable() {
110
+ try {
111
+ execFileSync("gh", ["--version"], { stdio: "ignore" });
112
+ return true;
113
+ }
114
+ catch {
115
+ return false;
116
+ }
117
+ }
118
+ // ─── Severity Filter ────────────────────────────────────────────────────────
119
+ const SEVERITY_RANK = { critical: 5, high: 4, medium: 3, low: 2, info: 1 };
120
+ function meetsMinSeverity(severity, minSeverity) {
121
+ return (SEVERITY_RANK[severity] ?? 0) >= (SEVERITY_RANK[minSeverity] ?? 0);
122
+ }
123
+ export async function runFixPr(argv) {
124
+ // Parse args
125
+ const target = argv.find((a, i) => i > 1 &&
126
+ !a.startsWith("-") &&
127
+ argv[i - 1] !== "--branch" &&
128
+ argv[i - 1] !== "--severity" &&
129
+ argv[i - 1] !== "--repo") || ".";
130
+ const branch = argv.find((_a, i) => argv[i - 1] === "--branch") || `judges/auto-fix-${Date.now()}`;
131
+ const minSeverity = argv.find((_a, i) => argv[i - 1] === "--severity") || "low";
132
+ const repo = argv.find((_a, i) => argv[i - 1] === "--repo") || detectRepo();
133
+ const dryRun = argv.includes("--dry-run") || argv.includes("-n");
134
+ if (argv.includes("--help") || argv.includes("-h")) {
135
+ console.log(`
136
+ judges fix-pr — Create a PR with auto-fix patches
137
+
138
+ Usage:
139
+ judges fix-pr <path> Fix all files and create PR
140
+ judges fix-pr <path> --dry-run Preview fixes without creating PR
141
+ judges fix-pr <path> --branch <name> Custom branch name
142
+ judges fix-pr <path> --severity <level> Only apply fixes at or above severity
143
+ judges fix-pr <path> --repo <owner/repo> Target repository
144
+
145
+ Options:
146
+ --dry-run, -n Preview changes without pushing
147
+ --branch <name> Branch name (default: judges/auto-fix-<timestamp>)
148
+ --severity <level> Minimum severity: critical, high, medium, low, info
149
+ --repo <owner/repo> GitHub repository (auto-detected from git remote)
150
+ --help, -h Show this help
151
+
152
+ Environment:
153
+ GITHUB_TOKEN GitHub token for API access
154
+ GH_TOKEN Alternative token variable
155
+
156
+ Requires: git, and either GITHUB_TOKEN or gh CLI authenticated.
157
+ `);
158
+ return;
159
+ }
160
+ const token = getToken();
161
+ if (!token && !ghCliAvailable() && !dryRun) {
162
+ console.error("Error: GITHUB_TOKEN not set and gh CLI not available.");
163
+ console.error("Set GITHUB_TOKEN or authenticate with: gh auth login");
164
+ process.exit(1);
165
+ }
166
+ if (!repo && !dryRun) {
167
+ console.error("Error: Could not detect GitHub repository. Use --repo owner/repo.");
168
+ process.exit(1);
169
+ }
170
+ // Collect files
171
+ const resolvedTarget = resolve(target);
172
+ let files;
173
+ if (statSync(resolvedTarget).isDirectory()) {
174
+ files = collectFiles(resolvedTarget);
175
+ }
176
+ else {
177
+ files = [resolvedTarget];
178
+ }
179
+ console.log(`\n Scanning ${files.length} file(s) for auto-fixable findings...\n`);
180
+ // Evaluate and collect patches per file
181
+ const fileFixes = [];
182
+ let totalPatches = 0;
183
+ for (const filePath of files) {
184
+ const code = readFileSync(filePath, "utf-8");
185
+ const lang = detectLanguage(filePath);
186
+ const verdict = evaluateWithTribunal(code, lang);
187
+ const fixable = verdict.findings
188
+ .filter((f) => f.patch && meetsMinSeverity(f.severity, minSeverity))
189
+ .map((f) => ({
190
+ ruleId: f.ruleId,
191
+ title: f.title,
192
+ severity: f.severity,
193
+ patch: f.patch,
194
+ lineNumbers: f.lineNumbers,
195
+ }));
196
+ if (fixable.length === 0)
197
+ continue;
198
+ const result = applyPatches(code, fixable);
199
+ if (result.applied === 0)
200
+ continue;
201
+ const relPath = relative(process.cwd(), filePath);
202
+ fileFixes.push({
203
+ path: filePath,
204
+ relPath,
205
+ originalCode: code,
206
+ fixedCode: result.result,
207
+ applied: result.applied,
208
+ });
209
+ totalPatches += result.applied;
210
+ console.log(` ✓ ${relPath}: ${result.applied} fix(es) applied`);
211
+ }
212
+ if (fileFixes.length === 0) {
213
+ console.log("\n No auto-fixable findings found. Nothing to do.\n");
214
+ return;
215
+ }
216
+ console.log(`\n Total: ${totalPatches} fix(es) across ${fileFixes.length} file(s)\n`);
217
+ if (dryRun) {
218
+ console.log(" --dry-run: No PR will be created.\n");
219
+ // Show diff preview
220
+ for (const fix of fileFixes) {
221
+ console.log(` --- ${fix.relPath}`);
222
+ console.log(` +++ ${fix.relPath} (${fix.applied} fixes)`);
223
+ }
224
+ return;
225
+ }
226
+ // Create branch, apply fixes, commit, push, create PR
227
+ const baseBranch = getCurrentBranch();
228
+ try {
229
+ // Create and checkout new branch
230
+ execSync(`git checkout -b ${branch}`, { stdio: "pipe" });
231
+ // Write fixed files
232
+ for (const fix of fileFixes) {
233
+ writeFileSync(fix.path, fix.fixedCode, "utf-8");
234
+ }
235
+ // Stage and commit
236
+ execSync("git add -A", { stdio: "pipe" });
237
+ const commitMsg = `fix: auto-fix ${totalPatches} finding(s) across ${fileFixes.length} file(s)\n\nApplied by Judges Panel auto-fix.\n\nFixes applied:\n${fileFixes.map((f) => `- ${f.relPath}: ${f.applied} fix(es)`).join("\n")}`;
238
+ execSync(`git commit -m "${commitMsg.replace(/"/g, '\\"')}"`, { stdio: "pipe" });
239
+ // Push
240
+ execSync(`git push origin ${branch}`, { stdio: "pipe" });
241
+ console.log(` ✓ Pushed branch: ${branch}`);
242
+ // Create PR
243
+ const prTitle = `fix: Judges Panel auto-fix — ${totalPatches} finding(s)`;
244
+ const prBody = [
245
+ "## 🔧 Auto-Fix by Judges Panel",
246
+ "",
247
+ `Applied **${totalPatches}** automated fix(es) across **${fileFixes.length}** file(s).`,
248
+ "",
249
+ "### Files Fixed",
250
+ "",
251
+ ...fileFixes.map((f) => `- \`${f.relPath}\` — ${f.applied} fix(es)`),
252
+ "",
253
+ "---",
254
+ "",
255
+ "*This PR was generated automatically by [Judges Panel](https://github.com/KevinRabun/judges). Review the changes before merging.*",
256
+ ].join("\n");
257
+ if (ghCliAvailable()) {
258
+ try {
259
+ const output = execFileSync("gh", ["pr", "create", "--title", prTitle, "--body", prBody, "--base", baseBranch, "--head", branch], { encoding: "utf-8" }).trim();
260
+ console.log(` ✓ PR created: ${output}`);
261
+ }
262
+ catch (err) {
263
+ console.error(` ✗ Failed to create PR via gh CLI: ${err instanceof Error ? err.message : String(err)}`);
264
+ }
265
+ }
266
+ else if (token && repo) {
267
+ const tmpFile = join(tmpdir(), `.judges-fix-pr-${process.pid}.json`);
268
+ const body = { title: prTitle, body: prBody, head: branch, base: baseBranch };
269
+ writeFileSync(tmpFile, JSON.stringify(body), "utf-8");
270
+ try {
271
+ const curlArgs = [
272
+ "-s",
273
+ "-X",
274
+ "POST",
275
+ "-H",
276
+ `Authorization: Bearer ${token}`,
277
+ "-H",
278
+ "Accept: application/vnd.github.v3+json",
279
+ "-H",
280
+ "Content-Type: application/json",
281
+ "-d",
282
+ `@${tmpFile}`,
283
+ `https://api.github.com/repos/${repo}/pulls`,
284
+ ];
285
+ const output = execFileSync("curl", curlArgs, { encoding: "utf-8" }).trim();
286
+ try {
287
+ const parsed = JSON.parse(output);
288
+ if (parsed.html_url) {
289
+ console.log(` ✓ PR created: ${parsed.html_url}`);
290
+ }
291
+ else {
292
+ console.error(` ✗ PR creation response: ${output.slice(0, 300)}`);
293
+ }
294
+ }
295
+ catch {
296
+ console.error(` ✗ Failed to parse PR response`);
297
+ }
298
+ }
299
+ finally {
300
+ try {
301
+ const { unlinkSync } = await import("fs");
302
+ unlinkSync(tmpFile);
303
+ }
304
+ catch {
305
+ // ignore cleanup
306
+ }
307
+ }
308
+ }
309
+ }
310
+ catch (err) {
311
+ console.error(` ✗ Git error: ${err instanceof Error ? err.message : String(err)}`);
312
+ }
313
+ finally {
314
+ // Return to original branch
315
+ try {
316
+ execSync(`git checkout ${baseBranch}`, { stdio: "pipe" });
317
+ }
318
+ catch {
319
+ // If checkout fails, we're still on the fix branch
320
+ }
321
+ }
322
+ }
323
+ //# sourceMappingURL=fix-pr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fix-pr.js","sourceRoot":"","sources":["../../src/commands/fix-pr.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Finding grouping — group related findings by category, file, or rule
3
+ * for better review UX and digest-style reporting.
4
+ */
5
+ import type { Finding } from "../types.js";
6
+ export type GroupByKey = "category" | "severity" | "file" | "rule" | "judge";
7
+ export interface FindingGroup {
8
+ key: string;
9
+ label: string;
10
+ findings: Finding[];
11
+ count: number;
12
+ criticalCount: number;
13
+ highCount: number;
14
+ }
15
+ export interface GroupedReport {
16
+ groupBy: GroupByKey;
17
+ groups: FindingGroup[];
18
+ totalFindings: number;
19
+ totalGroups: number;
20
+ }
21
+ export declare function groupFindings(findings: Finding[], groupBy: GroupByKey): GroupedReport;
22
+ export declare function runGroupFindings(argv: string[]): void;
23
+ //# sourceMappingURL=group-findings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"group-findings.d.ts","sourceRoot":"","sources":["../../src/commands/group-findings.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAI3C,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAE7E,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,UAAU,CAAC;IACpB,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB;AA4ED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,UAAU,GAAG,aAAa,CA2BrF;AAID,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAmErD"}