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.
- checksums.yaml +4 -4
- data/README.md +128 -151
- data/bin/aidp +1 -1
- data/lib/aidp/analysis/kb_inspector.rb +471 -0
- data/lib/aidp/analysis/seams.rb +159 -0
- data/lib/aidp/analysis/tree_sitter_grammar_loader.rb +480 -0
- data/lib/aidp/analysis/tree_sitter_scan.rb +686 -0
- data/lib/aidp/analyze/error_handler.rb +2 -78
- data/lib/aidp/analyze/json_file_storage.rb +292 -0
- data/lib/aidp/analyze/progress.rb +12 -0
- data/lib/aidp/analyze/progress_visualizer.rb +12 -17
- data/lib/aidp/analyze/ruby_maat_integration.rb +13 -31
- data/lib/aidp/analyze/runner.rb +256 -87
- data/lib/aidp/analyze/steps.rb +6 -0
- data/lib/aidp/cli/jobs_command.rb +103 -435
- data/lib/aidp/cli.rb +317 -191
- data/lib/aidp/config.rb +298 -10
- data/lib/aidp/debug_logger.rb +195 -0
- data/lib/aidp/debug_mixin.rb +187 -0
- data/lib/aidp/execute/progress.rb +9 -0
- data/lib/aidp/execute/runner.rb +221 -40
- data/lib/aidp/execute/steps.rb +17 -7
- data/lib/aidp/execute/workflow_selector.rb +211 -0
- data/lib/aidp/harness/completion_checker.rb +268 -0
- data/lib/aidp/harness/condition_detector.rb +1526 -0
- data/lib/aidp/harness/config_loader.rb +373 -0
- data/lib/aidp/harness/config_manager.rb +382 -0
- data/lib/aidp/harness/config_schema.rb +1006 -0
- data/lib/aidp/harness/config_validator.rb +355 -0
- data/lib/aidp/harness/configuration.rb +477 -0
- data/lib/aidp/harness/enhanced_runner.rb +494 -0
- data/lib/aidp/harness/error_handler.rb +616 -0
- data/lib/aidp/harness/provider_config.rb +423 -0
- data/lib/aidp/harness/provider_factory.rb +306 -0
- data/lib/aidp/harness/provider_manager.rb +1269 -0
- data/lib/aidp/harness/provider_type_checker.rb +88 -0
- data/lib/aidp/harness/runner.rb +411 -0
- data/lib/aidp/harness/state/errors.rb +28 -0
- data/lib/aidp/harness/state/metrics.rb +219 -0
- data/lib/aidp/harness/state/persistence.rb +128 -0
- data/lib/aidp/harness/state/provider_state.rb +132 -0
- data/lib/aidp/harness/state/ui_state.rb +68 -0
- data/lib/aidp/harness/state/workflow_state.rb +123 -0
- data/lib/aidp/harness/state_manager.rb +586 -0
- data/lib/aidp/harness/status_display.rb +888 -0
- data/lib/aidp/harness/ui/base.rb +16 -0
- data/lib/aidp/harness/ui/enhanced_tui.rb +545 -0
- data/lib/aidp/harness/ui/enhanced_workflow_selector.rb +252 -0
- data/lib/aidp/harness/ui/error_handler.rb +132 -0
- data/lib/aidp/harness/ui/frame_manager.rb +361 -0
- data/lib/aidp/harness/ui/job_monitor.rb +500 -0
- data/lib/aidp/harness/ui/navigation/main_menu.rb +311 -0
- data/lib/aidp/harness/ui/navigation/menu_formatter.rb +120 -0
- data/lib/aidp/harness/ui/navigation/menu_item.rb +142 -0
- data/lib/aidp/harness/ui/navigation/menu_state.rb +139 -0
- data/lib/aidp/harness/ui/navigation/submenu.rb +202 -0
- data/lib/aidp/harness/ui/navigation/workflow_selector.rb +176 -0
- data/lib/aidp/harness/ui/progress_display.rb +280 -0
- data/lib/aidp/harness/ui/question_collector.rb +141 -0
- data/lib/aidp/harness/ui/spinner_group.rb +184 -0
- data/lib/aidp/harness/ui/spinner_helper.rb +152 -0
- data/lib/aidp/harness/ui/status_manager.rb +312 -0
- data/lib/aidp/harness/ui/status_widget.rb +280 -0
- data/lib/aidp/harness/ui/workflow_controller.rb +312 -0
- data/lib/aidp/harness/user_interface.rb +2381 -0
- data/lib/aidp/provider_manager.rb +131 -7
- data/lib/aidp/providers/anthropic.rb +28 -109
- data/lib/aidp/providers/base.rb +170 -0
- data/lib/aidp/providers/cursor.rb +52 -183
- data/lib/aidp/providers/gemini.rb +24 -109
- data/lib/aidp/providers/macos_ui.rb +99 -5
- data/lib/aidp/providers/opencode.rb +194 -0
- data/lib/aidp/storage/csv_storage.rb +172 -0
- data/lib/aidp/storage/file_manager.rb +214 -0
- data/lib/aidp/storage/json_storage.rb +140 -0
- data/lib/aidp/version.rb +1 -1
- data/lib/aidp.rb +56 -35
- data/templates/ANALYZE/06a_tree_sitter_scan.md +217 -0
- data/templates/COMMON/AGENT_BASE.md +11 -0
- data/templates/EXECUTE/00_PRD.md +4 -4
- data/templates/EXECUTE/02_ARCHITECTURE.md +5 -4
- data/templates/EXECUTE/07_TEST_PLAN.md +4 -1
- data/templates/EXECUTE/08_TASKS.md +4 -4
- data/templates/EXECUTE/10_IMPLEMENTATION_AGENT.md +4 -4
- data/templates/README.md +279 -0
- data/templates/aidp-development.yml.example +373 -0
- data/templates/aidp-minimal.yml.example +48 -0
- data/templates/aidp-production.yml.example +475 -0
- data/templates/aidp.yml.example +598 -0
- metadata +106 -64
- data/lib/aidp/analyze/agent_personas.rb +0 -71
- data/lib/aidp/analyze/agent_tool_executor.rb +0 -445
- data/lib/aidp/analyze/data_retention_manager.rb +0 -426
- data/lib/aidp/analyze/database.rb +0 -260
- data/lib/aidp/analyze/dependencies.rb +0 -335
- data/lib/aidp/analyze/export_manager.rb +0 -425
- data/lib/aidp/analyze/focus_guidance.rb +0 -517
- data/lib/aidp/analyze/incremental_analyzer.rb +0 -543
- data/lib/aidp/analyze/language_analysis_strategies.rb +0 -897
- data/lib/aidp/analyze/large_analysis_progress.rb +0 -504
- data/lib/aidp/analyze/memory_manager.rb +0 -365
- data/lib/aidp/analyze/metrics_storage.rb +0 -336
- data/lib/aidp/analyze/parallel_processor.rb +0 -460
- data/lib/aidp/analyze/performance_optimizer.rb +0 -694
- data/lib/aidp/analyze/repository_chunker.rb +0 -704
- data/lib/aidp/analyze/static_analysis_detector.rb +0 -577
- data/lib/aidp/analyze/storage.rb +0 -662
- data/lib/aidp/analyze/tool_configuration.rb +0 -456
- data/lib/aidp/analyze/tool_modernization.rb +0 -750
- data/lib/aidp/database/pg_adapter.rb +0 -148
- data/lib/aidp/database_config.rb +0 -69
- data/lib/aidp/database_connection.rb +0 -72
- data/lib/aidp/database_migration.rb +0 -158
- data/lib/aidp/job_manager.rb +0 -41
- data/lib/aidp/jobs/base_job.rb +0 -47
- data/lib/aidp/jobs/provider_execution_job.rb +0 -96
- data/lib/aidp/project_detector.rb +0 -117
- data/lib/aidp/providers/agent_supervisor.rb +0 -348
- data/lib/aidp/providers/supervised_base.rb +0 -317
- data/lib/aidp/providers/supervised_cursor.rb +0 -22
- data/lib/aidp/sync.rb +0 -13
- data/lib/aidp/workspace.rb +0 -19
@@ -0,0 +1,373 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
require_relative "config_schema"
|
5
|
+
require_relative "config_validator"
|
6
|
+
|
7
|
+
module Aidp
|
8
|
+
module Harness
|
9
|
+
# Enhanced configuration loader for harness
|
10
|
+
class ConfigLoader
|
11
|
+
def initialize(project_dir = Dir.pwd)
|
12
|
+
@project_dir = project_dir
|
13
|
+
@validator = ConfigValidator.new(project_dir)
|
14
|
+
@config_cache = nil
|
15
|
+
@last_loaded = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
# Load and validate configuration with caching
|
19
|
+
def load_config(force_reload = false)
|
20
|
+
return @config_cache if @config_cache && !force_reload && !config_file_changed?
|
21
|
+
|
22
|
+
# Load and validate configuration
|
23
|
+
validation_result = @validator.load_and_validate
|
24
|
+
|
25
|
+
if validation_result[:valid]
|
26
|
+
@config_cache = @validator.get_validated_config
|
27
|
+
@last_loaded = Time.now
|
28
|
+
|
29
|
+
# Log warnings if any
|
30
|
+
unless validation_result[:warnings].empty?
|
31
|
+
log_warnings(validation_result[:warnings])
|
32
|
+
end
|
33
|
+
|
34
|
+
@config_cache
|
35
|
+
else
|
36
|
+
# Handle validation errors
|
37
|
+
handle_validation_errors(validation_result[:errors])
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Get harness configuration with defaults
|
43
|
+
def get_harness_config(force_reload = false)
|
44
|
+
config = load_config(force_reload)
|
45
|
+
return nil unless config
|
46
|
+
|
47
|
+
config[:harness] || {}
|
48
|
+
end
|
49
|
+
|
50
|
+
# Get provider configuration with defaults
|
51
|
+
def get_provider_config(provider_name, force_reload = false)
|
52
|
+
config = load_config(force_reload)
|
53
|
+
return nil unless config
|
54
|
+
|
55
|
+
providers = config[:providers] || {}
|
56
|
+
providers[provider_name.to_sym] || providers[provider_name.to_s]
|
57
|
+
end
|
58
|
+
|
59
|
+
# Get all provider configurations
|
60
|
+
def get_all_provider_configs(force_reload = false)
|
61
|
+
config = load_config(force_reload)
|
62
|
+
return {} unless config
|
63
|
+
|
64
|
+
config[:providers] || {}
|
65
|
+
end
|
66
|
+
|
67
|
+
# Get configured provider names
|
68
|
+
def get_configured_providers(force_reload = false)
|
69
|
+
config = load_config(force_reload)
|
70
|
+
return [] unless config
|
71
|
+
|
72
|
+
providers = config[:providers] || {}
|
73
|
+
providers.keys.map(&:to_s)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Check if configuration exists
|
77
|
+
def config_exists?
|
78
|
+
@validator.config_exists?
|
79
|
+
end
|
80
|
+
|
81
|
+
# Get configuration file path
|
82
|
+
def config_file_path
|
83
|
+
@validator.config_file_path
|
84
|
+
end
|
85
|
+
|
86
|
+
# Create example configuration
|
87
|
+
def create_example_config
|
88
|
+
@validator.create_example_config
|
89
|
+
end
|
90
|
+
|
91
|
+
# Fix configuration issues
|
92
|
+
def fix_config_issues
|
93
|
+
@validator.fix_common_issues
|
94
|
+
end
|
95
|
+
|
96
|
+
# Get configuration summary
|
97
|
+
def get_config_summary
|
98
|
+
@validator.get_summary
|
99
|
+
end
|
100
|
+
|
101
|
+
# Validate specific provider
|
102
|
+
def validate_provider(provider_name)
|
103
|
+
@validator.validate_provider(provider_name)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Check if provider is configured
|
107
|
+
def provider_configured?(provider_name)
|
108
|
+
@validator.provider_configured?(provider_name)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Get configuration with specific overrides
|
112
|
+
def get_config_with_overrides(overrides = {})
|
113
|
+
base_config = load_config
|
114
|
+
return nil unless base_config
|
115
|
+
|
116
|
+
merge_overrides(base_config, overrides)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Get harness configuration with overrides
|
120
|
+
def get_harness_config_with_overrides(overrides = {})
|
121
|
+
harness_config = get_harness_config
|
122
|
+
return nil unless harness_config
|
123
|
+
|
124
|
+
harness_overrides = overrides[:harness] || overrides["harness"] || {}
|
125
|
+
deep_merge(harness_config, harness_overrides)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Get provider configuration with overrides
|
129
|
+
def get_provider_config_with_overrides(provider_name, overrides = {})
|
130
|
+
provider_config = get_provider_config(provider_name)
|
131
|
+
return nil unless provider_config
|
132
|
+
|
133
|
+
provider_overrides = overrides[:providers]&.dig(provider_name.to_sym) ||
|
134
|
+
overrides[:providers]&.dig(provider_name.to_s) ||
|
135
|
+
overrides["providers"]&.dig(provider_name.to_s) ||
|
136
|
+
overrides["providers"]&.dig(provider_name.to_sym) ||
|
137
|
+
{}
|
138
|
+
|
139
|
+
deep_merge(provider_config, provider_overrides)
|
140
|
+
end
|
141
|
+
|
142
|
+
# Export configuration
|
143
|
+
def export_config(format = :yaml)
|
144
|
+
@validator.export_config(format)
|
145
|
+
end
|
146
|
+
|
147
|
+
# Reload configuration from file
|
148
|
+
def reload_config
|
149
|
+
@config_cache = nil
|
150
|
+
@last_loaded = nil
|
151
|
+
load_config(true)
|
152
|
+
end
|
153
|
+
|
154
|
+
# Check if configuration is valid
|
155
|
+
def config_valid?
|
156
|
+
validation_result = @validator.validate_existing
|
157
|
+
validation_result[:valid]
|
158
|
+
end
|
159
|
+
|
160
|
+
# Get validation errors
|
161
|
+
def get_validation_errors
|
162
|
+
validation_result = @validator.validate_existing
|
163
|
+
validation_result[:errors] || []
|
164
|
+
end
|
165
|
+
|
166
|
+
# Get validation warnings
|
167
|
+
def get_validation_warnings
|
168
|
+
validation_result = @validator.validate_existing
|
169
|
+
validation_result[:warnings] || []
|
170
|
+
end
|
171
|
+
|
172
|
+
# Get configuration for specific harness mode
|
173
|
+
def get_mode_config(mode, force_reload = false)
|
174
|
+
config = load_config(force_reload)
|
175
|
+
return nil unless config
|
176
|
+
|
177
|
+
case mode.to_s
|
178
|
+
when "analyze"
|
179
|
+
get_analyze_mode_config(config)
|
180
|
+
when "execute"
|
181
|
+
get_execute_mode_config(config)
|
182
|
+
else
|
183
|
+
config
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# Get environment-specific configuration
|
188
|
+
def get_environment_config(environment = nil, force_reload = false)
|
189
|
+
environment ||= ENV["AIDP_ENV"] || "development"
|
190
|
+
config = load_config(force_reload)
|
191
|
+
return nil unless config
|
192
|
+
|
193
|
+
env_config = config[:environments]&.dig(environment.to_sym) ||
|
194
|
+
config[:environments]&.dig(environment.to_s) ||
|
195
|
+
config["environments"]&.dig(environment.to_s) ||
|
196
|
+
config["environments"]&.dig(environment.to_sym) ||
|
197
|
+
{}
|
198
|
+
|
199
|
+
merge_overrides(config, env_config)
|
200
|
+
end
|
201
|
+
|
202
|
+
# Get configuration for specific step
|
203
|
+
def get_step_config(step_name, force_reload = false)
|
204
|
+
config = load_config(force_reload)
|
205
|
+
return nil unless config
|
206
|
+
|
207
|
+
step_config = config[:steps]&.dig(step_name.to_sym) ||
|
208
|
+
config[:steps]&.dig(step_name.to_s) ||
|
209
|
+
config["steps"]&.dig(step_name.to_s) ||
|
210
|
+
config["steps"]&.dig(step_name.to_sym) ||
|
211
|
+
{}
|
212
|
+
|
213
|
+
merge_overrides(config, step_config)
|
214
|
+
end
|
215
|
+
|
216
|
+
# Get configuration with feature flags
|
217
|
+
def get_config_with_features(features = {}, force_reload = false)
|
218
|
+
config = load_config(force_reload)
|
219
|
+
return nil unless config
|
220
|
+
|
221
|
+
feature_overrides = {}
|
222
|
+
|
223
|
+
features.each do |feature, enabled|
|
224
|
+
if enabled
|
225
|
+
feature_config = config[:features]&.dig(feature.to_sym) ||
|
226
|
+
config[:features]&.dig(feature.to_s) ||
|
227
|
+
config["features"]&.dig(feature.to_s) ||
|
228
|
+
config["features"]&.dig(feature.to_sym) ||
|
229
|
+
{}
|
230
|
+
feature_overrides = deep_merge(feature_overrides, feature_config)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
merge_overrides(config, feature_overrides)
|
235
|
+
end
|
236
|
+
|
237
|
+
# Get configuration for specific user
|
238
|
+
def get_user_config(user_id = nil, force_reload = false)
|
239
|
+
user_id ||= ENV["USER"] || "default"
|
240
|
+
config = load_config(force_reload)
|
241
|
+
return nil unless config
|
242
|
+
|
243
|
+
user_config = config[:users]&.dig(user_id.to_sym) ||
|
244
|
+
config[:users]&.dig(user_id.to_s) ||
|
245
|
+
config["users"]&.dig(user_id.to_s) ||
|
246
|
+
config["users"]&.dig(user_id.to_sym) ||
|
247
|
+
{}
|
248
|
+
|
249
|
+
merge_overrides(config, user_config)
|
250
|
+
end
|
251
|
+
|
252
|
+
# Get configuration with time-based overrides
|
253
|
+
def get_time_based_config(force_reload = false)
|
254
|
+
config = load_config(force_reload)
|
255
|
+
return nil unless config
|
256
|
+
|
257
|
+
time_overrides = {}
|
258
|
+
current_hour = Time.now.hour
|
259
|
+
|
260
|
+
# Check for time-based configurations
|
261
|
+
if config[:time_based]
|
262
|
+
time_config = config[:time_based]
|
263
|
+
|
264
|
+
# Check for hour-based overrides
|
265
|
+
time_config[:hours]&.each do |hour_range, hour_config|
|
266
|
+
if hour_in_range?(current_hour, hour_range)
|
267
|
+
time_overrides = deep_merge(time_overrides, hour_config)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
# Check for day-based overrides
|
272
|
+
if time_config[:days]
|
273
|
+
current_day = Time.now.strftime("%A").downcase
|
274
|
+
day_config = time_config[:days][current_day.to_sym] || time_config[:days][current_day]
|
275
|
+
if day_config
|
276
|
+
time_overrides = deep_merge(time_overrides, day_config)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
merge_overrides(config, time_overrides)
|
282
|
+
end
|
283
|
+
|
284
|
+
private
|
285
|
+
|
286
|
+
def config_file_changed?
|
287
|
+
return true unless @last_loaded && @validator.config_file_path
|
288
|
+
|
289
|
+
File.mtime(@validator.config_file_path) > @last_loaded
|
290
|
+
rescue
|
291
|
+
true
|
292
|
+
end
|
293
|
+
|
294
|
+
def handle_validation_errors(errors)
|
295
|
+
error_message = "Configuration validation failed:\n" + errors.join("\n")
|
296
|
+
|
297
|
+
# Log error
|
298
|
+
if defined?(Rails) && Rails.logger
|
299
|
+
Rails.logger.error(error_message)
|
300
|
+
else
|
301
|
+
warn(error_message)
|
302
|
+
end
|
303
|
+
|
304
|
+
# In development, try to fix common issues
|
305
|
+
if ENV["AIDP_ENV"] == "development" || ENV["RACK_ENV"] == "development"
|
306
|
+
if @validator.fix_common_issues
|
307
|
+
warn("Attempted to fix configuration issues. Please review the updated configuration file.")
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
def log_warnings(warnings)
|
313
|
+
warning_message = "Configuration warnings:\n" + warnings.join("\n")
|
314
|
+
|
315
|
+
# Log warnings
|
316
|
+
if defined?(Rails) && Rails.logger
|
317
|
+
Rails.logger.warn(warning_message)
|
318
|
+
else
|
319
|
+
warn(warning_message)
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
def merge_overrides(base_config, overrides)
|
324
|
+
return base_config if overrides.empty?
|
325
|
+
|
326
|
+
deep_merge(base_config, overrides)
|
327
|
+
end
|
328
|
+
|
329
|
+
def deep_merge(base, override)
|
330
|
+
result = base.dup
|
331
|
+
|
332
|
+
override.each do |key, value|
|
333
|
+
result[key] = if result[key].is_a?(Hash) && value.is_a?(Hash)
|
334
|
+
deep_merge(result[key], value)
|
335
|
+
else
|
336
|
+
value
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
result
|
341
|
+
end
|
342
|
+
|
343
|
+
def get_analyze_mode_config(config)
|
344
|
+
analyze_overrides = config[:analyze_mode] || config["analyze_mode"] || {}
|
345
|
+
merge_overrides(config, analyze_overrides)
|
346
|
+
end
|
347
|
+
|
348
|
+
def get_execute_mode_config(config)
|
349
|
+
execute_overrides = config[:execute_mode] || config["execute_mode"] || {}
|
350
|
+
merge_overrides(config, execute_overrides)
|
351
|
+
end
|
352
|
+
|
353
|
+
def hour_in_range?(hour, range)
|
354
|
+
case range
|
355
|
+
when Integer
|
356
|
+
hour == range
|
357
|
+
when Range
|
358
|
+
range.include?(hour)
|
359
|
+
when String
|
360
|
+
# Parse "9-17" format
|
361
|
+
if range.include?("-")
|
362
|
+
start_hour, end_hour = range.split("-").map(&:to_i)
|
363
|
+
hour.between?(start_hour, end_hour)
|
364
|
+
else
|
365
|
+
hour == range.to_i
|
366
|
+
end
|
367
|
+
else
|
368
|
+
false
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|