@kevinrabun/judges 3.49.0 → 3.50.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/api-audit.d.ts +9 -0
  6. package/dist/commands/api-audit.d.ts.map +1 -0
  7. package/dist/commands/api-audit.js +360 -0
  8. package/dist/commands/api-audit.js.map +1 -0
  9. package/dist/commands/compliance-map.d.ts +9 -0
  10. package/dist/commands/compliance-map.d.ts.map +1 -0
  11. package/dist/commands/compliance-map.js +375 -0
  12. package/dist/commands/compliance-map.js.map +1 -0
  13. package/dist/commands/exec-report.d.ts +9 -0
  14. package/dist/commands/exec-report.d.ts.map +1 -0
  15. package/dist/commands/exec-report.js +272 -0
  16. package/dist/commands/exec-report.js.map +1 -0
  17. package/dist/commands/guided-tour.d.ts +9 -0
  18. package/dist/commands/guided-tour.d.ts.map +1 -0
  19. package/dist/commands/guided-tour.js +288 -0
  20. package/dist/commands/guided-tour.js.map +1 -0
  21. package/dist/commands/iac-lint.d.ts +8 -0
  22. package/dist/commands/iac-lint.d.ts.map +1 -0
  23. package/dist/commands/iac-lint.js +313 -0
  24. package/dist/commands/iac-lint.js.map +1 -0
  25. package/dist/commands/perf-compare.d.ts +9 -0
  26. package/dist/commands/perf-compare.d.ts.map +1 -0
  27. package/dist/commands/perf-compare.js +246 -0
  28. package/dist/commands/perf-compare.js.map +1 -0
  29. package/dist/commands/pii-scan.d.ts +8 -0
  30. package/dist/commands/pii-scan.d.ts.map +1 -0
  31. package/dist/commands/pii-scan.js +300 -0
  32. package/dist/commands/pii-scan.js.map +1 -0
  33. package/dist/commands/secret-scan.d.ts +8 -0
  34. package/dist/commands/secret-scan.d.ts.map +1 -0
  35. package/dist/commands/secret-scan.js +245 -0
  36. package/dist/commands/secret-scan.js.map +1 -0
  37. package/package.json +1 -1
  38. package/server.json +2 -2
@@ -0,0 +1,313 @@
1
+ /**
2
+ * IaC lint — dedicated linting for Dockerfiles, Kubernetes
3
+ * manifests, and Helm charts for security misconfigurations.
4
+ *
5
+ * All analysis local.
6
+ */
7
+ import { existsSync, readFileSync, readdirSync } from "fs";
8
+ import { join, basename } from "path";
9
+ // ─── Rules ──────────────────────────────────────────────────────────────────
10
+ const IAC_RULES = [
11
+ // Dockerfile rules
12
+ {
13
+ id: "dockerfile-run-as-root",
14
+ type: "dockerfile",
15
+ severity: "high",
16
+ check: (_content, lines) => {
17
+ const hasUser = lines.some((l) => /^USER\s+(?!root)/i.test(l.trim()));
18
+ if (!hasUser)
19
+ return [{ line: 1, message: "No USER directive — container runs as root" }];
20
+ return [];
21
+ },
22
+ recommendation: "Add USER directive with a non-root user",
23
+ },
24
+ {
25
+ id: "dockerfile-latest-tag",
26
+ type: "dockerfile",
27
+ severity: "medium",
28
+ check: (_content, lines) => {
29
+ const results = [];
30
+ for (let i = 0; i < lines.length; i++) {
31
+ if (/^FROM\s+\S+:latest/i.test(lines[i].trim()) ||
32
+ (/^FROM\s+\S+$/i.test(lines[i].trim()) && !lines[i].includes(":"))) {
33
+ results.push({ line: i + 1, message: "Using 'latest' or untagged base image" });
34
+ }
35
+ }
36
+ return results;
37
+ },
38
+ recommendation: "Pin base image to a specific version tag",
39
+ },
40
+ {
41
+ id: "dockerfile-copy-chown",
42
+ type: "dockerfile",
43
+ severity: "low",
44
+ check: (_content, lines) => {
45
+ const results = [];
46
+ for (let i = 0; i < lines.length; i++) {
47
+ if (/^COPY\s/i.test(lines[i].trim()) && !lines[i].includes("--chown")) {
48
+ results.push({ line: i + 1, message: "COPY without --chown — files owned by root" });
49
+ }
50
+ }
51
+ return results;
52
+ },
53
+ recommendation: "Use COPY --chown=user:group to set proper ownership",
54
+ },
55
+ {
56
+ id: "dockerfile-add-url",
57
+ type: "dockerfile",
58
+ severity: "high",
59
+ check: (_content, lines) => {
60
+ const results = [];
61
+ for (let i = 0; i < lines.length; i++) {
62
+ if (/^ADD\s+https?:\/\//i.test(lines[i].trim())) {
63
+ results.push({ line: i + 1, message: "ADD with URL — use COPY + RUN curl instead" });
64
+ }
65
+ }
66
+ return results;
67
+ },
68
+ recommendation: "Replace ADD with RUN curl/wget + COPY for better security",
69
+ },
70
+ {
71
+ id: "dockerfile-env-secret",
72
+ type: "dockerfile",
73
+ severity: "critical",
74
+ check: (_content, lines) => {
75
+ const results = [];
76
+ for (let i = 0; i < lines.length; i++) {
77
+ if (/^ENV\s+.*(?:PASSWORD|SECRET|API_KEY|TOKEN)\s*=/i.test(lines[i].trim())) {
78
+ results.push({ line: i + 1, message: "Secret exposed in ENV directive" });
79
+ }
80
+ }
81
+ return results;
82
+ },
83
+ recommendation: "Use Docker secrets or runtime environment variables instead",
84
+ },
85
+ // Kubernetes rules
86
+ {
87
+ id: "k8s-privileged",
88
+ type: "kubernetes",
89
+ severity: "critical",
90
+ check: (content) => {
91
+ const results = [];
92
+ const lines = content.split("\n");
93
+ for (let i = 0; i < lines.length; i++) {
94
+ if (/privileged:\s*true/i.test(lines[i])) {
95
+ results.push({ line: i + 1, message: "Container running in privileged mode" });
96
+ }
97
+ }
98
+ return results;
99
+ },
100
+ recommendation: "Set privileged: false and use specific capabilities instead",
101
+ },
102
+ {
103
+ id: "k8s-host-network",
104
+ type: "kubernetes",
105
+ severity: "high",
106
+ check: (content) => {
107
+ const results = [];
108
+ const lines = content.split("\n");
109
+ for (let i = 0; i < lines.length; i++) {
110
+ if (/hostNetwork:\s*true/i.test(lines[i])) {
111
+ results.push({ line: i + 1, message: "Pod using host network namespace" });
112
+ }
113
+ }
114
+ return results;
115
+ },
116
+ recommendation: "Disable hostNetwork unless absolutely required",
117
+ },
118
+ {
119
+ id: "k8s-no-resource-limits",
120
+ type: "kubernetes",
121
+ severity: "medium",
122
+ check: (content) => {
123
+ if (/kind:\s*(?:Deployment|Pod|StatefulSet|DaemonSet)/i.test(content) &&
124
+ !/resources:\s*\n\s+limits:/i.test(content)) {
125
+ return [{ line: 1, message: "No resource limits defined" }];
126
+ }
127
+ return [];
128
+ },
129
+ recommendation: "Add resources.limits for CPU and memory",
130
+ },
131
+ {
132
+ id: "k8s-run-as-root",
133
+ type: "kubernetes",
134
+ severity: "high",
135
+ check: (content) => {
136
+ const results = [];
137
+ const lines = content.split("\n");
138
+ for (let i = 0; i < lines.length; i++) {
139
+ if (/runAsUser:\s*0/i.test(lines[i])) {
140
+ results.push({ line: i + 1, message: "Container running as root (UID 0)" });
141
+ }
142
+ }
143
+ return results;
144
+ },
145
+ recommendation: "Set runAsUser to a non-zero UID and runAsNonRoot: true",
146
+ },
147
+ {
148
+ id: "k8s-no-readiness-probe",
149
+ type: "kubernetes",
150
+ severity: "low",
151
+ check: (content) => {
152
+ if (/kind:\s*Deployment/i.test(content) && !/readinessProbe:/i.test(content)) {
153
+ return [{ line: 1, message: "No readiness probe configured" }];
154
+ }
155
+ return [];
156
+ },
157
+ recommendation: "Add readinessProbe for proper traffic management",
158
+ },
159
+ ];
160
+ // ─── Scanner ────────────────────────────────────────────────────────────────
161
+ function detectFileType(filePath, content) {
162
+ const name = basename(filePath).toLowerCase();
163
+ if (name === "dockerfile" || name.startsWith("dockerfile."))
164
+ return "dockerfile";
165
+ if (name.endsWith(".dockerfile"))
166
+ return "dockerfile";
167
+ if (/kind:\s*(?:Deployment|Service|Pod|StatefulSet|DaemonSet|ConfigMap|Secret|Ingress)/i.test(content))
168
+ return "kubernetes";
169
+ if (/apiVersion:\s*v\d|apiVersion:\s*apps\//i.test(content))
170
+ return "kubernetes";
171
+ if (name === "chart.yaml" || name === "values.yaml")
172
+ return "helm";
173
+ return null;
174
+ }
175
+ function collectIacFiles(dir) {
176
+ const result = [];
177
+ const skipDirs = new Set(["node_modules", ".git", "dist", "build"]);
178
+ function walk(d) {
179
+ let entries;
180
+ try {
181
+ entries = readdirSync(d);
182
+ }
183
+ catch {
184
+ return;
185
+ }
186
+ for (const name of entries) {
187
+ if (skipDirs.has(name))
188
+ continue;
189
+ const full = join(d, name);
190
+ try {
191
+ const sub = readdirSync(full);
192
+ void sub;
193
+ walk(full);
194
+ }
195
+ catch {
196
+ const lower = name.toLowerCase();
197
+ if (lower.includes("dockerfile") || lower.endsWith(".yaml") || lower.endsWith(".yml")) {
198
+ result.push(full);
199
+ }
200
+ }
201
+ }
202
+ }
203
+ walk(dir);
204
+ return result;
205
+ }
206
+ // ─── CLI ────────────────────────────────────────────────────────────────────
207
+ export function runIacLint(argv) {
208
+ if (argv.includes("--help") || argv.includes("-h")) {
209
+ console.log(`
210
+ judges iac-lint — Lint Dockerfiles, Kubernetes manifests, and Helm charts
211
+
212
+ Usage:
213
+ judges iac-lint [dir]
214
+ judges iac-lint Dockerfile
215
+ judges iac-lint k8s/ --severity critical,high
216
+
217
+ Options:
218
+ --severity <levels> Filter by severity (comma-separated)
219
+ --rules List all IaC lint rules
220
+ --format json JSON output
221
+ --help, -h Show this help
222
+ `);
223
+ return;
224
+ }
225
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
226
+ // List rules
227
+ if (argv.includes("--rules")) {
228
+ if (format === "json") {
229
+ console.log(JSON.stringify(IAC_RULES.map(({ check: _c, ...rest }) => rest), null, 2));
230
+ }
231
+ else {
232
+ console.log(`\n IaC Lint Rules (${IAC_RULES.length})\n ──────────────────────────`);
233
+ for (const r of IAC_RULES) {
234
+ console.log(` [${r.severity.toUpperCase().padEnd(8)}] ${r.id.padEnd(30)} (${r.type})`);
235
+ }
236
+ console.log("");
237
+ }
238
+ return;
239
+ }
240
+ const target = argv.find((a) => !a.startsWith("--") && !argv[argv.indexOf(a) - 1]?.startsWith("--")) || ".";
241
+ const sevFilter = argv.find((_a, i) => argv[i - 1] === "--severity");
242
+ // Collect files
243
+ let files;
244
+ if (existsSync(target)) {
245
+ try {
246
+ readdirSync(target);
247
+ files = collectIacFiles(target);
248
+ }
249
+ catch {
250
+ files = [target];
251
+ }
252
+ }
253
+ else {
254
+ console.error(` Path not found: ${target}`);
255
+ return;
256
+ }
257
+ let findings = [];
258
+ for (const file of files) {
259
+ let content;
260
+ try {
261
+ content = readFileSync(file, "utf-8");
262
+ }
263
+ catch {
264
+ continue;
265
+ }
266
+ const fileType = detectFileType(file, content);
267
+ if (!fileType)
268
+ continue;
269
+ const applicableRules = IAC_RULES.filter((r) => r.type === fileType);
270
+ const lines = content.split("\n");
271
+ for (const rule of applicableRules) {
272
+ const matches = rule.check(content, lines);
273
+ for (const m of matches) {
274
+ findings.push({
275
+ file,
276
+ line: m.line,
277
+ ruleId: rule.id,
278
+ severity: rule.severity,
279
+ message: m.message,
280
+ recommendation: rule.recommendation,
281
+ });
282
+ }
283
+ }
284
+ }
285
+ if (sevFilter) {
286
+ const allowed = sevFilter.split(",");
287
+ findings = findings.filter((f) => allowed.includes(f.severity));
288
+ }
289
+ if (format === "json") {
290
+ console.log(JSON.stringify({ findings, scannedFiles: files.length, timestamp: new Date().toISOString() }, null, 2));
291
+ }
292
+ else {
293
+ console.log(`\n IaC Lint — ${files.length} files scanned`);
294
+ console.log(` Found: ${findings.length} issues\n ──────────────────────────`);
295
+ if (findings.length === 0) {
296
+ console.log(` ✅ No IaC issues detected\n`);
297
+ return;
298
+ }
299
+ for (const sev of ["critical", "high", "medium", "low"]) {
300
+ const items = findings.filter((f) => f.severity === sev);
301
+ if (items.length === 0)
302
+ continue;
303
+ console.log(`\n ${sev.toUpperCase()} (${items.length})`);
304
+ for (const f of items) {
305
+ console.log(` ${f.file}:${f.line} — ${f.ruleId}`);
306
+ console.log(` ${f.message}`);
307
+ console.log(` → ${f.recommendation}`);
308
+ }
309
+ }
310
+ console.log("");
311
+ }
312
+ }
313
+ //# sourceMappingURL=iac-lint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iac-lint.js","sourceRoot":"","sources":["../../src/commands/iac-lint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Perf compare — before/after performance comparison of code changes.
3
+ * Compares algorithmic complexity, loop nesting, allocation patterns,
4
+ * and async anti-patterns between two code versions.
5
+ *
6
+ * All analysis local.
7
+ */
8
+ export declare function runPerfCompare(argv: string[]): void;
9
+ //# sourceMappingURL=perf-compare.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"perf-compare.d.ts","sourceRoot":"","sources":["../../src/commands/perf-compare.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA4KH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAkHnD"}
@@ -0,0 +1,246 @@
1
+ /**
2
+ * Perf compare — before/after performance comparison of code changes.
3
+ * Compares algorithmic complexity, loop nesting, allocation patterns,
4
+ * and async anti-patterns between two code versions.
5
+ *
6
+ * All analysis local.
7
+ */
8
+ import { existsSync, readFileSync } from "fs";
9
+ // ─── Analysers ──────────────────────────────────────────────────────────────
10
+ function analyzePerformance(content) {
11
+ const lines = content.split("\n");
12
+ // Loop depth
13
+ let maxLoopDepth = 0;
14
+ let currentDepth = 0;
15
+ let loopCount = 0;
16
+ for (const line of lines) {
17
+ if (/\b(?:for|while|do)\s*\(/.test(line) || /\.(?:forEach|map|filter|reduce|flatMap|some|every)\s*\(/.test(line)) {
18
+ currentDepth++;
19
+ loopCount++;
20
+ maxLoopDepth = Math.max(maxLoopDepth, currentDepth);
21
+ }
22
+ // Rough depth tracking by braces
23
+ const opens = (line.match(/{/g) || []).length;
24
+ const closes = (line.match(/}/g) || []).length;
25
+ if (closes > opens && currentDepth > 0)
26
+ currentDepth--;
27
+ }
28
+ // Allocations (new, object/array literals in loops)
29
+ let allocations = 0;
30
+ for (const line of lines) {
31
+ if (/\bnew\s+\w+/.test(line))
32
+ allocations++;
33
+ if (/(?:new\s+Array|new\s+Object|\[\s*\]|\{\s*\})\s*;?\s*$/.test(line.trim()))
34
+ allocations++;
35
+ }
36
+ // Async anti-patterns
37
+ let asyncAntiPatterns = 0;
38
+ for (let i = 0; i < lines.length; i++) {
39
+ // await in loop
40
+ if (/\bawait\b/.test(lines[i]) && currentDepth > 0)
41
+ asyncAntiPatterns++;
42
+ // sequential awaits that could be parallel
43
+ if (/\bawait\b/.test(lines[i]) && i > 0 && /\bawait\b/.test(lines[i - 1]))
44
+ asyncAntiPatterns++;
45
+ }
46
+ // Recursive calls
47
+ let recursiveCalls = 0;
48
+ const fnNames = [];
49
+ for (const line of lines) {
50
+ const fnMatch = line.match(/(?:function\s+(\w+)|(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?(?:\(|function))/);
51
+ if (fnMatch)
52
+ fnNames.push(fnMatch[1] || fnMatch[2]);
53
+ }
54
+ for (const line of lines) {
55
+ for (const fn of fnNames) {
56
+ if (fn && new RegExp(`\\b${fn}\\s*\\(`).test(line)) {
57
+ const fnDef = lines.find((l) => l.includes(`function ${fn}`) || l.includes(`${fn} =`));
58
+ if (fnDef && fnDef !== line)
59
+ recursiveCalls++;
60
+ }
61
+ }
62
+ }
63
+ // Regex count (complex regex can be perf bottleneck)
64
+ let regexCount = 0;
65
+ for (const line of lines) {
66
+ if (/new\s+RegExp|\/[^/]+\/[gimsuy]*/.test(line))
67
+ regexCount++;
68
+ }
69
+ // String concatenation in loops
70
+ let stringConcat = 0;
71
+ for (const line of lines) {
72
+ if (/\+=\s*["'`]|["'`]\s*\+/.test(line))
73
+ stringConcat++;
74
+ }
75
+ // Nested callbacks
76
+ let nestedCallbacks = 0;
77
+ let callbackDepth = 0;
78
+ for (const line of lines) {
79
+ if (/\bcallback\b|function\s*\(|=>\s*{/.test(line)) {
80
+ callbackDepth++;
81
+ if (callbackDepth >= 3)
82
+ nestedCallbacks++;
83
+ }
84
+ if (/}\s*\)/.test(line) && callbackDepth > 0)
85
+ callbackDepth--;
86
+ }
87
+ // Big-O estimate
88
+ let bigO = "O(n)";
89
+ if (maxLoopDepth >= 3)
90
+ bigO = "O(n³+)";
91
+ else if (maxLoopDepth === 2)
92
+ bigO = "O(n²)";
93
+ else if (recursiveCalls > 0 && maxLoopDepth > 0)
94
+ bigO = "O(n log n)";
95
+ else if (loopCount === 0)
96
+ bigO = "O(1)";
97
+ return {
98
+ loopDepth: maxLoopDepth,
99
+ loopCount,
100
+ allocations,
101
+ asyncAntiPatterns,
102
+ recursiveCalls,
103
+ regexCount,
104
+ stringConcat,
105
+ nestedCallbacks,
106
+ bigOEstimate: bigO,
107
+ lineCount: lines.length,
108
+ };
109
+ }
110
+ function compareAnalyses(before, after) {
111
+ const metrics = [];
112
+ function add(name, b, a, higherIsWorse, severity) {
113
+ const delta = a - b;
114
+ let verdict = "unchanged";
115
+ if (delta !== 0)
116
+ verdict = delta > 0 === higherIsWorse ? "regressed" : "improved";
117
+ metrics.push({
118
+ name,
119
+ before: b,
120
+ after: a,
121
+ delta,
122
+ verdict,
123
+ severity: verdict === "regressed" ? severity : undefined,
124
+ });
125
+ }
126
+ add("Loop nesting depth", before.loopDepth, after.loopDepth, true, "high");
127
+ add("Loop count", before.loopCount, after.loopCount, true, "medium");
128
+ add("Allocations", before.allocations, after.allocations, true, "medium");
129
+ add("Async anti-patterns", before.asyncAntiPatterns, after.asyncAntiPatterns, true, "high");
130
+ add("Recursive calls", before.recursiveCalls, after.recursiveCalls, true, "medium");
131
+ add("Regex operations", before.regexCount, after.regexCount, true, "low");
132
+ add("String concatenations", before.stringConcat, after.stringConcat, true, "low");
133
+ add("Nested callbacks", before.nestedCallbacks, after.nestedCallbacks, true, "medium");
134
+ add("Lines of code", before.lineCount, after.lineCount, true, "low");
135
+ // Big-O change
136
+ const oOrder = ["O(1)", "O(log n)", "O(n)", "O(n log n)", "O(n²)", "O(n³+)"];
137
+ const bIdx = oOrder.indexOf(before.bigOEstimate);
138
+ const aIdx = oOrder.indexOf(after.bigOEstimate);
139
+ metrics.push({
140
+ name: "Algorithmic complexity",
141
+ before: bIdx,
142
+ after: aIdx,
143
+ delta: aIdx - bIdx,
144
+ verdict: aIdx > bIdx ? "regressed" : aIdx < bIdx ? "improved" : "unchanged",
145
+ severity: aIdx > bIdx ? "critical" : undefined,
146
+ detail: `${before.bigOEstimate} → ${after.bigOEstimate}`,
147
+ });
148
+ return metrics;
149
+ }
150
+ // ─── CLI ────────────────────────────────────────────────────────────────────
151
+ export function runPerfCompare(argv) {
152
+ if (argv.includes("--help") || argv.includes("-h")) {
153
+ console.log(`
154
+ judges perf-compare — Before/after performance comparison
155
+
156
+ Usage:
157
+ judges perf-compare <before-file> <after-file>
158
+ judges perf-compare old.ts new.ts --format json
159
+
160
+ Options:
161
+ --format json JSON output
162
+ --help, -h Show this help
163
+
164
+ Analyses:
165
+ • Loop nesting depth & count
166
+ • Memory allocations
167
+ • Async anti-patterns (await in loop, sequential awaits)
168
+ • Recursive call patterns
169
+ • Regex operation count
170
+ • String concatenation patterns
171
+ • Callback nesting depth
172
+ • Algorithmic complexity estimate (Big-O)
173
+ `);
174
+ return;
175
+ }
176
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
177
+ const positional = argv.filter((a) => !a.startsWith("--") && !argv[argv.indexOf(a) - 1]?.startsWith("--"));
178
+ if (positional.length < 2) {
179
+ console.error(" Usage: judges perf-compare <before-file> <after-file>");
180
+ return;
181
+ }
182
+ const [beforeFile, afterFile] = positional;
183
+ if (!existsSync(beforeFile)) {
184
+ console.error(` File not found: ${beforeFile}`);
185
+ return;
186
+ }
187
+ if (!existsSync(afterFile)) {
188
+ console.error(` File not found: ${afterFile}`);
189
+ return;
190
+ }
191
+ let beforeContent, afterContent;
192
+ try {
193
+ beforeContent = readFileSync(beforeFile, "utf-8");
194
+ }
195
+ catch {
196
+ console.error(` Cannot read: ${beforeFile}`);
197
+ return;
198
+ }
199
+ try {
200
+ afterContent = readFileSync(afterFile, "utf-8");
201
+ }
202
+ catch {
203
+ console.error(` Cannot read: ${afterFile}`);
204
+ return;
205
+ }
206
+ const beforeAnalysis = analyzePerformance(beforeContent);
207
+ const afterAnalysis = analyzePerformance(afterContent);
208
+ const metrics = compareAnalyses(beforeAnalysis, afterAnalysis);
209
+ const regressions = metrics.filter((m) => m.verdict === "regressed");
210
+ const improvements = metrics.filter((m) => m.verdict === "improved");
211
+ if (format === "json") {
212
+ console.log(JSON.stringify({
213
+ before: { file: beforeFile, analysis: beforeAnalysis },
214
+ after: { file: afterFile, analysis: afterAnalysis },
215
+ metrics,
216
+ summary: {
217
+ regressions: regressions.length,
218
+ improvements: improvements.length,
219
+ unchanged: metrics.filter((m) => m.verdict === "unchanged").length,
220
+ },
221
+ timestamp: new Date().toISOString(),
222
+ }, null, 2));
223
+ }
224
+ else {
225
+ console.log(`\n Performance Comparison`);
226
+ console.log(` Before: ${beforeFile} (${beforeAnalysis.bigOEstimate})`);
227
+ console.log(` After: ${afterFile} (${afterAnalysis.bigOEstimate})\n ──────────────────────────`);
228
+ console.log(`\n ${"Metric".padEnd(30)} ${"Before".padEnd(8)} ${"After".padEnd(8)} ${"Delta".padEnd(8)} Verdict`);
229
+ console.log(` ${"─".repeat(70)}`);
230
+ for (const m of metrics) {
231
+ const icon = m.verdict === "improved" ? "✅" : m.verdict === "regressed" ? "❌" : "➖";
232
+ const deltaStr = m.delta > 0 ? `+${m.delta}` : String(m.delta);
233
+ const detail = m.detail ? ` (${m.detail})` : "";
234
+ console.log(` ${m.name.padEnd(30)} ${String(m.before).padEnd(8)} ${String(m.after).padEnd(8)} ${deltaStr.padEnd(8)} ${icon}${detail}`);
235
+ }
236
+ console.log(`\n Summary: ${improvements.length} improved, ${regressions.length} regressed, ${metrics.length - improvements.length - regressions.length} unchanged`);
237
+ if (regressions.length > 0) {
238
+ console.log(`\n ⚠️ Performance regressions detected:`);
239
+ for (const r of regressions) {
240
+ console.log(` • ${r.name}: ${r.before} → ${r.after}${r.severity ? ` [${r.severity}]` : ""}${r.detail ? ` (${r.detail})` : ""}`);
241
+ }
242
+ }
243
+ console.log("");
244
+ }
245
+ }
246
+ //# sourceMappingURL=perf-compare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"perf-compare.js","sourceRoot":"","sources":["../../src/commands/perf-compare.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * PII scan — detect personally-identifiable information patterns
3
+ * in source code: string literals, logs, config files.
4
+ *
5
+ * All analysis local.
6
+ */
7
+ export declare function runPiiScan(argv: string[]): void;
8
+ //# sourceMappingURL=pii-scan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pii-scan.d.ts","sourceRoot":"","sources":["../../src/commands/pii-scan.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAuNH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAsH/C"}