pi-lens 1.3.7 → 1.3.9

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.
@@ -238,6 +238,7 @@ function long(): number {
238
238
  maintainabilityIndex: 75,
239
239
  linesOfCode: 100,
240
240
  commentLines: 10,
241
+ codeEntropy: 0.5,
241
242
  };
242
243
 
243
244
  const formatted = client.formatMetrics(metrics);
@@ -259,6 +260,7 @@ function long(): number {
259
260
  maintainabilityIndex: 25,
260
261
  linesOfCode: 500,
261
262
  commentLines: 10,
263
+ codeEntropy: 0.5,
262
264
  };
263
265
 
264
266
  const formatted = client.formatMetrics(metrics);
@@ -34,6 +34,7 @@ export interface FileComplexity {
34
34
  maintainabilityIndex: number; // 0-100
35
35
  linesOfCode: number;
36
36
  commentLines: number;
37
+ codeEntropy: number; // Shannon entropy (0-1, lower = more predictable)
37
38
  }
38
39
 
39
40
  export interface FunctionMetrics {
@@ -195,6 +196,9 @@ export class ComplexityClient {
195
196
  commentLines
196
197
  );
197
198
 
199
+ // Code Entropy (Shannon entropy of code tokens)
200
+ const codeEntropy = this.calculateCodeEntropy(content);
201
+
198
202
  return {
199
203
  filePath: path.relative(process.cwd(), absolutePath),
200
204
  maxNestingDepth,
@@ -208,6 +212,7 @@ export class ComplexityClient {
208
212
  maintainabilityIndex: Math.round(maintainabilityIndex * 10) / 10,
209
213
  linesOfCode: codeLines,
210
214
  commentLines,
215
+ codeEntropy: Math.round(codeEntropy * 100) / 100,
211
216
  };
212
217
  } catch (err: any) {
213
218
  this.log(`Analysis error for ${filePath}: ${err.message}`);
@@ -242,6 +247,11 @@ export class ComplexityClient {
242
247
  parts.push(` Max nesting: ${metrics.maxNestingDepth} levels (consider extracting)`);
243
248
  }
244
249
 
250
+ // Code entropy (in bits, >3.5 = risky AI-induced complexity)
251
+ if (metrics.codeEntropy > 3.5) {
252
+ parts.push(` Entropy: ${metrics.codeEntropy.toFixed(1)} bits (>3.5 — risky AI-induced complexity)`);
253
+ }
254
+
245
255
  // Function length
246
256
  if (metrics.maxFunctionLength > 50) {
247
257
  parts.push(` Longest function: ${metrics.maxFunctionLength} lines (avg: ${metrics.avgFunctionLength})`);
@@ -491,6 +501,41 @@ export class ComplexityClient {
491
501
  return totalOps * Math.log2(uniqueOps);
492
502
  }
493
503
 
504
+ /**
505
+ * Calculate Shannon entropy of code tokens (in bits)
506
+ * Uses log2 for entropy measured in bits
507
+ * Threshold: >3.5 bits indicates risky AI-induced complexity
508
+ */
509
+ private calculateCodeEntropy(sourceText: string): number {
510
+ // Tokenize by splitting on whitespace and common delimiters
511
+ const tokens = sourceText
512
+ .replace(/\/\/.*/g, "") // Remove single-line comments
513
+ .replace(/\/\*[\s\S]*?\*\//g, "") // Remove multi-line comments
514
+ .replace(/["'`][^"'`]*["'`]/g, "STR") // Normalize strings
515
+ .replace(/\b\d+(\.\d+)?\b/g, "NUM") // Normalize numbers
516
+ .split(/[\s\n\r\t,;:()[\]{}=<>!&|+\-*/%^~?]+/)
517
+ .filter(t => t.length > 0);
518
+
519
+ if (tokens.length === 0) return 0;
520
+
521
+ // Count token frequencies
522
+ const freq = new Map<string, number>();
523
+ for (const token of tokens) {
524
+ freq.set(token, (freq.get(token) || 0) + 1);
525
+ }
526
+
527
+ // Calculate Shannon entropy in bits: H = -sum(p * log2(p))
528
+ let entropy = 0;
529
+ for (const count of freq.values()) {
530
+ const p = count / tokens.length;
531
+ if (p > 0) {
532
+ entropy -= p * Math.log2(p);
533
+ }
534
+ }
535
+
536
+ return entropy; // Return in bits, not normalized
537
+ }
538
+
494
539
  private isKeyword(text: string): boolean {
495
540
  const keywords = new Set([
496
541
  "if", "else", "for", "while", "do", "switch", "case", "break", "continue",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-lens",
3
- "version": "1.3.7",
3
+ "version": "1.3.9",
4
4
  "description": "Real-time code feedback for pi — TypeScript LSP, Biome, ast-grep, Ruff, TODO scanner, dead code, duplicate detection, type coverage",
5
5
  "repository": {
6
6
  "type": "git",