@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.
- package/CHANGELOG.md +39 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +133 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/auto-calibrate.d.ts +15 -0
- package/dist/commands/auto-calibrate.d.ts.map +1 -0
- package/dist/commands/auto-calibrate.js +107 -0
- package/dist/commands/auto-calibrate.js.map +1 -0
- package/dist/commands/auto-triage.d.ts +32 -0
- package/dist/commands/auto-triage.d.ts.map +1 -0
- package/dist/commands/auto-triage.js +126 -0
- package/dist/commands/auto-triage.js.map +1 -0
- package/dist/commands/config-migrate.d.ts +44 -0
- package/dist/commands/config-migrate.d.ts.map +1 -0
- package/dist/commands/config-migrate.js +241 -0
- package/dist/commands/config-migrate.js.map +1 -0
- package/dist/commands/coverage-map.d.ts +23 -0
- package/dist/commands/coverage-map.d.ts.map +1 -0
- package/dist/commands/coverage-map.js +223 -0
- package/dist/commands/coverage-map.js.map +1 -0
- package/dist/commands/dedup-report.d.ts +13 -0
- package/dist/commands/dedup-report.d.ts.map +1 -0
- package/dist/commands/dedup-report.js +138 -0
- package/dist/commands/dedup-report.js.map +1 -0
- package/dist/commands/dep-audit.d.ts +53 -0
- package/dist/commands/dep-audit.d.ts.map +1 -0
- package/dist/commands/dep-audit.js +278 -0
- package/dist/commands/dep-audit.js.map +1 -0
- package/dist/commands/deprecated.d.ts +48 -0
- package/dist/commands/deprecated.d.ts.map +1 -0
- package/dist/commands/deprecated.js +202 -0
- package/dist/commands/deprecated.js.map +1 -0
- package/dist/commands/diff-only.d.ts +34 -0
- package/dist/commands/diff-only.d.ts.map +1 -0
- package/dist/commands/diff-only.js +152 -0
- package/dist/commands/diff-only.js.map +1 -0
- package/dist/commands/fix-pr.d.ts +23 -0
- package/dist/commands/fix-pr.d.ts.map +1 -0
- package/dist/commands/fix-pr.js +323 -0
- package/dist/commands/fix-pr.js.map +1 -0
- package/dist/commands/group-findings.d.ts +23 -0
- package/dist/commands/group-findings.d.ts.map +1 -0
- package/dist/commands/group-findings.js +155 -0
- package/dist/commands/group-findings.js.map +1 -0
- package/dist/commands/interactive-fix.d.ts +23 -0
- package/dist/commands/interactive-fix.d.ts.map +1 -0
- package/dist/commands/interactive-fix.js +140 -0
- package/dist/commands/interactive-fix.js.map +1 -0
- package/dist/commands/monorepo.d.ts +38 -0
- package/dist/commands/monorepo.d.ts.map +1 -0
- package/dist/commands/monorepo.js +233 -0
- package/dist/commands/monorepo.js.map +1 -0
- package/dist/commands/notify.d.ts +79 -0
- package/dist/commands/notify.d.ts.map +1 -0
- package/dist/commands/notify.js +325 -0
- package/dist/commands/notify.js.map +1 -0
- package/dist/commands/pr-summary.d.ts +26 -0
- package/dist/commands/pr-summary.d.ts.map +1 -0
- package/dist/commands/pr-summary.js +188 -0
- package/dist/commands/pr-summary.js.map +1 -0
- package/dist/commands/profile.d.ts +38 -0
- package/dist/commands/profile.d.ts.map +1 -0
- package/dist/commands/profile.js +102 -0
- package/dist/commands/profile.js.map +1 -0
- package/dist/commands/quality-gate.d.ts +70 -0
- package/dist/commands/quality-gate.d.ts.map +1 -0
- package/dist/commands/quality-gate.js +264 -0
- package/dist/commands/quality-gate.js.map +1 -0
- package/dist/commands/smart-select.d.ts +27 -0
- package/dist/commands/smart-select.d.ts.map +1 -0
- package/dist/commands/smart-select.js +346 -0
- package/dist/commands/smart-select.js.map +1 -0
- package/dist/commands/upload.d.ts +14 -0
- package/dist/commands/upload.d.ts.map +1 -0
- package/dist/commands/upload.js +173 -0
- package/dist/commands/upload.js.map +1 -0
- package/dist/commands/validate-config.d.ts +17 -0
- package/dist/commands/validate-config.d.ts.map +1 -0
- package/dist/commands/validate-config.js +268 -0
- package/dist/commands/validate-config.js.map +1 -0
- package/dist/commands/warm-cache.d.ts +31 -0
- package/dist/commands/warm-cache.d.ts.map +1 -0
- package/dist/commands/warm-cache.js +166 -0
- package/dist/commands/warm-cache.js.map +1 -0
- package/dist/evaluators/framework-rules.d.ts +59 -0
- package/dist/evaluators/framework-rules.d.ts.map +1 -0
- package/dist/evaluators/framework-rules.js +292 -0
- package/dist/evaluators/framework-rules.js.map +1 -0
- package/dist/parallel.d.ts +53 -0
- package/dist/parallel.d.ts.map +1 -0
- package/dist/parallel.js +170 -0
- package/dist/parallel.js.map +1 -0
- package/package.json +1 -1
- 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"}
|