lex-tick 0.1.0 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4a3808a8152389198268ec0a2064aee1a4acdcf8fc7aa5593118e1cd7f82deda
4
- data.tar.gz: 770f22284ee087b9319597ebe194b34bcc4e1b17b901db13f4bc8d45b38a6d3c
3
+ metadata.gz: 67d55a4a8a94f12d6ba0fca7937ff3597e428017e21a2ef09f6a790076316072
4
+ data.tar.gz: 80c0a4c792e8cc3648693926253bd82609326cc32a56adebd39dd9ed9acd1068
5
5
  SHA512:
6
- metadata.gz: 80498e4cfb7859876f8efb0e72ad89bad390f307d56f7a27dea617092f946d828db57522591af4629a3fe00e6c1ae279e7effca892a35cb5d14fe4085ad5eb3d
7
- data.tar.gz: f9a62ee7072446e4c0caf5b55c05fff8d12323ab3619fb7d9c923e0e252649ec9acab3d287f46a1358b6298ecb7285e519499838bf6e6c0b3c1f66b36c7662a6
6
+ metadata.gz: ceba58abf3a0ca2e43249adc62b9e39e3a7ea2f82482778b59f68aaad522f8e766ee4e62a860c51b8d0c706bd4b1611cea4b6f8eeb50cfbadcab8b5c53e88d2c
7
+ data.tar.gz: e1257c6343e35af0dfcd264913f733cd541df4318197edf1b97461adc9d1c734987b516ab981a4fb0e1194eb665e379f4433b3e3dba55fd3fea38bfa6f80eca9
data/Gemfile CHANGED
@@ -7,4 +7,4 @@ gemspec
7
7
  gem 'rspec', '~> 3.13'
8
8
  gem 'rubocop', '~> 1.75', require: false
9
9
 
10
- gem 'legion-gaia', path: '../../legion-gaia'
10
+ gem 'legion-gaia'
data/lex-tick.gemspec CHANGED
@@ -25,5 +25,12 @@ Gem::Specification.new do |spec|
25
25
  Dir.glob('{lib,spec}/**/*') + %w[lex-tick.gemspec Gemfile]
26
26
  end
27
27
  spec.require_paths = ['lib']
28
- spec.add_development_dependency 'legion-gaia'
28
+
29
+ spec.add_dependency 'legion-cache', '>= 1.3.11'
30
+ spec.add_dependency 'legion-crypt', '>= 1.4.9'
31
+ spec.add_dependency 'legion-data', '>= 1.4.17'
32
+ spec.add_dependency 'legion-json', '>= 1.2.1'
33
+ spec.add_dependency 'legion-logging', '>= 1.3.2'
34
+ spec.add_dependency 'legion-settings', '>= 1.3.14'
35
+ spec.add_dependency 'legion-transport', '>= 1.3.9'
29
36
  end
@@ -9,37 +9,16 @@ module Legion
9
9
  Legion::Extensions::Helpers.const_defined?(:Lex)
10
10
 
11
11
  def execute_tick(signals: [], phase_handlers: {}, **)
12
- state = tick_state
13
- state.increment_tick
14
-
15
- max_salience = signals.map { |s| s.is_a?(Hash) ? (s[:salience] || 0.0) : 0.0 }.max || 0.0
16
- state.record_signal(salience: max_salience) unless signals.empty?
17
-
18
- Legion::Logging.debug "[tick] ##{state.tick_count} starting | mode=#{state.mode} signals=#{signals.size} max_salience=#{max_salience.round(2)}"
19
-
20
- transition = evaluate_mode_transition(signals: signals)
21
- if transition[:transitioned]
22
- Legion::Logging.info "[tick] mode transition: #{transition[:previous_mode]} -> #{transition[:new_mode]} (#{transition[:reason]})"
12
+ if defined?(Legion::Telemetry::OpenInference)
13
+ state = tick_state
14
+ Legion::Telemetry::OpenInference.agent_span(
15
+ name: "tick-#{state.tick_count + 1}", mode: state.mode,
16
+ phase_count: Helpers::Constants.phases_for_mode(state.mode).size,
17
+ budget_ms: (Helpers::Constants.tick_budget(state.mode) * 1000).round
18
+ ) { |_span| execute_tick_impl(signals: signals, phase_handlers: phase_handlers) }
19
+ else
20
+ execute_tick_impl(signals: signals, phase_handlers: phase_handlers)
23
21
  end
24
-
25
- phases = Helpers::Constants.phases_for_mode(state.mode)
26
- budget = Helpers::Constants.tick_budget(state.mode)
27
- start_time = Time.now.utc
28
- ctx = { budget: budget, start_time: start_time, phase_handlers: phase_handlers, signals: signals }
29
- results = run_phases(phases, state, ctx)
30
-
31
- total_elapsed = Time.now.utc - start_time
32
- skipped = phases - results.keys
33
- log_tick_complete(state, results, phases, total_elapsed, skipped)
34
-
35
- {
36
- tick_number: state.tick_count,
37
- mode: state.mode,
38
- phases_executed: results.keys,
39
- phases_skipped: skipped,
40
- results: results,
41
- elapsed: total_elapsed
42
- }
43
22
  end
44
23
 
45
24
  def evaluate_mode_transition(signals: [], emergency: nil, dream_complete: false, **) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
@@ -48,7 +27,7 @@ module Legion
48
27
 
49
28
  # Emergency promotion
50
29
  if emergency && Helpers::Constants::EMERGENCY_TRIGGERS.include?(emergency)
51
- Legion::Logging.warn "[tick] emergency promotion triggered: #{emergency}"
30
+ log.warn "[tick] emergency promotion triggered: #{emergency}"
52
31
  state.transition_to(:full_active)
53
32
  return { transitioned: true, new_mode: :full_active, previous_mode: previous_mode, reason: :emergency }
54
33
  end
@@ -96,40 +75,72 @@ module Legion
96
75
  { transitioned: false, current_mode: state.mode }
97
76
  else
98
77
  state.transition_to(new_mode)
99
- Legion::Logging.info "[tick] mode transition: #{previous_mode} -> #{new_mode} (threshold)"
78
+ log.info "[tick] mode transition: #{previous_mode} -> #{new_mode} (threshold)"
100
79
  { transitioned: true, new_mode: new_mode, previous_mode: previous_mode, reason: :threshold }
101
80
  end
102
81
  end
103
82
 
104
83
  def tick_status(**)
105
84
  status = tick_state.to_h
106
- Legion::Logging.debug "[tick] status query: mode=#{status[:mode]} tick_count=#{status[:tick_count]}"
85
+ log.debug "[tick] status query: mode=#{status[:mode]} tick_count=#{status[:tick_count]}"
107
86
  status
108
87
  end
109
88
 
110
89
  def set_mode(mode:, **)
111
90
  unless Helpers::Constants::MODES.include?(mode)
112
- Legion::Logging.warn "[tick] invalid mode requested: #{mode}"
91
+ log.warn "[tick] invalid mode requested: #{mode}"
113
92
  return { error: :invalid_mode, valid_modes: Helpers::Constants::MODES }
114
93
  end
115
94
 
116
95
  previous = tick_state.mode
117
96
  tick_state.transition_to(mode)
118
- Legion::Logging.info "[tick] mode forced: #{previous} -> #{mode}"
97
+ log.info "[tick] mode forced: #{previous} -> #{mode}"
119
98
  { mode: mode }
120
99
  end
121
100
 
122
101
  private
123
102
 
103
+ def execute_tick_impl(signals:, phase_handlers:)
104
+ state = tick_state
105
+ state.increment_tick
106
+
107
+ max_salience = signals.map { |s| s.is_a?(Hash) ? (s[:salience] || 0.0) : 0.0 }.max || 0.0
108
+ state.record_signal(salience: max_salience) unless signals.empty?
109
+
110
+ log.debug "[tick] ##{state.tick_count} starting | mode=#{state.mode} signals=#{signals.size} max_salience=#{max_salience.round(2)}"
111
+
112
+ transition = evaluate_mode_transition(signals: signals)
113
+ log.info "[tick] mode transition: #{transition[:previous_mode]} -> #{transition[:new_mode]} (#{transition[:reason]})" if transition[:transitioned]
114
+
115
+ phases = Helpers::Constants.phases_for_mode(state.mode)
116
+ budget = Helpers::Constants.tick_budget(state.mode)
117
+ start_time = Time.now.utc
118
+ ctx = { budget: budget, start_time: start_time, phase_handlers: phase_handlers, signals: signals }
119
+ results = run_phases(phases, state, ctx)
120
+
121
+ total_elapsed = Time.now.utc - start_time
122
+ skipped = phases - results.keys
123
+ log_tick_complete(state, results, phases, total_elapsed, skipped)
124
+
125
+ {
126
+ tick_number: state.tick_count,
127
+ mode: state.mode,
128
+ phases_executed: results.keys,
129
+ phases_skipped: skipped,
130
+ results: results,
131
+ elapsed: total_elapsed
132
+ }
133
+ end
134
+
124
135
  def run_phases(phases, state, ctx)
125
136
  results = {}
126
137
  budget = ctx[:budget]
127
138
  start_time = ctx[:start_time]
128
- Legion::Logging.debug "[tick] ##{state.tick_count} running #{phases.size} phases with #{budget}s budget"
139
+ log.debug "[tick] ##{state.tick_count} running #{phases.size} phases with #{budget}s budget"
129
140
  phases.each do |phase|
130
141
  elapsed = Time.now.utc - start_time
131
142
  if elapsed >= budget
132
- Legion::Logging.debug "[tick] ##{state.tick_count} budget exhausted at #{elapsed.round(3)}s, skipping remaining phases"
143
+ log.debug "[tick] ##{state.tick_count} budget exhausted at #{elapsed.round(3)}s, skipping remaining phases"
133
144
  break
134
145
  end
135
146
 
@@ -145,15 +156,15 @@ module Legion
145
156
  result = handler ? handler.call(state: state, signals: signals, prior_results: results) : { status: :no_handler }
146
157
  phase_elapsed = ((Time.now.utc - phase_start) * 1000).round(1)
147
158
  status = result.is_a?(Hash) ? (result[:status] || :ok) : :ok
148
- Legion::Logging.debug "[tick] ##{state.tick_count} phase=#{phase} status=#{status} (#{phase_elapsed}ms)"
159
+ log.debug "[tick] ##{state.tick_count} phase=#{phase} status=#{status} (#{phase_elapsed}ms)"
149
160
  result
150
161
  end
151
162
 
152
163
  def log_tick_complete(state, results, phases, total_elapsed, skipped)
153
164
  skipped_suffix = skipped.empty? ? '' : " skipped=#{skipped}"
154
- Legion::Logging.info "[tick] ##{state.tick_count} complete | mode=#{state.mode} " \
155
- "phases=#{results.size}/#{phases.size} " \
156
- "elapsed=#{(total_elapsed * 1000).round(1)}ms#{skipped_suffix}"
165
+ log.info "[tick] ##{state.tick_count} complete | mode=#{state.mode} " \
166
+ "phases=#{results.size}/#{phases.size} " \
167
+ "elapsed=#{(total_elapsed * 1000).round(1)}ms#{skipped_suffix}"
157
168
  end
158
169
 
159
170
  def tick_state
@@ -3,7 +3,7 @@
3
3
  module Legion
4
4
  module Extensions
5
5
  module Tick
6
- VERSION = '0.1.0'
6
+ VERSION = '0.1.3'
7
7
  end
8
8
  end
9
9
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe 'Orchestrator OpenInference instrumentation' do
6
+ let(:host) { Object.new.extend(Legion::Extensions::Tick::Runners::Orchestrator) }
7
+
8
+ before do
9
+ stub_const('Legion::Telemetry::OpenInference', Module.new do
10
+ def self.open_inference_enabled?
11
+ true
12
+ end
13
+
14
+ def self.agent_span(**)
15
+ yield(nil)
16
+ end
17
+ end)
18
+ end
19
+
20
+ describe '#execute_tick' do
21
+ it 'wraps tick execution in agent_span' do
22
+ expect(Legion::Telemetry::OpenInference).to receive(:agent_span)
23
+ .with(hash_including(name: kind_of(String), mode: kind_of(Symbol)))
24
+ .and_yield(nil)
25
+
26
+ host.execute_tick(signals: [], phase_handlers: {})
27
+ end
28
+
29
+ it 'works without OpenInference loaded' do
30
+ hide_const('Legion::Telemetry::OpenInference')
31
+ result = host.execute_tick(signals: [], phase_handlers: {})
32
+ expect(result[:tick_number]).to eq(1)
33
+ end
34
+ end
35
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,13 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bundler/setup'
4
+ require 'legion/logging'
5
+ require 'legion/settings'
6
+ require 'legion/cache/helper'
7
+ require 'legion/crypt/helper'
8
+ require 'legion/data/helper'
9
+ require 'legion/json/helper'
10
+ require 'legion/transport/helper'
4
11
 
5
12
  module Legion
6
- module Logging
7
- def self.debug(_msg); end
8
- def self.info(_msg); end
9
- def self.warn(_msg); end
10
- def self.error(_msg); end
13
+ module Extensions
14
+ module Helpers
15
+ module Lex
16
+ include Legion::Logging::Helper
17
+ include Legion::Settings::Helper
18
+ include Legion::Cache::Helper
19
+ include Legion::Crypt::Helper
20
+ include Legion::Data::Helper
21
+ include Legion::JSON::Helper
22
+ include Legion::Transport::Helper
23
+ end
24
+ end
25
+
26
+ module Actors
27
+ class Every
28
+ include Helpers::Lex
29
+ end
30
+
31
+ class Once
32
+ include Helpers::Lex
33
+ end
34
+ end
11
35
  end
12
36
  end
13
37
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lex-tick
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -10,19 +10,103 @@ cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
- name: legion-gaia
13
+ name: legion-cache
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: '0'
19
- type: :development
18
+ version: 1.3.11
19
+ type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
- version: '0'
25
+ version: 1.3.11
26
+ - !ruby/object:Gem::Dependency
27
+ name: legion-crypt
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.4.9
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: 1.4.9
40
+ - !ruby/object:Gem::Dependency
41
+ name: legion-data
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 1.4.17
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 1.4.17
54
+ - !ruby/object:Gem::Dependency
55
+ name: legion-json
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 1.2.1
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: 1.2.1
68
+ - !ruby/object:Gem::Dependency
69
+ name: legion-logging
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 1.3.2
75
+ type: :runtime
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: 1.3.2
82
+ - !ruby/object:Gem::Dependency
83
+ name: legion-settings
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: 1.3.14
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: 1.3.14
96
+ - !ruby/object:Gem::Dependency
97
+ name: legion-transport
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 1.3.9
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: 1.3.9
26
110
  description: Atomic cognitive processing cycle (11 phases, 3 modes) for brain-modeled
27
111
  agentic AI
28
112
  email:
@@ -44,6 +128,7 @@ files:
44
128
  - spec/legion/extensions/tick/client_spec.rb
45
129
  - spec/legion/extensions/tick/helpers/constants_spec.rb
46
130
  - spec/legion/extensions/tick/helpers/state_spec.rb
131
+ - spec/legion/extensions/tick/runners/orchestrator_open_inference_spec.rb
47
132
  - spec/legion/extensions/tick/runners/orchestrator_spec.rb
48
133
  - spec/spec_helper.rb
49
134
  homepage: https://github.com/LegionIO/lex-tick