@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.
Files changed (74) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +112 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/assign-findings.d.ts +37 -0
  6. package/dist/commands/assign-findings.d.ts.map +1 -0
  7. package/dist/commands/assign-findings.js +178 -0
  8. package/dist/commands/assign-findings.js.map +1 -0
  9. package/dist/commands/burndown.d.ts +27 -0
  10. package/dist/commands/burndown.d.ts.map +1 -0
  11. package/dist/commands/burndown.js +180 -0
  12. package/dist/commands/burndown.js.map +1 -0
  13. package/dist/commands/ci-template.d.ts +15 -0
  14. package/dist/commands/ci-template.d.ts.map +1 -0
  15. package/dist/commands/ci-template.js +212 -0
  16. package/dist/commands/ci-template.js.map +1 -0
  17. package/dist/commands/false-negatives.d.ts +35 -0
  18. package/dist/commands/false-negatives.d.ts.map +1 -0
  19. package/dist/commands/false-negatives.js +166 -0
  20. package/dist/commands/false-negatives.js.map +1 -0
  21. package/dist/commands/hook-install.d.ts +22 -0
  22. package/dist/commands/hook-install.d.ts.map +1 -0
  23. package/dist/commands/hook-install.js +143 -0
  24. package/dist/commands/hook-install.js.map +1 -0
  25. package/dist/commands/kb.d.ts +41 -0
  26. package/dist/commands/kb.d.ts.map +1 -0
  27. package/dist/commands/kb.js +231 -0
  28. package/dist/commands/kb.js.map +1 -0
  29. package/dist/commands/noise-advisor.d.ts +30 -0
  30. package/dist/commands/noise-advisor.d.ts.map +1 -0
  31. package/dist/commands/noise-advisor.js +171 -0
  32. package/dist/commands/noise-advisor.js.map +1 -0
  33. package/dist/commands/policy-audit.d.ts +53 -0
  34. package/dist/commands/policy-audit.d.ts.map +1 -0
  35. package/dist/commands/policy-audit.js +161 -0
  36. package/dist/commands/policy-audit.js.map +1 -0
  37. package/dist/commands/recommend.d.ts +21 -0
  38. package/dist/commands/recommend.d.ts.map +1 -0
  39. package/dist/commands/recommend.js +283 -0
  40. package/dist/commands/recommend.js.map +1 -0
  41. package/dist/commands/regression-alert.d.ts +32 -0
  42. package/dist/commands/regression-alert.d.ts.map +1 -0
  43. package/dist/commands/regression-alert.js +216 -0
  44. package/dist/commands/regression-alert.js.map +1 -0
  45. package/dist/commands/remediation.d.ts +21 -0
  46. package/dist/commands/remediation.d.ts.map +1 -0
  47. package/dist/commands/remediation.js +257 -0
  48. package/dist/commands/remediation.js.map +1 -0
  49. package/dist/commands/report-template.d.ts +17 -0
  50. package/dist/commands/report-template.d.ts.map +1 -0
  51. package/dist/commands/report-template.js +291 -0
  52. package/dist/commands/report-template.js.map +1 -0
  53. package/dist/commands/review-queue.d.ts +34 -0
  54. package/dist/commands/review-queue.d.ts.map +1 -0
  55. package/dist/commands/review-queue.js +226 -0
  56. package/dist/commands/review-queue.js.map +1 -0
  57. package/dist/commands/rule-owner.d.ts +31 -0
  58. package/dist/commands/rule-owner.d.ts.map +1 -0
  59. package/dist/commands/rule-owner.js +182 -0
  60. package/dist/commands/rule-owner.js.map +1 -0
  61. package/dist/commands/sla-track.d.ts +57 -0
  62. package/dist/commands/sla-track.d.ts.map +1 -0
  63. package/dist/commands/sla-track.js +269 -0
  64. package/dist/commands/sla-track.js.map +1 -0
  65. package/dist/commands/suppress.d.ts +40 -0
  66. package/dist/commands/suppress.d.ts.map +1 -0
  67. package/dist/commands/suppress.js +209 -0
  68. package/dist/commands/suppress.js.map +1 -0
  69. package/dist/commands/ticket-sync.d.ts +26 -0
  70. package/dist/commands/ticket-sync.d.ts.map +1 -0
  71. package/dist/commands/ticket-sync.js +236 -0
  72. package/dist/commands/ticket-sync.js.map +1 -0
  73. package/package.json +1 -1
  74. package/server.json +2 -2
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Policy audit trail — record which rules/judges were active at evaluation
3
+ * time, creating an immutable local audit log for compliance proof.
4
+ *
5
+ * Enables SOC2/ISO27001 auditors to verify that security policies were
6
+ * enforced at the time of each evaluation. All data stays local.
7
+ */
8
+ import { createHash } from "crypto";
9
+ // ─── Policy Snapshot ────────────────────────────────────────────────────────
10
+ export function capturePolicySnapshot(config, configPath, enabledJudges, version) {
11
+ const { execSync } = require("child_process");
12
+ let gitCommit;
13
+ try {
14
+ gitCommit = execSync("git rev-parse HEAD", { encoding: "utf-8" }).trim();
15
+ }
16
+ catch {
17
+ /* not in git */
18
+ }
19
+ const snapshot = {
20
+ policyHash: "",
21
+ timestamp: new Date().toISOString(),
22
+ configPath,
23
+ presets: config.preset ? [config.preset] : [],
24
+ enabledJudges,
25
+ disabledJudges: config.disabledJudges || [],
26
+ disabledRules: config.disabledRules || [],
27
+ ruleOverrides: config.ruleOverrides || {},
28
+ minSeverity: config.minSeverity || "info",
29
+ gitCommit,
30
+ version,
31
+ };
32
+ // Compute deterministic hash of policy state
33
+ const hashInput = JSON.stringify({
34
+ presets: snapshot.presets,
35
+ enabledJudges: snapshot.enabledJudges.sort(),
36
+ disabledJudges: snapshot.disabledJudges.sort(),
37
+ disabledRules: snapshot.disabledRules.sort(),
38
+ ruleOverrides: snapshot.ruleOverrides,
39
+ minSeverity: snapshot.minSeverity,
40
+ });
41
+ snapshot.policyHash = createHash("sha256").update(hashInput).digest("hex").slice(0, 16);
42
+ return snapshot;
43
+ }
44
+ // ─── Audit Log Management ──────────────────────────────────────────────────
45
+ const AUDIT_FILE = ".judges-audit.json";
46
+ function loadAuditLog() {
47
+ const { readFileSync, existsSync } = require("fs");
48
+ if (existsSync(AUDIT_FILE)) {
49
+ try {
50
+ return JSON.parse(readFileSync(AUDIT_FILE, "utf-8"));
51
+ }
52
+ catch {
53
+ /* corrupt file */
54
+ }
55
+ }
56
+ return { entries: [], version: "1.0" };
57
+ }
58
+ function saveAuditLog(log) {
59
+ const { writeFileSync } = require("fs");
60
+ writeFileSync(AUDIT_FILE, JSON.stringify(log, null, 2), "utf-8");
61
+ }
62
+ export function recordAuditEntry(policySnapshot, verdict, filesEvaluated) {
63
+ const entry = {
64
+ id: createHash("sha256")
65
+ .update(policySnapshot.timestamp + policySnapshot.policyHash)
66
+ .digest("hex")
67
+ .slice(0, 12),
68
+ timestamp: policySnapshot.timestamp,
69
+ policySnapshot,
70
+ verdictSummary: {
71
+ verdict: verdict.overallVerdict,
72
+ score: verdict.overallScore,
73
+ criticalCount: verdict.criticalCount,
74
+ highCount: verdict.highCount,
75
+ totalFindings: verdict.findings.length,
76
+ },
77
+ filesEvaluated,
78
+ };
79
+ const log = loadAuditLog();
80
+ log.entries.push(entry);
81
+ // Keep last 1000 entries
82
+ if (log.entries.length > 1000) {
83
+ log.entries = log.entries.slice(-1000);
84
+ }
85
+ saveAuditLog(log);
86
+ return entry;
87
+ }
88
+ // ─── CLI ────────────────────────────────────────────────────────────────────
89
+ export function runPolicyAudit(argv) {
90
+ if (argv.includes("--help") || argv.includes("-h")) {
91
+ console.log(`
92
+ judges policy-audit — View and manage the policy audit trail
93
+
94
+ Usage:
95
+ judges policy-audit Show recent audit entries
96
+ judges policy-audit --last 10 Show last 10 entries
97
+ judges policy-audit --diff Compare current policy to last evaluation
98
+ judges policy-audit --export audit.json Export full audit log
99
+
100
+ Options:
101
+ --last <n> Show last N entries (default: 5)
102
+ --diff Show policy changes since last evaluation
103
+ --export <path> Export audit log to file
104
+ --format json JSON output
105
+ --help, -h Show this help
106
+
107
+ The audit trail records which rules, judges, and configs were active at
108
+ each evaluation time. Useful for SOC2/ISO27001 compliance proof.
109
+ `);
110
+ return;
111
+ }
112
+ const { readFileSync, existsSync, writeFileSync } = require("fs");
113
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
114
+ const lastN = parseInt(argv.find((_a, i) => argv[i - 1] === "--last") || "5", 10);
115
+ const exportPath = argv.find((_a, i) => argv[i - 1] === "--export");
116
+ if (!existsSync(AUDIT_FILE)) {
117
+ console.log("\n No audit trail found. Run an evaluation first.\n");
118
+ return;
119
+ }
120
+ const log = JSON.parse(readFileSync(AUDIT_FILE, "utf-8"));
121
+ if (exportPath) {
122
+ writeFileSync(exportPath, JSON.stringify(log, null, 2), "utf-8");
123
+ console.log(` Exported ${log.entries.length} audit entries to ${exportPath}`);
124
+ return;
125
+ }
126
+ const entries = log.entries.slice(-lastN);
127
+ if (format === "json") {
128
+ console.log(JSON.stringify(entries, null, 2));
129
+ return;
130
+ }
131
+ if (argv.includes("--diff") && log.entries.length >= 2) {
132
+ const prev = log.entries[log.entries.length - 2].policySnapshot;
133
+ const curr = log.entries[log.entries.length - 1].policySnapshot;
134
+ console.log("\n Policy Diff (last two evaluations)\n");
135
+ if (prev.policyHash !== curr.policyHash) {
136
+ console.log(" ⚠️ Policy changed!\n");
137
+ const addedJudges = curr.enabledJudges.filter((j) => !prev.enabledJudges.includes(j));
138
+ const removedJudges = prev.enabledJudges.filter((j) => !curr.enabledJudges.includes(j));
139
+ if (addedJudges.length)
140
+ console.log(` + Added judges: ${addedJudges.join(", ")}`);
141
+ if (removedJudges.length)
142
+ console.log(` - Removed judges: ${removedJudges.join(", ")}`);
143
+ if (prev.minSeverity !== curr.minSeverity)
144
+ console.log(` ~ Severity: ${prev.minSeverity} → ${curr.minSeverity}`);
145
+ }
146
+ else {
147
+ console.log(" ✅ No policy changes\n");
148
+ }
149
+ console.log("");
150
+ return;
151
+ }
152
+ console.log(`\n Policy Audit Trail (last ${entries.length} of ${log.entries.length})\n`);
153
+ for (const e of entries) {
154
+ const v = e.verdictSummary;
155
+ console.log(` ${e.id} ${e.timestamp}`);
156
+ console.log(` Policy: ${e.policySnapshot.policyHash} Judges: ${e.policySnapshot.enabledJudges.length} Commit: ${e.policySnapshot.gitCommit?.slice(0, 8) || "N/A"}`);
157
+ console.log(` Verdict: ${v.verdict} Score: ${v.score} Critical: ${v.criticalCount} High: ${v.highCount} Findings: ${v.totalFindings}`);
158
+ console.log("");
159
+ }
160
+ }
161
+ //# sourceMappingURL=policy-audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy-audit.js","sourceRoot":"","sources":["../../src/commands/policy-audit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Rule recommendations — analyze project stack and suggest which
3
+ * judges/rules are most relevant.
4
+ *
5
+ * Uses local file analysis only — no external services.
6
+ */
7
+ export interface StackSignal {
8
+ framework: string;
9
+ confidence: number;
10
+ detectedVia: string;
11
+ }
12
+ export interface JudgeRecommendation {
13
+ judgeId: string;
14
+ relevance: "high" | "medium" | "low";
15
+ reason: string;
16
+ estimatedCoverage: string;
17
+ }
18
+ export declare function detectStack(dir?: string): StackSignal[];
19
+ export declare function getRecommendations(dir?: string): JudgeRecommendation[];
20
+ export declare function runRecommend(argv: string[]): void;
21
+ //# sourceMappingURL=recommend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recommend.d.ts","sourceRoot":"","sources":["../../src/commands/recommend.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AA+ED,wBAAgB,WAAW,CAAC,GAAG,SAAM,GAAG,WAAW,EAAE,CAuDpD;AAgBD,wBAAgB,kBAAkB,CAAC,GAAG,SAAM,GAAG,mBAAmB,EAAE,CAsEnE;AAID,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAmEjD"}
@@ -0,0 +1,283 @@
1
+ /**
2
+ * Rule recommendations — analyze project stack and suggest which
3
+ * judges/rules are most relevant.
4
+ *
5
+ * Uses local file analysis only — no external services.
6
+ */
7
+ import { readdirSync, readFileSync, existsSync, statSync } from "fs";
8
+ import { join, extname } from "path";
9
+ import { defaultRegistry } from "../judge-registry.js";
10
+ // ─── Stack Detection ────────────────────────────────────────────────────────
11
+ const FRAMEWORK_SIGNALS = [
12
+ { framework: "React", files: [], deps: ["react", "react-dom", "next", "@remix-run/react"] },
13
+ { framework: "Next.js", files: ["next.config.js", "next.config.mjs", "next.config.ts"], deps: ["next"] },
14
+ { framework: "Express", files: [], deps: ["express"] },
15
+ { framework: "FastAPI", files: [], deps: ["fastapi", "uvicorn"] },
16
+ { framework: "Django", files: ["manage.py", "settings.py"], deps: ["django"] },
17
+ { framework: "Spring Boot", files: ["pom.xml", "build.gradle"], deps: ["spring-boot"] },
18
+ { framework: "Rails", files: ["Gemfile", "config/routes.rb"], deps: ["rails"] },
19
+ { framework: "Terraform", files: [], deps: [] },
20
+ { framework: "Kubernetes", files: [], deps: [] },
21
+ { framework: "Docker", files: ["Dockerfile", "docker-compose.yml", "docker-compose.yaml"], deps: [] },
22
+ { framework: "Vue", files: [], deps: ["vue", "nuxt"] },
23
+ { framework: "Angular", files: ["angular.json"], deps: ["@angular/core"] },
24
+ { framework: "Svelte", files: ["svelte.config.js"], deps: ["svelte", "@sveltejs/kit"] },
25
+ { framework: "Flask", files: [], deps: ["flask"] },
26
+ { framework: "Go", files: ["go.mod", "go.sum"], deps: [] },
27
+ { framework: "Rust", files: ["Cargo.toml"], deps: [] },
28
+ ];
29
+ function scanDirectory(dir, depth = 0, maxDepth = 3) {
30
+ if (depth > maxDepth)
31
+ return [];
32
+ const files = [];
33
+ try {
34
+ for (const entry of readdirSync(dir)) {
35
+ if (entry.startsWith(".") || entry === "node_modules" || entry === "vendor" || entry === "dist")
36
+ continue;
37
+ const full = join(dir, entry);
38
+ try {
39
+ const stat = statSync(full);
40
+ if (stat.isFile())
41
+ files.push(entry);
42
+ else if (stat.isDirectory())
43
+ files.push(...scanDirectory(full, depth + 1, maxDepth).map((f) => `${entry}/${f}`));
44
+ }
45
+ catch {
46
+ /* skip */
47
+ }
48
+ }
49
+ }
50
+ catch {
51
+ /* skip */
52
+ }
53
+ return files;
54
+ }
55
+ function detectLanguages(files) {
56
+ const extMap = {
57
+ ".ts": "TypeScript",
58
+ ".tsx": "TypeScript",
59
+ ".js": "JavaScript",
60
+ ".jsx": "JavaScript",
61
+ ".py": "Python",
62
+ ".java": "Java",
63
+ ".go": "Go",
64
+ ".rs": "Rust",
65
+ ".cs": "C#",
66
+ ".cpp": "C++",
67
+ ".c": "C",
68
+ ".rb": "Ruby",
69
+ ".tf": "Terraform",
70
+ ".yaml": "YAML",
71
+ ".yml": "YAML",
72
+ ".sql": "SQL",
73
+ ".sh": "Shell",
74
+ ".ps1": "PowerShell",
75
+ };
76
+ const counts = {};
77
+ for (const f of files) {
78
+ const ext = extname(f);
79
+ const lang = extMap[ext];
80
+ if (lang)
81
+ counts[lang] = (counts[lang] || 0) + 1;
82
+ }
83
+ return counts;
84
+ }
85
+ export function detectStack(dir = ".") {
86
+ const files = scanDirectory(dir);
87
+ const signals = [];
88
+ // Check for framework config files
89
+ for (const fw of FRAMEWORK_SIGNALS) {
90
+ for (const file of fw.files) {
91
+ if (files.includes(file) || existsSync(join(dir, file))) {
92
+ signals.push({ framework: fw.framework, confidence: 0.9, detectedVia: `config file: ${file}` });
93
+ }
94
+ }
95
+ }
96
+ // Check package.json dependencies
97
+ const pkgPath = join(dir, "package.json");
98
+ if (existsSync(pkgPath)) {
99
+ try {
100
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
101
+ const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
102
+ for (const fw of FRAMEWORK_SIGNALS) {
103
+ for (const dep of fw.deps) {
104
+ if (allDeps[dep]) {
105
+ const existing = signals.find((s) => s.framework === fw.framework);
106
+ if (!existing) {
107
+ signals.push({ framework: fw.framework, confidence: 0.85, detectedVia: `package.json: ${dep}` });
108
+ }
109
+ }
110
+ }
111
+ }
112
+ }
113
+ catch {
114
+ /* skip */
115
+ }
116
+ }
117
+ // Check for Terraform files
118
+ if (files.some((f) => f.endsWith(".tf"))) {
119
+ signals.push({ framework: "Terraform", confidence: 0.95, detectedVia: "*.tf files" });
120
+ }
121
+ // Check for Kubernetes manifests
122
+ if (files.some((f) => f.endsWith(".yaml") || f.endsWith(".yml"))) {
123
+ for (const f of files.filter((f) => f.endsWith(".yaml") || f.endsWith(".yml"))) {
124
+ try {
125
+ const content = readFileSync(join(dir, f), "utf-8").slice(0, 500);
126
+ if (content.includes("apiVersion:") && content.includes("kind:")) {
127
+ signals.push({ framework: "Kubernetes", confidence: 0.9, detectedVia: `manifest: ${f}` });
128
+ break;
129
+ }
130
+ }
131
+ catch {
132
+ /* skip */
133
+ }
134
+ }
135
+ }
136
+ return signals;
137
+ }
138
+ // ─── Recommendation Engine ──────────────────────────────────────────────────
139
+ const JUDGE_FRAMEWORK_MAP = {
140
+ react: ["xss-judge", "frontend-judge"],
141
+ "next.js": ["xss-judge", "ssr-judge", "frontend-judge"],
142
+ express: ["injection-judge", "auth-judge", "ssrf-judge"],
143
+ fastapi: ["injection-judge", "auth-judge", "python-judge"],
144
+ django: ["injection-judge", "auth-judge", "python-judge"],
145
+ "spring boot": ["injection-judge", "auth-judge", "java-judge"],
146
+ terraform: ["iac-judge", "secrets-judge"],
147
+ kubernetes: ["iac-judge", "container-judge"],
148
+ docker: ["container-judge", "secrets-judge"],
149
+ };
150
+ export function getRecommendations(dir = ".") {
151
+ const stack = detectStack(dir);
152
+ const files = scanDirectory(dir);
153
+ const languages = detectLanguages(files);
154
+ const allJudges = defaultRegistry.getJudges().map((j) => j.id);
155
+ const recommendations = [];
156
+ const seen = new Set();
157
+ // Framework-specific recommendations
158
+ for (const signal of stack) {
159
+ const matching = JUDGE_FRAMEWORK_MAP[signal.framework.toLowerCase()] || [];
160
+ for (const judgeId of matching) {
161
+ if (seen.has(judgeId))
162
+ continue;
163
+ // Check if this judge actually exists
164
+ const actual = allJudges.find((j) => j.includes(judgeId.replace("-judge", "")));
165
+ if (actual) {
166
+ seen.add(actual);
167
+ recommendations.push({
168
+ judgeId: actual,
169
+ relevance: "high",
170
+ reason: `${signal.framework} detected (${signal.detectedVia}). This judge covers common ${signal.framework} patterns.`,
171
+ estimatedCoverage: "80-90%",
172
+ });
173
+ }
174
+ }
175
+ }
176
+ // Language-based recommendations
177
+ const topLang = Object.entries(languages)
178
+ .sort((a, b) => b[1] - a[1])
179
+ .slice(0, 3);
180
+ for (const [lang, count] of topLang) {
181
+ const percentage = Math.round((count / files.length) * 100);
182
+ if (percentage < 5)
183
+ continue;
184
+ for (const jId of allJudges) {
185
+ if (seen.has(jId))
186
+ continue;
187
+ if (jId.toLowerCase().includes(lang.toLowerCase().replace(/[#+]/g, ""))) {
188
+ seen.add(jId);
189
+ recommendations.push({
190
+ judgeId: jId,
191
+ relevance: "medium",
192
+ reason: `${lang} is ${percentage}% of your codebase (${count} files).`,
193
+ estimatedCoverage: "60-80%",
194
+ });
195
+ }
196
+ }
197
+ }
198
+ // Universal judges everyone should use
199
+ const universalJudges = ["security", "secrets", "error", "performance"];
200
+ for (const keyword of universalJudges) {
201
+ for (const jId of allJudges) {
202
+ if (seen.has(jId))
203
+ continue;
204
+ if (jId.toLowerCase().includes(keyword)) {
205
+ seen.add(jId);
206
+ recommendations.push({
207
+ judgeId: jId,
208
+ relevance: "medium",
209
+ reason: `Universal ${keyword} rules apply to all codebases.`,
210
+ estimatedCoverage: "70-85%",
211
+ });
212
+ }
213
+ }
214
+ }
215
+ return recommendations.sort((a, b) => {
216
+ const order = { high: 0, medium: 1, low: 2 };
217
+ return order[a.relevance] - order[b.relevance];
218
+ });
219
+ }
220
+ // ─── CLI ────────────────────────────────────────────────────────────────────
221
+ export function runRecommend(argv) {
222
+ if (argv.includes("--help") || argv.includes("-h")) {
223
+ console.log(`
224
+ judges recommend — Analyze project and recommend judges
225
+
226
+ Usage:
227
+ judges recommend Analyze current directory
228
+ judges recommend --dir /path Analyze specific directory
229
+ judges recommend --stack-only Only show detected stack
230
+
231
+ Options:
232
+ --dir <path> Directory to analyze (default: .)
233
+ --stack-only Only show detected frameworks
234
+ --format json JSON output
235
+ --help, -h Show this help
236
+ `);
237
+ return;
238
+ }
239
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
240
+ const dir = argv.find((_a, i) => argv[i - 1] === "--dir") || ".";
241
+ if (argv.includes("--stack-only")) {
242
+ const stack = detectStack(dir);
243
+ if (format === "json") {
244
+ console.log(JSON.stringify(stack, null, 2));
245
+ }
246
+ else if (stack.length === 0) {
247
+ console.log("\n No frameworks detected.\n");
248
+ }
249
+ else {
250
+ console.log("\n Detected Stack\n ──────────────");
251
+ for (const s of stack) {
252
+ console.log(` ${s.framework.padEnd(16)} (${(s.confidence * 100).toFixed(0)}%) via ${s.detectedVia}`);
253
+ }
254
+ console.log("");
255
+ }
256
+ return;
257
+ }
258
+ const recs = getRecommendations(dir);
259
+ const stack = detectStack(dir);
260
+ if (format === "json") {
261
+ console.log(JSON.stringify({ stack, recommendations: recs }, null, 2));
262
+ return;
263
+ }
264
+ console.log("\n Project Analysis\n ────────────────");
265
+ if (stack.length > 0) {
266
+ console.log("\n Detected stack:");
267
+ for (const s of stack) {
268
+ console.log(` ${s.framework.padEnd(16)} (${(s.confidence * 100).toFixed(0)}%) via ${s.detectedVia}`);
269
+ }
270
+ }
271
+ if (recs.length === 0) {
272
+ console.log("\n No specific recommendations. All judges are applicable.\n");
273
+ return;
274
+ }
275
+ console.log(`\n Recommended Judges (${recs.length}):\n`);
276
+ for (const r of recs) {
277
+ const icon = r.relevance === "high" ? "🟢" : r.relevance === "medium" ? "🟡" : "⚪";
278
+ console.log(` ${icon} ${r.judgeId.padEnd(25)} [${r.relevance}] coverage: ${r.estimatedCoverage}`);
279
+ console.log(` ${r.reason}`);
280
+ }
281
+ console.log("");
282
+ }
283
+ //# sourceMappingURL=recommend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recommend.js","sourceRoot":"","sources":["../../src/commands/recommend.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Regression alerting — compare current scan results against a saved
3
+ * baseline snapshot to detect quality regressions.
4
+ *
5
+ * Snapshots are stored locally in .judges-baseline.json.
6
+ */
7
+ import type { Finding } from "../types.js";
8
+ export interface BaselineSnapshot {
9
+ timestamp: string;
10
+ gitCommit?: string;
11
+ gitBranch?: string;
12
+ totalFindings: number;
13
+ bySeverity: Record<string, number>;
14
+ byRule: Record<string, number>;
15
+ findingIds: string[];
16
+ }
17
+ export interface RegressionReport {
18
+ status: "improved" | "stable" | "regressed";
19
+ newFindings: string[];
20
+ fixedFindings: string[];
21
+ delta: number;
22
+ severityDelta: Record<string, number>;
23
+ ruleDelta: Record<string, number>;
24
+ baseline: BaselineSnapshot;
25
+ current: BaselineSnapshot;
26
+ }
27
+ export declare function buildSnapshot(findings: Finding[]): BaselineSnapshot;
28
+ export declare function saveBaseline(snapshot: BaselineSnapshot, file?: string): void;
29
+ export declare function loadBaseline(file?: string): BaselineSnapshot | null;
30
+ export declare function compareSnapshots(baseline: BaselineSnapshot, current: BaselineSnapshot): RegressionReport;
31
+ export declare function runRegressionAlert(argv: string[]): Promise<void>;
32
+ //# sourceMappingURL=regression-alert.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regression-alert.d.ts","sourceRoot":"","sources":["../../src/commands/regression-alert.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAI3C,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,UAAU,GAAG,QAAQ,GAAG,WAAW,CAAC;IAC5C,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,OAAO,EAAE,gBAAgB,CAAC;CAC3B;AAqBD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,gBAAgB,CAqBnE;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,gBAAgB,EAAE,IAAI,SAAgB,GAAG,IAAI,CAEnF;AAED,wBAAgB,YAAY,CAAC,IAAI,SAAgB,GAAG,gBAAgB,GAAG,IAAI,CAG1E;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,OAAO,EAAE,gBAAgB,GAAG,gBAAgB,CAmCxG;AAID,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA6ItE"}