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
@@ -0,0 +1,382 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "config_loader"
4
+ require_relative "config_schema"
5
+ require_relative "provider_type_checker"
6
+
7
+ module Aidp
8
+ module Harness
9
+ # Unified configuration manager for harness
10
+ class ConfigManager
11
+ include ProviderTypeChecker
12
+
13
+ def initialize(project_dir = Dir.pwd)
14
+ @project_dir = project_dir
15
+ @loader = ConfigLoader.new(project_dir)
16
+ @cache = {}
17
+ @cache_timestamp = nil
18
+ end
19
+
20
+ # Get complete configuration
21
+ def get_config(options = {})
22
+ cache_key = "config_#{options.hash}"
23
+
24
+ if cache_valid?(cache_key)
25
+ return @cache[cache_key]
26
+ end
27
+
28
+ config = load_config_with_options(options)
29
+ @cache[cache_key] = config if config
30
+ config
31
+ end
32
+
33
+ # Get harness configuration
34
+ def get_harness_config(options = {})
35
+ config = get_config(options)
36
+ return nil unless config
37
+
38
+ config[:harness] || {}
39
+ end
40
+
41
+ # Get provider configuration
42
+ def get_provider_config(provider_name, options = {})
43
+ config = get_config(options)
44
+ return nil unless config
45
+
46
+ providers = config[:providers] || {}
47
+ providers[provider_name.to_sym] || providers[provider_name.to_s]
48
+ end
49
+
50
+ # Get all provider configurations
51
+ def get_all_providers(options = {})
52
+ config = get_config(options)
53
+ return {} unless config
54
+
55
+ config[:providers] || {}
56
+ end
57
+
58
+ # Get configured provider names
59
+ def get_provider_names(options = {})
60
+ providers = get_all_providers(options)
61
+ providers.keys.map(&:to_s)
62
+ end
63
+
64
+ # Get default provider
65
+ def get_default_provider(options = {})
66
+ harness_config = get_harness_config(options)
67
+ harness_config[:default_provider] || harness_config["default_provider"]
68
+ end
69
+
70
+ # Get fallback providers
71
+ def get_fallback_providers(options = {})
72
+ harness_config = get_harness_config(options)
73
+ fallback_providers = harness_config[:fallback_providers] || harness_config["fallback_providers"] || []
74
+
75
+ # Ensure fallback providers are configured
76
+ configured_providers = get_provider_names(options)
77
+ fallback_providers.select { |provider| configured_providers.include?(provider) }
78
+ end
79
+
80
+ # Get provider weights
81
+ def get_provider_weights(options = {})
82
+ harness_config = get_harness_config(options)
83
+ weights = harness_config[:provider_weights] || harness_config["provider_weights"] || {}
84
+
85
+ # Normalize weights to ensure they're positive integers
86
+ weights.transform_values { |weight| [weight.to_i, 1].max }
87
+ end
88
+
89
+ # Get retry configuration
90
+ def get_retry_config(options = {})
91
+ harness_config = get_harness_config(options)
92
+ retry_config = harness_config[:retry] || harness_config["retry"] || {}
93
+
94
+ {
95
+ enabled: retry_config[:enabled] != false,
96
+ max_attempts: retry_config[:max_attempts] || 3,
97
+ base_delay: retry_config[:base_delay] || 1.0,
98
+ max_delay: retry_config[:max_delay] || 60.0,
99
+ exponential_base: retry_config[:exponential_base] || 2.0,
100
+ jitter: retry_config[:jitter] != false
101
+ }
102
+ end
103
+
104
+ # Get circuit breaker configuration
105
+ def get_circuit_breaker_config(options = {})
106
+ harness_config = get_harness_config(options)
107
+ cb_config = harness_config[:circuit_breaker] || harness_config["circuit_breaker"] || {}
108
+
109
+ {
110
+ enabled: cb_config[:enabled] != false,
111
+ failure_threshold: cb_config[:failure_threshold] || 5,
112
+ timeout: cb_config[:timeout] || 300,
113
+ half_open_max_calls: cb_config[:half_open_max_calls] || 3
114
+ }
115
+ end
116
+
117
+ # Get rate limit configuration
118
+ def get_rate_limit_config(options = {})
119
+ harness_config = get_harness_config(options)
120
+ rate_limit_config = harness_config[:rate_limit] || harness_config["rate_limit"] || {}
121
+
122
+ {
123
+ enabled: rate_limit_config[:enabled] != false,
124
+ default_reset_time: rate_limit_config[:default_reset_time] || 3600,
125
+ burst_limit: rate_limit_config[:burst_limit] || 10,
126
+ sustained_limit: rate_limit_config[:sustained_limit] || 5
127
+ }
128
+ end
129
+
130
+ # Get load balancing configuration
131
+ def get_load_balancing_config(options = {})
132
+ harness_config = get_harness_config(options)
133
+ lb_config = harness_config[:load_balancing] || harness_config["load_balancing"] || {}
134
+
135
+ {
136
+ enabled: lb_config[:enabled] != false,
137
+ strategy: lb_config[:strategy] || "weighted_round_robin",
138
+ health_check_interval: lb_config[:health_check_interval] || 30,
139
+ unhealthy_threshold: lb_config[:unhealthy_threshold] || 3
140
+ }
141
+ end
142
+
143
+ # Get model switching configuration
144
+ def get_model_switching_config(options = {})
145
+ harness_config = get_harness_config(options)
146
+ ms_config = harness_config[:model_switching] || harness_config["model_switching"] || {}
147
+
148
+ {
149
+ enabled: ms_config[:enabled] != false,
150
+ auto_switch_on_error: ms_config[:auto_switch_on_error] != false,
151
+ auto_switch_on_rate_limit: ms_config[:auto_switch_on_rate_limit] != false,
152
+ fallback_strategy: ms_config[:fallback_strategy] || "sequential"
153
+ }
154
+ end
155
+
156
+ # Get health check configuration
157
+ def get_health_check_config(options = {})
158
+ harness_config = get_harness_config(options)
159
+ hc_config = harness_config[:health_check] || harness_config["health_check"] || {}
160
+
161
+ {
162
+ enabled: hc_config[:enabled] != false,
163
+ interval: hc_config[:interval] || 60,
164
+ timeout: hc_config[:timeout] || 10,
165
+ failure_threshold: hc_config[:failure_threshold] || 3,
166
+ success_threshold: hc_config[:success_threshold] || 2
167
+ }
168
+ end
169
+
170
+ # Get metrics configuration
171
+ def get_metrics_config(options = {})
172
+ harness_config = get_harness_config(options)
173
+ metrics_config = harness_config[:metrics] || harness_config["metrics"] || {}
174
+
175
+ {
176
+ enabled: metrics_config[:enabled] != false,
177
+ retention_days: metrics_config[:retention_days] || 30,
178
+ aggregation_interval: metrics_config[:aggregation_interval] || 300,
179
+ export_interval: metrics_config[:export_interval] || 3600
180
+ }
181
+ end
182
+
183
+ # Get session configuration
184
+ def get_session_config(options = {})
185
+ harness_config = get_harness_config(options)
186
+ session_config = harness_config[:session] || harness_config["session"] || {}
187
+
188
+ {
189
+ enabled: session_config[:enabled] != false,
190
+ timeout: session_config[:timeout] || 1800,
191
+ sticky_sessions: session_config[:sticky_sessions] != false,
192
+ session_affinity: session_config[:session_affinity] || "provider_model"
193
+ }
194
+ end
195
+
196
+ # Get provider models
197
+ def get_provider_models(provider_name, options = {})
198
+ provider_config = get_provider_config(provider_name, options)
199
+ return [] unless provider_config
200
+
201
+ models = provider_config[:models] || provider_config["models"] || []
202
+ models.map(&:to_s)
203
+ end
204
+
205
+ # Get provider model weights
206
+ def get_provider_model_weights(provider_name, options = {})
207
+ provider_config = get_provider_config(provider_name, options)
208
+ return {} unless provider_config
209
+
210
+ weights = provider_config[:model_weights] || provider_config["model_weights"] || {}
211
+ weights.transform_values { |weight| [weight.to_i, 1].max }
212
+ end
213
+
214
+ # Get provider model configuration
215
+ def get_provider_model_config(provider_name, model_name, options = {})
216
+ provider_config = get_provider_config(provider_name, options)
217
+ return {} unless provider_config
218
+
219
+ models_config = provider_config[:models_config] || provider_config["models_config"] || {}
220
+ model_config = models_config[model_name.to_sym] || models_config[model_name.to_s] || {}
221
+
222
+ {
223
+ flags: model_config[:flags] || model_config["flags"] || [],
224
+ max_tokens: model_config[:max_tokens] || model_config["max_tokens"],
225
+ timeout: model_config[:timeout] || model_config["timeout"]
226
+ }
227
+ end
228
+
229
+ # Get provider features
230
+ def get_provider_features(provider_name, options = {})
231
+ provider_config = get_provider_config(provider_name, options)
232
+ return {} unless provider_config
233
+
234
+ features = provider_config[:features] || provider_config["features"] || {}
235
+
236
+ {
237
+ file_upload: features[:file_upload] == true,
238
+ code_generation: features[:code_generation] != false,
239
+ analysis: features[:analysis] != false,
240
+ vision: features[:vision] == true
241
+ }
242
+ end
243
+
244
+ # Get provider monitoring configuration
245
+ def get_provider_monitoring_config(provider_name, options = {})
246
+ provider_config = get_provider_config(provider_name, options)
247
+ return {} unless provider_config
248
+
249
+ monitoring = provider_config[:monitoring] || provider_config["monitoring"] || {}
250
+
251
+ {
252
+ enabled: monitoring[:enabled] != false,
253
+ metrics_interval: monitoring[:metrics_interval] || 60
254
+ }
255
+ end
256
+
257
+ # Check if provider supports feature
258
+ def provider_supports_feature?(provider_name, feature, options = {})
259
+ features = get_provider_features(provider_name, options)
260
+ features[feature.to_sym] == true
261
+ end
262
+
263
+ # Get provider priority
264
+ def get_provider_priority(provider_name, options = {})
265
+ provider_config = get_provider_config(provider_name, options)
266
+ return 1 unless provider_config
267
+
268
+ provider_config[:priority] || provider_config["priority"] || 1
269
+ end
270
+
271
+ # Get provider type
272
+ def get_provider_type(provider_name, options = {})
273
+ provider_config = get_provider_config(provider_name, options)
274
+ return nil unless provider_config
275
+
276
+ provider_config[:type] || provider_config["type"]
277
+ end
278
+
279
+ # Provider type checking methods are now provided by ProviderTypeChecker module
280
+
281
+ # Get provider max tokens
282
+ def get_provider_max_tokens(provider_name, options = {})
283
+ provider_config = get_provider_config(provider_name, options)
284
+ return nil unless provider_config
285
+
286
+ provider_config[:max_tokens] || provider_config["max_tokens"]
287
+ end
288
+
289
+ # Get provider default flags
290
+ def get_provider_default_flags(provider_name, options = {})
291
+ provider_config = get_provider_config(provider_name, options)
292
+ return [] unless provider_config
293
+
294
+ flags = provider_config[:default_flags] || provider_config["default_flags"] || []
295
+ flags.map(&:to_s)
296
+ end
297
+
298
+ # Get provider auth configuration
299
+ def get_provider_auth_config(provider_name, options = {})
300
+ provider_config = get_provider_config(provider_name, options)
301
+ return {} unless provider_config
302
+
303
+ auth = provider_config[:auth] || provider_config["auth"] || {}
304
+
305
+ {
306
+ api_key_env: auth[:api_key_env] || auth["api_key_env"],
307
+ api_key: auth[:api_key] || auth["api_key"]
308
+ }
309
+ end
310
+
311
+ # Get provider endpoints
312
+ def get_provider_endpoints(provider_name, options = {})
313
+ provider_config = get_provider_config(provider_name, options)
314
+ return {} unless provider_config
315
+
316
+ endpoints = provider_config[:endpoints] || provider_config["endpoints"] || {}
317
+
318
+ {
319
+ default: endpoints[:default] || endpoints["default"]
320
+ }
321
+ end
322
+
323
+ # Check if configuration is valid
324
+ def config_valid?
325
+ @loader.config_valid?
326
+ end
327
+
328
+ # Get validation errors
329
+ def get_validation_errors
330
+ @loader.get_validation_errors
331
+ end
332
+
333
+ # Get validation warnings
334
+ def get_validation_warnings
335
+ @loader.get_validation_warnings
336
+ end
337
+
338
+ # Reload configuration
339
+ def reload_config
340
+ @cache.clear
341
+ @cache_timestamp = nil
342
+ @loader.reload_config
343
+ end
344
+
345
+ # Get configuration summary
346
+ def get_config_summary
347
+ @loader.get_config_summary
348
+ end
349
+
350
+ private
351
+
352
+ def load_config_with_options(options)
353
+ # Apply different loading strategies based on options
354
+ if options[:mode]
355
+ @loader.get_mode_config(options[:mode], options[:force_reload])
356
+ elsif options[:environment]
357
+ @loader.get_environment_config(options[:environment], options[:force_reload])
358
+ elsif options[:step]
359
+ @loader.get_step_config(options[:step], options[:force_reload])
360
+ elsif options[:features]
361
+ @loader.get_config_with_features(options[:features], options[:force_reload])
362
+ elsif options[:user]
363
+ @loader.get_user_config(options[:user], options[:force_reload])
364
+ elsif options[:time_based]
365
+ @loader.get_time_based_config(options[:force_reload])
366
+ elsif options[:overrides]
367
+ @loader.get_config_with_overrides(options[:overrides])
368
+ else
369
+ @loader.load_config(options[:force_reload])
370
+ end
371
+ end
372
+
373
+ def cache_valid?(cache_key)
374
+ return false unless @cache[cache_key]
375
+ return false unless @cache_timestamp
376
+
377
+ # Cache is valid for 5 minutes
378
+ Time.now - @cache_timestamp < 300
379
+ end
380
+ end
381
+ end
382
+ end