@kevinrabun/judges 3.46.0 → 3.47.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 +12 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +56 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/adoption-report.d.ts +8 -0
- package/dist/commands/adoption-report.d.ts.map +1 -0
- package/dist/commands/adoption-report.js +219 -0
- package/dist/commands/adoption-report.js.map +1 -0
- package/dist/commands/ai-model-trust.d.ts +17 -0
- package/dist/commands/ai-model-trust.d.ts.map +1 -0
- package/dist/commands/ai-model-trust.js +235 -0
- package/dist/commands/ai-model-trust.js.map +1 -0
- package/dist/commands/ai-prompt-audit.d.ts +23 -0
- package/dist/commands/ai-prompt-audit.d.ts.map +1 -0
- package/dist/commands/ai-prompt-audit.js +255 -0
- package/dist/commands/ai-prompt-audit.js.map +1 -0
- package/dist/commands/code-owner-suggest.d.ts +17 -0
- package/dist/commands/code-owner-suggest.d.ts.map +1 -0
- package/dist/commands/code-owner-suggest.js +215 -0
- package/dist/commands/code-owner-suggest.js.map +1 -0
- package/dist/commands/cost-forecast.d.ts +19 -0
- package/dist/commands/cost-forecast.d.ts.map +1 -0
- package/dist/commands/cost-forecast.js +194 -0
- package/dist/commands/cost-forecast.js.map +1 -0
- package/dist/commands/pr-quality-gate.d.ts +29 -0
- package/dist/commands/pr-quality-gate.d.ts.map +1 -0
- package/dist/commands/pr-quality-gate.js +208 -0
- package/dist/commands/pr-quality-gate.js.map +1 -0
- package/dist/commands/team-leaderboard.d.ts +25 -0
- package/dist/commands/team-leaderboard.d.ts.map +1 -0
- package/dist/commands/team-leaderboard.js +228 -0
- package/dist/commands/team-leaderboard.js.map +1 -0
- package/dist/commands/team-rules-sync.d.ts +8 -0
- package/dist/commands/team-rules-sync.d.ts.map +1 -0
- package/dist/commands/team-rules-sync.js +251 -0
- package/dist/commands/team-rules-sync.js.map +1 -0
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI prompt audit — scans AI-generated code for prompt injection
|
|
3
|
+
* risks: user input echoed into SQL, shell, config, etc.
|
|
4
|
+
*
|
|
5
|
+
* Pattern-based analysis only — no data stored externally.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
const AUDIT_DIR = ".judges-prompt-audit";
|
|
10
|
+
const AUDIT_FILE = join(AUDIT_DIR, "audit-history.json");
|
|
11
|
+
const RISK_PATTERNS = [
|
|
12
|
+
{
|
|
13
|
+
id: "sql-template-literal",
|
|
14
|
+
regex: /`[^`]*\$\{[^}]*(?:user|input|param|query|req\.|request|body|args)[^}]*\}[^`]*(?:SELECT|INSERT|UPDATE|DELETE|FROM|WHERE)/i,
|
|
15
|
+
severity: "critical",
|
|
16
|
+
description: "Template literal with user input in SQL context",
|
|
17
|
+
recommendation: "Use parameterized queries ($1, $2) instead of string interpolation",
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: "sql-concat",
|
|
21
|
+
regex: /(?:query|sql|execute|prepare)\s*\([^)]*(?:\+|\bconcat)\s*[^)]*(?:user|input|param|req\.|request|body)/i,
|
|
22
|
+
severity: "critical",
|
|
23
|
+
description: "String concatenation with user input in SQL query",
|
|
24
|
+
recommendation: "Use parameterized queries with placeholder values",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: "shell-injection",
|
|
28
|
+
regex: /(?:exec|spawn|execSync|execFile|system|popen)\s*\([^)]*(?:\$\{|[\s+].*(?:user|input|param|req\.|args))/i,
|
|
29
|
+
severity: "critical",
|
|
30
|
+
description: "User input in shell command execution",
|
|
31
|
+
recommendation: "Use execFile with argument array, or validate against an allowlist",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: "eval-user-input",
|
|
35
|
+
regex: /(?:eval|Function|setTimeout|setInterval)\s*\([^)]*(?:user|input|param|req\.|request|body|query)/i,
|
|
36
|
+
severity: "critical",
|
|
37
|
+
description: "User input passed to eval or dynamic code execution",
|
|
38
|
+
recommendation: "Never use eval with user input; use safe parsers instead",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: "innerHTML-assignment",
|
|
42
|
+
regex: /\.innerHTML\s*=\s*(?).*(?:user|input|param|data|response|result)/i,
|
|
43
|
+
severity: "high",
|
|
44
|
+
description: "Dynamic content assigned to innerHTML without sanitization",
|
|
45
|
+
recommendation: "Use textContent for text or a sanitization library (DOMPurify) for HTML",
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: "hardcoded-secret",
|
|
49
|
+
regex: /(?:password|secret|api_key|apiKey|token|auth)\s*[:=]\s*['"][^'"]{8,}['"]/i,
|
|
50
|
+
severity: "high",
|
|
51
|
+
description: "Hardcoded credential or secret in source code",
|
|
52
|
+
recommendation: "Use environment variables or a secrets manager",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: "url-user-input",
|
|
56
|
+
regex: /(?:fetch|axios|http\.get|request|got)\s*\([^)]*(?:\$\{|[\s+].*(?:user|input|param|req\.|url|host))/i,
|
|
57
|
+
severity: "high",
|
|
58
|
+
description: "User-controlled URL in HTTP request (SSRF risk)",
|
|
59
|
+
recommendation: "Validate URLs against an allowlist and block private IP ranges",
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
id: "path-traversal",
|
|
63
|
+
regex: /(?:readFile|readFileSync|createReadStream|writeFile|writeFileSync|unlink|rmdir)\s*\([^)]*(?:\$\{|[\s+].*(?:user|input|param|req\.|path|file|name))/i,
|
|
64
|
+
severity: "high",
|
|
65
|
+
description: "User input in file system operation (path traversal risk)",
|
|
66
|
+
recommendation: "Sanitize paths with path.resolve and validate within allowed directory",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: "prompt-echo",
|
|
70
|
+
regex: /(?:\/\/|#)\s*(?:TODO|FIXME|HACK|generated|copilot|cursor|claude|gpt|ai)[:\s].*(?:user|implement|replace|change)/i,
|
|
71
|
+
severity: "medium",
|
|
72
|
+
description: "AI prompt remnant in code comment — may expose intent or instructions",
|
|
73
|
+
recommendation: "Remove AI generation comments and prompt artifacts before committing",
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: "cors-wildcard",
|
|
77
|
+
regex: /(?:Access-Control-Allow-Origin|cors|origin)\s*[:=]\s*['"`]\*['"`]/i,
|
|
78
|
+
severity: "medium",
|
|
79
|
+
description: "Wildcard CORS allows any origin to access the API",
|
|
80
|
+
recommendation: "Restrict CORS to specific trusted origins",
|
|
81
|
+
},
|
|
82
|
+
];
|
|
83
|
+
// ─── Core ───────────────────────────────────────────────────────────────────
|
|
84
|
+
function ensureDir() {
|
|
85
|
+
if (!existsSync(AUDIT_DIR))
|
|
86
|
+
mkdirSync(AUDIT_DIR, { recursive: true });
|
|
87
|
+
}
|
|
88
|
+
function loadStore() {
|
|
89
|
+
if (!existsSync(AUDIT_FILE))
|
|
90
|
+
return { results: [], updatedAt: new Date().toISOString() };
|
|
91
|
+
try {
|
|
92
|
+
return JSON.parse(readFileSync(AUDIT_FILE, "utf-8"));
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return { results: [], updatedAt: new Date().toISOString() };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function saveStore(store) {
|
|
99
|
+
ensureDir();
|
|
100
|
+
store.updatedAt = new Date().toISOString();
|
|
101
|
+
writeFileSync(AUDIT_FILE, JSON.stringify(store, null, 2));
|
|
102
|
+
}
|
|
103
|
+
export function auditFile(filePath) {
|
|
104
|
+
const content = readFileSync(filePath, "utf-8");
|
|
105
|
+
const lines = content.split("\n");
|
|
106
|
+
const risks = [];
|
|
107
|
+
for (let i = 0; i < lines.length; i++) {
|
|
108
|
+
const line = lines[i];
|
|
109
|
+
for (const pattern of RISK_PATTERNS) {
|
|
110
|
+
if (pattern.regex.test(line)) {
|
|
111
|
+
risks.push({
|
|
112
|
+
line: i + 1,
|
|
113
|
+
pattern: pattern.id,
|
|
114
|
+
severity: pattern.severity,
|
|
115
|
+
description: pattern.description,
|
|
116
|
+
recommendation: pattern.recommendation,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Risk score: critical=30, high=15, medium=5
|
|
122
|
+
const riskScore = risks.reduce((sum, r) => {
|
|
123
|
+
if (r.severity === "critical")
|
|
124
|
+
return sum + 30;
|
|
125
|
+
if (r.severity === "high")
|
|
126
|
+
return sum + 15;
|
|
127
|
+
return sum + 5;
|
|
128
|
+
}, 0);
|
|
129
|
+
const result = {
|
|
130
|
+
file: filePath,
|
|
131
|
+
risks,
|
|
132
|
+
riskScore: Math.min(100, riskScore),
|
|
133
|
+
timestamp: new Date().toISOString(),
|
|
134
|
+
};
|
|
135
|
+
// Persist
|
|
136
|
+
const store = loadStore();
|
|
137
|
+
store.results.push(result);
|
|
138
|
+
if (store.results.length > 200)
|
|
139
|
+
store.results = store.results.slice(-200);
|
|
140
|
+
saveStore(store);
|
|
141
|
+
return result;
|
|
142
|
+
}
|
|
143
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
144
|
+
export function runAiPromptAudit(argv) {
|
|
145
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
146
|
+
console.log(`
|
|
147
|
+
judges ai-prompt-audit — Scan for prompt injection risks in AI-generated code
|
|
148
|
+
|
|
149
|
+
Usage:
|
|
150
|
+
judges ai-prompt-audit --file src/app.ts
|
|
151
|
+
judges ai-prompt-audit --patterns
|
|
152
|
+
judges ai-prompt-audit --history
|
|
153
|
+
judges ai-prompt-audit --summary
|
|
154
|
+
|
|
155
|
+
Options:
|
|
156
|
+
--file <path> Scan a file for prompt injection risks
|
|
157
|
+
--patterns Show all detection patterns
|
|
158
|
+
--history Show audit history
|
|
159
|
+
--summary Show risk summary across all audits
|
|
160
|
+
--format json JSON output
|
|
161
|
+
--help, -h Show this help
|
|
162
|
+
`);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
166
|
+
// Patterns
|
|
167
|
+
if (argv.includes("--patterns")) {
|
|
168
|
+
const patterns = RISK_PATTERNS.map(({ id, severity, description, recommendation }) => ({
|
|
169
|
+
id,
|
|
170
|
+
severity,
|
|
171
|
+
description,
|
|
172
|
+
recommendation,
|
|
173
|
+
}));
|
|
174
|
+
if (format === "json") {
|
|
175
|
+
console.log(JSON.stringify(patterns, null, 2));
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
console.log(`\n Prompt Audit Patterns (${patterns.length})\n ──────────────────────────`);
|
|
179
|
+
for (const p of patterns) {
|
|
180
|
+
console.log(` [${p.severity.padEnd(8)}] ${p.id.padEnd(25)} ${p.description}`);
|
|
181
|
+
}
|
|
182
|
+
console.log("");
|
|
183
|
+
}
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
// History
|
|
187
|
+
if (argv.includes("--history")) {
|
|
188
|
+
const store = loadStore();
|
|
189
|
+
if (format === "json") {
|
|
190
|
+
console.log(JSON.stringify(store, null, 2));
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
console.log(`\n Audit History (${store.results.length} scans)\n ──────────────────────────`);
|
|
194
|
+
for (const r of store.results.slice(-15)) {
|
|
195
|
+
const icon = r.riskScore === 0 ? "✅" : r.riskScore >= 50 ? "🔴" : "⚠️";
|
|
196
|
+
console.log(` ${icon} ${r.timestamp.slice(0, 16)} risk:${r.riskScore.toString().padEnd(4)} ${r.risks.length} issues ${r.file}`);
|
|
197
|
+
}
|
|
198
|
+
console.log("");
|
|
199
|
+
}
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
// Summary
|
|
203
|
+
if (argv.includes("--summary")) {
|
|
204
|
+
const store = loadStore();
|
|
205
|
+
const totalRisks = store.results.reduce((s, r) => s + r.risks.length, 0);
|
|
206
|
+
const critCount = store.results.reduce((s, r) => s + r.risks.filter((x) => x.severity === "critical").length, 0);
|
|
207
|
+
const highCount = store.results.reduce((s, r) => s + r.risks.filter((x) => x.severity === "high").length, 0);
|
|
208
|
+
const avgScore = store.results.length > 0
|
|
209
|
+
? Math.round(store.results.reduce((s, r) => s + r.riskScore, 0) / store.results.length)
|
|
210
|
+
: 0;
|
|
211
|
+
if (format === "json") {
|
|
212
|
+
console.log(JSON.stringify({ totalScans: store.results.length, totalRisks, critCount, highCount, avgScore }, null, 2));
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
console.log(`\n Prompt Audit Summary\n ──────────────────────────`);
|
|
216
|
+
console.log(` Scans: ${store.results.length}`);
|
|
217
|
+
console.log(` Risks: ${totalRisks} (${critCount} critical, ${highCount} high)`);
|
|
218
|
+
console.log(` Avg risk: ${avgScore}/100`);
|
|
219
|
+
console.log("");
|
|
220
|
+
}
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
// Scan file
|
|
224
|
+
const filePath = argv.find((_a, i) => argv[i - 1] === "--file");
|
|
225
|
+
if (!filePath) {
|
|
226
|
+
console.error(" Use --file <path>, --patterns, --history, or --summary. --help for usage.");
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
if (!existsSync(filePath)) {
|
|
230
|
+
console.error(` File not found: ${filePath}`);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
const result = auditFile(filePath);
|
|
234
|
+
if (format === "json") {
|
|
235
|
+
console.log(JSON.stringify(result, null, 2));
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
const icon = result.riskScore === 0 ? "✅" : result.riskScore >= 50 ? "🔴" : "⚠️";
|
|
239
|
+
console.log(`\n ${icon} Prompt Audit — ${filePath}`);
|
|
240
|
+
console.log(` Risk score: ${result.riskScore}/100 | Issues: ${result.risks.length}`);
|
|
241
|
+
console.log(` ──────────────────────────`);
|
|
242
|
+
if (result.risks.length === 0) {
|
|
243
|
+
console.log(" No prompt injection risks detected.");
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
for (const r of result.risks) {
|
|
247
|
+
console.log(` L${r.line.toString().padEnd(5)} [${r.severity.padEnd(8)}] ${r.pattern}`);
|
|
248
|
+
console.log(` ${r.description}`);
|
|
249
|
+
console.log(` Fix: ${r.recommendation}`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
console.log("");
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
//# sourceMappingURL=ai-prompt-audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-prompt-audit.js","sourceRoot":"","sources":["../../src/commands/ai-prompt-audit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code owner suggest — auto-recommend CODEOWNERS entries
|
|
3
|
+
* based on finding patterns and resolution history.
|
|
4
|
+
*
|
|
5
|
+
* All analysis uses local data only.
|
|
6
|
+
*/
|
|
7
|
+
interface OwnerSuggestion {
|
|
8
|
+
path: string;
|
|
9
|
+
suggestedOwner: string;
|
|
10
|
+
reason: string;
|
|
11
|
+
confidence: number;
|
|
12
|
+
ruleCategories: string[];
|
|
13
|
+
}
|
|
14
|
+
export declare function suggestOwner(path: string, author: string, ruleCategories: string[]): OwnerSuggestion;
|
|
15
|
+
export declare function runCodeOwnerSuggest(argv: string[]): void;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=code-owner-suggest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-owner-suggest.d.ts","sourceRoot":"","sources":["../../src/commands/code-owner-suggest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAuDD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,eAAe,CAkBpG;AAwBD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA2HxD"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code owner suggest — auto-recommend CODEOWNERS entries
|
|
3
|
+
* based on finding patterns and resolution history.
|
|
4
|
+
*
|
|
5
|
+
* All analysis uses local data only.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
const OWNER_DIR = ".judges-code-owners";
|
|
10
|
+
const OWNER_FILE = join(OWNER_DIR, "suggestions.json");
|
|
11
|
+
// ─── Core ───────────────────────────────────────────────────────────────────
|
|
12
|
+
function ensureDir() {
|
|
13
|
+
if (!existsSync(OWNER_DIR))
|
|
14
|
+
mkdirSync(OWNER_DIR, { recursive: true });
|
|
15
|
+
}
|
|
16
|
+
function loadStore() {
|
|
17
|
+
if (!existsSync(OWNER_FILE))
|
|
18
|
+
return { suggestions: [], updatedAt: new Date().toISOString() };
|
|
19
|
+
try {
|
|
20
|
+
return JSON.parse(readFileSync(OWNER_FILE, "utf-8"));
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return { suggestions: [], updatedAt: new Date().toISOString() };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function saveStore(store) {
|
|
27
|
+
ensureDir();
|
|
28
|
+
store.updatedAt = new Date().toISOString();
|
|
29
|
+
writeFileSync(OWNER_FILE, JSON.stringify(store, null, 2));
|
|
30
|
+
}
|
|
31
|
+
function loadScoreData() {
|
|
32
|
+
// Try to load from dev-score data
|
|
33
|
+
const scoreDir = ".judges-scores";
|
|
34
|
+
if (!existsSync(scoreDir))
|
|
35
|
+
return [];
|
|
36
|
+
try {
|
|
37
|
+
const { readdirSync: rds } = require("fs");
|
|
38
|
+
const files = rds(scoreDir).filter((f) => f.endsWith(".json"));
|
|
39
|
+
return files.map((f) => {
|
|
40
|
+
try {
|
|
41
|
+
const data = JSON.parse(readFileSync(join(scoreDir, f), "utf-8"));
|
|
42
|
+
return {
|
|
43
|
+
author: data.author || f.replace(".json", ""),
|
|
44
|
+
findingsFixed: data.findingsFixed || data.score || 0,
|
|
45
|
+
categories: data.topCategories || [],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return { author: f.replace(".json", ""), findingsFixed: 0, categories: [] };
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export function suggestOwner(path, author, ruleCategories) {
|
|
58
|
+
const suggestion = {
|
|
59
|
+
path,
|
|
60
|
+
suggestedOwner: author,
|
|
61
|
+
reason: `Most active reviewer for ${ruleCategories.join(", ")} findings`,
|
|
62
|
+
confidence: Math.min(100, 50 + ruleCategories.length * 10),
|
|
63
|
+
ruleCategories,
|
|
64
|
+
};
|
|
65
|
+
const store = loadStore();
|
|
66
|
+
// Replace existing suggestion for same path
|
|
67
|
+
const idx = store.suggestions.findIndex((s) => s.path === path);
|
|
68
|
+
if (idx >= 0)
|
|
69
|
+
store.suggestions[idx] = suggestion;
|
|
70
|
+
else
|
|
71
|
+
store.suggestions.push(suggestion);
|
|
72
|
+
if (store.suggestions.length > 200)
|
|
73
|
+
store.suggestions = store.suggestions.slice(-200);
|
|
74
|
+
saveStore(store);
|
|
75
|
+
return suggestion;
|
|
76
|
+
}
|
|
77
|
+
function generateCodeowners(suggestions) {
|
|
78
|
+
const lines = [
|
|
79
|
+
"# CODEOWNERS — Generated by judges code-owner-suggest",
|
|
80
|
+
"# Review and customize before committing",
|
|
81
|
+
"",
|
|
82
|
+
];
|
|
83
|
+
const grouped = new Map();
|
|
84
|
+
for (const s of suggestions) {
|
|
85
|
+
const existing = grouped.get(s.suggestedOwner) || [];
|
|
86
|
+
existing.push(s.path);
|
|
87
|
+
grouped.set(s.suggestedOwner, existing);
|
|
88
|
+
}
|
|
89
|
+
for (const [owner, paths] of grouped) {
|
|
90
|
+
for (const p of paths) {
|
|
91
|
+
lines.push(`${p} @${owner}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return lines.join("\n") + "\n";
|
|
95
|
+
}
|
|
96
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
97
|
+
export function runCodeOwnerSuggest(argv) {
|
|
98
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
99
|
+
console.log(`
|
|
100
|
+
judges code-owner-suggest — Auto-recommend CODEOWNERS entries
|
|
101
|
+
|
|
102
|
+
Usage:
|
|
103
|
+
judges code-owner-suggest --analyze
|
|
104
|
+
judges code-owner-suggest --suggest --path "src/auth/" --owner "alice@co.com" --rules SEC,AUTH
|
|
105
|
+
judges code-owner-suggest --export
|
|
106
|
+
judges code-owner-suggest --export --out CODEOWNERS
|
|
107
|
+
|
|
108
|
+
Options:
|
|
109
|
+
--analyze Auto-suggest from dev-score and finding data
|
|
110
|
+
--suggest Manually add a suggestion
|
|
111
|
+
--path <path> File/directory path for suggestion
|
|
112
|
+
--owner <name> Owner email/username
|
|
113
|
+
--rules <csv> Rule categories (comma-separated)
|
|
114
|
+
--export Export as CODEOWNERS format
|
|
115
|
+
--out <file> Write CODEOWNERS to file
|
|
116
|
+
--format json JSON output
|
|
117
|
+
--help, -h Show this help
|
|
118
|
+
`);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
122
|
+
// Manual suggestion
|
|
123
|
+
if (argv.includes("--suggest")) {
|
|
124
|
+
const path = argv.find((_a, i) => argv[i - 1] === "--path");
|
|
125
|
+
const owner = argv.find((_a, i) => argv[i - 1] === "--owner");
|
|
126
|
+
const rulesStr = argv.find((_a, i) => argv[i - 1] === "--rules");
|
|
127
|
+
if (!path || !owner) {
|
|
128
|
+
console.error(" --path and --owner required for --suggest");
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const rules = rulesStr ? rulesStr.split(",") : [];
|
|
132
|
+
const suggestion = suggestOwner(path, owner, rules);
|
|
133
|
+
if (format === "json") {
|
|
134
|
+
console.log(JSON.stringify(suggestion, null, 2));
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
console.log(`\n ✅ Suggestion recorded:`);
|
|
138
|
+
console.log(` ${suggestion.path} → @${suggestion.suggestedOwner} (${suggestion.confidence}% confidence)`);
|
|
139
|
+
console.log(` Reason: ${suggestion.reason}\n`);
|
|
140
|
+
}
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
// Auto-analyze
|
|
144
|
+
if (argv.includes("--analyze")) {
|
|
145
|
+
const devs = loadScoreData();
|
|
146
|
+
if (devs.length === 0) {
|
|
147
|
+
console.log(" No dev-score data found. Record developer activity with `judges dev-score` first.");
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const suggestions = [];
|
|
151
|
+
// Map categories to path prefixes
|
|
152
|
+
const categoryPaths = {
|
|
153
|
+
SEC: "src/security/",
|
|
154
|
+
AUTH: "src/auth/",
|
|
155
|
+
SQL: "src/database/",
|
|
156
|
+
XSS: "src/frontend/",
|
|
157
|
+
CRYPTO: "src/crypto/",
|
|
158
|
+
SSRF: "src/network/",
|
|
159
|
+
CMD: "src/commands/",
|
|
160
|
+
};
|
|
161
|
+
for (const dev of devs) {
|
|
162
|
+
for (const cat of dev.categories) {
|
|
163
|
+
const path = categoryPaths[cat] || `src/${cat.toLowerCase()}/`;
|
|
164
|
+
suggestions.push(suggestOwner(path, dev.author, [cat]));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (format === "json") {
|
|
168
|
+
console.log(JSON.stringify(suggestions, null, 2));
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
console.log(`\n Auto-Analyzed Code Owners (${suggestions.length} suggestions)\n ──────────────────────────`);
|
|
172
|
+
for (const s of suggestions) {
|
|
173
|
+
console.log(` ${s.path.padEnd(25)} → @${s.suggestedOwner.padEnd(20)} ${s.ruleCategories.join(",")}`);
|
|
174
|
+
}
|
|
175
|
+
console.log(`\n Export with: judges code-owner-suggest --export\n`);
|
|
176
|
+
}
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
// Export
|
|
180
|
+
if (argv.includes("--export")) {
|
|
181
|
+
const store = loadStore();
|
|
182
|
+
if (store.suggestions.length === 0) {
|
|
183
|
+
console.log(" No suggestions yet. Use --analyze or --suggest first.");
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
const content = generateCodeowners(store.suggestions);
|
|
187
|
+
const outPath = argv.find((_a, i) => argv[i - 1] === "--out");
|
|
188
|
+
if (outPath) {
|
|
189
|
+
writeFileSync(outPath, content);
|
|
190
|
+
console.log(` ✅ Written to ${outPath} (${store.suggestions.length} entries)`);
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
console.log(content);
|
|
194
|
+
}
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
// Default: show current suggestions
|
|
198
|
+
const store = loadStore();
|
|
199
|
+
if (format === "json") {
|
|
200
|
+
console.log(JSON.stringify(store, null, 2));
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
console.log(`\n Code Owner Suggestions (${store.suggestions.length})\n ──────────────────────────`);
|
|
204
|
+
if (store.suggestions.length === 0) {
|
|
205
|
+
console.log(" No suggestions yet. Use --analyze or --suggest to add.");
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
for (const s of store.suggestions) {
|
|
209
|
+
console.log(` ${s.path.padEnd(25)} → @${s.suggestedOwner.padEnd(20)} ${s.confidence}% ${s.ruleCategories.join(",")}`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
console.log("");
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=code-owner-suggest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-owner-suggest.js","sourceRoot":"","sources":["../../src/commands/code-owner-suggest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cost forecast — projects 30/60/90-day security debt and
|
|
3
|
+
* remediation cost trends from local finding history.
|
|
4
|
+
*
|
|
5
|
+
* All data stays local — no upload or external services.
|
|
6
|
+
*/
|
|
7
|
+
interface CostSnapshot {
|
|
8
|
+
date: string;
|
|
9
|
+
critical: number;
|
|
10
|
+
high: number;
|
|
11
|
+
medium: number;
|
|
12
|
+
low: number;
|
|
13
|
+
totalFindings: number;
|
|
14
|
+
estimatedCost: number;
|
|
15
|
+
}
|
|
16
|
+
export declare function recordSnapshot(critical: number, high: number, medium: number, low: number): CostSnapshot;
|
|
17
|
+
export declare function runCostForecast(argv: string[]): void;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=cost-forecast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cost-forecast.d.ts","sourceRoot":"","sources":["../../src/commands/cost-forecast.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACvB;AAoDD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CAkDxG;AAID,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA6GpD"}
|