aidp 0.7.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 (119) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +60 -214
  3. data/bin/aidp +1 -1
  4. data/lib/aidp/analysis/kb_inspector.rb +38 -23
  5. data/lib/aidp/analysis/seams.rb +2 -31
  6. data/lib/aidp/analysis/tree_sitter_grammar_loader.rb +0 -13
  7. data/lib/aidp/analysis/tree_sitter_scan.rb +3 -20
  8. data/lib/aidp/analyze/error_handler.rb +2 -75
  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/cli/jobs_command.rb +100 -432
  15. data/lib/aidp/cli.rb +309 -239
  16. data/lib/aidp/config.rb +298 -10
  17. data/lib/aidp/debug_logger.rb +195 -0
  18. data/lib/aidp/debug_mixin.rb +187 -0
  19. data/lib/aidp/execute/progress.rb +9 -0
  20. data/lib/aidp/execute/runner.rb +221 -40
  21. data/lib/aidp/execute/steps.rb +17 -7
  22. data/lib/aidp/execute/workflow_selector.rb +211 -0
  23. data/lib/aidp/harness/completion_checker.rb +268 -0
  24. data/lib/aidp/harness/condition_detector.rb +1526 -0
  25. data/lib/aidp/harness/config_loader.rb +373 -0
  26. data/lib/aidp/harness/config_manager.rb +382 -0
  27. data/lib/aidp/harness/config_schema.rb +1006 -0
  28. data/lib/aidp/harness/config_validator.rb +355 -0
  29. data/lib/aidp/harness/configuration.rb +477 -0
  30. data/lib/aidp/harness/enhanced_runner.rb +494 -0
  31. data/lib/aidp/harness/error_handler.rb +616 -0
  32. data/lib/aidp/harness/provider_config.rb +423 -0
  33. data/lib/aidp/harness/provider_factory.rb +306 -0
  34. data/lib/aidp/harness/provider_manager.rb +1269 -0
  35. data/lib/aidp/harness/provider_type_checker.rb +88 -0
  36. data/lib/aidp/harness/runner.rb +411 -0
  37. data/lib/aidp/harness/state/errors.rb +28 -0
  38. data/lib/aidp/harness/state/metrics.rb +219 -0
  39. data/lib/aidp/harness/state/persistence.rb +128 -0
  40. data/lib/aidp/harness/state/provider_state.rb +132 -0
  41. data/lib/aidp/harness/state/ui_state.rb +68 -0
  42. data/lib/aidp/harness/state/workflow_state.rb +123 -0
  43. data/lib/aidp/harness/state_manager.rb +586 -0
  44. data/lib/aidp/harness/status_display.rb +888 -0
  45. data/lib/aidp/harness/ui/base.rb +16 -0
  46. data/lib/aidp/harness/ui/enhanced_tui.rb +545 -0
  47. data/lib/aidp/harness/ui/enhanced_workflow_selector.rb +252 -0
  48. data/lib/aidp/harness/ui/error_handler.rb +132 -0
  49. data/lib/aidp/harness/ui/frame_manager.rb +361 -0
  50. data/lib/aidp/harness/ui/job_monitor.rb +500 -0
  51. data/lib/aidp/harness/ui/navigation/main_menu.rb +311 -0
  52. data/lib/aidp/harness/ui/navigation/menu_formatter.rb +120 -0
  53. data/lib/aidp/harness/ui/navigation/menu_item.rb +142 -0
  54. data/lib/aidp/harness/ui/navigation/menu_state.rb +139 -0
  55. data/lib/aidp/harness/ui/navigation/submenu.rb +202 -0
  56. data/lib/aidp/harness/ui/navigation/workflow_selector.rb +176 -0
  57. data/lib/aidp/harness/ui/progress_display.rb +280 -0
  58. data/lib/aidp/harness/ui/question_collector.rb +141 -0
  59. data/lib/aidp/harness/ui/spinner_group.rb +184 -0
  60. data/lib/aidp/harness/ui/spinner_helper.rb +152 -0
  61. data/lib/aidp/harness/ui/status_manager.rb +312 -0
  62. data/lib/aidp/harness/ui/status_widget.rb +280 -0
  63. data/lib/aidp/harness/ui/workflow_controller.rb +312 -0
  64. data/lib/aidp/harness/user_interface.rb +2381 -0
  65. data/lib/aidp/provider_manager.rb +131 -7
  66. data/lib/aidp/providers/anthropic.rb +28 -103
  67. data/lib/aidp/providers/base.rb +170 -0
  68. data/lib/aidp/providers/cursor.rb +52 -181
  69. data/lib/aidp/providers/gemini.rb +24 -107
  70. data/lib/aidp/providers/macos_ui.rb +99 -5
  71. data/lib/aidp/providers/opencode.rb +194 -0
  72. data/lib/aidp/storage/csv_storage.rb +172 -0
  73. data/lib/aidp/storage/file_manager.rb +214 -0
  74. data/lib/aidp/storage/json_storage.rb +140 -0
  75. data/lib/aidp/version.rb +1 -1
  76. data/lib/aidp.rb +54 -39
  77. data/templates/COMMON/AGENT_BASE.md +11 -0
  78. data/templates/EXECUTE/00_PRD.md +4 -4
  79. data/templates/EXECUTE/02_ARCHITECTURE.md +5 -4
  80. data/templates/EXECUTE/07_TEST_PLAN.md +4 -1
  81. data/templates/EXECUTE/08_TASKS.md +4 -4
  82. data/templates/EXECUTE/10_IMPLEMENTATION_AGENT.md +4 -4
  83. data/templates/README.md +279 -0
  84. data/templates/aidp-development.yml.example +373 -0
  85. data/templates/aidp-minimal.yml.example +48 -0
  86. data/templates/aidp-production.yml.example +475 -0
  87. data/templates/aidp.yml.example +598 -0
  88. metadata +93 -69
  89. data/lib/aidp/analyze/agent_personas.rb +0 -71
  90. data/lib/aidp/analyze/agent_tool_executor.rb +0 -439
  91. data/lib/aidp/analyze/data_retention_manager.rb +0 -421
  92. data/lib/aidp/analyze/database.rb +0 -260
  93. data/lib/aidp/analyze/dependencies.rb +0 -335
  94. data/lib/aidp/analyze/export_manager.rb +0 -418
  95. data/lib/aidp/analyze/focus_guidance.rb +0 -517
  96. data/lib/aidp/analyze/incremental_analyzer.rb +0 -533
  97. data/lib/aidp/analyze/language_analysis_strategies.rb +0 -897
  98. data/lib/aidp/analyze/large_analysis_progress.rb +0 -499
  99. data/lib/aidp/analyze/memory_manager.rb +0 -339
  100. data/lib/aidp/analyze/metrics_storage.rb +0 -336
  101. data/lib/aidp/analyze/parallel_processor.rb +0 -454
  102. data/lib/aidp/analyze/performance_optimizer.rb +0 -691
  103. data/lib/aidp/analyze/repository_chunker.rb +0 -697
  104. data/lib/aidp/analyze/static_analysis_detector.rb +0 -577
  105. data/lib/aidp/analyze/storage.rb +0 -655
  106. data/lib/aidp/analyze/tool_configuration.rb +0 -441
  107. data/lib/aidp/analyze/tool_modernization.rb +0 -750
  108. data/lib/aidp/database/pg_adapter.rb +0 -148
  109. data/lib/aidp/database_config.rb +0 -69
  110. data/lib/aidp/database_connection.rb +0 -72
  111. data/lib/aidp/job_manager.rb +0 -41
  112. data/lib/aidp/jobs/base_job.rb +0 -45
  113. data/lib/aidp/jobs/provider_execution_job.rb +0 -83
  114. data/lib/aidp/project_detector.rb +0 -117
  115. data/lib/aidp/providers/agent_supervisor.rb +0 -348
  116. data/lib/aidp/providers/supervised_base.rb +0 -317
  117. data/lib/aidp/providers/supervised_cursor.rb +0 -22
  118. data/lib/aidp/sync.rb +0 -13
  119. data/lib/aidp/workspace.rb +0 -19
@@ -1,418 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "json"
4
- require "csv"
5
- require "yaml"
6
-
7
- module Aidp
8
- class ExportManager
9
- # Supported export formats
10
- SUPPORTED_FORMATS = %w[json csv yaml xml].freeze
11
-
12
- def initialize(project_dir = Dir.pwd, config = {})
13
- @project_dir = project_dir
14
- @config = config
15
- @output_dir = config[:output_dir] || File.join(project_dir, "exports")
16
- end
17
-
18
- # Export analysis data to JSON format
19
- def export_to_json(data, options = {})
20
- export_data(data, "json", options) do |formatted_data|
21
- JSON.pretty_generate(formatted_data)
22
- end
23
- end
24
-
25
- # Export analysis data to CSV format
26
- def export_to_csv(data, options = {})
27
- export_data(data, "csv", options) do |formatted_data|
28
- generate_csv_content(formatted_data, options)
29
- end
30
- end
31
-
32
- # Export analysis data to YAML format
33
- def export_to_yaml(data, options = {})
34
- export_data(data, "yaml", options) do |formatted_data|
35
- YAML.dump(formatted_data)
36
- end
37
- end
38
-
39
- # Export analysis data to XML format
40
- def export_to_xml(data, options = {})
41
- export_data(data, "xml", options) do |formatted_data|
42
- generate_xml_content(formatted_data, options)
43
- end
44
- end
45
-
46
- # Export analysis data to multiple formats
47
- def export_to_multiple_formats(data, formats, options = {})
48
- results = {}
49
-
50
- formats.each do |format|
51
- case format.downcase
52
- when "json"
53
- results[:json] = export_to_json(data, options)
54
- when "csv"
55
- results[:csv] = export_to_csv(data, options)
56
- when "yaml"
57
- results[:yaml] = export_to_yaml(data, options)
58
- when "xml"
59
- results[:xml] = export_to_xml(data, options)
60
- else
61
- results[format] = {error: "Unsupported format: #{format}"}
62
- end
63
- end
64
-
65
- results
66
- end
67
-
68
- # Export specific analysis components
69
- def export_analysis_component(component_name, data, format, options = {})
70
- component_data = extract_component_data(component_name, data)
71
-
72
- case format.downcase
73
- when "json"
74
- export_to_json(component_data, options.merge(component: component_name))
75
- when "csv"
76
- export_to_csv(component_data, options.merge(component: component_name))
77
- when "yaml"
78
- export_to_yaml(component_data, options.merge(component: component_name))
79
- when "xml"
80
- export_to_xml(component_data, options.merge(component: component_name))
81
- else
82
- {error: "Unsupported format: #{format}"}
83
- end
84
- end
85
-
86
- # Export metrics data
87
- def export_metrics(metrics_data, format, options = {})
88
- formatted_metrics = format_metrics_data(metrics_data)
89
-
90
- case format.downcase
91
- when "json"
92
- export_to_json(formatted_metrics, options.merge(type: "metrics"))
93
- when "csv"
94
- export_to_csv(formatted_metrics, options.merge(type: "metrics"))
95
- when "yaml"
96
- export_to_yaml(formatted_metrics, options.merge(type: "metrics"))
97
- when "xml"
98
- export_to_xml(formatted_metrics, options.merge(type: "metrics"))
99
- else
100
- {error: "Unsupported format: #{format}"}
101
- end
102
- end
103
-
104
- # Export comparison data
105
- def export_comparison(before_data, after_data, format, options = {})
106
- comparison_data = prepare_comparison_data(before_data, after_data)
107
-
108
- case format.downcase
109
- when "json"
110
- export_to_json(comparison_data, options.merge(type: "comparison"))
111
- when "csv"
112
- export_to_csv(comparison_data, options.merge(type: "comparison"))
113
- when "yaml"
114
- export_to_yaml(comparison_data, options.merge(type: "comparison"))
115
- when "xml"
116
- export_to_xml(comparison_data, options.merge(type: "comparison"))
117
- else
118
- {error: "Unsupported format: #{format}"}
119
- end
120
- end
121
-
122
- # Generate export summary
123
- def generate_export_summary(exports)
124
- {
125
- total_exports: exports.length,
126
- successful_exports: exports.count { |_, result| result[:success] },
127
- failed_exports: exports.count { |_, result| !result[:success] },
128
- formats_used: exports.keys.uniq,
129
- files_generated: exports.values.filter_map { |result| result[:path] },
130
- generated_at: Time.now
131
- }
132
- end
133
-
134
- private
135
-
136
- def export_data(data, format, options)
137
- timestamp = Time.now.strftime("%Y%m%d_%H%M%S")
138
- component = options[:component] || "analysis"
139
- type = options[:type] || "data"
140
-
141
- filename = options[:filename] || "#{component}_#{type}_#{timestamp}.#{format}"
142
- output_path = File.join(@output_dir, filename)
143
-
144
- # Ensure output directory exists
145
- FileUtils.mkdir_p(@output_dir)
146
-
147
- # Format and write data
148
- formatted_data = format_export_data(data, options)
149
- content = yield(formatted_data)
150
-
151
- File.write(output_path, content)
152
-
153
- {
154
- success: true,
155
- path: output_path,
156
- format: format,
157
- filename: filename,
158
- size: File.size(output_path),
159
- generated_at: Time.now
160
- }
161
- end
162
-
163
- def format_export_data(data, options)
164
- formatted = {
165
- metadata: {
166
- exported_at: Time.now.iso8601,
167
- project_name: File.basename(@project_dir),
168
- project_path: @project_dir,
169
- export_type: options[:type] || "analysis",
170
- component: options[:component]
171
- },
172
- data: data
173
- }
174
-
175
- # Add configuration if requested
176
- formatted[:config] = @config if options[:include_config]
177
-
178
- formatted
179
- end
180
-
181
- def generate_csv_content(data, options)
182
- # Flatten nested data for CSV export
183
- flattened_data = flatten_data_for_csv(data)
184
-
185
- return "" if flattened_data.empty?
186
-
187
- # Generate CSV content
188
- CSV.generate do |csv|
189
- # Add headers
190
- headers = flattened_data.first.keys
191
- csv << headers
192
-
193
- # Add data rows
194
- flattened_data.each do |row|
195
- csv << headers.map { |header| row[header] }
196
- end
197
- end
198
- end
199
-
200
- def flatten_data_for_csv(data)
201
- flattened = []
202
-
203
- if data[:data].is_a?(Array)
204
- # Handle array data
205
- data[:data].each_with_index do |item, index|
206
- flattened_item = flatten_hash(item)
207
- flattened_item["index"] = index
208
- flattened << flattened_item
209
- end
210
- elsif data[:data].is_a?(Hash)
211
- # Handle hash data
212
- flattened << flatten_hash(data[:data])
213
- end
214
-
215
- flattened
216
- end
217
-
218
- def flatten_hash(hash, prefix = "")
219
- flattened = {}
220
-
221
- hash.each do |key, value|
222
- new_key = prefix.empty? ? key.to_s : "#{prefix}_#{key}"
223
-
224
- case value
225
- when Hash
226
- flattened.merge!(flatten_hash(value, new_key))
227
- when Array
228
- if value.all?(Hash)
229
- # Array of hashes - create separate rows
230
- value.each_with_index do |item, index|
231
- item_flattened = flatten_hash(item, "#{new_key}_#{index}")
232
- flattened.merge!(item_flattened)
233
- end
234
- else
235
- # Simple array - join with semicolon
236
- flattened[new_key] = value.join("; ")
237
- end
238
- else
239
- flattened[new_key] = value
240
- end
241
- end
242
-
243
- flattened
244
- end
245
-
246
- def generate_xml_content(data, options)
247
- require "rexml/document"
248
-
249
- doc = REXML::Document.new
250
- doc.add_element("analysis_export")
251
-
252
- # Add metadata
253
- metadata_elem = doc.root.add_element("metadata")
254
- data[:metadata].each do |key, value|
255
- elem = metadata_elem.add_element(key.to_s)
256
- elem.text = value.to_s
257
- end
258
-
259
- # Add data
260
- data_elem = doc.root.add_element("data")
261
- add_xml_element(data_elem, data[:data])
262
-
263
- # Format XML
264
- formatter = REXML::Formatters::Pretty.new(2)
265
- formatter.compact = true
266
- output = ""
267
- formatter.write(doc, output)
268
-
269
- output
270
- end
271
-
272
- def add_xml_element(parent, data)
273
- case data
274
- when Hash
275
- data.each do |key, value|
276
- elem = parent.add_element(key.to_s)
277
- add_xml_element(elem, value)
278
- end
279
- when Array
280
- data.each_with_index do |item, index|
281
- elem = parent.add_element("item_#{index}")
282
- add_xml_element(elem, item)
283
- end
284
- else
285
- parent.text = data.to_s
286
- end
287
- end
288
-
289
- def extract_component_data(component_name, data)
290
- case component_name
291
- when "repository_analysis"
292
- data[:repository_analysis] || {}
293
- when "architecture_analysis"
294
- data[:architecture_analysis] || {}
295
- when "static_analysis"
296
- data[:static_analysis] || {}
297
- when "security_analysis"
298
- data[:security_analysis] || {}
299
- when "performance_analysis"
300
- data[:performance_analysis] || {}
301
- when "test_coverage"
302
- data[:test_coverage] || {}
303
- when "refactoring_recommendations"
304
- data[:refactoring_recommendations] || {}
305
- when "modernization_recommendations"
306
- data[:modernization_recommendations] || {}
307
- else
308
- data[component_name.to_sym] || {}
309
- end
310
- end
311
-
312
- def format_metrics_data(metrics_data)
313
- formatted = {
314
- metrics: {},
315
- summary: {},
316
- trends: {}
317
- }
318
-
319
- if metrics_data.is_a?(Hash)
320
- metrics_data.each do |category, metrics|
321
- if metrics.is_a?(Hash)
322
- formatted[:metrics][category] = metrics
323
- else
324
- formatted[:summary][category] = metrics
325
- end
326
- end
327
- end
328
-
329
- formatted
330
- end
331
-
332
- def prepare_comparison_data(before_data, after_data)
333
- {
334
- before: before_data,
335
- after: after_data,
336
- changes: calculate_changes(before_data, after_data),
337
- improvements: identify_improvements(before_data, after_data),
338
- regressions: identify_regressions(before_data, after_data)
339
- }
340
- end
341
-
342
- def calculate_changes(before_data, after_data)
343
- changes = {}
344
-
345
- # Compare metrics
346
- before_metrics = extract_metrics(before_data)
347
- after_metrics = extract_metrics(after_data)
348
-
349
- all_metrics = (before_metrics.keys + after_metrics.keys).uniq
350
-
351
- all_metrics.each do |metric|
352
- before_value = before_metrics[metric]
353
- after_value = after_metrics[metric]
354
-
355
- next unless before_value && after_value
356
-
357
- changes[metric] = {
358
- before: before_value,
359
- after: after_value,
360
- change: after_value - before_value,
361
- percentage_change: ((after_value - before_value) / before_value * 100).round(2)
362
- }
363
- end
364
-
365
- changes
366
- end
367
-
368
- def identify_improvements(before_data, after_data)
369
- improvements = []
370
-
371
- changes = calculate_changes(before_data, after_data)
372
- changes.each do |metric, change|
373
- next unless change[:change] > 0
374
-
375
- improvements << {
376
- metric: metric,
377
- improvement: change[:change],
378
- percentage: change[:percentage_change]
379
- }
380
- end
381
-
382
- improvements
383
- end
384
-
385
- def identify_regressions(before_data, after_data)
386
- regressions = []
387
-
388
- changes = calculate_changes(before_data, after_data)
389
- changes.each do |metric, change|
390
- next unless change[:change] < 0
391
-
392
- regressions << {
393
- metric: metric,
394
- regression: change[:change].abs,
395
- percentage: change[:percentage_change].abs
396
- }
397
- end
398
-
399
- regressions
400
- end
401
-
402
- def extract_metrics(data)
403
- metrics = {}
404
-
405
- if data.is_a?(Hash)
406
- data.each do |key, value|
407
- if value.is_a?(Numeric)
408
- metrics[key] = value
409
- elsif value.is_a?(Hash)
410
- metrics.merge!(extract_metrics(value))
411
- end
412
- end
413
- end
414
-
415
- metrics
416
- end
417
- end
418
- end