@aiready/pattern-detect 0.16.20 → 0.16.22

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/dist/index.d.mts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { ToolProvider } from '@aiready/core';
2
2
  export { Severity } from '@aiready/core';
3
- export { D as DuplicateGroup, P as PatternDetectOptions, a as PatternSummary, R as RefactorCluster, b as analyzePatterns, c as createRefactorClusters, f as filterClustersByImpact, g as generateSummary, d as getSmartDefaults, e as groupDuplicatesByFilePair } from './analyzer-entry-BVz-HnZd.mjs';
4
- export { detectDuplicatePatterns } from './detector-entry.mjs';
5
- export { calculatePatternScore } from './scoring-entry.mjs';
6
- export { C as CONTEXT_RULES, a as ContextRule, c as calculateSeverity, f as filterBySeverity, g as getSeverityLabel, b as getSeverityThreshold } from './context-rules-entry-y2uJSngh.mjs';
3
+ export { D as DuplicateGroup, P as PatternDetectOptions, a as PatternSummary, R as RefactorCluster, b as analyzePatterns, c as createRefactorClusters, f as filterClustersByImpact, g as generateSummary, d as getSmartDefaults, e as groupDuplicatesByFilePair } from './index-BVz-HnZd.mjs';
4
+ export { detectDuplicatePatterns } from './detector-entry/index.mjs';
5
+ export { calculatePatternScore } from './scoring-entry/index.mjs';
6
+ export { C as CONTEXT_RULES, a as ContextRule, c as calculateSeverity, f as filterBySeverity, g as getSeverityLabel, b as getSeverityThreshold } from './index-y2uJSngh.mjs';
7
7
  export { D as DuplicatePattern, P as PatternType } from './types-DU2mmhwb.mjs';
8
8
 
9
9
  /**
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { ToolProvider } from '@aiready/core';
2
2
  export { Severity } from '@aiready/core';
3
- export { D as DuplicateGroup, P as PatternDetectOptions, a as PatternSummary, R as RefactorCluster, b as analyzePatterns, c as createRefactorClusters, f as filterClustersByImpact, g as generateSummary, d as getSmartDefaults, e as groupDuplicatesByFilePair } from './analyzer-entry-BwuoiCNm.js';
4
- export { detectDuplicatePatterns } from './detector-entry.js';
5
- export { calculatePatternScore } from './scoring-entry.js';
6
- export { C as CONTEXT_RULES, a as ContextRule, c as calculateSeverity, f as filterBySeverity, g as getSeverityLabel, b as getSeverityThreshold } from './context-rules-entry-y2uJSngh.js';
3
+ export { D as DuplicateGroup, P as PatternDetectOptions, a as PatternSummary, R as RefactorCluster, b as analyzePatterns, c as createRefactorClusters, f as filterClustersByImpact, g as generateSummary, d as getSmartDefaults, e as groupDuplicatesByFilePair } from './index-BwuoiCNm.js';
4
+ export { detectDuplicatePatterns } from './detector-entry/index.js';
5
+ export { calculatePatternScore } from './scoring-entry/index.js';
6
+ export { C as CONTEXT_RULES, a as ContextRule, c as calculateSeverity, f as filterBySeverity, g as getSeverityLabel, b as getSeverityThreshold } from './index-y2uJSngh.js';
7
7
  export { D as DuplicatePattern, P as PatternType } from './types-DU2mmhwb.js';
8
8
 
9
9
  /**
@@ -0,0 +1,23 @@
1
+ import { CostConfig, ToolScoringOutput } from '@aiready/core';
2
+ import { D as DuplicatePattern } from '../types-DU2mmhwb.mjs';
3
+
4
+ /**
5
+ * Calculate AI Readiness Score for pattern duplication (0-100)
6
+ *
7
+ * Based on:
8
+ * - Number of duplicates per file
9
+ * - Token waste per file
10
+ * - High-impact duplicates (>1000 tokens or >70% similarity)
11
+ *
12
+ * Includes business value metrics:
13
+ * - Estimated monthly cost of token waste
14
+ * - Estimated developer hours to fix
15
+ *
16
+ * @param duplicates - Array of detected duplicate patterns.
17
+ * @param totalFilesAnalyzed - Total count of files scanned.
18
+ * @param costConfig - Optional configuration for business value calculations.
19
+ * @returns Standardized scoring output for pattern detection.
20
+ */
21
+ declare function calculatePatternScore(duplicates: DuplicatePattern[], totalFilesAnalyzed: number, costConfig?: Partial<CostConfig>): ToolScoringOutput;
22
+
23
+ export { calculatePatternScore };
@@ -0,0 +1,23 @@
1
+ import { CostConfig, ToolScoringOutput } from '@aiready/core';
2
+ import { D as DuplicatePattern } from '../types-DU2mmhwb.js';
3
+
4
+ /**
5
+ * Calculate AI Readiness Score for pattern duplication (0-100)
6
+ *
7
+ * Based on:
8
+ * - Number of duplicates per file
9
+ * - Token waste per file
10
+ * - High-impact duplicates (>1000 tokens or >70% similarity)
11
+ *
12
+ * Includes business value metrics:
13
+ * - Estimated monthly cost of token waste
14
+ * - Estimated developer hours to fix
15
+ *
16
+ * @param duplicates - Array of detected duplicate patterns.
17
+ * @param totalFilesAnalyzed - Total count of files scanned.
18
+ * @param costConfig - Optional configuration for business value calculations.
19
+ * @returns Standardized scoring output for pattern detection.
20
+ */
21
+ declare function calculatePatternScore(duplicates: DuplicatePattern[], totalFilesAnalyzed: number, costConfig?: Partial<CostConfig>): ToolScoringOutput;
22
+
23
+ export { calculatePatternScore };
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/scoring-entry/index.ts
21
+ var scoring_entry_exports = {};
22
+ __export(scoring_entry_exports, {
23
+ calculatePatternScore: () => calculatePatternScore
24
+ });
25
+ module.exports = __toCommonJS(scoring_entry_exports);
26
+
27
+ // src/scoring.ts
28
+ var import_core = require("@aiready/core");
29
+ function calculatePatternScore(duplicates, totalFilesAnalyzed, costConfig) {
30
+ const totalDuplicates = duplicates.length;
31
+ const totalTokenCost = duplicates.reduce((sum, d) => sum + d.tokenCost, 0);
32
+ const highImpactDuplicates = duplicates.filter(
33
+ (d) => d.tokenCost > 1e3 || d.similarity > 0.7
34
+ ).length;
35
+ if (totalFilesAnalyzed === 0) {
36
+ return {
37
+ toolName: import_core.ToolName.PatternDetect,
38
+ score: 100,
39
+ rawMetrics: {
40
+ totalDuplicates: 0,
41
+ totalTokenCost: 0,
42
+ highImpactDuplicates: 0,
43
+ totalFilesAnalyzed: 0
44
+ },
45
+ factors: [],
46
+ recommendations: []
47
+ };
48
+ }
49
+ const duplicatesPerFile = totalDuplicates / totalFilesAnalyzed * 100;
50
+ const tokenWastePerFile = totalTokenCost / totalFilesAnalyzed;
51
+ const duplicatesPenalty = Math.min(60, duplicatesPerFile * 0.6);
52
+ const tokenPenalty = Math.min(40, tokenWastePerFile / 125);
53
+ const highImpactPenalty = highImpactDuplicates > 0 ? Math.min(15, highImpactDuplicates * 2 - 5) : -5;
54
+ const score = 100 - duplicatesPenalty - tokenPenalty - highImpactPenalty;
55
+ const finalScore = Math.max(0, Math.min(100, Math.round(score)));
56
+ const factors = [
57
+ {
58
+ name: "Duplication Density",
59
+ impact: -Math.round(duplicatesPenalty),
60
+ description: `${duplicatesPerFile.toFixed(1)} duplicates per 100 files`
61
+ },
62
+ {
63
+ name: "Token Waste",
64
+ impact: -Math.round(tokenPenalty),
65
+ description: `${Math.round(tokenWastePerFile)} tokens wasted per file`
66
+ }
67
+ ];
68
+ if (highImpactDuplicates > 0) {
69
+ factors.push({
70
+ name: "High-Impact Patterns",
71
+ impact: -Math.round(highImpactPenalty),
72
+ description: `${highImpactDuplicates} high-impact duplicates (>1000 tokens or >70% similar)`
73
+ });
74
+ } else {
75
+ factors.push({
76
+ name: "No High-Impact Patterns",
77
+ impact: 5,
78
+ description: "No severe duplicates detected"
79
+ });
80
+ }
81
+ const recommendations = [];
82
+ if (highImpactDuplicates > 0) {
83
+ const estimatedImpact = Math.min(15, highImpactDuplicates * 3);
84
+ recommendations.push({
85
+ action: `Deduplicate ${highImpactDuplicates} high-impact pattern${highImpactDuplicates > 1 ? "s" : ""}`,
86
+ estimatedImpact,
87
+ priority: "high"
88
+ });
89
+ }
90
+ if (totalDuplicates > 10 && duplicatesPerFile > 20) {
91
+ const estimatedImpact = Math.min(10, Math.round(duplicatesPenalty * 0.3));
92
+ recommendations.push({
93
+ action: "Extract common patterns into shared utilities",
94
+ estimatedImpact,
95
+ priority: "medium"
96
+ });
97
+ }
98
+ if (tokenWastePerFile > 2e3) {
99
+ const estimatedImpact = Math.min(8, Math.round(tokenPenalty * 0.4));
100
+ recommendations.push({
101
+ action: "Consolidate duplicated logic to reduce AI context waste",
102
+ estimatedImpact,
103
+ priority: totalTokenCost > 1e4 ? "high" : "medium"
104
+ });
105
+ }
106
+ const cfg = { ...import_core.DEFAULT_COST_CONFIG, ...costConfig };
107
+ const estimatedMonthlyCost = (0, import_core.calculateMonthlyCost)(totalTokenCost, cfg);
108
+ const issues = duplicates.map((d) => ({
109
+ severity: d.severity === "critical" ? "critical" : d.severity === "major" ? "major" : "minor"
110
+ }));
111
+ const productivityImpact = (0, import_core.calculateProductivityImpact)(issues);
112
+ return {
113
+ toolName: "pattern-detect",
114
+ score: finalScore,
115
+ rawMetrics: {
116
+ totalDuplicates,
117
+ totalTokenCost,
118
+ highImpactDuplicates,
119
+ totalFilesAnalyzed,
120
+ duplicatesPerFile: Math.round(duplicatesPerFile * 10) / 10,
121
+ tokenWastePerFile: Math.round(tokenWastePerFile),
122
+ // Business value metrics
123
+ estimatedMonthlyCost,
124
+ estimatedDeveloperHours: productivityImpact.totalHours
125
+ },
126
+ factors,
127
+ recommendations
128
+ };
129
+ }
130
+ // Annotate the CommonJS export names for ESM import in node:
131
+ 0 && (module.exports = {
132
+ calculatePatternScore
133
+ });
@@ -0,0 +1,6 @@
1
+ import {
2
+ calculatePatternScore
3
+ } from "../chunk-WBBO35SC.mjs";
4
+ export {
5
+ calculatePatternScore
6
+ };
@@ -1,5 +1,5 @@
1
1
  import { CostConfig, ToolScoringOutput } from '@aiready/core';
2
- import { D as DuplicatePattern } from './types-DU2mmhwb.mjs';
2
+ import { a as DuplicatePattern } from './types-C4lmb2Yh.mjs';
3
3
 
4
4
  /**
5
5
  * Calculate AI Readiness Score for pattern duplication (0-100)
@@ -1,5 +1,5 @@
1
1
  import { CostConfig, ToolScoringOutput } from '@aiready/core';
2
- import { D as DuplicatePattern } from './types-DU2mmhwb.js';
2
+ import { a as DuplicatePattern } from './types-C4lmb2Yh.js';
3
3
 
4
4
  /**
5
5
  * Calculate AI Readiness Score for pattern duplication (0-100)
@@ -0,0 +1,36 @@
1
+ import { Severity } from '@aiready/core';
2
+
3
+ type PatternType = 'api-handler' | 'validator' | 'utility' | 'class-method' | 'component' | 'function' | 'unknown';
4
+ interface DuplicatePattern {
5
+ file1: string;
6
+ line1: number;
7
+ endLine1: number;
8
+ file2: string;
9
+ line2: number;
10
+ endLine2: number;
11
+ code1: string;
12
+ code2: string;
13
+ similarity: number;
14
+ confidence: number;
15
+ patternType: PatternType;
16
+ tokenCost: number;
17
+ severity: Severity;
18
+ reason?: string;
19
+ suggestion?: string;
20
+ matchedRule?: string;
21
+ }
22
+ interface DetectionOptions {
23
+ minSimilarity: number;
24
+ minLines: number;
25
+ batchSize: number;
26
+ approx: boolean;
27
+ minSharedTokens: number;
28
+ maxCandidatesPerBlock: number;
29
+ streamResults: boolean;
30
+ excludePatterns?: string[];
31
+ confidenceThreshold?: number;
32
+ ignoreWhitelist?: string[];
33
+ onProgress?: (processed: number, total: number, message: string) => void;
34
+ }
35
+
36
+ export type { DetectionOptions as D, PatternType as P, DuplicatePattern as a };
@@ -0,0 +1,36 @@
1
+ import { Severity } from '@aiready/core';
2
+
3
+ type PatternType = 'api-handler' | 'validator' | 'utility' | 'class-method' | 'component' | 'function' | 'unknown';
4
+ interface DuplicatePattern {
5
+ file1: string;
6
+ line1: number;
7
+ endLine1: number;
8
+ file2: string;
9
+ line2: number;
10
+ endLine2: number;
11
+ code1: string;
12
+ code2: string;
13
+ similarity: number;
14
+ confidence: number;
15
+ patternType: PatternType;
16
+ tokenCost: number;
17
+ severity: Severity;
18
+ reason?: string;
19
+ suggestion?: string;
20
+ matchedRule?: string;
21
+ }
22
+ interface DetectionOptions {
23
+ minSimilarity: number;
24
+ minLines: number;
25
+ batchSize: number;
26
+ approx: boolean;
27
+ minSharedTokens: number;
28
+ maxCandidatesPerBlock: number;
29
+ streamResults: boolean;
30
+ excludePatterns?: string[];
31
+ confidenceThreshold?: number;
32
+ ignoreWhitelist?: string[];
33
+ onProgress?: (processed: number, total: number, message: string) => void;
34
+ }
35
+
36
+ export type { DetectionOptions as D, PatternType as P, DuplicatePattern as a };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/pattern-detect",
3
- "version": "0.16.20",
3
+ "version": "0.16.22",
4
4
  "description": "Semantic duplicate pattern detection for AI-generated code - finds similar implementations that waste AI context tokens",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -15,24 +15,24 @@
15
15
  "import": "./dist/index.mjs"
16
16
  },
17
17
  "./analyzer": {
18
- "types": "./dist/analyzer-entry.d.ts",
19
- "require": "./dist/analyzer-entry.js",
20
- "import": "./dist/analyzer-entry.mjs"
18
+ "types": "./dist/analyzer-entry/index.d.ts",
19
+ "require": "./dist/analyzer-entry/index.js",
20
+ "import": "./dist/analyzer-entry/index.mjs"
21
21
  },
22
22
  "./detector": {
23
- "types": "./dist/detector-entry.d.ts",
24
- "require": "./dist/detector-entry.js",
25
- "import": "./dist/detector-entry.mjs"
23
+ "types": "./dist/detector-entry/index.d.ts",
24
+ "require": "./dist/detector-entry/index.js",
25
+ "import": "./dist/detector-entry/index.mjs"
26
26
  },
27
27
  "./scoring": {
28
- "types": "./dist/scoring-entry.d.ts",
29
- "require": "./dist/scoring-entry.js",
30
- "import": "./dist/scoring-entry.mjs"
28
+ "types": "./dist/scoring-entry/index.d.ts",
29
+ "require": "./dist/scoring-entry/index.js",
30
+ "import": "./dist/scoring-entry/index.mjs"
31
31
  },
32
32
  "./context-rules": {
33
- "types": "./dist/context-rules-entry.d.ts",
34
- "require": "./dist/context-rules-entry.js",
35
- "import": "./dist/context-rules-entry.mjs"
33
+ "types": "./dist/context-rules-entry/index.d.ts",
34
+ "require": "./dist/context-rules-entry/index.js",
35
+ "import": "./dist/context-rules-entry/index.mjs"
36
36
  }
37
37
  },
38
38
  "keywords": [
@@ -65,7 +65,7 @@
65
65
  "dependencies": {
66
66
  "commander": "^14.0.0",
67
67
  "chalk": "^5.3.0",
68
- "@aiready/core": "0.23.21"
68
+ "@aiready/core": "0.23.23"
69
69
  },
70
70
  "devDependencies": {
71
71
  "tsup": "^8.3.5",
@@ -84,8 +84,8 @@
84
84
  "access": "public"
85
85
  },
86
86
  "scripts": {
87
- "build": "tsup src/index.ts src/cli.ts src/analyzer-entry.ts src/detector-entry.ts src/scoring-entry.ts src/context-rules-entry.ts --format cjs,esm --dts",
88
- "dev": "tsup src/index.ts src/cli.ts src/analyzer-entry.ts src/detector-entry.ts src/scoring-entry.ts src/context-rules-entry.ts --format cjs,esm --dts --watch",
87
+ "build": "tsup src/index.ts src/cli.ts src/analyzer-entry/index.ts src/detector-entry/index.ts src/scoring-entry/index.ts src/context-rules-entry/index.ts --format cjs,esm --dts",
88
+ "dev": "tsup src/index.ts src/cli.ts src/analyzer-entry/index.ts src/detector-entry/index.ts src/scoring-entry/index.ts src/context-rules-entry/index.ts --format cjs,esm --dts --watch",
89
89
  "test": "vitest run",
90
90
  "lint": "eslint src",
91
91
  "clean": "rm -rf dist",