Class: Aidp::Harness::AIDecisionEngine

Inherits:
Object
  • Object
show all
Defined in:
lib/aidp/harness/ai_decision_engine.rb

Overview

Zero Framework Cognition (ZFC) Decision Engine

Delegates semantic analysis and decision-making to AI models instead of using brittle pattern matching, scoring formulas, or heuristic thresholds.

All prompts are loaded from YAML templates at:

  • Project level: .aidp/prompts/decision_engine/.yml
  • User level: ~/.aidp/prompts/decision_engine/.yml
  • Built-in: lib/aidp/prompts/defaults/decision_engine/.yml

Examples:

Basic usage

engine = AIDecisionEngine.new(config, provider_manager)
result = engine.decide(:condition_detection,
  context: { error: "Rate limit exceeded" },
  tier: "mini"
)
# => { condition: "rate_limit", confidence: 0.95, reasoning: "..." }

See Also:

  • docs/ZFC_COMPLIANCE_ASSESSMENTdocs/ZFC_COMPLIANCE_ASSESSMENT.md
  • docs/ZFC_IMPLEMENTATION_PLANdocs/ZFC_IMPLEMENTATION_PLAN.md

Constant Summary collapse

TEMPLATE_PATHS =

Maps decision types to template file paths

{
  condition_detection: "decision_engine/condition_detection",
  error_classification: "decision_engine/error_classification",
  completion_detection: "decision_engine/completion_detection",
  implementation_verification: "decision_engine/implementation_verification",
  prompt_evaluation: "decision_engine/prompt_evaluation",
  template_improvement: "decision_engine/template_improvement",
  template_evolution: "decision_engine/template_evolution"
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config, provider_factory: nil, prompt_template_manager: nil, project_dir: Dir.pwd) ⇒ AIDecisionEngine

Initialize the AI Decision Engine

Parameters:

  • config (Configuration)

    AIDP configuration object

  • provider_factory (ProviderFactory) (defaults to: nil)

    Factory for creating provider instances

  • prompt_template_manager (PromptTemplateManager) (defaults to: nil)

    Optional template manager

  • project_dir (String) (defaults to: Dir.pwd)

    Project directory for template loading



50
51
52
53
54
55
56
57
58
# File 'lib/aidp/harness/ai_decision_engine.rb', line 50

def initialize(config, provider_factory: nil, prompt_template_manager: nil, project_dir: Dir.pwd)
  @config = config
  # ProviderFactory expects a ConfigManager, not a Configuration object.
  # Pass nil to let ProviderFactory create its own ConfigManager.
  @provider_factory = provider_factory || ProviderFactory.new
  @prompt_template_manager = prompt_template_manager || Prompts::PromptTemplateManager.new(project_dir: project_dir)
  @cache = {}
  @cache_timestamps = {}
end

Instance Attribute Details

#cacheObject (readonly)

Returns the value of attribute cache.



42
43
44
# File 'lib/aidp/harness/ai_decision_engine.rb', line 42

def cache
  @cache
end

#configObject (readonly)

Returns the value of attribute config.



42
43
44
# File 'lib/aidp/harness/ai_decision_engine.rb', line 42

def config
  @config
end

#prompt_template_managerObject (readonly)

Returns the value of attribute prompt_template_manager.



42
43
44
# File 'lib/aidp/harness/ai_decision_engine.rb', line 42

def prompt_template_manager
  @prompt_template_manager
end

#provider_factoryObject (readonly)

Returns the value of attribute provider_factory.



42
43
44
# File 'lib/aidp/harness/ai_decision_engine.rb', line 42

def provider_factory
  @provider_factory
end

Instance Method Details

#available_decision_typesArray<Symbol>

List available decision types

Returns:

  • (Array<Symbol>)

    Available decision type symbols



135
136
137
# File 'lib/aidp/harness/ai_decision_engine.rb', line 135

def available_decision_types
  TEMPLATE_PATHS.keys
end

#decide(decision_type, context:, schema: nil, tier: nil, cache_ttl: nil) ⇒ Hash

Make an AI-powered decision

Parameters:

  • decision_type (Symbol)

    Type of decision (:condition_detection, :error_classification, etc.)

  • context (Hash)

    Context data for the decision

  • schema (Hash, nil) (defaults to: nil)

    JSON schema for response validation (overrides template schema)

  • tier (String, nil) (defaults to: nil)

    Thinking depth tier (overrides template tier)

  • cache_ttl (Integer, nil) (defaults to: nil)

    Cache TTL in seconds (overrides template cache_ttl)

Returns:

  • (Hash)

    Validated decision result

Raises:



71
72
73
74
75
76
77
78
79
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
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/aidp/harness/ai_decision_engine.rb', line 71

def decide(decision_type, context:, schema: nil, tier: nil, cache_ttl: nil)
  template_path = TEMPLATE_PATHS[decision_type]
  raise ArgumentError, "Unknown decision type: #{decision_type}" unless template_path

  # Load template data
  template_data = @prompt_template_manager.load_template(template_path)
  raise Prompts::TemplateNotFoundError, "Template not found: #{template_path}" unless template_data

  # Check cache if TTL specified
  template_cache_ttl = template_data["cache_ttl"] || template_data[:cache_ttl]
  ttl = cache_ttl || template_cache_ttl
  cache_key = build_cache_key(decision_type, context)
  if ttl && (cached_result = get_cached(cache_key, ttl))
    Aidp.log_debug("ai_decision_engine", "cache_hit", {
      decision_type: decision_type,
      cache_key: cache_key,
      ttl: ttl
    })
    return cached_result
  end

  # Render prompt with variables
  prompt = @prompt_template_manager.render(template_path, **context)

  # Select tier from parameter, template, or default
  template_tier = template_data["tier"] || template_data[:tier]
  selected_tier = tier || template_tier || "mini"

  # Get model for tier, using harness default provider
  thinking_manager = ThinkingDepthManager.new(config)
  provider_name, model_name, _model_data = thinking_manager.select_model_for_tier(
    selected_tier,
    provider: config.default_provider
  )

  Aidp.log_debug("ai_decision_engine", "making_decision", {
    decision_type: decision_type,
    template_path: template_path,
    tier: selected_tier,
    provider: provider_name,
    model: model_name,
    cache_ttl: ttl
  })

  # Get schema from parameter or template
  template_schema = template_data["schema"] || template_data[:schema]
  response_schema = schema || symbolize_schema(template_schema)
  raise ArgumentError, "No schema defined for decision type: #{decision_type}" unless response_schema

  # Call AI with schema validation
  result = call_ai_with_schema(provider_name, model_name, prompt, response_schema)

  # Validate result
  validate_schema(result, response_schema)

  # Cache if TTL specified
  set_cached(cache_key, result) if ttl

  result
end