@kevinrabun/judges 3.45.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 +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/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/audit-bundle.d.ts +29 -0
- package/dist/commands/audit-bundle.d.ts.map +1 -0
- package/dist/commands/audit-bundle.js +235 -0
- package/dist/commands/audit-bundle.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/config-drift.d.ts +25 -0
- package/dist/commands/config-drift.d.ts.map +1 -0
- package/dist/commands/config-drift.js +214 -0
- package/dist/commands/config-drift.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/dev-score.d.ts +37 -0
- package/dist/commands/dev-score.d.ts.map +1 -0
- package/dist/commands/dev-score.js +204 -0
- package/dist/commands/dev-score.js.map +1 -0
- package/dist/commands/generate.d.ts +8 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +404 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/learn.d.ts +27 -0
- package/dist/commands/learn.d.ts.map +1 -0
- package/dist/commands/learn.js +289 -0
- package/dist/commands/learn.js.map +1 -0
- package/dist/commands/model-risk.d.ts +28 -0
- package/dist/commands/model-risk.d.ts.map +1 -0
- package/dist/commands/model-risk.js +221 -0
- package/dist/commands/model-risk.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/reg-watch.d.ts +21 -0
- package/dist/commands/reg-watch.d.ts.map +1 -0
- package/dist/commands/reg-watch.js +220 -0
- package/dist/commands/reg-watch.js.map +1 -0
- package/dist/commands/retro.d.ts +23 -0
- package/dist/commands/retro.d.ts.map +1 -0
- package/dist/commands/retro.js +217 -0
- package/dist/commands/retro.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,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,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config drift detector — compare team configurations against an
|
|
3
|
+
* organizational baseline to detect policy divergence.
|
|
4
|
+
*
|
|
5
|
+
* Uses local .judgesrc files.
|
|
6
|
+
*/
|
|
7
|
+
interface DriftItem {
|
|
8
|
+
type: "disabled-rule" | "disabled-judge" | "severity-override" | "missing-preset" | "extra-rule";
|
|
9
|
+
key: string;
|
|
10
|
+
baselineValue?: string;
|
|
11
|
+
actualValue?: string;
|
|
12
|
+
impact: "high" | "medium" | "low";
|
|
13
|
+
}
|
|
14
|
+
interface ConfigDriftReport {
|
|
15
|
+
configFile: string;
|
|
16
|
+
baselineFile: string;
|
|
17
|
+
driftScore: number;
|
|
18
|
+
items: DriftItem[];
|
|
19
|
+
summary: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function detectDrift(baselineFile: string, configFile: string): ConfigDriftReport;
|
|
22
|
+
export declare function scanDirectory(baselineFile: string, dir: string): ConfigDriftReport[];
|
|
23
|
+
export declare function runConfigDrift(argv: string[]): void;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=config-drift.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-drift.d.ts","sourceRoot":"","sources":["../../src/commands/config-drift.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,UAAU,SAAS;IACjB,IAAI,EAAE,eAAe,GAAG,gBAAgB,GAAG,mBAAmB,GAAG,gBAAgB,GAAG,YAAY,CAAC;IACjG,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;CACnC;AAED,UAAU,iBAAiB;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAaD,wBAAgB,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,iBAAiB,CAuFvF;AAED,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAqBpF;AAID,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAgFnD"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config drift detector — compare team configurations against an
|
|
3
|
+
* organizational baseline to detect policy divergence.
|
|
4
|
+
*
|
|
5
|
+
* Uses local .judgesrc files.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync, existsSync, readdirSync, statSync } from "fs";
|
|
8
|
+
import { join, basename } from "path";
|
|
9
|
+
// ─── Core ───────────────────────────────────────────────────────────────────
|
|
10
|
+
function loadConfig(file) {
|
|
11
|
+
if (!existsSync(file))
|
|
12
|
+
return {};
|
|
13
|
+
try {
|
|
14
|
+
return JSON.parse(readFileSync(file, "utf-8"));
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return {};
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export function detectDrift(baselineFile, configFile) {
|
|
21
|
+
const baseline = loadConfig(baselineFile);
|
|
22
|
+
const config = loadConfig(configFile);
|
|
23
|
+
const items = [];
|
|
24
|
+
// Check disabled rules
|
|
25
|
+
const baselineDisabledRules = new Set(baseline.disabledRules || []);
|
|
26
|
+
const configDisabledRules = new Set(config.disabledRules || []);
|
|
27
|
+
for (const rule of configDisabledRules) {
|
|
28
|
+
if (!baselineDisabledRules.has(rule)) {
|
|
29
|
+
items.push({
|
|
30
|
+
type: "disabled-rule",
|
|
31
|
+
key: rule,
|
|
32
|
+
baselineValue: "enabled",
|
|
33
|
+
actualValue: "disabled",
|
|
34
|
+
impact: rule.startsWith("SEC") || rule.startsWith("AUTH") || rule.startsWith("CRYPTO") ? "high" : "medium",
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// Check disabled judges
|
|
39
|
+
const baselineDisabledJudges = new Set(baseline.disabledJudges || []);
|
|
40
|
+
const configDisabledJudges = new Set(config.disabledJudges || []);
|
|
41
|
+
for (const judge of configDisabledJudges) {
|
|
42
|
+
if (!baselineDisabledJudges.has(judge)) {
|
|
43
|
+
items.push({
|
|
44
|
+
type: "disabled-judge",
|
|
45
|
+
key: judge,
|
|
46
|
+
baselineValue: "enabled",
|
|
47
|
+
actualValue: "disabled",
|
|
48
|
+
impact: ["cybersecurity", "authentication", "injection"].includes(judge) ? "high" : "medium",
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Check severity overrides
|
|
53
|
+
const baselineOverrides = (baseline.ruleOverrides || {});
|
|
54
|
+
const configOverrides = (config.ruleOverrides || {});
|
|
55
|
+
for (const [ruleId, override] of Object.entries(configOverrides)) {
|
|
56
|
+
const baseOverride = baselineOverrides[ruleId];
|
|
57
|
+
if (override.severity && (!baseOverride || override.severity !== baseOverride.severity)) {
|
|
58
|
+
const severityOrder = ["critical", "high", "medium", "low"];
|
|
59
|
+
const configIdx = severityOrder.indexOf(override.severity);
|
|
60
|
+
const baseIdx = baseOverride ? severityOrder.indexOf(baseOverride.severity) : -1;
|
|
61
|
+
const weakened = configIdx > baseIdx;
|
|
62
|
+
items.push({
|
|
63
|
+
type: "severity-override",
|
|
64
|
+
key: ruleId,
|
|
65
|
+
baselineValue: baseOverride?.severity || "default",
|
|
66
|
+
actualValue: override.severity,
|
|
67
|
+
impact: weakened ? "high" : "low",
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Check preset alignment
|
|
72
|
+
if (baseline.preset && config.preset !== baseline.preset) {
|
|
73
|
+
items.push({
|
|
74
|
+
type: "missing-preset",
|
|
75
|
+
key: "preset",
|
|
76
|
+
baselineValue: baseline.preset,
|
|
77
|
+
actualValue: config.preset || "none",
|
|
78
|
+
impact: "medium",
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
// Drift score
|
|
82
|
+
const highCount = items.filter((i) => i.impact === "high").length;
|
|
83
|
+
const medCount = items.filter((i) => i.impact === "medium").length;
|
|
84
|
+
const lowCount = items.filter((i) => i.impact === "low").length;
|
|
85
|
+
const driftScore = Math.min(100, highCount * 20 + medCount * 10 + lowCount * 5);
|
|
86
|
+
return {
|
|
87
|
+
configFile,
|
|
88
|
+
baselineFile,
|
|
89
|
+
driftScore,
|
|
90
|
+
items,
|
|
91
|
+
summary: items.length === 0
|
|
92
|
+
? "Configuration is aligned with baseline."
|
|
93
|
+
: `${items.length} deviation(s) detected. Drift score: ${driftScore}/100.`,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
export function scanDirectory(baselineFile, dir) {
|
|
97
|
+
const reports = [];
|
|
98
|
+
function walk(d) {
|
|
99
|
+
for (const entry of readdirSync(d)) {
|
|
100
|
+
const full = join(d, entry);
|
|
101
|
+
try {
|
|
102
|
+
const stat = statSync(full);
|
|
103
|
+
if (stat.isDirectory() && !entry.startsWith(".") && entry !== "node_modules") {
|
|
104
|
+
walk(full);
|
|
105
|
+
}
|
|
106
|
+
else if (entry === ".judgesrc" || entry === ".judgesrc.json") {
|
|
107
|
+
reports.push(detectDrift(baselineFile, full));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
// Skip inaccessible entries
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
walk(dir);
|
|
116
|
+
return reports;
|
|
117
|
+
}
|
|
118
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
119
|
+
export function runConfigDrift(argv) {
|
|
120
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
121
|
+
console.log(`
|
|
122
|
+
judges config-drift — Detect configuration divergence from baseline
|
|
123
|
+
|
|
124
|
+
Usage:
|
|
125
|
+
judges config-drift --baseline org-baseline.judgesrc --config team/.judgesrc
|
|
126
|
+
judges config-drift --baseline org-baseline.judgesrc --scan ./teams/
|
|
127
|
+
judges config-drift --baseline org-baseline.judgesrc --self
|
|
128
|
+
|
|
129
|
+
Options:
|
|
130
|
+
--baseline <file> Organization baseline config file
|
|
131
|
+
--config <file> Team config to compare
|
|
132
|
+
--scan <dir> Scan directory for .judgesrc files and compare all
|
|
133
|
+
--self Compare local .judgesrc against baseline
|
|
134
|
+
--format json JSON output
|
|
135
|
+
--help, -h Show this help
|
|
136
|
+
`);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
140
|
+
const baselineFile = argv.find((_a, i) => argv[i - 1] === "--baseline");
|
|
141
|
+
if (!baselineFile) {
|
|
142
|
+
console.error(" ❌ Provide --baseline <file>. Use --help for usage.");
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (!existsSync(baselineFile)) {
|
|
146
|
+
console.error(` ❌ Baseline not found: ${baselineFile}`);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
// Scan directory
|
|
150
|
+
const scanDir = argv.find((_a, i) => argv[i - 1] === "--scan");
|
|
151
|
+
if (scanDir) {
|
|
152
|
+
const reports = scanDirectory(baselineFile, scanDir);
|
|
153
|
+
if (format === "json") {
|
|
154
|
+
console.log(JSON.stringify(reports, null, 2));
|
|
155
|
+
}
|
|
156
|
+
else if (reports.length === 0) {
|
|
157
|
+
console.log("\n No .judgesrc files found in scan directory.\n");
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
console.log(`\n Config Drift Scan (${reports.length} config(s))\n ──────────────────────────────`);
|
|
161
|
+
for (const r of reports) {
|
|
162
|
+
const icon = r.driftScore === 0 ? "✅" : r.driftScore > 50 ? "🚨" : "⚠️";
|
|
163
|
+
console.log(` ${icon} ${basename(r.configFile).padEnd(20)} drift: ${r.driftScore}/100 (${r.items.length} item(s))`);
|
|
164
|
+
}
|
|
165
|
+
console.log("");
|
|
166
|
+
}
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
// Compare self
|
|
170
|
+
if (argv.includes("--self")) {
|
|
171
|
+
const localConfig = existsSync(".judgesrc") ? ".judgesrc" : ".judgesrc.json";
|
|
172
|
+
if (!existsSync(localConfig)) {
|
|
173
|
+
console.error(" ❌ No local .judgesrc found");
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const report = detectDrift(baselineFile, localConfig);
|
|
177
|
+
printReport(report, format);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
// Compare specific config
|
|
181
|
+
const configFile = argv.find((_a, i) => argv[i - 1] === "--config");
|
|
182
|
+
if (configFile) {
|
|
183
|
+
if (!existsSync(configFile)) {
|
|
184
|
+
console.error(` ❌ Config not found: ${configFile}`);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const report = detectDrift(baselineFile, configFile);
|
|
188
|
+
printReport(report, format);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
console.error(" ❌ Provide --config, --scan, or --self. Use --help for usage.");
|
|
192
|
+
}
|
|
193
|
+
function printReport(report, format) {
|
|
194
|
+
if (format === "json") {
|
|
195
|
+
console.log(JSON.stringify(report, null, 2));
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const icon = report.driftScore === 0 ? "✅" : report.driftScore > 50 ? "🚨" : "⚠️";
|
|
199
|
+
console.log(`\n ${icon} Config Drift Report`);
|
|
200
|
+
console.log(` Baseline: ${report.baselineFile}`);
|
|
201
|
+
console.log(` Config: ${report.configFile}`);
|
|
202
|
+
console.log(` Drift Score: ${report.driftScore}/100`);
|
|
203
|
+
console.log(` ─────────────────────────`);
|
|
204
|
+
if (report.items.length === 0) {
|
|
205
|
+
console.log(" Configuration is aligned with baseline.\n");
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
for (const item of report.items) {
|
|
209
|
+
const impactIcon = item.impact === "high" ? "🔴" : item.impact === "medium" ? "🟡" : "🟢";
|
|
210
|
+
console.log(` ${impactIcon} [${item.type}] ${item.key}: ${item.baselineValue} → ${item.actualValue}`);
|
|
211
|
+
}
|
|
212
|
+
console.log("");
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=config-drift.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-drift.js","sourceRoot":"","sources":["../../src/commands/config-drift.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"}
|