aidp 0.32.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.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +35 -0
  3. data/lib/aidp/analyze/feature_analyzer.rb +322 -320
  4. data/lib/aidp/analyze/tree_sitter_scan.rb +3 -0
  5. data/lib/aidp/auto_update/coordinator.rb +97 -7
  6. data/lib/aidp/auto_update.rb +0 -12
  7. data/lib/aidp/cli/devcontainer_commands.rb +0 -5
  8. data/lib/aidp/cli/eval_command.rb +399 -0
  9. data/lib/aidp/cli/harness_command.rb +1 -1
  10. data/lib/aidp/cli/security_command.rb +416 -0
  11. data/lib/aidp/cli/tools_command.rb +6 -4
  12. data/lib/aidp/cli.rb +172 -4
  13. data/lib/aidp/comment_consolidator.rb +78 -0
  14. data/lib/aidp/concurrency/exec.rb +3 -0
  15. data/lib/aidp/concurrency.rb +0 -3
  16. data/lib/aidp/config.rb +113 -1
  17. data/lib/aidp/config_paths.rb +91 -0
  18. data/lib/aidp/daemon/runner.rb +8 -4
  19. data/lib/aidp/errors.rb +134 -0
  20. data/lib/aidp/evaluations/context_capture.rb +205 -0
  21. data/lib/aidp/evaluations/evaluation_record.rb +114 -0
  22. data/lib/aidp/evaluations/evaluation_storage.rb +250 -0
  23. data/lib/aidp/evaluations.rb +23 -0
  24. data/lib/aidp/execute/async_work_loop_runner.rb +4 -1
  25. data/lib/aidp/execute/interactive_repl.rb +6 -2
  26. data/lib/aidp/execute/prompt_evaluator.rb +359 -0
  27. data/lib/aidp/execute/repl_macros.rb +100 -1
  28. data/lib/aidp/execute/work_loop_runner.rb +719 -58
  29. data/lib/aidp/execute/work_loop_state.rb +4 -1
  30. data/lib/aidp/execute/workflow_selector.rb +3 -0
  31. data/lib/aidp/harness/ai_decision_engine.rb +79 -0
  32. data/lib/aidp/harness/ai_filter_factory.rb +285 -0
  33. data/lib/aidp/harness/capability_registry.rb +2 -0
  34. data/lib/aidp/harness/condition_detector.rb +3 -0
  35. data/lib/aidp/harness/config_loader.rb +3 -0
  36. data/lib/aidp/harness/config_schema.rb +97 -1
  37. data/lib/aidp/harness/config_validator.rb +1 -1
  38. data/lib/aidp/harness/configuration.rb +61 -5
  39. data/lib/aidp/harness/enhanced_runner.rb +14 -11
  40. data/lib/aidp/harness/error_handler.rb +3 -0
  41. data/lib/aidp/harness/filter_definition.rb +212 -0
  42. data/lib/aidp/harness/generated_filter_strategy.rb +197 -0
  43. data/lib/aidp/harness/output_filter.rb +50 -25
  44. data/lib/aidp/harness/output_filter_config.rb +129 -0
  45. data/lib/aidp/harness/provider_factory.rb +3 -0
  46. data/lib/aidp/harness/provider_manager.rb +96 -2
  47. data/lib/aidp/harness/runner.rb +5 -12
  48. data/lib/aidp/harness/state/persistence.rb +3 -0
  49. data/lib/aidp/harness/state_manager.rb +3 -0
  50. data/lib/aidp/harness/status_display.rb +28 -20
  51. data/lib/aidp/harness/test_runner.rb +179 -41
  52. data/lib/aidp/harness/thinking_depth_manager.rb +44 -28
  53. data/lib/aidp/harness/ui/enhanced_tui.rb +4 -0
  54. data/lib/aidp/harness/ui/enhanced_workflow_selector.rb +4 -0
  55. data/lib/aidp/harness/ui/error_handler.rb +3 -0
  56. data/lib/aidp/harness/ui/job_monitor.rb +4 -0
  57. data/lib/aidp/harness/ui/navigation/submenu.rb +2 -2
  58. data/lib/aidp/harness/ui/navigation/workflow_selector.rb +6 -0
  59. data/lib/aidp/harness/ui/spinner_helper.rb +3 -0
  60. data/lib/aidp/harness/ui/workflow_controller.rb +3 -0
  61. data/lib/aidp/harness/user_interface.rb +3 -0
  62. data/lib/aidp/loader.rb +195 -0
  63. data/lib/aidp/logger.rb +3 -0
  64. data/lib/aidp/message_display.rb +31 -0
  65. data/lib/aidp/metadata/compiler.rb +29 -17
  66. data/lib/aidp/metadata/query.rb +1 -1
  67. data/lib/aidp/metadata/scanner.rb +8 -1
  68. data/lib/aidp/metadata/tool_metadata.rb +13 -13
  69. data/lib/aidp/metadata/validator.rb +10 -0
  70. data/lib/aidp/metadata.rb +16 -0
  71. data/lib/aidp/pr_worktree_manager.rb +20 -8
  72. data/lib/aidp/provider_manager.rb +4 -7
  73. data/lib/aidp/providers/base.rb +2 -0
  74. data/lib/aidp/security/rule_of_two_enforcer.rb +210 -0
  75. data/lib/aidp/security/secrets_proxy.rb +328 -0
  76. data/lib/aidp/security/secrets_registry.rb +227 -0
  77. data/lib/aidp/security/trifecta_state.rb +220 -0
  78. data/lib/aidp/security/watch_mode_handler.rb +306 -0
  79. data/lib/aidp/security/work_loop_adapter.rb +277 -0
  80. data/lib/aidp/security.rb +56 -0
  81. data/lib/aidp/setup/wizard.rb +283 -11
  82. data/lib/aidp/skills.rb +0 -5
  83. data/lib/aidp/storage/csv_storage.rb +3 -0
  84. data/lib/aidp/style_guide/selector.rb +360 -0
  85. data/lib/aidp/tooling_detector.rb +283 -16
  86. data/lib/aidp/version.rb +1 -1
  87. data/lib/aidp/watch/auto_merger.rb +274 -0
  88. data/lib/aidp/watch/auto_pr_processor.rb +125 -7
  89. data/lib/aidp/watch/build_processor.rb +16 -1
  90. data/lib/aidp/watch/change_request_processor.rb +682 -150
  91. data/lib/aidp/watch/ci_fix_processor.rb +262 -4
  92. data/lib/aidp/watch/feedback_collector.rb +191 -0
  93. data/lib/aidp/watch/hierarchical_pr_strategy.rb +256 -0
  94. data/lib/aidp/watch/implementation_verifier.rb +142 -1
  95. data/lib/aidp/watch/plan_generator.rb +70 -13
  96. data/lib/aidp/watch/plan_processor.rb +12 -5
  97. data/lib/aidp/watch/projects_processor.rb +286 -0
  98. data/lib/aidp/watch/repository_client.rb +871 -22
  99. data/lib/aidp/watch/review_processor.rb +33 -6
  100. data/lib/aidp/watch/runner.rb +80 -29
  101. data/lib/aidp/watch/state_store.rb +233 -0
  102. data/lib/aidp/watch/sub_issue_creator.rb +221 -0
  103. data/lib/aidp/watch.rb +5 -7
  104. data/lib/aidp/workflows/guided_agent.rb +4 -0
  105. data/lib/aidp/workstream_cleanup.rb +0 -2
  106. data/lib/aidp/workstream_executor.rb +3 -4
  107. data/lib/aidp/worktree.rb +61 -12
  108. data/lib/aidp/worktree_branch_manager.rb +347 -101
  109. data/lib/aidp.rb +21 -106
  110. data/templates/implementation/iterative_implementation.md +46 -3
  111. metadata +91 -36
  112. data/lib/aidp/config/paths.rb +0 -131
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aidp
4
+ module Harness
5
+ # Value object for output filter configuration
6
+ # Provides validation and type-safe access to filtering options
7
+ class OutputFilterConfig
8
+ VALID_MODES = %i[full failures_only minimal].freeze
9
+ DEFAULT_MODE = :full
10
+ DEFAULT_INCLUDE_CONTEXT = true
11
+ DEFAULT_CONTEXT_LINES = 3
12
+ DEFAULT_MAX_LINES = 500
13
+ MIN_CONTEXT_LINES = 0
14
+ MAX_CONTEXT_LINES = 20
15
+ MIN_MAX_LINES = 10
16
+ MAX_MAX_LINES = 10_000
17
+
18
+ attr_reader :mode, :include_context, :context_lines, :max_lines
19
+
20
+ # Create a new OutputFilterConfig
21
+ # @param mode [Symbol] Output mode (:full, :failures_only, :minimal)
22
+ # @param include_context [Boolean] Include surrounding lines
23
+ # @param context_lines [Integer] Number of context lines (0-20)
24
+ # @param max_lines [Integer] Maximum output lines (10-10000)
25
+ # @raise [ArgumentError] If any parameter is invalid
26
+ def initialize(mode: DEFAULT_MODE, include_context: DEFAULT_INCLUDE_CONTEXT,
27
+ context_lines: DEFAULT_CONTEXT_LINES, max_lines: DEFAULT_MAX_LINES)
28
+ @mode = validate_mode(mode)
29
+ @include_context = validate_boolean(include_context, "include_context")
30
+ @context_lines = validate_context_lines(context_lines)
31
+ @max_lines = validate_max_lines(max_lines)
32
+
33
+ freeze
34
+ end
35
+
36
+ # Create from a hash (useful for configuration loading)
37
+ # @param hash [Hash] Configuration hash
38
+ # @return [OutputFilterConfig] New config instance
39
+ def self.from_hash(hash)
40
+ hash = hash.transform_keys(&:to_sym) if hash.respond_to?(:transform_keys)
41
+
42
+ new(
43
+ mode: hash[:mode] || DEFAULT_MODE,
44
+ include_context: hash.fetch(:include_context, DEFAULT_INCLUDE_CONTEXT),
45
+ context_lines: hash[:context_lines] || DEFAULT_CONTEXT_LINES,
46
+ max_lines: hash[:max_lines] || DEFAULT_MAX_LINES
47
+ )
48
+ end
49
+
50
+ # Convert to hash (useful for serialization)
51
+ # @return [Hash] Configuration as hash
52
+ def to_h
53
+ {
54
+ mode: @mode,
55
+ include_context: @include_context,
56
+ context_lines: @context_lines,
57
+ max_lines: @max_lines
58
+ }
59
+ end
60
+
61
+ # Check if filtering is enabled
62
+ # @return [Boolean] True if mode is not :full
63
+ def filtering_enabled?
64
+ @mode != :full
65
+ end
66
+
67
+ # Compare with another config
68
+ # @param other [OutputFilterConfig] Other config to compare
69
+ # @return [Boolean] True if equal
70
+ def ==(other)
71
+ return false unless other.is_a?(OutputFilterConfig)
72
+
73
+ @mode == other.mode &&
74
+ @include_context == other.include_context &&
75
+ @context_lines == other.context_lines &&
76
+ @max_lines == other.max_lines
77
+ end
78
+ alias_method :eql?, :==
79
+
80
+ # Hash for use in Hash/Set
81
+ def hash
82
+ [@mode, @include_context, @context_lines, @max_lines].hash
83
+ end
84
+
85
+ private
86
+
87
+ def validate_mode(mode)
88
+ mode = mode.to_sym if mode.respond_to?(:to_sym)
89
+
90
+ unless VALID_MODES.include?(mode)
91
+ raise ArgumentError,
92
+ "Invalid mode: #{mode.inspect}. Must be one of #{VALID_MODES.join(", ")}"
93
+ end
94
+
95
+ mode
96
+ end
97
+
98
+ def validate_boolean(value, name)
99
+ unless [true, false].include?(value)
100
+ raise ArgumentError, "#{name} must be a boolean, got: #{value.inspect}"
101
+ end
102
+
103
+ value
104
+ end
105
+
106
+ def validate_context_lines(value)
107
+ value = value.to_i if value.respond_to?(:to_i) && !value.is_a?(Integer)
108
+
109
+ unless value.is_a?(Integer) && value >= MIN_CONTEXT_LINES && value <= MAX_CONTEXT_LINES
110
+ raise ArgumentError,
111
+ "context_lines must be an integer between #{MIN_CONTEXT_LINES} and #{MAX_CONTEXT_LINES}, got: #{value.inspect}"
112
+ end
113
+
114
+ value
115
+ end
116
+
117
+ def validate_max_lines(value)
118
+ value = value.to_i if value.respond_to?(:to_i) && !value.is_a?(Integer)
119
+
120
+ unless value.is_a?(Integer) && value >= MIN_MAX_LINES && value <= MAX_MAX_LINES
121
+ raise ArgumentError,
122
+ "max_lines must be an integer between #{MIN_MAX_LINES} and #{MAX_MAX_LINES}, got: #{value.inspect}"
123
+ end
124
+
125
+ value
126
+ end
127
+ end
128
+ end
129
+ end
@@ -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
@@ -1240,6 +1246,11 @@ module Aidp
1240
1246
  total_tokens: m[:total_tokens] || 0,
1241
1247
  last_used: m[:last_used]
1242
1248
  }
1249
+
1250
+ # Set reason if currently rate limited (for display in Reason column)
1251
+ if rl && reset_in && reset_in > 0
1252
+ row[:unhealthy_reason] ||= "rate_limited"
1253
+ end
1243
1254
  # Incorporate CLI check outcome into reason/availability if failing
1244
1255
  unless cli_ok_prefetch
1245
1256
  row[:available] = false
@@ -1416,9 +1427,43 @@ module Aidp
1416
1427
 
1417
1428
  # Execute a prompt with a specific provider
1418
1429
  def execute_with_provider(provider_type, prompt, options = {})
1430
+ options = options.dup
1431
+
1419
1432
  # Extract model from options if provided
1420
1433
  model_name = options.delete(:model)
1421
- retry_on_rate_limit = options.delete(:retry_on_rate_limit) != false # Default true
1434
+ retry_on_rate_limit = if options.key?(:retry_on_rate_limit)
1435
+ options.delete(:retry_on_rate_limit) != false
1436
+ else
1437
+ true
1438
+ end
1439
+ retry_on_unsupported = if options.key?(:retry_on_unsupported)
1440
+ options.delete(:retry_on_unsupported) != false
1441
+ else
1442
+ true
1443
+ end
1444
+ tier = options[:tier]
1445
+ base_options = options.dup
1446
+
1447
+ if model_name && model_denied?(provider_type, model_name)
1448
+ alternate_model = select_alternate_model(provider_type, tier: tier, current_model: model_name)
1449
+ if alternate_model
1450
+ Aidp.logger.warn("provider_manager", "Model is denylisted, selecting alternate",
1451
+ provider: provider_type,
1452
+ model: model_name,
1453
+ alternate_model: alternate_model,
1454
+ tier: tier)
1455
+
1456
+ return execute_with_provider(
1457
+ provider_type,
1458
+ prompt,
1459
+ base_options.merge(
1460
+ model: alternate_model,
1461
+ retry_on_rate_limit: retry_on_rate_limit,
1462
+ retry_on_unsupported: false
1463
+ )
1464
+ )
1465
+ end
1466
+ end
1422
1467
 
1423
1468
  # Create provider factory instance
1424
1469
  provider_factory = ProviderFactory.new
@@ -1440,7 +1485,7 @@ module Aidp
1440
1485
  prompt_length: prompt.length)
1441
1486
 
1442
1487
  # Execute the prompt with the provider
1443
- result = provider.send_message(prompt: prompt, session: nil)
1488
+ result = provider.send_message(prompt: prompt, session: nil, options: options)
1444
1489
 
1445
1490
  # Return structured result
1446
1491
  {
@@ -1460,6 +1505,28 @@ module Aidp
1460
1505
 
1461
1506
  if unsupported_model_error?(e, model_name)
1462
1507
  deny_model(provider_type, model_name, error: e)
1508
+
1509
+ if retry_on_unsupported
1510
+ alternate_model = select_alternate_model(provider_type, tier: tier, current_model: model_name)
1511
+
1512
+ if alternate_model
1513
+ Aidp.logger.info("provider_manager", "Retrying with alternate model after unsupported model error",
1514
+ provider: provider_type,
1515
+ original_model: model_name,
1516
+ alternate_model: alternate_model,
1517
+ tier: tier)
1518
+
1519
+ return execute_with_provider(
1520
+ provider_type,
1521
+ prompt,
1522
+ base_options.merge(
1523
+ model: alternate_model,
1524
+ retry_on_rate_limit: retry_on_rate_limit,
1525
+ retry_on_unsupported: false
1526
+ )
1527
+ )
1528
+ end
1529
+ end
1463
1530
  end
1464
1531
 
1465
1532
  # Detect rate limit / quota errors and attempt fallback
@@ -1615,12 +1682,39 @@ module Aidp
1615
1682
 
1616
1683
  message = error&.message.to_s.downcase
1617
1684
  return false if message.empty?
1685
+ return false unless message.include?(model_name.to_s.downcase)
1618
1686
 
1619
1687
  (message.include?("unsupported") && message.include?("model")) ||
1620
1688
  (message.include?("model") && message.include?("not supported")) ||
1621
1689
  message.include?("invalid model")
1622
1690
  end
1623
1691
 
1692
+ # Select an alternate model for the provider and tier, excluding denylisted/current models
1693
+ def select_alternate_model(provider_name, tier:, current_model: nil)
1694
+ candidates = []
1695
+
1696
+ if tier && @configuration.respond_to?(:models_for_tier)
1697
+ tier_models = Array(@configuration.models_for_tier(tier, provider_name)).map(&:to_s)
1698
+ candidates.concat(tier_models)
1699
+ end
1700
+
1701
+ if candidates.empty? && @configuration.respond_to?(:provider_models)
1702
+ provider_models = Array(@configuration.provider_models(provider_name)).map(&:to_s)
1703
+ candidates.concat(provider_models)
1704
+ end
1705
+
1706
+ candidates = candidates.uniq
1707
+ return nil if candidates.empty?
1708
+
1709
+ excluded = Array(current_model).compact + Array(@model_denylist[provider_name])
1710
+ candidates.reject! { |model| excluded.include?(model) }
1711
+ candidates.first
1712
+ rescue => e
1713
+ log_rescue(e, component: "provider_manager", action: "select_alternate_model", fallback: nil,
1714
+ provider: provider_name, tier: tier, current_model: current_model)
1715
+ nil
1716
+ end
1717
+
1624
1718
  public
1625
1719
 
1626
1720
  # Log provider switch
@@ -2,16 +2,6 @@
2
2
 
3
3
  require "timeout"
4
4
  require "json"
5
- require_relative "configuration"
6
- require_relative "state_manager"
7
- require_relative "condition_detector"
8
- require_relative "provider_manager"
9
- require_relative "simple_user_interface"
10
- require_relative "error_handler"
11
- require_relative "status_display"
12
- require_relative "completion_checker"
13
- require_relative "../concurrency"
14
- require_relative "../errors"
15
5
 
16
6
  module Aidp
17
7
  module Harness
@@ -33,7 +23,11 @@ module Aidp
33
23
  }.freeze
34
24
 
35
25
  # Public accessors for testing and integration
36
- attr_reader :current_provider, :current_step, :user_input, :execution_log, :provider_manager, :clarification_questions
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
37
31
 
38
32
  def initialize(project_dir, mode = :analyze, options = {})
39
33
  @project_dir = project_dir
@@ -61,7 +55,6 @@ module Aidp
61
55
  # Use ZFC-enabled condition detector
62
56
  # ZfcConditionDetector will create its own ProviderFactory if needed
63
57
  # Falls back to legacy pattern matching when ZFC is disabled
64
- require_relative "zfc_condition_detector"
65
58
  @condition_detector = ZfcConditionDetector.new(@configuration)
66
59
 
67
60
  @user_interface = SimpleUserInterface.new
@@ -11,6 +11,9 @@ module Aidp
11
11
  class Persistence
12
12
  include Aidp::SafeDirectory
13
13
 
14
+ # Expose for testability
15
+ attr_reader :state_file, :lock_file
16
+
14
17
  def initialize(project_dir, mode, skip_persistence: false)
15
18
  @project_dir = project_dir
16
19
  @mode = mode
@@ -14,6 +14,9 @@ module Aidp
14
14
  class StateManager
15
15
  include Aidp::SafeDirectory
16
16
 
17
+ # Expose for testability
18
+ attr_reader :project_dir, :mode
19
+
17
20
  def initialize(project_dir, mode, skip_persistence: false)
18
21
  @project_dir = project_dir
19
22
  @mode = mode
@@ -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
- # Set display mode
171
- def display_mode(mode)
172
- @display_mode = mode
173
- @display_config[:mode] = mode
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
- # Set update interval
177
- def update_interval(interval)
178
- @update_interval = interval
179
- @display_config[:update_interval] = interval
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