Class: Legion::Extensions::Agentic::Homeostasis::Hourglass::Helpers::Hourglass

Inherits:
Object
  • Object
show all
Defined in:
lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(domain: nil, grain_type: :attention, top_level: 1.0, neck_width: 0.5, bottom_level: 0.0) ⇒ Hourglass

Returns a new instance of Hourglass.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass.rb', line 13

def initialize(domain: nil, grain_type: :attention, top_level: 1.0,
               neck_width: 0.5, bottom_level: 0.0)
  validate_args!(grain_type, top_level, bottom_level, neck_width)

  @id           = SecureRandom.uuid
  @domain       = domain&.to_s
  @grain_type   = grain_type.to_sym
  @top_level    = top_level.to_f.clamp(0.0, 1.0).round(10)
  @bottom_level = bottom_level.to_f.clamp(0.0, 1.0).round(10)
  @neck_width   = neck_width.to_f.clamp(0.0, 1.0).round(10)
  @created_at   = Time.now.utc
  @flipped_at   = nil
  @state        = derive_state
end

Instance Attribute Details

#bottom_levelObject (readonly)

Returns the value of attribute bottom_level.



10
11
12
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass.rb', line 10

def bottom_level
  @bottom_level
end

#created_atObject (readonly)

Returns the value of attribute created_at.



10
11
12
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass.rb', line 10

def created_at
  @created_at
end

#domainObject (readonly)

Returns the value of attribute domain.



10
11
12
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass.rb', line 10

def domain
  @domain
end

#flipped_atObject (readonly)

Returns the value of attribute flipped_at.



10
11
12
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass.rb', line 10

def flipped_at
  @flipped_at
end

#grain_typeObject (readonly)

Returns the value of attribute grain_type.



10
11
12
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass.rb', line 10

def grain_type
  @grain_type
end

#idObject (readonly)

Returns the value of attribute id.



10
11
12
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass.rb', line 10

def id
  @id
end

#neck_widthObject (readonly)

Returns the value of attribute neck_width.



10
11
12
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass.rb', line 10

def neck_width
  @neck_width
end

#stateObject (readonly)

Returns the value of attribute state.



10
11
12
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass.rb', line 10

def state
  @state
end

#top_levelObject (readonly)

Returns the value of attribute top_level.



10
11
12
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass.rb', line 10

def top_level
  @top_level
end

Instance Method Details

#expired?Boolean

Top chamber is empty — no more cognitive resource remaining

Returns:

  • (Boolean)


66
67
68
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass.rb', line 66

def expired?
  @top_level <= 0.0
end

#flip!Object

Flip the hourglass — top and bottom swap, state resets to flowing



44
45
46
47
48
49
50
51
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass.rb', line 44

def flip!
  @top_level, @bottom_level = @bottom_level, @top_level
  @top_level    = @top_level.round(10)
  @bottom_level = @bottom_level.round(10)
  @flipped_at   = Time.now.utc
  @state        = derive_state
  self
end

#flow!(rate = Constants::FLOW_RATE) ⇒ Object

Advance one flow tick — sand moves from top to bottom through the neck



29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass.rb', line 29

def flow!(rate = Constants::FLOW_RATE)
  return self if @state == :paused
  return self if expired?

  effective_rate = (rate.to_f * @neck_width).clamp(0.0, 1.0).round(10)
  transferred    = [@top_level, effective_rate].min.round(10)

  @top_level    = (@top_level - transferred).clamp(0.0, 1.0).round(10)
  @bottom_level = (@bottom_level + transferred).clamp(0.0, 1.0).round(10)

  @state = derive_state
  self
end

#fresh?Boolean

Just flipped within the last 30 seconds

Returns:

  • (Boolean)


71
72
73
74
75
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass.rb', line 71

def fresh?
  return false unless @flipped_at

  (Time.now.utc - @flipped_at) < 30.0
end

#fullness_labelObject

Fullness label based on the top chamber level



84
85
86
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass.rb', line 84

def fullness_label
  Constants.label_for(:FULLNESS_LABELS, @top_level)
end

#pause!Object

Pause flow — grains stop moving through the neck



54
55
56
57
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass.rb', line 54

def pause!
  @state = :paused
  self
end

#resume!Object

Resume flow — grains move again, state re-derived from levels



60
61
62
63
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass.rb', line 60

def resume!
  @state = derive_state
  self
end

#to_hObject



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass.rb', line 88

def to_h
  {
    id:             @id,
    domain:         @domain,
    grain_type:     @grain_type,
    top_level:      @top_level,
    bottom_level:   @bottom_level,
    neck_width:     @neck_width,
    state:          @state,
    expired:        expired?,
    fresh:          fresh?,
    urgency_label:  urgency_label,
    fullness_label: fullness_label,
    created_at:     @created_at,
    flipped_at:     @flipped_at
  }
end

#urgency_labelObject

Urgency label based on how empty the top chamber is



78
79
80
81
# File 'lib/legion/extensions/agentic/homeostasis/hourglass/helpers/hourglass.rb', line 78

def urgency_label
  urgency = 1.0 - @top_level
  Constants.label_for(:URGENCY_LABELS, urgency)
end