@aiready/pattern-detect 0.17.8 → 0.17.12

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 (190) hide show
  1. package/dist/analyzer-entry/index.d.mts +1 -1
  2. package/dist/analyzer-entry/index.d.ts +1 -1
  3. package/dist/analyzer-entry/index.js +370 -135
  4. package/dist/analyzer-entry/index.mjs +4 -3
  5. package/dist/chunk-2P7BQHGR.mjs +306 -0
  6. package/dist/{chunk-VGMM3L3O.mjs → chunk-3EORD7DC.mjs} +1 -1
  7. package/dist/{chunk-GREN7X5H.mjs → chunk-4PVPQMRT.mjs} +2 -2
  8. package/dist/{chunk-RS73WLNI.mjs → chunk-6VDL7TAS.mjs} +5 -113
  9. package/dist/chunk-AQIP4JGM.mjs +283 -0
  10. package/dist/{chunk-JBUZ6YHE.mjs → chunk-B4NLWKPZ.mjs} +85 -9
  11. package/dist/chunk-IPBGVPUX.mjs +143 -0
  12. package/dist/chunk-LUUJOUK5.mjs +283 -0
  13. package/dist/chunk-P3BOCGVV.mjs +498 -0
  14. package/dist/{scoring-entry.js → chunk-PHJE6A3J.mjs} +20 -37
  15. package/dist/chunk-PQXOORR4.mjs +234 -0
  16. package/dist/{chunk-GLKAGFKX.mjs → chunk-RDR75DVI.mjs} +85 -9
  17. package/dist/chunk-SXVLRPMF.mjs +143 -0
  18. package/dist/{chunk-DNZS4ESD.mjs → chunk-SY7RX5YQ.mjs} +85 -9
  19. package/dist/{context-rules-entry.js → chunk-TIBF7KST.mjs} +81 -78
  20. package/dist/chunk-WYYSQX5M.mjs +467 -0
  21. package/dist/{chunk-I6ETJC7L.mjs → chunk-X553BOMI.mjs} +56 -26
  22. package/dist/{chunk-K7BO57OO.mjs → chunk-Y6OB7K34.mjs} +80 -4
  23. package/dist/chunk-YLVV6YZ5.mjs +143 -0
  24. package/dist/chunk-ZUWPFVJV.mjs +115 -0
  25. package/dist/chunk-ZZMONVPE.mjs +467 -0
  26. package/dist/cli.js +402 -167
  27. package/dist/cli.mjs +4 -3
  28. package/dist/context-rules-entry/index.d.mts +35 -1
  29. package/dist/context-rules-entry/index.d.ts +35 -1
  30. package/dist/context-rules-entry/index.js +194 -48
  31. package/dist/context-rules-entry/index.mjs +1 -1
  32. package/dist/detector-entry/index.js +192 -46
  33. package/dist/detector-entry/index.mjs +2 -2
  34. package/dist/{analyzer-entry-BVz-HnZd.d.mts → index-B-pnXpgn.d.mts} +10 -1
  35. package/dist/{index-BwuoiCNm.d.ts → index-CWgYOKaK.d.ts} +35 -16
  36. package/dist/{index-BVz-HnZd.d.mts → index-Dl4BrGIT.d.mts} +35 -16
  37. package/dist/{analyzer-entry-BwuoiCNm.d.ts → index-DqS2e0kK.d.ts} +10 -1
  38. package/dist/index.d.mts +5 -6
  39. package/dist/index.d.ts +5 -6
  40. package/dist/index.js +467 -214
  41. package/dist/index.mjs +37 -22
  42. package/dist/scoring-entry/index.js +7 -3
  43. package/dist/scoring-entry/index.mjs +1 -1
  44. package/package.json +2 -2
  45. package/dist/analyzer-entry.d.mts +0 -100
  46. package/dist/analyzer-entry.d.ts +0 -100
  47. package/dist/analyzer-entry.js +0 -693
  48. package/dist/analyzer-entry.mjs +0 -12
  49. package/dist/chunk-262N2JB7.mjs +0 -497
  50. package/dist/chunk-2R7HOR5H.mjs +0 -777
  51. package/dist/chunk-3D7RVGHM.mjs +0 -64
  52. package/dist/chunk-3LS3E6MO.mjs +0 -508
  53. package/dist/chunk-3VRQYFW3.mjs +0 -782
  54. package/dist/chunk-3WK24ZOX.mjs +0 -860
  55. package/dist/chunk-3YYN6ZXN.mjs +0 -1038
  56. package/dist/chunk-4BPRGZRG.mjs +0 -1041
  57. package/dist/chunk-4UHDGB7U.mjs +0 -920
  58. package/dist/chunk-5LYDB7DY.mjs +0 -771
  59. package/dist/chunk-65G3HXLQ.mjs +0 -497
  60. package/dist/chunk-65UQ5J2J.mjs +0 -64
  61. package/dist/chunk-6JTVOBJX.mjs +0 -64
  62. package/dist/chunk-6OEHUI5J.mjs +0 -1045
  63. package/dist/chunk-6YUGU4P4.mjs +0 -914
  64. package/dist/chunk-7EJGNGXM.mjs +0 -771
  65. package/dist/chunk-7O2DUBSN.mjs +0 -1058
  66. package/dist/chunk-7S4AUL5S.mjs +0 -911
  67. package/dist/chunk-A76JUWER.mjs +0 -786
  68. package/dist/chunk-AJZUNNFH.mjs +0 -817
  69. package/dist/chunk-AXHGYYYZ.mjs +0 -404
  70. package/dist/chunk-BKRPSTT2.mjs +0 -64
  71. package/dist/chunk-BUBQ3W6W.mjs +0 -980
  72. package/dist/chunk-CCHM2VLK.mjs +0 -1051
  73. package/dist/chunk-CHFK6EBT.mjs +0 -419
  74. package/dist/chunk-CMT3MWWO.mjs +0 -948
  75. package/dist/chunk-CMWW24HW.mjs +0 -259
  76. package/dist/chunk-CTDBJP25.mjs +0 -1043
  77. package/dist/chunk-DGAKXYIP.mjs +0 -1041
  78. package/dist/chunk-DQSLTL7J.mjs +0 -788
  79. package/dist/chunk-DR5W7S3Z.mjs +0 -968
  80. package/dist/chunk-EFUKPMBE.mjs +0 -950
  81. package/dist/chunk-EVBFDILL.mjs +0 -927
  82. package/dist/chunk-EXORBAXR.mjs +0 -887
  83. package/dist/chunk-EZT3NZGB.mjs +0 -1057
  84. package/dist/chunk-FWUKMJEQ.mjs +0 -1133
  85. package/dist/chunk-GSJFORRO.mjs +0 -504
  86. package/dist/chunk-H4ADJYOG.mjs +0 -925
  87. package/dist/chunk-H5FB2USZ.mjs +0 -762
  88. package/dist/chunk-H73HEG7M.mjs +0 -670
  89. package/dist/chunk-HOS5Z2NC.mjs +0 -669
  90. package/dist/chunk-HXHQOQB5.mjs +0 -508
  91. package/dist/chunk-INEOYHUM.mjs +0 -911
  92. package/dist/chunk-INJ4SBTV.mjs +0 -754
  93. package/dist/chunk-J5CW6NYY.mjs +0 -64
  94. package/dist/chunk-JAFZCZAP.mjs +0 -776
  95. package/dist/chunk-JKVKOXYR.mjs +0 -407
  96. package/dist/chunk-JTHW7EYW.mjs +0 -1041
  97. package/dist/chunk-JWR3AHKO.mjs +0 -788
  98. package/dist/chunk-KC2CQMG2.mjs +0 -858
  99. package/dist/chunk-KDWGWBP5.mjs +0 -832
  100. package/dist/chunk-KPEK5REL.mjs +0 -919
  101. package/dist/chunk-KT6O2IAE.mjs +0 -861
  102. package/dist/chunk-KWMNN3TG.mjs +0 -391
  103. package/dist/chunk-LUA5FXSZ.mjs +0 -771
  104. package/dist/chunk-LYKRYBSM.mjs +0 -64
  105. package/dist/chunk-M4PQMW34.mjs +0 -480
  106. package/dist/chunk-MH6LBXZF.mjs +0 -816
  107. package/dist/chunk-MHU3CL4R.mjs +0 -64
  108. package/dist/chunk-MJWBS6SM.mjs +0 -1058
  109. package/dist/chunk-OFGMDX66.mjs +0 -402
  110. package/dist/chunk-P7B6Z4I2.mjs +0 -1043
  111. package/dist/chunk-PBCXSG7E.mjs +0 -658
  112. package/dist/chunk-PEEHSFDR.mjs +0 -1058
  113. package/dist/chunk-PSVG2NLH.mjs +0 -966
  114. package/dist/chunk-PWNQ6JZW.mjs +0 -508
  115. package/dist/chunk-QE4E3F7C.mjs +0 -410
  116. package/dist/chunk-QEP76HGK.mjs +0 -1039
  117. package/dist/chunk-QX2BQJEO.mjs +0 -1058
  118. package/dist/chunk-R2S73CVG.mjs +0 -503
  119. package/dist/chunk-RMGDSNLE.mjs +0 -770
  120. package/dist/chunk-S2KQFII2.mjs +0 -491
  121. package/dist/chunk-SLDK5PQK.mjs +0 -1129
  122. package/dist/chunk-SNSDVGWW.mjs +0 -783
  123. package/dist/chunk-SUUZMLPS.mjs +0 -391
  124. package/dist/chunk-SVCSIZ2A.mjs +0 -259
  125. package/dist/chunk-T2C6WS73.mjs +0 -670
  126. package/dist/chunk-TCG2G32F.mjs +0 -911
  127. package/dist/chunk-TGBZP7SB.mjs +0 -773
  128. package/dist/chunk-THF4RW63.mjs +0 -254
  129. package/dist/chunk-TJKDLVLN.mjs +0 -503
  130. package/dist/chunk-TXWPOVYU.mjs +0 -402
  131. package/dist/chunk-UB3CGOQ7.mjs +0 -64
  132. package/dist/chunk-UKIKN27B.mjs +0 -950
  133. package/dist/chunk-V5DP4FP6.mjs +0 -876
  134. package/dist/chunk-VRMXVYDZ.mjs +0 -419
  135. package/dist/chunk-WACZ5LFH.mjs +0 -1055
  136. package/dist/chunk-WC7CBAA7.mjs +0 -1058
  137. package/dist/chunk-WKBCNITM.mjs +0 -1072
  138. package/dist/chunk-WMOGJFME.mjs +0 -391
  139. package/dist/chunk-X4GR2N2M.mjs +0 -947
  140. package/dist/chunk-XCWY2DQY.mjs +0 -788
  141. package/dist/chunk-XJD35DS6.mjs +0 -1058
  142. package/dist/chunk-XNPID6FU.mjs +0 -391
  143. package/dist/chunk-XUUVS54V.mjs +0 -776
  144. package/dist/chunk-YCGV65F5.mjs +0 -508
  145. package/dist/chunk-YJYDBFT3.mjs +0 -780
  146. package/dist/chunk-YP3HEDQW.mjs +0 -859
  147. package/dist/chunk-YSDOUNJJ.mjs +0 -1142
  148. package/dist/chunk-Z6GBFFOV.mjs +0 -1040
  149. package/dist/cli.d.ts.map +0 -1
  150. package/dist/cli.js.map +0 -1
  151. package/dist/context-rules-entry-y2uJSngh.d.mts +0 -60
  152. package/dist/context-rules-entry-y2uJSngh.d.ts +0 -60
  153. package/dist/context-rules-entry.d.mts +0 -55
  154. package/dist/context-rules-entry.d.ts +0 -55
  155. package/dist/context-rules-entry.mjs +0 -12
  156. package/dist/context-rules.d.ts +0 -41
  157. package/dist/context-rules.d.ts.map +0 -1
  158. package/dist/context-rules.js +0 -225
  159. package/dist/context-rules.js.map +0 -1
  160. package/dist/detector-entry.d.mts +0 -14
  161. package/dist/detector-entry.d.ts +0 -14
  162. package/dist/detector-entry.js +0 -301
  163. package/dist/detector-entry.mjs +0 -7
  164. package/dist/detector.d.ts +0 -40
  165. package/dist/detector.d.ts.map +0 -1
  166. package/dist/detector.js +0 -385
  167. package/dist/detector.js.map +0 -1
  168. package/dist/extractors/python-extractor.d.ts +0 -19
  169. package/dist/extractors/python-extractor.d.ts.map +0 -1
  170. package/dist/extractors/python-extractor.js +0 -164
  171. package/dist/extractors/python-extractor.js.map +0 -1
  172. package/dist/grouping.d.ts +0 -54
  173. package/dist/grouping.d.ts.map +0 -1
  174. package/dist/grouping.js +0 -347
  175. package/dist/grouping.js.map +0 -1
  176. package/dist/index-y2uJSngh.d.mts +0 -60
  177. package/dist/index-y2uJSngh.d.ts +0 -60
  178. package/dist/index.d.ts.map +0 -1
  179. package/dist/index.js.map +0 -1
  180. package/dist/python-extractor-BGKGX6BK.mjs +0 -131
  181. package/dist/python-extractor-ELAKYK2W.mjs +0 -140
  182. package/dist/scoring-entry.d.mts +0 -23
  183. package/dist/scoring-entry.d.ts +0 -23
  184. package/dist/scoring-entry.mjs +0 -6
  185. package/dist/scoring.d.ts +0 -12
  186. package/dist/scoring.d.ts.map +0 -1
  187. package/dist/scoring.js +0 -116
  188. package/dist/scoring.js.map +0 -1
  189. package/dist/types-C4lmb2Yh.d.mts +0 -36
  190. package/dist/types-C4lmb2Yh.d.ts +0 -36
package/dist/cli.js CHANGED
@@ -27,14 +27,17 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  var import_commander = require("commander");
28
28
 
29
29
  // src/analyzer.ts
30
- var import_core4 = require("@aiready/core");
30
+ var import_core11 = require("@aiready/core");
31
31
 
32
32
  // src/detector.ts
33
- var import_core2 = require("@aiready/core");
33
+ var import_core6 = require("@aiready/core");
34
34
 
35
35
  // src/context-rules.ts
36
+ var import_core5 = require("@aiready/core");
37
+
38
+ // src/rules/categories/test-rules.ts
36
39
  var import_core = require("@aiready/core");
37
- var CONTEXT_RULES = [
40
+ var TEST_RULES = [
38
41
  // Test Fixtures - Intentional duplication for test isolation
39
42
  {
40
43
  name: "test-fixtures",
@@ -47,6 +50,35 @@ var CONTEXT_RULES = [
47
50
  reason: "Test fixture duplication is intentional for test isolation",
48
51
  suggestion: "Consider if shared test setup would improve maintainability without coupling tests"
49
52
  },
53
+ // E2E/Integration Test Page Objects - Test independence
54
+ {
55
+ name: "e2e-page-objects",
56
+ detect: (file, code) => {
57
+ const isE2ETest = file.includes("e2e/") || file.includes("/e2e/") || file.includes(".e2e.") || file.includes("/playwright/") || file.includes("playwright/") || file.includes("/cypress/") || file.includes("cypress/") || file.includes("/integration/") || file.includes("integration/");
58
+ const hasPageObjectPatterns = code.includes("page.") || code.includes("await page") || code.includes("locator") || code.includes("getBy") || code.includes("selector") || code.includes("click(") || code.includes("fill(");
59
+ return isE2ETest && hasPageObjectPatterns;
60
+ },
61
+ severity: import_core.Severity.Info,
62
+ reason: "E2E test duplication ensures test independence and reduces coupling",
63
+ suggestion: "Consider page object pattern only if duplication causes maintenance issues"
64
+ },
65
+ // Mock Data - Test data intentionally duplicated
66
+ {
67
+ name: "mock-data",
68
+ detect: (file, code) => {
69
+ const isMockFile = file.includes("/mocks/") || file.includes("/__mocks__/") || file.includes("/fixtures/") || file.includes(".mock.") || file.includes(".fixture.");
70
+ const hasMockData = code.includes("mock") || code.includes("Mock") || code.includes("fixture") || code.includes("stub") || code.includes("export const");
71
+ return isMockFile && hasMockData;
72
+ },
73
+ severity: import_core.Severity.Info,
74
+ reason: "Mock data duplication is expected for comprehensive test coverage",
75
+ suggestion: "Consider shared factories only for complex mock generation"
76
+ }
77
+ ];
78
+
79
+ // src/rules/categories/web-rules.ts
80
+ var import_core2 = require("@aiready/core");
81
+ var WEB_RULES = [
50
82
  // Email/Document Templates - Often intentionally similar for consistency
51
83
  {
52
84
  name: "templates",
@@ -55,66 +87,59 @@ var CONTEXT_RULES = [
55
87
  const hasTemplateContent = (code.includes("return") || code.includes("export")) && (code.includes("html") || code.includes("subject") || code.includes("body"));
56
88
  return isTemplate && hasTemplateContent;
57
89
  },
58
- severity: import_core.Severity.Minor,
90
+ severity: import_core2.Severity.Info,
59
91
  reason: "Template duplication may be intentional for maintainability and branding consistency",
60
92
  suggestion: "Extract shared structure only if templates become hard to maintain"
61
93
  },
62
- // E2E/Integration Test Page Objects - Test independence
94
+ // Common UI Event Handlers - Very specific patterns only
63
95
  {
64
- name: "e2e-page-objects",
96
+ name: "common-ui-handlers",
65
97
  detect: (file, code) => {
66
- const isE2ETest = file.includes("e2e/") || file.includes("/e2e/") || file.includes(".e2e.") || file.includes("/playwright/") || file.includes("playwright/") || file.includes("/cypress/") || file.includes("cypress/") || file.includes("/integration/") || file.includes("integration/");
67
- const hasPageObjectPatterns = code.includes("page.") || code.includes("await page") || code.includes("locator") || code.includes("getBy") || code.includes("selector") || code.includes("click(") || code.includes("fill(");
68
- return isE2ETest && hasPageObjectPatterns;
98
+ const isUIFile = file.includes("/components/") || file.includes(".tsx") || file.includes(".jsx") || file.includes("/hooks/");
99
+ const hasCommonHandler = code.includes("handleClickOutside") && code.includes("dropdownRef.current") && code.includes("!dropdownRef.current.contains") || code.includes("handleEscape") && code.includes("event.key") && code.includes("=== 'Escape'") || code.includes("handleClickInside") && code.includes("event.stopPropagation");
100
+ return isUIFile && hasCommonHandler;
69
101
  },
70
- severity: import_core.Severity.Minor,
71
- reason: "E2E test duplication ensures test independence and reduces coupling",
72
- suggestion: "Consider page object pattern only if duplication causes maintenance issues"
102
+ severity: import_core2.Severity.Info,
103
+ reason: "Common UI event handlers are boilerplate patterns that repeat across components",
104
+ suggestion: "Consider extracting to shared hooks (useClickOutside, useEscapeKey) only if causing maintenance issues"
73
105
  },
106
+ // Next.js Route Handler Patterns - Boilerplate API route patterns
107
+ {
108
+ name: "nextjs-route-handlers",
109
+ detect: (file, code) => {
110
+ const isRouteFile = file.includes("/api/") && (file.endsWith("/route.ts") || file.endsWith("/route.js"));
111
+ const hasRoutePattern = code.includes("export async function POST") || code.includes("export async function GET") || code.includes("export async function PUT") || code.includes("export async function DELETE") || code.includes("NextResponse.json") || code.includes("NextRequest");
112
+ return isRouteFile && hasRoutePattern;
113
+ },
114
+ severity: import_core2.Severity.Info,
115
+ reason: "Next.js route handlers follow standard patterns and are intentionally similar across endpoints",
116
+ suggestion: "Route handler duplication is acceptable for API endpoint boilerplate"
117
+ }
118
+ ];
119
+
120
+ // src/rules/categories/infra-rules.ts
121
+ var import_core3 = require("@aiready/core");
122
+ var INFRA_RULES = [
74
123
  // Configuration Files - Often necessarily similar by design
75
124
  {
76
125
  name: "config-files",
77
126
  detect: (file) => {
78
127
  return file.endsWith(".config.ts") || file.endsWith(".config.js") || file.includes("jest.config") || file.includes("vite.config") || file.includes("webpack.config") || file.includes("rollup.config") || file.includes("tsconfig");
79
128
  },
80
- severity: import_core.Severity.Minor,
129
+ severity: import_core3.Severity.Info,
81
130
  reason: "Configuration files often have similar structure by design",
82
131
  suggestion: "Consider shared config base only if configurations become hard to maintain"
83
132
  },
84
- // Type Definitions - Duplication for type safety and module independence
85
- {
86
- name: "type-definitions",
87
- detect: (file, code) => {
88
- const isTypeFile = file.endsWith(".d.ts") || file.includes("/types/");
89
- const hasTypeDefinitions = code.includes("interface ") || code.includes("type ") || code.includes("enum ");
90
- return isTypeFile && hasTypeDefinitions;
91
- },
92
- severity: import_core.Severity.Info,
93
- reason: "Type duplication may be intentional for module independence and type safety",
94
- suggestion: "Extract to shared types package only if causing maintenance burden"
95
- },
96
133
  // Migration Scripts - One-off scripts that are similar by nature
97
134
  {
98
135
  name: "migration-scripts",
99
136
  detect: (file) => {
100
137
  return file.includes("/migrations/") || file.includes("/migrate/") || file.includes(".migration.");
101
138
  },
102
- severity: import_core.Severity.Info,
139
+ severity: import_core3.Severity.Info,
103
140
  reason: "Migration scripts are typically one-off and intentionally similar",
104
141
  suggestion: "Duplication is acceptable for migration scripts"
105
142
  },
106
- // Mock Data - Test data intentionally duplicated
107
- {
108
- name: "mock-data",
109
- detect: (file, code) => {
110
- const isMockFile = file.includes("/mocks/") || file.includes("/__mocks__/") || file.includes("/fixtures/") || file.includes(".mock.") || file.includes(".fixture.");
111
- const hasMockData = code.includes("mock") || code.includes("Mock") || code.includes("fixture") || code.includes("stub") || code.includes("export const");
112
- return isMockFile && hasMockData;
113
- },
114
- severity: import_core.Severity.Info,
115
- reason: "Mock data duplication is expected for comprehensive test coverage",
116
- suggestion: "Consider shared factories only for complex mock generation"
117
- },
118
143
  // Tool Implementations - Structural Boilerplate
119
144
  {
120
145
  name: "tool-implementations",
@@ -123,11 +148,132 @@ var CONTEXT_RULES = [
123
148
  const hasToolStructure = code.includes("execute") && (code.includes("try") || code.includes("catch"));
124
149
  return isToolFile && hasToolStructure;
125
150
  },
126
- severity: import_core.Severity.Info,
151
+ severity: import_core3.Severity.Info,
127
152
  reason: "Tool implementations share structural boilerplate but have distinct business logic",
128
153
  suggestion: "Tool duplication is acceptable for boilerplate interface wrappers"
154
+ },
155
+ // CLI Command Definitions - Commander.js boilerplate patterns
156
+ {
157
+ name: "cli-command-definitions",
158
+ detect: (file, code) => {
159
+ const isCliFile = file.includes("/commands/") || file.includes("/cli/") || file.endsWith(".command.ts");
160
+ const hasCommandPattern = (code.includes(".command(") || code.includes("defineCommand")) && (code.includes(".description(") || code.includes(".option(")) && (code.includes(".action(") || code.includes("async"));
161
+ return isCliFile && hasCommandPattern;
162
+ },
163
+ severity: import_core3.Severity.Info,
164
+ reason: "CLI command definitions follow standard Commander.js patterns and are intentionally similar",
165
+ suggestion: "Command boilerplate duplication is acceptable for CLI interfaces"
166
+ }
167
+ ];
168
+
169
+ // src/rules/categories/logic-rules.ts
170
+ var import_core4 = require("@aiready/core");
171
+ var LOGIC_RULES = [
172
+ // Type Definitions - Duplication for type safety and module independence
173
+ {
174
+ name: "type-definitions",
175
+ detect: (file, code) => {
176
+ const isTypeFile = file.endsWith(".d.ts") || file.includes("/types/");
177
+ const hasOnlyTypeDefinitions = (code.includes("interface ") || code.includes("type ") || code.includes("enum ")) && !code.includes("function ") && !code.includes("class ") && !code.includes("const ") && !code.includes("let ") && !code.includes("export default");
178
+ const isInterfaceOnlySnippet = code.trim().startsWith("interface ") && code.includes("{") && code.includes("}") && !code.includes("function ") && !code.includes("const ") && !code.includes("return ");
179
+ return isTypeFile && hasOnlyTypeDefinitions || isInterfaceOnlySnippet;
180
+ },
181
+ severity: import_core4.Severity.Info,
182
+ reason: "Type/interface definitions are intentionally duplicated for module independence",
183
+ suggestion: "Extract to shared types package only if causing maintenance burden"
184
+ },
185
+ // Utility Functions - Small helpers in dedicated utility files
186
+ {
187
+ name: "utility-functions",
188
+ detect: (file, code) => {
189
+ const isUtilFile = file.endsWith(".util.ts") || file.endsWith(".helper.ts") || file.endsWith(".utils.ts");
190
+ const hasUtilPattern = code.includes("function format") || code.includes("function parse") || code.includes("function sanitize") || code.includes("function normalize") || code.includes("function convert");
191
+ return isUtilFile && hasUtilPattern;
192
+ },
193
+ severity: import_core4.Severity.Info,
194
+ reason: "Utility functions in dedicated utility files may be intentionally similar",
195
+ suggestion: "Consider extracting to shared utilities only if causing significant duplication"
196
+ },
197
+ // React/Vue Hooks - Standard patterns
198
+ {
199
+ name: "shared-hooks",
200
+ detect: (file, code) => {
201
+ const isHookFile = file.includes("/hooks/") || file.endsWith(".hook.ts") || file.endsWith(".hook.tsx");
202
+ const hasHookPattern = code.includes("function use") || code.includes("export function use") || code.includes("const use") || code.includes("export const use");
203
+ return isHookFile && hasHookPattern;
204
+ },
205
+ severity: import_core4.Severity.Info,
206
+ reason: "Hooks follow standard patterns and are often intentionally similar across components",
207
+ suggestion: "Consider extracting common hook logic only if hooks become complex"
208
+ },
209
+ // Score/Rating Helper Functions - Common threshold patterns
210
+ {
211
+ name: "score-helpers",
212
+ detect: (file, code) => {
213
+ const isHelperFile = file.includes("/utils/") || file.includes("/helpers/") || file.endsWith(".util.ts");
214
+ const hasScorePattern = (code.includes("if (score >=") || code.includes("if (score >")) && code.includes("return") && code.includes("'") && code.split("if (score").length >= 3;
215
+ return isHelperFile && hasScorePattern;
216
+ },
217
+ severity: import_core4.Severity.Info,
218
+ reason: "Score/rating helper functions use common threshold patterns that are intentionally similar",
219
+ suggestion: "Score formatting duplication is acceptable for consistent UI display"
220
+ },
221
+ // D3/Canvas Event Handlers - Standard visualization patterns
222
+ {
223
+ name: "visualization-handlers",
224
+ detect: (file, code) => {
225
+ const isVizFile = file.includes("/visualizer/") || file.includes("/charts/") || file.includes("GraphCanvas") || file.includes("ForceDirected");
226
+ const hasVizPattern = (code.includes("dragstarted") || code.includes("dragged") || code.includes("dragended")) && (code.includes("simulation") || code.includes("d3.") || code.includes("alphaTarget"));
227
+ return isVizFile && hasVizPattern;
228
+ },
229
+ severity: import_core4.Severity.Info,
230
+ reason: "D3/visualization event handlers follow standard patterns and are intentionally similar",
231
+ suggestion: "Visualization boilerplate duplication is acceptable for interactive charts"
232
+ },
233
+ // Icon/Switch Statement Helpers - Common enum-to-value patterns
234
+ {
235
+ name: "switch-helpers",
236
+ detect: (file, code) => {
237
+ const hasSwitchPattern = code.includes("switch (") && code.includes("case '") && code.includes("return") && code.split("case ").length >= 4;
238
+ const hasIconPattern = code.includes("getIcon") || code.includes("getColor") || code.includes("getLabel") || code.includes("getRating");
239
+ return hasSwitchPattern && hasIconPattern;
240
+ },
241
+ severity: import_core4.Severity.Info,
242
+ reason: "Switch statement helpers for enum-to-value mapping are inherently similar",
243
+ suggestion: "Switch duplication is acceptable for mapping enums to display values"
244
+ },
245
+ // Common API/Utility Functions - Legitimate duplication across modules
246
+ {
247
+ name: "common-api-functions",
248
+ detect: (file, code) => {
249
+ const isApiFile = file.includes("/api/") || file.includes("/lib/") || file.includes("/utils/") || file.endsWith(".ts");
250
+ const hasCommonApiPattern = code.includes("getStripe") && code.includes("process.env.STRIPE_SECRET_KEY") || code.includes("getUserByEmail") && code.includes("queryItems") || code.includes("updateUser") && code.includes("buildUpdateExpression") || code.includes("listUserRepositories") && code.includes("queryItems") || code.includes("listTeamRepositories") && code.includes("queryItems") || code.includes("getRemediation") && code.includes("queryItems") || code.includes("formatBreakdownKey") && code.includes(".replace(/([A-Z])/g") || code.includes("queryItems") && code.includes("KeyConditionExpression") || code.includes("putItem") && code.includes("createdAt") || code.includes("updateItem") && code.includes("buildUpdateExpression");
251
+ return isApiFile && hasCommonApiPattern;
252
+ },
253
+ severity: import_core4.Severity.Info,
254
+ reason: "Common API/utility functions are legitimately duplicated across modules for clarity and independence",
255
+ suggestion: "Consider extracting to shared utilities only if causing significant duplication"
256
+ },
257
+ // Validation Functions - Inherently similar patterns
258
+ {
259
+ name: "validation-functions",
260
+ detect: (file, code) => {
261
+ const hasValidationPattern = code.includes("isValid") || code.includes("validate") || code.includes("checkValid") || code.includes("isEmail") || code.includes("isPhone") || code.includes("isUrl") || code.includes("isNumeric") || code.includes("isAlpha") || code.includes("isAlphanumeric") || code.includes("isEmpty") || code.includes("isNotEmpty") || code.includes("isRequired") || code.includes("isOptional");
262
+ return hasValidationPattern;
263
+ },
264
+ severity: import_core4.Severity.Info,
265
+ reason: "Validation functions are inherently similar and often intentionally duplicated for domain clarity",
266
+ suggestion: "Consider extracting to shared validators only if validation logic becomes complex"
129
267
  }
130
268
  ];
269
+
270
+ // src/context-rules.ts
271
+ var CONTEXT_RULES = [
272
+ ...TEST_RULES,
273
+ ...WEB_RULES,
274
+ ...INFRA_RULES,
275
+ ...LOGIC_RULES
276
+ ];
131
277
  function calculateSeverity(file1, file2, code, similarity, linesOfCode) {
132
278
  for (const rule of CONTEXT_RULES) {
133
279
  if (rule.detect(file1, code) || rule.detect(file2, code)) {
@@ -141,31 +287,31 @@ function calculateSeverity(file1, file2, code, similarity, linesOfCode) {
141
287
  }
142
288
  if (similarity >= 0.95 && linesOfCode >= 30) {
143
289
  return {
144
- severity: import_core.Severity.Critical,
290
+ severity: import_core5.Severity.Critical,
145
291
  reason: "Large nearly-identical code blocks waste tokens and create maintenance burden",
146
292
  suggestion: "Extract to shared utility module immediately"
147
293
  };
148
294
  } else if (similarity >= 0.95 && linesOfCode >= 15) {
149
295
  return {
150
- severity: import_core.Severity.Major,
296
+ severity: import_core5.Severity.Major,
151
297
  reason: "Nearly identical code should be consolidated",
152
298
  suggestion: "Move to shared utility file"
153
299
  };
154
300
  } else if (similarity >= 0.85) {
155
301
  return {
156
- severity: import_core.Severity.Major,
302
+ severity: import_core5.Severity.Major,
157
303
  reason: "High similarity indicates significant duplication",
158
304
  suggestion: "Extract common logic to shared function"
159
305
  };
160
306
  } else if (similarity >= 0.7) {
161
307
  return {
162
- severity: import_core.Severity.Minor,
308
+ severity: import_core5.Severity.Minor,
163
309
  reason: "Moderate similarity detected",
164
310
  suggestion: "Consider extracting shared patterns if code evolves together"
165
311
  };
166
312
  } else {
167
313
  return {
168
- severity: import_core.Severity.Minor,
314
+ severity: import_core5.Severity.Minor,
169
315
  reason: "Minor similarity detected",
170
316
  suggestion: "Monitor but refactoring may not be worthwhile"
171
317
  };
@@ -186,13 +332,13 @@ function normalizeCode(code, isPython = false) {
186
332
 
187
333
  // src/detector.ts
188
334
  function extractBlocks(file, content) {
189
- return (0, import_core2.extractCodeBlocks)(file, content);
335
+ return (0, import_core6.extractCodeBlocks)(file, content);
190
336
  }
191
337
  function calculateSimilarity(a, b) {
192
- return (0, import_core2.calculateStringSimilarity)(a, b);
338
+ return (0, import_core6.calculateStringSimilarity)(a, b);
193
339
  }
194
340
  function calculateConfidence(similarity, tokens, lines) {
195
- return (0, import_core2.calculateHeuristicConfidence)(similarity, tokens, lines);
341
+ return (0, import_core6.calculateHeuristicConfidence)(similarity, tokens, lines);
196
342
  }
197
343
  async function detectDuplicatePatterns(fileContents, options) {
198
344
  const {
@@ -302,7 +448,7 @@ async function detectDuplicatePatterns(fileContents, options) {
302
448
  }
303
449
 
304
450
  // src/grouping.ts
305
- var import_core3 = require("@aiready/core");
451
+ var import_core7 = require("@aiready/core");
306
452
  var import_path = __toESM(require("path"));
307
453
  function groupDuplicatesByFilePair(duplicates) {
308
454
  const groups = /* @__PURE__ */ new Map();
@@ -330,7 +476,7 @@ function groupDuplicatesByFilePair(duplicates) {
330
476
  file2: { start: dup.line2, end: dup.endLine2 }
331
477
  });
332
478
  const currentSev = dup.severity;
333
- if ((0, import_core3.getSeverityLevel)(currentSev) > (0, import_core3.getSeverityLevel)(group.severity)) {
479
+ if ((0, import_core7.getSeverityLevel)(currentSev) > (0, import_core7.getSeverityLevel)(group.severity)) {
334
480
  group.severity = currentSev;
335
481
  }
336
482
  }
@@ -420,21 +566,77 @@ function filterClustersByImpact(clusters, minTokenCost = 1e3, minFiles = 3) {
420
566
  (c) => c.totalTokenCost >= minTokenCost && c.files.length >= minFiles
421
567
  );
422
568
  }
423
-
424
- // src/analyzer.ts
425
- function getRefactoringSuggestion(patternType, similarity) {
426
- const baseMessages = {
427
- "api-handler": "Extract common middleware or create a base handler class",
428
- validator: "Consolidate validation logic into shared schema validators (Zod/Yup)",
429
- utility: "Move to a shared utilities file and reuse across modules",
430
- "class-method": "Consider inheritance or composition to share behavior",
431
- component: "Extract shared logic into a custom hook or HOC",
432
- function: "Extract into a shared helper function",
433
- unknown: "Extract common logic into a reusable module"
434
- };
435
- const urgency = similarity > 0.95 ? " (CRITICAL: Nearly identical code)" : similarity > 0.9 ? " (HIGH: Very similar, refactor soon)" : "";
436
- return baseMessages[patternType] + urgency;
569
+ function isPureInterfaceDefinition(code) {
570
+ const trimmed = code.trim();
571
+ if (!trimmed.startsWith("interface ") && !trimmed.startsWith("type ") && !trimmed.startsWith("export interface ") && !trimmed.startsWith("export type ") && !trimmed.startsWith("enum ") && !trimmed.startsWith("export enum ")) {
572
+ return false;
573
+ }
574
+ if (trimmed.includes("={") || trimmed.includes("=> {") || trimmed.includes("function ") || trimmed.includes("() {") || trimmed.includes(" implements ")) {
575
+ return false;
576
+ }
577
+ if (trimmed.length > 200) return false;
578
+ return true;
579
+ }
580
+ var BRAND_INDICATORS = [
581
+ "cyberpunk",
582
+ "cyber-blue",
583
+ "cyber-purple",
584
+ "slate-900",
585
+ "slate-400",
586
+ "zinc-",
587
+ "indigo-",
588
+ "neon-",
589
+ "glassmorphism",
590
+ "backdrop-blur"
591
+ ];
592
+ function isBrandSpecificComponent(filePath) {
593
+ const lower = filePath.toLowerCase();
594
+ const brandingTerms = ["landing", "clawmore", "platform", "apps/"];
595
+ for (const term of brandingTerms) {
596
+ if (lower.includes(term)) return true;
597
+ }
598
+ return false;
437
599
  }
600
+ function areBrandSpecificVariants(file1, file2, code1, code2) {
601
+ const f1IsBrand = isBrandSpecificComponent(file1);
602
+ const f2IsBrand = isBrandSpecificComponent(file2);
603
+ if (f1IsBrand && f2IsBrand && file1 !== file2) {
604
+ const hasBrandKeyword = (code) => {
605
+ const lowerCode = code.toLowerCase();
606
+ return BRAND_INDICATORS.some((ind) => lowerCode.includes(ind));
607
+ };
608
+ const code1Brand = hasBrandKeyword(code1);
609
+ const code2Brand = hasBrandKeyword(code2);
610
+ if (code1Brand && code2Brand) {
611
+ return true;
612
+ }
613
+ }
614
+ return false;
615
+ }
616
+ function filterBrandSpecificVariants(duplicates) {
617
+ return duplicates.filter((dup) => {
618
+ if (dup.file1 === dup.file2) return true;
619
+ const isBrandVariant = areBrandSpecificVariants(
620
+ dup.file1,
621
+ dup.file2,
622
+ dup.code1,
623
+ dup.code2
624
+ );
625
+ if (isBrandVariant) {
626
+ dup.severity = import_core7.Severity.Info;
627
+ dup.suggestion = "Brand-specific themed component variant (intentional)";
628
+ }
629
+ const isInterfaceDef = isPureInterfaceDefinition(dup.code1) && isPureInterfaceDefinition(dup.code2);
630
+ if (isInterfaceDef) {
631
+ dup.severity = import_core7.Severity.Info;
632
+ dup.suggestion = "Pure interface/type definition - intentional for module independence";
633
+ }
634
+ return true;
635
+ });
636
+ }
637
+
638
+ // src/config.ts
639
+ var import_core8 = require("@aiready/core");
438
640
  async function getSmartDefaults(directory, userOptions) {
439
641
  if (userOptions.useSmartDefaults === false) {
440
642
  return {
@@ -455,7 +657,7 @@ async function getSmartDefaults(directory, userOptions) {
455
657
  include: userOptions.include || ["**/*.{ts,tsx,js,jsx,py,java}"],
456
658
  exclude: userOptions.exclude
457
659
  };
458
- const files = await (0, import_core4.scanFiles)(scanOptions);
660
+ const files = await (0, import_core8.scanFiles)(scanOptions);
459
661
  const fileCount = files.length;
460
662
  const estimatedBlocks = fileCount * 5;
461
663
  const minLines = Math.max(
@@ -513,6 +715,98 @@ function logConfiguration(config, estimatedBlocks) {
513
715
  }
514
716
  console.log("");
515
717
  }
718
+
719
+ // src/summary.ts
720
+ var import_core9 = require("@aiready/core");
721
+ function getRefactoringSuggestion(patternType, similarity) {
722
+ const baseMessages = {
723
+ "api-handler": "Extract common middleware or create a base handler class",
724
+ validator: "Consolidate validation logic into shared schema validators (Zod/Yup)",
725
+ utility: "Move to a shared utilities file and reuse across modules",
726
+ "class-method": "Consider inheritance or composition to share behavior",
727
+ component: "Extract shared logic into a custom hook or HOC",
728
+ function: "Extract into a shared helper function",
729
+ unknown: "Extract common logic into a reusable module"
730
+ };
731
+ const urgency = similarity > 0.95 ? " (CRITICAL: Nearly identical code)" : similarity > 0.9 ? " (HIGH: Very similar, refactor soon)" : "";
732
+ return baseMessages[patternType] + urgency;
733
+ }
734
+ function generateSummary(results) {
735
+ const allIssues = results.flatMap((r) => r.issues || []);
736
+ const totalTokenCost = results.reduce(
737
+ (sum, r) => sum + (r.metrics?.tokenCost || 0),
738
+ 0
739
+ );
740
+ const patternsByType = {
741
+ "api-handler": 0,
742
+ validator: 0,
743
+ utility: 0,
744
+ "class-method": 0,
745
+ component: 0,
746
+ function: 0,
747
+ unknown: 0
748
+ };
749
+ allIssues.forEach((issue) => {
750
+ const match = issue.message.match(/^(\S+(?:-\S+)*) pattern/);
751
+ if (match) {
752
+ const type = match[1] || "unknown";
753
+ patternsByType[type] = (patternsByType[type] || 0) + 1;
754
+ }
755
+ });
756
+ const topDuplicates = allIssues.slice(0, 10).map((issue) => {
757
+ const similarityMatch = issue.message.match(/(\d+)% similar/);
758
+ const tokenMatch = issue.message.match(/\((\d+) tokens/);
759
+ const typeMatch = issue.message.match(/^(\S+(?:-\S+)*) pattern/);
760
+ const fileMatch = issue.message.match(/similar to (.+?) \(/);
761
+ return {
762
+ files: [
763
+ {
764
+ path: issue.location.file,
765
+ startLine: issue.location.line,
766
+ endLine: 0
767
+ },
768
+ {
769
+ path: fileMatch?.[1] || "unknown",
770
+ startLine: 0,
771
+ endLine: 0
772
+ }
773
+ ],
774
+ similarity: similarityMatch ? parseInt(similarityMatch[1]) / 100 : 0,
775
+ patternType: typeMatch?.[1] || "unknown",
776
+ tokenCost: tokenMatch ? parseInt(tokenMatch[1]) : 0
777
+ };
778
+ });
779
+ return {
780
+ totalPatterns: allIssues.length,
781
+ totalTokenCost,
782
+ patternsByType,
783
+ topDuplicates
784
+ };
785
+ }
786
+ function filterBySeverity2(issues, severity) {
787
+ if (severity === "all") return issues;
788
+ const severityMap = {
789
+ critical: [import_core9.Severity.Critical],
790
+ high: [import_core9.Severity.Critical, import_core9.Severity.Major],
791
+ medium: [import_core9.Severity.Critical, import_core9.Severity.Major, import_core9.Severity.Minor]
792
+ };
793
+ const allowed = severityMap[severity] || [
794
+ import_core9.Severity.Critical,
795
+ import_core9.Severity.Major,
796
+ import_core9.Severity.Minor
797
+ ];
798
+ return issues.filter((issue) => allowed.includes(issue.severity));
799
+ }
800
+ function calculateSeverity2(similarity) {
801
+ if (similarity > 0.95) return import_core9.Severity.Critical;
802
+ if (similarity > 0.9) return import_core9.Severity.Major;
803
+ return import_core9.Severity.Minor;
804
+ }
805
+
806
+ // src/scoring.ts
807
+ var import_core10 = require("@aiready/core");
808
+
809
+ // src/analyzer.ts
516
810
  async function analyzePatterns(options) {
517
811
  const smartDefaults = await getSmartDefaults(options.rootDir || ".", options);
518
812
  const finalOptions = { ...smartDefaults, ...options };
@@ -534,7 +828,7 @@ async function analyzePatterns(options) {
534
828
  ignoreWhitelist = [],
535
829
  ...scanOptions
536
830
  } = finalOptions;
537
- const files = await (0, import_core4.scanFiles)(scanOptions);
831
+ const files = await (0, import_core11.scanFiles)(scanOptions);
538
832
  const estimatedBlocks = files.length * 3;
539
833
  logConfiguration(finalOptions, estimatedBlocks);
540
834
  const results = [];
@@ -545,7 +839,7 @@ async function analyzePatterns(options) {
545
839
  const batchContents = await Promise.all(
546
840
  batch.map(async (file) => ({
547
841
  file,
548
- content: await (0, import_core4.readFileContent)(file)
842
+ content: await (0, import_core11.readFileContent)(file)
549
843
  }))
550
844
  );
551
845
  fileContents.push(...batchContents);
@@ -563,16 +857,22 @@ async function analyzePatterns(options) {
563
857
  ignoreWhitelist,
564
858
  onProgress: options.onProgress
565
859
  });
860
+ filterBrandSpecificVariants(duplicates);
566
861
  for (const file of files) {
567
862
  const fileDuplicates = duplicates.filter(
568
863
  (dup) => dup.file1 === file || dup.file2 === file
569
864
  );
570
865
  const issues = fileDuplicates.map((dup) => {
571
866
  const otherFile = dup.file1 === file ? dup.file2 : dup.file1;
572
- const severity2 = dup.similarity > 0.95 ? import_core4.Severity.Critical : dup.similarity > 0.9 ? import_core4.Severity.Major : import_core4.Severity.Minor;
867
+ let severityLevel;
868
+ if (dup.severity === "info" || dup.severity === "Info") {
869
+ severityLevel = import_core11.Severity.Info;
870
+ } else {
871
+ severityLevel = calculateSeverity2(dup.similarity);
872
+ }
573
873
  return {
574
- type: import_core4.IssueType.DuplicatePattern,
575
- severity: severity2,
874
+ type: import_core11.IssueType.DuplicatePattern,
875
+ severity: severityLevel,
576
876
  message: `${dup.patternType} pattern ${Math.round(dup.similarity * 100)}% similar to ${otherFile} (${dup.tokenCost} tokens wasted)`,
577
877
  location: {
578
878
  file,
@@ -581,18 +881,7 @@ async function analyzePatterns(options) {
581
881
  suggestion: getRefactoringSuggestion(dup.patternType, dup.similarity)
582
882
  };
583
883
  });
584
- let filteredIssues = issues;
585
- if (severity !== "all") {
586
- const severityMap = {
587
- critical: [import_core4.Severity.Critical],
588
- high: [import_core4.Severity.Critical, import_core4.Severity.Major],
589
- medium: [import_core4.Severity.Critical, import_core4.Severity.Major, import_core4.Severity.Minor]
590
- };
591
- const allowedSeverities = severityMap[severity] || [import_core4.Severity.Critical, import_core4.Severity.Major, import_core4.Severity.Minor];
592
- filteredIssues = issues.filter(
593
- (issue) => allowedSeverities.includes(issue.severity)
594
- );
595
- }
884
+ const filteredIssues = filterBySeverity2(issues, severity || "all");
596
885
  const totalTokenCost = fileDuplicates.reduce(
597
886
  (sum, dup) => sum + dup.tokenCost,
598
887
  0
@@ -621,69 +910,15 @@ async function analyzePatterns(options) {
621
910
  }
622
911
  return { results, duplicates, files, groups, clusters, config: finalOptions };
623
912
  }
624
- function generateSummary(results) {
625
- const allIssues = results.flatMap((r) => r.issues || []);
626
- const totalTokenCost = results.reduce(
627
- (sum, r) => sum + (r.metrics?.tokenCost || 0),
628
- 0
629
- );
630
- const patternsByType = {
631
- "api-handler": 0,
632
- validator: 0,
633
- utility: 0,
634
- "class-method": 0,
635
- component: 0,
636
- function: 0,
637
- unknown: 0
638
- };
639
- allIssues.forEach((issue) => {
640
- const match = issue.message.match(/^(\S+(?:-\S+)*) pattern/);
641
- if (match) {
642
- const type = match[1];
643
- patternsByType[type] = (patternsByType[type] || 0) + 1;
644
- }
645
- });
646
- const topDuplicates = allIssues.slice(0, 10).map((issue) => {
647
- const similarityMatch = issue.message.match(/(\d+)% similar/);
648
- const tokenMatch = issue.message.match(/\((\d+) tokens/);
649
- const typeMatch = issue.message.match(/^(\S+(?:-\S+)*) pattern/);
650
- const fileMatch = issue.message.match(/similar to (.+?) \(/);
651
- return {
652
- files: [
653
- {
654
- path: issue.location.file,
655
- startLine: issue.location.line,
656
- endLine: 0
657
- },
658
- {
659
- path: fileMatch?.[1] || "unknown",
660
- startLine: 0,
661
- endLine: 0
662
- }
663
- ],
664
- similarity: similarityMatch ? parseInt(similarityMatch[1]) / 100 : 0,
665
- confidence: similarityMatch ? parseInt(similarityMatch[1]) / 100 : 0,
666
- // Fallback for summary
667
- patternType: typeMatch?.[1] || "unknown",
668
- tokenCost: tokenMatch ? parseInt(tokenMatch[1]) : 0
669
- };
670
- });
671
- return {
672
- totalPatterns: allIssues.length,
673
- totalTokenCost,
674
- patternsByType,
675
- topDuplicates
676
- };
677
- }
678
913
 
679
914
  // src/cli-action.ts
680
915
  var import_chalk2 = __toESM(require("chalk"));
681
916
  var import_fs = require("fs");
682
917
  var import_path2 = require("path");
683
- var import_core8 = require("@aiready/core");
918
+ var import_core15 = require("@aiready/core");
684
919
 
685
920
  // src/config-resolver.ts
686
- var import_core5 = require("@aiready/core");
921
+ var import_core12 = require("@aiready/core");
687
922
 
688
923
  // src/constants.ts
689
924
  var DEFAULT_MIN_SIMILARITY = 0.4;
@@ -715,7 +950,7 @@ EXAMPLES:
715
950
 
716
951
  // src/config-resolver.ts
717
952
  async function resolvePatternConfig(directory, options) {
718
- const fileConfig = await (0, import_core5.loadConfig)(directory);
953
+ const fileConfig = await (0, import_core12.loadConfig)(directory);
719
954
  const defaults = {
720
955
  minSimilarity: DEFAULT_MIN_SIMILARITY,
721
956
  minLines: DEFAULT_MIN_LINES,
@@ -729,7 +964,7 @@ async function resolvePatternConfig(directory, options) {
729
964
  excludePatterns: void 0,
730
965
  confidenceThreshold: 0,
731
966
  ignoreWhitelist: void 0,
732
- minSeverity: import_core5.Severity.Minor,
967
+ minSeverity: import_core12.Severity.Minor,
733
968
  excludeTestFixtures: false,
734
969
  excludeTemplates: false,
735
970
  includeTests: false,
@@ -740,7 +975,7 @@ async function resolvePatternConfig(directory, options) {
740
975
  minClusterFiles: DEFAULT_MIN_CLUSTER_FILES,
741
976
  showRawDuplicates: false
742
977
  };
743
- const mergedConfig = (0, import_core5.mergeConfigWithDefaults)(fileConfig, defaults);
978
+ const mergedConfig = (0, import_core12.mergeConfigWithDefaults)(fileConfig, defaults);
744
979
  const finalOptions = {
745
980
  rootDir: directory,
746
981
  minSimilarity: options.similarity ? parseFloat(options.similarity) : mergedConfig.minSimilarity,
@@ -782,7 +1017,7 @@ async function resolvePatternConfig(directory, options) {
782
1017
  }
783
1018
 
784
1019
  // src/cli-output.ts
785
- var import_core6 = require("@aiready/core");
1020
+ var import_core13 = require("@aiready/core");
786
1021
  function getPatternIcon(type) {
787
1022
  const icons = {
788
1023
  "api-handler": "\u{1F50C}",
@@ -808,7 +1043,7 @@ function generateHTMLReport(results, summary) {
808
1043
  dup.files.map((f) => `<code>${f.path}:${f.startLine}-${f.endLine}</code>`).join("<br>\u2194<br>"),
809
1044
  dup.tokenCost.toLocaleString()
810
1045
  ]);
811
- return (0, import_core6.generateStandardHtmlReport)(
1046
+ return (0, import_core13.generateStandardHtmlReport)(
812
1047
  {
813
1048
  title: "Pattern Detection Report",
814
1049
  packageName: "pattern-detect",
@@ -825,7 +1060,7 @@ function generateHTMLReport(results, summary) {
825
1060
  [
826
1061
  {
827
1062
  title: "Duplicate Patterns",
828
- content: (0, import_core6.generateTable)({
1063
+ content: (0, import_core13.generateTable)({
829
1064
  headers: ["Similarity", "Type", "Locations", "Tokens Wasted"],
830
1065
  rows: tableRows
831
1066
  })
@@ -837,9 +1072,9 @@ function generateHTMLReport(results, summary) {
837
1072
 
838
1073
  // src/terminal-output.ts
839
1074
  var import_chalk = __toESM(require("chalk"));
840
- var import_core7 = require("@aiready/core");
1075
+ var import_core14 = require("@aiready/core");
841
1076
  function printAnalysisSummary(resultsLength, totalIssues, totalTokenCost, elapsedTime) {
842
- (0, import_core7.printTerminalHeader)("PATTERN ANALYSIS SUMMARY");
1077
+ (0, import_core14.printTerminalHeader)("PATTERN ANALYSIS SUMMARY");
843
1078
  console.log(import_chalk.default.white(`\u{1F4C1} Files analyzed: ${import_chalk.default.bold(resultsLength)}`));
844
1079
  console.log(
845
1080
  import_chalk.default.yellow(
@@ -856,9 +1091,9 @@ function printAnalysisSummary(resultsLength, totalIssues, totalTokenCost, elapse
856
1091
  function printPatternBreakdown(patternsByType) {
857
1092
  const sortedTypes = Object.entries(patternsByType).filter(([, count]) => count > 0).sort(([, a], [, b]) => b - a);
858
1093
  if (sortedTypes.length > 0) {
859
- console.log("\n" + (0, import_core7.getTerminalDivider)());
1094
+ console.log("\n" + (0, import_core14.getTerminalDivider)());
860
1095
  console.log(import_chalk.default.bold.white(" PATTERNS BY TYPE"));
861
- console.log((0, import_core7.getTerminalDivider)() + "\n");
1096
+ console.log((0, import_core14.getTerminalDivider)() + "\n");
862
1097
  sortedTypes.forEach(([type, count]) => {
863
1098
  const icon = getPatternIcon(type);
864
1099
  console.log(
@@ -869,20 +1104,20 @@ function printPatternBreakdown(patternsByType) {
869
1104
  }
870
1105
  function printDuplicateGroups(groups, maxResults) {
871
1106
  if (groups.length === 0) return;
872
- console.log("\n" + (0, import_core7.getTerminalDivider)());
1107
+ console.log("\n" + (0, import_core14.getTerminalDivider)());
873
1108
  console.log(
874
1109
  import_chalk.default.bold.white(` \u{1F4E6} DUPLICATE GROUPS (${groups.length} file pairs)`)
875
1110
  );
876
- console.log((0, import_core7.getTerminalDivider)() + "\n");
1111
+ console.log((0, import_core14.getTerminalDivider)() + "\n");
877
1112
  const topGroups = groups.sort((a, b) => {
878
- const bVal = (0, import_core7.getSeverityValue)(b.severity);
879
- const aVal = (0, import_core7.getSeverityValue)(a.severity);
1113
+ const bVal = (0, import_core14.getSeverityValue)(b.severity);
1114
+ const aVal = (0, import_core14.getSeverityValue)(a.severity);
880
1115
  const severityDiff = bVal - aVal;
881
1116
  if (severityDiff !== 0) return severityDiff;
882
1117
  return b.totalTokenCost - a.totalTokenCost;
883
1118
  }).slice(0, maxResults);
884
1119
  topGroups.forEach((group, idx) => {
885
- const severityBadge = (0, import_core7.getSeverityBadge)(group.severity);
1120
+ const severityBadge = (0, import_core14.getSeverityBadge)(group.severity);
886
1121
  const [file1, file2] = group.filePair.split("::");
887
1122
  const file1Name = file1.split("/").pop() || file1;
888
1123
  const file2Name = file2.split("/").pop() || file2;
@@ -915,13 +1150,13 @@ function printDuplicateGroups(groups, maxResults) {
915
1150
  }
916
1151
  function printRefactorClusters(clusters) {
917
1152
  if (clusters.length === 0) return;
918
- console.log("\n" + (0, import_core7.getTerminalDivider)());
1153
+ console.log("\n" + (0, import_core14.getTerminalDivider)());
919
1154
  console.log(
920
1155
  import_chalk.default.bold.white(` \u{1F3AF} REFACTOR CLUSTERS (${clusters.length} patterns)`)
921
1156
  );
922
- console.log((0, import_core7.getTerminalDivider)() + "\n");
1157
+ console.log((0, import_core14.getTerminalDivider)() + "\n");
923
1158
  clusters.sort((a, b) => b.totalTokenCost - a.totalTokenCost).forEach((cluster, idx) => {
924
- const severityBadge = (0, import_core7.getSeverityBadge)(cluster.severity);
1159
+ const severityBadge = (0, import_core14.getSeverityBadge)(cluster.severity);
925
1160
  console.log(`${idx + 1}. ${severityBadge} ${import_chalk.default.bold(cluster.name)}`);
926
1161
  console.log(
927
1162
  ` Total tokens: ${import_chalk.default.bold(cluster.totalTokenCost.toLocaleString())} | Avg similarity: ${import_chalk.default.bold(Math.round(cluster.averageSimilarity * 100) + "%")} | Duplicates: ${import_chalk.default.bold(cluster.duplicateCount)}`
@@ -948,18 +1183,18 @@ function printRefactorClusters(clusters) {
948
1183
  }
949
1184
  function printRawDuplicates(duplicates, maxResults) {
950
1185
  if (duplicates.length === 0) return;
951
- console.log("\n" + (0, import_core7.getTerminalDivider)());
1186
+ console.log("\n" + (0, import_core14.getTerminalDivider)());
952
1187
  console.log(import_chalk.default.bold.white(" TOP DUPLICATE PATTERNS"));
953
- console.log((0, import_core7.getTerminalDivider)() + "\n");
1188
+ console.log((0, import_core14.getTerminalDivider)() + "\n");
954
1189
  const topDuplicates = duplicates.sort((a, b) => {
955
- const bVal = (0, import_core7.getSeverityValue)(b.severity);
956
- const aVal = (0, import_core7.getSeverityValue)(a.severity);
1190
+ const bVal = (0, import_core14.getSeverityValue)(b.severity);
1191
+ const aVal = (0, import_core14.getSeverityValue)(a.severity);
957
1192
  const severityDiff = bVal - aVal;
958
1193
  if (severityDiff !== 0) return severityDiff;
959
1194
  return b.similarity - a.similarity;
960
1195
  }).slice(0, maxResults);
961
1196
  topDuplicates.forEach((dup) => {
962
- const severityBadge = (0, import_core7.getSeverityBadge)(dup.severity);
1197
+ const severityBadge = (0, import_core14.getSeverityBadge)(dup.severity);
963
1198
  const file1Name = dup.file1.split("/").pop() || dup.file1;
964
1199
  const file2Name = dup.file2.split("/").pop() || dup.file2;
965
1200
  console.log(
@@ -992,9 +1227,9 @@ function printRawDuplicates(duplicates, maxResults) {
992
1227
  }
993
1228
  function printCriticalIssues(issues) {
994
1229
  if (issues.length === 0) return;
995
- console.log((0, import_core7.getTerminalDivider)());
1230
+ console.log((0, import_core14.getTerminalDivider)());
996
1231
  console.log(import_chalk.default.bold.white(" CRITICAL ISSUES (>95% similar)"));
997
- console.log((0, import_core7.getTerminalDivider)() + "\n");
1232
+ console.log((0, import_core14.getTerminalDivider)() + "\n");
998
1233
  issues.slice(0, 5).forEach((issue) => {
999
1234
  console.log(
1000
1235
  import_chalk.default.red("\u25CF ") + import_chalk.default.white(`${issue.file}:${issue.location.line}`)
@@ -1018,7 +1253,7 @@ async function patternActionHandler(directory, options) {
1018
1253
  } = await analyzePatterns(finalOptions);
1019
1254
  let filteredDuplicates = rawDuplicates;
1020
1255
  if (finalOptions.minSeverity) {
1021
- filteredDuplicates = (0, import_core.filterBySeverity)(
1256
+ filteredDuplicates = (0, import_core5.filterBySeverity)(
1022
1257
  filteredDuplicates,
1023
1258
  finalOptions.minSeverity
1024
1259
  );
@@ -1066,7 +1301,7 @@ async function patternActionHandler(directory, options) {
1066
1301
  );
1067
1302
  }
1068
1303
  function handleJsonOutput(outputFile, directory, data) {
1069
- const outputPath = (0, import_core8.resolveOutputPath)(
1304
+ const outputPath = (0, import_core15.resolveOutputPath)(
1070
1305
  outputFile,
1071
1306
  `pattern-report-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.json`,
1072
1307
  directory
@@ -1079,7 +1314,7 @@ function handleJsonOutput(outputFile, directory, data) {
1079
1314
  }
1080
1315
  function handleHtmlOutput(outputFile, directory, summary, results) {
1081
1316
  const html = generateHTMLReport(summary, results);
1082
- const outputPath = (0, import_core8.resolveOutputPath)(
1317
+ const outputPath = (0, import_core15.resolveOutputPath)(
1083
1318
  outputFile,
1084
1319
  `pattern-report-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.html`,
1085
1320
  directory
@@ -1114,7 +1349,7 @@ function renderTerminalOutput(fileCount, totalIssues, summary, elapsedTime, opti
1114
1349
  } else if (totalIssues < 5) {
1115
1350
  printGuidance();
1116
1351
  }
1117
- console.log((0, import_core8.getTerminalDivider)());
1352
+ console.log((0, import_core15.getTerminalDivider)());
1118
1353
  if (totalIssues > 0) {
1119
1354
  console.log(
1120
1355
  import_chalk2.default.white(
@@ -1126,7 +1361,7 @@ function renderTerminalOutput(fileCount, totalIssues, summary, elapsedTime, opti
1126
1361
  printFooter();
1127
1362
  }
1128
1363
  function resultsToCriticalIssues(summary, duplicates) {
1129
- return duplicates.filter((d) => (0, import_core8.getSeverityValue)(d.severity) === 4).map((d) => ({
1364
+ return duplicates.filter((d) => (0, import_core15.getSeverityValue)(d.severity) === 4).map((d) => ({
1130
1365
  file: d.file1,
1131
1366
  location: { line: d.line1 },
1132
1367
  message: `${d.patternType} pattern highly similar to ${d.file2}`,