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,454 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "concurrent"
4
- require "json"
5
-
6
- module Aidp
7
- module Analyze
8
- class ParallelProcessor
9
- # Default configuration
10
- DEFAULT_CONFIG = {
11
- max_workers: 4,
12
- chunk_size: 10,
13
- timeout: 300, # 5 minutes
14
- retry_attempts: 2,
15
- memory_limit: 1024 * 1024 * 1024, # 1GB
16
- cpu_limit: 0.8 # 80% CPU usage
17
- }.freeze
18
-
19
- def initialize(config = {})
20
- @config = DEFAULT_CONFIG.merge(config)
21
- @executor = nil
22
- @results = Concurrent::Array.new
23
- @errors = Concurrent::Array.new
24
- @progress = Concurrent::AtomicFixnum.new(0)
25
- end
26
-
27
- # Process chunks in parallel
28
- def process_chunks_parallel(chunks, processor_method, options = {})
29
- return [] if chunks.empty?
30
-
31
- setup_executor
32
- start_time = Time.now
33
-
34
- results = {
35
- total_chunks: chunks.length,
36
- processed_chunks: 0,
37
- failed_chunks: 0,
38
- start_time: start_time,
39
- end_time: nil,
40
- duration: nil,
41
- results: [],
42
- errors: [],
43
- statistics: {}
44
- }
45
-
46
- begin
47
- # Create futures for each chunk
48
- futures = create_futures(chunks, processor_method, options)
49
-
50
- # Wait for all futures to complete
51
- completed_futures = wait_for_completion(futures, options)
52
-
53
- # Collect results
54
- collect_results(completed_futures, results)
55
- rescue => e
56
- results[:errors] << {
57
- type: "processing_error",
58
- message: e.message,
59
- backtrace: e.backtrace
60
- }
61
- ensure
62
- cleanup_executor
63
- results[:end_time] = Time.now
64
- results[:duration] = results[:end_time] - results[:start_time]
65
- results[:statistics] = calculate_statistics(results)
66
- end
67
-
68
- results
69
- end
70
-
71
- # Process chunks with dependency management
72
- def process_chunks_with_dependencies(chunks, dependencies, processor_method, options = {})
73
- return [] if chunks.empty?
74
-
75
- setup_executor
76
- start_time = Time.now
77
-
78
- results = {
79
- total_chunks: chunks.length,
80
- processed_chunks: 0,
81
- failed_chunks: 0,
82
- start_time: start_time,
83
- end_time: nil,
84
- duration: nil,
85
- results: [],
86
- errors: [],
87
- execution_order: [],
88
- statistics: {}
89
- }
90
-
91
- begin
92
- # Create execution plan based on dependencies
93
- execution_plan = create_execution_plan(chunks, dependencies)
94
-
95
- # Execute chunks in dependency order
96
- execution_plan.each do |phase|
97
- phase_results = process_phase_parallel(phase, processor_method, options)
98
- results[:results].concat(phase_results[:results])
99
- results[:errors].concat(phase_results[:errors])
100
- results[:processed_chunks] += phase_results[:processed_chunks]
101
- results[:failed_chunks] += phase_results[:failed_chunks]
102
- results[:execution_order].concat(phase.map { |chunk| chunk[:id] })
103
- end
104
- rescue => e
105
- results[:errors] << {
106
- type: "dependency_error",
107
- message: e.message,
108
- backtrace: e.backtrace
109
- }
110
- ensure
111
- cleanup_executor
112
- results[:end_time] = Time.now
113
- results[:duration] = results[:end_time] - results[:start_time]
114
- results[:statistics] = calculate_statistics(results)
115
- end
116
-
117
- results
118
- end
119
-
120
- # Process chunks with resource management
121
- def process_chunks_with_resource_management(chunks, processor_method, options = {})
122
- return [] if chunks.empty?
123
-
124
- setup_executor
125
- start_time = Time.now
126
-
127
- results = {
128
- total_chunks: chunks.length,
129
- processed_chunks: 0,
130
- failed_chunks: 0,
131
- start_time: start_time,
132
- end_time: nil,
133
- duration: nil,
134
- results: [],
135
- errors: [],
136
- resource_usage: {},
137
- statistics: {}
138
- }
139
-
140
- begin
141
- # Monitor system resources
142
- resource_monitor = start_resource_monitoring
143
-
144
- # Process chunks with resource constraints
145
- chunk_results = process_with_resource_constraints(chunks, processor_method, options, resource_monitor)
146
-
147
- results[:results] = chunk_results[:results]
148
- results[:errors] = chunk_results[:errors]
149
- results[:processed_chunks] = chunk_results[:processed_chunks]
150
- results[:failed_chunks] = chunk_results[:failed_chunks]
151
- results[:resource_usage] = resource_monitor[:usage]
152
- rescue => e
153
- results[:errors] << {
154
- type: "resource_error",
155
- message: e.message,
156
- backtrace: e.backtrace
157
- }
158
- ensure
159
- stop_resource_monitoring
160
- cleanup_executor
161
- results[:end_time] = Time.now
162
- results[:duration] = results[:end_time] - results[:start_time]
163
- results[:statistics] = calculate_statistics(results)
164
- end
165
-
166
- results
167
- end
168
-
169
- # Get processing statistics
170
- def get_processing_statistics
171
- {
172
- total_processed: @progress.value,
173
- total_errors: @errors.length,
174
- executor_status: executor_status,
175
- memory_usage: get_memory_usage,
176
- cpu_usage: get_cpu_usage
177
- }
178
- end
179
-
180
- # Cancel ongoing processing
181
- def cancel_processing
182
- cleanup_executor
183
- {
184
- cancelled: true,
185
- processed_count: @progress.value,
186
- error_count: @errors.length
187
- }
188
- end
189
-
190
- private
191
-
192
- def setup_executor
193
- @executor = Concurrent::ThreadPoolExecutor.new(
194
- min_threads: 1,
195
- max_threads: @config[:max_workers],
196
- max_queue: @config[:max_workers] * 2,
197
- fallback_policy: :caller_runs
198
- )
199
- end
200
-
201
- def cleanup_executor
202
- return unless @executor
203
-
204
- @executor.shutdown
205
- @executor.wait_for_termination(@config[:timeout])
206
- @executor = nil
207
- end
208
-
209
- def create_futures(chunks, processor_method, options)
210
- futures = []
211
-
212
- chunks.each_with_index do |chunk, index|
213
- future = @executor.post do
214
- process_chunk_with_retry(chunk, processor_method, options, index)
215
- end
216
-
217
- futures << {
218
- future: future,
219
- chunk: chunk,
220
- index: index
221
- }
222
- end
223
-
224
- futures
225
- end
226
-
227
- def wait_for_completion(futures, options)
228
- timeout = options[:timeout] || @config[:timeout]
229
- completed_futures = []
230
-
231
- futures.each do |future_info|
232
- result = future_info[:future].value(timeout)
233
- completed_futures << {
234
- chunk: future_info[:chunk],
235
- result: result,
236
- index: future_info[:index]
237
- }
238
- @progress.increment
239
- end
240
-
241
- completed_futures
242
- end
243
-
244
- def collect_results(completed_futures, results)
245
- completed_futures.each do |future_result|
246
- if future_result[:result][:success]
247
- results[:results] << future_result[:result]
248
- results[:processed_chunks] += 1
249
- else
250
- results[:errors] << {
251
- chunk_id: future_result[:chunk][:id],
252
- error: future_result[:result][:error],
253
- index: future_result[:index]
254
- }
255
- results[:failed_chunks] += 1
256
- end
257
- end
258
- end
259
-
260
- def process_chunk_with_retry(chunk, processor_method, options, index)
261
- retry_attempts = options[:retry_attempts] || @config[:retry_attempts]
262
- attempt = 0
263
-
264
- begin
265
- attempt += 1
266
- result = processor_method.call(chunk, options)
267
- result[:success] = true
268
- result[:attempt] = attempt
269
- result
270
- rescue => e
271
- if attempt < retry_attempts
272
- sleep(2**attempt) # Exponential backoff
273
- retry
274
- else
275
- {
276
- success: false,
277
- error: e.message,
278
- attempt: attempt,
279
- chunk_id: chunk[:id]
280
- }
281
- end
282
- end
283
- end
284
-
285
- def create_execution_plan(chunks, dependencies)
286
- # Create a topological sort of chunks based on dependencies
287
- execution_plan = []
288
- remaining_chunks = chunks.dup
289
- completed_chunks = Set.new
290
-
291
- until remaining_chunks.empty?
292
- phase = []
293
-
294
- remaining_chunks.each do |chunk|
295
- chunk_deps = dependencies[chunk[:id]] || []
296
- phase << chunk if chunk_deps.all? { |dep| completed_chunks.include?(dep) }
297
- end
298
-
299
- if phase.empty?
300
- # Circular dependency detected
301
- raise "Circular dependency detected in chunks"
302
- end
303
-
304
- execution_plan << phase
305
- phase.each { |chunk| completed_chunks.add(chunk[:id]) }
306
- remaining_chunks.reject! { |chunk| phase.include?(chunk) }
307
- end
308
-
309
- execution_plan
310
- end
311
-
312
- def process_phase_parallel(phase_chunks, processor_method, options)
313
- return {results: [], errors: [], processed_chunks: 0, failed_chunks: 0} if phase_chunks.empty?
314
-
315
- phase_results = process_chunks_parallel(phase_chunks, processor_method, options)
316
-
317
- {
318
- results: phase_results[:results],
319
- errors: phase_results[:errors],
320
- processed_chunks: phase_results[:processed_chunks],
321
- failed_chunks: phase_results[:failed_chunks]
322
- }
323
- end
324
-
325
- def start_resource_monitoring
326
- monitor = {
327
- start_time: Time.now,
328
- usage: {
329
- memory: [],
330
- cpu: [],
331
- disk: []
332
- },
333
- running: true
334
- }
335
-
336
- # Start monitoring thread
337
- Thread.new do
338
- while monitor[:running]
339
- monitor[:usage][:memory] << get_memory_usage
340
- monitor[:usage][:cpu] << get_cpu_usage
341
- monitor[:usage][:disk] << get_disk_usage
342
- sleep(1)
343
- end
344
- end
345
-
346
- monitor
347
- end
348
-
349
- def stop_resource_monitoring
350
- # This would be called to stop the monitoring thread
351
- # For now, just return
352
- end
353
-
354
- def process_with_resource_constraints(chunks, processor_method, options, resource_monitor)
355
- results = {
356
- results: [],
357
- errors: [],
358
- processed_chunks: 0,
359
- failed_chunks: 0
360
- }
361
-
362
- chunks.each do |chunk|
363
- # Check resource constraints
364
- if resource_constraints_exceeded(resource_monitor)
365
- # Wait for resources to become available
366
- wait_for_resources(resource_monitor)
367
- end
368
-
369
- # Process chunk
370
- begin
371
- result = processor_method.call(chunk, options)
372
- if result[:success]
373
- results[:results] << result
374
- results[:processed_chunks] += 1
375
- else
376
- results[:errors] << {
377
- chunk_id: chunk[:id],
378
- error: result[:error]
379
- }
380
- results[:failed_chunks] += 1
381
- end
382
- rescue => e
383
- results[:errors] << {
384
- chunk_id: chunk[:id],
385
- error: e.message
386
- }
387
- results[:failed_chunks] += 1
388
- end
389
- end
390
-
391
- results
392
- end
393
-
394
- def resource_constraints_exceeded(resource_monitor)
395
- memory_usage = get_memory_usage
396
- cpu_usage = get_cpu_usage
397
-
398
- memory_usage > @config[:memory_limit] || cpu_usage > @config[:cpu_limit]
399
- end
400
-
401
- def wait_for_resources(resource_monitor)
402
- # Wait until resources are available
403
- sleep(1)
404
- end
405
-
406
- def get_memory_usage
407
- # Get current memory usage
408
- # This is a simplified implementation
409
- Process.getrusage(:SELF).maxrss * 1024 # Convert to bytes
410
- end
411
-
412
- def get_cpu_usage
413
- # Get current CPU usage
414
- # This is a simplified implementation
415
- 0.5 # Return 50% as default
416
- end
417
-
418
- def get_disk_usage
419
- # Get current disk usage
420
- # This is a simplified implementation
421
- 0.3 # Return 30% as default
422
- end
423
-
424
- def executor_status
425
- return "not_initialized" unless @executor
426
-
427
- if @executor.shutdown?
428
- "shutdown"
429
- elsif @executor.shuttingdown?
430
- "shutting_down"
431
- else
432
- "running"
433
- end
434
- end
435
-
436
- def calculate_statistics(results)
437
- return {} if results[:results].empty?
438
-
439
- durations = results[:results].map { |r| r[:duration] || 0 }
440
- memory_usage = results[:results].map { |r| r[:memory_usage] || 0 }
441
-
442
- {
443
- average_duration: durations.sum.to_f / durations.length,
444
- min_duration: durations.min,
445
- max_duration: durations.max,
446
- total_duration: durations.sum,
447
- average_memory: memory_usage.sum.to_f / memory_usage.length,
448
- success_rate: results[:processed_chunks].to_f / results[:total_chunks] * 100,
449
- throughput: results[:processed_chunks].to_f / results[:duration]
450
- }
451
- end
452
- end
453
- end
454
- end