@kevinrabun/judges 3.42.0 → 3.44.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 +25 -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/assign-findings.d.ts +37 -0
- package/dist/commands/assign-findings.d.ts.map +1 -0
- package/dist/commands/assign-findings.js +178 -0
- package/dist/commands/assign-findings.js.map +1 -0
- package/dist/commands/burndown.d.ts +27 -0
- package/dist/commands/burndown.d.ts.map +1 -0
- package/dist/commands/burndown.js +180 -0
- package/dist/commands/burndown.js.map +1 -0
- package/dist/commands/ci-template.d.ts +15 -0
- package/dist/commands/ci-template.d.ts.map +1 -0
- package/dist/commands/ci-template.js +212 -0
- package/dist/commands/ci-template.js.map +1 -0
- package/dist/commands/false-negatives.d.ts +35 -0
- package/dist/commands/false-negatives.d.ts.map +1 -0
- package/dist/commands/false-negatives.js +166 -0
- package/dist/commands/false-negatives.js.map +1 -0
- package/dist/commands/hook-install.d.ts +22 -0
- package/dist/commands/hook-install.d.ts.map +1 -0
- package/dist/commands/hook-install.js +143 -0
- package/dist/commands/hook-install.js.map +1 -0
- package/dist/commands/kb.d.ts +41 -0
- package/dist/commands/kb.d.ts.map +1 -0
- package/dist/commands/kb.js +231 -0
- package/dist/commands/kb.js.map +1 -0
- package/dist/commands/noise-advisor.d.ts +30 -0
- package/dist/commands/noise-advisor.d.ts.map +1 -0
- package/dist/commands/noise-advisor.js +171 -0
- package/dist/commands/noise-advisor.js.map +1 -0
- package/dist/commands/policy-audit.d.ts +53 -0
- package/dist/commands/policy-audit.d.ts.map +1 -0
- package/dist/commands/policy-audit.js +161 -0
- package/dist/commands/policy-audit.js.map +1 -0
- package/dist/commands/recommend.d.ts +21 -0
- package/dist/commands/recommend.d.ts.map +1 -0
- package/dist/commands/recommend.js +283 -0
- package/dist/commands/recommend.js.map +1 -0
- package/dist/commands/regression-alert.d.ts +32 -0
- package/dist/commands/regression-alert.d.ts.map +1 -0
- package/dist/commands/regression-alert.js +216 -0
- package/dist/commands/regression-alert.js.map +1 -0
- package/dist/commands/remediation.d.ts +21 -0
- package/dist/commands/remediation.d.ts.map +1 -0
- package/dist/commands/remediation.js +257 -0
- package/dist/commands/remediation.js.map +1 -0
- package/dist/commands/report-template.d.ts +17 -0
- package/dist/commands/report-template.d.ts.map +1 -0
- package/dist/commands/report-template.js +291 -0
- package/dist/commands/report-template.js.map +1 -0
- package/dist/commands/review-queue.d.ts +34 -0
- package/dist/commands/review-queue.d.ts.map +1 -0
- package/dist/commands/review-queue.js +226 -0
- package/dist/commands/review-queue.js.map +1 -0
- package/dist/commands/rule-owner.d.ts +31 -0
- package/dist/commands/rule-owner.d.ts.map +1 -0
- package/dist/commands/rule-owner.js +182 -0
- package/dist/commands/rule-owner.js.map +1 -0
- package/dist/commands/sla-track.d.ts +57 -0
- package/dist/commands/sla-track.d.ts.map +1 -0
- package/dist/commands/sla-track.js +269 -0
- package/dist/commands/sla-track.js.map +1 -0
- package/dist/commands/suppress.d.ts +40 -0
- package/dist/commands/suppress.d.ts.map +1 -0
- package/dist/commands/suppress.js +209 -0
- package/dist/commands/suppress.js.map +1 -0
- package/dist/commands/ticket-sync.d.ts +26 -0
- package/dist/commands/ticket-sync.d.ts.map +1 -0
- package/dist/commands/ticket-sync.js +236 -0
- package/dist/commands/ticket-sync.js.map +1 -0
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Report templates — generate reports from different predefined
|
|
3
|
+
* templates targeting different audiences (exec, dev, compliance).
|
|
4
|
+
*
|
|
5
|
+
* Pure local generation — no external services.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
8
|
+
// ─── Templates ──────────────────────────────────────────────────────────────
|
|
9
|
+
const TEMPLATES = [
|
|
10
|
+
{
|
|
11
|
+
id: "exec-summary",
|
|
12
|
+
name: "Executive Summary",
|
|
13
|
+
audience: "Leadership",
|
|
14
|
+
description: "One-page overview with verdict, risk score, and trend",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
id: "dev-detail",
|
|
18
|
+
name: "Developer Detail",
|
|
19
|
+
audience: "Developers",
|
|
20
|
+
description: "Full findings with code locations, fixes, and references",
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
id: "compliance",
|
|
24
|
+
name: "Compliance Report",
|
|
25
|
+
audience: "Auditors",
|
|
26
|
+
description: "SOC2/ISO-aligned report with policy hash and evidence",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: "pr-review",
|
|
30
|
+
name: "PR Review",
|
|
31
|
+
audience: "Code Reviewers",
|
|
32
|
+
description: "Focused diff-aware summary for PR review",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: "trend",
|
|
36
|
+
name: "Trend Report",
|
|
37
|
+
audience: "Management",
|
|
38
|
+
description: "Historical comparison showing improvement trajectory",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: "onboarding",
|
|
42
|
+
name: "Onboarding Report",
|
|
43
|
+
audience: "New Team Members",
|
|
44
|
+
description: "Gentle introduction to codebase health with learning resources",
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
// ─── Report Generators ─────────────────────────────────────────────────────
|
|
48
|
+
function renderExecSummary(verdict) {
|
|
49
|
+
const critical = verdict.criticalCount || 0;
|
|
50
|
+
const high = verdict.highCount || 0;
|
|
51
|
+
const lines = [
|
|
52
|
+
"# Executive Summary — Code Review Report",
|
|
53
|
+
"",
|
|
54
|
+
`**Date:** ${new Date().toISOString().split("T")[0]}`,
|
|
55
|
+
`**Verdict:** ${verdict.overallVerdict.toUpperCase()}`,
|
|
56
|
+
`**Score:** ${verdict.overallScore}/100`,
|
|
57
|
+
"",
|
|
58
|
+
"## Risk Overview",
|
|
59
|
+
"",
|
|
60
|
+
`| Metric | Value |`,
|
|
61
|
+
`|--------|-------|`,
|
|
62
|
+
`| Critical findings | ${critical} |`,
|
|
63
|
+
`| High findings | ${high} |`,
|
|
64
|
+
`| Total findings | ${verdict.findings.length} |`,
|
|
65
|
+
`| Judges evaluated | ${verdict.evaluations.length} |`,
|
|
66
|
+
"",
|
|
67
|
+
"## Summary",
|
|
68
|
+
"",
|
|
69
|
+
verdict.summary,
|
|
70
|
+
"",
|
|
71
|
+
"## Action Required",
|
|
72
|
+
"",
|
|
73
|
+
];
|
|
74
|
+
if (critical > 0) {
|
|
75
|
+
lines.push("**IMMEDIATE ACTION:** Critical findings require attention within 24 hours.");
|
|
76
|
+
}
|
|
77
|
+
else if (high > 0) {
|
|
78
|
+
lines.push("**ACTION NEEDED:** High-severity findings should be addressed this sprint.");
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
lines.push("**STATUS:** No critical issues. Continue monitoring.");
|
|
82
|
+
}
|
|
83
|
+
lines.push("", "---", "_Generated by Judges_");
|
|
84
|
+
return lines.join("\n");
|
|
85
|
+
}
|
|
86
|
+
function renderDevDetail(verdict) {
|
|
87
|
+
const lines = [
|
|
88
|
+
"# Developer Report — Detailed Findings",
|
|
89
|
+
"",
|
|
90
|
+
`**Verdict:** ${verdict.overallVerdict} (${verdict.overallScore}/100)`,
|
|
91
|
+
`**Findings:** ${verdict.findings.length}`,
|
|
92
|
+
"",
|
|
93
|
+
];
|
|
94
|
+
const bySeverity = {};
|
|
95
|
+
for (const f of verdict.findings) {
|
|
96
|
+
(bySeverity[f.severity] ??= []).push(f);
|
|
97
|
+
}
|
|
98
|
+
for (const sev of ["critical", "high", "medium", "low", "info"]) {
|
|
99
|
+
const findings = bySeverity[sev];
|
|
100
|
+
if (!findings?.length)
|
|
101
|
+
continue;
|
|
102
|
+
lines.push(`## ${sev.toUpperCase()} (${findings.length})`, "");
|
|
103
|
+
for (const f of findings) {
|
|
104
|
+
lines.push(`### ${f.ruleId}: ${f.title}`);
|
|
105
|
+
if (f.lineNumbers?.length)
|
|
106
|
+
lines.push(`**Lines:** ${f.lineNumbers.join(", ")}`);
|
|
107
|
+
lines.push("", f.description, "");
|
|
108
|
+
lines.push("**Fix:**", f.recommendation, "");
|
|
109
|
+
if (f.reference)
|
|
110
|
+
lines.push(`**Reference:** ${f.reference}`, "");
|
|
111
|
+
lines.push("---", "");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return lines.join("\n");
|
|
115
|
+
}
|
|
116
|
+
function renderComplianceReport(verdict) {
|
|
117
|
+
const lines = [
|
|
118
|
+
"# Compliance Report",
|
|
119
|
+
"",
|
|
120
|
+
`**Generated:** ${new Date().toISOString()}`,
|
|
121
|
+
`**Verdict:** ${verdict.overallVerdict}`,
|
|
122
|
+
`**Score:** ${verdict.overallScore}/100`,
|
|
123
|
+
"",
|
|
124
|
+
"## Evaluation Summary",
|
|
125
|
+
"",
|
|
126
|
+
`| Judge | Verdict | Score | Findings |`,
|
|
127
|
+
`|-------|---------|-------|----------|`,
|
|
128
|
+
];
|
|
129
|
+
for (const e of verdict.evaluations) {
|
|
130
|
+
lines.push(`| ${e.judgeId} | ${e.verdict} | ${e.score} | ${e.findings.length} |`);
|
|
131
|
+
}
|
|
132
|
+
lines.push("", "## Finding Categories", "", "| Severity | Count |", "|----------|-------|");
|
|
133
|
+
const bySev = {};
|
|
134
|
+
for (const f of verdict.findings) {
|
|
135
|
+
bySev[f.severity] = (bySev[f.severity] || 0) + 1;
|
|
136
|
+
}
|
|
137
|
+
for (const [s, c] of Object.entries(bySev)) {
|
|
138
|
+
lines.push(`| ${s} | ${c} |`);
|
|
139
|
+
}
|
|
140
|
+
lines.push("", "## Evidence", "", `- Total judges evaluated: ${verdict.evaluations.length}`, `- Total findings: ${verdict.findings.length}`, `- Critical count: ${verdict.criticalCount || 0}`, `- High count: ${verdict.highCount || 0}`, "", "---", "_Audit report generated by Judges_");
|
|
141
|
+
return lines.join("\n");
|
|
142
|
+
}
|
|
143
|
+
function renderTrendReport(verdict) {
|
|
144
|
+
const lines = [
|
|
145
|
+
"# Trend Report",
|
|
146
|
+
"",
|
|
147
|
+
`**Current Score:** ${verdict.overallScore}/100`,
|
|
148
|
+
`**Current Findings:** ${verdict.findings.length}`,
|
|
149
|
+
"",
|
|
150
|
+
"## Current Snapshot",
|
|
151
|
+
"",
|
|
152
|
+
];
|
|
153
|
+
const bySev = {};
|
|
154
|
+
for (const f of verdict.findings) {
|
|
155
|
+
bySev[f.severity] = (bySev[f.severity] || 0) + 1;
|
|
156
|
+
}
|
|
157
|
+
lines.push("| Severity | Count |", "|----------|-------|");
|
|
158
|
+
for (const [s, c] of Object.entries(bySev)) {
|
|
159
|
+
lines.push(`| ${s} | ${c} |`);
|
|
160
|
+
}
|
|
161
|
+
lines.push("", "## Top Rules", "", "| Rule | Count |", "|------|-------|");
|
|
162
|
+
const byRule = {};
|
|
163
|
+
for (const f of verdict.findings) {
|
|
164
|
+
byRule[f.ruleId] = (byRule[f.ruleId] || 0) + 1;
|
|
165
|
+
}
|
|
166
|
+
const sorted = Object.entries(byRule)
|
|
167
|
+
.sort((a, b) => b[1] - a[1])
|
|
168
|
+
.slice(0, 10);
|
|
169
|
+
for (const [r, c] of sorted) {
|
|
170
|
+
lines.push(`| ${r} | ${c} |`);
|
|
171
|
+
}
|
|
172
|
+
lines.push("", "> Compare with `judges regression-alert --check` for baseline comparison.", "", "---", "_Generated by Judges_");
|
|
173
|
+
return lines.join("\n");
|
|
174
|
+
}
|
|
175
|
+
function renderOnboarding(verdict) {
|
|
176
|
+
const lines = [
|
|
177
|
+
"# Welcome to Your Codebase Health Report",
|
|
178
|
+
"",
|
|
179
|
+
"This report helps new team members understand the current code quality state.",
|
|
180
|
+
"",
|
|
181
|
+
`**Overall Score:** ${verdict.overallScore}/100 (${verdict.overallVerdict})`,
|
|
182
|
+
`**Total Findings:** ${verdict.findings.length}`,
|
|
183
|
+
"",
|
|
184
|
+
"## What Do These Findings Mean?",
|
|
185
|
+
"",
|
|
186
|
+
"Findings are categorized by severity:",
|
|
187
|
+
"- **Critical/High:** Security issues that must be fixed",
|
|
188
|
+
"- **Medium:** Best practice violations worth addressing",
|
|
189
|
+
"- **Low/Info:** Suggestions for improvement",
|
|
190
|
+
"",
|
|
191
|
+
"## Key Areas to Learn",
|
|
192
|
+
"",
|
|
193
|
+
];
|
|
194
|
+
const categories = new Set(verdict.findings.map((f) => f.ruleId.split("-")[0]));
|
|
195
|
+
const catDescriptions = {
|
|
196
|
+
SEC: "Security vulnerabilities (injections, XSS, etc.)",
|
|
197
|
+
AUTH: "Authentication and authorization issues",
|
|
198
|
+
CRYPTO: "Cryptography best practices",
|
|
199
|
+
PERF: "Performance optimization opportunities",
|
|
200
|
+
ERR: "Error handling patterns",
|
|
201
|
+
IAC: "Infrastructure as Code security",
|
|
202
|
+
SSRF: "Server-side request forgery prevention",
|
|
203
|
+
CONCUR: "Concurrency and race condition safety",
|
|
204
|
+
};
|
|
205
|
+
for (const cat of categories) {
|
|
206
|
+
lines.push(`- **${cat}:** ${catDescriptions[cat] || "Code quality rules"}`);
|
|
207
|
+
}
|
|
208
|
+
lines.push("", "## Getting Started", "", "1. Run `judges remediation <rule-id>` for fix guides", "2. Run `judges explain <rule-id>` for rule details", "3. Ask your team lead about suppression policies", "", "---", "_Generated by Judges_");
|
|
209
|
+
return lines.join("\n");
|
|
210
|
+
}
|
|
211
|
+
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
212
|
+
export function listTemplates() {
|
|
213
|
+
return TEMPLATES;
|
|
214
|
+
}
|
|
215
|
+
export function generateReport(templateId, verdict) {
|
|
216
|
+
switch (templateId) {
|
|
217
|
+
case "exec-summary":
|
|
218
|
+
return renderExecSummary(verdict);
|
|
219
|
+
case "dev-detail":
|
|
220
|
+
return renderDevDetail(verdict);
|
|
221
|
+
case "compliance":
|
|
222
|
+
return renderComplianceReport(verdict);
|
|
223
|
+
case "trend":
|
|
224
|
+
return renderTrendReport(verdict);
|
|
225
|
+
case "onboarding":
|
|
226
|
+
return renderOnboarding(verdict);
|
|
227
|
+
case "pr-review":
|
|
228
|
+
return renderDevDetail(verdict); // reuse dev detail for PR
|
|
229
|
+
default:
|
|
230
|
+
throw new Error(`Unknown template: ${templateId}. Use --list to see options.`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
234
|
+
export function runReportTemplate(argv) {
|
|
235
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
236
|
+
console.log(`
|
|
237
|
+
judges report-template — Generate reports from predefined templates
|
|
238
|
+
|
|
239
|
+
Usage:
|
|
240
|
+
judges report-template --list List available templates
|
|
241
|
+
judges report-template --template exec-summary --input results.json
|
|
242
|
+
judges report-template --template dev-detail --input results.json --output report.md
|
|
243
|
+
|
|
244
|
+
Options:
|
|
245
|
+
--template <id> Template to use (required)
|
|
246
|
+
--input <path> Results JSON file (required)
|
|
247
|
+
--output <path> Write report to file (default: stdout)
|
|
248
|
+
--list List available templates
|
|
249
|
+
--help, -h Show this help
|
|
250
|
+
|
|
251
|
+
Templates:
|
|
252
|
+
exec-summary One-page leadership overview
|
|
253
|
+
dev-detail Full findings with fixes
|
|
254
|
+
compliance SOC2/ISO-aligned evidence report
|
|
255
|
+
pr-review Diff-aware PR summary
|
|
256
|
+
trend Historical comparison
|
|
257
|
+
onboarding New team member introduction
|
|
258
|
+
`);
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
if (argv.includes("--list")) {
|
|
262
|
+
console.log("\n Report Templates\n ────────────────");
|
|
263
|
+
for (const t of TEMPLATES) {
|
|
264
|
+
console.log(` ${t.id.padEnd(16)} ${t.name} (${t.audience})`);
|
|
265
|
+
console.log(` ${t.description}`);
|
|
266
|
+
}
|
|
267
|
+
console.log("");
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
const templateId = argv.find((_a, i) => argv[i - 1] === "--template");
|
|
271
|
+
const inputPath = argv.find((_a, i) => argv[i - 1] === "--input");
|
|
272
|
+
const outputPath = argv.find((_a, i) => argv[i - 1] === "--output");
|
|
273
|
+
if (!templateId || !inputPath) {
|
|
274
|
+
console.error("Error: --template and --input required");
|
|
275
|
+
process.exit(1);
|
|
276
|
+
}
|
|
277
|
+
if (!existsSync(inputPath)) {
|
|
278
|
+
console.error(`Error: file not found: ${inputPath}`);
|
|
279
|
+
process.exit(1);
|
|
280
|
+
}
|
|
281
|
+
const verdict = JSON.parse(readFileSync(inputPath, "utf-8"));
|
|
282
|
+
const report = generateReport(templateId, verdict);
|
|
283
|
+
if (outputPath) {
|
|
284
|
+
writeFileSync(outputPath, report);
|
|
285
|
+
console.log(` Report written to ${outputPath}`);
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
console.log(report);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
//# sourceMappingURL=report-template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report-template.js","sourceRoot":"","sources":["../../src/commands/report-template.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Review queue — surface findings needing human judgment and route
|
|
3
|
+
* them to appropriate experts based on rule ownership.
|
|
4
|
+
*
|
|
5
|
+
* Uses local data from findings, rule-owners, and feedback.
|
|
6
|
+
*/
|
|
7
|
+
import type { Finding } from "../types.js";
|
|
8
|
+
export interface ReviewItem {
|
|
9
|
+
id: string;
|
|
10
|
+
ruleId: string;
|
|
11
|
+
severity: string;
|
|
12
|
+
title: string;
|
|
13
|
+
description: string;
|
|
14
|
+
confidence: number;
|
|
15
|
+
recommendedReviewer?: string;
|
|
16
|
+
status: "pending" | "approved" | "dismissed" | "escalated";
|
|
17
|
+
verdict?: string;
|
|
18
|
+
reviewedBy?: string;
|
|
19
|
+
reviewedIso?: string;
|
|
20
|
+
addedIso: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function addToReviewQueue(findings: Finding[], confidenceThreshold?: number): ReviewItem[];
|
|
23
|
+
export declare function reviewItem(id: string, verdict: "approved" | "dismissed" | "escalated", reviewer: string): void;
|
|
24
|
+
export declare function getQueueStats(): {
|
|
25
|
+
total: number;
|
|
26
|
+
pending: number;
|
|
27
|
+
approved: number;
|
|
28
|
+
dismissed: number;
|
|
29
|
+
escalated: number;
|
|
30
|
+
byReviewer: Record<string, number>;
|
|
31
|
+
avgConfidence: number;
|
|
32
|
+
};
|
|
33
|
+
export declare function runReviewQueue(argv: string[]): Promise<void>;
|
|
34
|
+
//# sourceMappingURL=review-queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-queue.d.ts","sourceRoot":"","sources":["../../src/commands/review-queue.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAI3C,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,WAAW,CAAC;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AA6CD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,mBAAmB,SAAM,GAAG,UAAU,EAAE,CA+B7F;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,WAAW,GAAG,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAS9G;AAED,wBAAgB,aAAa,IAAI;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;CACvB,CAuBA;AAID,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA0HlE"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Review queue — surface findings needing human judgment and route
|
|
3
|
+
* them to appropriate experts based on rule ownership.
|
|
4
|
+
*
|
|
5
|
+
* Uses local data from findings, rule-owners, and feedback.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
8
|
+
const REVIEW_FILE = ".judges-review-queue.json";
|
|
9
|
+
// ─── Core ───────────────────────────────────────────────────────────────────
|
|
10
|
+
function loadDb(file = REVIEW_FILE) {
|
|
11
|
+
if (!existsSync(file))
|
|
12
|
+
return { items: [] };
|
|
13
|
+
return JSON.parse(readFileSync(file, "utf-8"));
|
|
14
|
+
}
|
|
15
|
+
function saveDb(db, file = REVIEW_FILE) {
|
|
16
|
+
writeFileSync(file, JSON.stringify(db, null, 2));
|
|
17
|
+
}
|
|
18
|
+
function itemId(f) {
|
|
19
|
+
return `${f.ruleId}:${f.title}`.slice(0, 80);
|
|
20
|
+
}
|
|
21
|
+
function resolveReviewer(ruleId) {
|
|
22
|
+
try {
|
|
23
|
+
const ownerFile = ".judges-owners.json";
|
|
24
|
+
if (!existsSync(ownerFile))
|
|
25
|
+
return undefined;
|
|
26
|
+
const db = JSON.parse(readFileSync(ownerFile, "utf-8"));
|
|
27
|
+
if (!db.owners)
|
|
28
|
+
return undefined;
|
|
29
|
+
// Exact match first
|
|
30
|
+
const exact = db.owners.find((o) => o.pattern === ruleId);
|
|
31
|
+
if (exact)
|
|
32
|
+
return exact.owner;
|
|
33
|
+
// Prefix match
|
|
34
|
+
let best;
|
|
35
|
+
for (const o of db.owners) {
|
|
36
|
+
if (ruleId.startsWith(o.pattern) && (!best || o.pattern.length > best.pattern.length)) {
|
|
37
|
+
best = o;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return best?.owner;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export function addToReviewQueue(findings, confidenceThreshold = 0.6) {
|
|
47
|
+
const db = loadDb();
|
|
48
|
+
const existing = new Set(db.items.map((i) => i.id));
|
|
49
|
+
const added = [];
|
|
50
|
+
const now = new Date().toISOString();
|
|
51
|
+
for (const f of findings) {
|
|
52
|
+
const conf = f.confidence ?? 0.5;
|
|
53
|
+
if (conf >= confidenceThreshold)
|
|
54
|
+
continue; // High-confidence: auto-approved
|
|
55
|
+
const id = itemId(f);
|
|
56
|
+
if (existing.has(id))
|
|
57
|
+
continue;
|
|
58
|
+
const item = {
|
|
59
|
+
id,
|
|
60
|
+
ruleId: f.ruleId,
|
|
61
|
+
severity: f.severity,
|
|
62
|
+
title: f.title,
|
|
63
|
+
description: f.description,
|
|
64
|
+
confidence: conf,
|
|
65
|
+
recommendedReviewer: resolveReviewer(f.ruleId),
|
|
66
|
+
status: "pending",
|
|
67
|
+
addedIso: now,
|
|
68
|
+
};
|
|
69
|
+
db.items.push(item);
|
|
70
|
+
added.push(item);
|
|
71
|
+
existing.add(id);
|
|
72
|
+
}
|
|
73
|
+
saveDb(db);
|
|
74
|
+
return added;
|
|
75
|
+
}
|
|
76
|
+
export function reviewItem(id, verdict, reviewer) {
|
|
77
|
+
const db = loadDb();
|
|
78
|
+
const item = db.items.find((i) => i.id === id);
|
|
79
|
+
if (!item)
|
|
80
|
+
throw new Error(`Review item not found: ${id}`);
|
|
81
|
+
item.status = verdict;
|
|
82
|
+
item.verdict = verdict;
|
|
83
|
+
item.reviewedBy = reviewer;
|
|
84
|
+
item.reviewedIso = new Date().toISOString();
|
|
85
|
+
saveDb(db);
|
|
86
|
+
}
|
|
87
|
+
export function getQueueStats() {
|
|
88
|
+
const db = loadDb();
|
|
89
|
+
const stats = {
|
|
90
|
+
total: db.items.length,
|
|
91
|
+
pending: db.items.filter((i) => i.status === "pending").length,
|
|
92
|
+
approved: db.items.filter((i) => i.status === "approved").length,
|
|
93
|
+
dismissed: db.items.filter((i) => i.status === "dismissed").length,
|
|
94
|
+
escalated: db.items.filter((i) => i.status === "escalated").length,
|
|
95
|
+
byReviewer: {},
|
|
96
|
+
avgConfidence: 0,
|
|
97
|
+
};
|
|
98
|
+
for (const i of db.items) {
|
|
99
|
+
const reviewer = i.recommendedReviewer || "unassigned";
|
|
100
|
+
stats.byReviewer[reviewer] = (stats.byReviewer[reviewer] || 0) + 1;
|
|
101
|
+
}
|
|
102
|
+
const pending = db.items.filter((i) => i.status === "pending");
|
|
103
|
+
if (pending.length > 0) {
|
|
104
|
+
stats.avgConfidence = Math.round((pending.reduce((s, i) => s + i.confidence, 0) / pending.length) * 100) / 100;
|
|
105
|
+
}
|
|
106
|
+
return stats;
|
|
107
|
+
}
|
|
108
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
109
|
+
export async function runReviewQueue(argv) {
|
|
110
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
111
|
+
console.log(`
|
|
112
|
+
judges review-queue — Human review queue for low-confidence findings
|
|
113
|
+
|
|
114
|
+
Usage:
|
|
115
|
+
judges review-queue --input results.json Add low-confidence findings to queue
|
|
116
|
+
judges review-queue --list Show pending review items
|
|
117
|
+
judges review-queue --approve <id> --reviewer "Alice"
|
|
118
|
+
judges review-queue --dismiss <id> --reviewer "Bob"
|
|
119
|
+
judges review-queue --escalate <id> --reviewer "Carol"
|
|
120
|
+
judges review-queue --stats Show queue statistics
|
|
121
|
+
|
|
122
|
+
Options:
|
|
123
|
+
--input <path> Results JSON with findings
|
|
124
|
+
--threshold <n> Confidence threshold (default: 0.6, below → queue)
|
|
125
|
+
--list Show pending items
|
|
126
|
+
--approve <id> Approve a finding as valid
|
|
127
|
+
--dismiss <id> Dismiss a finding as FP
|
|
128
|
+
--escalate <id> Escalate for deeper review
|
|
129
|
+
--reviewer <name> Reviewer name (required for verdicts)
|
|
130
|
+
--stats Queue statistics
|
|
131
|
+
--format json JSON output
|
|
132
|
+
--help, -h Show this help
|
|
133
|
+
`);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
137
|
+
// Add findings from input
|
|
138
|
+
const inputPath = argv.find((_a, i) => argv[i - 1] === "--input");
|
|
139
|
+
if (inputPath) {
|
|
140
|
+
if (!existsSync(inputPath)) {
|
|
141
|
+
console.error(`Error: file not found: ${inputPath}`);
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
144
|
+
const data = JSON.parse(readFileSync(inputPath, "utf-8"));
|
|
145
|
+
const findings = data.evaluations
|
|
146
|
+
? data.evaluations.flatMap((e) => e.findings || [])
|
|
147
|
+
: data.findings || data;
|
|
148
|
+
const thresholdStr = argv.find((_a, i) => argv[i - 1] === "--threshold");
|
|
149
|
+
const threshold = thresholdStr ? parseFloat(thresholdStr) : 0.6;
|
|
150
|
+
const added = addToReviewQueue(findings, threshold);
|
|
151
|
+
if (format === "json") {
|
|
152
|
+
console.log(JSON.stringify(added, null, 2));
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
console.log(`\n Added ${added.length} finding(s) to review queue (threshold: ${threshold})\n`);
|
|
156
|
+
for (const item of added.slice(0, 10)) {
|
|
157
|
+
console.log(` ${item.severity.padEnd(8)} ${item.ruleId.padEnd(12)} conf: ${item.confidence} → ${item.recommendedReviewer || "unassigned"}`);
|
|
158
|
+
}
|
|
159
|
+
if (added.length > 10)
|
|
160
|
+
console.log(` ... and ${added.length - 10} more`);
|
|
161
|
+
console.log("");
|
|
162
|
+
}
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
// Verdicts
|
|
166
|
+
const reviewer = argv.find((_a, i) => argv[i - 1] === "--reviewer");
|
|
167
|
+
for (const action of ["approve", "dismiss", "escalate"]) {
|
|
168
|
+
const target = argv.find((_a, i) => argv[i - 1] === `--${action}`);
|
|
169
|
+
if (target) {
|
|
170
|
+
if (!reviewer) {
|
|
171
|
+
console.error("Error: --reviewer required");
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
const verdict = action === "approve" ? "approved" : action === "dismiss" ? "dismissed" : "escalated";
|
|
175
|
+
reviewItem(target, verdict, reviewer);
|
|
176
|
+
console.log(` ${verdict}: ${target} by ${reviewer}`);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// List pending
|
|
181
|
+
if (argv.includes("--list")) {
|
|
182
|
+
const db = loadDb();
|
|
183
|
+
const pending = db.items.filter((i) => i.status === "pending");
|
|
184
|
+
if (format === "json") {
|
|
185
|
+
console.log(JSON.stringify(pending, null, 2));
|
|
186
|
+
}
|
|
187
|
+
else if (pending.length === 0) {
|
|
188
|
+
console.log("\n Review queue is empty.\n");
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
console.log(`\n Pending Reviews (${pending.length})\n ──────────────────`);
|
|
192
|
+
for (const item of pending) {
|
|
193
|
+
console.log(` ${item.severity.padEnd(8)} ${item.ruleId.padEnd(12)} conf: ${item.confidence} → ${item.recommendedReviewer || "unassigned"}`);
|
|
194
|
+
console.log(` ${item.title}`);
|
|
195
|
+
console.log(` ID: ${item.id}`);
|
|
196
|
+
}
|
|
197
|
+
console.log("");
|
|
198
|
+
}
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
// Stats (default)
|
|
202
|
+
const s = getQueueStats();
|
|
203
|
+
if (format === "json") {
|
|
204
|
+
console.log(JSON.stringify(s, null, 2));
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
console.log(`
|
|
208
|
+
Review Queue
|
|
209
|
+
────────────
|
|
210
|
+
Total: ${s.total}
|
|
211
|
+
Pending: ${s.pending}
|
|
212
|
+
Approved: ${s.approved}
|
|
213
|
+
Dismissed: ${s.dismissed}
|
|
214
|
+
Escalated: ${s.escalated}
|
|
215
|
+
Avg conf: ${s.avgConfidence}
|
|
216
|
+
`);
|
|
217
|
+
if (Object.keys(s.byReviewer).length > 0) {
|
|
218
|
+
console.log(" By reviewer:");
|
|
219
|
+
for (const [name, count] of Object.entries(s.byReviewer)) {
|
|
220
|
+
console.log(` ${name.padEnd(20)} ${count}`);
|
|
221
|
+
}
|
|
222
|
+
console.log("");
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=review-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-queue.js","sourceRoot":"","sources":["../../src/commands/review-queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule ownership — map rules/categories to team owners for
|
|
3
|
+
* accountability, escalation, and expertise routing.
|
|
4
|
+
*
|
|
5
|
+
* Stored locally in .judges-owners.json.
|
|
6
|
+
*/
|
|
7
|
+
export interface RuleOwner {
|
|
8
|
+
/** Rule ID or prefix (e.g., "SEC-001" or "SEC") */
|
|
9
|
+
pattern: string;
|
|
10
|
+
/** Owner name or team */
|
|
11
|
+
owner: string;
|
|
12
|
+
/** Contact (email/Slack handle) */
|
|
13
|
+
contact?: string;
|
|
14
|
+
/** Expertise level */
|
|
15
|
+
expertise: "expert" | "familiar" | "learning";
|
|
16
|
+
/** When assigned */
|
|
17
|
+
assignedIso: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function assignOwner(pattern: string, owner: string, opts?: {
|
|
20
|
+
contact?: string;
|
|
21
|
+
expertise?: RuleOwner["expertise"];
|
|
22
|
+
}): RuleOwner;
|
|
23
|
+
export declare function removeOwner(pattern: string): boolean;
|
|
24
|
+
export declare function findOwner(ruleId: string): RuleOwner | undefined;
|
|
25
|
+
export declare function getOwnerStats(): {
|
|
26
|
+
totalPatterns: number;
|
|
27
|
+
byOwner: Record<string, number>;
|
|
28
|
+
byExpertise: Record<string, number>;
|
|
29
|
+
};
|
|
30
|
+
export declare function runRuleOwner(argv: string[]): void;
|
|
31
|
+
//# sourceMappingURL=rule-owner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-owner.d.ts","sourceRoot":"","sources":["../../src/commands/rule-owner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,WAAW,SAAS;IACxB,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sBAAsB;IACtB,SAAS,EAAE,QAAQ,GAAG,UAAU,GAAG,UAAU,CAAC;IAC9C,oBAAoB;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAmBD,wBAAgB,WAAW,CACzB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,SAAS,CAAC,WAAW,CAAC,CAAA;CAAE,GAC9D,SAAS,CAiBX;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAOpD;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAa/D;AAED,wBAAgB,aAAa,IAAI;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC,CASA;AAID,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAgHjD"}
|