@kevinrabun/judges 3.59.0 → 3.60.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 (38) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +56 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/adoption-track.d.ts +5 -0
  6. package/dist/commands/adoption-track.d.ts.map +1 -0
  7. package/dist/commands/adoption-track.js +247 -0
  8. package/dist/commands/adoption-track.js.map +1 -0
  9. package/dist/commands/context-blind.d.ts +5 -0
  10. package/dist/commands/context-blind.d.ts.map +1 -0
  11. package/dist/commands/context-blind.js +273 -0
  12. package/dist/commands/context-blind.js.map +1 -0
  13. package/dist/commands/finding-budget.d.ts +5 -0
  14. package/dist/commands/finding-budget.d.ts.map +1 -0
  15. package/dist/commands/finding-budget.js +233 -0
  16. package/dist/commands/finding-budget.js.map +1 -0
  17. package/dist/commands/hallucination-detect.d.ts +5 -0
  18. package/dist/commands/hallucination-detect.d.ts.map +1 -0
  19. package/dist/commands/hallucination-detect.js +351 -0
  20. package/dist/commands/hallucination-detect.js.map +1 -0
  21. package/dist/commands/over-abstraction.d.ts +5 -0
  22. package/dist/commands/over-abstraction.d.ts.map +1 -0
  23. package/dist/commands/over-abstraction.js +308 -0
  24. package/dist/commands/over-abstraction.js.map +1 -0
  25. package/dist/commands/review-digest.d.ts +5 -0
  26. package/dist/commands/review-digest.d.ts.map +1 -0
  27. package/dist/commands/review-digest.js +266 -0
  28. package/dist/commands/review-digest.js.map +1 -0
  29. package/dist/commands/security-theater.d.ts +5 -0
  30. package/dist/commands/security-theater.d.ts.map +1 -0
  31. package/dist/commands/security-theater.js +279 -0
  32. package/dist/commands/security-theater.js.map +1 -0
  33. package/dist/commands/stale-pattern.d.ts +5 -0
  34. package/dist/commands/stale-pattern.d.ts.map +1 -0
  35. package/dist/commands/stale-pattern.js +294 -0
  36. package/dist/commands/stale-pattern.js.map +1 -0
  37. package/package.json +1 -1
  38. package/server.json +2 -2
@@ -0,0 +1,308 @@
1
+ /**
2
+ * Over-abstraction — detect unnecessary abstractions and premature generalization from AI.
3
+ */
4
+ import { readFileSync, readdirSync, statSync } from "fs";
5
+ import { join, extname } from "path";
6
+ // ─── File Collection ────────────────────────────────────────────────────────
7
+ const CODE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx"]);
8
+ function collectFiles(dir, max = 300) {
9
+ const files = [];
10
+ function walk(d) {
11
+ if (files.length >= max)
12
+ return;
13
+ let entries;
14
+ try {
15
+ entries = readdirSync(d);
16
+ }
17
+ catch {
18
+ return;
19
+ }
20
+ for (const e of entries) {
21
+ if (files.length >= max)
22
+ return;
23
+ if (e.startsWith(".") || e === "node_modules" || e === "dist" || e === "build")
24
+ continue;
25
+ const full = join(d, e);
26
+ try {
27
+ if (statSync(full).isDirectory())
28
+ walk(full);
29
+ else if (CODE_EXTS.has(extname(full)))
30
+ files.push(full);
31
+ }
32
+ catch {
33
+ /* skip */
34
+ }
35
+ }
36
+ }
37
+ walk(dir);
38
+ return files;
39
+ }
40
+ // ─── Cross-file data ────────────────────────────────────────────────────────
41
+ function buildUsageIndex(files) {
42
+ const usageCount = new Map();
43
+ const allContent = new Map();
44
+ for (const f of files) {
45
+ try {
46
+ allContent.set(f, readFileSync(f, "utf-8"));
47
+ }
48
+ catch {
49
+ /* skip */
50
+ }
51
+ }
52
+ // Count how many files reference each exported name
53
+ for (const [_file, content] of allContent) {
54
+ const exportNames = [
55
+ ...content.matchAll(/export\s+(?:default\s+)?(?:function|class|const|let|var|type|interface|enum|abstract\s+class)\s+(\w+)/g),
56
+ ].map((m) => m[1]);
57
+ for (const name of exportNames) {
58
+ let count = 0;
59
+ for (const [otherFile, otherContent] of allContent) {
60
+ if (otherFile === _file)
61
+ continue;
62
+ if (new RegExp(`\\b${name}\\b`).test(otherContent))
63
+ count++;
64
+ }
65
+ usageCount.set(name, count);
66
+ }
67
+ }
68
+ return usageCount;
69
+ }
70
+ // ─── Analysis ───────────────────────────────────────────────────────────────
71
+ function analyzeFile(filepath, usageCount, allContents) {
72
+ const issues = [];
73
+ let content;
74
+ try {
75
+ content = readFileSync(filepath, "utf-8");
76
+ }
77
+ catch {
78
+ return issues;
79
+ }
80
+ const lines = content.split("\n");
81
+ for (let i = 0; i < lines.length; i++) {
82
+ const line = lines[i];
83
+ // Abstract class with single subclass
84
+ if (/(?:export\s+)?abstract\s+class\s+(\w+)/.test(line)) {
85
+ const className = line.match(/abstract\s+class\s+(\w+)/)?.[1];
86
+ if (className) {
87
+ let subclassCount = 0;
88
+ for (const [_f, c] of allContents) {
89
+ const extends_ = (c.match(new RegExp(`extends\\s+${className}\\b`, "g")) || []).length;
90
+ subclassCount += extends_;
91
+ }
92
+ if (subclassCount <= 1) {
93
+ issues.push({
94
+ file: filepath,
95
+ line: i + 1,
96
+ issue: "Abstract class with single implementation",
97
+ severity: "medium",
98
+ detail: `\`${className}\` has ${subclassCount} subclass(es) — abstract base is premature; inline into the concrete class`,
99
+ });
100
+ }
101
+ }
102
+ }
103
+ // Interface with single implementation
104
+ if (/(?:export\s+)?interface\s+(\w+)\s*\{/.test(line)) {
105
+ const ifaceName = line.match(/interface\s+(\w+)/)?.[1];
106
+ if (ifaceName &&
107
+ !ifaceName.endsWith("Props") &&
108
+ !ifaceName.endsWith("Options") &&
109
+ !ifaceName.endsWith("Config")) {
110
+ let implCount = 0;
111
+ for (const [_f, c] of allContents) {
112
+ if (new RegExp(`implements\\s+${ifaceName}\\b`).test(c))
113
+ implCount++;
114
+ if (new RegExp(`:\\s*${ifaceName}\\b`).test(c))
115
+ implCount++;
116
+ }
117
+ const uses = usageCount.get(ifaceName) || 0;
118
+ if (implCount <= 1 && uses <= 1 && !/export/.test(line)) {
119
+ issues.push({
120
+ file: filepath,
121
+ line: i + 1,
122
+ issue: "Interface used only once",
123
+ severity: "low",
124
+ detail: `\`${ifaceName}\` has single implementation and minimal usage — may be premature abstraction`,
125
+ });
126
+ }
127
+ }
128
+ }
129
+ // Generic type parameter used in one instantiation
130
+ if (/(?:function|class)\s+\w+\s*<(\w+)/.test(line)) {
131
+ const genericParam = line.match(/<(\w+)(?:\s+extends)?/)?.[1];
132
+ if (genericParam && genericParam !== "T") {
133
+ // This is a heuristic — single-letter generics are normal
134
+ const body = lines.slice(i, Math.min(i + 30, lines.length)).join("\n");
135
+ const usages = (body.match(new RegExp(`\\b${genericParam}\\b`, "g")) || []).length;
136
+ if (usages <= 2) {
137
+ issues.push({
138
+ file: filepath,
139
+ line: i + 1,
140
+ issue: "Generic type parameter barely used",
141
+ severity: "low",
142
+ detail: `Generic \`<${genericParam}>\` used only ${usages} times in body — concrete type may suffice`,
143
+ });
144
+ }
145
+ }
146
+ }
147
+ // Factory function that creates only one type
148
+ if (/(?:function|const)\s+create(\w+)\s*(?:=\s*\(|\()/.test(line)) {
149
+ const factoryName = line.match(/(?:function|const)\s+(create\w+)/)?.[1];
150
+ if (factoryName) {
151
+ const block = lines.slice(i, Math.min(i + 20, lines.length)).join("\n");
152
+ const newCount = (block.match(/new\s+\w+/g) || []).length;
153
+ const returnCount = (block.match(/return\s+(?:new\s+)?\w+/g) || []).length;
154
+ if (newCount === 1 && returnCount <= 1) {
155
+ issues.push({
156
+ file: filepath,
157
+ line: i + 1,
158
+ issue: "Factory that creates single type",
159
+ severity: "low",
160
+ detail: `\`${factoryName}\` creates one concrete type — factory pattern adds unnecessary indirection`,
161
+ });
162
+ }
163
+ }
164
+ }
165
+ // Wrapper function that only delegates
166
+ if (/(?:export\s+)?(?:async\s+)?function\s+(\w+)\s*\(([^)]*)\)/.test(line)) {
167
+ const funcName = line.match(/function\s+(\w+)/)?.[1];
168
+ const block = lines
169
+ .slice(i + 1, Math.min(i + 5, lines.length))
170
+ .join("\n")
171
+ .trim();
172
+ // Function body is just "return otherFunc(args)" or similar
173
+ if (/^(?:\{?\s*)?return\s+\w+\s*\([^)]*\)\s*;?\s*\}?\s*$/.test(block)) {
174
+ issues.push({
175
+ file: filepath,
176
+ line: i + 1,
177
+ issue: "Wrapper function with no added logic",
178
+ severity: "medium",
179
+ detail: `\`${funcName}\` only delegates to another function — remove the wrapper and call directly`,
180
+ });
181
+ }
182
+ }
183
+ // Config object for single value
184
+ if (/(?:interface|type)\s+(\w*Config\w*|\w*Options\w*)\s*[={]/.test(line)) {
185
+ const configName = line.match(/(?:interface|type)\s+(\w+)/)?.[1];
186
+ if (configName) {
187
+ let depth = 0;
188
+ let end = i;
189
+ let started = false;
190
+ for (let j = i; j < Math.min(i + 20, lines.length); j++) {
191
+ for (const ch of lines[j]) {
192
+ if (ch === "{") {
193
+ depth++;
194
+ started = true;
195
+ }
196
+ if (ch === "}")
197
+ depth--;
198
+ }
199
+ if (started && depth <= 0) {
200
+ end = j;
201
+ break;
202
+ }
203
+ }
204
+ const body = lines.slice(i + 1, end).join("\n");
205
+ const fieldCount = (body.match(/\w+\s*[?:]?\s*:/g) || []).length;
206
+ if (fieldCount === 1) {
207
+ issues.push({
208
+ file: filepath,
209
+ line: i + 1,
210
+ issue: "Config type with single field",
211
+ severity: "low",
212
+ detail: `\`${configName}\` has only 1 field — pass the value directly instead of wrapping in config object`,
213
+ });
214
+ }
215
+ }
216
+ }
217
+ // Strategy pattern with single strategy
218
+ if (/(?:Strategy|Handler|Provider|Adapter)\s*[{<\]]/.test(line) && /interface|type/.test(line)) {
219
+ const patternName = line.match(/(\w+(?:Strategy|Handler|Provider|Adapter))/)?.[1];
220
+ if (patternName) {
221
+ let implCount = 0;
222
+ for (const [_f, c] of allContents) {
223
+ if (new RegExp(`implements\\s+${patternName}\\b`).test(c))
224
+ implCount++;
225
+ if (new RegExp(`class\\s+\\w+${patternName.replace(/^I/, "")}\\b`).test(c))
226
+ implCount++;
227
+ }
228
+ if (implCount <= 1) {
229
+ issues.push({
230
+ file: filepath,
231
+ line: i + 1,
232
+ issue: "Pattern interface with single implementation",
233
+ severity: "medium",
234
+ detail: `\`${patternName}\` has ${implCount} implementation(s) — strategy/adapter pattern is premature`,
235
+ });
236
+ }
237
+ }
238
+ }
239
+ }
240
+ return issues;
241
+ }
242
+ // ─── CLI ────────────────────────────────────────────────────────────────────
243
+ export function runOverAbstraction(argv) {
244
+ if (argv.includes("--help") || argv.includes("-h")) {
245
+ console.log(`
246
+ judges over-abstraction — Detect unnecessary abstractions from AI-generated code
247
+
248
+ Usage:
249
+ judges over-abstraction [dir]
250
+ judges over-abstraction src/ --format json
251
+
252
+ Options:
253
+ [dir] Directory to scan (default: .)
254
+ --format json JSON output
255
+ --help, -h Show this help
256
+
257
+ Checks: abstract classes with single subclass, single-implementation interfaces,
258
+ barely-used generics, single-type factories, delegation-only wrappers,
259
+ single-field config types, single-impl strategy/adapter patterns.
260
+ `);
261
+ return;
262
+ }
263
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
264
+ const dir = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0) || ".";
265
+ const files = collectFiles(dir);
266
+ const usageCount = buildUsageIndex(files);
267
+ const allContents = new Map();
268
+ for (const f of files) {
269
+ try {
270
+ allContents.set(f, readFileSync(f, "utf-8"));
271
+ }
272
+ catch {
273
+ /* skip */
274
+ }
275
+ }
276
+ const allIssues = [];
277
+ for (const f of files)
278
+ allIssues.push(...analyzeFile(f, usageCount, allContents));
279
+ const highCount = allIssues.filter((i) => i.severity === "high").length;
280
+ const medCount = allIssues.filter((i) => i.severity === "medium").length;
281
+ const score = Math.max(0, 100 - highCount * 10 - medCount * 5 - allIssues.filter((i) => i.severity === "low").length * 2);
282
+ if (format === "json") {
283
+ console.log(JSON.stringify({
284
+ issues: allIssues,
285
+ score,
286
+ summary: { high: highCount, medium: medCount, total: allIssues.length },
287
+ timestamp: new Date().toISOString(),
288
+ }, null, 2));
289
+ }
290
+ else {
291
+ const badge = score >= 80 ? "✅ LEAN" : score >= 50 ? "⚠️ OVER-BUILT" : "❌ OVER-ENGINEERED";
292
+ console.log(`\n Over-Abstraction: ${badge} (${score}/100)\n ─────────────────────────────`);
293
+ if (allIssues.length === 0) {
294
+ console.log(" No over-abstraction detected.\n");
295
+ return;
296
+ }
297
+ for (const issue of allIssues.slice(0, 25)) {
298
+ const icon = issue.severity === "high" ? "🔴" : issue.severity === "medium" ? "🟡" : "🔵";
299
+ console.log(` ${icon} ${issue.issue}`);
300
+ console.log(` ${issue.file}:${issue.line}`);
301
+ console.log(` ${issue.detail}`);
302
+ }
303
+ if (allIssues.length > 25)
304
+ console.log(` ... and ${allIssues.length - 25} more`);
305
+ console.log(`\n Total: ${allIssues.length} | High: ${highCount} | Medium: ${medCount} | Score: ${score}/100\n`);
306
+ }
307
+ }
308
+ //# sourceMappingURL=over-abstraction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"over-abstraction.js","sourceRoot":"","sources":["../../src/commands/over-abstraction.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Review-digest — generate concise, role-appropriate review summaries.
3
+ */
4
+ export declare function runReviewDigest(argv: string[]): void;
5
+ //# sourceMappingURL=review-digest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-digest.d.ts","sourceRoot":"","sources":["../../src/commands/review-digest.ts"],"names":[],"mappings":"AAAA;;GAEG;AAiOH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAmFpD"}
@@ -0,0 +1,266 @@
1
+ /**
2
+ * Review-digest — generate concise, role-appropriate review summaries.
3
+ */
4
+ import { readFileSync, readdirSync, statSync, writeFileSync } from "fs";
5
+ import { join, extname, relative } from "path";
6
+ // ─── File Collection ────────────────────────────────────────────────────────
7
+ const CODE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".py", ".java", ".go", ".cs", ".rb", ".rs"]);
8
+ function collectFiles(dir, max = 300) {
9
+ const files = [];
10
+ function walk(d) {
11
+ if (files.length >= max)
12
+ return;
13
+ let entries;
14
+ try {
15
+ entries = readdirSync(d);
16
+ }
17
+ catch {
18
+ return;
19
+ }
20
+ for (const e of entries) {
21
+ if (files.length >= max)
22
+ return;
23
+ if (e.startsWith(".") || e === "node_modules" || e === "dist" || e === "build")
24
+ continue;
25
+ const full = join(d, e);
26
+ try {
27
+ if (statSync(full).isDirectory())
28
+ walk(full);
29
+ else if (CODE_EXTS.has(extname(full)))
30
+ files.push(full);
31
+ }
32
+ catch {
33
+ /* skip */
34
+ }
35
+ }
36
+ }
37
+ walk(dir);
38
+ return files;
39
+ }
40
+ const QUICK_PATTERNS = [
41
+ { regex: /eval\s*\(/, category: "Security", title: "eval() usage", severity: "critical", autoFix: false },
42
+ {
43
+ regex: /(?:password|secret|api[_-]?key)\s*[:=]\s*['"][^'"]+['"]/,
44
+ category: "Security",
45
+ title: "Hardcoded credential",
46
+ severity: "critical",
47
+ autoFix: false,
48
+ },
49
+ { regex: /TODO|FIXME|HACK|XXX/, category: "Debt", title: "Open TODO/FIXME", severity: "low", autoFix: false },
50
+ { regex: /console\.\w+\s*\(/, category: "Quality", title: "Console statement", severity: "low", autoFix: true },
51
+ {
52
+ regex: /catch\s*\(\s*\w*\s*\)\s*\{\s*\}/,
53
+ category: "Reliability",
54
+ title: "Empty catch block",
55
+ severity: "medium",
56
+ autoFix: false,
57
+ },
58
+ {
59
+ regex: /any(?:\s*[;,)\]}]|\s*$)/,
60
+ category: "Types",
61
+ title: "Explicit 'any' type",
62
+ severity: "low",
63
+ autoFix: false,
64
+ },
65
+ {
66
+ regex: /(?:\.innerHTML|\.outerHTML)\s*=/,
67
+ category: "Security",
68
+ title: "innerHTML assignment (XSS risk)",
69
+ severity: "high",
70
+ autoFix: false,
71
+ },
72
+ {
73
+ regex: /new\s+Buffer\s*\(/,
74
+ category: "Security",
75
+ title: "Deprecated new Buffer()",
76
+ severity: "high",
77
+ autoFix: true,
78
+ },
79
+ {
80
+ regex: /process\.exit\s*\(/,
81
+ category: "Reliability",
82
+ title: "process.exit() call",
83
+ severity: "medium",
84
+ autoFix: false,
85
+ },
86
+ {
87
+ regex: /(?:setTimeout|setInterval)\s*\(\s*['"]/,
88
+ category: "Security",
89
+ title: "String passed to timer (implicit eval)",
90
+ severity: "high",
91
+ autoFix: false,
92
+ },
93
+ {
94
+ regex: /\.then\s*\([^)]*\)\s*(?:;|\n)\s*(?!\.catch)/,
95
+ category: "Reliability",
96
+ title: "Unhandled promise rejection",
97
+ severity: "medium",
98
+ autoFix: false,
99
+ },
100
+ { regex: /debugger\b/, category: "Quality", title: "Debugger statement", severity: "medium", autoFix: true },
101
+ ];
102
+ // ─── Analysis ───────────────────────────────────────────────────────────────
103
+ function analyzeFile(filepath, baseDir) {
104
+ const findings = [];
105
+ let content;
106
+ try {
107
+ content = readFileSync(filepath, "utf-8");
108
+ }
109
+ catch {
110
+ return findings;
111
+ }
112
+ const lines = content.split("\n");
113
+ const rel = relative(baseDir, filepath);
114
+ for (let i = 0; i < lines.length; i++) {
115
+ const line = lines[i];
116
+ const trimmed = line.trim();
117
+ if (trimmed.startsWith("//") || trimmed.startsWith("*") || trimmed.startsWith("/*"))
118
+ continue;
119
+ for (const pattern of QUICK_PATTERNS) {
120
+ if (pattern.regex.test(line)) {
121
+ findings.push({
122
+ file: rel,
123
+ line: i + 1,
124
+ severity: pattern.severity,
125
+ category: pattern.category,
126
+ title: pattern.title,
127
+ autoFixable: pattern.autoFix,
128
+ });
129
+ }
130
+ }
131
+ }
132
+ return findings;
133
+ }
134
+ function buildDigest(allFindings) {
135
+ const critical = allFindings.filter((f) => f.severity === "critical").length;
136
+ const high = allFindings.filter((f) => f.severity === "high").length;
137
+ const medium = allFindings.filter((f) => f.severity === "medium").length;
138
+ const low = allFindings.filter((f) => f.severity === "low").length;
139
+ const autoFixable = allFindings.filter((f) => f.autoFixable).length;
140
+ const riskScore = Math.max(0, 100 - critical * 20 - high * 10 - medium * 4 - low * 1);
141
+ // Top categories
142
+ const catMap = new Map();
143
+ for (const f of allFindings)
144
+ catMap.set(f.category, (catMap.get(f.category) || 0) + 1);
145
+ const topCategories = [...catMap.entries()]
146
+ .sort((a, b) => b[1] - a[1])
147
+ .slice(0, 5)
148
+ .map(([category, count]) => ({ category, count }));
149
+ // Hot files
150
+ const fileMap = new Map();
151
+ for (const f of allFindings)
152
+ fileMap.set(f.file, (fileMap.get(f.file) || 0) + 1);
153
+ const hotFiles = [...fileMap.entries()]
154
+ .sort((a, b) => b[1] - a[1])
155
+ .slice(0, 5)
156
+ .map(([file, count]) => ({ file, count }));
157
+ // Action items
158
+ const actionItems = [];
159
+ if (critical > 0)
160
+ actionItems.push(`Fix ${critical} critical finding(s) immediately`);
161
+ if (high > 0)
162
+ actionItems.push(`Address ${high} high-severity finding(s) before merge`);
163
+ if (autoFixable > 0)
164
+ actionItems.push(`${autoFixable} finding(s) can be auto-fixed`);
165
+ if (hotFiles.length > 0)
166
+ actionItems.push(`Focus on ${hotFiles[0].file} (${hotFiles[0].count} findings)`);
167
+ // Start here — top 5 most impactful
168
+ const startHere = allFindings.filter((f) => f.severity === "critical" || f.severity === "high").slice(0, 5);
169
+ const badge = riskScore >= 80 ? "LOW RISK" : riskScore >= 50 ? "MODERATE RISK" : "HIGH RISK";
170
+ return {
171
+ riskScore,
172
+ badge,
173
+ totalFindings: allFindings.length,
174
+ critical,
175
+ high,
176
+ medium,
177
+ low,
178
+ autoFixable,
179
+ topCategories,
180
+ hotFiles,
181
+ actionItems,
182
+ startHere,
183
+ };
184
+ }
185
+ // ─── CLI ────────────────────────────────────────────────────────────────────
186
+ export function runReviewDigest(argv) {
187
+ if (argv.includes("--help") || argv.includes("-h")) {
188
+ console.log(`
189
+ judges review-digest — Generate concise, role-appropriate review summaries
190
+
191
+ Usage:
192
+ judges review-digest [dir]
193
+ judges review-digest src/ --format json
194
+ judges review-digest src/ --out digest.md
195
+
196
+ Options:
197
+ [dir] Directory to scan (default: .)
198
+ --format json JSON output
199
+ --out <file> Write digest to file
200
+ --help, -h Show this help
201
+
202
+ Generates: risk score, top categories, hot files, action items,
203
+ "start here" list of most impactful findings, auto-fix counts.
204
+ `);
205
+ return;
206
+ }
207
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
208
+ const outFile = argv.find((_a, i) => argv[i - 1] === "--out");
209
+ const dir = argv.find((a) => !a.startsWith("-") &&
210
+ argv.indexOf(a) > 0 &&
211
+ argv[argv.indexOf(a) - 1] !== "--format" &&
212
+ argv[argv.indexOf(a) - 1] !== "--out") || ".";
213
+ const files = collectFiles(dir);
214
+ const allFindings = [];
215
+ for (const f of files)
216
+ allFindings.push(...analyzeFile(f, dir));
217
+ const digest = buildDigest(allFindings);
218
+ if (format === "json") {
219
+ const json = JSON.stringify({ digest, findings: allFindings, timestamp: new Date().toISOString() }, null, 2);
220
+ if (outFile) {
221
+ writeFileSync(outFile, json, "utf-8");
222
+ console.log(`Digest written to ${outFile}`);
223
+ }
224
+ else
225
+ console.log(json);
226
+ }
227
+ else {
228
+ const icon = digest.riskScore >= 80 ? "✅" : digest.riskScore >= 50 ? "⚠️ " : "❌";
229
+ let out = `\n Review Digest: ${icon} ${digest.badge} (${digest.riskScore}/100)\n ─────────────────────────────\n`;
230
+ out += ` Findings: ${digest.totalFindings} (${digest.critical} critical, ${digest.high} high, ${digest.medium} medium, ${digest.low} low)\n`;
231
+ out += ` Auto-fixable: ${digest.autoFixable}\n\n`;
232
+ if (digest.actionItems.length > 0) {
233
+ out += ` Action Items:\n`;
234
+ for (const item of digest.actionItems)
235
+ out += ` → ${item}\n`;
236
+ out += `\n`;
237
+ }
238
+ if (digest.startHere.length > 0) {
239
+ out += ` Start Here (highest impact):\n`;
240
+ for (const f of digest.startHere) {
241
+ const icon2 = f.severity === "critical" ? "🔴" : "🟡";
242
+ out += ` ${icon2} [${f.category}] ${f.title} — ${f.file}:${f.line}\n`;
243
+ }
244
+ out += `\n`;
245
+ }
246
+ if (digest.hotFiles.length > 0) {
247
+ out += ` Hot Files:\n`;
248
+ for (const h of digest.hotFiles)
249
+ out += ` ${h.file} — ${h.count} finding(s)\n`;
250
+ out += `\n`;
251
+ }
252
+ if (digest.topCategories.length > 0) {
253
+ out += ` Top Categories:\n`;
254
+ for (const c of digest.topCategories)
255
+ out += ` ${c.category}: ${c.count}\n`;
256
+ out += `\n`;
257
+ }
258
+ if (outFile) {
259
+ writeFileSync(outFile, out, "utf-8");
260
+ console.log(`Digest written to ${outFile}`);
261
+ }
262
+ else
263
+ console.log(out);
264
+ }
265
+ }
266
+ //# sourceMappingURL=review-digest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-digest.js","sourceRoot":"","sources":["../../src/commands/review-digest.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AA4B/C,+EAA+E;AAE/E,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;AAEtG,SAAS,YAAY,CAAC,GAAW,EAAE,GAAG,GAAG,GAAG;IAC1C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,SAAS,IAAI,CAAC,CAAS;QACrB,IAAI,KAAK,CAAC,MAAM,IAAI,GAAG;YAAE,OAAO;QAChC,IAAI,OAAiB,CAAC;QACtB,IAAI,CAAC;YACH,OAAO,GAAG,WAAW,CAAC,CAAC,CAAwB,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;QACT,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,IAAI,KAAK,CAAC,MAAM,IAAI,GAAG;gBAAE,OAAO;YAChC,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,cAAc,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,OAAO;gBAAE,SAAS;YACzF,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACxB,IAAI,CAAC;gBACH,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE;oBAAE,IAAI,CAAC,IAAI,CAAC,CAAC;qBACxC,IAAI,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;oBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1D,CAAC;YAAC,MAAM,CAAC;gBACP,UAAU;YACZ,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,KAAK,CAAC;AACf,CAAC;AAYD,MAAM,cAAc,GAAe;IACjC,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE;IACzG;QACE,KAAK,EAAE,yDAAyD;QAChE,QAAQ,EAAE,UAAU;QACpB,KAAK,EAAE,sBAAsB;QAC7B,QAAQ,EAAE,UAAU;QACpB,OAAO,EAAE,KAAK;KACf;IACD,EAAE,KAAK,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE;IAC7G,EAAE,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE;IAC/G;QACE,KAAK,EAAE,iCAAiC;QACxC,QAAQ,EAAE,aAAa;QACvB,KAAK,EAAE,mBAAmB;QAC1B,QAAQ,EAAE,QAAQ;QAClB,OAAO,EAAE,KAAK;KACf;IACD;QACE,KAAK,EAAE,yBAAyB;QAChC,QAAQ,EAAE,OAAO;QACjB,KAAK,EAAE,qBAAqB;QAC5B,QAAQ,EAAE,KAAK;QACf,OAAO,EAAE,KAAK;KACf;IACD;QACE,KAAK,EAAE,iCAAiC;QACxC,QAAQ,EAAE,UAAU;QACpB,KAAK,EAAE,iCAAiC;QACxC,QAAQ,EAAE,MAAM;QAChB,OAAO,EAAE,KAAK;KACf;IACD;QACE,KAAK,EAAE,mBAAmB;QAC1B,QAAQ,EAAE,UAAU;QACpB,KAAK,EAAE,yBAAyB;QAChC,QAAQ,EAAE,MAAM;QAChB,OAAO,EAAE,IAAI;KACd;IACD;QACE,KAAK,EAAE,oBAAoB;QAC3B,QAAQ,EAAE,aAAa;QACvB,KAAK,EAAE,qBAAqB;QAC5B,QAAQ,EAAE,QAAQ;QAClB,OAAO,EAAE,KAAK;KACf;IACD;QACE,KAAK,EAAE,wCAAwC;QAC/C,QAAQ,EAAE,UAAU;QACpB,KAAK,EAAE,wCAAwC;QAC/C,QAAQ,EAAE,MAAM;QAChB,OAAO,EAAE,KAAK;KACf;IACD;QACE,KAAK,EAAE,6CAA6C;QACpD,QAAQ,EAAE,aAAa;QACvB,KAAK,EAAE,6BAA6B;QACpC,QAAQ,EAAE,QAAQ;QAClB,OAAO,EAAE,KAAK;KACf;IACD,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,oBAAoB,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE;CAC7G,CAAC;AAEF,+EAA+E;AAE/E,SAAS,WAAW,CAAC,QAAgB,EAAE,OAAe;IACpD,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAExC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,SAAS;QAE9F,KAAK,MAAM,OAAO,IAAI,cAAc,EAAE,CAAC;YACrC,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC7B,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,GAAG;oBACT,IAAI,EAAE,CAAC,GAAG,CAAC;oBACX,QAAQ,EAAE,OAAO,CAAC,QAAQ;oBAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;oBAC1B,KAAK,EAAE,OAAO,CAAC,KAAK;oBACpB,WAAW,EAAE,OAAO,CAAC,OAAO;iBAC7B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,WAAW,CAAC,WAA4B;IAC/C,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,MAAM,CAAC;IAC7E,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,MAAM,CAAC;IACrE,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,MAAM,CAAC;IACzE,MAAM,GAAG,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC,MAAM,CAAC;IACnE,MAAM,WAAW,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC;IAEpE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,QAAQ,GAAG,EAAE,GAAG,IAAI,GAAG,EAAE,GAAG,MAAM,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC;IAEtF,iBAAiB;IACjB,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,CAAC,IAAI,WAAW;QAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACvF,MAAM,aAAa,GAAG,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;SACxC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;SAC3B,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;SACX,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAErD,YAAY;IACZ,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC1C,KAAK,MAAM,CAAC,IAAI,WAAW;QAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACjF,MAAM,QAAQ,GAAG,CAAC,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;SACpC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;SAC3B,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;SACX,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAE7C,eAAe;IACf,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,IAAI,QAAQ,GAAG,CAAC;QAAE,WAAW,CAAC,IAAI,CAAC,OAAO,QAAQ,kCAAkC,CAAC,CAAC;IACtF,IAAI,IAAI,GAAG,CAAC;QAAE,WAAW,CAAC,IAAI,CAAC,WAAW,IAAI,wCAAwC,CAAC,CAAC;IACxF,IAAI,WAAW,GAAG,CAAC;QAAE,WAAW,CAAC,IAAI,CAAC,GAAG,WAAW,+BAA+B,CAAC,CAAC;IACrF,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,WAAW,CAAC,IAAI,CAAC,YAAY,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,YAAY,CAAC,CAAC;IAE1G,oCAAoC;IACpC,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,IAAI,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAE5G,MAAM,KAAK,GAAG,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,WAAW,CAAC;IAE7F,OAAO;QACL,SAAS;QACT,KAAK;QACL,aAAa,EAAE,WAAW,CAAC,MAAM;QACjC,QAAQ;QACR,IAAI;QACJ,MAAM;QACN,GAAG;QACH,WAAW;QACX,aAAa;QACb,QAAQ;QACR,WAAW;QACX,SAAS;KACV,CAAC;AACJ,CAAC;AAED,+EAA+E;AAE/E,MAAM,UAAU,eAAe,CAAC,IAAc;IAC5C,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;CAgBf,CAAC,CAAC;QACC,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,UAAU,CAAC,IAAI,MAAM,CAAC;IAC1F,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC;IAC9E,MAAM,GAAG,GACP,IAAI,CAAC,IAAI,CACP,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC;QAClB,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;QACnB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,UAAU;QACxC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,OAAO,CACxC,IAAI,GAAG,CAAC;IAEX,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,WAAW,GAAoB,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,WAAW,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAEhE,MAAM,MAAM,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;IAExC,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC7G,IAAI,OAAO,EAAE,CAAC;YACZ,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;YACtC,OAAO,CAAC,GAAG,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAC;QAC9C,CAAC;;YAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;QACjF,IAAI,GAAG,GAAG,sBAAsB,IAAI,IAAI,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,SAAS,0CAA0C,CAAC;QACpH,GAAG,IAAI,iBAAiB,MAAM,CAAC,aAAa,KAAK,MAAM,CAAC,QAAQ,cAAc,MAAM,CAAC,IAAI,UAAU,MAAM,CAAC,MAAM,YAAY,MAAM,CAAC,GAAG,SAAS,CAAC;QAChJ,GAAG,IAAI,qBAAqB,MAAM,CAAC,WAAW,MAAM,CAAC;QAErD,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClC,GAAG,IAAI,qBAAqB,CAAC;YAC7B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,WAAW;gBAAE,GAAG,IAAI,WAAW,IAAI,IAAI,CAAC;YAClE,GAAG,IAAI,IAAI,CAAC;QACd,CAAC;QAED,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,GAAG,IAAI,oCAAoC,CAAC;YAC5C,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;gBACjC,MAAM,KAAK,GAAG,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;gBACtD,GAAG,IAAI,SAAS,KAAK,KAAK,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC;YAC7E,CAAC;YACD,GAAG,IAAI,IAAI,CAAC;QACd,CAAC;QAED,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/B,GAAG,IAAI,kBAAkB,CAAC;YAC1B,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ;gBAAE,GAAG,IAAI,SAAS,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,KAAK,eAAe,CAAC;YACpF,GAAG,IAAI,IAAI,CAAC;QACd,CAAC;QAED,IAAI,MAAM,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpC,GAAG,IAAI,uBAAuB,CAAC;YAC/B,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,aAAa;gBAAE,GAAG,IAAI,SAAS,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC;YACjF,GAAG,IAAI,IAAI,CAAC;QACd,CAAC;QAED,IAAI,OAAO,EAAE,CAAC;YACZ,aAAa,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;YACrC,OAAO,CAAC,GAAG,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAC;QAC9C,CAAC;;YAAM,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Security-theater — detect security-looking code that provides no actual protection.
3
+ */
4
+ export declare function runSecurityTheater(argv: string[]): void;
5
+ //# sourceMappingURL=security-theater.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security-theater.d.ts","sourceRoot":"","sources":["../../src/commands/security-theater.ts"],"names":[],"mappings":"AAAA;;GAEG;AA4PH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAiEvD"}