@kevinrabun/judges 3.111.0 → 3.112.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 +13 -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/finding-fix-estimate.d.ts +2 -0
- package/dist/commands/finding-fix-estimate.d.ts.map +1 -0
- package/dist/commands/finding-fix-estimate.js +96 -0
- package/dist/commands/finding-fix-estimate.js.map +1 -0
- package/dist/commands/finding-noise-score.d.ts +2 -0
- package/dist/commands/finding-noise-score.d.ts.map +1 -0
- package/dist/commands/finding-noise-score.js +94 -0
- package/dist/commands/finding-noise-score.js.map +1 -0
- package/dist/commands/finding-repeat-detect.d.ts +2 -0
- package/dist/commands/finding-repeat-detect.d.ts.map +1 -0
- package/dist/commands/finding-repeat-detect.js +93 -0
- package/dist/commands/finding-repeat-detect.js.map +1 -0
- package/dist/commands/finding-scope-impact.d.ts +2 -0
- package/dist/commands/finding-scope-impact.d.ts.map +1 -0
- package/dist/commands/finding-scope-impact.js +84 -0
- package/dist/commands/finding-scope-impact.js.map +1 -0
- package/dist/commands/finding-top-offender.d.ts +2 -0
- package/dist/commands/finding-top-offender.d.ts.map +1 -0
- package/dist/commands/finding-top-offender.js +76 -0
- package/dist/commands/finding-top-offender.js.map +1 -0
- package/dist/commands/review-health-trend.d.ts +2 -0
- package/dist/commands/review-health-trend.d.ts.map +1 -0
- package/dist/commands/review-health-trend.js +108 -0
- package/dist/commands/review-health-trend.js.map +1 -0
- package/dist/commands/review-readiness-check.d.ts +2 -0
- package/dist/commands/review-readiness-check.d.ts.map +1 -0
- package/dist/commands/review-readiness-check.js +99 -0
- package/dist/commands/review-readiness-check.js.map +1 -0
- package/dist/commands/review-team-skill-map.d.ts +2 -0
- package/dist/commands/review-team-skill-map.d.ts.map +1 -0
- package/dist/commands/review-team-skill-map.js +103 -0
- package/dist/commands/review-team-skill-map.js.map +1 -0
- package/dist/commands/review-workflow-suggest.d.ts +2 -0
- package/dist/commands/review-workflow-suggest.d.ts.map +1 -0
- package/dist/commands/review-workflow-suggest.js +130 -0
- package/dist/commands/review-workflow-suggest.js.map +1 -0
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-health-trend.js","sourceRoot":"","sources":["../../src/commands/review-health-trend.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-readiness-check.d.ts","sourceRoot":"","sources":["../../src/commands/review-readiness-check.ts"],"names":[],"mappings":"AA4FA,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAuC5D"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { readFileSync, existsSync, readdirSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
function checkReadiness(baseDir) {
|
|
4
|
+
const items = [];
|
|
5
|
+
const configPath = join(baseDir, ".judgesrc.json");
|
|
6
|
+
const configExists = existsSync(configPath);
|
|
7
|
+
items.push({
|
|
8
|
+
criterion: "Configuration file",
|
|
9
|
+
passed: configExists,
|
|
10
|
+
detail: configExists ? ".judgesrc.json found" : ".judgesrc.json not found — run judges init",
|
|
11
|
+
});
|
|
12
|
+
const baselinePath = join(baseDir, ".judges", "baseline.json");
|
|
13
|
+
const baselineExists = existsSync(baselinePath);
|
|
14
|
+
items.push({
|
|
15
|
+
criterion: "Baseline available",
|
|
16
|
+
passed: baselineExists,
|
|
17
|
+
detail: baselineExists ? "Baseline found — suppressions will work" : "No baseline — run judges baseline first",
|
|
18
|
+
});
|
|
19
|
+
const historyDir = join(baseDir, ".judges", "history");
|
|
20
|
+
let historyCount = 0;
|
|
21
|
+
if (existsSync(historyDir)) {
|
|
22
|
+
const files = readdirSync(historyDir);
|
|
23
|
+
historyCount = files.filter((f) => String(f).endsWith(".json")).length;
|
|
24
|
+
}
|
|
25
|
+
items.push({
|
|
26
|
+
criterion: "Review history",
|
|
27
|
+
passed: historyCount >= 1,
|
|
28
|
+
detail: historyCount >= 1 ? `${historyCount} prior reviews found` : "No review history — first-time setup",
|
|
29
|
+
});
|
|
30
|
+
const lastVerdictPath = join(baseDir, ".judges", "last-verdict.json");
|
|
31
|
+
let lastVerdictFresh = false;
|
|
32
|
+
if (existsSync(lastVerdictPath)) {
|
|
33
|
+
try {
|
|
34
|
+
const raw = readFileSync(lastVerdictPath, "utf-8");
|
|
35
|
+
const verdict = JSON.parse(raw);
|
|
36
|
+
if (verdict.timestamp) {
|
|
37
|
+
const age = Date.now() - new Date(verdict.timestamp).getTime();
|
|
38
|
+
lastVerdictFresh = age < 7 * 24 * 60 * 60 * 1000;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
/* ignore parse errors */
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
items.push({
|
|
46
|
+
criterion: "Recent verdict",
|
|
47
|
+
passed: lastVerdictFresh,
|
|
48
|
+
detail: lastVerdictFresh ? "Last verdict is less than 7 days old" : "No recent verdict — run judges review",
|
|
49
|
+
});
|
|
50
|
+
const gitDir = join(baseDir, ".git");
|
|
51
|
+
const gitExists = existsSync(gitDir);
|
|
52
|
+
items.push({
|
|
53
|
+
criterion: "Git repository",
|
|
54
|
+
passed: gitExists,
|
|
55
|
+
detail: gitExists ? "Git repo detected" : "Not a git repository — diff features limited",
|
|
56
|
+
});
|
|
57
|
+
const passCount = items.filter((i) => i.passed).length;
|
|
58
|
+
return {
|
|
59
|
+
ready: passCount === items.length,
|
|
60
|
+
passCount,
|
|
61
|
+
totalChecks: items.length,
|
|
62
|
+
items,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export function runReviewReadinessCheck(argv) {
|
|
66
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
67
|
+
console.log(`Usage: judges review-readiness-check [options]
|
|
68
|
+
|
|
69
|
+
Assess whether a codebase is ready for review.
|
|
70
|
+
|
|
71
|
+
Options:
|
|
72
|
+
--dir <path> Project directory (default: cwd)
|
|
73
|
+
--format <fmt> Output format: table (default) or json
|
|
74
|
+
-h, --help Show this help message`);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const formatIdx = argv.indexOf("--format");
|
|
78
|
+
const format = formatIdx !== -1 && argv[formatIdx + 1] ? argv[formatIdx + 1] : "table";
|
|
79
|
+
const dirIdx = argv.indexOf("--dir");
|
|
80
|
+
const baseDir = dirIdx !== -1 && argv[dirIdx + 1] ? join(process.cwd(), argv[dirIdx + 1]) : process.cwd();
|
|
81
|
+
const report = checkReadiness(baseDir);
|
|
82
|
+
if (format === "json") {
|
|
83
|
+
console.log(JSON.stringify(report, null, 2));
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
console.log(`\n=== Review Readiness Check (${report.passCount}/${report.totalChecks}) ===\n`);
|
|
87
|
+
for (const item of report.items) {
|
|
88
|
+
const icon = item.passed ? "✓" : "✗";
|
|
89
|
+
console.log(` ${icon} ${item.criterion.padEnd(24)} ${item.detail}`);
|
|
90
|
+
}
|
|
91
|
+
console.log();
|
|
92
|
+
if (report.ready) {
|
|
93
|
+
console.log(" All checks passed — ready for review.");
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
console.log(" Some checks failed — address issues above before review.");
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=review-readiness-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-readiness-check.js","sourceRoot":"","sources":["../../src/commands/review-readiness-check.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-team-skill-map.d.ts","sourceRoot":"","sources":["../../src/commands/review-team-skill-map.ts"],"names":[],"mappings":"AAmGA,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA8C1D"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { readFileSync, existsSync, readdirSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
function extractDomain(ruleId) {
|
|
4
|
+
const parts = ruleId.split("/");
|
|
5
|
+
return parts.length > 1 ? parts[0] : "general";
|
|
6
|
+
}
|
|
7
|
+
function buildSkillMaps(historyDir) {
|
|
8
|
+
if (!existsSync(historyDir))
|
|
9
|
+
return [];
|
|
10
|
+
const files = readdirSync(historyDir);
|
|
11
|
+
const jsonFiles = files.filter((f) => String(f).endsWith(".json"));
|
|
12
|
+
const memberData = {};
|
|
13
|
+
for (const file of jsonFiles) {
|
|
14
|
+
const member = String(file)
|
|
15
|
+
.replace(/\.json$/, "")
|
|
16
|
+
.replace(/[-_]\d+$/, "");
|
|
17
|
+
const raw = readFileSync(join(historyDir, String(file)), "utf-8");
|
|
18
|
+
let verdict;
|
|
19
|
+
try {
|
|
20
|
+
verdict = JSON.parse(raw);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (!memberData[member])
|
|
26
|
+
memberData[member] = {};
|
|
27
|
+
const domainCounts = {};
|
|
28
|
+
for (const f of verdict.findings ?? []) {
|
|
29
|
+
const domain = extractDomain(f.ruleId);
|
|
30
|
+
domainCounts[domain] = (domainCounts[domain] ?? 0) + 1;
|
|
31
|
+
}
|
|
32
|
+
const allDomains = new Set(Object.keys(domainCounts));
|
|
33
|
+
if (allDomains.size === 0)
|
|
34
|
+
allDomains.add("general");
|
|
35
|
+
for (const domain of allDomains) {
|
|
36
|
+
if (!memberData[member][domain]) {
|
|
37
|
+
memberData[member][domain] = { reviews: 0, findings: 0 };
|
|
38
|
+
}
|
|
39
|
+
memberData[member][domain].reviews += 1;
|
|
40
|
+
memberData[member][domain].findings += domainCounts[domain] ?? 0;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const maps = [];
|
|
44
|
+
for (const [member, domains] of Object.entries(memberData)) {
|
|
45
|
+
const skills = [];
|
|
46
|
+
for (const [domain, stats] of Object.entries(domains)) {
|
|
47
|
+
const rate = stats.reviews > 0 ? stats.findings / stats.reviews : 0;
|
|
48
|
+
let level;
|
|
49
|
+
if (rate <= 0.5)
|
|
50
|
+
level = "expert";
|
|
51
|
+
else if (rate <= 1.5)
|
|
52
|
+
level = "proficient";
|
|
53
|
+
else if (rate <= 3)
|
|
54
|
+
level = "developing";
|
|
55
|
+
else
|
|
56
|
+
level = "beginner";
|
|
57
|
+
skills.push({ domain, level, findingRate: Math.round(rate * 10) / 10, reviewCount: stats.reviews });
|
|
58
|
+
}
|
|
59
|
+
skills.sort((a, b) => a.findingRate - b.findingRate);
|
|
60
|
+
const strongest = skills.length > 0 ? skills[0].domain : "none";
|
|
61
|
+
const weakest = skills.length > 0 ? skills[skills.length - 1].domain : "none";
|
|
62
|
+
maps.push({ member, skills, strongestDomain: strongest, weakestDomain: weakest });
|
|
63
|
+
}
|
|
64
|
+
return maps;
|
|
65
|
+
}
|
|
66
|
+
export function runReviewTeamSkillMap(argv) {
|
|
67
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
68
|
+
console.log(`Usage: judges review-team-skill-map [options]
|
|
69
|
+
|
|
70
|
+
Build a team skill map from review history.
|
|
71
|
+
|
|
72
|
+
Options:
|
|
73
|
+
--history <dir> Directory with verdict JSON files (default: .judges/history)
|
|
74
|
+
--format <fmt> Output format: table (default) or json
|
|
75
|
+
-h, --help Show this help message`);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const formatIdx = argv.indexOf("--format");
|
|
79
|
+
const format = formatIdx !== -1 && argv[formatIdx + 1] ? argv[formatIdx + 1] : "table";
|
|
80
|
+
const histIdx = argv.indexOf("--history");
|
|
81
|
+
const historyDir = histIdx !== -1 && argv[histIdx + 1]
|
|
82
|
+
? join(process.cwd(), argv[histIdx + 1])
|
|
83
|
+
: join(process.cwd(), ".judges", "history");
|
|
84
|
+
const maps = buildSkillMaps(historyDir);
|
|
85
|
+
if (format === "json") {
|
|
86
|
+
console.log(JSON.stringify(maps, null, 2));
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
console.log(`\n=== Team Skill Map (${maps.length} members) ===\n`);
|
|
90
|
+
if (maps.length === 0) {
|
|
91
|
+
console.log("No review history found. Run some reviews first.");
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
for (const m of maps) {
|
|
95
|
+
console.log(` ${m.member}`);
|
|
96
|
+
console.log(` Strongest: ${m.strongestDomain} | Weakest: ${m.weakestDomain}`);
|
|
97
|
+
for (const s of m.skills) {
|
|
98
|
+
console.log(` ${s.domain.padEnd(20)} ${s.level.padEnd(12)} (rate: ${s.findingRate}, reviews: ${s.reviewCount})`);
|
|
99
|
+
}
|
|
100
|
+
console.log();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=review-team-skill-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-team-skill-map.js","sourceRoot":"","sources":["../../src/commands/review-team-skill-map.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-workflow-suggest.d.ts","sourceRoot":"","sources":["../../src/commands/review-workflow-suggest.ts"],"names":[],"mappings":"AA8HA,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAkC7D"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { readFileSync, existsSync, readdirSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
function buildSuggestions(baseDir) {
|
|
4
|
+
const suggestions = [];
|
|
5
|
+
const configPath = join(baseDir, ".judgesrc.json");
|
|
6
|
+
if (!existsSync(configPath)) {
|
|
7
|
+
suggestions.push({
|
|
8
|
+
area: "Configuration",
|
|
9
|
+
suggestion: "Create .judgesrc.json with judges init",
|
|
10
|
+
priority: "high",
|
|
11
|
+
reason: "No config file found — using defaults may produce noisy results",
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
const baselinePath = join(baseDir, ".judges", "baseline.json");
|
|
15
|
+
if (!existsSync(baselinePath)) {
|
|
16
|
+
suggestions.push({
|
|
17
|
+
area: "Baseline",
|
|
18
|
+
suggestion: "Generate a baseline to suppress known findings",
|
|
19
|
+
priority: "high",
|
|
20
|
+
reason: "Without a baseline, existing issues flood every review",
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
const historyDir = join(baseDir, ".judges", "history");
|
|
24
|
+
let historyCount = 0;
|
|
25
|
+
if (existsSync(historyDir)) {
|
|
26
|
+
const files = readdirSync(historyDir);
|
|
27
|
+
historyCount = files.filter((f) => String(f).endsWith(".json")).length;
|
|
28
|
+
}
|
|
29
|
+
if (historyCount === 0) {
|
|
30
|
+
suggestions.push({
|
|
31
|
+
area: "Review cadence",
|
|
32
|
+
suggestion: "Start with weekly reviews, then move to per-PR",
|
|
33
|
+
priority: "medium",
|
|
34
|
+
reason: "No review history — establish a rhythm before scaling up",
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
else if (historyCount < 5) {
|
|
38
|
+
suggestions.push({
|
|
39
|
+
area: "Review cadence",
|
|
40
|
+
suggestion: "Consider integrating into CI for automatic PR reviews",
|
|
41
|
+
priority: "medium",
|
|
42
|
+
reason: `Only ${historyCount} reviews on file — automate to increase coverage`,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
const lastVerdictPath = join(baseDir, ".judges", "last-verdict.json");
|
|
46
|
+
if (existsSync(lastVerdictPath)) {
|
|
47
|
+
try {
|
|
48
|
+
const raw = readFileSync(lastVerdictPath, "utf-8");
|
|
49
|
+
const verdict = JSON.parse(raw);
|
|
50
|
+
const findings = verdict.findings ?? [];
|
|
51
|
+
const criticals = findings.filter((f) => f.severity === "critical").length;
|
|
52
|
+
const highs = findings.filter((f) => f.severity === "high").length;
|
|
53
|
+
if (criticals > 5) {
|
|
54
|
+
suggestions.push({
|
|
55
|
+
area: "Security focus",
|
|
56
|
+
suggestion: "Enable focused security judge preset",
|
|
57
|
+
priority: "high",
|
|
58
|
+
reason: `${criticals} critical findings — prioritise security review`,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
if (highs > 10) {
|
|
62
|
+
suggestions.push({
|
|
63
|
+
area: "Severity tuning",
|
|
64
|
+
suggestion: "Review minSeverity setting to reduce noise",
|
|
65
|
+
priority: "medium",
|
|
66
|
+
reason: `${highs} high-severity findings may cause alert fatigue`,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
if (findings.length > 50) {
|
|
70
|
+
suggestions.push({
|
|
71
|
+
area: "Scope",
|
|
72
|
+
suggestion: "Use diff-only mode to review only changed code",
|
|
73
|
+
priority: "medium",
|
|
74
|
+
reason: `${findings.length} findings — full-scan mode may overwhelm developers`,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
const patchable = findings.filter((f) => f.patch !== undefined && f.patch !== null).length;
|
|
78
|
+
if (patchable > 0) {
|
|
79
|
+
suggestions.push({
|
|
80
|
+
area: "Autofix",
|
|
81
|
+
suggestion: "Enable auto-fix to apply available patches automatically",
|
|
82
|
+
priority: "low",
|
|
83
|
+
reason: `${patchable} findings have patches — auto-apply saves time`,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
/* skip if parse fails */
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (suggestions.length === 0) {
|
|
92
|
+
suggestions.push({
|
|
93
|
+
area: "General",
|
|
94
|
+
suggestion: "Current workflow looks good — continue iterating",
|
|
95
|
+
priority: "low",
|
|
96
|
+
reason: "No obvious improvements detected",
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return suggestions;
|
|
100
|
+
}
|
|
101
|
+
export function runReviewWorkflowSuggest(argv) {
|
|
102
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
103
|
+
console.log(`Usage: judges review-workflow-suggest [options]
|
|
104
|
+
|
|
105
|
+
Suggest optimal review workflows based on project characteristics.
|
|
106
|
+
|
|
107
|
+
Options:
|
|
108
|
+
--dir <path> Project directory (default: cwd)
|
|
109
|
+
--format <fmt> Output format: table (default) or json
|
|
110
|
+
-h, --help Show this help message`);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const formatIdx = argv.indexOf("--format");
|
|
114
|
+
const format = formatIdx !== -1 && argv[formatIdx + 1] ? argv[formatIdx + 1] : "table";
|
|
115
|
+
const dirIdx = argv.indexOf("--dir");
|
|
116
|
+
const baseDir = dirIdx !== -1 && argv[dirIdx + 1] ? join(process.cwd(), argv[dirIdx + 1]) : process.cwd();
|
|
117
|
+
const suggestions = buildSuggestions(baseDir);
|
|
118
|
+
if (format === "json") {
|
|
119
|
+
console.log(JSON.stringify(suggestions, null, 2));
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
console.log(`\n=== Workflow Suggestions (${suggestions.length}) ===\n`);
|
|
123
|
+
for (const s of suggestions) {
|
|
124
|
+
console.log(` [${s.priority.toUpperCase()}] ${s.area}`);
|
|
125
|
+
console.log(` ${s.suggestion}`);
|
|
126
|
+
console.log(` Reason: ${s.reason}`);
|
|
127
|
+
console.log();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=review-workflow-suggest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-workflow-suggest.js","sourceRoot":"","sources":["../../src/commands/review-workflow-suggest.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
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.
|
|
10
|
+
"version": "3.112.0",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"identifier": "@kevinrabun/judges",
|
|
15
|
-
"version": "3.
|
|
15
|
+
"version": "3.112.0",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
18
18
|
}
|