@aiready/pattern-detect 0.8.0 → 0.8.2
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/README.md +18 -3
- package/dist/cli.js +20 -7
- package/dist/cli.mjs +23 -10
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -24,11 +24,21 @@ aiready-patterns ./src
|
|
|
24
24
|
|
|
25
25
|
AI tools generate similar code in different ways because they lack awareness of your codebase patterns. This tool:
|
|
26
26
|
|
|
27
|
-
- **Semantic detection**: Finds functionally similar code (not just copy-paste)
|
|
27
|
+
- **Semantic detection**: Finds functionally similar code (not just copy-paste) using Jaccard similarity on AST tokens
|
|
28
28
|
- **Pattern classification**: Groups duplicates by type (API handlers, validators, utilities, etc.)
|
|
29
29
|
- **Token cost analysis**: Shows wasted AI context budget
|
|
30
30
|
- **Refactoring guidance**: Suggests specific fixes per pattern type
|
|
31
31
|
|
|
32
|
+
### How It Works
|
|
33
|
+
|
|
34
|
+
The tool uses **Jaccard similarity** to compare code semantically:
|
|
35
|
+
1. Parses TypeScript/JavaScript files into Abstract Syntax Trees (AST)
|
|
36
|
+
2. Extracts semantic tokens (identifiers, operators, keywords) from each function
|
|
37
|
+
3. Calculates Jaccard similarity between token sets: `|A ∩ B| / |A ∪ B|`
|
|
38
|
+
4. Groups similar functions above the similarity threshold
|
|
39
|
+
|
|
40
|
+
This approach catches duplicates even when variable names or minor logic differs.
|
|
41
|
+
|
|
32
42
|
### Example Output
|
|
33
43
|
|
|
34
44
|
```
|
|
@@ -58,10 +68,15 @@ aiready patterns ./src --similarity 0.9
|
|
|
58
68
|
# Include smaller patterns
|
|
59
69
|
aiready patterns ./src --min-lines 3
|
|
60
70
|
|
|
61
|
-
# Export results
|
|
62
|
-
aiready patterns ./src --output json
|
|
71
|
+
# Export results (saved to .aiready/ by default)
|
|
72
|
+
aiready patterns ./src --output json
|
|
73
|
+
|
|
74
|
+
# Or specify custom path
|
|
75
|
+
aiready patterns ./src --output json --output-file custom-report.json
|
|
63
76
|
```
|
|
64
77
|
|
|
78
|
+
> **📁 Output Files:** By default, all output files are saved to the `.aiready/` directory in your project root. You can override this with `--output-file`.
|
|
79
|
+
|
|
65
80
|
## 🎛️ Tuning Guide
|
|
66
81
|
|
|
67
82
|
### Main Parameters
|
package/dist/cli.js
CHANGED
|
@@ -590,18 +590,31 @@ program.name("aiready-patterns").description("Detect duplicate patterns in your
|
|
|
590
590
|
results,
|
|
591
591
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
592
592
|
};
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
593
|
+
const outputPath = (0, import_core3.resolveOutputPath)(
|
|
594
|
+
options.outputFile,
|
|
595
|
+
`pattern-report-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.json`,
|
|
596
|
+
directory
|
|
597
|
+
);
|
|
598
|
+
const dir = (0, import_path.dirname)(outputPath);
|
|
599
|
+
if (!(0, import_fs.existsSync)(dir)) {
|
|
600
|
+
(0, import_fs.mkdirSync)(dir, { recursive: true });
|
|
599
601
|
}
|
|
602
|
+
(0, import_fs.writeFileSync)(outputPath, JSON.stringify(jsonOutput, null, 2));
|
|
603
|
+
console.log(import_chalk.default.green(`
|
|
604
|
+
\u2713 JSON report saved to ${outputPath}`));
|
|
600
605
|
return;
|
|
601
606
|
}
|
|
602
607
|
if (options.output === "html") {
|
|
603
608
|
const html = generateHTMLReport(summary, results);
|
|
604
|
-
const outputPath =
|
|
609
|
+
const outputPath = (0, import_core3.resolveOutputPath)(
|
|
610
|
+
options.outputFile,
|
|
611
|
+
`pattern-report-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.html`,
|
|
612
|
+
directory
|
|
613
|
+
);
|
|
614
|
+
const dir = (0, import_path.dirname)(outputPath);
|
|
615
|
+
if (!(0, import_fs.existsSync)(dir)) {
|
|
616
|
+
(0, import_fs.mkdirSync)(dir, { recursive: true });
|
|
617
|
+
}
|
|
605
618
|
(0, import_fs.writeFileSync)(outputPath, html);
|
|
606
619
|
console.log(import_chalk.default.green(`
|
|
607
620
|
\u2713 HTML report saved to ${outputPath}`));
|
package/dist/cli.mjs
CHANGED
|
@@ -7,9 +7,9 @@ import {
|
|
|
7
7
|
// src/cli.ts
|
|
8
8
|
import { Command } from "commander";
|
|
9
9
|
import chalk from "chalk";
|
|
10
|
-
import { writeFileSync } from "fs";
|
|
11
|
-
import {
|
|
12
|
-
import { loadConfig, mergeConfigWithDefaults } from "@aiready/core";
|
|
10
|
+
import { writeFileSync, mkdirSync, existsSync } from "fs";
|
|
11
|
+
import { dirname } from "path";
|
|
12
|
+
import { loadConfig, mergeConfigWithDefaults, resolveOutputPath } from "@aiready/core";
|
|
13
13
|
var program = new Command();
|
|
14
14
|
program.name("aiready-patterns").description("Detect duplicate patterns in your codebase").version("0.1.0").addHelpText("after", "\nCONFIGURATION:\n Supports config files: aiready.json, aiready.config.json, .aiready.json, .aireadyrc.json, aiready.config.js, .aireadyrc.js\n CLI options override config file settings\n\nPARAMETER TUNING:\n If you get too few results: decrease --similarity, --min-lines, or --min-shared-tokens\n If analysis is too slow: increase --min-lines, --min-shared-tokens, or decrease --max-candidates\n If you get too many false positives: increase --similarity or --min-lines\n\nEXAMPLES:\n aiready-patterns . # Basic analysis with smart defaults\n aiready-patterns . --similarity 0.3 --min-lines 3 # More sensitive detection\n aiready-patterns . --max-candidates 50 --no-approx # Slower but more thorough\n aiready-patterns . --output json > report.json # JSON export").argument("<directory>", "Directory to analyze").option("-s, --similarity <number>", "Minimum similarity score (0-1). Lower = more results, higher = fewer but more accurate. Default: 0.4").option("-l, --min-lines <number>", "Minimum lines to consider. Lower = more results, higher = faster analysis. Default: 5").option("--batch-size <number>", "Batch size for comparisons. Higher = faster but more memory. Default: 100").option("--no-approx", "Disable approximate candidate selection. Slower but more thorough on small repos").option("--min-shared-tokens <number>", "Minimum shared tokens to consider a candidate. Higher = faster, fewer results. Default: 8").option("--max-candidates <number>", "Maximum candidates per block. Higher = more thorough but slower. Default: 100").option("--no-stream-results", "Disable incremental output (default: enabled)").option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("--severity <level>", "Filter by severity: critical|high|medium|all. Default: all").option("--include-tests", "Include test files in analysis (excluded by default)").option("--max-results <number>", "Maximum number of results to show in console output. Default: 10").option(
|
|
15
15
|
"-o, --output <format>",
|
|
@@ -71,18 +71,31 @@ program.name("aiready-patterns").description("Detect duplicate patterns in your
|
|
|
71
71
|
results,
|
|
72
72
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
73
73
|
};
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
74
|
+
const outputPath = resolveOutputPath(
|
|
75
|
+
options.outputFile,
|
|
76
|
+
`pattern-report-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.json`,
|
|
77
|
+
directory
|
|
78
|
+
);
|
|
79
|
+
const dir = dirname(outputPath);
|
|
80
|
+
if (!existsSync(dir)) {
|
|
81
|
+
mkdirSync(dir, { recursive: true });
|
|
80
82
|
}
|
|
83
|
+
writeFileSync(outputPath, JSON.stringify(jsonOutput, null, 2));
|
|
84
|
+
console.log(chalk.green(`
|
|
85
|
+
\u2713 JSON report saved to ${outputPath}`));
|
|
81
86
|
return;
|
|
82
87
|
}
|
|
83
88
|
if (options.output === "html") {
|
|
84
89
|
const html = generateHTMLReport(summary, results);
|
|
85
|
-
const outputPath =
|
|
90
|
+
const outputPath = resolveOutputPath(
|
|
91
|
+
options.outputFile,
|
|
92
|
+
`pattern-report-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.html`,
|
|
93
|
+
directory
|
|
94
|
+
);
|
|
95
|
+
const dir = dirname(outputPath);
|
|
96
|
+
if (!existsSync(dir)) {
|
|
97
|
+
mkdirSync(dir, { recursive: true });
|
|
98
|
+
}
|
|
86
99
|
writeFileSync(outputPath, html);
|
|
87
100
|
console.log(chalk.green(`
|
|
88
101
|
\u2713 HTML report saved to ${outputPath}`));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiready/pattern-detect",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
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",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"commander": "^14.0.0",
|
|
47
47
|
"chalk": "^5.3.0",
|
|
48
|
-
"@aiready/core": "0.5.
|
|
48
|
+
"@aiready/core": "0.5.3"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"tsup": "^8.3.5",
|