@girardelli/architect 2.2.0 → 5.0.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 (212) hide show
  1. package/README.md +105 -116
  2. package/architect-run.sh +431 -0
  3. package/assets/banner-v3.html +561 -0
  4. package/dist/agent-generator/context-enricher.d.ts +58 -0
  5. package/dist/agent-generator/context-enricher.d.ts.map +1 -0
  6. package/dist/agent-generator/context-enricher.js +613 -0
  7. package/dist/agent-generator/context-enricher.js.map +1 -0
  8. package/dist/agent-generator/domain-inferrer.d.ts +52 -0
  9. package/dist/agent-generator/domain-inferrer.d.ts.map +1 -0
  10. package/dist/agent-generator/domain-inferrer.js +585 -0
  11. package/dist/agent-generator/domain-inferrer.js.map +1 -0
  12. package/dist/agent-generator/framework-detector.d.ts +40 -0
  13. package/dist/agent-generator/framework-detector.d.ts.map +1 -0
  14. package/dist/agent-generator/framework-detector.js +611 -0
  15. package/dist/agent-generator/framework-detector.js.map +1 -0
  16. package/dist/agent-generator/index.d.ts +47 -0
  17. package/dist/agent-generator/index.d.ts.map +1 -0
  18. package/dist/agent-generator/index.js +545 -0
  19. package/dist/agent-generator/index.js.map +1 -0
  20. package/dist/agent-generator/stack-detector.d.ts +14 -0
  21. package/dist/agent-generator/stack-detector.d.ts.map +1 -0
  22. package/dist/agent-generator/stack-detector.js +124 -0
  23. package/dist/agent-generator/stack-detector.js.map +1 -0
  24. package/dist/agent-generator/templates/core/agents.d.ts +17 -0
  25. package/dist/agent-generator/templates/core/agents.d.ts.map +1 -0
  26. package/dist/agent-generator/templates/core/agents.js +1256 -0
  27. package/dist/agent-generator/templates/core/agents.js.map +1 -0
  28. package/dist/agent-generator/templates/core/architecture-rules.d.ts +7 -0
  29. package/dist/agent-generator/templates/core/architecture-rules.d.ts.map +1 -0
  30. package/dist/agent-generator/templates/core/architecture-rules.js +274 -0
  31. package/dist/agent-generator/templates/core/architecture-rules.js.map +1 -0
  32. package/dist/agent-generator/templates/core/general-rules.d.ts +8 -0
  33. package/dist/agent-generator/templates/core/general-rules.d.ts.map +1 -0
  34. package/dist/agent-generator/templates/core/general-rules.js +301 -0
  35. package/dist/agent-generator/templates/core/general-rules.js.map +1 -0
  36. package/dist/agent-generator/templates/core/hooks-generator.d.ts +21 -0
  37. package/dist/agent-generator/templates/core/hooks-generator.d.ts.map +1 -0
  38. package/dist/agent-generator/templates/core/hooks-generator.js +233 -0
  39. package/dist/agent-generator/templates/core/hooks-generator.js.map +1 -0
  40. package/dist/agent-generator/templates/core/index-md.d.ts +7 -0
  41. package/dist/agent-generator/templates/core/index-md.d.ts.map +1 -0
  42. package/dist/agent-generator/templates/core/index-md.js +246 -0
  43. package/dist/agent-generator/templates/core/index-md.js.map +1 -0
  44. package/dist/agent-generator/templates/core/orchestrator.d.ts +8 -0
  45. package/dist/agent-generator/templates/core/orchestrator.d.ts.map +1 -0
  46. package/dist/agent-generator/templates/core/orchestrator.js +422 -0
  47. package/dist/agent-generator/templates/core/orchestrator.js.map +1 -0
  48. package/dist/agent-generator/templates/core/preflight.d.ts +8 -0
  49. package/dist/agent-generator/templates/core/preflight.d.ts.map +1 -0
  50. package/dist/agent-generator/templates/core/preflight.js +213 -0
  51. package/dist/agent-generator/templates/core/preflight.js.map +1 -0
  52. package/dist/agent-generator/templates/core/quality-gates.d.ts +11 -0
  53. package/dist/agent-generator/templates/core/quality-gates.d.ts.map +1 -0
  54. package/dist/agent-generator/templates/core/quality-gates.js +254 -0
  55. package/dist/agent-generator/templates/core/quality-gates.js.map +1 -0
  56. package/dist/agent-generator/templates/core/security-rules.d.ts +7 -0
  57. package/dist/agent-generator/templates/core/security-rules.d.ts.map +1 -0
  58. package/dist/agent-generator/templates/core/security-rules.js +528 -0
  59. package/dist/agent-generator/templates/core/security-rules.js.map +1 -0
  60. package/dist/agent-generator/templates/core/skills-generator.d.ts +19 -0
  61. package/dist/agent-generator/templates/core/skills-generator.d.ts.map +1 -0
  62. package/dist/agent-generator/templates/core/skills-generator.js +546 -0
  63. package/dist/agent-generator/templates/core/skills-generator.js.map +1 -0
  64. package/dist/agent-generator/templates/core/workflow-fix-bug.d.ts +7 -0
  65. package/dist/agent-generator/templates/core/workflow-fix-bug.d.ts.map +1 -0
  66. package/dist/agent-generator/templates/core/workflow-fix-bug.js +237 -0
  67. package/dist/agent-generator/templates/core/workflow-fix-bug.js.map +1 -0
  68. package/dist/agent-generator/templates/core/workflow-new-feature.d.ts +8 -0
  69. package/dist/agent-generator/templates/core/workflow-new-feature.d.ts.map +1 -0
  70. package/dist/agent-generator/templates/core/workflow-new-feature.js +321 -0
  71. package/dist/agent-generator/templates/core/workflow-new-feature.js.map +1 -0
  72. package/dist/agent-generator/templates/core/workflow-review.d.ts +7 -0
  73. package/dist/agent-generator/templates/core/workflow-review.d.ts.map +1 -0
  74. package/dist/agent-generator/templates/core/workflow-review.js +104 -0
  75. package/dist/agent-generator/templates/core/workflow-review.js.map +1 -0
  76. package/dist/agent-generator/templates/domain/index.d.ts +22 -0
  77. package/dist/agent-generator/templates/domain/index.d.ts.map +1 -0
  78. package/dist/agent-generator/templates/domain/index.js +1176 -0
  79. package/dist/agent-generator/templates/domain/index.js.map +1 -0
  80. package/dist/agent-generator/templates/stack/index.d.ts +8 -0
  81. package/dist/agent-generator/templates/stack/index.d.ts.map +1 -0
  82. package/dist/agent-generator/templates/stack/index.js +695 -0
  83. package/dist/agent-generator/templates/stack/index.js.map +1 -0
  84. package/dist/agent-generator/templates/template-helpers.d.ts +75 -0
  85. package/dist/agent-generator/templates/template-helpers.d.ts.map +1 -0
  86. package/dist/agent-generator/templates/template-helpers.js +726 -0
  87. package/dist/agent-generator/templates/template-helpers.js.map +1 -0
  88. package/dist/agent-generator/types.d.ts +196 -0
  89. package/dist/agent-generator/types.d.ts.map +1 -0
  90. package/dist/agent-generator/types.js +27 -0
  91. package/dist/agent-generator/types.js.map +1 -0
  92. package/dist/analyzer.d.ts +5 -0
  93. package/dist/analyzer.d.ts.map +1 -1
  94. package/dist/analyzer.js +46 -5
  95. package/dist/analyzer.js.map +1 -1
  96. package/dist/analyzers/forecast.d.ts +85 -0
  97. package/dist/analyzers/forecast.d.ts.map +1 -0
  98. package/dist/analyzers/forecast.js +337 -0
  99. package/dist/analyzers/forecast.js.map +1 -0
  100. package/dist/analyzers/git-cache.d.ts +7 -0
  101. package/dist/analyzers/git-cache.d.ts.map +1 -0
  102. package/dist/analyzers/git-cache.js +41 -0
  103. package/dist/analyzers/git-cache.js.map +1 -0
  104. package/dist/analyzers/git-history.d.ts +113 -0
  105. package/dist/analyzers/git-history.d.ts.map +1 -0
  106. package/dist/analyzers/git-history.js +333 -0
  107. package/dist/analyzers/git-history.js.map +1 -0
  108. package/dist/analyzers/index.d.ts +10 -0
  109. package/dist/analyzers/index.d.ts.map +1 -0
  110. package/dist/analyzers/index.js +7 -0
  111. package/dist/analyzers/index.js.map +1 -0
  112. package/dist/analyzers/temporal-scorer.d.ts +72 -0
  113. package/dist/analyzers/temporal-scorer.d.ts.map +1 -0
  114. package/dist/analyzers/temporal-scorer.js +140 -0
  115. package/dist/analyzers/temporal-scorer.js.map +1 -0
  116. package/dist/anti-patterns.d.ts +7 -0
  117. package/dist/anti-patterns.d.ts.map +1 -1
  118. package/dist/anti-patterns.js +25 -6
  119. package/dist/anti-patterns.js.map +1 -1
  120. package/dist/cli.d.ts +2 -3
  121. package/dist/cli.d.ts.map +1 -1
  122. package/dist/cli.js +275 -113
  123. package/dist/cli.js.map +1 -1
  124. package/dist/config.d.ts +6 -0
  125. package/dist/config.d.ts.map +1 -1
  126. package/dist/config.js +48 -11
  127. package/dist/config.js.map +1 -1
  128. package/dist/html-reporter.d.ts +3 -1
  129. package/dist/html-reporter.d.ts.map +1 -1
  130. package/dist/html-reporter.js +248 -12
  131. package/dist/html-reporter.js.map +1 -1
  132. package/dist/index.d.ts +16 -3
  133. package/dist/index.d.ts.map +1 -1
  134. package/dist/index.js +63 -4
  135. package/dist/index.js.map +1 -1
  136. package/dist/project-summarizer.d.ts +38 -0
  137. package/dist/project-summarizer.d.ts.map +1 -0
  138. package/dist/project-summarizer.js +463 -0
  139. package/dist/project-summarizer.js.map +1 -0
  140. package/dist/refactor-reporter.js +1 -1
  141. package/dist/scanner.d.ts +8 -2
  142. package/dist/scanner.d.ts.map +1 -1
  143. package/dist/scanner.js +153 -113
  144. package/dist/scanner.js.map +1 -1
  145. package/dist/scorer.d.ts.map +1 -1
  146. package/dist/scorer.js +24 -11
  147. package/dist/scorer.js.map +1 -1
  148. package/dist/types.d.ts +29 -0
  149. package/dist/types.d.ts.map +1 -1
  150. package/package.json +12 -3
  151. package/src/agent-generator/context-enricher.ts +672 -0
  152. package/src/agent-generator/domain-inferrer.ts +635 -0
  153. package/src/agent-generator/framework-detector.ts +669 -0
  154. package/src/agent-generator/index.ts +634 -0
  155. package/src/agent-generator/stack-detector.ts +115 -0
  156. package/src/agent-generator/templates/core/agents.ts +1296 -0
  157. package/src/agent-generator/templates/core/architecture-rules.ts +287 -0
  158. package/src/agent-generator/templates/core/general-rules.ts +306 -0
  159. package/src/agent-generator/templates/core/hooks-generator.ts +242 -0
  160. package/src/agent-generator/templates/core/index-md.ts +260 -0
  161. package/src/agent-generator/templates/core/orchestrator.ts +459 -0
  162. package/src/agent-generator/templates/core/preflight.ts +215 -0
  163. package/src/agent-generator/templates/core/quality-gates.ts +256 -0
  164. package/src/agent-generator/templates/core/security-rules.ts +543 -0
  165. package/src/agent-generator/templates/core/skills-generator.ts +585 -0
  166. package/src/agent-generator/templates/core/workflow-fix-bug.ts +239 -0
  167. package/src/agent-generator/templates/core/workflow-new-feature.ts +323 -0
  168. package/src/agent-generator/templates/core/workflow-review.ts +106 -0
  169. package/src/agent-generator/templates/domain/index.ts +1201 -0
  170. package/src/agent-generator/templates/stack/index.ts +705 -0
  171. package/src/agent-generator/templates/template-helpers.ts +776 -0
  172. package/src/agent-generator/types.ts +232 -0
  173. package/src/analyzer.ts +51 -5
  174. package/src/analyzers/forecast.ts +496 -0
  175. package/src/analyzers/git-cache.ts +52 -0
  176. package/src/analyzers/git-history.ts +488 -0
  177. package/src/analyzers/index.ts +33 -0
  178. package/src/analyzers/temporal-scorer.ts +227 -0
  179. package/src/anti-patterns.ts +29 -6
  180. package/src/cli.ts +316 -117
  181. package/src/config.ts +52 -11
  182. package/src/html-reporter.ts +263 -13
  183. package/src/index.ts +93 -10
  184. package/src/project-summarizer.ts +521 -0
  185. package/src/refactor-reporter.ts +1 -1
  186. package/src/scanner.ts +136 -90
  187. package/src/scorer.ts +26 -11
  188. package/src/types.ts +27 -0
  189. package/tests/agent-generator.test.ts +427 -0
  190. package/tests/analyzers-integration.test.ts +174 -0
  191. package/tests/architect-adapter-enrichment.test.ts +9 -0
  192. package/tests/context-enricher.test.ts +971 -0
  193. package/tests/fixtures/monorepo/package.json +6 -0
  194. package/tests/fixtures/monorepo/packages/app/package.json +12 -0
  195. package/tests/fixtures/monorepo/packages/app/src/index.ts +6 -0
  196. package/tests/fixtures/monorepo/packages/core/package.json +7 -0
  197. package/tests/fixtures/monorepo/packages/core/src/index.ts +7 -0
  198. package/tests/forecast.test.ts +509 -0
  199. package/tests/framework-detector.test.ts +1172 -0
  200. package/tests/git-history.test.ts +254 -0
  201. package/tests/monorepo-scan.test.ts +170 -0
  202. package/tests/scanner.test.ts +7 -8
  203. package/tests/scorer.test.ts +594 -0
  204. package/tests/stack-detector.test.ts +241 -0
  205. package/tests/template-generation.test.ts +706 -0
  206. package/tests/template-helpers.test.ts +1152 -0
  207. package/tests/temporal-scorer.test.ts +307 -0
  208. package/dist/agent-generator.d.ts +0 -106
  209. package/dist/agent-generator.d.ts.map +0 -1
  210. package/dist/agent-generator.js +0 -1398
  211. package/dist/agent-generator.js.map +0 -1
  212. package/src/agent-generator.ts +0 -1526
@@ -0,0 +1,227 @@
1
+ /**
2
+ * Temporal Score Dimension — Adds time-series awareness to architecture scoring
3
+ *
4
+ * Combines current static score with historical velocity to produce:
5
+ * - Trend per module (improving / stable / degrading)
6
+ * - Temporal risk score (static score penalized by negative velocity)
7
+ * - Projected score in N weeks
8
+ *
9
+ * @author Camilo Girardelli — Girardelli Tecnologia
10
+ * @license MIT
11
+ */
12
+
13
+ import type {
14
+ ModuleHistory,
15
+ VelocityVector,
16
+ GitHistoryReport,
17
+ } from './git-history.js';
18
+
19
+ // ═══════════════════════════════════════════════════════════════
20
+ // TYPES
21
+ // ═══════════════════════════════════════════════════════════════
22
+
23
+ export type Trend = 'improving' | 'stable' | 'degrading';
24
+
25
+ export interface TemporalScore {
26
+ /** Module or file path */
27
+ module: string;
28
+ /** Current static score (from ArchitectureScorer) */
29
+ staticScore: number;
30
+ /** Temporal-adjusted score (penalizes degrading trends) */
31
+ temporalScore: number;
32
+ /** Direction of change */
33
+ trend: Trend;
34
+ /** Projected score in projectionWeeks */
35
+ projectedScore: number;
36
+ /** Confidence in the projection (0-1) */
37
+ projectionConfidence: number;
38
+ /** Weeks used for projection */
39
+ projectionWeeks: number;
40
+ /** Risk level derived from temporal analysis */
41
+ riskLevel: 'low' | 'medium' | 'high' | 'critical';
42
+ /** Velocity data */
43
+ velocity: VelocityVector;
44
+ }
45
+
46
+ export interface TemporalReport {
47
+ projectPath: string;
48
+ analyzedAt: string;
49
+ overallTrend: Trend;
50
+ overallTemporalScore: number;
51
+ modules: TemporalScore[];
52
+ degradingModules: TemporalScore[];
53
+ improvingModules: TemporalScore[];
54
+ }
55
+
56
+ export interface TemporalScorerConfig {
57
+ /** Weeks ahead to project (default: 12) */
58
+ projectionWeeks?: number;
59
+ /** Weight of churn trend in temporal penalty (0-1, default: 0.6) */
60
+ churnWeight?: number;
61
+ /** Weight of commit acceleration in temporal penalty (0-1, default: 0.4) */
62
+ commitWeight?: number;
63
+ /** Threshold for trend classification: accelerating if > threshold % */
64
+ acceleratingThreshold?: number;
65
+ /** Threshold for trend classification: decelerating if < -threshold % */
66
+ deceleratingThreshold?: number;
67
+ }
68
+
69
+ const DEFAULT_CONFIG: Required<TemporalScorerConfig> = {
70
+ projectionWeeks: 12,
71
+ churnWeight: 0.6,
72
+ commitWeight: 0.4,
73
+ acceleratingThreshold: 15,
74
+ deceleratingThreshold: -15,
75
+ };
76
+
77
+ // ═══════════════════════════════════════════════════════════════
78
+ // TEMPORAL SCORER
79
+ // ═══════════════════════════════════════════════════════════════
80
+
81
+ export class TemporalScorer {
82
+ private config: Required<TemporalScorerConfig>;
83
+
84
+ constructor(config?: TemporalScorerConfig) {
85
+ this.config = { ...DEFAULT_CONFIG, ...config };
86
+ }
87
+
88
+ /**
89
+ * Score modules temporally using git history + static scores.
90
+ *
91
+ * @param gitReport - Output from GitHistoryAnalyzer
92
+ * @param staticScores - Map of modulePath → static score (0-100)
93
+ */
94
+ score(
95
+ gitReport: GitHistoryReport,
96
+ staticScores: Map<string, number>,
97
+ ): TemporalReport {
98
+ const modules: TemporalScore[] = [];
99
+
100
+ for (const moduleHistory of gitReport.modules) {
101
+ const staticScore = staticScores.get(moduleHistory.modulePath)
102
+ ?? this.inferStaticScore(moduleHistory);
103
+
104
+ const ts = this.scoreModule(moduleHistory, staticScore);
105
+ modules.push(ts);
106
+ }
107
+
108
+ // Sort by risk (worst first)
109
+ modules.sort((a, b) => a.temporalScore - b.temporalScore);
110
+
111
+ const degrading = modules.filter(m => m.trend === 'degrading');
112
+ const improving = modules.filter(m => m.trend === 'improving');
113
+
114
+ const overallTrend = this.classifyOverallTrend(modules);
115
+ const overallScore = modules.length > 0
116
+ ? Math.round(modules.reduce((s, m) => s + m.temporalScore, 0) / modules.length)
117
+ : 0;
118
+
119
+ return {
120
+ projectPath: gitReport.projectPath,
121
+ analyzedAt: new Date().toISOString(),
122
+ overallTrend: overallTrend,
123
+ overallTemporalScore: overallScore,
124
+ modules,
125
+ degradingModules: degrading,
126
+ improvingModules: improving,
127
+ };
128
+ }
129
+
130
+ private scoreModule(module: ModuleHistory, staticScore: number): TemporalScore {
131
+ const velocity = module.velocityVector;
132
+
133
+ // Calculate temporal penalty based on velocity
134
+ const churnPenalty = velocity.churnTrend > 0
135
+ ? velocity.churnTrend * this.config.churnWeight * 0.3 // 30% impact per 100% churn increase
136
+ : velocity.churnTrend * this.config.churnWeight * 0.1; // 10% bonus per 100% churn decrease
137
+
138
+ const commitPenalty = velocity.commitAcceleration > 20
139
+ ? (velocity.commitAcceleration - 20) * this.config.commitWeight * 0.2 // penalty for excessive churn
140
+ : 0;
141
+
142
+ const totalPenalty = Math.max(-20, Math.min(30, churnPenalty + commitPenalty));
143
+ const temporalScore = Math.max(0, Math.min(100, Math.round(staticScore - totalPenalty)));
144
+
145
+ // Trend classification
146
+ const trend = this.classifyTrend(velocity);
147
+
148
+ // Linear projection
149
+ const weeklyDelta = totalPenalty / Math.max(this.config.projectionWeeks, 1);
150
+ const projectedScore = Math.max(0, Math.min(100,
151
+ Math.round(temporalScore - (weeklyDelta * this.config.projectionWeeks))
152
+ ));
153
+
154
+ // Confidence decreases with projection distance and instability
155
+ const instability = Math.abs(velocity.churnTrend) + Math.abs(velocity.commitAcceleration);
156
+ const projectionConfidence = Math.max(0.1, Math.min(1,
157
+ 1 - (instability / 200) - (this.config.projectionWeeks / 52)
158
+ ));
159
+
160
+ const riskLevel = this.classifyRisk(temporalScore, trend, module.busFactor);
161
+
162
+ return {
163
+ module: module.modulePath,
164
+ staticScore,
165
+ temporalScore,
166
+ trend,
167
+ projectedScore,
168
+ projectionConfidence: Math.round(projectionConfidence * 100) / 100,
169
+ projectionWeeks: this.config.projectionWeeks,
170
+ riskLevel,
171
+ velocity,
172
+ };
173
+ }
174
+
175
+ private classifyTrend(velocity: VelocityVector): Trend {
176
+ // Degrading: churn increasing significantly or commit acceleration very high
177
+ if (velocity.churnTrend > 30 || velocity.commitAcceleration > 50) {
178
+ return 'degrading';
179
+ }
180
+ // Improving: churn decreasing and stable or decelerating
181
+ if (velocity.churnTrend < -10 && velocity.direction !== 'accelerating') {
182
+ return 'improving';
183
+ }
184
+ return 'stable';
185
+ }
186
+
187
+ private classifyRisk(
188
+ temporalScore: number,
189
+ trend: Trend,
190
+ busFactor: number,
191
+ ): TemporalScore['riskLevel'] {
192
+ if (temporalScore < 30 || (temporalScore < 50 && trend === 'degrading')) {
193
+ return 'critical';
194
+ }
195
+ if (temporalScore < 50 || (trend === 'degrading' && busFactor <= 1)) {
196
+ return 'high';
197
+ }
198
+ if (temporalScore < 70 || trend === 'degrading') {
199
+ return 'medium';
200
+ }
201
+ return 'low';
202
+ }
203
+
204
+ private classifyOverallTrend(modules: TemporalScore[]): Trend {
205
+ if (modules.length === 0) return 'stable';
206
+
207
+ const degrading = modules.filter(m => m.trend === 'degrading').length;
208
+ const improving = modules.filter(m => m.trend === 'improving').length;
209
+
210
+ const degradingRatio = degrading / modules.length;
211
+ const improvingRatio = improving / modules.length;
212
+
213
+ if (degradingRatio > 0.3) return 'degrading';
214
+ if (improvingRatio > 0.3) return 'improving';
215
+ return 'stable';
216
+ }
217
+
218
+ /** Infer a static score when none is provided (based on churn metrics) */
219
+ private inferStaticScore(module: ModuleHistory): number {
220
+ const avgChurn = module.aggregateChurn / Math.max(module.aggregateCommits, 1);
221
+ if (avgChurn < 20) return 85;
222
+ if (avgChurn < 50) return 75;
223
+ if (avgChurn < 100) return 65;
224
+ if (avgChurn < 200) return 50;
225
+ return 35;
226
+ }
227
+ }
@@ -5,11 +5,28 @@ export class AntiPatternDetector {
5
5
  private config: ArchitectConfig;
6
6
  private dependencyGraph: Map<string, Set<string>>;
7
7
 
8
+ /** Paths that indicate third-party or build artifacts — never report anti-patterns here */
9
+ private static readonly EXCLUDED_PATH_SEGMENTS = [
10
+ 'node_modules', '/dist/', '/build/', '/coverage/',
11
+ '/.next/', '/venv/', '/__pycache__/', '/target/',
12
+ ];
13
+
8
14
  constructor(config: ArchitectConfig) {
9
15
  this.config = config;
10
16
  this.dependencyGraph = new Map();
11
17
  }
12
18
 
19
+ /**
20
+ * Check if a file path belongs to the project's own source code.
21
+ * Returns false for node_modules, dist, build artifacts, etc.
22
+ */
23
+ private isProjectFile(filePath: string): boolean {
24
+ const normalized = filePath.replace(/\\/g, '/');
25
+ return !AntiPatternDetector.EXCLUDED_PATH_SEGMENTS.some(seg =>
26
+ normalized.includes(seg)
27
+ );
28
+ }
29
+
13
30
  detect(
14
31
  fileTree: FileNode,
15
32
  dependencies: Map<string, Set<string>>
@@ -42,7 +59,7 @@ export class AntiPatternDetector {
42
59
  this.config.antiPatterns?.godClass?.methodsThreshold || 10;
43
60
 
44
61
  this.walkFileTree(node, (file) => {
45
- if (file.type === 'file' && (file.lines || 0) > threshold) {
62
+ if (file.type === 'file' && (file.lines || 0) > threshold && this.isProjectFile(file.path)) {
46
63
  const methods = this.countMethods(file.path);
47
64
  if (methods > methodThreshold) {
48
65
  patterns.push({
@@ -70,9 +87,12 @@ export class AntiPatternDetector {
70
87
  const recursionStack = new Set<string>();
71
88
 
72
89
  for (const file of this.dependencyGraph.keys()) {
90
+ // Only check cycles starting from project files
91
+ if (!this.isProjectFile(file)) continue;
92
+
73
93
  if (!visited.has(file)) {
74
94
  const cycle = this.findCycle(file, visited, recursionStack);
75
- if (cycle) {
95
+ if (cycle && cycle.every(f => this.isProjectFile(f))) {
76
96
  patterns.push({
77
97
  name: 'Circular Dependency',
78
98
  severity: 'HIGH',
@@ -118,7 +138,7 @@ export class AntiPatternDetector {
118
138
  const patterns: AntiPattern[] = [];
119
139
 
120
140
  this.walkFileTree(node, (file) => {
121
- if (file.type === 'file') {
141
+ if (file.type === 'file' && this.isProjectFile(file.path)) {
122
142
  const internalExports = this.countInternalExports(file.path);
123
143
  if (internalExports > 5) {
124
144
  patterns.push({
@@ -146,13 +166,13 @@ export class AntiPatternDetector {
146
166
  const patterns: AntiPattern[] = [];
147
167
 
148
168
  this.walkFileTree(node, (file) => {
149
- if (file.type === 'file') {
169
+ if (file.type === 'file' && this.isProjectFile(file.path)) {
150
170
  const externalMethodCalls = (dependencies.get(file.path) || new Set())
151
171
  .size;
152
172
  const internalMethods = this.countMethods(file.path);
153
173
  const name = file.name.toLowerCase();
154
174
 
155
- // Skip NestJS infrastructure files where external deps are by design
175
+ // Skip infrastructure files where external deps are by design
156
176
  const isInfraFile =
157
177
  name.endsWith('.module.ts') ||
158
178
  name.endsWith('.dto.ts') ||
@@ -194,6 +214,9 @@ export class AntiPatternDetector {
194
214
  ?.changePropagationThreshold || 8;
195
215
 
196
216
  for (const [file, dependents] of dependencies) {
217
+ // Only report for project files
218
+ if (!this.isProjectFile(file)) continue;
219
+
197
220
  if (dependents.size >= threshold) {
198
221
  patterns.push({
199
222
  name: 'Shotgun Surgery',
@@ -202,7 +225,7 @@ export class AntiPatternDetector {
202
225
  description: `Changes to this file likely require modifications in ${dependents.size} other files`,
203
226
  suggestion:
204
227
  'Refactor to reduce coupling and consolidate related functionality into modules',
205
- affectedFiles: Array.from(dependents),
228
+ affectedFiles: Array.from(dependents).filter(f => this.isProjectFile(f)),
206
229
  metrics: {
207
230
  dependentFileCount: dependents.size,
208
231
  },