Class: Legion::Extensions::Agentic::Executive::FlexibilityTraining::Helpers::FlexibilityEngine

Inherits:
Object
  • Object
show all
Defined in:
lib/legion/extensions/agentic/executive/flexibility_training/helpers/flexibility_engine.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeFlexibilityEngine

Returns a new instance of FlexibilityEngine.



12
13
14
15
16
17
# File 'lib/legion/extensions/agentic/executive/flexibility_training/helpers/flexibility_engine.rb', line 12

def initialize
  @tasks           = {}
  @trials          = []
  @sessions        = []
  @current_session = nil
end

Instance Attribute Details

#sessionsObject (readonly)

Returns the value of attribute sessions.



10
11
12
# File 'lib/legion/extensions/agentic/executive/flexibility_training/helpers/flexibility_engine.rb', line 10

def sessions
  @sessions
end

#tasksObject (readonly)

Returns the value of attribute tasks.



10
11
12
# File 'lib/legion/extensions/agentic/executive/flexibility_training/helpers/flexibility_engine.rb', line 10

def tasks
  @tasks
end

#trialsObject (readonly)

Returns the value of attribute trials.



10
11
12
# File 'lib/legion/extensions/agentic/executive/flexibility_training/helpers/flexibility_engine.rb', line 10

def trials
  @trials
end

Instance Method Details

#average_switch_cost(window: 50) ⇒ Object



71
72
73
74
75
76
# File 'lib/legion/extensions/agentic/executive/flexibility_training/helpers/flexibility_engine.rb', line 71

def average_switch_cost(window: 50)
  recent = @trials.last(window)
  return 0.0 if recent.empty?

  (recent.sum(&:switch_cost) / recent.size).round(10)
end

#easiest_switches(limit: 5) ⇒ Object



108
109
110
111
112
# File 'lib/legion/extensions/agentic/executive/flexibility_training/helpers/flexibility_engine.rb', line 108

def easiest_switches(limit: 5)
  pair_averages.sort_by { |_, cost| cost }.first(limit).map do |pair, cost|
    { from_task_id: pair[0], to_task_id: pair[1], average_switch_cost: cost.round(10) }
  end
end

#end_sessionObject



61
62
63
64
65
66
67
68
69
# File 'lib/legion/extensions/agentic/executive/flexibility_training/helpers/flexibility_engine.rb', line 61

def end_session
  return nil unless @current_session

  session = @current_session.dup
  @sessions << session
  @sessions.shift while @sessions.size > Constants::MAX_SESSIONS
  @current_session = nil
  session
end

#flexibility_scoreObject



98
99
100
# File 'lib/legion/extensions/agentic/executive/flexibility_training/helpers/flexibility_engine.rb', line 98

def flexibility_score
  (1.0 - average_switch_cost).round(10)
end

#hardest_switches(limit: 5) ⇒ Object



102
103
104
105
106
# File 'lib/legion/extensions/agentic/executive/flexibility_training/helpers/flexibility_engine.rb', line 102

def hardest_switches(limit: 5)
  pair_averages.sort_by { |_, cost| -cost }.first(limit).map do |pair, cost|
    { from_task_id: pair[0], to_task_id: pair[1], average_switch_cost: cost.round(10) }
  end
end

#improvement_rateObject



85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/legion/extensions/agentic/executive/flexibility_training/helpers/flexibility_engine.rb', line 85

def improvement_rate
  return 0.0 if @trials.size < 4

  half   = @trials.size / 2
  early  = @trials.first(half)
  recent = @trials.last(half)

  early_avg  = early.sum(&:switch_cost) / early.size.to_f
  recent_avg = recent.sum(&:switch_cost) / recent.size.to_f

  ((early_avg - recent_avg) / early_avg.clamp(0.001, 1.0)).round(10)
end

#perform_switch(from_task_id:, to_task_id:) ⇒ 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
# File 'lib/legion/extensions/agentic/executive/flexibility_training/helpers/flexibility_engine.rb', line 28

def perform_switch(from_task_id:, to_task_id:)
  return { error: :max_trials_reached } if @trials.size >= Constants::MAX_TRIALS

  from_task = @tasks[from_task_id]
  to_task   = @tasks[to_task_id]

  return { error: :task_not_found, missing: :from } unless from_task
  return { error: :task_not_found, missing: :to }   unless to_task

  cost     = compute_switch_cost(from_task, to_task)
  accuracy = compute_accuracy(to_task, cost)

  trial = SwitchTrial.new(
    from_task_id: from_task_id,
    to_task_id:   to_task_id,
    switch_cost:  cost,
    accuracy:     accuracy
  )

  @trials << trial
  @current_session << trial if @current_session

  from_task.practice!
  to_task.practice!

  trial
end

#register_task(name:, domain:, difficulty: 0.5) ⇒ Object



19
20
21
22
23
24
25
26
# File 'lib/legion/extensions/agentic/executive/flexibility_training/helpers/flexibility_engine.rb', line 19

def register_task(name:, domain:, difficulty: 0.5)
  return { error: :max_tasks_reached } if @tasks.size >= Constants::MAX_TASKS
  return { error: :invalid_domain } unless Constants::TASK_DOMAINS.include?(domain)

  task = TrainingTask.new(name: name, domain: domain, difficulty: difficulty)
  @tasks[task.id] = task
  task
end

#start_sessionObject



56
57
58
59
# File 'lib/legion/extensions/agentic/executive/flexibility_training/helpers/flexibility_engine.rb', line 56

def start_session
  @current_session = []
  self
end

#switch_cost_between(from_id:, to_id:) ⇒ Object



78
79
80
81
82
83
# File 'lib/legion/extensions/agentic/executive/flexibility_training/helpers/flexibility_engine.rb', line 78

def switch_cost_between(from_id:, to_id:)
  pair_trials = @trials.select { |t| t.from_task_id == from_id && t.to_task_id == to_id }
  return 0.0 if pair_trials.empty?

  (pair_trials.sum(&:switch_cost) / pair_trials.size).round(10)
end

#to_hObject



129
130
131
132
133
134
135
136
# File 'lib/legion/extensions/agentic/executive/flexibility_training/helpers/flexibility_engine.rb', line 129

def to_h
  {
    tasks:    @tasks.transform_values(&:to_h),
    trials:   @trials.map(&:to_h),
    sessions: @sessions.map { |s| s.map(&:to_h) },
    report:   training_report
  }
end

#training_reportObject



114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/legion/extensions/agentic/executive/flexibility_training/helpers/flexibility_engine.rb', line 114

def training_report
  {
    task_count:             @tasks.size,
    trial_count:            @trials.size,
    session_count:          @sessions.size,
    average_switch_cost:    average_switch_cost,
    flexibility_score:      flexibility_score,
    improvement_rate:       improvement_rate,
    flexibility_label:      Constants.label_for(flexibility_score, Constants::FLEXIBILITY_LABELS),
    progress_label:         Constants.label_for(1.0 - average_switch_cost, Constants::PROGRESS_LABELS),
    costly_trial_ratio:     costly_ratio,
    successful_trial_ratio: success_ratio
  }
end