@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,155 @@
1
+ /**
2
+ * Finding grouping — group related findings by category, file, or rule
3
+ * for better review UX and digest-style reporting.
4
+ */
5
+ // ─── Category Classification ────────────────────────────────────────────────
6
+ const RULE_CATEGORIES = {
7
+ // Security
8
+ "SEC-": "Security",
9
+ "AUTH-": "Authentication",
10
+ "CRYPTO-": "Cryptography",
11
+ "INJECT-": "Injection",
12
+ "XSS-": "Cross-Site Scripting",
13
+ "SSRF-": "Server-Side Request Forgery",
14
+ "IDOR-": "Broken Access Control",
15
+ // Quality
16
+ "PERF-": "Performance",
17
+ "ERR-": "Error Handling",
18
+ "LOG-": "Logging",
19
+ "TEST-": "Testing",
20
+ "DOC-": "Documentation",
21
+ "MAINT-": "Maintainability",
22
+ "STRUCT-": "Code Structure",
23
+ // Reliability
24
+ "CONCUR-": "Concurrency",
25
+ "RACE-": "Race Conditions",
26
+ "SCALE-": "Scalability",
27
+ "CACHE-": "Caching",
28
+ "RATE-": "Rate Limiting",
29
+ // Compliance
30
+ "COMPLY-": "Compliance",
31
+ "DATA-": "Data Protection",
32
+ "PII-": "Privacy",
33
+ // AI
34
+ "AI-": "AI Safety",
35
+ "HALLUC-": "Hallucination",
36
+ "FW-": "Framework Safety",
37
+ // Infrastructure
38
+ "IAC-": "Infrastructure as Code",
39
+ "CICD-": "CI/CD",
40
+ "CLOUD-": "Cloud Readiness",
41
+ "DB-": "Database",
42
+ // Accessibility / UX
43
+ "A11Y-": "Accessibility",
44
+ "I18N-": "Internationalization",
45
+ "UX-": "User Experience",
46
+ };
47
+ function classifyRule(ruleId) {
48
+ for (const [prefix, category] of Object.entries(RULE_CATEGORIES)) {
49
+ if (ruleId.toUpperCase().startsWith(prefix))
50
+ return category;
51
+ }
52
+ return "Other";
53
+ }
54
+ // ─── Grouping Logic ─────────────────────────────────────────────────────────
55
+ function getGroupKey(finding, groupBy) {
56
+ switch (groupBy) {
57
+ case "category":
58
+ return classifyRule(finding.ruleId);
59
+ case "severity":
60
+ return finding.severity;
61
+ case "file":
62
+ return "(grouped)";
63
+ case "rule":
64
+ return finding.ruleId;
65
+ case "judge":
66
+ return finding.judgeId || "(unknown)";
67
+ }
68
+ }
69
+ export function groupFindings(findings, groupBy) {
70
+ const groups = new Map();
71
+ for (const f of findings) {
72
+ const key = getGroupKey(f, groupBy);
73
+ const arr = groups.get(key) || [];
74
+ arr.push(f);
75
+ groups.set(key, arr);
76
+ }
77
+ const sortedGroups = [...groups.entries()]
78
+ .map(([key, items]) => ({
79
+ key,
80
+ label: key,
81
+ findings: items,
82
+ count: items.length,
83
+ criticalCount: items.filter((f) => f.severity === "critical").length,
84
+ highCount: items.filter((f) => f.severity === "high").length,
85
+ }))
86
+ .sort((a, b) => b.criticalCount - a.criticalCount || b.highCount - a.highCount || b.count - a.count);
87
+ return {
88
+ groupBy,
89
+ groups: sortedGroups,
90
+ totalFindings: findings.length,
91
+ totalGroups: sortedGroups.length,
92
+ };
93
+ }
94
+ // ─── CLI ────────────────────────────────────────────────────────────────────
95
+ export function runGroupFindings(argv) {
96
+ if (argv.includes("--help") || argv.includes("-h")) {
97
+ console.log(`
98
+ judges group — Group findings by category, severity, file, rule, or judge
99
+
100
+ Usage:
101
+ judges group --input results.json Group by category (default)
102
+ judges group --input results.json --by severity Group by severity
103
+ judges group --input results.json --by file Group by file
104
+
105
+ Options:
106
+ --input <path> Path to JSON results file (required)
107
+ --by <key> Group by: category, severity, file, rule, judge (default: category)
108
+ --format json JSON output
109
+ --help, -h Show this help
110
+ `);
111
+ return;
112
+ }
113
+ const { readFileSync, existsSync } = require("fs");
114
+ const inputPath = argv.find((_a, i) => argv[i - 1] === "--input");
115
+ if (!inputPath || !existsSync(inputPath)) {
116
+ console.error("Error: --input <path> required (JSON results file)");
117
+ process.exit(1);
118
+ }
119
+ const byArg = argv.find((_a, i) => argv[i - 1] === "--by") || "category";
120
+ const validKeys = new Set(["category", "severity", "file", "rule", "judge"]);
121
+ if (!validKeys.has(byArg)) {
122
+ console.error(`Error: --by must be one of: ${[...validKeys].join(", ")}`);
123
+ process.exit(1);
124
+ }
125
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
126
+ const data = JSON.parse(readFileSync(inputPath, "utf-8"));
127
+ const findings = data.evaluations
128
+ ? data.evaluations.flatMap((e) => e.findings || [])
129
+ : data.findings || data;
130
+ const report = groupFindings(findings, byArg);
131
+ if (format === "json") {
132
+ console.log(JSON.stringify(report, null, 2));
133
+ return;
134
+ }
135
+ console.log(`\n Findings Grouped by ${report.groupBy}\n`);
136
+ console.log(` Total: ${report.totalFindings} findings in ${report.totalGroups} groups\n`);
137
+ for (const g of report.groups) {
138
+ const badges = [];
139
+ if (g.criticalCount > 0)
140
+ badges.push(`🔴 ${g.criticalCount} critical`);
141
+ if (g.highCount > 0)
142
+ badges.push(`🟠 ${g.highCount} high`);
143
+ const badge = badges.length > 0 ? ` (${badges.join(", ")})` : "";
144
+ console.log(` 📁 ${g.label} — ${g.count} findings${badge}`);
145
+ for (const f of g.findings.slice(0, 5)) {
146
+ const loc = f.lineNumbers?.length ? `:${f.lineNumbers[0]}` : "";
147
+ console.log(` ${f.severity.padEnd(8)} ${f.ruleId}: ${f.title.slice(0, 80)}${loc}`);
148
+ }
149
+ if (g.findings.length > 5) {
150
+ console.log(` ... and ${g.findings.length - 5} more`);
151
+ }
152
+ console.log("");
153
+ }
154
+ }
155
+ //# sourceMappingURL=group-findings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"group-findings.js","sourceRoot":"","sources":["../../src/commands/group-findings.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"}
@@ -0,0 +1,233 @@
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 { existsSync, readdirSync, readFileSync, statSync } from "fs";
14
+ import { resolve, join, relative, basename } from "path";
15
+ import { loadCascadingConfig } from "../config.js";
16
+ // ─── Package Discovery ─────────────────────────────────────────────────────
17
+ function readJsonSafe(filepath) {
18
+ try {
19
+ return JSON.parse(readFileSync(filepath, "utf-8"));
20
+ }
21
+ catch {
22
+ return null;
23
+ }
24
+ }
25
+ function readYamlWorkspaces(filepath) {
26
+ try {
27
+ const content = readFileSync(filepath, "utf-8");
28
+ const patterns = [];
29
+ // Simple extraction — lines starting with " - " under "packages:"
30
+ let inPackages = false;
31
+ for (const line of content.split("\n")) {
32
+ if (/^packages:/i.test(line.trim())) {
33
+ inPackages = true;
34
+ continue;
35
+ }
36
+ if (inPackages && line.match(/^\s+-\s+/)) {
37
+ patterns.push(line
38
+ .replace(/^\s+-\s+/, "")
39
+ .replace(/['"]/g, "")
40
+ .trim());
41
+ }
42
+ else if (inPackages && !line.match(/^\s/)) {
43
+ inPackages = false;
44
+ }
45
+ }
46
+ return patterns;
47
+ }
48
+ catch {
49
+ return [];
50
+ }
51
+ }
52
+ function expandGlobDirs(root, patterns) {
53
+ const dirs = [];
54
+ for (const pattern of patterns) {
55
+ const clean = pattern.replace(/\/\*$/, "").replace(/\*\*$/, "");
56
+ const base = join(root, clean);
57
+ if (!existsSync(base) || !statSync(base).isDirectory())
58
+ continue;
59
+ // If pattern ends with * — list subdirectories
60
+ if (pattern.endsWith("/*") || pattern.endsWith("/**")) {
61
+ try {
62
+ for (const entry of readdirSync(base)) {
63
+ const full = join(base, entry);
64
+ if (statSync(full).isDirectory())
65
+ dirs.push(full);
66
+ }
67
+ }
68
+ catch {
69
+ /* skip */
70
+ }
71
+ }
72
+ else {
73
+ dirs.push(base);
74
+ }
75
+ }
76
+ return dirs;
77
+ }
78
+ function detectLanguagesInDir(dir) {
79
+ const langs = new Set();
80
+ const EXT_MAP = {
81
+ ".ts": "typescript",
82
+ ".tsx": "typescript",
83
+ ".js": "javascript",
84
+ ".jsx": "javascript",
85
+ ".mjs": "javascript",
86
+ ".py": "python",
87
+ ".go": "go",
88
+ ".rs": "rust",
89
+ ".java": "java",
90
+ ".cs": "csharp",
91
+ ".rb": "ruby",
92
+ ".php": "php",
93
+ ".swift": "swift",
94
+ ".kt": "kotlin",
95
+ ".cpp": "cpp",
96
+ ".cc": "cpp",
97
+ ".hpp": "cpp",
98
+ ".c": "c",
99
+ ".h": "c",
100
+ };
101
+ try {
102
+ const entries = readdirSync(dir, { recursive: true, withFileTypes: false });
103
+ for (const entry of entries.slice(0, 500)) {
104
+ const ext = entry.substring(entry.lastIndexOf(".")).toLowerCase();
105
+ if (EXT_MAP[ext])
106
+ langs.add(EXT_MAP[ext]);
107
+ }
108
+ }
109
+ catch {
110
+ /* skip */
111
+ }
112
+ return [...langs];
113
+ }
114
+ export function discoverPackages(root) {
115
+ const absRoot = resolve(root);
116
+ let tool = "heuristic";
117
+ let packageDirs = [];
118
+ // 1. pnpm-workspace.yaml
119
+ const pnpmWs = join(absRoot, "pnpm-workspace.yaml");
120
+ if (existsSync(pnpmWs)) {
121
+ tool = "pnpm";
122
+ const patterns = readYamlWorkspaces(pnpmWs);
123
+ packageDirs = expandGlobDirs(absRoot, patterns);
124
+ }
125
+ // 2. lerna.json
126
+ if (packageDirs.length === 0) {
127
+ const lernaPath = join(absRoot, "lerna.json");
128
+ if (existsSync(lernaPath)) {
129
+ tool = "lerna";
130
+ const lerna = readJsonSafe(lernaPath);
131
+ const patterns = lerna?.packages || ["packages/*"];
132
+ packageDirs = expandGlobDirs(absRoot, patterns);
133
+ }
134
+ }
135
+ // 3. turbo.json — check root package.json workspaces
136
+ if (packageDirs.length === 0 && existsSync(join(absRoot, "turbo.json"))) {
137
+ tool = "turbo";
138
+ const rootPkg = readJsonSafe(join(absRoot, "package.json"));
139
+ const workspaces = rootPkg?.workspaces || [];
140
+ packageDirs = expandGlobDirs(absRoot, workspaces.length > 0 ? workspaces : ["packages/*", "apps/*"]);
141
+ }
142
+ // 4. npm workspaces (package.json "workspaces" field)
143
+ if (packageDirs.length === 0) {
144
+ const rootPkg = readJsonSafe(join(absRoot, "package.json"));
145
+ if (rootPkg?.workspaces) {
146
+ tool = "npm-workspaces";
147
+ const workspaces = Array.isArray(rootPkg.workspaces)
148
+ ? rootPkg.workspaces
149
+ : rootPkg.workspaces.packages || [];
150
+ packageDirs = expandGlobDirs(absRoot, workspaces);
151
+ }
152
+ }
153
+ // 5. nx.json
154
+ if (packageDirs.length === 0 && existsSync(join(absRoot, "nx.json"))) {
155
+ tool = "nx";
156
+ packageDirs = expandGlobDirs(absRoot, ["packages/*", "apps/*", "libs/*"]);
157
+ }
158
+ // 6. Heuristic — look for packages/ and apps/ directories
159
+ if (packageDirs.length === 0) {
160
+ packageDirs = expandGlobDirs(absRoot, ["packages/*", "apps/*"]);
161
+ }
162
+ // Build package metadata
163
+ const packages = packageDirs
164
+ .filter((dir) => existsSync(dir) && statSync(dir).isDirectory())
165
+ .map((dir) => {
166
+ const pkg = readJsonSafe(join(dir, "package.json"));
167
+ const hasLocalConfig = existsSync(join(dir, ".judgesrc"));
168
+ const config = loadCascadingConfig(dir, absRoot);
169
+ const name = pkg?.name || basename(dir);
170
+ return {
171
+ name,
172
+ path: dir,
173
+ relativePath: relative(absRoot, dir),
174
+ hasLocalConfig,
175
+ config,
176
+ languages: detectLanguagesInDir(dir),
177
+ };
178
+ });
179
+ return { root: absRoot, tool, packages };
180
+ }
181
+ // ─── CLI Runner ─────────────────────────────────────────────────────────────
182
+ export function runMonorepoCommand(argv) {
183
+ if (argv.includes("--help") || argv.includes("-h")) {
184
+ console.log(`
185
+ judges monorepo — Monorepo workspace evaluation
186
+
187
+ Usage:
188
+ judges monorepo [root] Auto-detect and list packages
189
+ judges monorepo --list List detected packages only
190
+ judges monorepo --format json JSON output
191
+
192
+ Supports:
193
+ • pnpm-workspace.yaml
194
+ • lerna.json
195
+ • turbo.json
196
+ • npm workspaces (package.json "workspaces")
197
+ • nx.json
198
+ • Heuristic (packages/, apps/ directories)
199
+
200
+ Each package inherits its .judgesrc config via cascading config resolution.
201
+
202
+ Options:
203
+ --list List packages only (no evaluation)
204
+ --format <fmt> Output format: text, json
205
+ --help, -h Show this help
206
+ `);
207
+ return;
208
+ }
209
+ const root = argv.find((a, i) => i > 1 && !a.startsWith("-") && argv[i - 1] !== "--format") || ".";
210
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
211
+ console.log(`\n Scanning for monorepo packages in ${resolve(root)}...\n`);
212
+ const result = discoverPackages(resolve(root));
213
+ if (format === "json") {
214
+ console.log(JSON.stringify(result, null, 2));
215
+ return;
216
+ }
217
+ // Text output
218
+ console.log(` Monorepo tool: ${result.tool}`);
219
+ console.log(` Packages found: ${result.packages.length}\n`);
220
+ if (result.packages.length === 0) {
221
+ console.log(" No packages detected. Run from a monorepo root or use manual package paths.\n");
222
+ return;
223
+ }
224
+ const nameWidth = Math.max(12, ...result.packages.map((p) => p.name.length));
225
+ console.log(` ${"PACKAGE".padEnd(nameWidth)} ${"PATH".padEnd(30)} ${"CONFIG"} LANGUAGES`);
226
+ console.log(` ${"─".repeat(nameWidth)} ${"─".repeat(30)} ${"──────"} ${"─".repeat(20)}`);
227
+ for (const pkg of result.packages) {
228
+ const configStatus = pkg.hasLocalConfig ? "local " : "inherit";
229
+ console.log(` ${pkg.name.padEnd(nameWidth)} ${pkg.relativePath.padEnd(30)} ${configStatus} ${pkg.languages.join(", ") || "—"}`);
230
+ }
231
+ console.log("");
232
+ }
233
+ //# sourceMappingURL=monorepo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monorepo.js","sourceRoot":"","sources":["../../src/commands/monorepo.ts"],"names":[],"mappings":"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"}