aios-core 4.1.0 → 4.2.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 (145) hide show
  1. package/.aios-core/.session/current-session.json +14 -0
  2. package/.aios-core/core/registry/registry-schema.json +166 -166
  3. package/.aios-core/core/registry/service-registry.json +6585 -6585
  4. package/.aios-core/data/entity-registry.yaml +208 -8
  5. package/.aios-core/data/registry-update-log.jsonl +165 -0
  6. package/.aios-core/development/scripts/approval-workflow.js +642 -642
  7. package/.aios-core/development/scripts/backup-manager.js +606 -606
  8. package/.aios-core/development/scripts/branch-manager.js +389 -389
  9. package/.aios-core/development/scripts/code-quality-improver.js +1311 -1311
  10. package/.aios-core/development/scripts/commit-message-generator.js +849 -849
  11. package/.aios-core/development/scripts/conflict-resolver.js +674 -674
  12. package/.aios-core/development/scripts/dependency-analyzer.js +637 -637
  13. package/.aios-core/development/scripts/diff-generator.js +351 -351
  14. package/.aios-core/development/scripts/elicitation-engine.js +384 -384
  15. package/.aios-core/development/scripts/elicitation-session-manager.js +299 -299
  16. package/.aios-core/development/scripts/git-wrapper.js +461 -461
  17. package/.aios-core/development/scripts/manifest-preview.js +244 -244
  18. package/.aios-core/development/scripts/metrics-tracker.js +775 -775
  19. package/.aios-core/development/scripts/modification-validator.js +554 -554
  20. package/.aios-core/development/scripts/pattern-learner.js +1224 -1224
  21. package/.aios-core/development/scripts/performance-analyzer.js +757 -757
  22. package/.aios-core/development/scripts/refactoring-suggester.js +1138 -1138
  23. package/.aios-core/development/scripts/rollback-handler.js +530 -530
  24. package/.aios-core/development/scripts/security-checker.js +358 -358
  25. package/.aios-core/development/scripts/template-engine.js +239 -239
  26. package/.aios-core/development/scripts/template-validator.js +278 -278
  27. package/.aios-core/development/scripts/test-generator.js +843 -843
  28. package/.aios-core/development/scripts/transaction-manager.js +589 -589
  29. package/.aios-core/development/scripts/usage-tracker.js +673 -673
  30. package/.aios-core/development/scripts/validate-filenames.js +226 -226
  31. package/.aios-core/development/scripts/version-tracker.js +526 -526
  32. package/.aios-core/development/scripts/yaml-validator.js +396 -396
  33. package/.aios-core/development/tasks/validate-next-story.md +99 -2
  34. package/.aios-core/development/templates/service-template/README.md.hbs +158 -158
  35. package/.aios-core/development/templates/service-template/__tests__/index.test.ts.hbs +237 -237
  36. package/.aios-core/development/templates/service-template/client.ts.hbs +403 -403
  37. package/.aios-core/development/templates/service-template/errors.ts.hbs +182 -182
  38. package/.aios-core/development/templates/service-template/index.ts.hbs +120 -120
  39. package/.aios-core/development/templates/service-template/package.json.hbs +87 -87
  40. package/.aios-core/development/templates/service-template/types.ts.hbs +145 -145
  41. package/.aios-core/development/templates/squad-template/LICENSE +21 -21
  42. package/.aios-core/docs/SHARD-TRANSLATION-GUIDE.md +335 -0
  43. package/.aios-core/docs/component-creation-guide.md +458 -0
  44. package/.aios-core/docs/session-update-pattern.md +307 -0
  45. package/.aios-core/docs/standards/AIOS-FRAMEWORK-MASTER.md +1963 -0
  46. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1-SUMMARY.md +1190 -0
  47. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1.md +439 -0
  48. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO.md +5398 -0
  49. package/.aios-core/docs/standards/V3-ARCHITECTURAL-DECISIONS.md +523 -0
  50. package/.aios-core/docs/template-syntax.md +267 -0
  51. package/.aios-core/docs/troubleshooting-guide.md +625 -0
  52. package/.aios-core/infrastructure/templates/aios-sync.yaml.template +193 -193
  53. package/.aios-core/infrastructure/templates/coderabbit.yaml.template +279 -279
  54. package/.aios-core/infrastructure/templates/github-workflows/ci.yml.template +169 -169
  55. package/.aios-core/infrastructure/templates/github-workflows/pr-automation.yml.template +330 -330
  56. package/.aios-core/infrastructure/templates/github-workflows/release.yml.template +196 -196
  57. package/.aios-core/infrastructure/templates/gitignore/gitignore-aios-base.tmpl +63 -63
  58. package/.aios-core/infrastructure/templates/gitignore/gitignore-brownfield-merge.tmpl +18 -18
  59. package/.aios-core/infrastructure/templates/gitignore/gitignore-node.tmpl +85 -85
  60. package/.aios-core/infrastructure/templates/gitignore/gitignore-python.tmpl +145 -145
  61. package/.aios-core/infrastructure/tests/utilities-audit-results.json +501 -0
  62. package/.aios-core/install-manifest.yaml +101 -101
  63. package/.aios-core/local-config.yaml.template +70 -70
  64. package/.aios-core/manifests/agents.csv +29 -0
  65. package/.aios-core/manifests/schema/manifest-schema.json +190 -190
  66. package/.aios-core/manifests/tasks.csv +198 -0
  67. package/.aios-core/manifests/workers.csv +204 -0
  68. package/.aios-core/monitor/hooks/lib/__init__.py +1 -1
  69. package/.aios-core/monitor/hooks/lib/enrich.py +58 -58
  70. package/.aios-core/monitor/hooks/lib/send_event.py +47 -47
  71. package/.aios-core/monitor/hooks/notification.py +29 -29
  72. package/.aios-core/monitor/hooks/post_tool_use.py +45 -45
  73. package/.aios-core/monitor/hooks/pre_compact.py +29 -29
  74. package/.aios-core/monitor/hooks/pre_tool_use.py +40 -40
  75. package/.aios-core/monitor/hooks/stop.py +29 -29
  76. package/.aios-core/monitor/hooks/subagent_stop.py +29 -29
  77. package/.aios-core/monitor/hooks/user_prompt_submit.py +38 -38
  78. package/.aios-core/product/templates/adr.hbs +125 -125
  79. package/.aios-core/product/templates/component-react-tmpl.tsx +98 -98
  80. package/.aios-core/product/templates/dbdr.hbs +241 -241
  81. package/.aios-core/product/templates/engine/schemas/adr.schema.json +102 -102
  82. package/.aios-core/product/templates/engine/schemas/dbdr.schema.json +205 -205
  83. package/.aios-core/product/templates/engine/schemas/epic.schema.json +175 -175
  84. package/.aios-core/product/templates/engine/schemas/pmdr.schema.json +175 -175
  85. package/.aios-core/product/templates/engine/schemas/prd-v2.schema.json +300 -300
  86. package/.aios-core/product/templates/engine/schemas/prd.schema.json +152 -152
  87. package/.aios-core/product/templates/engine/schemas/story.schema.json +222 -222
  88. package/.aios-core/product/templates/engine/schemas/task.schema.json +154 -154
  89. package/.aios-core/product/templates/epic.hbs +212 -212
  90. package/.aios-core/product/templates/eslintrc-security.json +32 -32
  91. package/.aios-core/product/templates/github-actions-cd.yml +212 -212
  92. package/.aios-core/product/templates/github-actions-ci.yml +172 -172
  93. package/.aios-core/product/templates/pmdr.hbs +186 -186
  94. package/.aios-core/product/templates/prd-v2.0.hbs +216 -216
  95. package/.aios-core/product/templates/prd.hbs +201 -201
  96. package/.aios-core/product/templates/shock-report-tmpl.html +502 -502
  97. package/.aios-core/product/templates/story.hbs +263 -263
  98. package/.aios-core/product/templates/task.hbs +170 -170
  99. package/.aios-core/product/templates/tmpl-comment-on-examples.sql +158 -158
  100. package/.aios-core/product/templates/tmpl-migration-script.sql +91 -91
  101. package/.aios-core/product/templates/tmpl-rls-granular-policies.sql +104 -104
  102. package/.aios-core/product/templates/tmpl-rls-kiss-policy.sql +10 -10
  103. package/.aios-core/product/templates/tmpl-rls-roles.sql +135 -135
  104. package/.aios-core/product/templates/tmpl-rls-simple.sql +77 -77
  105. package/.aios-core/product/templates/tmpl-rls-tenant.sql +152 -152
  106. package/.aios-core/product/templates/tmpl-rollback-script.sql +77 -77
  107. package/.aios-core/product/templates/tmpl-seed-data.sql +140 -140
  108. package/.aios-core/product/templates/tmpl-smoke-test.sql +16 -16
  109. package/.aios-core/product/templates/tmpl-staging-copy-merge.sql +139 -139
  110. package/.aios-core/product/templates/tmpl-stored-proc.sql +140 -140
  111. package/.aios-core/product/templates/tmpl-trigger.sql +152 -152
  112. package/.aios-core/product/templates/tmpl-view-materialized.sql +133 -133
  113. package/.aios-core/product/templates/tmpl-view.sql +177 -177
  114. package/.aios-core/product/templates/token-exports-css-tmpl.css +240 -240
  115. package/.aios-core/quality/schemas/quality-metrics.schema.json +233 -233
  116. package/.aios-core/scripts/migrate-framework-docs.sh +300 -300
  117. package/.aios-core/scripts/pm.sh +0 -0
  118. package/.claude/hooks/enforce-architecture-first.py +196 -196
  119. package/.claude/hooks/mind-clone-governance.py +192 -192
  120. package/.claude/hooks/read-protection.py +151 -151
  121. package/.claude/hooks/slug-validation.py +176 -176
  122. package/.claude/hooks/sql-governance.py +182 -182
  123. package/.claude/hooks/write-path-validation.py +194 -194
  124. package/.claude/rules/agent-authority.md +105 -0
  125. package/.claude/rules/coderabbit-integration.md +93 -0
  126. package/.claude/rules/ids-principles.md +112 -0
  127. package/.claude/rules/story-lifecycle.md +139 -0
  128. package/.claude/rules/workflow-execution.md +150 -0
  129. package/LICENSE +48 -48
  130. package/bin/aios-minimal.js +0 -0
  131. package/bin/aios.js +0 -0
  132. package/package.json +1 -1
  133. package/packages/aios-install/bin/aios-install.js +0 -0
  134. package/packages/aios-install/bin/edmcp.js +0 -0
  135. package/packages/aios-pro-cli/bin/aios-pro.js +0 -0
  136. package/packages/installer/src/wizard/pro-setup.js +433 -49
  137. package/scripts/check-markdown-links.py +352 -352
  138. package/scripts/code-intel-health-check.js +343 -0
  139. package/scripts/dashboard-parallel-dev.sh +0 -0
  140. package/scripts/dashboard-parallel-phase3.sh +0 -0
  141. package/scripts/dashboard-parallel-phase4.sh +0 -0
  142. package/scripts/glue/README.md +355 -0
  143. package/scripts/glue/compose-agent-prompt.cjs +362 -0
  144. package/scripts/install-monitor-hooks.sh +0 -0
  145. package/.aios-core/lib/build.json +0 -1
@@ -1,758 +1,758 @@
1
- const fs = require('fs').promises;
2
- const path = require('path');
3
- const chalk = require('chalk');
4
-
5
- /**
6
- * Performance bottleneck analyzer for AIOS-FULLSTACK framework
7
- * Identifies performance issues and optimization opportunities
8
- */
9
- class PerformanceAnalyzer {
10
- constructor(options = {}) {
11
- this.rootPath = options.rootPath || process.cwd();
12
- this.thresholds = {
13
- fileSize: 50 * 1024, // 50KB
14
- functionLength: 50, // lines
15
- cyclomaticComplexity: 10,
16
- nestingDepth: 5,
17
- importCount: 20,
18
- unusedCode: 0.1 // 10% unused code ratio
19
- };
20
- this.performancePatterns = {
21
- // Sync operations that should be async
22
- syncOperations: [
23
- /fs\.readFileSync/g,
24
- /fs\.writeFileSync/g,
25
- /fs\.existsSync/g,
26
- /JSON\.parse\(\s*fs\.readFileSync/g
27
- ],
28
- // Memory-intensive patterns
29
- memoryIssues: [
30
- /\.map\(\s*.*\.map\(/g, // Nested maps
31
- /new Array\(\d{4,}\)/g, // Large arrays
32
- /JSON\.stringify.*JSON\.parse/g, // Unnecessary serialization
33
- /require\(\s*['"`][^'"`]+\.json['"`]\s*\)/g // Large JSON imports
34
- ],
35
- // Performance anti-patterns
36
- antiPatterns: [
37
- /console\.log/g, // Console logs in production
38
- /debugger/g, // Debugger statements
39
- /setTimeout\(\s*.*,\s*0\s*\)/g, // Unnecessary setTimeout
40
- /setInterval\(\s*.*,\s*[0-9]{1,2}\s*\)/g // High-frequency intervals
41
- ],
42
- // Inefficient loops
43
- inefficientLoops: [
44
- /for\s*\(\s*.*\.length\s*;/g, // Length calculated in loop condition
45
- /while\s*\(\s*true\s*\)/g, // Infinite loops
46
- /forEach.*forEach/g // Nested forEach
47
- ]
48
- };
49
- }
50
-
51
- /**
52
- * Analyze performance across all components
53
- */
54
- async analyzePerformance(components) {
55
- const analysis = {
56
- timestamp: new Date().toISOString(),
57
- overall_score: 0,
58
- bottlenecks: [],
59
- optimization_opportunities: [],
60
- memory_issues: [],
61
- async_opportunities: [],
62
- code_quality_issues: [],
63
- file_size_issues: [],
64
- complexity_issues: [],
65
- recommendations: [],
66
- metrics: {
67
- total_files_analyzed: 0,
68
- total_issues_found: 0,
69
- critical_issues: 0,
70
- high_priority_issues: 0,
71
- medium_priority_issues: 0,
72
- low_priority_issues: 0
73
- }
74
- };
75
-
76
- try {
77
- console.log(chalk.blue('🔍 Analyzing performance bottlenecks...'));
78
-
79
- // Analyze each component
80
- for (const component of components) {
81
- const componentAnalysis = await this.analyzeComponentPerformance(component);
82
-
83
- // Aggregate results
84
- analysis.bottlenecks.push(...componentAnalysis.bottlenecks);
85
- analysis.optimization_opportunities.push(...componentAnalysis.optimizations);
86
- analysis.memory_issues.push(...componentAnalysis.memory_issues);
87
- analysis.async_opportunities.push(...componentAnalysis.async_opportunities);
88
- analysis.code_quality_issues.push(...componentAnalysis.quality_issues);
89
- analysis.file_size_issues.push(...componentAnalysis.file_size_issues);
90
- analysis.complexity_issues.push(...componentAnalysis.complexity_issues);
91
-
92
- analysis.metrics.total_files_analyzed++;
93
- }
94
-
95
- // Calculate overall metrics
96
- analysis.overall_score = this.calculateOverallScore(analysis);
97
- analysis.metrics.total_issues_found = this.countTotalIssues(analysis);
98
- analysis.metrics = this.calculateIssuePriorities(analysis);
99
- analysis.recommendations = this.generatePerformanceRecommendations(analysis);
100
-
101
- console.log(chalk.green(`✅ Performance analysis completed`));
102
- console.log(chalk.gray(` Files analyzed: ${analysis.metrics.total_files_analyzed}`));
103
- console.log(chalk.gray(` Issues found: ${analysis.metrics.total_issues_found}`));
104
- console.log(chalk.gray(` Overall score: ${analysis.overall_score}/10`));
105
-
106
- return analysis;
107
-
108
- } catch (error) {
109
- console.error(chalk.red(`Performance analysis failed: ${error.message}`));
110
- throw error;
111
- }
112
- }
113
-
114
- /**
115
- * Analyze performance for a single component
116
- */
117
- async analyzeComponentPerformance(component) {
118
- const analysis = {
119
- component_id: component.id,
120
- component_type: component.type,
121
- bottlenecks: [],
122
- optimizations: [],
123
- memory_issues: [],
124
- async_opportunities: [],
125
- quality_issues: [],
126
- file_size_issues: [],
127
- complexity_issues: []
128
- };
129
-
130
- try {
131
- // Only analyze JavaScript files and executable components
132
- if (!this.shouldAnalyzeComponent(component)) {
133
- return analysis;
134
- }
135
-
136
- const filePath = path.join(this.rootPath, component.file_path);
137
- const content = await fs.readFile(filePath, 'utf-8');
138
- const stats = await fs.stat(filePath);
139
-
140
- // File size analysis
141
- if (stats.size > this.thresholds.fileSize) {
142
- analysis.file_size_issues.push({
143
- component: component.id,
144
- issue: `Large file size: ${this.formatBytes(stats.size)}`,
145
- severity: stats.size > this.thresholds.fileSize * 2 ? 'high' : 'medium',
146
- recommendation: 'Consider breaking down into smaller modules',
147
- impact: 'high',
148
- effort: 'medium'
149
- });
150
- }
151
-
152
- // Synchronous operations analysis
153
- const syncIssues = this.findSyncOperations(content, component);
154
- analysis.async_opportunities.push(...syncIssues);
155
-
156
- // Memory usage analysis
157
- const memoryIssues = this.findMemoryIssues(content, component);
158
- analysis.memory_issues.push(...memoryIssues);
159
-
160
- // Performance anti-patterns
161
- const antiPatterns = this.findAntiPatterns(content, component);
162
- analysis.quality_issues.push(...antiPatterns);
163
-
164
- // Loop efficiency analysis
165
- const loopIssues = this.findLoopIssues(content, component);
166
- analysis.bottlenecks.push(...loopIssues);
167
-
168
- // Function complexity analysis
169
- const complexityIssues = this.analyzeComplexity(content, component);
170
- analysis.complexity_issues.push(...complexityIssues);
171
-
172
- // Import/require analysis
173
- const importIssues = this.analyzeImports(content, component);
174
- analysis.optimizations.push(...importIssues);
175
-
176
- // Dead code analysis
177
- const deadCodeIssues = await this.findDeadCode(content, component);
178
- analysis.optimizations.push(...deadCodeIssues);
179
-
180
- } catch (error) {
181
- console.warn(chalk.yellow(`Failed to analyze performance for ${component.id}: ${error.message}`));
182
- }
183
-
184
- return analysis;
185
- }
186
-
187
- /**
188
- * Find synchronous operations that should be async
189
- */
190
- findSyncOperations(content, component) {
191
- const issues = [];
192
- const lines = content.split('\n');
193
-
194
- this.performancePatterns.syncOperations.forEach(pattern => {
195
- lines.forEach((line, index) => {
196
- const matches = line.match(pattern);
197
- if (matches) {
198
- matches.forEach(match => {
199
- issues.push({
200
- component: component.id,
201
- issue: `Synchronous operation: ${match}`,
202
- line: index + 1,
203
- context: line.trim(),
204
- severity: 'high',
205
- recommendation: 'Convert to async equivalent',
206
- impact: 'high',
207
- effort: 'low'
208
- });
209
- });
210
- }
211
- });
212
- });
213
-
214
- return issues;
215
- }
216
-
217
- /**
218
- * Find memory-intensive patterns
219
- */
220
- findMemoryIssues(content, component) {
221
- const issues = [];
222
- const lines = content.split('\n');
223
-
224
- this.performancePatterns.memoryIssues.forEach(pattern => {
225
- lines.forEach((line, index) => {
226
- const matches = line.match(pattern);
227
- if (matches) {
228
- matches.forEach(match => {
229
- let severity = 'medium';
230
- let recommendation = 'Optimize memory usage';
231
-
232
- if (match.includes('new Array')) {
233
- severity = 'high';
234
- recommendation = 'Use array literals or streaming for large datasets';
235
- } else if (match.includes('JSON.stringify.*JSON.parse')) {
236
- recommendation = 'Use direct object assignment or deep clone utilities';
237
- } else if (match.includes('.map(.*map(')) {
238
- recommendation = 'Combine operations or use more efficient iteration';
239
- }
240
-
241
- issues.push({
242
- component: component.id,
243
- issue: `Memory-intensive pattern: ${match}`,
244
- line: index + 1,
245
- context: line.trim(),
246
- severity,
247
- recommendation,
248
- impact: 'medium',
249
- effort: 'medium'
250
- });
251
- });
252
- }
253
- });
254
- });
255
-
256
- return issues;
257
- }
258
-
259
- /**
260
- * Find performance anti-patterns
261
- */
262
- findAntiPatterns(content, component) {
263
- const issues = [];
264
- const lines = content.split('\n');
265
-
266
- this.performancePatterns.antiPatterns.forEach(pattern => {
267
- lines.forEach((line, index) => {
268
- const matches = line.match(pattern);
269
- if (matches) {
270
- matches.forEach(match => {
271
- let severity = 'low';
272
- let recommendation = 'Remove or optimize';
273
-
274
- if (match.includes('console.log')) {
275
- recommendation = 'Remove console.log statements from production code';
276
- } else if (match.includes('debugger')) {
277
- severity = 'medium';
278
- recommendation = 'Remove debugger statements';
279
- } else if (match.includes('setTimeout')) {
280
- recommendation = 'Use proper async/await or promises instead';
281
- }
282
-
283
- issues.push({
284
- component: component.id,
285
- issue: `Performance anti-pattern: ${match}`,
286
- line: index + 1,
287
- context: line.trim(),
288
- severity,
289
- recommendation,
290
- impact: 'low',
291
- effort: 'low'
292
- });
293
- });
294
- }
295
- });
296
- });
297
-
298
- return issues;
299
- }
300
-
301
- /**
302
- * Find inefficient loop patterns
303
- */
304
- findLoopIssues(content, component) {
305
- const issues = [];
306
- const lines = content.split('\n');
307
-
308
- this.performancePatterns.inefficientLoops.forEach(pattern => {
309
- lines.forEach((line, index) => {
310
- const matches = line.match(pattern);
311
- if (matches) {
312
- matches.forEach(match => {
313
- let severity = 'medium';
314
- let recommendation = 'Optimize loop structure';
315
-
316
- if (match.includes('.length')) {
317
- recommendation = 'Cache array length in variable before loop';
318
- } else if (match.includes('while(true)')) {
319
- severity = 'high';
320
- recommendation = 'Add proper exit condition to prevent infinite loops';
321
- } else if (match.includes('forEach.*forEach')) {
322
- recommendation = 'Consider using nested for loops or array methods like flatMap';
323
- }
324
-
325
- issues.push({
326
- component: component.id,
327
- issue: `Inefficient loop: ${match}`,
328
- line: index + 1,
329
- context: line.trim(),
330
- severity,
331
- recommendation,
332
- impact: 'medium',
333
- effort: 'low'
334
- });
335
- });
336
- }
337
- });
338
- });
339
-
340
- return issues;
341
- }
342
-
343
- /**
344
- * Analyze function complexity
345
- */
346
- analyzeComplexity(content, component) {
347
- const issues = [];
348
- const functions = this.extractFunctions(content);
349
-
350
- functions.forEach(func => {
351
- // Check function length
352
- if (func.lines > this.thresholds.functionLength) {
353
- issues.push({
354
- component: component.id,
355
- issue: `Long function: ${func.name} (${func.lines} lines)`,
356
- line: func.startLine,
357
- severity: func.lines > this.thresholds.functionLength * 2 ? 'high' : 'medium',
358
- recommendation: 'Break down into smaller functions',
359
- impact: 'medium',
360
- effort: 'medium'
361
- });
362
- }
363
-
364
- // Check cyclomatic complexity
365
- if (func.complexity > this.thresholds.cyclomaticComplexity) {
366
- issues.push({
367
- component: component.id,
368
- issue: `High complexity: ${func.name} (complexity: ${func.complexity})`,
369
- line: func.startLine,
370
- severity: func.complexity > this.thresholds.cyclomaticComplexity * 1.5 ? 'high' : 'medium',
371
- recommendation: 'Reduce conditional complexity',
372
- impact: 'high',
373
- effort: 'high'
374
- });
375
- }
376
-
377
- // Check nesting depth
378
- if (func.nestingDepth > this.thresholds.nestingDepth) {
379
- issues.push({
380
- component: component.id,
381
- issue: `Deep nesting: ${func.name} (depth: ${func.nestingDepth})`,
382
- line: func.startLine,
383
- severity: 'medium',
384
- recommendation: 'Reduce nesting depth using early returns or guard clauses',
385
- impact: 'medium',
386
- effort: 'medium'
387
- });
388
- }
389
- });
390
-
391
- return issues;
392
- }
393
-
394
- /**
395
- * Analyze imports and requires
396
- */
397
- analyzeImports(content, component) {
398
- const issues = [];
399
- const imports = this.extractImports(content);
400
-
401
- if (imports.length > this.thresholds.importCount) {
402
- issues.push({
403
- component: component.id,
404
- issue: `Too many imports: ${imports.length}`,
405
- severity: 'medium',
406
- recommendation: 'Consider breaking down module or using dynamic imports',
407
- impact: 'low',
408
- effort: 'medium'
409
- });
410
- }
411
-
412
- // Find unused imports (basic heuristic)
413
- const unusedImports = imports.filter(imp => {
414
- const usage = content.split(imp.name).length - 1;
415
- return usage <= 1; // Only appears in import statement
416
- });
417
-
418
- if (unusedImports.length > 0) {
419
- issues.push({
420
- component: component.id,
421
- issue: `Unused imports: ${unusedImports.map(i => i.name).join(', ')}`,
422
- severity: 'low',
423
- recommendation: 'Remove unused imports',
424
- impact: 'low',
425
- effort: 'low'
426
- });
427
- }
428
-
429
- return issues;
430
- }
431
-
432
- /**
433
- * Find dead code (unused functions, variables)
434
- */
435
- async findDeadCode(content, component) {
436
- const issues = [];
437
-
438
- // This is a simplified implementation
439
- // A full implementation would analyze the entire codebase for usage
440
- const functions = this.extractFunctions(content);
441
- const exports = this.extractExports(content);
442
-
443
- // Check for functions that are defined but never called within the file
444
- functions.forEach(func => {
445
- if (!func.name.startsWith('_') && !exports.includes(func.name)) {
446
- const usage = content.split(func.name).length - 1;
447
- if (usage <= 1) { // Only appears in definition
448
- issues.push({
449
- component: component.id,
450
- issue: `Potentially unused function: ${func.name}`,
451
- line: func.startLine,
452
- severity: 'low',
453
- recommendation: 'Remove if truly unused or export if needed elsewhere',
454
- impact: 'low',
455
- effort: 'low'
456
- });
457
- }
458
- }
459
- });
460
-
461
- return issues;
462
- }
463
-
464
- /**
465
- * Extract function information from code
466
- */
467
- extractFunctions(content) {
468
- const functions = [];
469
- const lines = content.split('\n');
470
- const functionRegex = /(?:function\s+(\w+)|(\w+)\s*[:=]\s*(?:async\s+)?function|(?:async\s+)?(\w+)\s*\([^)]*\)\s*(?:=>|{))/g;
471
-
472
- lines.forEach((line, index) => {
473
- const matches = [...line.matchAll(functionRegex)];
474
- matches.forEach(match => {
475
- const name = match[1] || match[2] || match[3] || 'anonymous';
476
-
477
- // Calculate function metrics (simplified)
478
- const funcInfo = {
479
- name,
480
- startLine: index + 1,
481
- lines: this.estimateFunctionLength(lines, index),
482
- complexity: this.estimateComplexity(lines, index),
483
- nestingDepth: this.estimateNestingDepth(lines, index)
484
- };
485
-
486
- functions.push(funcInfo);
487
- });
488
- });
489
-
490
- return functions;
491
- }
492
-
493
- /**
494
- * Extract import information
495
- */
496
- extractImports(content) {
497
- const imports = [];
498
- const importRegex = /(?:import\s+(?:(\w+)|\{([^}]+)\}|.*)\s+from\s+['"`]([^'"`]+)['"`]|const\s+(?:(\w+)|\{([^}]+)\})\s*=\s*require\(['"`]([^'"`]+)['"`]\))/g;
499
-
500
- const matches = [...content.matchAll(importRegex)];
501
- matches.forEach(match => {
502
- const defaultImport = match[1] || match[4];
503
- const namedImports = match[2] || match[5];
504
- const source = match[3] || match[6];
505
-
506
- if (defaultImport) {
507
- imports.push({ name: defaultImport, source, type: 'default' });
508
- }
509
-
510
- if (namedImports) {
511
- namedImports.split(',').forEach(name => {
512
- imports.push({ name: name.trim(), source, type: 'named' });
513
- });
514
- }
515
- });
516
-
517
- return imports;
518
- }
519
-
520
- /**
521
- * Extract export information
522
- */
523
- extractExports(content) {
524
- const exports = [];
525
- const exportRegex = /(?:export\s+(?:default\s+)?(?:function\s+(\w+)|class\s+(\w+)|(?:const|let|var)\s+(\w+))|module\.exports\s*=\s*(\w+))/g;
526
-
527
- const matches = [...content.matchAll(exportRegex)];
528
- matches.forEach(match => {
529
- const name = match[1] || match[2] || match[3] || match[4];
530
- if (name) exports.push(name);
531
- });
532
-
533
- return exports;
534
- }
535
-
536
- /**
537
- * Estimate function length (simplified)
538
- */
539
- estimateFunctionLength(lines, startIndex) {
540
- let braceCount = 0;
541
- let lineCount = 0;
542
- let inFunction = false;
543
-
544
- for (let i = startIndex; i < lines.length; i++) {
545
- const line = lines[i];
546
- lineCount++;
547
-
548
- // Count braces to find function end
549
- for (const char of line) {
550
- if (char === '{') {
551
- braceCount++;
552
- inFunction = true;
553
- } else if (char === '}') {
554
- braceCount--;
555
- if (inFunction && braceCount === 0) {
556
- return lineCount;
557
- }
558
- }
559
- }
560
-
561
- // Safety limit
562
- if (lineCount > 200) break;
563
- }
564
-
565
- return lineCount;
566
- }
567
-
568
- /**
569
- * Estimate cyclomatic complexity (simplified)
570
- */
571
- estimateComplexity(lines, startIndex) {
572
- let complexity = 1; // Base complexity
573
- const complexityKeywords = ['if', 'else', 'while', 'for', 'switch', 'case', 'catch', '&&', '||', '?'];
574
-
575
- const functionLines = lines.slice(startIndex, startIndex + this.estimateFunctionLength(lines, startIndex));
576
-
577
- functionLines.forEach(line => {
578
- complexityKeywords.forEach(keyword => {
579
- const matches = line.match(new RegExp(`\\b${keyword}\\b`, 'g'));
580
- if (matches) {
581
- complexity += matches.length;
582
- }
583
- });
584
- });
585
-
586
- return complexity;
587
- }
588
-
589
- /**
590
- * Estimate nesting depth (simplified)
591
- */
592
- estimateNestingDepth(lines, startIndex) {
593
- let maxDepth = 0;
594
- let currentDepth = 0;
595
-
596
- const functionLines = lines.slice(startIndex, startIndex + this.estimateFunctionLength(lines, startIndex));
597
-
598
- functionLines.forEach(line => {
599
- for (const char of line) {
600
- if (char === '{') {
601
- currentDepth++;
602
- maxDepth = Math.max(maxDepth, currentDepth);
603
- } else if (char === '}') {
604
- currentDepth--;
605
- }
606
- }
607
- });
608
-
609
- return maxDepth;
610
- }
611
-
612
- /**
613
- * Calculate overall performance score
614
- */
615
- calculateOverallScore(analysis) {
616
- let score = 10;
617
- const penalties = {
618
- critical: 2,
619
- high: 1,
620
- medium: 0.5,
621
- low: 0.1
622
- };
623
-
624
- // Apply penalties based on issue severity
625
- [...analysis.bottlenecks, ...analysis.memory_issues, ...analysis.async_opportunities,
626
- ...analysis.code_quality_issues, ...analysis.file_size_issues, ...analysis.complexity_issues]
627
- .forEach(issue => {
628
- score -= penalties[issue.severity] || 0.1;
629
- });
630
-
631
- return Math.max(0, Math.round(score * 10) / 10);
632
- }
633
-
634
- /**
635
- * Count total issues
636
- */
637
- countTotalIssues(analysis) {
638
- return analysis.bottlenecks.length +
639
- analysis.memory_issues.length +
640
- analysis.async_opportunities.length +
641
- analysis.code_quality_issues.length +
642
- analysis.file_size_issues.length +
643
- analysis.complexity_issues.length;
644
- }
645
-
646
- /**
647
- * Calculate issue priorities
648
- */
649
- calculateIssuePriorities(analysis) {
650
- const metrics = analysis.metrics;
651
- const allIssues = [
652
- ...analysis.bottlenecks,
653
- ...analysis.memory_issues,
654
- ...analysis.async_opportunities,
655
- ...analysis.code_quality_issues,
656
- ...analysis.file_size_issues,
657
- ...analysis.complexity_issues
658
- ];
659
-
660
- metrics.critical_issues = allIssues.filter(i => i.severity === 'critical').length;
661
- metrics.high_priority_issues = allIssues.filter(i => i.severity === 'high').length;
662
- metrics.medium_priority_issues = allIssues.filter(i => i.severity === 'medium').length;
663
- metrics.low_priority_issues = allIssues.filter(i => i.severity === 'low').length;
664
-
665
- return metrics;
666
- }
667
-
668
- /**
669
- * Generate performance recommendations
670
- */
671
- generatePerformanceRecommendations(analysis) {
672
- const recommendations = [];
673
-
674
- // Critical issues
675
- if (analysis.metrics.critical_issues > 0) {
676
- recommendations.push({
677
- priority: 'critical',
678
- category: 'immediate_action',
679
- message: `${analysis.metrics.critical_issues} critical performance issues require immediate attention`,
680
- action: 'Fix critical bottlenecks before deployment'
681
- });
682
- }
683
-
684
- // High severity issues
685
- if (analysis.metrics.high_priority_issues > 5) {
686
- recommendations.push({
687
- priority: 'high',
688
- category: 'performance',
689
- message: `${analysis.metrics.high_priority_issues} high-priority performance issues detected`,
690
- action: 'Address synchronous operations and complexity issues'
691
- });
692
- }
693
-
694
- // Memory issues
695
- if (analysis.memory_issues.length > 0) {
696
- recommendations.push({
697
- priority: 'medium',
698
- category: 'memory',
699
- message: `${analysis.memory_issues.length} memory optimization opportunities found`,
700
- action: 'Implement memory-efficient patterns and data structures'
701
- });
702
- }
703
-
704
- // File size issues
705
- if (analysis.file_size_issues.length > 0) {
706
- recommendations.push({
707
- priority: 'medium',
708
- category: 'modularity',
709
- message: `${analysis.file_size_issues.length} files are too large`,
710
- action: 'Break down large files into smaller, focused modules'
711
- });
712
- }
713
-
714
- // Overall score
715
- if (analysis.overall_score < 7) {
716
- recommendations.push({
717
- priority: 'high',
718
- category: 'general',
719
- message: `Overall performance score is ${analysis.overall_score}/10`,
720
- action: 'Comprehensive performance review and optimization needed'
721
- });
722
- }
723
-
724
- return recommendations;
725
- }
726
-
727
- /**
728
- * Check if component should be analyzed
729
- */
730
- shouldAnalyzeComponent(component) {
731
- const analyzableTypes = ['utility', 'task'];
732
- const analyzableExtensions = ['.js', '.mjs', '.ts'];
733
-
734
- if (!analyzableTypes.includes(component.type)) {
735
- return false;
736
- }
737
-
738
- if (component.file_path) {
739
- const ext = path.extname(component.file_path).toLowerCase();
740
- return analyzableExtensions.includes(ext);
741
- }
742
-
743
- return false;
744
- }
745
-
746
- /**
747
- * Format bytes for display
748
- */
749
- formatBytes(bytes) {
750
- if (bytes === 0) return '0 B';
751
- const k = 1024;
752
- const sizes = ['B', 'KB', 'MB', 'GB'];
753
- const i = Math.floor(Math.log(bytes) / Math.log(k));
754
- return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
755
- }
756
- }
757
-
1
+ const fs = require('fs').promises;
2
+ const path = require('path');
3
+ const chalk = require('chalk');
4
+
5
+ /**
6
+ * Performance bottleneck analyzer for AIOS-FULLSTACK framework
7
+ * Identifies performance issues and optimization opportunities
8
+ */
9
+ class PerformanceAnalyzer {
10
+ constructor(options = {}) {
11
+ this.rootPath = options.rootPath || process.cwd();
12
+ this.thresholds = {
13
+ fileSize: 50 * 1024, // 50KB
14
+ functionLength: 50, // lines
15
+ cyclomaticComplexity: 10,
16
+ nestingDepth: 5,
17
+ importCount: 20,
18
+ unusedCode: 0.1 // 10% unused code ratio
19
+ };
20
+ this.performancePatterns = {
21
+ // Sync operations that should be async
22
+ syncOperations: [
23
+ /fs\.readFileSync/g,
24
+ /fs\.writeFileSync/g,
25
+ /fs\.existsSync/g,
26
+ /JSON\.parse\(\s*fs\.readFileSync/g
27
+ ],
28
+ // Memory-intensive patterns
29
+ memoryIssues: [
30
+ /\.map\(\s*.*\.map\(/g, // Nested maps
31
+ /new Array\(\d{4,}\)/g, // Large arrays
32
+ /JSON\.stringify.*JSON\.parse/g, // Unnecessary serialization
33
+ /require\(\s*['"`][^'"`]+\.json['"`]\s*\)/g // Large JSON imports
34
+ ],
35
+ // Performance anti-patterns
36
+ antiPatterns: [
37
+ /console\.log/g, // Console logs in production
38
+ /debugger/g, // Debugger statements
39
+ /setTimeout\(\s*.*,\s*0\s*\)/g, // Unnecessary setTimeout
40
+ /setInterval\(\s*.*,\s*[0-9]{1,2}\s*\)/g // High-frequency intervals
41
+ ],
42
+ // Inefficient loops
43
+ inefficientLoops: [
44
+ /for\s*\(\s*.*\.length\s*;/g, // Length calculated in loop condition
45
+ /while\s*\(\s*true\s*\)/g, // Infinite loops
46
+ /forEach.*forEach/g // Nested forEach
47
+ ]
48
+ };
49
+ }
50
+
51
+ /**
52
+ * Analyze performance across all components
53
+ */
54
+ async analyzePerformance(components) {
55
+ const analysis = {
56
+ timestamp: new Date().toISOString(),
57
+ overall_score: 0,
58
+ bottlenecks: [],
59
+ optimization_opportunities: [],
60
+ memory_issues: [],
61
+ async_opportunities: [],
62
+ code_quality_issues: [],
63
+ file_size_issues: [],
64
+ complexity_issues: [],
65
+ recommendations: [],
66
+ metrics: {
67
+ total_files_analyzed: 0,
68
+ total_issues_found: 0,
69
+ critical_issues: 0,
70
+ high_priority_issues: 0,
71
+ medium_priority_issues: 0,
72
+ low_priority_issues: 0
73
+ }
74
+ };
75
+
76
+ try {
77
+ console.log(chalk.blue('🔍 Analyzing performance bottlenecks...'));
78
+
79
+ // Analyze each component
80
+ for (const component of components) {
81
+ const componentAnalysis = await this.analyzeComponentPerformance(component);
82
+
83
+ // Aggregate results
84
+ analysis.bottlenecks.push(...componentAnalysis.bottlenecks);
85
+ analysis.optimization_opportunities.push(...componentAnalysis.optimizations);
86
+ analysis.memory_issues.push(...componentAnalysis.memory_issues);
87
+ analysis.async_opportunities.push(...componentAnalysis.async_opportunities);
88
+ analysis.code_quality_issues.push(...componentAnalysis.quality_issues);
89
+ analysis.file_size_issues.push(...componentAnalysis.file_size_issues);
90
+ analysis.complexity_issues.push(...componentAnalysis.complexity_issues);
91
+
92
+ analysis.metrics.total_files_analyzed++;
93
+ }
94
+
95
+ // Calculate overall metrics
96
+ analysis.overall_score = this.calculateOverallScore(analysis);
97
+ analysis.metrics.total_issues_found = this.countTotalIssues(analysis);
98
+ analysis.metrics = this.calculateIssuePriorities(analysis);
99
+ analysis.recommendations = this.generatePerformanceRecommendations(analysis);
100
+
101
+ console.log(chalk.green(`✅ Performance analysis completed`));
102
+ console.log(chalk.gray(` Files analyzed: ${analysis.metrics.total_files_analyzed}`));
103
+ console.log(chalk.gray(` Issues found: ${analysis.metrics.total_issues_found}`));
104
+ console.log(chalk.gray(` Overall score: ${analysis.overall_score}/10`));
105
+
106
+ return analysis;
107
+
108
+ } catch (error) {
109
+ console.error(chalk.red(`Performance analysis failed: ${error.message}`));
110
+ throw error;
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Analyze performance for a single component
116
+ */
117
+ async analyzeComponentPerformance(component) {
118
+ const analysis = {
119
+ component_id: component.id,
120
+ component_type: component.type,
121
+ bottlenecks: [],
122
+ optimizations: [],
123
+ memory_issues: [],
124
+ async_opportunities: [],
125
+ quality_issues: [],
126
+ file_size_issues: [],
127
+ complexity_issues: []
128
+ };
129
+
130
+ try {
131
+ // Only analyze JavaScript files and executable components
132
+ if (!this.shouldAnalyzeComponent(component)) {
133
+ return analysis;
134
+ }
135
+
136
+ const filePath = path.join(this.rootPath, component.file_path);
137
+ const content = await fs.readFile(filePath, 'utf-8');
138
+ const stats = await fs.stat(filePath);
139
+
140
+ // File size analysis
141
+ if (stats.size > this.thresholds.fileSize) {
142
+ analysis.file_size_issues.push({
143
+ component: component.id,
144
+ issue: `Large file size: ${this.formatBytes(stats.size)}`,
145
+ severity: stats.size > this.thresholds.fileSize * 2 ? 'high' : 'medium',
146
+ recommendation: 'Consider breaking down into smaller modules',
147
+ impact: 'high',
148
+ effort: 'medium'
149
+ });
150
+ }
151
+
152
+ // Synchronous operations analysis
153
+ const syncIssues = this.findSyncOperations(content, component);
154
+ analysis.async_opportunities.push(...syncIssues);
155
+
156
+ // Memory usage analysis
157
+ const memoryIssues = this.findMemoryIssues(content, component);
158
+ analysis.memory_issues.push(...memoryIssues);
159
+
160
+ // Performance anti-patterns
161
+ const antiPatterns = this.findAntiPatterns(content, component);
162
+ analysis.quality_issues.push(...antiPatterns);
163
+
164
+ // Loop efficiency analysis
165
+ const loopIssues = this.findLoopIssues(content, component);
166
+ analysis.bottlenecks.push(...loopIssues);
167
+
168
+ // Function complexity analysis
169
+ const complexityIssues = this.analyzeComplexity(content, component);
170
+ analysis.complexity_issues.push(...complexityIssues);
171
+
172
+ // Import/require analysis
173
+ const importIssues = this.analyzeImports(content, component);
174
+ analysis.optimizations.push(...importIssues);
175
+
176
+ // Dead code analysis
177
+ const deadCodeIssues = await this.findDeadCode(content, component);
178
+ analysis.optimizations.push(...deadCodeIssues);
179
+
180
+ } catch (error) {
181
+ console.warn(chalk.yellow(`Failed to analyze performance for ${component.id}: ${error.message}`));
182
+ }
183
+
184
+ return analysis;
185
+ }
186
+
187
+ /**
188
+ * Find synchronous operations that should be async
189
+ */
190
+ findSyncOperations(content, component) {
191
+ const issues = [];
192
+ const lines = content.split('\n');
193
+
194
+ this.performancePatterns.syncOperations.forEach(pattern => {
195
+ lines.forEach((line, index) => {
196
+ const matches = line.match(pattern);
197
+ if (matches) {
198
+ matches.forEach(match => {
199
+ issues.push({
200
+ component: component.id,
201
+ issue: `Synchronous operation: ${match}`,
202
+ line: index + 1,
203
+ context: line.trim(),
204
+ severity: 'high',
205
+ recommendation: 'Convert to async equivalent',
206
+ impact: 'high',
207
+ effort: 'low'
208
+ });
209
+ });
210
+ }
211
+ });
212
+ });
213
+
214
+ return issues;
215
+ }
216
+
217
+ /**
218
+ * Find memory-intensive patterns
219
+ */
220
+ findMemoryIssues(content, component) {
221
+ const issues = [];
222
+ const lines = content.split('\n');
223
+
224
+ this.performancePatterns.memoryIssues.forEach(pattern => {
225
+ lines.forEach((line, index) => {
226
+ const matches = line.match(pattern);
227
+ if (matches) {
228
+ matches.forEach(match => {
229
+ let severity = 'medium';
230
+ let recommendation = 'Optimize memory usage';
231
+
232
+ if (match.includes('new Array')) {
233
+ severity = 'high';
234
+ recommendation = 'Use array literals or streaming for large datasets';
235
+ } else if (match.includes('JSON.stringify.*JSON.parse')) {
236
+ recommendation = 'Use direct object assignment or deep clone utilities';
237
+ } else if (match.includes('.map(.*map(')) {
238
+ recommendation = 'Combine operations or use more efficient iteration';
239
+ }
240
+
241
+ issues.push({
242
+ component: component.id,
243
+ issue: `Memory-intensive pattern: ${match}`,
244
+ line: index + 1,
245
+ context: line.trim(),
246
+ severity,
247
+ recommendation,
248
+ impact: 'medium',
249
+ effort: 'medium'
250
+ });
251
+ });
252
+ }
253
+ });
254
+ });
255
+
256
+ return issues;
257
+ }
258
+
259
+ /**
260
+ * Find performance anti-patterns
261
+ */
262
+ findAntiPatterns(content, component) {
263
+ const issues = [];
264
+ const lines = content.split('\n');
265
+
266
+ this.performancePatterns.antiPatterns.forEach(pattern => {
267
+ lines.forEach((line, index) => {
268
+ const matches = line.match(pattern);
269
+ if (matches) {
270
+ matches.forEach(match => {
271
+ let severity = 'low';
272
+ let recommendation = 'Remove or optimize';
273
+
274
+ if (match.includes('console.log')) {
275
+ recommendation = 'Remove console.log statements from production code';
276
+ } else if (match.includes('debugger')) {
277
+ severity = 'medium';
278
+ recommendation = 'Remove debugger statements';
279
+ } else if (match.includes('setTimeout')) {
280
+ recommendation = 'Use proper async/await or promises instead';
281
+ }
282
+
283
+ issues.push({
284
+ component: component.id,
285
+ issue: `Performance anti-pattern: ${match}`,
286
+ line: index + 1,
287
+ context: line.trim(),
288
+ severity,
289
+ recommendation,
290
+ impact: 'low',
291
+ effort: 'low'
292
+ });
293
+ });
294
+ }
295
+ });
296
+ });
297
+
298
+ return issues;
299
+ }
300
+
301
+ /**
302
+ * Find inefficient loop patterns
303
+ */
304
+ findLoopIssues(content, component) {
305
+ const issues = [];
306
+ const lines = content.split('\n');
307
+
308
+ this.performancePatterns.inefficientLoops.forEach(pattern => {
309
+ lines.forEach((line, index) => {
310
+ const matches = line.match(pattern);
311
+ if (matches) {
312
+ matches.forEach(match => {
313
+ let severity = 'medium';
314
+ let recommendation = 'Optimize loop structure';
315
+
316
+ if (match.includes('.length')) {
317
+ recommendation = 'Cache array length in variable before loop';
318
+ } else if (match.includes('while(true)')) {
319
+ severity = 'high';
320
+ recommendation = 'Add proper exit condition to prevent infinite loops';
321
+ } else if (match.includes('forEach.*forEach')) {
322
+ recommendation = 'Consider using nested for loops or array methods like flatMap';
323
+ }
324
+
325
+ issues.push({
326
+ component: component.id,
327
+ issue: `Inefficient loop: ${match}`,
328
+ line: index + 1,
329
+ context: line.trim(),
330
+ severity,
331
+ recommendation,
332
+ impact: 'medium',
333
+ effort: 'low'
334
+ });
335
+ });
336
+ }
337
+ });
338
+ });
339
+
340
+ return issues;
341
+ }
342
+
343
+ /**
344
+ * Analyze function complexity
345
+ */
346
+ analyzeComplexity(content, component) {
347
+ const issues = [];
348
+ const functions = this.extractFunctions(content);
349
+
350
+ functions.forEach(func => {
351
+ // Check function length
352
+ if (func.lines > this.thresholds.functionLength) {
353
+ issues.push({
354
+ component: component.id,
355
+ issue: `Long function: ${func.name} (${func.lines} lines)`,
356
+ line: func.startLine,
357
+ severity: func.lines > this.thresholds.functionLength * 2 ? 'high' : 'medium',
358
+ recommendation: 'Break down into smaller functions',
359
+ impact: 'medium',
360
+ effort: 'medium'
361
+ });
362
+ }
363
+
364
+ // Check cyclomatic complexity
365
+ if (func.complexity > this.thresholds.cyclomaticComplexity) {
366
+ issues.push({
367
+ component: component.id,
368
+ issue: `High complexity: ${func.name} (complexity: ${func.complexity})`,
369
+ line: func.startLine,
370
+ severity: func.complexity > this.thresholds.cyclomaticComplexity * 1.5 ? 'high' : 'medium',
371
+ recommendation: 'Reduce conditional complexity',
372
+ impact: 'high',
373
+ effort: 'high'
374
+ });
375
+ }
376
+
377
+ // Check nesting depth
378
+ if (func.nestingDepth > this.thresholds.nestingDepth) {
379
+ issues.push({
380
+ component: component.id,
381
+ issue: `Deep nesting: ${func.name} (depth: ${func.nestingDepth})`,
382
+ line: func.startLine,
383
+ severity: 'medium',
384
+ recommendation: 'Reduce nesting depth using early returns or guard clauses',
385
+ impact: 'medium',
386
+ effort: 'medium'
387
+ });
388
+ }
389
+ });
390
+
391
+ return issues;
392
+ }
393
+
394
+ /**
395
+ * Analyze imports and requires
396
+ */
397
+ analyzeImports(content, component) {
398
+ const issues = [];
399
+ const imports = this.extractImports(content);
400
+
401
+ if (imports.length > this.thresholds.importCount) {
402
+ issues.push({
403
+ component: component.id,
404
+ issue: `Too many imports: ${imports.length}`,
405
+ severity: 'medium',
406
+ recommendation: 'Consider breaking down module or using dynamic imports',
407
+ impact: 'low',
408
+ effort: 'medium'
409
+ });
410
+ }
411
+
412
+ // Find unused imports (basic heuristic)
413
+ const unusedImports = imports.filter(imp => {
414
+ const usage = content.split(imp.name).length - 1;
415
+ return usage <= 1; // Only appears in import statement
416
+ });
417
+
418
+ if (unusedImports.length > 0) {
419
+ issues.push({
420
+ component: component.id,
421
+ issue: `Unused imports: ${unusedImports.map(i => i.name).join(', ')}`,
422
+ severity: 'low',
423
+ recommendation: 'Remove unused imports',
424
+ impact: 'low',
425
+ effort: 'low'
426
+ });
427
+ }
428
+
429
+ return issues;
430
+ }
431
+
432
+ /**
433
+ * Find dead code (unused functions, variables)
434
+ */
435
+ async findDeadCode(content, component) {
436
+ const issues = [];
437
+
438
+ // This is a simplified implementation
439
+ // A full implementation would analyze the entire codebase for usage
440
+ const functions = this.extractFunctions(content);
441
+ const exports = this.extractExports(content);
442
+
443
+ // Check for functions that are defined but never called within the file
444
+ functions.forEach(func => {
445
+ if (!func.name.startsWith('_') && !exports.includes(func.name)) {
446
+ const usage = content.split(func.name).length - 1;
447
+ if (usage <= 1) { // Only appears in definition
448
+ issues.push({
449
+ component: component.id,
450
+ issue: `Potentially unused function: ${func.name}`,
451
+ line: func.startLine,
452
+ severity: 'low',
453
+ recommendation: 'Remove if truly unused or export if needed elsewhere',
454
+ impact: 'low',
455
+ effort: 'low'
456
+ });
457
+ }
458
+ }
459
+ });
460
+
461
+ return issues;
462
+ }
463
+
464
+ /**
465
+ * Extract function information from code
466
+ */
467
+ extractFunctions(content) {
468
+ const functions = [];
469
+ const lines = content.split('\n');
470
+ const functionRegex = /(?:function\s+(\w+)|(\w+)\s*[:=]\s*(?:async\s+)?function|(?:async\s+)?(\w+)\s*\([^)]*\)\s*(?:=>|{))/g;
471
+
472
+ lines.forEach((line, index) => {
473
+ const matches = [...line.matchAll(functionRegex)];
474
+ matches.forEach(match => {
475
+ const name = match[1] || match[2] || match[3] || 'anonymous';
476
+
477
+ // Calculate function metrics (simplified)
478
+ const funcInfo = {
479
+ name,
480
+ startLine: index + 1,
481
+ lines: this.estimateFunctionLength(lines, index),
482
+ complexity: this.estimateComplexity(lines, index),
483
+ nestingDepth: this.estimateNestingDepth(lines, index)
484
+ };
485
+
486
+ functions.push(funcInfo);
487
+ });
488
+ });
489
+
490
+ return functions;
491
+ }
492
+
493
+ /**
494
+ * Extract import information
495
+ */
496
+ extractImports(content) {
497
+ const imports = [];
498
+ const importRegex = /(?:import\s+(?:(\w+)|\{([^}]+)\}|.*)\s+from\s+['"`]([^'"`]+)['"`]|const\s+(?:(\w+)|\{([^}]+)\})\s*=\s*require\(['"`]([^'"`]+)['"`]\))/g;
499
+
500
+ const matches = [...content.matchAll(importRegex)];
501
+ matches.forEach(match => {
502
+ const defaultImport = match[1] || match[4];
503
+ const namedImports = match[2] || match[5];
504
+ const source = match[3] || match[6];
505
+
506
+ if (defaultImport) {
507
+ imports.push({ name: defaultImport, source, type: 'default' });
508
+ }
509
+
510
+ if (namedImports) {
511
+ namedImports.split(',').forEach(name => {
512
+ imports.push({ name: name.trim(), source, type: 'named' });
513
+ });
514
+ }
515
+ });
516
+
517
+ return imports;
518
+ }
519
+
520
+ /**
521
+ * Extract export information
522
+ */
523
+ extractExports(content) {
524
+ const exports = [];
525
+ const exportRegex = /(?:export\s+(?:default\s+)?(?:function\s+(\w+)|class\s+(\w+)|(?:const|let|var)\s+(\w+))|module\.exports\s*=\s*(\w+))/g;
526
+
527
+ const matches = [...content.matchAll(exportRegex)];
528
+ matches.forEach(match => {
529
+ const name = match[1] || match[2] || match[3] || match[4];
530
+ if (name) exports.push(name);
531
+ });
532
+
533
+ return exports;
534
+ }
535
+
536
+ /**
537
+ * Estimate function length (simplified)
538
+ */
539
+ estimateFunctionLength(lines, startIndex) {
540
+ let braceCount = 0;
541
+ let lineCount = 0;
542
+ let inFunction = false;
543
+
544
+ for (let i = startIndex; i < lines.length; i++) {
545
+ const line = lines[i];
546
+ lineCount++;
547
+
548
+ // Count braces to find function end
549
+ for (const char of line) {
550
+ if (char === '{') {
551
+ braceCount++;
552
+ inFunction = true;
553
+ } else if (char === '}') {
554
+ braceCount--;
555
+ if (inFunction && braceCount === 0) {
556
+ return lineCount;
557
+ }
558
+ }
559
+ }
560
+
561
+ // Safety limit
562
+ if (lineCount > 200) break;
563
+ }
564
+
565
+ return lineCount;
566
+ }
567
+
568
+ /**
569
+ * Estimate cyclomatic complexity (simplified)
570
+ */
571
+ estimateComplexity(lines, startIndex) {
572
+ let complexity = 1; // Base complexity
573
+ const complexityKeywords = ['if', 'else', 'while', 'for', 'switch', 'case', 'catch', '&&', '||', '?'];
574
+
575
+ const functionLines = lines.slice(startIndex, startIndex + this.estimateFunctionLength(lines, startIndex));
576
+
577
+ functionLines.forEach(line => {
578
+ complexityKeywords.forEach(keyword => {
579
+ const matches = line.match(new RegExp(`\\b${keyword}\\b`, 'g'));
580
+ if (matches) {
581
+ complexity += matches.length;
582
+ }
583
+ });
584
+ });
585
+
586
+ return complexity;
587
+ }
588
+
589
+ /**
590
+ * Estimate nesting depth (simplified)
591
+ */
592
+ estimateNestingDepth(lines, startIndex) {
593
+ let maxDepth = 0;
594
+ let currentDepth = 0;
595
+
596
+ const functionLines = lines.slice(startIndex, startIndex + this.estimateFunctionLength(lines, startIndex));
597
+
598
+ functionLines.forEach(line => {
599
+ for (const char of line) {
600
+ if (char === '{') {
601
+ currentDepth++;
602
+ maxDepth = Math.max(maxDepth, currentDepth);
603
+ } else if (char === '}') {
604
+ currentDepth--;
605
+ }
606
+ }
607
+ });
608
+
609
+ return maxDepth;
610
+ }
611
+
612
+ /**
613
+ * Calculate overall performance score
614
+ */
615
+ calculateOverallScore(analysis) {
616
+ let score = 10;
617
+ const penalties = {
618
+ critical: 2,
619
+ high: 1,
620
+ medium: 0.5,
621
+ low: 0.1
622
+ };
623
+
624
+ // Apply penalties based on issue severity
625
+ [...analysis.bottlenecks, ...analysis.memory_issues, ...analysis.async_opportunities,
626
+ ...analysis.code_quality_issues, ...analysis.file_size_issues, ...analysis.complexity_issues]
627
+ .forEach(issue => {
628
+ score -= penalties[issue.severity] || 0.1;
629
+ });
630
+
631
+ return Math.max(0, Math.round(score * 10) / 10);
632
+ }
633
+
634
+ /**
635
+ * Count total issues
636
+ */
637
+ countTotalIssues(analysis) {
638
+ return analysis.bottlenecks.length +
639
+ analysis.memory_issues.length +
640
+ analysis.async_opportunities.length +
641
+ analysis.code_quality_issues.length +
642
+ analysis.file_size_issues.length +
643
+ analysis.complexity_issues.length;
644
+ }
645
+
646
+ /**
647
+ * Calculate issue priorities
648
+ */
649
+ calculateIssuePriorities(analysis) {
650
+ const metrics = analysis.metrics;
651
+ const allIssues = [
652
+ ...analysis.bottlenecks,
653
+ ...analysis.memory_issues,
654
+ ...analysis.async_opportunities,
655
+ ...analysis.code_quality_issues,
656
+ ...analysis.file_size_issues,
657
+ ...analysis.complexity_issues
658
+ ];
659
+
660
+ metrics.critical_issues = allIssues.filter(i => i.severity === 'critical').length;
661
+ metrics.high_priority_issues = allIssues.filter(i => i.severity === 'high').length;
662
+ metrics.medium_priority_issues = allIssues.filter(i => i.severity === 'medium').length;
663
+ metrics.low_priority_issues = allIssues.filter(i => i.severity === 'low').length;
664
+
665
+ return metrics;
666
+ }
667
+
668
+ /**
669
+ * Generate performance recommendations
670
+ */
671
+ generatePerformanceRecommendations(analysis) {
672
+ const recommendations = [];
673
+
674
+ // Critical issues
675
+ if (analysis.metrics.critical_issues > 0) {
676
+ recommendations.push({
677
+ priority: 'critical',
678
+ category: 'immediate_action',
679
+ message: `${analysis.metrics.critical_issues} critical performance issues require immediate attention`,
680
+ action: 'Fix critical bottlenecks before deployment'
681
+ });
682
+ }
683
+
684
+ // High severity issues
685
+ if (analysis.metrics.high_priority_issues > 5) {
686
+ recommendations.push({
687
+ priority: 'high',
688
+ category: 'performance',
689
+ message: `${analysis.metrics.high_priority_issues} high-priority performance issues detected`,
690
+ action: 'Address synchronous operations and complexity issues'
691
+ });
692
+ }
693
+
694
+ // Memory issues
695
+ if (analysis.memory_issues.length > 0) {
696
+ recommendations.push({
697
+ priority: 'medium',
698
+ category: 'memory',
699
+ message: `${analysis.memory_issues.length} memory optimization opportunities found`,
700
+ action: 'Implement memory-efficient patterns and data structures'
701
+ });
702
+ }
703
+
704
+ // File size issues
705
+ if (analysis.file_size_issues.length > 0) {
706
+ recommendations.push({
707
+ priority: 'medium',
708
+ category: 'modularity',
709
+ message: `${analysis.file_size_issues.length} files are too large`,
710
+ action: 'Break down large files into smaller, focused modules'
711
+ });
712
+ }
713
+
714
+ // Overall score
715
+ if (analysis.overall_score < 7) {
716
+ recommendations.push({
717
+ priority: 'high',
718
+ category: 'general',
719
+ message: `Overall performance score is ${analysis.overall_score}/10`,
720
+ action: 'Comprehensive performance review and optimization needed'
721
+ });
722
+ }
723
+
724
+ return recommendations;
725
+ }
726
+
727
+ /**
728
+ * Check if component should be analyzed
729
+ */
730
+ shouldAnalyzeComponent(component) {
731
+ const analyzableTypes = ['utility', 'task'];
732
+ const analyzableExtensions = ['.js', '.mjs', '.ts'];
733
+
734
+ if (!analyzableTypes.includes(component.type)) {
735
+ return false;
736
+ }
737
+
738
+ if (component.file_path) {
739
+ const ext = path.extname(component.file_path).toLowerCase();
740
+ return analyzableExtensions.includes(ext);
741
+ }
742
+
743
+ return false;
744
+ }
745
+
746
+ /**
747
+ * Format bytes for display
748
+ */
749
+ formatBytes(bytes) {
750
+ if (bytes === 0) return '0 B';
751
+ const k = 1024;
752
+ const sizes = ['B', 'KB', 'MB', 'GB'];
753
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
754
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
755
+ }
756
+ }
757
+
758
758
  module.exports = PerformanceAnalyzer;