@kevinrabun/judges 3.54.0 → 3.56.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 (70) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +112 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/api-versioning-audit.d.ts +6 -0
  6. package/dist/commands/api-versioning-audit.d.ts.map +1 -0
  7. package/dist/commands/api-versioning-audit.js +234 -0
  8. package/dist/commands/api-versioning-audit.js.map +1 -0
  9. package/dist/commands/boundary-enforce.d.ts +6 -0
  10. package/dist/commands/boundary-enforce.d.ts.map +1 -0
  11. package/dist/commands/boundary-enforce.js +256 -0
  12. package/dist/commands/boundary-enforce.js.map +1 -0
  13. package/dist/commands/build-optimize.d.ts +7 -0
  14. package/dist/commands/build-optimize.d.ts.map +1 -0
  15. package/dist/commands/build-optimize.js +257 -0
  16. package/dist/commands/build-optimize.js.map +1 -0
  17. package/dist/commands/commit-hygiene.d.ts +6 -0
  18. package/dist/commands/commit-hygiene.d.ts.map +1 -0
  19. package/dist/commands/commit-hygiene.js +176 -0
  20. package/dist/commands/commit-hygiene.js.map +1 -0
  21. package/dist/commands/deploy-readiness.d.ts +6 -0
  22. package/dist/commands/deploy-readiness.d.ts.map +1 -0
  23. package/dist/commands/deploy-readiness.js +212 -0
  24. package/dist/commands/deploy-readiness.js.map +1 -0
  25. package/dist/commands/error-taxonomy.d.ts +6 -0
  26. package/dist/commands/error-taxonomy.d.ts.map +1 -0
  27. package/dist/commands/error-taxonomy.js +227 -0
  28. package/dist/commands/error-taxonomy.js.map +1 -0
  29. package/dist/commands/log-quality.d.ts +6 -0
  30. package/dist/commands/log-quality.d.ts.map +1 -0
  31. package/dist/commands/log-quality.js +212 -0
  32. package/dist/commands/log-quality.js.map +1 -0
  33. package/dist/commands/migration-safety.d.ts +6 -0
  34. package/dist/commands/migration-safety.d.ts.map +1 -0
  35. package/dist/commands/migration-safety.js +257 -0
  36. package/dist/commands/migration-safety.js.map +1 -0
  37. package/dist/commands/null-safety-audit.d.ts +6 -0
  38. package/dist/commands/null-safety-audit.d.ts.map +1 -0
  39. package/dist/commands/null-safety-audit.js +222 -0
  40. package/dist/commands/null-safety-audit.js.map +1 -0
  41. package/dist/commands/observability-gap.d.ts +6 -0
  42. package/dist/commands/observability-gap.d.ts.map +1 -0
  43. package/dist/commands/observability-gap.js +212 -0
  44. package/dist/commands/observability-gap.js.map +1 -0
  45. package/dist/commands/ownership-map.d.ts +6 -0
  46. package/dist/commands/ownership-map.d.ts.map +1 -0
  47. package/dist/commands/ownership-map.js +229 -0
  48. package/dist/commands/ownership-map.js.map +1 -0
  49. package/dist/commands/retry-pattern-audit.d.ts +6 -0
  50. package/dist/commands/retry-pattern-audit.d.ts.map +1 -0
  51. package/dist/commands/retry-pattern-audit.js +216 -0
  52. package/dist/commands/retry-pattern-audit.js.map +1 -0
  53. package/dist/commands/rollback-safety.d.ts +5 -0
  54. package/dist/commands/rollback-safety.d.ts.map +1 -0
  55. package/dist/commands/rollback-safety.js +192 -0
  56. package/dist/commands/rollback-safety.js.map +1 -0
  57. package/dist/commands/secret-age.d.ts +6 -0
  58. package/dist/commands/secret-age.d.ts.map +1 -0
  59. package/dist/commands/secret-age.js +215 -0
  60. package/dist/commands/secret-age.js.map +1 -0
  61. package/dist/commands/test-isolation.d.ts +6 -0
  62. package/dist/commands/test-isolation.d.ts.map +1 -0
  63. package/dist/commands/test-isolation.js +235 -0
  64. package/dist/commands/test-isolation.js.map +1 -0
  65. package/dist/commands/test-quality.d.ts +6 -0
  66. package/dist/commands/test-quality.d.ts.map +1 -0
  67. package/dist/commands/test-quality.js +161 -0
  68. package/dist/commands/test-quality.js.map +1 -0
  69. package/package.json +1 -1
  70. package/server.json +2 -2
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Test isolation — detect shared mutable state, ordering dependencies,
3
+ * and resource leaks between test cases.
4
+ */
5
+ import { readFileSync, readdirSync, statSync } from "fs";
6
+ import { join, extname, basename } from "path";
7
+ // ─── File Collection ────────────────────────────────────────────────────────
8
+ const TEST_EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".py", ".java", ".go"]);
9
+ const TEST_PATTERNS = [/\.test\./i, /\.spec\./i, /test_/i, /_test\./i];
10
+ function isTestFile(name) {
11
+ return TEST_PATTERNS.some((p) => p.test(name));
12
+ }
13
+ function collectTestFiles(dir, max = 300) {
14
+ const files = [];
15
+ function walk(d) {
16
+ if (files.length >= max)
17
+ return;
18
+ let entries;
19
+ try {
20
+ entries = readdirSync(d);
21
+ }
22
+ catch {
23
+ return;
24
+ }
25
+ for (const e of entries) {
26
+ if (files.length >= max)
27
+ return;
28
+ if (e.startsWith(".") || e === "node_modules" || e === "dist" || e === "build")
29
+ continue;
30
+ const full = join(d, e);
31
+ try {
32
+ if (statSync(full).isDirectory())
33
+ walk(full);
34
+ else if (TEST_EXTS.has(extname(full)) && isTestFile(basename(full)))
35
+ files.push(full);
36
+ }
37
+ catch {
38
+ /* skip */
39
+ }
40
+ }
41
+ }
42
+ walk(dir);
43
+ return files;
44
+ }
45
+ // ─── Analysis ───────────────────────────────────────────────────────────────
46
+ function analyzeFile(filepath) {
47
+ const issues = [];
48
+ let content;
49
+ try {
50
+ content = readFileSync(filepath, "utf-8");
51
+ }
52
+ catch {
53
+ return issues;
54
+ }
55
+ const lines = content.split("\n");
56
+ // Track scope context
57
+ let inDescribe = false;
58
+ let describeDepth = 0;
59
+ for (let i = 0; i < lines.length; i++) {
60
+ const line = lines[i];
61
+ if (/\b(?:describe|context|suite)\s*\(/.test(line)) {
62
+ inDescribe = true;
63
+ describeDepth++;
64
+ }
65
+ if (inDescribe && /^\s*\}\s*\)\s*;?\s*$/.test(line)) {
66
+ describeDepth--;
67
+ if (describeDepth <= 0)
68
+ inDescribe = false;
69
+ }
70
+ // Global mutable state
71
+ if (/^\s*(?:let|var)\s+\w+\s*=/.test(line) && !inDescribe) {
72
+ const varName = line.match(/(?:let|var)\s+(\w+)/)?.[1];
73
+ if (varName && /\b(?:state|data|count|result|output|db|conn|client|server)\b/i.test(varName)) {
74
+ issues.push({
75
+ file: filepath,
76
+ line: i + 1,
77
+ issue: "Mutable global test state",
78
+ severity: "high",
79
+ detail: `Global \`${varName}\` — tests sharing mutable state cause order-dependent failures`,
80
+ });
81
+ }
82
+ }
83
+ // Module-level side effects in test files
84
+ if (/^\s*(?:fs\.|writeFileSync|mkdirSync|execSync|spawn|createServer)/.test(line) && !inDescribe) {
85
+ issues.push({
86
+ file: filepath,
87
+ line: i + 1,
88
+ issue: "Module-level side effect",
89
+ severity: "high",
90
+ detail: "Side effects outside test blocks affect all tests in the file",
91
+ });
92
+ }
93
+ // Shared fixtures without reset
94
+ if (/\b(?:beforeAll|before)\s*\(\s*(?:async\s+)?(?:function|\(|=>)/.test(line)) {
95
+ const beforeBlock = lines.slice(i, Math.min(i + 15, lines.length)).join("\n");
96
+ const hasAfter = /\b(?:afterAll|afterEach|after)\s*\(/.test(content);
97
+ if (!hasAfter && /(?:create|setup|init|connect|insert|write)/i.test(beforeBlock)) {
98
+ issues.push({
99
+ file: filepath,
100
+ line: i + 1,
101
+ issue: "Setup without teardown",
102
+ severity: "high",
103
+ detail: "beforeAll creates resources but no afterAll/afterEach cleans them — leaked state",
104
+ });
105
+ }
106
+ }
107
+ // File system operations without cleanup
108
+ if (/(?:writeFileSync|mkdirSync|writeFile|mkdir)\s*\(/.test(line)) {
109
+ const hasCleanup = /(?:unlinkSync|rmdirSync|rimraf|rm\s*\(|removeSync|afterEach.*unlink|afterAll.*unlink)/i.test(content);
110
+ if (!hasCleanup) {
111
+ issues.push({
112
+ file: filepath,
113
+ line: i + 1,
114
+ issue: "File system write without cleanup",
115
+ severity: "medium",
116
+ detail: "Test creates files but never cleans up — pollutes workspace",
117
+ });
118
+ }
119
+ }
120
+ // Network listeners without close
121
+ if (/(?:createServer|listen)\s*\(/.test(line)) {
122
+ const hasClose = /(?:\.close\s*\(|server\.close|afterAll.*close|afterEach.*close)/i.test(content);
123
+ if (!hasClose) {
124
+ issues.push({
125
+ file: filepath,
126
+ line: i + 1,
127
+ issue: "Server started without closing",
128
+ severity: "high",
129
+ detail: "Test starts a server but never closes it — port conflicts in parallel runs",
130
+ });
131
+ }
132
+ }
133
+ // setTimeout in tests (flakiness)
134
+ if (/setTimeout\s*\(\s*(?:resolve|done|callback|cb)\s*,\s*\d+/.test(line)) {
135
+ issues.push({
136
+ file: filepath,
137
+ line: i + 1,
138
+ issue: "setTimeout for async coordination",
139
+ severity: "medium",
140
+ detail: "Timer-based waits are flaky — use event-based or polling patterns",
141
+ });
142
+ }
143
+ // Order-dependent assertions (relying on previous test state)
144
+ if (/\.toBe\(.*\+\+|\.toEqual\(.*count/i.test(line)) {
145
+ issues.push({
146
+ file: filepath,
147
+ line: i + 1,
148
+ issue: "Assertion relies on accumulated state",
149
+ severity: "medium",
150
+ detail: "Tests should be independently runnable — avoid cross-test counters",
151
+ });
152
+ }
153
+ // Shared database connections
154
+ if (/(?:mongoose\.connect|createConnection|pg\.Pool|knex|prisma\.\$connect|sequelize)/i.test(line) && !inDescribe) {
155
+ issues.push({
156
+ file: filepath,
157
+ line: i + 1,
158
+ issue: "Shared database connection",
159
+ severity: "medium",
160
+ detail: "Use per-test or per-suite DB connections with transaction rollback",
161
+ });
162
+ }
163
+ // Environment variable mutation
164
+ if (/process\.env\.\w+\s*=/.test(line)) {
165
+ const hasRestore = /process\.env\.\w+\s*=.*original|delete\s+process\.env|afterEach.*env/i.test(content);
166
+ if (!hasRestore) {
167
+ issues.push({
168
+ file: filepath,
169
+ line: i + 1,
170
+ issue: "Environment mutation without restore",
171
+ severity: "high",
172
+ detail: "Setting process.env leaks to other tests — restore in afterEach",
173
+ });
174
+ }
175
+ }
176
+ }
177
+ return issues;
178
+ }
179
+ // ─── CLI ────────────────────────────────────────────────────────────────────
180
+ export function runTestIsolation(argv) {
181
+ if (argv.includes("--help") || argv.includes("-h")) {
182
+ console.log(`
183
+ judges test-isolation — Detect test isolation violations
184
+
185
+ Usage:
186
+ judges test-isolation [dir]
187
+ judges test-isolation tests/ --format json
188
+
189
+ Options:
190
+ [dir] Directory to scan (default: .)
191
+ --format json JSON output
192
+ --help, -h Show this help
193
+
194
+ Detects: shared mutable state, missing teardown, file system leaks, unclosed servers,
195
+ setTimeout waits, environment mutations, shared DB connections.
196
+ `);
197
+ return;
198
+ }
199
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
200
+ const dir = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0) || ".";
201
+ const files = collectTestFiles(dir);
202
+ const allIssues = [];
203
+ for (const f of files)
204
+ allIssues.push(...analyzeFile(f));
205
+ const highCount = allIssues.filter((i) => i.severity === "high").length;
206
+ const medCount = allIssues.filter((i) => i.severity === "medium").length;
207
+ const score = Math.max(0, 100 - highCount * 10 - medCount * 5);
208
+ if (format === "json") {
209
+ console.log(JSON.stringify({
210
+ issues: allIssues,
211
+ score,
212
+ summary: { files: files.length, high: highCount, medium: medCount, total: allIssues.length },
213
+ timestamp: new Date().toISOString(),
214
+ }, null, 2));
215
+ }
216
+ else {
217
+ const badge = score >= 80 ? "✅ ISOLATED" : score >= 50 ? "⚠️ LEAKY" : "❌ COUPLED";
218
+ console.log(`\n Test Isolation: ${badge} (${score}/100)\n ─────────────────────────`);
219
+ console.log(` Test files: ${files.length}\n`);
220
+ if (allIssues.length === 0) {
221
+ console.log(" No isolation issues detected.\n");
222
+ return;
223
+ }
224
+ for (const issue of allIssues.slice(0, 25)) {
225
+ const icon = issue.severity === "high" ? "🔴" : issue.severity === "medium" ? "🟡" : "🔵";
226
+ console.log(` ${icon} ${issue.issue}`);
227
+ console.log(` ${issue.file}:${issue.line}`);
228
+ console.log(` ${issue.detail}`);
229
+ }
230
+ if (allIssues.length > 25)
231
+ console.log(` ... and ${allIssues.length - 25} more`);
232
+ console.log(`\n Total: ${allIssues.length} | High: ${highCount} | Medium: ${medCount} | Score: ${score}/100\n`);
233
+ }
234
+ }
235
+ //# sourceMappingURL=test-isolation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-isolation.js","sourceRoot":"","sources":["../../src/commands/test-isolation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Test quality — score test suites for assertion density, boundary coverage,
3
+ * flakiness patterns, and mutation-testing readiness.
4
+ */
5
+ export declare function runTestQuality(argv: string[]): void;
6
+ //# sourceMappingURL=test-quality.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-quality.d.ts","sourceRoot":"","sources":["../../src/commands/test-quality.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAuHH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAwEnD"}
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Test quality — score test suites for assertion density, boundary coverage,
3
+ * flakiness patterns, and mutation-testing readiness.
4
+ */
5
+ import { readFileSync, readdirSync, statSync } from "fs";
6
+ import { join, extname, basename } from "path";
7
+ // ─── File Collection ────────────────────────────────────────────────────────
8
+ const TEST_EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".py", ".java", ".go", ".rs"]);
9
+ const TEST_PATTERNS = [/\.test\./i, /\.spec\./i, /test_/i, /_test\./i];
10
+ function isTestFile(name) {
11
+ return TEST_PATTERNS.some((p) => p.test(name));
12
+ }
13
+ function collectTestFiles(dir, max = 300) {
14
+ const files = [];
15
+ function walk(d) {
16
+ if (files.length >= max)
17
+ return;
18
+ let entries;
19
+ try {
20
+ entries = readdirSync(d);
21
+ }
22
+ catch {
23
+ return;
24
+ }
25
+ for (const e of entries) {
26
+ if (files.length >= max)
27
+ return;
28
+ if (e.startsWith(".") || e === "node_modules" || e === "dist" || e === "build")
29
+ continue;
30
+ const full = join(d, e);
31
+ try {
32
+ if (statSync(full).isDirectory())
33
+ walk(full);
34
+ else if (TEST_EXTS.has(extname(full)) && isTestFile(basename(full)))
35
+ files.push(full);
36
+ }
37
+ catch {
38
+ /* skip */
39
+ }
40
+ }
41
+ }
42
+ walk(dir);
43
+ return files;
44
+ }
45
+ // ─── Analysis ───────────────────────────────────────────────────────────────
46
+ function analyzeTestFile(filepath) {
47
+ const issues = [];
48
+ let content;
49
+ try {
50
+ content = readFileSync(filepath, "utf-8");
51
+ }
52
+ catch {
53
+ return { file: filepath, tests: 0, assertions: 0, assertionDensity: 0, issues: ["Could not read file"] };
54
+ }
55
+ // Count tests
56
+ const testMatches = content.match(/(?:it|test|specify)\s*\(|def\s+test_|@Test|func\s+Test/g) || [];
57
+ const tests = testMatches.length;
58
+ // Count assertions
59
+ const assertionPatterns = /assert|expect|should|toBe|toEqual|toMatch|toThrow|toContain|toHaveLength|toHaveBeenCalled|assertEqual|assertIn|assertRaises|assert_eq!|require\./g;
60
+ const assertions = (content.match(assertionPatterns) || []).length;
61
+ const assertionDensity = tests > 0 ? assertions / tests : 0;
62
+ // Zero-assertion tests
63
+ if (tests > 0 && assertions === 0) {
64
+ issues.push("No assertions found — tests that never assert prove nothing");
65
+ }
66
+ else if (assertionDensity < 1 && tests > 0) {
67
+ issues.push(`Low assertion density (${assertionDensity.toFixed(1)}/test) — some tests may lack assertions`);
68
+ }
69
+ // setTimeout / sleep (flakiness)
70
+ if (/setTimeout|sleep|time\.sleep|Thread\.sleep|time\.After/i.test(content)) {
71
+ issues.push("Timer-based waits detected — flakiness risk");
72
+ }
73
+ // Snapshot auto-update
74
+ if (/toMatchSnapshot|toMatchInlineSnapshot/i.test(content)) {
75
+ issues.push("Snapshot tests found — check for auto-update masking regressions");
76
+ }
77
+ // Mock overuse
78
+ const mockCount = (content.match(/mock|jest\.fn|sinon\.stub|patch\(|@Mock|gomock/gi) || []).length;
79
+ if (mockCount > 10) {
80
+ issues.push(`Heavy mocking (${mockCount} mocks) — test may not reflect real behavior`);
81
+ }
82
+ // Missing edge cases
83
+ const hasNullCheck = /null|undefined|nil|None|empty|boundary|edge/i.test(content);
84
+ const hasErrorCheck = /error|exception|throw|reject|fail|panic/i.test(content);
85
+ if (!hasNullCheck && !hasErrorCheck && tests > 0) {
86
+ issues.push("No null/error/boundary test cases — missing edge coverage");
87
+ }
88
+ // Hardcoded values only
89
+ const hasParameterized = /\.each|@parameterized|@pytest\.mark\.parametrize|testCases|table.?driven/i.test(content);
90
+ if (tests >= 5 && !hasParameterized) {
91
+ issues.push("No parameterized tests — consider table-driven testing for broader coverage");
92
+ }
93
+ // Commented-out tests
94
+ const commentedTests = (content.match(/\/\/\s*(it|test|describe)\s*\(|#\s*def\s+test_/g) || []).length;
95
+ if (commentedTests > 0) {
96
+ issues.push(`${commentedTests} commented-out test(s) — remove or restore`);
97
+ }
98
+ return { file: filepath, tests, assertions, assertionDensity, issues };
99
+ }
100
+ // ─── CLI ────────────────────────────────────────────────────────────────────
101
+ export function runTestQuality(argv) {
102
+ if (argv.includes("--help") || argv.includes("-h")) {
103
+ console.log(`
104
+ judges test-quality — Score test suites beyond coverage percentage
105
+
106
+ Usage:
107
+ judges test-quality [dir]
108
+ judges test-quality tests/ --format json
109
+
110
+ Options:
111
+ [dir] Directory to scan (default: .)
112
+ --format json JSON output
113
+ --help, -h Show this help
114
+
115
+ Checks: assertion density, zero-assertion tests, timer-based waits, snapshot abuse,
116
+ mock overuse, missing edge cases, parameterized tests, commented-out tests.
117
+ `);
118
+ return;
119
+ }
120
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
121
+ const dir = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0) || ".";
122
+ const files = collectTestFiles(dir);
123
+ const reports = files.map(analyzeTestFile);
124
+ const totalTests = reports.reduce((s, r) => s + r.tests, 0);
125
+ const totalAssertions = reports.reduce((s, r) => s + r.assertions, 0);
126
+ const totalIssues = reports.reduce((s, r) => s + r.issues.length, 0);
127
+ const avgDensity = totalTests > 0 ? totalAssertions / totalTests : 0;
128
+ const score = Math.max(0, Math.min(100, Math.round(100 - totalIssues * 5)));
129
+ if (format === "json") {
130
+ console.log(JSON.stringify({
131
+ reports,
132
+ score,
133
+ summary: {
134
+ files: files.length,
135
+ tests: totalTests,
136
+ assertions: totalAssertions,
137
+ avgDensity: +avgDensity.toFixed(2),
138
+ issues: totalIssues,
139
+ },
140
+ timestamp: new Date().toISOString(),
141
+ }, null, 2));
142
+ }
143
+ else {
144
+ const badge = score >= 80 ? "✅ GOOD" : score >= 50 ? "⚠️ FAIR" : "❌ POOR";
145
+ console.log(`\n Test Quality: ${badge} (${score}/100)\n ──────────────────────────`);
146
+ console.log(` Files: ${files.length} | Tests: ${totalTests} | Assertions: ${totalAssertions} | Avg density: ${avgDensity.toFixed(1)}/test\n`);
147
+ const problematic = reports.filter((r) => r.issues.length > 0);
148
+ if (problematic.length === 0) {
149
+ console.log(" No quality issues detected.\n");
150
+ return;
151
+ }
152
+ for (const r of problematic) {
153
+ console.log(` 📄 ${r.file} (${r.tests} tests, ${r.assertions} assertions)`);
154
+ for (const issue of r.issues) {
155
+ console.log(` ⚠️ ${issue}`);
156
+ }
157
+ }
158
+ console.log(`\n Total issues: ${totalIssues} | Score: ${score}/100\n`);
159
+ }
160
+ }
161
+ //# sourceMappingURL=test-quality.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-quality.js","sourceRoot":"","sources":["../../src/commands/test-quality.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.54.0",
3
+ "version": "3.56.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.54.0",
10
+ "version": "3.56.0",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "identifier": "@kevinrabun/judges",
15
- "version": "3.54.0",
15
+ "version": "3.56.0",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  }