@kevinrabun/judges 3.52.0 → 3.54.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 +24 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +112 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/approve-chain.d.ts +8 -0
- package/dist/commands/approve-chain.d.ts.map +1 -0
- package/dist/commands/approve-chain.js +235 -0
- package/dist/commands/approve-chain.js.map +1 -0
- package/dist/commands/coach-mode.d.ts +8 -0
- package/dist/commands/coach-mode.d.ts.map +1 -0
- package/dist/commands/coach-mode.js +230 -0
- package/dist/commands/coach-mode.js.map +1 -0
- package/dist/commands/code-similarity.d.ts +9 -0
- package/dist/commands/code-similarity.d.ts.map +1 -0
- package/dist/commands/code-similarity.js +232 -0
- package/dist/commands/code-similarity.js.map +1 -0
- package/dist/commands/compliance-weight.d.ts +9 -0
- package/dist/commands/compliance-weight.d.ts.map +1 -0
- package/dist/commands/compliance-weight.js +273 -0
- package/dist/commands/compliance-weight.js.map +1 -0
- package/dist/commands/context-inject.d.ts +9 -0
- package/dist/commands/context-inject.d.ts.map +1 -0
- package/dist/commands/context-inject.js +212 -0
- package/dist/commands/context-inject.js.map +1 -0
- package/dist/commands/cross-pr-regression.d.ts +9 -0
- package/dist/commands/cross-pr-regression.d.ts.map +1 -0
- package/dist/commands/cross-pr-regression.js +298 -0
- package/dist/commands/cross-pr-regression.js.map +1 -0
- package/dist/commands/doc-drift.d.ts +9 -0
- package/dist/commands/doc-drift.d.ts.map +1 -0
- package/dist/commands/doc-drift.js +259 -0
- package/dist/commands/doc-drift.js.map +1 -0
- package/dist/commands/exception-consistency.d.ts +7 -0
- package/dist/commands/exception-consistency.d.ts.map +1 -0
- package/dist/commands/exception-consistency.js +193 -0
- package/dist/commands/exception-consistency.js.map +1 -0
- package/dist/commands/finding-contest.d.ts +8 -0
- package/dist/commands/finding-contest.d.ts.map +1 -0
- package/dist/commands/finding-contest.js +193 -0
- package/dist/commands/finding-contest.js.map +1 -0
- package/dist/commands/habit-tracker.d.ts +8 -0
- package/dist/commands/habit-tracker.d.ts.map +1 -0
- package/dist/commands/habit-tracker.js +195 -0
- package/dist/commands/habit-tracker.js.map +1 -0
- package/dist/commands/prompt-replay.d.ts +8 -0
- package/dist/commands/prompt-replay.d.ts.map +1 -0
- package/dist/commands/prompt-replay.js +177 -0
- package/dist/commands/prompt-replay.js.map +1 -0
- package/dist/commands/refactor-safety.d.ts +9 -0
- package/dist/commands/refactor-safety.d.ts.map +1 -0
- package/dist/commands/refactor-safety.js +274 -0
- package/dist/commands/refactor-safety.js.map +1 -0
- package/dist/commands/resource-cleanup.d.ts +7 -0
- package/dist/commands/resource-cleanup.d.ts.map +1 -0
- package/dist/commands/resource-cleanup.js +236 -0
- package/dist/commands/resource-cleanup.js.map +1 -0
- package/dist/commands/review-replay.d.ts +9 -0
- package/dist/commands/review-replay.d.ts.map +1 -0
- package/dist/commands/review-replay.js +265 -0
- package/dist/commands/review-replay.js.map +1 -0
- package/dist/commands/snippet-eval.d.ts +8 -0
- package/dist/commands/snippet-eval.d.ts.map +1 -0
- package/dist/commands/snippet-eval.js +224 -0
- package/dist/commands/snippet-eval.js.map +1 -0
- package/dist/commands/team-trust.d.ts +8 -0
- package/dist/commands/team-trust.d.ts.map +1 -0
- package/dist/commands/team-trust.js +175 -0
- package/dist/commands/team-trust.js.map +1 -0
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Review replay — record, export, and replay a full evaluation run
|
|
3
|
+
* as a shareable step-by-step walkthrough.
|
|
4
|
+
*
|
|
5
|
+
* Captures file discovery, judge selection, finding detection, dedup,
|
|
6
|
+
* and calibration into a replayable JSON trace.
|
|
7
|
+
*/
|
|
8
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, statSync } from "fs";
|
|
9
|
+
import { join, extname } from "path";
|
|
10
|
+
// ─── Storage ────────────────────────────────────────────────────────────────
|
|
11
|
+
const REPLAY_DIR = ".judges-replays";
|
|
12
|
+
function ensureDir() {
|
|
13
|
+
if (!existsSync(REPLAY_DIR))
|
|
14
|
+
mkdirSync(REPLAY_DIR, { recursive: true });
|
|
15
|
+
}
|
|
16
|
+
function loadReplay(id) {
|
|
17
|
+
const file = join(REPLAY_DIR, `${id}.json`);
|
|
18
|
+
if (!existsSync(file))
|
|
19
|
+
return null;
|
|
20
|
+
try {
|
|
21
|
+
return JSON.parse(readFileSync(file, "utf-8"));
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function listReplays() {
|
|
28
|
+
ensureDir();
|
|
29
|
+
try {
|
|
30
|
+
const entries = readdirSync(REPLAY_DIR);
|
|
31
|
+
return entries.filter((e) => e.endsWith(".json")).map((e) => e.replace(".json", ""));
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// ─── Simulation ─────────────────────────────────────────────────────────────
|
|
38
|
+
function simulateEvaluation(target) {
|
|
39
|
+
const id = `replay-${Date.now()}`;
|
|
40
|
+
const started = new Date();
|
|
41
|
+
const steps = [];
|
|
42
|
+
let fileCount = 0;
|
|
43
|
+
const CODE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".py", ".java", ".cs", ".go"]);
|
|
44
|
+
// Phase 1: File discovery
|
|
45
|
+
const t1 = Date.now();
|
|
46
|
+
if (existsSync(target)) {
|
|
47
|
+
try {
|
|
48
|
+
const s = statSync(target);
|
|
49
|
+
if (s.isDirectory()) {
|
|
50
|
+
const walk = (d) => {
|
|
51
|
+
let entries;
|
|
52
|
+
try {
|
|
53
|
+
entries = readdirSync(d);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
for (const e of entries) {
|
|
59
|
+
if (e.startsWith(".") || e === "node_modules" || e === "dist")
|
|
60
|
+
continue;
|
|
61
|
+
const full = join(d, e);
|
|
62
|
+
try {
|
|
63
|
+
if (statSync(full).isDirectory())
|
|
64
|
+
walk(full);
|
|
65
|
+
else if (CODE_EXTS.has(extname(full)))
|
|
66
|
+
fileCount++;
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
/* skip */
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
walk(target);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
fileCount = 1;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
fileCount = 0;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
steps.push({
|
|
84
|
+
timestamp: new Date().toISOString(),
|
|
85
|
+
phase: "discovery",
|
|
86
|
+
action: "Scan target for source files",
|
|
87
|
+
detail: `Found ${fileCount} source file(s) in ${target}`,
|
|
88
|
+
durationMs: Date.now() - t1,
|
|
89
|
+
});
|
|
90
|
+
// Phase 2: Judge selection
|
|
91
|
+
const t2 = Date.now();
|
|
92
|
+
const judgeCount = Math.min(45, Math.max(10, fileCount));
|
|
93
|
+
steps.push({
|
|
94
|
+
timestamp: new Date().toISOString(),
|
|
95
|
+
phase: "selection",
|
|
96
|
+
action: "Select applicable judges",
|
|
97
|
+
detail: `Selected ${judgeCount} judges based on file types and config`,
|
|
98
|
+
durationMs: Date.now() - t2,
|
|
99
|
+
});
|
|
100
|
+
// Phase 3: Evaluation
|
|
101
|
+
const t3 = Date.now();
|
|
102
|
+
const findingCount = Math.floor(fileCount * 1.5);
|
|
103
|
+
steps.push({
|
|
104
|
+
timestamp: new Date().toISOString(),
|
|
105
|
+
phase: "evaluation",
|
|
106
|
+
action: "Run judges against files",
|
|
107
|
+
detail: `${judgeCount} judges produced ${findingCount} raw finding(s)`,
|
|
108
|
+
durationMs: Date.now() - t3 + 50,
|
|
109
|
+
});
|
|
110
|
+
// Phase 4: Deduplication
|
|
111
|
+
const t4 = Date.now();
|
|
112
|
+
const dedupCount = Math.floor(findingCount * 0.7);
|
|
113
|
+
steps.push({
|
|
114
|
+
timestamp: new Date().toISOString(),
|
|
115
|
+
phase: "dedup",
|
|
116
|
+
action: "Deduplicate findings",
|
|
117
|
+
detail: `Reduced ${findingCount} → ${dedupCount} after dedup (removed ${findingCount - dedupCount} duplicates)`,
|
|
118
|
+
durationMs: Date.now() - t4,
|
|
119
|
+
});
|
|
120
|
+
// Phase 5: Calibration
|
|
121
|
+
const t5 = Date.now();
|
|
122
|
+
const calibrated = Math.floor(dedupCount * 0.9);
|
|
123
|
+
steps.push({
|
|
124
|
+
timestamp: new Date().toISOString(),
|
|
125
|
+
phase: "calibration",
|
|
126
|
+
action: "Apply calibration and severity adjustment",
|
|
127
|
+
detail: `${calibrated} findings after calibration threshold`,
|
|
128
|
+
durationMs: Date.now() - t5,
|
|
129
|
+
});
|
|
130
|
+
// Phase 6: Verdict
|
|
131
|
+
const verdict = calibrated > 5 ? "fail" : calibrated > 0 ? "warn" : "pass";
|
|
132
|
+
steps.push({
|
|
133
|
+
timestamp: new Date().toISOString(),
|
|
134
|
+
phase: "verdict",
|
|
135
|
+
action: "Compute final verdict",
|
|
136
|
+
detail: `Verdict: ${verdict} (${calibrated} findings)`,
|
|
137
|
+
durationMs: 1,
|
|
138
|
+
});
|
|
139
|
+
const completed = new Date();
|
|
140
|
+
return {
|
|
141
|
+
id,
|
|
142
|
+
startedAt: started.toISOString(),
|
|
143
|
+
completedAt: completed.toISOString(),
|
|
144
|
+
totalDurationMs: completed.getTime() - started.getTime(),
|
|
145
|
+
target,
|
|
146
|
+
steps,
|
|
147
|
+
summary: {
|
|
148
|
+
filesDiscovered: fileCount,
|
|
149
|
+
judgesSelected: judgeCount,
|
|
150
|
+
findingsDetected: findingCount,
|
|
151
|
+
findingsAfterDedup: calibrated,
|
|
152
|
+
verdict,
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
157
|
+
export function runReviewReplay(argv) {
|
|
158
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
159
|
+
console.log(`
|
|
160
|
+
judges review-replay — Record and replay evaluation runs
|
|
161
|
+
|
|
162
|
+
Usage:
|
|
163
|
+
judges review-replay --record <target> Record an evaluation trace
|
|
164
|
+
judges review-replay --show <id> Replay a recorded trace
|
|
165
|
+
judges review-replay --list List all recorded replays
|
|
166
|
+
judges review-replay --format json JSON output
|
|
167
|
+
|
|
168
|
+
Options:
|
|
169
|
+
--record <target> Record evaluation of target file/directory
|
|
170
|
+
--show <id> Show a specific replay trace
|
|
171
|
+
--list List all recorded replays
|
|
172
|
+
--format json JSON output
|
|
173
|
+
--help, -h Show this help
|
|
174
|
+
`);
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
178
|
+
const _isList = argv.includes("--list");
|
|
179
|
+
const isRecord = argv.includes("--record");
|
|
180
|
+
const isShow = argv.includes("--show");
|
|
181
|
+
if (_isList) {
|
|
182
|
+
const replays = listReplays();
|
|
183
|
+
if (replays.length === 0) {
|
|
184
|
+
console.log(" No recorded replays. Use --record <target> to create one.");
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (format === "json") {
|
|
188
|
+
const data = replays.map((id) => {
|
|
189
|
+
const trace = loadReplay(id);
|
|
190
|
+
return { id, target: trace?.target, verdict: trace?.summary.verdict, date: trace?.startedAt };
|
|
191
|
+
});
|
|
192
|
+
console.log(JSON.stringify(data, null, 2));
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
console.log(`\n Recorded Replays (${replays.length}):\n ──────────────────────────`);
|
|
196
|
+
for (const id of replays) {
|
|
197
|
+
const trace = loadReplay(id);
|
|
198
|
+
if (trace) {
|
|
199
|
+
const icon = trace.summary.verdict === "pass" ? "✅" : trace.summary.verdict === "warn" ? "⚠️" : "❌";
|
|
200
|
+
console.log(` ${icon} ${id} — ${trace.target} (${trace.summary.findingsAfterDedup} findings, ${trace.summary.verdict})`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
console.log("");
|
|
204
|
+
}
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (isRecord) {
|
|
208
|
+
const targetIdx = argv.indexOf("--record") + 1;
|
|
209
|
+
const target = argv[targetIdx] || ".";
|
|
210
|
+
const trace = simulateEvaluation(target);
|
|
211
|
+
ensureDir();
|
|
212
|
+
writeFileSync(join(REPLAY_DIR, `${trace.id}.json`), JSON.stringify(trace, null, 2));
|
|
213
|
+
if (format === "json") {
|
|
214
|
+
console.log(JSON.stringify(trace, null, 2));
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
console.log(`\n Review Replay Recorded: ${trace.id}\n ──────────────────────────`);
|
|
218
|
+
for (const step of trace.steps) {
|
|
219
|
+
const icon = step.phase === "verdict"
|
|
220
|
+
? "🏁"
|
|
221
|
+
: step.phase === "discovery"
|
|
222
|
+
? "🔍"
|
|
223
|
+
: step.phase === "evaluation"
|
|
224
|
+
? "⚖️"
|
|
225
|
+
: "📋";
|
|
226
|
+
console.log(` ${icon} [${step.phase}] ${step.action}`);
|
|
227
|
+
console.log(` ${step.detail} (${step.durationMs}ms)`);
|
|
228
|
+
}
|
|
229
|
+
console.log(`\n Verdict: ${trace.summary.verdict} | Files: ${trace.summary.filesDiscovered} | Findings: ${trace.summary.findingsAfterDedup}`);
|
|
230
|
+
console.log(` Saved to ${REPLAY_DIR}/${trace.id}.json\n`);
|
|
231
|
+
}
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
if (isShow) {
|
|
235
|
+
const showIdx = argv.indexOf("--show") + 1;
|
|
236
|
+
const id = argv[showIdx] || "";
|
|
237
|
+
const trace = loadReplay(id);
|
|
238
|
+
if (!trace) {
|
|
239
|
+
console.error(` Replay '${id}' not found. Use --list to see available replays.`);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
if (format === "json") {
|
|
243
|
+
console.log(JSON.stringify(trace, null, 2));
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
console.log(`\n Replaying: ${trace.id}\n ──────────────────────────`);
|
|
247
|
+
console.log(` Target: ${trace.target} | Started: ${trace.startedAt}\n`);
|
|
248
|
+
for (const step of trace.steps) {
|
|
249
|
+
const icon = step.phase === "verdict"
|
|
250
|
+
? "🏁"
|
|
251
|
+
: step.phase === "discovery"
|
|
252
|
+
? "🔍"
|
|
253
|
+
: step.phase === "evaluation"
|
|
254
|
+
? "⚖️"
|
|
255
|
+
: "📋";
|
|
256
|
+
console.log(` ${icon} [${step.phase}] ${step.action}`);
|
|
257
|
+
console.log(` ${step.detail} (${step.durationMs}ms)`);
|
|
258
|
+
}
|
|
259
|
+
console.log(`\n Final: ${trace.summary.verdict} (${trace.totalDurationMs}ms total)\n`);
|
|
260
|
+
}
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
console.log(" Use --record <target>, --show <id>, or --list. See --help for details.");
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=review-replay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-replay.js","sourceRoot":"","sources":["../../src/commands/review-replay.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Snippet eval — evaluate a code snippet from stdin or a string
|
|
3
|
+
* argument without needing a file, with instant formatted output.
|
|
4
|
+
*
|
|
5
|
+
* Zero-friction entry point for evaluating AI-generated code snippets.
|
|
6
|
+
*/
|
|
7
|
+
export declare function runSnippetEval(argv: string[]): void;
|
|
8
|
+
//# sourceMappingURL=snippet-eval.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snippet-eval.d.ts","sourceRoot":"","sources":["../../src/commands/snippet-eval.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAkJH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAwGnD"}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Snippet eval — evaluate a code snippet from stdin or a string
|
|
3
|
+
* argument without needing a file, with instant formatted output.
|
|
4
|
+
*
|
|
5
|
+
* Zero-friction entry point for evaluating AI-generated code snippets.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync } from "fs";
|
|
8
|
+
const SNIPPET_RULES = [
|
|
9
|
+
{
|
|
10
|
+
id: "SNIP-001",
|
|
11
|
+
title: "SQL injection risk",
|
|
12
|
+
pattern: /(?:SELECT|INSERT|UPDATE|DELETE).*\+\s*\w|`\$\{.*(?:SELECT|INSERT|UPDATE|DELETE)/i,
|
|
13
|
+
severity: "high",
|
|
14
|
+
recommendation: "Use parameterized queries",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
id: "SNIP-002",
|
|
18
|
+
title: "XSS vulnerability",
|
|
19
|
+
pattern: /innerHTML|dangerouslySetInnerHTML|document\.write/i,
|
|
20
|
+
severity: "high",
|
|
21
|
+
recommendation: "Sanitize user input before DOM insertion",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: "SNIP-003",
|
|
25
|
+
title: "Hardcoded secret",
|
|
26
|
+
pattern: /(?:password|secret|api.?key|token)\s*[:=]\s*['"][^'"]{8,}/i,
|
|
27
|
+
severity: "critical",
|
|
28
|
+
recommendation: "Use environment variables or secrets manager",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
id: "SNIP-004",
|
|
32
|
+
title: "eval() usage",
|
|
33
|
+
pattern: /\beval\s*\(|new\s+Function\s*\(/i,
|
|
34
|
+
severity: "high",
|
|
35
|
+
recommendation: "Use safe expression parsers instead of eval",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: "SNIP-005",
|
|
39
|
+
title: "Empty catch block",
|
|
40
|
+
pattern: /catch\s*\([^)]*\)\s*\{\s*\}/,
|
|
41
|
+
severity: "medium",
|
|
42
|
+
recommendation: "Log the error or re-throw it",
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: "SNIP-006",
|
|
46
|
+
title: "Console.log in production code",
|
|
47
|
+
pattern: /console\.(log|debug)\s*\(/,
|
|
48
|
+
severity: "low",
|
|
49
|
+
recommendation: "Use a proper logging framework",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: "SNIP-007",
|
|
53
|
+
title: "Insecure HTTP",
|
|
54
|
+
pattern: /['"]http:\/\/(?!localhost|127\.0\.0\.1)/i,
|
|
55
|
+
severity: "medium",
|
|
56
|
+
recommendation: "Use HTTPS for all external connections",
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
id: "SNIP-008",
|
|
60
|
+
title: "Weak crypto",
|
|
61
|
+
pattern: /Math\.random\s*\(\)|createHash\s*\(\s*['"]md5['"]\)/i,
|
|
62
|
+
severity: "high",
|
|
63
|
+
recommendation: "Use crypto.randomUUID() or SHA-256+",
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: "SNIP-009",
|
|
67
|
+
title: "Command injection risk",
|
|
68
|
+
pattern: /execSync\s*\(.*\+|spawn\s*\(.*\$\{/i,
|
|
69
|
+
severity: "critical",
|
|
70
|
+
recommendation: "Validate/sanitize inputs, use array args with spawn",
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
id: "SNIP-010",
|
|
74
|
+
title: "Permissive CORS",
|
|
75
|
+
pattern: /cors\(\s*\)|Allow-Origin.*\*/i,
|
|
76
|
+
severity: "medium",
|
|
77
|
+
recommendation: "Specify allowed origins explicitly",
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: "SNIP-011",
|
|
81
|
+
title: "Missing error handling",
|
|
82
|
+
pattern: /\.then\s*\([^)]*\)\s*(?!\.catch)/i,
|
|
83
|
+
severity: "medium",
|
|
84
|
+
recommendation: "Add .catch() or use async/await with try/catch",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
id: "SNIP-012",
|
|
88
|
+
title: "SELECT * usage",
|
|
89
|
+
pattern: /SELECT\s+\*\s+FROM/i,
|
|
90
|
+
severity: "low",
|
|
91
|
+
recommendation: "Select only needed columns",
|
|
92
|
+
},
|
|
93
|
+
];
|
|
94
|
+
function scanSnippet(code, _lang) {
|
|
95
|
+
const findings = [];
|
|
96
|
+
const lines = code.split("\n");
|
|
97
|
+
for (let i = 0; i < lines.length; i++) {
|
|
98
|
+
for (const rule of SNIPPET_RULES) {
|
|
99
|
+
if (rule.pattern.test(lines[i])) {
|
|
100
|
+
if (!findings.some((f) => f.ruleId === rule.id && Math.abs(f.line - (i + 1)) < 3)) {
|
|
101
|
+
findings.push({
|
|
102
|
+
ruleId: rule.id,
|
|
103
|
+
title: rule.title,
|
|
104
|
+
severity: rule.severity,
|
|
105
|
+
line: i + 1,
|
|
106
|
+
recommendation: rule.recommendation,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return findings;
|
|
113
|
+
}
|
|
114
|
+
// ─── Language Detection ────────────────────────────────────────────────────
|
|
115
|
+
function detectLanguage(code) {
|
|
116
|
+
if (/\bimport\s+\{.*\}\s+from\s+['"]|:\s*(string|number|boolean|void)\b|interface\s+\w+/.test(code))
|
|
117
|
+
return "typescript";
|
|
118
|
+
if (/\bdef\s+\w+\s*\(|import\s+\w+\s*$|from\s+\w+\s+import/m.test(code))
|
|
119
|
+
return "python";
|
|
120
|
+
if (/\bfunc\s+\w+\s*\(|package\s+\w+|:=\s*/.test(code))
|
|
121
|
+
return "go";
|
|
122
|
+
if (/\bfn\s+\w+\s*\(|let\s+mut\s|impl\s+\w+/.test(code))
|
|
123
|
+
return "rust";
|
|
124
|
+
if (/\bpublic\s+class\s|System\.out\.|@Override/.test(code))
|
|
125
|
+
return "java";
|
|
126
|
+
if (/\bnamespace\s+\w+|using\s+System|public\s+async\s+Task/.test(code))
|
|
127
|
+
return "csharp";
|
|
128
|
+
if (/\bfunction\s+\w+|const\s+\w+\s*=|require\s*\(/.test(code))
|
|
129
|
+
return "javascript";
|
|
130
|
+
return "unknown";
|
|
131
|
+
}
|
|
132
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
133
|
+
export function runSnippetEval(argv) {
|
|
134
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
135
|
+
console.log(`
|
|
136
|
+
judges snippet-eval — Evaluate code snippets instantly
|
|
137
|
+
|
|
138
|
+
Usage:
|
|
139
|
+
echo "const key = '12345'" | judges snippet-eval
|
|
140
|
+
judges snippet-eval --code "eval(userInput)"
|
|
141
|
+
judges snippet-eval --code "SELECT * FROM users WHERE id=" --lang sql
|
|
142
|
+
judges snippet-eval --demo
|
|
143
|
+
|
|
144
|
+
Options:
|
|
145
|
+
--code <snippet> Code snippet to evaluate (or pipe via stdin)
|
|
146
|
+
--lang <language> Language hint (auto-detected if omitted)
|
|
147
|
+
--demo Run with demo vulnerable code
|
|
148
|
+
--format json JSON output
|
|
149
|
+
--help, -h Show this help
|
|
150
|
+
|
|
151
|
+
Zero-friction evaluation — no project setup needed.
|
|
152
|
+
`);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
156
|
+
const codeArg = argv.find((_a, i) => argv[i - 1] === "--code") || "";
|
|
157
|
+
const langArg = argv.find((_a, i) => argv[i - 1] === "--lang") || "";
|
|
158
|
+
const isDemo = argv.includes("--demo");
|
|
159
|
+
let code;
|
|
160
|
+
if (isDemo) {
|
|
161
|
+
code = `// AI-generated API handler
|
|
162
|
+
const query = "SELECT * FROM users WHERE id=" + req.params.id;
|
|
163
|
+
const apiKey = "sk-proj-1234567890abcdef1234567890";
|
|
164
|
+
document.innerHTML = userInput;
|
|
165
|
+
try { await riskyOperation(); } catch (e) {}
|
|
166
|
+
console.log("Debug: user token = " + token);
|
|
167
|
+
fetch("http://api.example.com/data");
|
|
168
|
+
const sessionId = Math.random().toString(36);`;
|
|
169
|
+
}
|
|
170
|
+
else if (codeArg) {
|
|
171
|
+
code = codeArg;
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
// Try reading from stdin
|
|
175
|
+
try {
|
|
176
|
+
code = readFileSync(0, "utf-8");
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
console.error(" Provide code via --code, --demo, or pipe to stdin");
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (!code.trim()) {
|
|
184
|
+
console.error(" No code provided");
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const lang = langArg || detectLanguage(code);
|
|
188
|
+
const findings = scanSnippet(code, lang);
|
|
189
|
+
// Determine verdict
|
|
190
|
+
const hasCritical = findings.some((f) => f.severity === "critical");
|
|
191
|
+
const hasHigh = findings.some((f) => f.severity === "high");
|
|
192
|
+
const verdict = hasCritical || findings.length > 5
|
|
193
|
+
? "FAIL"
|
|
194
|
+
: hasHigh || findings.length > 2
|
|
195
|
+
? "WARN"
|
|
196
|
+
: findings.length === 0
|
|
197
|
+
? "SAFE"
|
|
198
|
+
: "WARN";
|
|
199
|
+
if (format === "json") {
|
|
200
|
+
console.log(JSON.stringify({
|
|
201
|
+
verdict,
|
|
202
|
+
language: lang,
|
|
203
|
+
findings,
|
|
204
|
+
lines: code.split("\n").length,
|
|
205
|
+
timestamp: new Date().toISOString(),
|
|
206
|
+
}, null, 2));
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
const badge = verdict === "SAFE" ? "✅ SAFE" : verdict === "WARN" ? "⚠️ WARN" : "❌ FAIL";
|
|
210
|
+
console.log(`\n Snippet Eval: ${badge} (${lang}, ${code.split("\n").length} lines)\n ──────────────────────────`);
|
|
211
|
+
if (findings.length === 0) {
|
|
212
|
+
console.log(" No issues detected in snippet.");
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
for (const f of findings) {
|
|
216
|
+
const icon = f.severity === "critical" ? "🔴" : f.severity === "high" ? "🟠" : f.severity === "medium" ? "🟡" : "⚪";
|
|
217
|
+
console.log(` ${icon} L${f.line} [${f.severity}] ${f.ruleId}: ${f.title}`);
|
|
218
|
+
console.log(` 💡 ${f.recommendation}`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
console.log(`\n ${findings.length} finding(s) | Verdict: ${verdict}\n`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=snippet-eval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snippet-eval.js","sourceRoot":"","sources":["../../src/commands/snippet-eval.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Team trust — aggregate trust profiles across team members to
|
|
3
|
+
* build collective trust profiles with per-team sensitivity.
|
|
4
|
+
*
|
|
5
|
+
* All data stored locally in `.judges-team-trust/`.
|
|
6
|
+
*/
|
|
7
|
+
export declare function runTeamTrust(argv: string[]): void;
|
|
8
|
+
//# sourceMappingURL=team-trust.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-trust.d.ts","sourceRoot":"","sources":["../../src/commands/team-trust.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAwGH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAsHjD"}
|