Class: DecisionAgent::Evaluators::JsonRuleEvaluator

Inherits:
Base
  • Object
show all
Defined in:
lib/decision_agent/evaluators/json_rule_evaluator.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(rules_json:, name: nil) ⇒ JsonRuleEvaluator

Returns a new instance of JsonRuleEvaluator.



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/decision_agent/evaluators/json_rule_evaluator.rb', line 10

def initialize(rules_json:, name: nil)
  @rules_json = rules_json.is_a?(String) ? rules_json : JSON.generate(rules_json)
  @ruleset = Dsl::RuleParser.parse(@rules_json)
  @ruleset_name = @ruleset["ruleset"] || "unknown"
  @name = name || "JsonRuleEvaluator(#{@ruleset_name})"

  # Pre-build O(1) rule lookup map keyed by rule_id
  @rules_by_id = (@ruleset["rules"] || []).each_with_index.to_h do |rule, i|
    [rule["id"] || "rule_#{i}", rule]
  end.freeze

  # Freeze ruleset to ensure thread-safety
  deep_freeze(@ruleset)
  @rules_json.freeze
  @ruleset_name.freeze
  @name.freeze
end

Instance Attribute Details

#ruleset_nameObject (readonly)

Returns the value of attribute ruleset_name.



8
9
10
# File 'lib/decision_agent/evaluators/json_rule_evaluator.rb', line 8

def ruleset_name
  @ruleset_name
end

Instance Method Details

#evaluate(context, feedback: {}) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/decision_agent/evaluators/json_rule_evaluator.rb', line 28

def evaluate(context, feedback: {})
  ctx = context.is_a?(DecisionAgent::Context) ? context : DecisionAgent::Context.new(context)

  # Collect explainability traces (this also finds the matching rule)
  explainability_result = collect_explainability(ctx)

  # Find the matched rule from explainability result
  matched_rule_trace = explainability_result&.matched_rules&.first
  return nil unless matched_rule_trace

  # Find the original rule to get the then clause (O(1) lookup)
  matched_rule = @rules_by_id[matched_rule_trace.rule_id]
  return nil unless matched_rule

  then_clause = matched_rule["then"]

   = {
    type: "json_rule",
    rule_id: matched_rule["id"],
    ruleset: @ruleset_name
  }

  # Add explainability data to metadata
  [:explainability] = explainability_result.to_h if explainability_result

  Evaluation.new(
    decision: then_clause["decision"],
    weight: then_clause["weight"] || 1.0,
    reason: then_clause["reason"] || "Rule matched",
    evaluator_name: @name,
    metadata: 
  )
end