@kevinrabun/judges 3.23.10 → 3.23.13

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 (133) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/dist/api.d.ts +3 -1
  3. package/dist/api.d.ts.map +1 -1
  4. package/dist/api.js +3 -1
  5. package/dist/api.js.map +1 -1
  6. package/dist/ast/structural-parser.d.ts.map +1 -1
  7. package/dist/ast/structural-parser.js +148 -3
  8. package/dist/ast/structural-parser.js.map +1 -1
  9. package/dist/auto-tune.d.ts +147 -0
  10. package/dist/auto-tune.d.ts.map +1 -0
  11. package/dist/auto-tune.js +374 -0
  12. package/dist/auto-tune.js.map +1 -0
  13. package/dist/cli.d.ts.map +1 -1
  14. package/dist/cli.js +7 -0
  15. package/dist/cli.js.map +1 -1
  16. package/dist/commands/auto-detect.js.map +1 -1
  17. package/dist/commands/benchmark-expanded-2.d.ts +13 -0
  18. package/dist/commands/benchmark-expanded-2.d.ts.map +1 -0
  19. package/dist/commands/benchmark-expanded-2.js +5531 -0
  20. package/dist/commands/benchmark-expanded-2.js.map +1 -0
  21. package/dist/commands/benchmark-expanded.d.ts +13 -0
  22. package/dist/commands/benchmark-expanded.d.ts.map +1 -0
  23. package/dist/commands/benchmark-expanded.js +2600 -0
  24. package/dist/commands/benchmark-expanded.js.map +1 -0
  25. package/dist/commands/benchmark.d.ts +1 -0
  26. package/dist/commands/benchmark.d.ts.map +1 -1
  27. package/dist/commands/benchmark.js +176 -3
  28. package/dist/commands/benchmark.js.map +1 -1
  29. package/dist/commands/doctor.js.map +1 -1
  30. package/dist/commands/feedback.d.ts.map +1 -1
  31. package/dist/commands/feedback.js +13 -0
  32. package/dist/commands/feedback.js.map +1 -1
  33. package/dist/commands/lsp.d.ts.map +1 -1
  34. package/dist/commands/lsp.js.map +1 -1
  35. package/dist/commands/review.d.ts +8 -0
  36. package/dist/commands/review.d.ts.map +1 -1
  37. package/dist/commands/review.js +175 -13
  38. package/dist/commands/review.js.map +1 -1
  39. package/dist/commands/tune.js.map +1 -1
  40. package/dist/dedup.d.ts.map +1 -1
  41. package/dist/dedup.js +24 -2
  42. package/dist/dedup.js.map +1 -1
  43. package/dist/disk-cache.js.map +1 -1
  44. package/dist/evaluators/accessibility.d.ts.map +1 -1
  45. package/dist/evaluators/accessibility.js +18 -4
  46. package/dist/evaluators/accessibility.js.map +1 -1
  47. package/dist/evaluators/agent-instructions.d.ts.map +1 -1
  48. package/dist/evaluators/agent-instructions.js +52 -1
  49. package/dist/evaluators/agent-instructions.js.map +1 -1
  50. package/dist/evaluators/authentication.d.ts.map +1 -1
  51. package/dist/evaluators/authentication.js +51 -2
  52. package/dist/evaluators/authentication.js.map +1 -1
  53. package/dist/evaluators/caching.d.ts.map +1 -1
  54. package/dist/evaluators/caching.js +5 -4
  55. package/dist/evaluators/caching.js.map +1 -1
  56. package/dist/evaluators/ci-cd.d.ts.map +1 -1
  57. package/dist/evaluators/ci-cd.js +23 -0
  58. package/dist/evaluators/ci-cd.js.map +1 -1
  59. package/dist/evaluators/compliance.d.ts.map +1 -1
  60. package/dist/evaluators/compliance.js +5 -1
  61. package/dist/evaluators/compliance.js.map +1 -1
  62. package/dist/evaluators/concurrency.d.ts.map +1 -1
  63. package/dist/evaluators/concurrency.js +34 -0
  64. package/dist/evaluators/concurrency.js.map +1 -1
  65. package/dist/evaluators/cybersecurity.d.ts.map +1 -1
  66. package/dist/evaluators/cybersecurity.js +231 -0
  67. package/dist/evaluators/cybersecurity.js.map +1 -1
  68. package/dist/evaluators/false-positive-review.js +25 -20
  69. package/dist/evaluators/false-positive-review.js.map +1 -1
  70. package/dist/evaluators/hallucination-detection.d.ts +3 -0
  71. package/dist/evaluators/hallucination-detection.d.ts.map +1 -0
  72. package/dist/evaluators/hallucination-detection.js +463 -0
  73. package/dist/evaluators/hallucination-detection.js.map +1 -0
  74. package/dist/evaluators/iac-security.d.ts.map +1 -1
  75. package/dist/evaluators/iac-security.js +18 -1
  76. package/dist/evaluators/iac-security.js.map +1 -1
  77. package/dist/evaluators/index.d.ts.map +1 -1
  78. package/dist/evaluators/index.js +18 -6
  79. package/dist/evaluators/index.js.map +1 -1
  80. package/dist/evaluators/maintainability.d.ts.map +1 -1
  81. package/dist/evaluators/maintainability.js +46 -0
  82. package/dist/evaluators/maintainability.js.map +1 -1
  83. package/dist/evaluators/observability.d.ts.map +1 -1
  84. package/dist/evaluators/observability.js +19 -1
  85. package/dist/evaluators/observability.js.map +1 -1
  86. package/dist/evaluators/reliability.d.ts.map +1 -1
  87. package/dist/evaluators/reliability.js +17 -1
  88. package/dist/evaluators/reliability.js.map +1 -1
  89. package/dist/evaluators/scalability.js +1 -1
  90. package/dist/evaluators/scalability.js.map +1 -1
  91. package/dist/evaluators/security.d.ts +13 -0
  92. package/dist/evaluators/security.d.ts.map +1 -0
  93. package/dist/evaluators/security.js +529 -0
  94. package/dist/evaluators/security.js.map +1 -0
  95. package/dist/evaluators/shared.d.ts.map +1 -1
  96. package/dist/evaluators/shared.js +15 -3
  97. package/dist/evaluators/shared.js.map +1 -1
  98. package/dist/evaluators/software-practices.d.ts.map +1 -1
  99. package/dist/evaluators/software-practices.js +20 -0
  100. package/dist/evaluators/software-practices.js.map +1 -1
  101. package/dist/evaluators/testing.d.ts.map +1 -1
  102. package/dist/evaluators/testing.js +3 -3
  103. package/dist/evaluators/testing.js.map +1 -1
  104. package/dist/evaluators/ux.d.ts.map +1 -1
  105. package/dist/evaluators/ux.js +10 -2
  106. package/dist/evaluators/ux.js.map +1 -1
  107. package/dist/github-app.d.ts +96 -0
  108. package/dist/github-app.d.ts.map +1 -0
  109. package/dist/github-app.js +541 -0
  110. package/dist/github-app.js.map +1 -0
  111. package/dist/index.js +8 -0
  112. package/dist/index.js.map +1 -1
  113. package/dist/judges/hallucination-detection.d.ts +3 -0
  114. package/dist/judges/hallucination-detection.d.ts.map +1 -0
  115. package/dist/judges/hallucination-detection.js +30 -0
  116. package/dist/judges/hallucination-detection.js.map +1 -0
  117. package/dist/judges/index.d.ts.map +1 -1
  118. package/dist/judges/index.js +8 -0
  119. package/dist/judges/index.js.map +1 -1
  120. package/dist/judges/security.d.ts +3 -0
  121. package/dist/judges/security.d.ts.map +1 -0
  122. package/dist/judges/security.js +28 -0
  123. package/dist/judges/security.js.map +1 -0
  124. package/dist/language-patterns.d.ts.map +1 -1
  125. package/dist/language-patterns.js +12 -4
  126. package/dist/language-patterns.js.map +1 -1
  127. package/dist/patches/index.d.ts.map +1 -1
  128. package/dist/patches/index.js +501 -0
  129. package/dist/patches/index.js.map +1 -1
  130. package/dist/types.d.ts +1 -1
  131. package/dist/types.d.ts.map +1 -1
  132. package/package.json +1 -1
  133. package/server.json +3 -3
@@ -0,0 +1,541 @@
1
+ /**
2
+ * Judges GitHub App — Zero-config PR review bot.
3
+ *
4
+ * A standalone webhook handler that automatically reviews pull requests
5
+ * when installed as a GitHub App. No workflow YAML needed in target repos.
6
+ *
7
+ * Deployment options:
8
+ * 1. `judges app serve --port 3000` → standalone HTTP server
9
+ * 2. Export `handleWebhook` for serverless (AWS Lambda, Azure Functions, Vercel)
10
+ * 3. Deploy via Docker: `docker run -p 3000:3000 judges app serve`
11
+ *
12
+ * Setup:
13
+ * 1. Create a GitHub App at https://github.com/settings/apps/new
14
+ * 2. Set webhook URL to your deployment endpoint
15
+ * 3. Grant permissions: pull_requests (read+write), contents (read), checks (write)
16
+ * 4. Subscribe to events: pull_request
17
+ * 5. Set environment variables:
18
+ * - JUDGES_APP_ID — GitHub App ID
19
+ * - JUDGES_PRIVATE_KEY — PEM private key (or path via JUDGES_PRIVATE_KEY_PATH)
20
+ * - JUDGES_WEBHOOK_SECRET — Webhook secret for signature verification
21
+ */
22
+ import { createHmac } from "crypto";
23
+ import { readFileSync, existsSync } from "fs";
24
+ import { createServer } from "http";
25
+ import { evaluateWithTribunal } from "./evaluators/index.js";
26
+ import { evaluateProject } from "./evaluators/project.js";
27
+ // ─── Language Detection ─────────────────────────────────────────────────────
28
+ const EXT_TO_LANG = {
29
+ ".ts": "typescript",
30
+ ".tsx": "typescript",
31
+ ".js": "javascript",
32
+ ".jsx": "javascript",
33
+ ".mjs": "javascript",
34
+ ".cjs": "javascript",
35
+ ".py": "python",
36
+ ".rs": "rust",
37
+ ".go": "go",
38
+ ".java": "java",
39
+ ".cs": "csharp",
40
+ ".rb": "ruby",
41
+ ".php": "php",
42
+ ".swift": "swift",
43
+ ".kt": "kotlin",
44
+ ".tf": "terraform",
45
+ ".hcl": "terraform",
46
+ ".bicep": "bicep",
47
+ ".sh": "bash",
48
+ ".ps1": "powershell",
49
+ ".c": "c",
50
+ ".cpp": "cpp",
51
+ ".h": "c",
52
+ ".hpp": "cpp",
53
+ };
54
+ function detectLanguage(filePath) {
55
+ const ext = filePath.toLowerCase().match(/\.[^.]+$/)?.[0] ?? "";
56
+ if (filePath.toLowerCase().includes("dockerfile"))
57
+ return "dockerfile";
58
+ return EXT_TO_LANG[ext];
59
+ }
60
+ // ─── JWT Generation (RS256, no dependencies) ───────────────────────────────
61
+ import { sign as cryptoSign, createPrivateKey } from "crypto";
62
+ function generateJwt(appId, privateKey) {
63
+ const now = Math.floor(Date.now() / 1000);
64
+ const header = Buffer.from(JSON.stringify({ alg: "RS256", typ: "JWT" })).toString("base64url");
65
+ const payload = Buffer.from(JSON.stringify({ iat: now - 60, exp: now + 600, iss: appId })).toString("base64url");
66
+ const signingInput = `${header}.${payload}`;
67
+ const key = createPrivateKey(privateKey);
68
+ const signature = cryptoSign("sha256", Buffer.from(signingInput), key).toString("base64url");
69
+ return `${signingInput}.${signature}`;
70
+ }
71
+ // ─── GitHub API Helper ──────────────────────────────────────────────────────
72
+ async function ghApi(method, path, token, body) {
73
+ const { default: https } = await import("https");
74
+ const payload = body ? JSON.stringify(body) : "";
75
+ return new Promise((resolve, reject) => {
76
+ const opts = {
77
+ hostname: "api.github.com",
78
+ path,
79
+ method,
80
+ headers: {
81
+ Authorization: `Bearer ${token}`,
82
+ Accept: "application/vnd.github.v3+json",
83
+ "User-Agent": "judges-github-app",
84
+ "Content-Type": "application/json",
85
+ ...(payload ? { "Content-Length": String(Buffer.byteLength(payload)) } : {}),
86
+ },
87
+ };
88
+ const req = https.request(opts, (res) => {
89
+ let data = "";
90
+ res.on("data", (chunk) => (data += chunk));
91
+ res.on("end", () => {
92
+ try {
93
+ resolve({ status: res.statusCode ?? 500, data: data ? JSON.parse(data) : null });
94
+ }
95
+ catch {
96
+ resolve({ status: res.statusCode ?? 500, data });
97
+ }
98
+ });
99
+ });
100
+ req.on("error", reject);
101
+ if (payload)
102
+ req.write(payload);
103
+ req.end();
104
+ });
105
+ }
106
+ // ─── Installation Token ─────────────────────────────────────────────────────
107
+ async function getInstallationToken(appId, privateKey, installationId) {
108
+ const jwt = generateJwt(appId, privateKey);
109
+ const res = await ghApi("POST", `/app/installations/${installationId}/access_tokens`, jwt);
110
+ const data = res.data;
111
+ if (!data?.token) {
112
+ throw new Error(`Failed to get installation token: ${JSON.stringify(res.data)}`);
113
+ }
114
+ return data.token;
115
+ }
116
+ // ─── Webhook Signature Verification ─────────────────────────────────────────
117
+ export function verifyWebhookSignature(payload, signature, secret) {
118
+ if (!signature)
119
+ return false;
120
+ const expected = `sha256=${createHmac("sha256", secret).update(payload).digest("hex")}`;
121
+ if (expected.length !== signature.length)
122
+ return false;
123
+ // Constant-time comparison
124
+ let mismatch = 0;
125
+ for (let i = 0; i < expected.length; i++) {
126
+ mismatch |= expected.charCodeAt(i) ^ signature.charCodeAt(i);
127
+ }
128
+ return mismatch === 0;
129
+ }
130
+ // ─── Diff Parsing ───────────────────────────────────────────────────────────
131
+ function parsePatchToHunk(filePath, patch) {
132
+ const lines = patch.split("\n");
133
+ const newLines = [];
134
+ const changedLineNumbers = [];
135
+ let newLineNum = 0;
136
+ for (const line of lines) {
137
+ const hunkMatch = line.match(/^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
138
+ if (hunkMatch) {
139
+ newLineNum = parseInt(hunkMatch[1], 10) - 1;
140
+ continue;
141
+ }
142
+ if (line.startsWith("-"))
143
+ continue; // Removed line — skip
144
+ if (line.startsWith("+")) {
145
+ newLineNum++;
146
+ newLines.push(line.slice(1));
147
+ changedLineNumbers.push(newLineNum);
148
+ }
149
+ else {
150
+ newLineNum++;
151
+ newLines.push(line.startsWith(" ") ? line.slice(1) : line);
152
+ }
153
+ }
154
+ return {
155
+ filePath,
156
+ newContent: newLines.join("\n"),
157
+ changedLines: changedLineNumbers,
158
+ };
159
+ }
160
+ // ─── Severity Helpers ───────────────────────────────────────────────────────
161
+ const SEVERITY_ORDER = ["critical", "high", "medium", "low", "info"];
162
+ function severityRank(s) {
163
+ return SEVERITY_ORDER.indexOf(s);
164
+ }
165
+ function meetsSeverityThreshold(severity, min) {
166
+ return severityRank(severity) <= severityRank(min);
167
+ }
168
+ const SEVERITY_ICON = {
169
+ critical: "🔴",
170
+ high: "🟠",
171
+ medium: "🟡",
172
+ low: "🔵",
173
+ info: "⚪",
174
+ };
175
+ // ─── Core Review Logic ──────────────────────────────────────────────────────
176
+ async function reviewPullRequest(payload, token, config) {
177
+ const pr = payload.pull_request;
178
+ const repo = payload.repository;
179
+ const repoFullName = repo.full_name;
180
+ const prNumber = pr.number;
181
+ const minSeverity = config.minSeverity ?? "medium";
182
+ const maxComments = config.maxComments ?? 25;
183
+ // Skip draft PRs
184
+ if (pr.draft) {
185
+ return { status: 200, body: "Skipped draft PR" };
186
+ }
187
+ // 1. Fetch PR files
188
+ const filesRes = await ghApi("GET", `/repos/${repoFullName}/pulls/${prNumber}/files?per_page=100`, token);
189
+ if (filesRes.status !== 200) {
190
+ return { status: 500, body: `Failed to fetch PR files: ${filesRes.status}` };
191
+ }
192
+ const prFiles = filesRes.data;
193
+ // 2. Evaluate each changed file
194
+ const allFindings = [];
195
+ for (const file of prFiles) {
196
+ if (file.status === "removed")
197
+ continue;
198
+ if (!file.patch)
199
+ continue;
200
+ const lang = detectLanguage(file.filename);
201
+ if (!lang)
202
+ continue;
203
+ const hunk = parsePatchToHunk(file.filename, file.patch);
204
+ if (!hunk.newContent.trim())
205
+ continue;
206
+ try {
207
+ const verdict = evaluateWithTribunal(hunk.newContent, lang, undefined, {
208
+ filePath: file.filename,
209
+ includeAstFindings: true,
210
+ });
211
+ const findings = verdict.findings || [];
212
+ for (const f of findings) {
213
+ // Only include findings on changed lines (if we have line numbers)
214
+ if (f.lineNumbers?.length) {
215
+ const onChangedLine = f.lineNumbers.some((ln) => hunk.changedLines.includes(ln));
216
+ if (!onChangedLine && config.diffOnly !== false)
217
+ continue;
218
+ }
219
+ if (!meetsSeverityThreshold(f.severity, minSeverity))
220
+ continue;
221
+ allFindings.push({ ...f, _file: file.filename, _changedLines: hunk.changedLines });
222
+ }
223
+ }
224
+ catch {
225
+ // Individual file failure should not block the entire review
226
+ continue;
227
+ }
228
+ }
229
+ // 2b. Cross-file architectural analysis (when 2+ files analyzed)
230
+ const projectFiles = [];
231
+ for (const file of prFiles) {
232
+ if (file.status === "removed" || !file.patch)
233
+ continue;
234
+ const lang = detectLanguage(file.filename);
235
+ if (!lang)
236
+ continue;
237
+ const hunk = parsePatchToHunk(file.filename, file.patch);
238
+ if (hunk.newContent.trim()) {
239
+ projectFiles.push({ path: file.filename, content: hunk.newContent, language: lang });
240
+ }
241
+ }
242
+ if (projectFiles.length >= 2) {
243
+ try {
244
+ const runner = { evaluateWithTribunal };
245
+ const projectVerdict = evaluateProject(runner, projectFiles);
246
+ for (const f of projectVerdict.architecturalFindings ?? []) {
247
+ if (!meetsSeverityThreshold(f.severity, minSeverity))
248
+ continue;
249
+ allFindings.push({ ...f, _file: projectFiles[0].path, _changedLines: [] });
250
+ }
251
+ }
252
+ catch {
253
+ // Cross-file failure should not block the review
254
+ }
255
+ }
256
+ // 3. Build review comments
257
+ const comments = [];
258
+ const seen = new Set();
259
+ // Sort by severity (critical first)
260
+ allFindings.sort((a, b) => severityRank(a.severity) - severityRank(b.severity));
261
+ for (const f of allFindings) {
262
+ if (comments.length >= maxComments)
263
+ break;
264
+ // When a patch spans multiple lines, position the comment at endLine
265
+ // and set start_line so the suggestion block covers the full range.
266
+ const line = f.patch?.endLine ?? f.lineNumbers?.[0] ?? 1;
267
+ const dedupKey = `${f.ruleId}::${f._file}::${line}`;
268
+ if (seen.has(dedupKey))
269
+ continue;
270
+ seen.add(dedupKey);
271
+ const icon = SEVERITY_ICON[f.severity] ?? "⚪";
272
+ let body = `${icon} **${f.severity.toUpperCase()}** \`${f.ruleId}\`: ${f.title}\n\n`;
273
+ body += `${f.description}\n\n`;
274
+ if (f.recommendation)
275
+ body += `**Recommendation:** ${f.recommendation}\n\n`;
276
+ // Prefer patch.newText for suggestion blocks (more precise)
277
+ if (f.patch) {
278
+ body += `**Suggested fix:**\n\`\`\`suggestion\n${f.patch.newText}\n\`\`\`\n`;
279
+ }
280
+ else if (f.suggestedFix) {
281
+ body += `**Suggested fix:**\n\`\`\`suggestion\n${f.suggestedFix}\n\`\`\`\n`;
282
+ }
283
+ if (f.reference)
284
+ body += `📚 ${f.reference}\n`;
285
+ if (f.confidence !== null && f.confidence !== undefined)
286
+ body += `\n_Confidence: ${Math.round(f.confidence * 100)}%_`;
287
+ const comment = { path: f._file, line, side: "RIGHT", body };
288
+ if (f.patch && f.patch.startLine < f.patch.endLine) {
289
+ comment.start_line = f.patch.startLine;
290
+ comment.start_side = "RIGHT";
291
+ }
292
+ comments.push(comment);
293
+ }
294
+ // 4. Dismiss previous Judges reviews
295
+ try {
296
+ const reviewsRes = await ghApi("GET", `/repos/${repoFullName}/pulls/${prNumber}/reviews`, token);
297
+ if (reviewsRes.status === 200 && Array.isArray(reviewsRes.data)) {
298
+ const oldReviews = reviewsRes.data.filter((r) => r.body?.includes("Judges Code Review") && (r.state === "COMMENTED" || r.state === "CHANGES_REQUESTED"));
299
+ for (const review of oldReviews) {
300
+ await ghApi("PUT", `/repos/${repoFullName}/pulls/${prNumber}/reviews/${review.id}/dismissals`, token, {
301
+ message: "Superseded by new Judges analysis",
302
+ }).catch(() => {
303
+ /* dismiss may fail without maintainer perms */
304
+ });
305
+ }
306
+ }
307
+ }
308
+ catch {
309
+ /* Non-critical — proceed with posting */
310
+ }
311
+ // 5. Post review
312
+ const criticalCount = allFindings.filter((f) => f.severity === "critical").length;
313
+ const highCount = allFindings.filter((f) => f.severity === "high").length;
314
+ const hasDangerousFindings = criticalCount > 0 || highCount > 0;
315
+ let reviewEvent = "COMMENT";
316
+ if (hasDangerousFindings) {
317
+ reviewEvent = "REQUEST_CHANGES";
318
+ }
319
+ else if (config.autoApprove && allFindings.length === 0) {
320
+ reviewEvent = "APPROVE";
321
+ }
322
+ const summaryLines = [
323
+ `## 🔍 Judges Code Review`,
324
+ "",
325
+ `| Metric | Value |`,
326
+ `|--------|-------|`,
327
+ `| Files analyzed | ${prFiles.filter((f) => f.status !== "removed" && detectLanguage(f.filename)).length} |`,
328
+ `| Findings | **${allFindings.length}** |`,
329
+ `| Critical | ${criticalCount} |`,
330
+ `| High | ${highCount} |`,
331
+ "",
332
+ ];
333
+ if (allFindings.length > maxComments) {
334
+ summaryLines.push(`> ⚠️ Showing top ${maxComments} of ${allFindings.length} findings.`);
335
+ }
336
+ if (allFindings.length === 0) {
337
+ summaryLines.push("✅ No findings — code looks good!");
338
+ }
339
+ const reviewBody = summaryLines.join("\n");
340
+ if (comments.length > 0) {
341
+ const reviewRes = await ghApi("POST", `/repos/${repoFullName}/pulls/${prNumber}/reviews`, token, {
342
+ event: reviewEvent,
343
+ body: reviewBody,
344
+ comments,
345
+ });
346
+ if (reviewRes.status < 200 || reviewRes.status >= 300) {
347
+ // Fallback: post as issue comment
348
+ await ghApi("POST", `/repos/${repoFullName}/issues/${prNumber}/comments`, token, {
349
+ body: reviewBody + "\n\n" + comments.map((c) => `- **${c.path}:${c.line}** — ${c.body}`).join("\n"),
350
+ });
351
+ }
352
+ }
353
+ else {
354
+ // Post summary even with no inline comments
355
+ await ghApi("POST", `/repos/${repoFullName}/pulls/${prNumber}/reviews`, token, {
356
+ event: reviewEvent,
357
+ body: reviewBody,
358
+ comments: [],
359
+ });
360
+ }
361
+ // 6. Create Check Run
362
+ const conclusion = hasDangerousFindings ? "failure" : allFindings.length > 0 ? "neutral" : "success";
363
+ const annotations = allFindings.slice(0, 50).map((f) => ({
364
+ path: f._file,
365
+ start_line: f.lineNumbers?.[0] ?? 1,
366
+ end_line: f.lineNumbers?.[0] ?? 1,
367
+ annotation_level: f.severity === "critical" || f.severity === "high"
368
+ ? "failure"
369
+ : f.severity === "medium"
370
+ ? "warning"
371
+ : "notice",
372
+ title: `${f.ruleId}: ${f.title}`,
373
+ message: `${f.description}${f.recommendation ? "\n\nRecommendation: " + f.recommendation : ""}`,
374
+ raw_details: f.suggestedFix ?? undefined,
375
+ }));
376
+ await ghApi("POST", `/repos/${repoFullName}/check-runs`, token, {
377
+ name: "Judges Code Review",
378
+ head_sha: pr.head.sha,
379
+ status: "completed",
380
+ conclusion,
381
+ output: {
382
+ title: `${allFindings.length} finding(s) — ${conclusion === "success" ? "PASS" : conclusion === "failure" ? "FAIL" : "WARNING"}`,
383
+ summary: `**${allFindings.length}** finding(s): ${criticalCount} critical, ${highCount} high`,
384
+ annotations,
385
+ },
386
+ });
387
+ return {
388
+ status: 200,
389
+ body: `Review posted: ${allFindings.length} findings, ${comments.length} comments`,
390
+ reviewPosted: true,
391
+ findingsCount: allFindings.length,
392
+ };
393
+ }
394
+ // ─── Webhook Handler ────────────────────────────────────────────────────────
395
+ /**
396
+ * Handle an incoming GitHub webhook event.
397
+ * This is the primary entry point — can be used in serverless functions,
398
+ * standalone servers, or test harnesses.
399
+ */
400
+ export async function handleWebhook(event, payload, signature, config) {
401
+ // 1. Verify signature
402
+ const rawPayload = typeof payload === "string" ? payload : JSON.stringify(payload);
403
+ if (!verifyWebhookSignature(rawPayload, signature, config.webhookSecret)) {
404
+ return { status: 401, body: "Invalid webhook signature" };
405
+ }
406
+ // 2. Parse payload
407
+ const data = typeof payload === "string" ? JSON.parse(payload) : payload;
408
+ // 3. Only handle pull_request events
409
+ if (event !== "pull_request") {
410
+ return { status: 200, body: `Ignored event: ${event}` };
411
+ }
412
+ // 4. Only handle opened/synchronize
413
+ if (!["opened", "synchronize", "reopened"].includes(data.action)) {
414
+ return { status: 200, body: `Ignored action: ${data.action}` };
415
+ }
416
+ if (!data.pull_request || !data.repository || !data.installation) {
417
+ return { status: 400, body: "Missing pull_request, repository, or installation in payload" };
418
+ }
419
+ // 5. Get installation token
420
+ const installationToken = await getInstallationToken(config.appId, config.privateKey, data.installation.id);
421
+ // 6. Run the review
422
+ return reviewPullRequest(data, installationToken, config);
423
+ }
424
+ // ─── App Configuration Loader ───────────────────────────────────────────────
425
+ export function loadAppConfig() {
426
+ const appId = process.env.JUDGES_APP_ID;
427
+ const webhookSecret = process.env.JUDGES_WEBHOOK_SECRET ?? "";
428
+ // Load private key from env or file
429
+ let privateKey = process.env.JUDGES_PRIVATE_KEY ?? "";
430
+ if (!privateKey) {
431
+ const keyPath = process.env.JUDGES_PRIVATE_KEY_PATH;
432
+ if (keyPath && existsSync(keyPath)) {
433
+ privateKey = readFileSync(keyPath, "utf8");
434
+ }
435
+ }
436
+ if (!appId)
437
+ throw new Error("JUDGES_APP_ID environment variable is required");
438
+ if (!privateKey)
439
+ throw new Error("JUDGES_PRIVATE_KEY or JUDGES_PRIVATE_KEY_PATH is required");
440
+ if (!webhookSecret)
441
+ throw new Error("JUDGES_WEBHOOK_SECRET environment variable is required");
442
+ return {
443
+ appId,
444
+ privateKey,
445
+ webhookSecret,
446
+ port: parseInt(process.env.JUDGES_APP_PORT ?? "3000", 10),
447
+ minSeverity: process.env.JUDGES_MIN_SEVERITY ?? "medium",
448
+ maxComments: parseInt(process.env.JUDGES_MAX_COMMENTS ?? "25", 10),
449
+ autoApprove: process.env.JUDGES_AUTO_APPROVE === "true",
450
+ diffOnly: process.env.JUDGES_DIFF_ONLY !== "false",
451
+ configPath: process.env.JUDGES_CONFIG_PATH,
452
+ };
453
+ }
454
+ // ─── Standalone HTTP Server ─────────────────────────────────────────────────
455
+ /**
456
+ * Start a standalone HTTP server that listens for GitHub webhooks.
457
+ * Usage: `judges app serve --port 3000`
458
+ */
459
+ export function startAppServer(config) {
460
+ const port = config.port ?? 3000;
461
+ const server = createServer(async (req, res) => {
462
+ // Health check
463
+ if (req.url === "/health" && req.method === "GET") {
464
+ res.writeHead(200, { "Content-Type": "application/json" });
465
+ res.end(JSON.stringify({ status: "ok", app: "judges-github-app" }));
466
+ return;
467
+ }
468
+ // Webhook endpoint
469
+ if (req.url === "/webhook" && req.method === "POST") {
470
+ const chunks = [];
471
+ req.on("data", (chunk) => chunks.push(chunk));
472
+ req.on("end", async () => {
473
+ const body = Buffer.concat(chunks).toString("utf8");
474
+ const event = req.headers["x-github-event"] ?? "";
475
+ const signature = req.headers["x-hub-signature-256"] ?? undefined;
476
+ try {
477
+ const result = await handleWebhook(event, body, signature, config);
478
+ res.writeHead(result.status, { "Content-Type": "application/json" });
479
+ res.end(JSON.stringify(result));
480
+ }
481
+ catch (err) {
482
+ const msg = err instanceof Error ? err.message : String(err);
483
+ console.error("Webhook handler error:", msg);
484
+ res.writeHead(500, { "Content-Type": "application/json" });
485
+ res.end(JSON.stringify({ status: 500, body: `Internal error: ${msg}` }));
486
+ }
487
+ });
488
+ return;
489
+ }
490
+ // 404 for everything else
491
+ res.writeHead(404, { "Content-Type": "application/json" });
492
+ res.end(JSON.stringify({ error: "Not found. POST to /webhook for GitHub events." }));
493
+ });
494
+ server.listen(port, () => {
495
+ console.log(`🔍 Judges GitHub App listening on port ${port}`);
496
+ console.log(` Webhook URL: http://localhost:${port}/webhook`);
497
+ console.log(` Health check: http://localhost:${port}/health`);
498
+ });
499
+ }
500
+ // ─── CLI Command ────────────────────────────────────────────────────────────
501
+ /**
502
+ * `judges app serve` — Start the GitHub App webhook server.
503
+ */
504
+ export function runAppCommand(args) {
505
+ const subcommand = args[0];
506
+ if (subcommand === "serve") {
507
+ const config = loadAppConfig();
508
+ const portIdx = args.indexOf("--port");
509
+ if (portIdx !== -1 && args[portIdx + 1]) {
510
+ config.port = parseInt(args[portIdx + 1], 10);
511
+ }
512
+ startAppServer(config);
513
+ }
514
+ else {
515
+ console.log(`Judges GitHub App
516
+
517
+ Usage:
518
+ judges app serve [--port 3000] Start webhook server
519
+
520
+ Environment variables:
521
+ JUDGES_APP_ID GitHub App ID (required)
522
+ JUDGES_PRIVATE_KEY PEM private key content (required, or use _PATH)
523
+ JUDGES_PRIVATE_KEY_PATH Path to PEM private key file
524
+ JUDGES_WEBHOOK_SECRET Webhook secret (required)
525
+ JUDGES_APP_PORT Server port (default: 3000)
526
+ JUDGES_MIN_SEVERITY Minimum severity to report (default: medium)
527
+ JUDGES_MAX_COMMENTS Max inline comments per review (default: 25)
528
+ JUDGES_AUTO_APPROVE Auto-approve clean PRs (default: false)
529
+ JUDGES_DIFF_ONLY Only analyze changed lines (default: true)
530
+
531
+ Setup guide:
532
+ 1. Create a GitHub App at https://github.com/settings/apps/new
533
+ 2. Permissions: pull_requests (read+write), contents (read), checks (write)
534
+ 3. Subscribe to: pull_request events
535
+ 4. Set webhook URL to: https://your-host/webhook
536
+ 5. Set environment variables above
537
+ 6. Run: judges app serve
538
+ `);
539
+ }
540
+ }
541
+ //# sourceMappingURL=github-app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-app.js","sourceRoot":"","sources":["../src/github-app.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -39,6 +39,14 @@ const cliCommands = new Set([
39
39
  "pack",
40
40
  "config",
41
41
  "compare",
42
+ "review",
43
+ "tune",
44
+ "app",
45
+ "trend",
46
+ "doctor",
47
+ "scaffold-plugin",
48
+ "lsp",
49
+ "version",
42
50
  ]);
43
51
  const cliFlags = new Set(["--help", "-h", "--file", "-f", "--version", "-v"]);
44
52
  const firstArg = process.argv[2];
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { JudgeDefinition } from "../types.js";
2
+ export declare const hallucinationDetectionJudge: JudgeDefinition;
3
+ //# sourceMappingURL=hallucination-detection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hallucination-detection.d.ts","sourceRoot":"","sources":["../../src/judges/hallucination-detection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,eAAO,MAAM,2BAA2B,EAAE,eA6BzC,CAAC"}
@@ -0,0 +1,30 @@
1
+ export const hallucinationDetectionJudge = {
2
+ id: "hallucination-detection",
3
+ name: "Judge Hallucination Detection",
4
+ domain: "AI-Hallucinated API & Import Validation",
5
+ description: "Detects APIs, imports, methods, and patterns that are commonly hallucinated by AI code generators — non-existent standard library functions, fabricated package names, phantom methods, and incorrect API signatures that look plausible but don't exist.",
6
+ rulePrefix: "HALLU",
7
+ systemPrompt: `You are Judge Hallucination Detection — a specialist in identifying APIs, imports, and code patterns that large language models frequently fabricate.
8
+
9
+ YOUR EVALUATION CRITERIA:
10
+ 1. **Non-existent Standard Library APIs**: Does the code call functions or methods that don't exist in the language's standard library (e.g., fs.readFileAsync in Node.js, json.parse in Python, String.new() in Rust)?
11
+ 2. **Fabricated Package Imports**: Does the code import from packages that don't exist on the language's package registry (npm, PyPI, crates.io)?
12
+ 3. **Phantom Methods**: Does the code call methods on objects that don't support them (e.g., Array.flat(callback), Promise.resolve().delay())?
13
+ 4. **API Signature Errors**: Are APIs called with incorrect parameter types or counts that would fail at runtime?
14
+ 5. **Cross-language API Confusion**: Are APIs from one language hallucinated into another (e.g., .push() in Python, .contains() in JavaScript, printf-style formatting in Kotlin)?
15
+ 6. **Invalid Submodule Imports**: Does the code import non-existent exports from known packages (e.g., importing useAuth from 'react', importing cors from 'express')?
16
+ 7. **Anti-pattern Generation**: Does the code contain common LLM anti-patterns like async inside Promise constructors or unnecessary error wrapping?
17
+ 8. **Fabricated Utility Names**: Does the code reference utility functions with names that follow LLM naming conventions but don't exist in any installed package?
18
+
19
+ SEVERITY MAPPING:
20
+ - **critical**: Fabricated security-critical API (crypto, auth, sanitization)
21
+ - **high**: Non-existent API call that will cause runtime errors
22
+ - **medium**: Anti-patterns or suspicious API usage that may work but is incorrect
23
+ - **low**: Style issues from AI pattern confusion
24
+
25
+ Each finding must include:
26
+ - The exact hallucinated API/import
27
+ - Why it doesn't exist or is incorrect
28
+ - The correct alternative to use`,
29
+ };
30
+ //# sourceMappingURL=hallucination-detection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hallucination-detection.js","sourceRoot":"","sources":["../../src/judges/hallucination-detection.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,2BAA2B,GAAoB;IAC1D,EAAE,EAAE,yBAAyB;IAC7B,IAAI,EAAE,+BAA+B;IACrC,MAAM,EAAE,yCAAyC;IACjD,WAAW,EACT,2PAA2P;IAC7P,UAAU,EAAE,OAAO;IACnB,YAAY,EAAE;;;;;;;;;;;;;;;;;;;;;iCAqBiB;CAChC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/judges/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAqHnD;;;;;;GAMG;AACH,eAAO,MAAM,MAAM,EAAE,eAAe,EAsCnC,CAAC;AAEF;;GAEG;AACH,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAEhE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,KAAK,CAAC;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC,CAOD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/judges/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AA2HnD;;;;;;GAMG;AACH,eAAO,MAAM,MAAM,EAAE,eAAe,EAwCnC,CAAC;AAEF;;GAEG;AACH,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAEhE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,KAAK,CAAC;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC,CAOD"}