Class: Aidp::Harness::ZfcConditionDetector
- Inherits:
-
Object
- Object
- Aidp::Harness::ZfcConditionDetector
- Defined in:
- lib/aidp/harness/zfc_condition_detector.rb
Overview
ZFC-enabled wrapper for ConditionDetector
Delegates semantic analysis to AI when ZFC is enabled, falls back to legacy pattern matching when disabled or on AI failure.
Instance Attribute Summary collapse
-
#ai_engine ⇒ Object
readonly
Returns the value of attribute ai_engine.
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#legacy_detector ⇒ Object
readonly
Returns the value of attribute legacy_detector.
-
#stats ⇒ Object
readonly
Returns the value of attribute stats.
Instance Method Summary collapse
-
#classify_error(error, context = {}) ⇒ Hash
Classify error using AI or legacy pattern matching.
-
#extract_questions(result) ⇒ Array<Hash>
Extract questions from result (delegates to legacy for now).
-
#extract_rate_limit_info(result, provider = nil) ⇒ Hash
Extract rate limit info (delegates to legacy for now).
-
#initialize(config, provider_factory: nil) ⇒ ZfcConditionDetector
constructor
Initialize ZFC condition detector.
-
#is_rate_limited?(result, provider = nil) ⇒ Boolean
Check if result indicates rate limiting.
-
#is_work_complete?(result, progress = nil) ⇒ Boolean
Check if work is complete.
-
#needs_user_feedback?(result) ⇒ Boolean
Check if result needs user feedback.
-
#statistics ⇒ Hash
Get statistics summary.
Constructor Details
#initialize(config, provider_factory: nil) ⇒ ZfcConditionDetector
Initialize ZFC condition detector
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/aidp/harness/zfc_condition_detector.rb', line 28 def initialize(config, provider_factory: nil) @config = config @legacy_detector = ConditionDetector.new # Create ProviderFactory if not provided and ZFC is enabled # Note: ConfigManager doesn't have zfc_enabled?, so we check respond_to? first if provider_factory.nil? && config.respond_to?(:zfc_enabled?) && config.zfc_enabled? require_relative "provider_factory" provider_factory = ProviderFactory.new end @ai_engine = AIDecisionEngine.new(config, provider_factory: provider_factory) # Statistics for A/B testing @stats = { zfc_calls: 0, legacy_calls: 0, zfc_fallbacks: 0, agreements: 0, disagreements: 0, zfc_total_cost: 0.0 } end |
Instance Attribute Details
#ai_engine ⇒ Object (readonly)
Returns the value of attribute ai_engine.
22 23 24 |
# File 'lib/aidp/harness/zfc_condition_detector.rb', line 22 def ai_engine @ai_engine end |
#config ⇒ Object (readonly)
Returns the value of attribute config.
22 23 24 |
# File 'lib/aidp/harness/zfc_condition_detector.rb', line 22 def config @config end |
#legacy_detector ⇒ Object (readonly)
Returns the value of attribute legacy_detector.
22 23 24 |
# File 'lib/aidp/harness/zfc_condition_detector.rb', line 22 def legacy_detector @legacy_detector end |
#stats ⇒ Object (readonly)
Returns the value of attribute stats.
22 23 24 |
# File 'lib/aidp/harness/zfc_condition_detector.rb', line 22 def stats @stats end |
Instance Method Details
#classify_error(error, context = {}) ⇒ Hash
Classify error using AI or legacy pattern matching
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/aidp/harness/zfc_condition_detector.rb', line 143 def classify_error(error, context = {}) return @legacy_detector.classify_error(error) unless zfc_enabled?(:error_classification) begin # Build context for AI decision error_context = { error_message: error_to_text(error), context: context.to_s } # Ask AI to classify error ai_result = @ai_engine.decide(:error_classification, context: error_context, tier: zfc_tier(:error_classification), cache_ttl: zfc_cache_ttl(:error_classification)) record_zfc_call(:error_classification, ai_result) # A/B test if enabled if ab_testing_enabled? legacy_result = @legacy_detector.classify_error(error) compare_error_results(ai_result, legacy_result) end # Only use AI result if confidence is high enough if ai_result[:confidence] >= confidence_threshold(:error_classification) # Convert AI result to legacy format { error: error, error_type: ai_result[:error_type].to_sym, retryable: ai_result[:retryable], recommended_action: ai_result[:recommended_action].to_sym, confidence: ai_result[:confidence], reasoning: ai_result[:reasoning], timestamp: Time.now, context: context, message: error&. || "Unknown error" } else @legacy_detector.classify_error(error) end rescue => e Aidp.log_error("zfc_condition_detector", "ZFC error classification failed, falling back to legacy", { error: e., error_class: e.class.name, original_error: error&.class&.name }) record_fallback(:error_classification) @legacy_detector.classify_error(error) end end |
#extract_questions(result) ⇒ Array<Hash>
Extract questions from result (delegates to legacy for now)
125 126 127 |
# File 'lib/aidp/harness/zfc_condition_detector.rb', line 125 def extract_questions(result) @legacy_detector.extract_questions(result) end |
#extract_rate_limit_info(result, provider = nil) ⇒ Hash
Extract rate limit info (delegates to legacy for now)
134 135 136 |
# File 'lib/aidp/harness/zfc_condition_detector.rb', line 134 def extract_rate_limit_info(result, provider = nil) @legacy_detector.extract_rate_limit_info(result, provider) end |
#is_rate_limited?(result, provider = nil) ⇒ Boolean
Check if result indicates rate limiting
57 58 59 60 61 62 |
# File 'lib/aidp/harness/zfc_condition_detector.rb', line 57 def is_rate_limited?(result, provider = nil) detect_condition(:is_rate_limited?, result, provider: provider) do |ai_result| ai_result[:condition] == "rate_limit" && ai_result[:confidence] >= confidence_threshold(:condition_detection) end end |
#is_work_complete?(result, progress = nil) ⇒ Boolean
Check if work is complete
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/aidp/harness/zfc_condition_detector.rb', line 80 def is_work_complete?(result, progress = nil) return false unless result if zfc_enabled?(:completion_detection) begin # Build context for AI decision context = { response: result_to_text(result), task_description: progress&.dig(:task) || "general task" } # Ask AI if work is complete ai_result = @ai_engine.decide(:completion_detection, context: context, tier: zfc_tier(:completion_detection), cache_ttl: zfc_cache_ttl(:completion_detection)) record_zfc_call(:completion_detection, ai_result) # A/B test if enabled if ab_testing_enabled? legacy_result = @legacy_detector.is_work_complete?(result, progress) compare_results(:is_work_complete, ai_result[:complete], legacy_result) end ai_result[:complete] && ai_result[:confidence] >= confidence_threshold(:completion_detection) rescue => e Aidp.log_error("zfc_condition_detector", "ZFC completion detection failed, falling back to legacy", { error: e., error_class: e.class.name }) record_fallback(:completion_detection) @legacy_detector.is_work_complete?(result, progress) end else @stats[:legacy_calls] += 1 @legacy_detector.is_work_complete?(result, progress) end end |
#needs_user_feedback?(result) ⇒ Boolean
Check if result needs user feedback
68 69 70 71 72 73 |
# File 'lib/aidp/harness/zfc_condition_detector.rb', line 68 def needs_user_feedback?(result) detect_condition(:needs_user_feedback?, result, provider: nil) do |ai_result| ai_result[:condition] == "user_feedback_needed" && ai_result[:confidence] >= confidence_threshold(:condition_detection) end end |
#statistics ⇒ Hash
Get statistics summary
198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/aidp/harness/zfc_condition_detector.rb', line 198 def statistics total_calls = @stats[:zfc_calls] + @stats[:legacy_calls] return @stats.merge(total_calls: 0, accuracy: nil) if total_calls.zero? comparisons = @stats[:agreements] + @stats[:disagreements] accuracy = comparisons.zero? ? nil : (@stats[:agreements].to_f / comparisons * 100).round(2) @stats.merge( total_calls: total_calls, zfc_percentage: (@stats[:zfc_calls].to_f / total_calls * 100).round(2), accuracy: accuracy, fallback_rate: (@stats[:zfc_fallbacks].to_f / [@stats[:zfc_calls], 1].max * 100).round(2) ) end |