aidp 0.5.0 → 0.8.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 (122) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +128 -151
  3. data/bin/aidp +1 -1
  4. data/lib/aidp/analysis/kb_inspector.rb +471 -0
  5. data/lib/aidp/analysis/seams.rb +159 -0
  6. data/lib/aidp/analysis/tree_sitter_grammar_loader.rb +480 -0
  7. data/lib/aidp/analysis/tree_sitter_scan.rb +686 -0
  8. data/lib/aidp/analyze/error_handler.rb +2 -78
  9. data/lib/aidp/analyze/json_file_storage.rb +292 -0
  10. data/lib/aidp/analyze/progress.rb +12 -0
  11. data/lib/aidp/analyze/progress_visualizer.rb +12 -17
  12. data/lib/aidp/analyze/ruby_maat_integration.rb +13 -31
  13. data/lib/aidp/analyze/runner.rb +256 -87
  14. data/lib/aidp/analyze/steps.rb +6 -0
  15. data/lib/aidp/cli/jobs_command.rb +103 -435
  16. data/lib/aidp/cli.rb +317 -191
  17. data/lib/aidp/config.rb +298 -10
  18. data/lib/aidp/debug_logger.rb +195 -0
  19. data/lib/aidp/debug_mixin.rb +187 -0
  20. data/lib/aidp/execute/progress.rb +9 -0
  21. data/lib/aidp/execute/runner.rb +221 -40
  22. data/lib/aidp/execute/steps.rb +17 -7
  23. data/lib/aidp/execute/workflow_selector.rb +211 -0
  24. data/lib/aidp/harness/completion_checker.rb +268 -0
  25. data/lib/aidp/harness/condition_detector.rb +1526 -0
  26. data/lib/aidp/harness/config_loader.rb +373 -0
  27. data/lib/aidp/harness/config_manager.rb +382 -0
  28. data/lib/aidp/harness/config_schema.rb +1006 -0
  29. data/lib/aidp/harness/config_validator.rb +355 -0
  30. data/lib/aidp/harness/configuration.rb +477 -0
  31. data/lib/aidp/harness/enhanced_runner.rb +494 -0
  32. data/lib/aidp/harness/error_handler.rb +616 -0
  33. data/lib/aidp/harness/provider_config.rb +423 -0
  34. data/lib/aidp/harness/provider_factory.rb +306 -0
  35. data/lib/aidp/harness/provider_manager.rb +1269 -0
  36. data/lib/aidp/harness/provider_type_checker.rb +88 -0
  37. data/lib/aidp/harness/runner.rb +411 -0
  38. data/lib/aidp/harness/state/errors.rb +28 -0
  39. data/lib/aidp/harness/state/metrics.rb +219 -0
  40. data/lib/aidp/harness/state/persistence.rb +128 -0
  41. data/lib/aidp/harness/state/provider_state.rb +132 -0
  42. data/lib/aidp/harness/state/ui_state.rb +68 -0
  43. data/lib/aidp/harness/state/workflow_state.rb +123 -0
  44. data/lib/aidp/harness/state_manager.rb +586 -0
  45. data/lib/aidp/harness/status_display.rb +888 -0
  46. data/lib/aidp/harness/ui/base.rb +16 -0
  47. data/lib/aidp/harness/ui/enhanced_tui.rb +545 -0
  48. data/lib/aidp/harness/ui/enhanced_workflow_selector.rb +252 -0
  49. data/lib/aidp/harness/ui/error_handler.rb +132 -0
  50. data/lib/aidp/harness/ui/frame_manager.rb +361 -0
  51. data/lib/aidp/harness/ui/job_monitor.rb +500 -0
  52. data/lib/aidp/harness/ui/navigation/main_menu.rb +311 -0
  53. data/lib/aidp/harness/ui/navigation/menu_formatter.rb +120 -0
  54. data/lib/aidp/harness/ui/navigation/menu_item.rb +142 -0
  55. data/lib/aidp/harness/ui/navigation/menu_state.rb +139 -0
  56. data/lib/aidp/harness/ui/navigation/submenu.rb +202 -0
  57. data/lib/aidp/harness/ui/navigation/workflow_selector.rb +176 -0
  58. data/lib/aidp/harness/ui/progress_display.rb +280 -0
  59. data/lib/aidp/harness/ui/question_collector.rb +141 -0
  60. data/lib/aidp/harness/ui/spinner_group.rb +184 -0
  61. data/lib/aidp/harness/ui/spinner_helper.rb +152 -0
  62. data/lib/aidp/harness/ui/status_manager.rb +312 -0
  63. data/lib/aidp/harness/ui/status_widget.rb +280 -0
  64. data/lib/aidp/harness/ui/workflow_controller.rb +312 -0
  65. data/lib/aidp/harness/user_interface.rb +2381 -0
  66. data/lib/aidp/provider_manager.rb +131 -7
  67. data/lib/aidp/providers/anthropic.rb +28 -109
  68. data/lib/aidp/providers/base.rb +170 -0
  69. data/lib/aidp/providers/cursor.rb +52 -183
  70. data/lib/aidp/providers/gemini.rb +24 -109
  71. data/lib/aidp/providers/macos_ui.rb +99 -5
  72. data/lib/aidp/providers/opencode.rb +194 -0
  73. data/lib/aidp/storage/csv_storage.rb +172 -0
  74. data/lib/aidp/storage/file_manager.rb +214 -0
  75. data/lib/aidp/storage/json_storage.rb +140 -0
  76. data/lib/aidp/version.rb +1 -1
  77. data/lib/aidp.rb +56 -35
  78. data/templates/ANALYZE/06a_tree_sitter_scan.md +217 -0
  79. data/templates/COMMON/AGENT_BASE.md +11 -0
  80. data/templates/EXECUTE/00_PRD.md +4 -4
  81. data/templates/EXECUTE/02_ARCHITECTURE.md +5 -4
  82. data/templates/EXECUTE/07_TEST_PLAN.md +4 -1
  83. data/templates/EXECUTE/08_TASKS.md +4 -4
  84. data/templates/EXECUTE/10_IMPLEMENTATION_AGENT.md +4 -4
  85. data/templates/README.md +279 -0
  86. data/templates/aidp-development.yml.example +373 -0
  87. data/templates/aidp-minimal.yml.example +48 -0
  88. data/templates/aidp-production.yml.example +475 -0
  89. data/templates/aidp.yml.example +598 -0
  90. metadata +106 -64
  91. data/lib/aidp/analyze/agent_personas.rb +0 -71
  92. data/lib/aidp/analyze/agent_tool_executor.rb +0 -445
  93. data/lib/aidp/analyze/data_retention_manager.rb +0 -426
  94. data/lib/aidp/analyze/database.rb +0 -260
  95. data/lib/aidp/analyze/dependencies.rb +0 -335
  96. data/lib/aidp/analyze/export_manager.rb +0 -425
  97. data/lib/aidp/analyze/focus_guidance.rb +0 -517
  98. data/lib/aidp/analyze/incremental_analyzer.rb +0 -543
  99. data/lib/aidp/analyze/language_analysis_strategies.rb +0 -897
  100. data/lib/aidp/analyze/large_analysis_progress.rb +0 -504
  101. data/lib/aidp/analyze/memory_manager.rb +0 -365
  102. data/lib/aidp/analyze/metrics_storage.rb +0 -336
  103. data/lib/aidp/analyze/parallel_processor.rb +0 -460
  104. data/lib/aidp/analyze/performance_optimizer.rb +0 -694
  105. data/lib/aidp/analyze/repository_chunker.rb +0 -704
  106. data/lib/aidp/analyze/static_analysis_detector.rb +0 -577
  107. data/lib/aidp/analyze/storage.rb +0 -662
  108. data/lib/aidp/analyze/tool_configuration.rb +0 -456
  109. data/lib/aidp/analyze/tool_modernization.rb +0 -750
  110. data/lib/aidp/database/pg_adapter.rb +0 -148
  111. data/lib/aidp/database_config.rb +0 -69
  112. data/lib/aidp/database_connection.rb +0 -72
  113. data/lib/aidp/database_migration.rb +0 -158
  114. data/lib/aidp/job_manager.rb +0 -41
  115. data/lib/aidp/jobs/base_job.rb +0 -47
  116. data/lib/aidp/jobs/provider_execution_job.rb +0 -96
  117. data/lib/aidp/project_detector.rb +0 -117
  118. data/lib/aidp/providers/agent_supervisor.rb +0 -348
  119. data/lib/aidp/providers/supervised_base.rb +0 -317
  120. data/lib/aidp/providers/supervised_cursor.rb +0 -22
  121. data/lib/aidp/sync.rb +0 -13
  122. data/lib/aidp/workspace.rb +0 -19
@@ -1,897 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Aidp
4
- class LanguageAnalysisStrategies
5
- # Define language-specific analysis strategies
6
- LANGUAGE_STRATEGIES = {
7
- "ruby" => {
8
- "analysis_phases" => [
9
- {
10
- phase: 1,
11
- name: "Code Style and Quality",
12
- tools: %w[rubocop reek],
13
- focus_areas: ["style violations", "code smells", "complexity metrics"],
14
- priority: "high"
15
- },
16
- {
17
- phase: 2,
18
- name: "Security Analysis",
19
- tools: %w[brakeman bundler-audit],
20
- focus_areas: ["security vulnerabilities", "dependency vulnerabilities"],
21
- priority: "high"
22
- },
23
- {
24
- phase: 3,
25
- name: "Performance Analysis",
26
- tools: %w[fasterer ruby-prof],
27
- focus_areas: ["performance bottlenecks", "memory usage"],
28
- priority: "medium"
29
- },
30
- {
31
- phase: 4,
32
- name: "Test Coverage",
33
- tools: %w[simplecov rspec],
34
- focus_areas: ["test coverage", "test quality"],
35
- priority: "medium"
36
- }
37
- ],
38
- "code_patterns" => {
39
- "complex_methods" => {
40
- pattern: "methods with high cyclomatic complexity",
41
- detection: "rubocop --only Metrics/CyclomaticComplexity",
42
- threshold: 10
43
- },
44
- "long_methods" => {
45
- pattern: "methods with excessive lines",
46
- detection: "rubocop --only Metrics/MethodLength",
47
- threshold: 20
48
- },
49
- "duplicate_code" => {
50
- pattern: "code duplication",
51
- detection: "reek --detect DuplicateMethodCall",
52
- threshold: 3
53
- },
54
- "security_issues" => {
55
- pattern: "SQL injection, XSS, CSRF vulnerabilities",
56
- detection: "brakeman --quiet --format json",
57
- threshold: 0
58
- }
59
- },
60
- "refactoring_priorities" => [
61
- "Extract complex methods",
62
- "Reduce method length",
63
- "Eliminate code duplication",
64
- "Improve naming conventions",
65
- "Add missing tests"
66
- ]
67
- },
68
- "javascript" => {
69
- "analysis_phases" => [
70
- {
71
- phase: 1,
72
- name: "Code Quality and Style",
73
- tools: %w[eslint prettier],
74
- focus_areas: ["linting errors", "code formatting", "best practices"],
75
- priority: "high"
76
- },
77
- {
78
- phase: 2,
79
- name: "Security Analysis",
80
- tools: %w[npm-audit eslint-plugin-security],
81
- focus_areas: ["dependency vulnerabilities", "security anti-patterns"],
82
- priority: "high"
83
- },
84
- {
85
- phase: 3,
86
- name: "Type Safety",
87
- tools: %w[typescript flow],
88
- focus_areas: ["type errors", "type coverage"],
89
- priority: "medium"
90
- },
91
- {
92
- phase: 4,
93
- name: "Performance Analysis",
94
- tools: %w[webpack-bundle-analyzer lighthouse],
95
- focus_areas: ["bundle size", "performance metrics"],
96
- priority: "medium"
97
- }
98
- ],
99
- "code_patterns" => {
100
- "callback_hell" => {
101
- pattern: "nested callbacks",
102
- detection: 'eslint --rule "callback-return: error"',
103
- threshold: 3
104
- },
105
- "memory_leaks" => {
106
- pattern: "event listeners not removed",
107
- detection: 'eslint --rule "no-unused-vars: error"',
108
- threshold: 0
109
- },
110
- "async_issues" => {
111
- pattern: "unhandled promises",
112
- detection: 'eslint --rule "no-floating-promises: error"',
113
- threshold: 0
114
- },
115
- "security_vulnerabilities" => {
116
- pattern: "XSS, CSRF, injection vulnerabilities",
117
- detection: "eslint-plugin-security",
118
- threshold: 0
119
- }
120
- },
121
- "refactoring_priorities" => [
122
- "Convert callbacks to async/await",
123
- "Add proper error handling",
124
- "Implement proper type safety",
125
- "Optimize bundle size",
126
- "Add comprehensive tests"
127
- ]
128
- },
129
- "python" => {
130
- "analysis_phases" => [
131
- {
132
- phase: 1,
133
- name: "Code Style and Quality",
134
- tools: %w[flake8 black pylint],
135
- focus_areas: ["PEP8 compliance", "code formatting", "code quality"],
136
- priority: "high"
137
- },
138
- {
139
- phase: 2,
140
- name: "Security Analysis",
141
- tools: %w[bandit safety],
142
- focus_areas: ["security vulnerabilities", "dependency vulnerabilities"],
143
- priority: "high"
144
- },
145
- {
146
- phase: 3,
147
- name: "Type Safety",
148
- tools: %w[mypy pyright],
149
- focus_areas: ["type checking", "type coverage"],
150
- priority: "medium"
151
- },
152
- {
153
- phase: 4,
154
- name: "Performance Analysis",
155
- tools: %w[py-spy memory-profiler],
156
- focus_areas: ["performance bottlenecks", "memory usage"],
157
- priority: "medium"
158
- }
159
- ],
160
- "code_patterns" => {
161
- "complex_functions" => {
162
- pattern: "functions with high complexity",
163
- detection: "pylint --disable=all --enable=too-complex",
164
- threshold: 10
165
- },
166
- "long_functions" => {
167
- pattern: "functions with excessive lines",
168
- detection: "pylint --disable=all --enable=too-many-lines",
169
- threshold: 50
170
- },
171
- "unused_imports" => {
172
- pattern: "unused imports",
173
- detection: "flake8 --select=F401",
174
- threshold: 0
175
- },
176
- "security_issues" => {
177
- pattern: "SQL injection, command injection",
178
- detection: "bandit -r .",
179
- threshold: 0
180
- }
181
- },
182
- "refactoring_priorities" => [
183
- "Simplify complex functions",
184
- "Remove unused imports",
185
- "Add type hints",
186
- "Improve error handling",
187
- "Add comprehensive tests"
188
- ]
189
- },
190
- "java" => {
191
- "analysis_phases" => [
192
- {
193
- phase: 1,
194
- name: "Code Quality",
195
- tools: %w[checkstyle pmd],
196
- focus_areas: ["code style", "code quality", "best practices"],
197
- priority: "high"
198
- },
199
- {
200
- phase: 2,
201
- name: "Security Analysis",
202
- tools: %w[spotbugs dependency-check],
203
- focus_areas: ["security vulnerabilities", "dependency vulnerabilities"],
204
- priority: "high"
205
- },
206
- {
207
- phase: 3,
208
- name: "Performance Analysis",
209
- tools: %w[jmh visualvm],
210
- focus_areas: ["performance bottlenecks", "memory leaks"],
211
- priority: "medium"
212
- },
213
- {
214
- phase: 4,
215
- name: "Test Coverage",
216
- tools: %w[jacoco junit],
217
- focus_areas: ["test coverage", "test quality"],
218
- priority: "medium"
219
- }
220
- ],
221
- "code_patterns" => {
222
- "complex_methods" => {
223
- pattern: "methods with high cyclomatic complexity",
224
- detection: "pmd --rulesets complexity",
225
- threshold: 10
226
- },
227
- "code_duplication" => {
228
- pattern: "duplicate code blocks",
229
- detection: "pmd --rulesets cpd",
230
- threshold: 50
231
- },
232
- "memory_leaks" => {
233
- pattern: "potential memory leaks",
234
- detection: "spotbugs --effort:max",
235
- threshold: 0
236
- },
237
- "security_vulnerabilities" => {
238
- pattern: "SQL injection, XSS, path traversal",
239
- detection: "spotbugs --effort:max",
240
- threshold: 0
241
- }
242
- },
243
- "refactoring_priorities" => [
244
- "Extract complex methods",
245
- "Eliminate code duplication",
246
- "Improve exception handling",
247
- "Add proper logging",
248
- "Increase test coverage"
249
- ]
250
- },
251
- "go" => {
252
- "analysis_phases" => [
253
- {
254
- phase: 1,
255
- name: "Code Quality",
256
- tools: %w[golangci-lint gofmt],
257
- focus_areas: ["code style", "code quality", "best practices"],
258
- priority: "high"
259
- },
260
- {
261
- phase: 2,
262
- name: "Security Analysis",
263
- tools: %w[gosec govet],
264
- focus_areas: ["security vulnerabilities", "common mistakes"],
265
- priority: "high"
266
- },
267
- {
268
- phase: 3,
269
- name: "Performance Analysis",
270
- tools: %w[pprof go-torch],
271
- focus_areas: ["performance bottlenecks", "memory usage"],
272
- priority: "medium"
273
- },
274
- {
275
- phase: 4,
276
- name: "Test Coverage",
277
- tools: %w[go test -cover],
278
- focus_areas: ["test coverage", "test quality"],
279
- priority: "medium"
280
- }
281
- ],
282
- "code_patterns" => {
283
- "complex_functions" => {
284
- pattern: "functions with high cyclomatic complexity",
285
- detection: "golangci-lint --enable=gocyclo",
286
- threshold: 15
287
- },
288
- "error_handling" => {
289
- pattern: "unhandled errors",
290
- detection: "golangci-lint --enable=errcheck",
291
- threshold: 0
292
- },
293
- "race_conditions" => {
294
- pattern: "potential race conditions",
295
- detection: "go test -race",
296
- threshold: 0
297
- },
298
- "security_issues" => {
299
- pattern: "security vulnerabilities",
300
- detection: "gosec ./...",
301
- threshold: 0
302
- }
303
- },
304
- "refactoring_priorities" => [
305
- "Simplify complex functions",
306
- "Improve error handling",
307
- "Add proper logging",
308
- "Eliminate race conditions",
309
- "Increase test coverage"
310
- ]
311
- },
312
- "rust" => {
313
- "analysis_phases" => [
314
- {
315
- phase: 1,
316
- name: "Code Quality",
317
- tools: %w[clippy rustfmt],
318
- focus_areas: ["code style", "code quality", "best practices"],
319
- priority: "high"
320
- },
321
- {
322
- phase: 2,
323
- name: "Security Analysis",
324
- tools: %w[cargo-audit cargo-geiger],
325
- focus_areas: ["dependency vulnerabilities", "unsafe code usage"],
326
- priority: "high"
327
- },
328
- {
329
- phase: 3,
330
- name: "Performance Analysis",
331
- tools: %w[cargo bench flamegraph],
332
- focus_areas: ["performance benchmarks", "memory usage"],
333
- priority: "medium"
334
- },
335
- {
336
- phase: 4,
337
- name: "Test Coverage",
338
- tools: %w[tarpaulin cargo test],
339
- focus_areas: ["test coverage", "test quality"],
340
- priority: "medium"
341
- }
342
- ],
343
- "code_patterns" => {
344
- "complex_functions" => {
345
- pattern: "functions with high cyclomatic complexity",
346
- detection: "clippy --all --warn clippy::cognitive_complexity",
347
- threshold: 25
348
- },
349
- "unsafe_code" => {
350
- pattern: "unsafe code blocks",
351
- detection: "cargo-geiger",
352
- threshold: 0
353
- },
354
- "unused_code" => {
355
- pattern: "unused functions and variables",
356
- detection: "clippy --all --warn dead_code",
357
- threshold: 0
358
- },
359
- "security_issues" => {
360
- pattern: "security vulnerabilities",
361
- detection: "cargo-audit",
362
- threshold: 0
363
- }
364
- },
365
- "refactoring_priorities" => [
366
- "Simplify complex functions",
367
- "Reduce unsafe code usage",
368
- "Remove unused code",
369
- "Improve error handling",
370
- "Add comprehensive tests"
371
- ]
372
- }
373
- }.freeze
374
-
375
- def initialize(project_dir = Dir.pwd)
376
- @project_dir = project_dir
377
- end
378
-
379
- # Get analysis strategy for a specific language
380
- def get_analysis_strategy(language)
381
- strategy = LANGUAGE_STRATEGIES[language]
382
- return nil unless strategy
383
-
384
- {
385
- language: language,
386
- phases: strategy["analysis_phases"],
387
- patterns: strategy["code_patterns"],
388
- refactoring_priorities: strategy["refactoring_priorities"],
389
- customizations: generate_customizations(language)
390
- }
391
- end
392
-
393
- # Get analysis phases for a language
394
- def get_analysis_phases(language)
395
- strategy = LANGUAGE_STRATEGIES[language]
396
- return [] unless strategy
397
-
398
- strategy["analysis_phases"]
399
- end
400
-
401
- # Get code patterns for a language
402
- def get_code_patterns(language)
403
- strategy = LANGUAGE_STRATEGIES[language]
404
- return {} unless strategy
405
-
406
- strategy["code_patterns"]
407
- end
408
-
409
- # Get refactoring priorities for a language
410
- def get_refactoring_priorities(language)
411
- strategy = LANGUAGE_STRATEGIES[language]
412
- return [] unless strategy
413
-
414
- strategy["refactoring_priorities"]
415
- end
416
-
417
- # Generate custom analysis plan for a language
418
- def generate_custom_analysis_plan(language, focus_areas = [])
419
- strategy = get_analysis_strategy(language)
420
- return nil unless strategy
421
-
422
- plan = {
423
- language: language,
424
- phases: [],
425
- focus_areas: focus_areas,
426
- estimated_duration: estimate_analysis_duration(language, focus_areas),
427
- tools_required: get_required_tools(language, focus_areas)
428
- }
429
-
430
- # Filter phases based on focus areas
431
- plan[:phases] = if focus_areas.any?
432
- strategy[:phases].select do |phase|
433
- focus_areas.any? { |area| phase[:focus_areas].any? { |fa| fa.include?(area) } }
434
- end
435
- else
436
- strategy[:phases]
437
- end
438
-
439
- plan
440
- end
441
-
442
- # Get language-specific recommendations
443
- def get_language_recommendations(language, analysis_results = {})
444
- recommendations = []
445
-
446
- case language
447
- when "ruby"
448
- recommendations.concat(generate_ruby_recommendations(analysis_results))
449
- when "javascript"
450
- recommendations.concat(generate_javascript_recommendations(analysis_results))
451
- when "python"
452
- recommendations.concat(generate_python_recommendations(analysis_results))
453
- when "java"
454
- recommendations.concat(generate_java_recommendations(analysis_results))
455
- when "go"
456
- recommendations.concat(generate_go_recommendations(analysis_results))
457
- when "rust"
458
- recommendations.concat(generate_rust_recommendations(analysis_results))
459
- end
460
-
461
- recommendations
462
- end
463
-
464
- # Get language-specific best practices
465
- def get_language_best_practices(language)
466
- case language
467
- when "ruby"
468
- {
469
- "style" => [
470
- "Follow Ruby style guide",
471
- "Use meaningful variable names",
472
- "Keep methods small and focused",
473
- "Use proper indentation"
474
- ],
475
- "security" => [
476
- "Use parameterized queries",
477
- "Validate user input",
478
- "Use HTTPS in production",
479
- "Keep gems updated"
480
- ],
481
- "performance" => [
482
- "Use appropriate data structures",
483
- "Avoid N+1 queries",
484
- "Use caching where appropriate",
485
- "Profile before optimizing"
486
- ]
487
- }
488
- when "javascript"
489
- {
490
- "style" => [
491
- "Use consistent formatting",
492
- "Follow ESLint rules",
493
- "Use meaningful variable names",
494
- "Avoid global variables"
495
- ],
496
- "security" => [
497
- "Validate user input",
498
- "Use HTTPS",
499
- "Avoid eval()",
500
- "Keep dependencies updated"
501
- ],
502
- "performance" => [
503
- "Minimize bundle size",
504
- "Use lazy loading",
505
- "Optimize images",
506
- "Use appropriate caching"
507
- ]
508
- }
509
- when "python"
510
- {
511
- "style" => [
512
- "Follow PEP 8",
513
- "Use meaningful variable names",
514
- "Keep functions small",
515
- "Use proper docstrings"
516
- ],
517
- "security" => [
518
- "Validate user input",
519
- "Use parameterized queries",
520
- "Keep packages updated",
521
- "Use virtual environments"
522
- ],
523
- "performance" => [
524
- "Use appropriate data structures",
525
- "Profile before optimizing",
526
- "Use list comprehensions",
527
- "Avoid global variables"
528
- ]
529
- }
530
- else
531
- {}
532
- end
533
- end
534
-
535
- # Get language-specific anti-patterns
536
- def get_language_anti_patterns(language)
537
- case language
538
- when "ruby"
539
- [
540
- "Monkey patching",
541
- "Global variables",
542
- "Complex conditionals",
543
- "Long methods",
544
- "Code duplication"
545
- ]
546
- when "javascript"
547
- [
548
- "Callback hell",
549
- "Global variables",
550
- "eval() usage",
551
- "Unhandled promises",
552
- "Memory leaks"
553
- ]
554
- when "python"
555
- [
556
- "Global variables",
557
- "Complex list comprehensions",
558
- "Unused imports",
559
- "Long functions",
560
- "Code duplication"
561
- ]
562
- else
563
- []
564
- end
565
- end
566
-
567
- private
568
-
569
- def generate_customizations(language)
570
- customizations = {}
571
-
572
- case language
573
- when "ruby"
574
- customizations = {
575
- "framework_specific" => detect_ruby_framework,
576
- "gem_analysis" => analyze_ruby_gems,
577
- "test_framework" => detect_test_framework
578
- }
579
- when "javascript"
580
- customizations = {
581
- "framework_specific" => detect_javascript_framework,
582
- "package_analysis" => analyze_javascript_packages,
583
- "build_tool" => detect_build_tool
584
- }
585
- when "python"
586
- customizations = {
587
- "framework_specific" => detect_python_framework,
588
- "package_analysis" => analyze_python_packages,
589
- "virtual_environment" => detect_virtual_environment
590
- }
591
- end
592
-
593
- customizations
594
- end
595
-
596
- def detect_ruby_framework
597
- if File.exist?(File.join(@project_dir, "config", "application.rb"))
598
- "rails"
599
- elsif File.exist?(File.join(@project_dir, "app.rb"))
600
- "sinatra"
601
- elsif File.exist?(File.join(@project_dir, "*.gemspec"))
602
- "gem"
603
- else
604
- "unknown"
605
- end
606
- end
607
-
608
- def analyze_ruby_gems
609
- gemfile_path = File.join(@project_dir, "Gemfile")
610
- return {} unless File.exist?(gemfile_path)
611
-
612
- gemfile_content = File.read(gemfile_path)
613
- {
614
- "total_gems" => gemfile_content.scan(/gem\s+['"]([^'"]+)['"]/).flatten.length,
615
- "development_gems" => gemfile_content.scan(/group\s+:development.*?end/m).any?,
616
- "test_gems" => gemfile_content.scan(/group\s+:test.*?end/m).any?,
617
- "production_gems" => gemfile_content.scan(/group\s+:production.*?end/m).any?
618
- }
619
- end
620
-
621
- def detect_test_framework
622
- if File.exist?(File.join(@project_dir, "spec"))
623
- "rspec"
624
- elsif File.exist?(File.join(@project_dir, "test"))
625
- "minitest"
626
- else
627
- "unknown"
628
- end
629
- end
630
-
631
- def detect_javascript_framework
632
- package_json_path = File.join(@project_dir, "package.json")
633
- return "unknown" unless File.exist?(package_json_path)
634
-
635
- package_json = JSON.parse(File.read(package_json_path))
636
- dependencies = package_json["dependencies"] || {}
637
- dev_dependencies = package_json["devDependencies"] || {}
638
-
639
- if dependencies["react"] || dev_dependencies["react"]
640
- "react"
641
- elsif dependencies["vue"] || dev_dependencies["vue"]
642
- "vue"
643
- elsif dependencies["angular"] || dev_dependencies["angular"]
644
- "angular"
645
- elsif dependencies["express"] || dev_dependencies["express"]
646
- "express"
647
- else
648
- "node"
649
- end
650
- end
651
-
652
- def analyze_javascript_packages
653
- package_json_path = File.join(@project_dir, "package.json")
654
- return {} unless File.exist?(package_json_path)
655
-
656
- package_json = JSON.parse(File.read(package_json_path))
657
- {
658
- "total_dependencies" => (package_json["dependencies"] || {}).length,
659
- "total_dev_dependencies" => (package_json["devDependencies"] || {}).length,
660
- "has_scripts" => (package_json["scripts"] || {}).any?,
661
- "has_type_definitions" => package_json["dependencies"]&.key?("@types") || false
662
- }
663
- end
664
-
665
- def detect_build_tool
666
- if File.exist?(File.join(@project_dir, "webpack.config.js"))
667
- "webpack"
668
- elsif File.exist?(File.join(@project_dir, "vite.config.js"))
669
- "vite"
670
- elsif File.exist?(File.join(@project_dir, "rollup.config.js"))
671
- "rollup"
672
- else
673
- "unknown"
674
- end
675
- end
676
-
677
- def detect_python_framework
678
- if File.exist?(File.join(@project_dir, "manage.py"))
679
- "django"
680
- elsif File.exist?(File.join(@project_dir, "app.py"))
681
- "flask"
682
- elsif File.exist?(File.join(@project_dir, "main.py"))
683
- "fastapi"
684
- else
685
- "unknown"
686
- end
687
- end
688
-
689
- def analyze_python_packages
690
- requirements_path = File.join(@project_dir, "requirements.txt")
691
- return {} unless File.exist?(requirements_path)
692
-
693
- requirements_content = File.read(requirements_path)
694
- {
695
- "total_packages" => requirements_content.lines.count { |line| line.strip != "" && !line.start_with?("#") },
696
- "has_dev_requirements" => File.exist?(File.join(@project_dir, "requirements-dev.txt")),
697
- "has_test_requirements" => File.exist?(File.join(@project_dir, "requirements-test.txt"))
698
- }
699
- end
700
-
701
- def detect_virtual_environment
702
- if File.exist?(File.join(@project_dir, "venv"))
703
- "venv"
704
- elsif File.exist?(File.join(@project_dir, ".venv"))
705
- ".venv"
706
- elsif File.exist?(File.join(@project_dir, "env"))
707
- "env"
708
- else
709
- "unknown"
710
- end
711
- end
712
-
713
- def estimate_analysis_duration(language, focus_areas)
714
- base_duration = case language
715
- when "ruby"
716
- 30 # minutes
717
- when "javascript"
718
- 45 # minutes
719
- when "python"
720
- 25 # minutes
721
- when "java"
722
- 60 # minutes
723
- when "go"
724
- 20 # minutes
725
- when "rust"
726
- 35 # minutes
727
- else
728
- 30 # minutes
729
- end
730
-
731
- # Adjust based on focus areas
732
- base_duration += 15 if focus_areas.include?("security")
733
- base_duration += 20 if focus_areas.include?("performance")
734
- base_duration += 10 if focus_areas.include?("test_coverage")
735
-
736
- base_duration
737
- end
738
-
739
- def get_required_tools(language, focus_areas)
740
- strategy = LANGUAGE_STRATEGIES[language]
741
- return [] unless strategy
742
-
743
- required_tools = []
744
- strategy["analysis_phases"].each do |phase|
745
- if focus_areas.empty? || focus_areas.any? { |area| phase[:focus_areas].any? { |fa| fa.include?(area) } }
746
- required_tools.concat(phase[:tools])
747
- end
748
- end
749
-
750
- required_tools.uniq
751
- end
752
-
753
- def generate_ruby_recommendations(analysis_results)
754
- recommendations = []
755
-
756
- if analysis_results["style_violations"]&.> 10
757
- recommendations << {
758
- type: "style",
759
- priority: "high",
760
- message: "High number of style violations detected",
761
- action: "Run RuboCop and fix style issues"
762
- }
763
- end
764
-
765
- if analysis_results["security_vulnerabilities"]&.> 0
766
- recommendations << {
767
- type: "security",
768
- priority: "critical",
769
- message: "Security vulnerabilities found",
770
- action: "Run Brakeman and address security issues immediately"
771
- }
772
- end
773
-
774
- recommendations
775
- end
776
-
777
- def generate_javascript_recommendations(analysis_results)
778
- recommendations = []
779
-
780
- if analysis_results["linting_errors"]&.> 20
781
- recommendations << {
782
- type: "quality",
783
- priority: "high",
784
- message: "High number of linting errors",
785
- action: "Run ESLint and fix code quality issues"
786
- }
787
- end
788
-
789
- if analysis_results["security_vulnerabilities"]&.> 0
790
- recommendations << {
791
- type: "security",
792
- priority: "critical",
793
- message: "Security vulnerabilities in dependencies",
794
- action: "Run npm audit and update vulnerable packages"
795
- }
796
- end
797
-
798
- recommendations
799
- end
800
-
801
- def generate_python_recommendations(analysis_results)
802
- recommendations = []
803
-
804
- if analysis_results["pep8_violations"]&.> 15
805
- recommendations << {
806
- type: "style",
807
- priority: "medium",
808
- message: "PEP8 violations detected",
809
- action: "Run flake8 and fix style issues"
810
- }
811
- end
812
-
813
- if analysis_results["security_issues"]&.> 0
814
- recommendations << {
815
- type: "security",
816
- priority: "critical",
817
- message: "Security issues found",
818
- action: "Run bandit and address security vulnerabilities"
819
- }
820
- end
821
-
822
- recommendations
823
- end
824
-
825
- def generate_java_recommendations(analysis_results)
826
- recommendations = []
827
-
828
- if analysis_results["checkstyle_violations"]&.> 25
829
- recommendations << {
830
- type: "style",
831
- priority: "medium",
832
- message: "Checkstyle violations detected",
833
- action: "Run Checkstyle and fix code style issues"
834
- }
835
- end
836
-
837
- if analysis_results["security_vulnerabilities"]&.> 0
838
- recommendations << {
839
- type: "security",
840
- priority: "critical",
841
- message: "Security vulnerabilities found",
842
- action: "Run SpotBugs and address security issues"
843
- }
844
- end
845
-
846
- recommendations
847
- end
848
-
849
- def generate_go_recommendations(analysis_results)
850
- recommendations = []
851
-
852
- if analysis_results["linting_errors"]&.> 10
853
- recommendations << {
854
- type: "quality",
855
- priority: "high",
856
- message: "Go linting errors detected",
857
- action: "Run golangci-lint and fix code quality issues"
858
- }
859
- end
860
-
861
- if analysis_results["security_issues"]&.> 0
862
- recommendations << {
863
- type: "security",
864
- priority: "critical",
865
- message: "Security issues found",
866
- action: "Run gosec and address security vulnerabilities"
867
- }
868
- end
869
-
870
- recommendations
871
- end
872
-
873
- def generate_rust_recommendations(analysis_results)
874
- recommendations = []
875
-
876
- if analysis_results["clippy_warnings"]&.> 15
877
- recommendations << {
878
- type: "quality",
879
- priority: "medium",
880
- message: "Clippy warnings detected",
881
- action: "Run cargo clippy and address code quality issues"
882
- }
883
- end
884
-
885
- if analysis_results["security_vulnerabilities"]&.> 0
886
- recommendations << {
887
- type: "security",
888
- priority: "critical",
889
- message: "Security vulnerabilities in dependencies",
890
- action: "Run cargo audit and update vulnerable dependencies"
891
- }
892
- end
893
-
894
- recommendations
895
- end
896
- end
897
- end