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
@@ -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