@kevinrabun/judges 3.40.0 → 3.41.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 +22 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +63 -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/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/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/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/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/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/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,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
|
+
* `judges fix --interactive` — Interactive fix mode.
|
|
3
|
+
*
|
|
4
|
+
* Presents each auto-fixable finding one by one, letting the developer
|
|
5
|
+
* accept, skip, or view the diff before applying each patch.
|
|
6
|
+
* Reduces trust barrier by giving full control over what gets changed.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* judges fix src/app.ts --interactive # Interactive per-finding review
|
|
10
|
+
* judges fix src/app.ts -I # Short form
|
|
11
|
+
*/
|
|
12
|
+
import type { Finding } from "../types.js";
|
|
13
|
+
export interface InteractiveFixResult {
|
|
14
|
+
accepted: number;
|
|
15
|
+
skipped: number;
|
|
16
|
+
total: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Run interactive fix mode — present each fixable finding and let the user
|
|
20
|
+
* accept or skip it before applying.
|
|
21
|
+
*/
|
|
22
|
+
export declare function runInteractiveFix(filePath: string, findings: Finding[]): Promise<InteractiveFixResult>;
|
|
23
|
+
//# sourceMappingURL=interactive-fix.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactive-fix.d.ts","sourceRoot":"","sources":["../../src/commands/interactive-fix.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAS,MAAM,aAAa,CAAC;AAKlD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAkDD;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA4F5G"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `judges fix --interactive` — Interactive fix mode.
|
|
3
|
+
*
|
|
4
|
+
* Presents each auto-fixable finding one by one, letting the developer
|
|
5
|
+
* accept, skip, or view the diff before applying each patch.
|
|
6
|
+
* Reduces trust barrier by giving full control over what gets changed.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* judges fix src/app.ts --interactive # Interactive per-finding review
|
|
10
|
+
* judges fix src/app.ts -I # Short form
|
|
11
|
+
*/
|
|
12
|
+
import { readFileSync, writeFileSync } from "fs";
|
|
13
|
+
import { createInterface } from "readline";
|
|
14
|
+
import { applyPatches } from "./fix.js";
|
|
15
|
+
// ─── Diff Display ───────────────────────────────────────────────────────────
|
|
16
|
+
function formatPatchDiff(patch) {
|
|
17
|
+
const lines = [];
|
|
18
|
+
lines.push(` Line ${patch.startLine}–${patch.endLine}:`);
|
|
19
|
+
for (const line of patch.oldText.split("\n")) {
|
|
20
|
+
lines.push(` \x1b[31m- ${line}\x1b[0m`);
|
|
21
|
+
}
|
|
22
|
+
for (const line of patch.newText.split("\n")) {
|
|
23
|
+
lines.push(` \x1b[32m+ ${line}\x1b[0m`);
|
|
24
|
+
}
|
|
25
|
+
return lines.join("\n");
|
|
26
|
+
}
|
|
27
|
+
function formatFindingHeader(finding, index, total) {
|
|
28
|
+
const sevColors = {
|
|
29
|
+
critical: "\x1b[31;1m",
|
|
30
|
+
high: "\x1b[31m",
|
|
31
|
+
medium: "\x1b[33m",
|
|
32
|
+
low: "\x1b[36m",
|
|
33
|
+
info: "\x1b[37m",
|
|
34
|
+
};
|
|
35
|
+
const color = sevColors[finding.severity] || "\x1b[37m";
|
|
36
|
+
const reset = "\x1b[0m";
|
|
37
|
+
return [
|
|
38
|
+
"",
|
|
39
|
+
`═══════════════════════════════════════════════════════════════`,
|
|
40
|
+
` [${index + 1}/${total}] ${color}${finding.severity.toUpperCase()}${reset} ${finding.ruleId} — ${finding.title}`,
|
|
41
|
+
` ${finding.description}`,
|
|
42
|
+
`───────────────────────────────────────────────────────────────`,
|
|
43
|
+
].join("\n");
|
|
44
|
+
}
|
|
45
|
+
// ─── Interactive Prompt ─────────────────────────────────────────────────────
|
|
46
|
+
async function promptUser(question) {
|
|
47
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
48
|
+
return new Promise((resolve) => {
|
|
49
|
+
rl.question(question, (answer) => {
|
|
50
|
+
rl.close();
|
|
51
|
+
resolve(answer.trim().toLowerCase());
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
// ─── Interactive Fix Runner ─────────────────────────────────────────────────
|
|
56
|
+
/**
|
|
57
|
+
* Run interactive fix mode — present each fixable finding and let the user
|
|
58
|
+
* accept or skip it before applying.
|
|
59
|
+
*/
|
|
60
|
+
export async function runInteractiveFix(filePath, findings) {
|
|
61
|
+
const fixable = findings.filter((f) => f.patch);
|
|
62
|
+
if (fixable.length === 0) {
|
|
63
|
+
console.log("\n No auto-fixable findings.\n");
|
|
64
|
+
return { accepted: 0, skipped: 0, total: 0 };
|
|
65
|
+
}
|
|
66
|
+
console.log(`\n Found ${fixable.length} auto-fixable finding(s). Review each one:\n`);
|
|
67
|
+
const accepted = [];
|
|
68
|
+
let skipped = 0;
|
|
69
|
+
for (let i = 0; i < fixable.length; i++) {
|
|
70
|
+
const finding = fixable[i];
|
|
71
|
+
console.log(formatFindingHeader(finding, i, fixable.length));
|
|
72
|
+
console.log(formatPatchDiff(finding.patch));
|
|
73
|
+
console.log("");
|
|
74
|
+
const answer = await promptUser(" Apply this fix? [y]es / [n]o / [a]ll / [q]uit: ");
|
|
75
|
+
switch (answer) {
|
|
76
|
+
case "y":
|
|
77
|
+
case "yes":
|
|
78
|
+
accepted.push({
|
|
79
|
+
ruleId: finding.ruleId,
|
|
80
|
+
title: finding.title,
|
|
81
|
+
severity: finding.severity,
|
|
82
|
+
patch: finding.patch,
|
|
83
|
+
lineNumbers: finding.lineNumbers,
|
|
84
|
+
});
|
|
85
|
+
console.log(" ✓ Accepted\n");
|
|
86
|
+
break;
|
|
87
|
+
case "a":
|
|
88
|
+
case "all":
|
|
89
|
+
// Accept this and all remaining
|
|
90
|
+
accepted.push({
|
|
91
|
+
ruleId: finding.ruleId,
|
|
92
|
+
title: finding.title,
|
|
93
|
+
severity: finding.severity,
|
|
94
|
+
patch: finding.patch,
|
|
95
|
+
lineNumbers: finding.lineNumbers,
|
|
96
|
+
});
|
|
97
|
+
for (let j = i + 1; j < fixable.length; j++) {
|
|
98
|
+
accepted.push({
|
|
99
|
+
ruleId: fixable[j].ruleId,
|
|
100
|
+
title: fixable[j].title,
|
|
101
|
+
severity: fixable[j].severity,
|
|
102
|
+
patch: fixable[j].patch,
|
|
103
|
+
lineNumbers: fixable[j].lineNumbers,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
console.log(` ✓ Accepted all remaining ${fixable.length - i} fix(es)\n`);
|
|
107
|
+
i = fixable.length; // break out of loop
|
|
108
|
+
break;
|
|
109
|
+
case "q":
|
|
110
|
+
case "quit":
|
|
111
|
+
skipped += fixable.length - i;
|
|
112
|
+
console.log(" Quit — remaining fixes skipped.\n");
|
|
113
|
+
i = fixable.length; // break out of loop
|
|
114
|
+
break;
|
|
115
|
+
case "n":
|
|
116
|
+
case "no":
|
|
117
|
+
default:
|
|
118
|
+
skipped++;
|
|
119
|
+
console.log(" ⏭ Skipped\n");
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Apply accepted patches
|
|
124
|
+
if (accepted.length > 0) {
|
|
125
|
+
const code = readFileSync(filePath, "utf-8");
|
|
126
|
+
const result = applyPatches(code, accepted);
|
|
127
|
+
writeFileSync(filePath, result.result, "utf-8");
|
|
128
|
+
console.log(` ✅ Applied ${result.applied} fix(es) to ${filePath}`);
|
|
129
|
+
if (result.skipped > 0) {
|
|
130
|
+
console.log(` ⏭ ${result.skipped} fix(es) could not be applied (source changed)`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
console.log(`\n Summary: ${accepted.length} accepted, ${skipped} skipped out of ${fixable.length}\n`);
|
|
134
|
+
return {
|
|
135
|
+
accepted: accepted.length,
|
|
136
|
+
skipped,
|
|
137
|
+
total: fixable.length,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=interactive-fix.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactive-fix.js","sourceRoot":"","sources":["../../src/commands/interactive-fix.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `judges monorepo` — Monorepo workspace evaluation.
|
|
3
|
+
*
|
|
4
|
+
* Discovers packages in a monorepo (lerna, pnpm-workspace, turbo, packages/,
|
|
5
|
+
* apps/) and evaluates each one with its local `.judgesrc` cascading config.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* judges monorepo # Auto-detect and evaluate all packages
|
|
9
|
+
* judges monorepo --list # List detected packages only
|
|
10
|
+
* judges monorepo --concurrency 4 # Evaluate 4 packages in parallel
|
|
11
|
+
* judges monorepo --format json # JSON summary
|
|
12
|
+
*/
|
|
13
|
+
import type { JudgesConfig } from "../types.js";
|
|
14
|
+
export interface MonorepoPackage {
|
|
15
|
+
/** Package name (from package.json name or directory name) */
|
|
16
|
+
name: string;
|
|
17
|
+
/** Absolute path to the package */
|
|
18
|
+
path: string;
|
|
19
|
+
/** Relative path from root */
|
|
20
|
+
relativePath: string;
|
|
21
|
+
/** Has its own .judgesrc */
|
|
22
|
+
hasLocalConfig: boolean;
|
|
23
|
+
/** Resolved config (cascading merge) */
|
|
24
|
+
config: JudgesConfig;
|
|
25
|
+
/** Languages detected */
|
|
26
|
+
languages: string[];
|
|
27
|
+
}
|
|
28
|
+
export interface MonorepoScanResult {
|
|
29
|
+
/** Root directory */
|
|
30
|
+
root: string;
|
|
31
|
+
/** Monorepo tool detected */
|
|
32
|
+
tool: "pnpm" | "lerna" | "turbo" | "nx" | "npm-workspaces" | "heuristic";
|
|
33
|
+
/** Discovered packages */
|
|
34
|
+
packages: MonorepoPackage[];
|
|
35
|
+
}
|
|
36
|
+
export declare function discoverPackages(root: string): MonorepoScanResult;
|
|
37
|
+
export declare function runMonorepoCommand(argv: string[]): void;
|
|
38
|
+
//# sourceMappingURL=monorepo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monorepo.d.ts","sourceRoot":"","sources":["../../src/commands/monorepo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD,MAAM,WAAW,eAAe;IAC9B,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,4BAA4B;IAC5B,cAAc,EAAE,OAAO,CAAC;IACxB,wCAAwC;IACxC,MAAM,EAAE,YAAY,CAAC;IACrB,yBAAyB;IACzB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,6BAA6B;IAC7B,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,IAAI,GAAG,gBAAgB,GAAG,WAAW,CAAC;IACzE,0BAA0B;IAC1B,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAqGD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CA2EjE;AAID,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA6DvD"}
|