@kevinrabun/judges 3.106.0 → 3.107.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 (42) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +63 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/finding-auto-fix-suggest.d.ts +2 -0
  6. package/dist/commands/finding-auto-fix-suggest.d.ts.map +1 -0
  7. package/dist/commands/finding-auto-fix-suggest.js +77 -0
  8. package/dist/commands/finding-auto-fix-suggest.js.map +1 -0
  9. package/dist/commands/finding-batch-triage.d.ts +2 -0
  10. package/dist/commands/finding-batch-triage.d.ts.map +1 -0
  11. package/dist/commands/finding-batch-triage.js +91 -0
  12. package/dist/commands/finding-batch-triage.js.map +1 -0
  13. package/dist/commands/finding-confidence-boost.d.ts +2 -0
  14. package/dist/commands/finding-confidence-boost.d.ts.map +1 -0
  15. package/dist/commands/finding-confidence-boost.js +89 -0
  16. package/dist/commands/finding-confidence-boost.js.map +1 -0
  17. package/dist/commands/finding-noise-reduce.d.ts +2 -0
  18. package/dist/commands/finding-noise-reduce.d.ts.map +1 -0
  19. package/dist/commands/finding-noise-reduce.js +82 -0
  20. package/dist/commands/finding-noise-reduce.js.map +1 -0
  21. package/dist/commands/finding-scope-filter.d.ts +2 -0
  22. package/dist/commands/finding-scope-filter.d.ts.map +1 -0
  23. package/dist/commands/finding-scope-filter.js +78 -0
  24. package/dist/commands/finding-scope-filter.js.map +1 -0
  25. package/dist/commands/review-code-ownership.d.ts +2 -0
  26. package/dist/commands/review-code-ownership.d.ts.map +1 -0
  27. package/dist/commands/review-code-ownership.js +89 -0
  28. package/dist/commands/review-code-ownership.js.map +1 -0
  29. package/dist/commands/review-pr-label-suggest.d.ts +2 -0
  30. package/dist/commands/review-pr-label-suggest.d.ts.map +1 -0
  31. package/dist/commands/review-pr-label-suggest.js +78 -0
  32. package/dist/commands/review-pr-label-suggest.js.map +1 -0
  33. package/dist/commands/review-release-gate.d.ts +2 -0
  34. package/dist/commands/review-release-gate.d.ts.map +1 -0
  35. package/dist/commands/review-release-gate.js +82 -0
  36. package/dist/commands/review-release-gate.js.map +1 -0
  37. package/dist/commands/review-review-cadence.d.ts +2 -0
  38. package/dist/commands/review-review-cadence.d.ts.map +1 -0
  39. package/dist/commands/review-review-cadence.js +86 -0
  40. package/dist/commands/review-review-cadence.js.map +1 -0
  41. package/package.json +1 -1
  42. package/server.json +2 -2
@@ -0,0 +1,78 @@
1
+ import { readFileSync, existsSync } from "fs";
2
+ import { join } from "path";
3
+ function suggestLabels(data) {
4
+ const labels = [];
5
+ const findings = data.findings ?? [];
6
+ // Verdict-based labels
7
+ if (data.overallVerdict === "fail") {
8
+ labels.push({ label: "needs-fixes", reason: "Verdict is fail" });
9
+ }
10
+ else if (data.overallVerdict === "warning") {
11
+ labels.push({ label: "needs-review", reason: "Verdict is warning" });
12
+ }
13
+ else {
14
+ labels.push({ label: "approved", reason: "Verdict is pass" });
15
+ }
16
+ // Severity-based labels
17
+ if (data.criticalCount > 0) {
18
+ labels.push({ label: "security-critical", reason: `${data.criticalCount} critical findings` });
19
+ }
20
+ if (data.highCount > 0) {
21
+ labels.push({ label: "high-priority", reason: `${data.highCount} high findings` });
22
+ }
23
+ // Domain-based labels
24
+ const domains = new Set();
25
+ for (const f of findings) {
26
+ const prefix = f.ruleId.split("-")[0].toUpperCase();
27
+ domains.add(prefix);
28
+ }
29
+ if (domains.has("SEC") || domains.has("AUTH") || domains.has("CRYPTO")) {
30
+ labels.push({ label: "security", reason: "Security-related findings" });
31
+ }
32
+ if (domains.has("PERF") || domains.has("OPT")) {
33
+ labels.push({ label: "performance", reason: "Performance-related findings" });
34
+ }
35
+ if (domains.has("COST")) {
36
+ labels.push({ label: "cost-impact", reason: "Cost-related findings" });
37
+ }
38
+ // Size-based label
39
+ if (findings.length > 10) {
40
+ labels.push({ label: "large-review", reason: `${findings.length} findings` });
41
+ }
42
+ return labels;
43
+ }
44
+ export function runReviewPrLabelSuggest(argv) {
45
+ if (argv.includes("--help") || argv.includes("-h")) {
46
+ console.log(`Usage: judges review-pr-label-suggest [options]
47
+
48
+ Suggest PR labels based on review findings.
49
+
50
+ Options:
51
+ --report <path> Path to verdict JSON file
52
+ --format <fmt> Output format: table (default) or json
53
+ -h, --help Show this help message`);
54
+ return;
55
+ }
56
+ const formatIdx = argv.indexOf("--format");
57
+ const format = formatIdx !== -1 && argv[formatIdx + 1] ? argv[formatIdx + 1] : "table";
58
+ const reportIdx = argv.indexOf("--report");
59
+ const reportPath = reportIdx !== -1 && argv[reportIdx + 1]
60
+ ? join(process.cwd(), argv[reportIdx + 1])
61
+ : join(process.cwd(), ".judges", "last-verdict.json");
62
+ if (!existsSync(reportPath)) {
63
+ console.log(`No report found at: ${reportPath}`);
64
+ return;
65
+ }
66
+ const data = JSON.parse(readFileSync(reportPath, "utf-8"));
67
+ const labels = suggestLabels(data);
68
+ if (format === "json") {
69
+ console.log(JSON.stringify(labels, null, 2));
70
+ return;
71
+ }
72
+ console.log("\n=== Suggested PR Labels ===\n");
73
+ for (const l of labels) {
74
+ console.log(` ${l.label} — ${l.reason}`);
75
+ }
76
+ console.log();
77
+ }
78
+ //# sourceMappingURL=review-pr-label-suggest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-pr-label-suggest.js","sourceRoot":"","sources":["../../src/commands/review-pr-label-suggest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function runReviewReleaseGate(argv: string[]): void;
2
+ //# sourceMappingURL=review-release-gate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-release-gate.d.ts","sourceRoot":"","sources":["../../src/commands/review-release-gate.ts"],"names":[],"mappings":"AAiEA,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA0DzD"}
@@ -0,0 +1,82 @@
1
+ import { readFileSync, existsSync } from "fs";
2
+ import { join } from "path";
3
+ function evaluateReleaseGate(data, config) {
4
+ const checks = [];
5
+ const critOk = data.criticalCount <= config.maxCritical;
6
+ checks.push({
7
+ check: `Critical findings ≤ ${config.maxCritical}`,
8
+ passed: critOk,
9
+ detail: `Found: ${data.criticalCount}`,
10
+ });
11
+ const highOk = data.highCount <= config.maxHigh;
12
+ checks.push({
13
+ check: `High findings ≤ ${config.maxHigh}`,
14
+ passed: highOk,
15
+ detail: `Found: ${data.highCount}`,
16
+ });
17
+ const scoreOk = data.overallScore >= config.minScore;
18
+ checks.push({
19
+ check: `Score ≥ ${config.minScore}`,
20
+ passed: scoreOk,
21
+ detail: `Score: ${data.overallScore}`,
22
+ });
23
+ if (config.requirePass) {
24
+ const verdictOk = data.overallVerdict === "pass";
25
+ checks.push({
26
+ check: "Verdict is pass",
27
+ passed: verdictOk,
28
+ detail: `Verdict: ${data.overallVerdict}`,
29
+ });
30
+ }
31
+ const releaseReady = checks.every((c) => c.passed);
32
+ return { releaseReady, checks };
33
+ }
34
+ export function runReviewReleaseGate(argv) {
35
+ if (argv.includes("--help") || argv.includes("-h")) {
36
+ console.log(`Usage: judges review-release-gate [options]
37
+
38
+ Evaluate release-level quality gate.
39
+
40
+ Options:
41
+ --report <path> Path to verdict JSON file
42
+ --config <path> Path to release gate config JSON
43
+ --format <fmt> Output format: table (default) or json
44
+ -h, --help Show this help message`);
45
+ return;
46
+ }
47
+ const formatIdx = argv.indexOf("--format");
48
+ const format = formatIdx !== -1 && argv[formatIdx + 1] ? argv[formatIdx + 1] : "table";
49
+ const reportIdx = argv.indexOf("--report");
50
+ const reportPath = reportIdx !== -1 && argv[reportIdx + 1]
51
+ ? join(process.cwd(), argv[reportIdx + 1])
52
+ : join(process.cwd(), ".judges", "last-verdict.json");
53
+ const confIdx = argv.indexOf("--config");
54
+ const confPath = confIdx !== -1 && argv[confIdx + 1]
55
+ ? join(process.cwd(), argv[confIdx + 1])
56
+ : join(process.cwd(), ".judges", "release-gate.json");
57
+ if (!existsSync(reportPath)) {
58
+ console.log(`No report found at: ${reportPath}`);
59
+ return;
60
+ }
61
+ const data = JSON.parse(readFileSync(reportPath, "utf-8"));
62
+ let config;
63
+ if (existsSync(confPath)) {
64
+ config = JSON.parse(readFileSync(confPath, "utf-8"));
65
+ }
66
+ else {
67
+ config = { maxCritical: 0, maxHigh: 0, minScore: 80, requirePass: true };
68
+ }
69
+ const result = evaluateReleaseGate(data, config);
70
+ if (format === "json") {
71
+ console.log(JSON.stringify(result, null, 2));
72
+ return;
73
+ }
74
+ const status = result.releaseReady ? "RELEASE READY" : "NOT RELEASE READY";
75
+ console.log(`\n=== ${status} ===\n`);
76
+ for (const c of result.checks) {
77
+ const icon = c.passed ? "PASS" : "FAIL";
78
+ console.log(` [${icon}] ${c.check} — ${c.detail}`);
79
+ }
80
+ console.log();
81
+ }
82
+ //# sourceMappingURL=review-release-gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-release-gate.js","sourceRoot":"","sources":["../../src/commands/review-release-gate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function runReviewReviewCadence(argv: string[]): void;
2
+ //# sourceMappingURL=review-review-cadence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-review-cadence.d.ts","sourceRoot":"","sources":["../../src/commands/review-review-cadence.ts"],"names":[],"mappings":"AAqEA,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA6C3D"}
@@ -0,0 +1,86 @@
1
+ import { readFileSync, existsSync, readdirSync } from "fs";
2
+ import { join } from "path";
3
+ function analyzeCadence(historyDir) {
4
+ const entries = [];
5
+ if (existsSync(historyDir)) {
6
+ const files = readdirSync(historyDir);
7
+ for (const file of files) {
8
+ if (typeof file === "string" && file.endsWith(".json")) {
9
+ const filePath = join(historyDir, file);
10
+ try {
11
+ const data = JSON.parse(readFileSync(filePath, "utf-8"));
12
+ entries.push({
13
+ date: data.timestamp ?? file.replace(".json", ""),
14
+ score: data.overallScore,
15
+ findingCount: (data.findings ?? []).length,
16
+ verdict: data.overallVerdict,
17
+ });
18
+ }
19
+ catch {
20
+ // Skip malformed files
21
+ }
22
+ }
23
+ }
24
+ }
25
+ entries.sort((a, b) => a.date.localeCompare(b.date));
26
+ const totalReviews = entries.length;
27
+ const avgScore = totalReviews > 0 ? Math.round(entries.reduce((s, e) => s + e.score, 0) / totalReviews) : 0;
28
+ const avgFindings = totalReviews > 0 ? Math.round(entries.reduce((s, e) => s + e.findingCount, 0) / totalReviews) : 0;
29
+ let cadenceAssessment;
30
+ if (totalReviews >= 20)
31
+ cadenceAssessment = "Excellent — frequent reviews";
32
+ else if (totalReviews >= 10)
33
+ cadenceAssessment = "Good — regular reviews";
34
+ else if (totalReviews >= 5)
35
+ cadenceAssessment = "Fair — increase review frequency";
36
+ else
37
+ cadenceAssessment = "Low — establish regular review cadence";
38
+ return {
39
+ totalReviews,
40
+ avgScore,
41
+ avgFindings,
42
+ recentEntries: entries.slice(-10),
43
+ cadenceAssessment,
44
+ };
45
+ }
46
+ export function runReviewReviewCadence(argv) {
47
+ if (argv.includes("--help") || argv.includes("-h")) {
48
+ console.log(`Usage: judges review-review-cadence [options]
49
+
50
+ Analyze review cadence and trends.
51
+
52
+ Options:
53
+ --history <path> Path to history directory
54
+ --format <fmt> Output format: table (default) or json
55
+ -h, --help Show this help message`);
56
+ return;
57
+ }
58
+ const formatIdx = argv.indexOf("--format");
59
+ const format = formatIdx !== -1 && argv[formatIdx + 1] ? argv[formatIdx + 1] : "table";
60
+ const histIdx = argv.indexOf("--history");
61
+ const historyDir = histIdx !== -1 && argv[histIdx + 1]
62
+ ? join(process.cwd(), argv[histIdx + 1])
63
+ : join(process.cwd(), ".judges", "history");
64
+ const report = analyzeCadence(historyDir);
65
+ if (format === "json") {
66
+ console.log(JSON.stringify(report, null, 2));
67
+ return;
68
+ }
69
+ console.log("\n=== Review Cadence ===\n");
70
+ console.log(`Total reviews: ${report.totalReviews}`);
71
+ console.log(`Average score: ${report.avgScore}`);
72
+ console.log(`Average findings: ${report.avgFindings}`);
73
+ console.log(`Assessment: ${report.cadenceAssessment}\n`);
74
+ if (report.recentEntries.length > 0) {
75
+ console.log("Recent reviews:");
76
+ for (const e of report.recentEntries) {
77
+ console.log(` ${e.date}: score=${e.score}, findings=${e.findingCount}, verdict=${e.verdict}`);
78
+ }
79
+ }
80
+ else {
81
+ console.log("No review history found.");
82
+ console.log(`Store verdict JSON files in: ${historyDir}`);
83
+ }
84
+ console.log();
85
+ }
86
+ //# sourceMappingURL=review-review-cadence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-review-cadence.js","sourceRoot":"","sources":["../../src/commands/review-review-cadence.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kevinrabun/judges",
3
- "version": "3.106.0",
3
+ "version": "3.107.0",
4
4
  "description": "45 specialized judges that evaluate AI-generated code for security, cost, and quality.",
5
5
  "mcpName": "io.github.KevinRabun/judges",
6
6
  "type": "module",
package/server.json CHANGED
@@ -7,12 +7,12 @@
7
7
  "url": "https://github.com/kevinrabun/judges",
8
8
  "source": "github"
9
9
  },
10
- "version": "3.106.0",
10
+ "version": "3.107.0",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "identifier": "@kevinrabun/judges",
15
- "version": "3.106.0",
15
+ "version": "3.107.0",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  }