aidp 0.33.0 → 0.34.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 +35 -0
- data/lib/aidp/analyze/tree_sitter_scan.rb +3 -0
- data/lib/aidp/cli/eval_command.rb +399 -0
- data/lib/aidp/cli/harness_command.rb +1 -1
- data/lib/aidp/cli/security_command.rb +416 -0
- data/lib/aidp/cli/tools_command.rb +6 -4
- data/lib/aidp/cli.rb +170 -3
- data/lib/aidp/concurrency/exec.rb +3 -0
- data/lib/aidp/config.rb +113 -0
- data/lib/aidp/config_paths.rb +20 -0
- data/lib/aidp/daemon/runner.rb +8 -4
- data/lib/aidp/errors.rb +134 -0
- data/lib/aidp/evaluations/context_capture.rb +205 -0
- data/lib/aidp/evaluations/evaluation_record.rb +114 -0
- data/lib/aidp/evaluations/evaluation_storage.rb +250 -0
- data/lib/aidp/evaluations.rb +23 -0
- data/lib/aidp/execute/async_work_loop_runner.rb +4 -1
- data/lib/aidp/execute/interactive_repl.rb +6 -2
- data/lib/aidp/execute/prompt_evaluator.rb +359 -0
- data/lib/aidp/execute/repl_macros.rb +100 -1
- data/lib/aidp/execute/work_loop_runner.rb +399 -47
- data/lib/aidp/execute/work_loop_state.rb +4 -1
- data/lib/aidp/execute/workflow_selector.rb +3 -0
- data/lib/aidp/harness/ai_decision_engine.rb +79 -0
- data/lib/aidp/harness/capability_registry.rb +2 -0
- data/lib/aidp/harness/condition_detector.rb +3 -0
- data/lib/aidp/harness/config_loader.rb +3 -0
- data/lib/aidp/harness/enhanced_runner.rb +14 -11
- data/lib/aidp/harness/error_handler.rb +3 -0
- data/lib/aidp/harness/provider_factory.rb +3 -0
- data/lib/aidp/harness/provider_manager.rb +6 -0
- data/lib/aidp/harness/runner.rb +5 -1
- data/lib/aidp/harness/state/persistence.rb +3 -0
- data/lib/aidp/harness/state_manager.rb +3 -0
- data/lib/aidp/harness/status_display.rb +28 -20
- data/lib/aidp/harness/thinking_depth_manager.rb +32 -32
- data/lib/aidp/harness/ui/enhanced_tui.rb +4 -0
- data/lib/aidp/harness/ui/enhanced_workflow_selector.rb +4 -0
- data/lib/aidp/harness/ui/error_handler.rb +3 -0
- data/lib/aidp/harness/ui/job_monitor.rb +4 -0
- data/lib/aidp/harness/ui/navigation/submenu.rb +2 -0
- data/lib/aidp/harness/ui/navigation/workflow_selector.rb +6 -0
- data/lib/aidp/harness/ui/spinner_helper.rb +3 -0
- data/lib/aidp/harness/ui/workflow_controller.rb +3 -0
- data/lib/aidp/harness/user_interface.rb +3 -0
- data/lib/aidp/loader.rb +2 -2
- data/lib/aidp/logger.rb +3 -0
- data/lib/aidp/message_display.rb +31 -0
- data/lib/aidp/pr_worktree_manager.rb +18 -6
- data/lib/aidp/provider_manager.rb +3 -0
- data/lib/aidp/providers/base.rb +2 -0
- data/lib/aidp/security/rule_of_two_enforcer.rb +210 -0
- data/lib/aidp/security/secrets_proxy.rb +328 -0
- data/lib/aidp/security/secrets_registry.rb +227 -0
- data/lib/aidp/security/trifecta_state.rb +220 -0
- data/lib/aidp/security/watch_mode_handler.rb +306 -0
- data/lib/aidp/security/work_loop_adapter.rb +277 -0
- data/lib/aidp/security.rb +56 -0
- data/lib/aidp/setup/wizard.rb +4 -2
- data/lib/aidp/version.rb +1 -1
- data/lib/aidp/watch/auto_merger.rb +274 -0
- data/lib/aidp/watch/auto_pr_processor.rb +125 -7
- data/lib/aidp/watch/build_processor.rb +16 -1
- data/lib/aidp/watch/change_request_processor.rb +680 -286
- data/lib/aidp/watch/ci_fix_processor.rb +262 -4
- data/lib/aidp/watch/feedback_collector.rb +191 -0
- data/lib/aidp/watch/hierarchical_pr_strategy.rb +256 -0
- data/lib/aidp/watch/implementation_verifier.rb +142 -1
- data/lib/aidp/watch/plan_generator.rb +70 -13
- data/lib/aidp/watch/plan_processor.rb +12 -5
- data/lib/aidp/watch/projects_processor.rb +286 -0
- data/lib/aidp/watch/repository_client.rb +861 -53
- data/lib/aidp/watch/review_processor.rb +33 -6
- data/lib/aidp/watch/runner.rb +51 -11
- data/lib/aidp/watch/state_store.rb +233 -0
- data/lib/aidp/watch/sub_issue_creator.rb +221 -0
- data/lib/aidp/workflows/guided_agent.rb +4 -0
- data/lib/aidp/workstream_executor.rb +3 -0
- data/lib/aidp/worktree.rb +61 -11
- data/lib/aidp/worktree_branch_manager.rb +347 -101
- data/templates/implementation/iterative_implementation.md +46 -3
- metadata +20 -1
|
@@ -187,6 +187,85 @@ module Aidp
|
|
|
187
187
|
},
|
|
188
188
|
default_tier: "mini",
|
|
189
189
|
cache_ttl: nil
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
# FIX for issue #391: Prompt effectiveness evaluation for stuck work loops
|
|
193
|
+
prompt_evaluation: {
|
|
194
|
+
prompt_template: "{{prompt}}", # Custom prompt provided by caller
|
|
195
|
+
schema: {
|
|
196
|
+
type: "object",
|
|
197
|
+
properties: {
|
|
198
|
+
effective: {
|
|
199
|
+
type: "boolean",
|
|
200
|
+
description: "True if the prompt is likely to lead to completion"
|
|
201
|
+
},
|
|
202
|
+
issues: {
|
|
203
|
+
type: "array",
|
|
204
|
+
items: {type: "string"},
|
|
205
|
+
description: "Specific problems with the current prompt"
|
|
206
|
+
},
|
|
207
|
+
suggestions: {
|
|
208
|
+
type: "array",
|
|
209
|
+
items: {type: "string"},
|
|
210
|
+
description: "Actionable suggestions to improve effectiveness"
|
|
211
|
+
},
|
|
212
|
+
likely_blockers: {
|
|
213
|
+
type: "array",
|
|
214
|
+
items: {type: "string"},
|
|
215
|
+
description: "Potential blockers preventing progress"
|
|
216
|
+
},
|
|
217
|
+
confidence: {
|
|
218
|
+
type: "number",
|
|
219
|
+
minimum: 0.0,
|
|
220
|
+
maximum: 1.0,
|
|
221
|
+
description: "Confidence in this assessment"
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
required: ["effective", "issues", "suggestions", "confidence"]
|
|
225
|
+
},
|
|
226
|
+
default_tier: "mini",
|
|
227
|
+
cache_ttl: nil
|
|
228
|
+
},
|
|
229
|
+
|
|
230
|
+
# FIX for issue #391: Template improvement suggestions for AGD pattern
|
|
231
|
+
template_improvement: {
|
|
232
|
+
prompt_template: "{{prompt}}", # Custom prompt provided by caller
|
|
233
|
+
schema: {
|
|
234
|
+
type: "object",
|
|
235
|
+
properties: {
|
|
236
|
+
improved_sections: {
|
|
237
|
+
type: "array",
|
|
238
|
+
items: {
|
|
239
|
+
type: "object",
|
|
240
|
+
properties: {
|
|
241
|
+
section_name: {type: "string"},
|
|
242
|
+
original: {type: "string"},
|
|
243
|
+
improved: {type: "string"},
|
|
244
|
+
rationale: {type: "string"}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
additional_sections: {
|
|
249
|
+
type: "array",
|
|
250
|
+
items: {
|
|
251
|
+
type: "object",
|
|
252
|
+
properties: {
|
|
253
|
+
section_name: {type: "string"},
|
|
254
|
+
content: {type: "string"},
|
|
255
|
+
rationale: {type: "string"}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
completion_criteria_improvements: {
|
|
260
|
+
type: "array",
|
|
261
|
+
items: {type: "string"},
|
|
262
|
+
description: "Improvements to completion criteria definitions"
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
required: ["improved_sections", "completion_criteria_improvements"]
|
|
266
|
+
},
|
|
267
|
+
default_tier: "standard", # Use standard tier for thoughtful improvements
|
|
268
|
+
cache_ttl: nil
|
|
190
269
|
}
|
|
191
270
|
}.freeze
|
|
192
271
|
|
|
@@ -6,6 +6,9 @@ module Aidp
|
|
|
6
6
|
module Harness
|
|
7
7
|
# Detects run conditions (rate limits, user feedback, completion, errors)
|
|
8
8
|
class ConditionDetector
|
|
9
|
+
# Expose patterns for testability
|
|
10
|
+
attr_reader :rate_limit_patterns, :user_feedback_patterns, :question_patterns, :reset_time_patterns
|
|
11
|
+
|
|
9
12
|
def initialize
|
|
10
13
|
# Enhanced rate limit patterns for different providers
|
|
11
14
|
@rate_limit_patterns = {
|
|
@@ -9,6 +9,9 @@ module Aidp
|
|
|
9
9
|
module Harness
|
|
10
10
|
# Enhanced configuration loader for harness
|
|
11
11
|
class ConfigLoader
|
|
12
|
+
# Expose for testability
|
|
13
|
+
attr_reader :validator
|
|
14
|
+
|
|
12
15
|
def initialize(project_dir = Dir.pwd, validator: nil)
|
|
13
16
|
@project_dir = project_dir
|
|
14
17
|
@validator = validator || ConfigValidator.new(project_dir)
|
|
@@ -23,6 +23,15 @@ module Aidp
|
|
|
23
23
|
error: "error"
|
|
24
24
|
}.freeze
|
|
25
25
|
|
|
26
|
+
# Expose state for testability
|
|
27
|
+
attr_accessor :state, :current_step, :start_time
|
|
28
|
+
attr_writer :current_provider, :user_input, :execution_log
|
|
29
|
+
attr_accessor :mode, :project_dir, :selected_steps, :workflow_type
|
|
30
|
+
attr_reader :provider_manager, :sleeper
|
|
31
|
+
attr_writer :completion_checker, :workflow_controller, :error_handler
|
|
32
|
+
attr_accessor :condition_detector
|
|
33
|
+
attr_writer :state_manager, :configuration
|
|
34
|
+
|
|
26
35
|
# Simple sleeper abstraction for test control
|
|
27
36
|
class Sleeper
|
|
28
37
|
def sleep(duration)
|
|
@@ -75,27 +84,21 @@ module Aidp
|
|
|
75
84
|
@completion_checker = options[:completion_checker] || CompletionChecker.new(@project_dir, @workflow_type)
|
|
76
85
|
end
|
|
77
86
|
|
|
78
|
-
# Get current provider (delegate to provider manager)
|
|
87
|
+
# Get current provider (delegate to provider manager with fallback)
|
|
79
88
|
def current_provider
|
|
80
89
|
@current_provider || @provider_manager&.current_provider || "unknown"
|
|
81
90
|
end
|
|
82
91
|
|
|
83
|
-
# Get
|
|
84
|
-
attr_reader :current_step
|
|
85
|
-
|
|
86
|
-
# Get user input
|
|
92
|
+
# Get user input (with nil safety)
|
|
87
93
|
def user_input
|
|
88
94
|
@user_input || {}
|
|
89
95
|
end
|
|
90
96
|
|
|
91
|
-
# Get execution log
|
|
97
|
+
# Get execution log (with nil safety)
|
|
92
98
|
def execution_log
|
|
93
99
|
@execution_log || []
|
|
94
100
|
end
|
|
95
101
|
|
|
96
|
-
# Get provider manager
|
|
97
|
-
attr_reader :provider_manager
|
|
98
|
-
|
|
99
102
|
# Main execution method with enhanced TUI
|
|
100
103
|
def run
|
|
101
104
|
@state = STATES[:running]
|
|
@@ -354,7 +357,7 @@ module Aidp
|
|
|
354
357
|
duration: @start_time ? Time.now - @start_time : 0,
|
|
355
358
|
user_input_count: @user_input.size,
|
|
356
359
|
execution_log_count: @execution_log.size,
|
|
357
|
-
jobs_count: @tui.
|
|
360
|
+
jobs_count: @tui.jobs.size
|
|
358
361
|
}
|
|
359
362
|
end
|
|
360
363
|
|
|
@@ -530,7 +533,7 @@ module Aidp
|
|
|
530
533
|
|
|
531
534
|
def cleanup
|
|
532
535
|
# Cleanup any remaining jobs
|
|
533
|
-
@tui.
|
|
536
|
+
@tui.jobs.keys.each do |job_id|
|
|
534
537
|
@tui.remove_job(job_id)
|
|
535
538
|
end
|
|
536
539
|
end
|
|
@@ -12,6 +12,9 @@ module Aidp
|
|
|
12
12
|
class ErrorHandler
|
|
13
13
|
include Aidp::DebugMixin
|
|
14
14
|
|
|
15
|
+
# Expose internal components for testability
|
|
16
|
+
attr_reader :retry_strategies, :backoff_calculator, :error_classifier, :recovery_planner
|
|
17
|
+
|
|
15
18
|
# Simple wrapper to allow dependency injection of sleep behavior in tests
|
|
16
19
|
class Sleeper
|
|
17
20
|
def sleep(seconds)
|
|
@@ -15,6 +15,9 @@ module Aidp
|
|
|
15
15
|
module Harness
|
|
16
16
|
# Factory for creating configured provider instances
|
|
17
17
|
class ProviderFactory
|
|
18
|
+
# Expose for testability
|
|
19
|
+
attr_reader :provider_instances, :provider_configs
|
|
20
|
+
|
|
18
21
|
PROVIDER_CLASSES = {
|
|
19
22
|
"cursor" => Aidp::Providers::Cursor,
|
|
20
23
|
"anthropic" => Aidp::Providers::Anthropic,
|
|
@@ -13,6 +13,12 @@ module Aidp
|
|
|
13
13
|
include Aidp::MessageDisplay
|
|
14
14
|
include Aidp::RescueLogging
|
|
15
15
|
|
|
16
|
+
# Expose state for testability
|
|
17
|
+
attr_accessor :sticky_sessions, :load_balancing_enabled
|
|
18
|
+
attr_writer :current_model
|
|
19
|
+
attr_accessor :provider_health, :provider_metrics, :rate_limit_info
|
|
20
|
+
attr_reader :binary_check_cache, :binary_check_ttl
|
|
21
|
+
|
|
16
22
|
def initialize(configuration, prompt: TTY::Prompt.new, binary_checker: Aidp::Util)
|
|
17
23
|
@configuration = configuration
|
|
18
24
|
@prompt = prompt
|
data/lib/aidp/harness/runner.rb
CHANGED
|
@@ -23,7 +23,11 @@ module Aidp
|
|
|
23
23
|
}.freeze
|
|
24
24
|
|
|
25
25
|
# Public accessors for testing and integration
|
|
26
|
-
attr_reader :
|
|
26
|
+
attr_reader :clarification_questions, :last_error
|
|
27
|
+
attr_accessor :current_provider, :current_step, :user_input, :execution_log, :provider_manager
|
|
28
|
+
attr_accessor :state, :mode, :project_dir, :configuration, :condition_detector
|
|
29
|
+
attr_accessor :state_manager, :user_interface, :error_handler, :status_display
|
|
30
|
+
attr_writer :completion_checker, :workflow_type, :non_interactive
|
|
27
31
|
|
|
28
32
|
def initialize(project_dir, mode = :analyze, options = {})
|
|
29
33
|
@project_dir = project_dir
|
|
@@ -9,6 +9,17 @@ module Aidp
|
|
|
9
9
|
class StatusDisplay
|
|
10
10
|
include Aidp::MessageDisplay
|
|
11
11
|
|
|
12
|
+
# Expose state for testability
|
|
13
|
+
attr_accessor :current_step, :current_provider, :current_model
|
|
14
|
+
attr_accessor :start_time, :running
|
|
15
|
+
attr_accessor :performance_metrics, :error_summary
|
|
16
|
+
attr_accessor :provider_status, :token_usage, :circuit_breaker_status
|
|
17
|
+
attr_accessor :rate_limit_status, :recovery_status, :user_feedback_status
|
|
18
|
+
attr_accessor :work_completion_status, :display_config
|
|
19
|
+
attr_reader :status_formatter, :metrics_calculator, :alert_manager, :display_animator
|
|
20
|
+
# Internal status hash (separate from computed status_data method)
|
|
21
|
+
attr_accessor :internal_status_data
|
|
22
|
+
|
|
12
23
|
def initialize(provider_manager = nil, metrics_manager = nil, circuit_breaker_manager = nil, error_logger = nil, prompt: TTY::Prompt.new)
|
|
13
24
|
@provider_manager = provider_manager
|
|
14
25
|
@metrics_manager = metrics_manager
|
|
@@ -27,6 +38,7 @@ module Aidp
|
|
|
27
38
|
@update_interval = 2
|
|
28
39
|
@last_update = Time.now
|
|
29
40
|
@status_data = {}
|
|
41
|
+
@internal_status_data = @status_data # Alias for testability
|
|
30
42
|
@performance_metrics = {}
|
|
31
43
|
@error_summary = {}
|
|
32
44
|
@provider_status = {}
|
|
@@ -167,16 +179,24 @@ module Aidp
|
|
|
167
179
|
@error_summary[:last_updated] = Time.now
|
|
168
180
|
end
|
|
169
181
|
|
|
170
|
-
#
|
|
171
|
-
def display_mode(mode)
|
|
172
|
-
|
|
173
|
-
|
|
182
|
+
# Get or set display mode
|
|
183
|
+
def display_mode(mode = nil)
|
|
184
|
+
if mode.nil?
|
|
185
|
+
@display_mode
|
|
186
|
+
else
|
|
187
|
+
@display_mode = mode
|
|
188
|
+
@display_config[:mode] = mode
|
|
189
|
+
end
|
|
174
190
|
end
|
|
175
191
|
|
|
176
|
-
#
|
|
177
|
-
def update_interval(interval)
|
|
178
|
-
|
|
179
|
-
|
|
192
|
+
# Get or set update interval
|
|
193
|
+
def update_interval(interval = nil)
|
|
194
|
+
if interval.nil?
|
|
195
|
+
@update_interval
|
|
196
|
+
else
|
|
197
|
+
@update_interval = interval
|
|
198
|
+
@display_config[:update_interval] = interval
|
|
199
|
+
end
|
|
180
200
|
end
|
|
181
201
|
|
|
182
202
|
# Configure display settings
|
|
@@ -686,8 +706,6 @@ module Aidp
|
|
|
686
706
|
}
|
|
687
707
|
end
|
|
688
708
|
|
|
689
|
-
attr_reader :provider_status
|
|
690
|
-
|
|
691
709
|
def performance_status
|
|
692
710
|
@performance_metrics
|
|
693
711
|
end
|
|
@@ -696,20 +714,10 @@ module Aidp
|
|
|
696
714
|
@error_summary
|
|
697
715
|
end
|
|
698
716
|
|
|
699
|
-
attr_reader :circuit_breaker_status
|
|
700
|
-
|
|
701
717
|
def token_status
|
|
702
718
|
@token_usage
|
|
703
719
|
end
|
|
704
720
|
|
|
705
|
-
attr_reader :rate_limit_status
|
|
706
|
-
|
|
707
|
-
attr_reader :recovery_status
|
|
708
|
-
|
|
709
|
-
attr_reader :user_feedback_status
|
|
710
|
-
|
|
711
|
-
attr_reader :work_completion_status
|
|
712
|
-
|
|
713
721
|
def alerts
|
|
714
722
|
@alert_manager.active_alerts
|
|
715
723
|
end
|
|
@@ -15,7 +15,7 @@ module Aidp
|
|
|
15
15
|
|
|
16
16
|
def initialize(configuration, registry: nil, root_dir: nil)
|
|
17
17
|
@configuration = configuration
|
|
18
|
-
@registry = registry || CapabilityRegistry.new(root_dir: root_dir || configuration.
|
|
18
|
+
@registry = registry || CapabilityRegistry.new(root_dir: root_dir || configuration.project_dir)
|
|
19
19
|
@current_tier = nil
|
|
20
20
|
@session_max_tier = nil
|
|
21
21
|
@tier_history = []
|
|
@@ -243,50 +243,47 @@ module Aidp
|
|
|
243
243
|
model: model_name)
|
|
244
244
|
return [provider, model_name, model_data]
|
|
245
245
|
end
|
|
246
|
-
|
|
247
|
-
# If provider doesn't support tier and switching allowed, try others
|
|
248
|
-
unless configuration.allow_provider_switch_for_tier?
|
|
249
|
-
Aidp.log_warn("thinking_depth_manager", "Provider lacks tier in catalog, switching disabled",
|
|
250
|
-
tier: tier,
|
|
251
|
-
provider: provider)
|
|
252
|
-
return nil
|
|
253
|
-
end
|
|
254
|
-
end
|
|
255
|
-
|
|
256
|
-
# Try all providers in catalog
|
|
257
|
-
if provider && !configuration.allow_provider_switch_for_tier?
|
|
258
|
-
return nil
|
|
246
|
+
# Per issue #323: Don't return nil here - let fallback logic handle missing tiers
|
|
259
247
|
end
|
|
260
248
|
|
|
261
|
-
|
|
249
|
+
# Try all providers in catalog if provider switching is allowed
|
|
250
|
+
if configuration.allow_provider_switch_for_tier?
|
|
251
|
+
providers_to_try = provider ? (@registry.provider_names - [provider]) : @registry.provider_names
|
|
262
252
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
253
|
+
providers_to_try.each do |prov_name|
|
|
254
|
+
model_name, model_data = @registry.best_model_for_tier(tier, prov_name)
|
|
255
|
+
if model_name
|
|
256
|
+
Aidp.log_info("thinking_depth_manager", "Selected model from catalog (alternate provider)",
|
|
257
|
+
tier: tier,
|
|
258
|
+
original_provider: provider,
|
|
259
|
+
selected_provider: prov_name,
|
|
260
|
+
model: model_name)
|
|
261
|
+
return [prov_name, model_name, model_data]
|
|
262
|
+
end
|
|
272
263
|
end
|
|
273
264
|
end
|
|
274
265
|
|
|
275
266
|
# No model found for requested tier - try fallback to other tiers
|
|
276
|
-
|
|
267
|
+
# Per issue #323: fallback events log at debug level
|
|
268
|
+
Aidp.log_debug("thinking_depth_manager", "tier_not_found_trying_fallback",
|
|
277
269
|
tier: tier,
|
|
278
270
|
provider: provider)
|
|
279
271
|
|
|
280
272
|
result = try_fallback_tiers(tier, provider)
|
|
281
273
|
|
|
282
|
-
|
|
283
|
-
|
|
274
|
+
# If no model found after fallback, defer to provider auto model selection
|
|
275
|
+
# This allows providers to select their own model when no explicit tier config exists
|
|
276
|
+
# Per issue #323: log at debug level, don't constrain model selection
|
|
277
|
+
if result.nil? && provider
|
|
278
|
+
Aidp.log_debug("thinking_depth_manager", "no_model_for_tier_deferring_to_provider",
|
|
284
279
|
requested_tier: tier,
|
|
285
|
-
provider: provider
|
|
286
|
-
|
|
280
|
+
provider: provider,
|
|
281
|
+
reason: provider_has_no_tiers ? "provider_has_no_tiers" : "tier_not_configured")
|
|
282
|
+
return [provider, nil, {auto_model: true, reason: provider_has_no_tiers ? "provider_has_no_tiers" : "tier_not_configured"}]
|
|
287
283
|
end
|
|
288
284
|
|
|
289
285
|
unless result
|
|
286
|
+
# This path should only be reached when no provider is specified
|
|
290
287
|
# Enhanced error message with discovery hints
|
|
291
288
|
display_enhanced_tier_error(tier, provider)
|
|
292
289
|
|
|
@@ -452,7 +449,8 @@ module Aidp
|
|
|
452
449
|
|
|
453
450
|
if configured_models.any?
|
|
454
451
|
model_name = configured_models.first
|
|
455
|
-
|
|
452
|
+
# Per issue #323: fallback events log at debug level
|
|
453
|
+
Aidp.log_debug("thinking_depth_manager", "tier_fallback_from_config",
|
|
456
454
|
requested_tier: requested_tier,
|
|
457
455
|
fallback_tier: fallback_tier,
|
|
458
456
|
provider: provider,
|
|
@@ -466,7 +464,8 @@ module Aidp
|
|
|
466
464
|
if provider
|
|
467
465
|
model_name, model_data = @registry.best_model_for_tier(fallback_tier, provider)
|
|
468
466
|
if model_name
|
|
469
|
-
|
|
467
|
+
# Per issue #323: fallback events log at debug level
|
|
468
|
+
Aidp.log_debug("thinking_depth_manager", "tier_fallback_from_catalog",
|
|
470
469
|
requested_tier: requested_tier,
|
|
471
470
|
fallback_tier: fallback_tier,
|
|
472
471
|
provider: provider,
|
|
@@ -482,7 +481,8 @@ module Aidp
|
|
|
482
481
|
|
|
483
482
|
model_name, model_data = @registry.best_model_for_tier(fallback_tier, prov_name)
|
|
484
483
|
if model_name
|
|
485
|
-
|
|
484
|
+
# Per issue #323: fallback events log at debug level
|
|
485
|
+
Aidp.log_debug("thinking_depth_manager", "tier_fallback_provider_switch",
|
|
486
486
|
requested_tier: requested_tier,
|
|
487
487
|
fallback_tier: fallback_tier,
|
|
488
488
|
requested_provider: provider,
|
|
@@ -20,6 +20,10 @@ module Aidp
|
|
|
20
20
|
|
|
21
21
|
class DisplayError < TUIError; end
|
|
22
22
|
|
|
23
|
+
# Expose state for testability
|
|
24
|
+
attr_accessor :headless, :current_mode, :workflow_active, :current_step
|
|
25
|
+
attr_reader :jobs
|
|
26
|
+
|
|
23
27
|
def initialize(prompt: TTY::Prompt.new, tty: $stdin)
|
|
24
28
|
@cursor = TTY::Cursor
|
|
25
29
|
@screen = TTY::Screen
|
|
@@ -11,6 +11,10 @@ module Aidp
|
|
|
11
11
|
class EnhancedWorkflowSelector
|
|
12
12
|
class WorkflowError < StandardError; end
|
|
13
13
|
|
|
14
|
+
# Expose state for testability
|
|
15
|
+
attr_reader :tui, :project_dir, :user_input
|
|
16
|
+
attr_accessor :workflow_selector
|
|
17
|
+
|
|
14
18
|
def initialize(tui = nil, project_dir: Dir.pwd)
|
|
15
19
|
@tui = tui || EnhancedTUI.new
|
|
16
20
|
@user_input = {}
|
|
@@ -18,6 +18,9 @@ module Aidp
|
|
|
18
18
|
|
|
19
19
|
class InteractionError < UIError; end
|
|
20
20
|
|
|
21
|
+
# Expose for testability
|
|
22
|
+
attr_reader :logger
|
|
23
|
+
|
|
21
24
|
def initialize(ui_components = {})
|
|
22
25
|
@logger = ui_components[:logger] || default_logger
|
|
23
26
|
@formatter = ui_components[:formatter] || ErrorFormatter.new
|
|
@@ -17,6 +17,9 @@ module Aidp
|
|
|
17
17
|
|
|
18
18
|
class SelectionError < WorkflowError; end
|
|
19
19
|
|
|
20
|
+
# Expose for testability
|
|
21
|
+
attr_reader :prompt
|
|
22
|
+
|
|
20
23
|
WORKFLOW_MODES = {
|
|
21
24
|
simple: {
|
|
22
25
|
name: "Simple Mode",
|
|
@@ -132,6 +135,9 @@ module Aidp
|
|
|
132
135
|
|
|
133
136
|
# Formats workflow selection display
|
|
134
137
|
class WorkflowFormatter
|
|
138
|
+
# Expose for testability
|
|
139
|
+
attr_reader :pastel
|
|
140
|
+
|
|
135
141
|
def initialize
|
|
136
142
|
@pastel = Pastel.new
|
|
137
143
|
end
|
|
@@ -9,6 +9,9 @@ module Aidp
|
|
|
9
9
|
class UserInterface
|
|
10
10
|
include Aidp::MessageDisplay
|
|
11
11
|
|
|
12
|
+
# Expose for testability
|
|
13
|
+
attr_reader :auto_confirm_defaults, :show_help_automatically, :verbose_mode, :file_selection_enabled
|
|
14
|
+
|
|
12
15
|
def initialize(prompt: TTY::Prompt.new)
|
|
13
16
|
@input_history = []
|
|
14
17
|
@file_selection_enabled = false
|
data/lib/aidp/loader.rb
CHANGED
|
@@ -21,10 +21,10 @@ module Aidp
|
|
|
21
21
|
module Loader
|
|
22
22
|
class << self
|
|
23
23
|
# @return [Zeitwerk::Loader, nil] The configured loader instance
|
|
24
|
-
|
|
24
|
+
attr_accessor :loader
|
|
25
25
|
|
|
26
26
|
# @return [Boolean] Whether reloading is enabled
|
|
27
|
-
|
|
27
|
+
attr_accessor :reloading_enabled
|
|
28
28
|
|
|
29
29
|
# Set up the Zeitwerk loader for AIDP
|
|
30
30
|
#
|
data/lib/aidp/logger.rb
CHANGED
|
@@ -307,6 +307,9 @@ module Aidp
|
|
|
307
307
|
|
|
308
308
|
# Module-level logger accessor
|
|
309
309
|
class << self
|
|
310
|
+
# Expose for testability
|
|
311
|
+
attr_writer :logger
|
|
312
|
+
|
|
310
313
|
# Set up global logger instance
|
|
311
314
|
def setup_logger(project_dir = Dir.pwd, config = {})
|
|
312
315
|
@logger = Logger.new(project_dir, config)
|
data/lib/aidp/message_display.rb
CHANGED
|
@@ -8,6 +8,11 @@ module Aidp
|
|
|
8
8
|
# include Aidp::MessageDisplay
|
|
9
9
|
# display_message("Hello", type: :success)
|
|
10
10
|
# Supports color types: :error, :success, :warning, :info, :highlight, :muted
|
|
11
|
+
#
|
|
12
|
+
# Quiet mode:
|
|
13
|
+
# When quiet mode is enabled (via CLI --quiet flag or setting quiet=true on instance),
|
|
14
|
+
# only :error, :warning, and :success messages are displayed. Info, highlight, and muted
|
|
15
|
+
# messages are suppressed to reduce output noise.
|
|
11
16
|
module MessageDisplay
|
|
12
17
|
COLOR_MAP = {
|
|
13
18
|
error: :red,
|
|
@@ -19,12 +24,28 @@ module Aidp
|
|
|
19
24
|
muted: :bright_black
|
|
20
25
|
}.freeze
|
|
21
26
|
|
|
27
|
+
# Message types that are always shown even in quiet mode
|
|
28
|
+
CRITICAL_TYPES = %i[error warning warn success].freeze
|
|
29
|
+
|
|
22
30
|
def self.included(base)
|
|
23
31
|
base.extend(ClassMethods)
|
|
24
32
|
end
|
|
25
33
|
|
|
34
|
+
# Check if quiet mode is enabled
|
|
35
|
+
# Priority: instance @quiet variable > CLI.last_options[:quiet]
|
|
36
|
+
def quiet_mode?
|
|
37
|
+
return @quiet if instance_variable_defined?(:@quiet) && !@quiet.nil?
|
|
38
|
+
|
|
39
|
+
Aidp::CLI.last_options&.dig(:quiet) || false
|
|
40
|
+
rescue
|
|
41
|
+
false
|
|
42
|
+
end
|
|
43
|
+
|
|
26
44
|
# Instance helper for displaying a colored message via TTY::Prompt
|
|
27
45
|
def display_message(message, type: :info)
|
|
46
|
+
# In quiet mode, suppress non-critical messages
|
|
47
|
+
return if quiet_mode? && !CRITICAL_TYPES.include?(type)
|
|
48
|
+
|
|
28
49
|
# Ensure message is UTF-8 encoded to handle emoji and special characters
|
|
29
50
|
message_str = message.to_s
|
|
30
51
|
message_str = message_str.force_encoding("UTF-8") if message_str.encoding.name == "ASCII-8BIT"
|
|
@@ -43,8 +64,18 @@ module Aidp
|
|
|
43
64
|
end
|
|
44
65
|
|
|
45
66
|
module ClassMethods
|
|
67
|
+
# Check if quiet mode is enabled at class level
|
|
68
|
+
def quiet_mode?
|
|
69
|
+
Aidp::CLI.last_options&.dig(:quiet) || false
|
|
70
|
+
rescue
|
|
71
|
+
false
|
|
72
|
+
end
|
|
73
|
+
|
|
46
74
|
# Class-level display helper (uses fresh prompt to respect $stdout changes)
|
|
47
75
|
def display_message(message, type: :info)
|
|
76
|
+
# In quiet mode, suppress non-critical messages
|
|
77
|
+
return if quiet_mode? && !CRITICAL_TYPES.include?(type)
|
|
78
|
+
|
|
48
79
|
# Ensure message is UTF-8 encoded to handle emoji and special characters
|
|
49
80
|
message_str = message.to_s
|
|
50
81
|
message_str = message_str.force_encoding("UTF-8") if message_str.encoding.name == "ASCII-8BIT"
|