legion-gaia 0.9.37 → 0.9.38

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: c68a10a1dc9fad8a793063f31a21c467b32da2a8fb3108ff8bb736daaac5d4d9
4
- data.tar.gz: dcbac65ba8b720b1a3a038a4d105254a836798984b1d06ec94b43b33e51ac776
3
+ metadata.gz: cc703551ee34547621861ff669735ce602151be08dcddcfdf0d704aebcd1bb7f
4
+ data.tar.gz: 969f9fcf9510ec29b3eee6d0dc1d691d0836528367dbb352074ec0a9b1b9b423
5
5
  SHA512:
6
- metadata.gz: 3f6c0639f083097c274c04406e5523eb4afd82fb1bb24c55b4251bbf7958e7fc9f94bf1ddb611272cfd6c2588f320b6d45bc49c150c7824a778f05cdda355350
7
- data.tar.gz: b5e8f25d46ccb1fb79af316cb5f29de97880249170f056cdef9a89fa2b4cd367dbdfdb16e89963084e5371fadcd6882a22a18da1c00e2759a1320f9deef1bf46
6
+ metadata.gz: c134c1b4d190ec7dd315e2c6a734254a3002f60b104f1d6f291cfecab3125bc9cc38d62b5937e10e1e06b0e0313df3a3031b47a640eee363cc30e9a5db06947d
7
+ data.tar.gz: f46a86969d2d6c16a5b204b08929cb3ddf86b53ca27a42414c1c657487163a0cc0cbdbb7d6f90368402a8b0be09eb9595ee54d3e1b3192bcc81e065897633fd4
data/.rubocop.yml CHANGED
@@ -15,16 +15,16 @@ Layout/LineLength:
15
15
  Max: 120
16
16
 
17
17
  Metrics/MethodLength:
18
- Max: 25
18
+ Max: 50
19
19
 
20
20
  Metrics/AbcSize:
21
- Max: 30
21
+ Max: 42
22
22
 
23
23
  Metrics/CyclomaticComplexity:
24
- Max: 10
24
+ Max: 15
25
25
 
26
26
  Metrics/PerceivedComplexity:
27
- Max: 10
27
+ Max: 15
28
28
 
29
29
  Metrics/ClassLength:
30
30
  Max: 200
data/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.9.38] - 2026-04-01
6
+
7
+ ### Fixed
8
+ - Add `require 'time'` in `TickHistory` to ensure `Time#iso8601` is always available
9
+ - Deep-dup entries in `TickHistory#recent` with `.map(&:dup)` to prevent callers from mutating ring buffer internals
10
+ - Add `gaia_available?` guard to `/api/gaia/ticks` route (returns 503 when GAIA not started)
11
+ - Use `TickHistory::MAX_ENTRIES` instead of hardcoded `200` for ticks route limit cap
12
+ - Track `@started_at` in `boot_router` for accurate uptime in router mode
13
+
5
14
  ## [0.9.37] - 2026-04-01
6
15
 
7
16
  ### Added
@@ -26,7 +26,7 @@ module Legion
26
26
  @bonds.values
27
27
  end
28
28
 
29
- def hydrate_from_apollo(store: nil) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
29
+ def hydrate_from_apollo(store: nil)
30
30
  return unless store
31
31
 
32
32
  result = store.query(text: 'partner', tags: %w[self-knowledge])
@@ -10,7 +10,7 @@
10
10
  module Legion
11
11
  module Gaia
12
12
  module Routes
13
- def self.registered(app) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
13
+ def self.registered(app)
14
14
  app.helpers do # rubocop:disable Metrics/BlockLength
15
15
  unless method_defined?(:gaia_available?)
16
16
  define_method(:gaia_available?) do
@@ -23,7 +23,8 @@ module Legion
23
23
  return nil unless defined?(Legion::Gaia::SensoryBuffer)
24
24
 
25
25
  Legion::Gaia::SensoryBuffer::MAX_BUFFER_SIZE
26
- rescue NameError
26
+ rescue NameError => e
27
+ Legion::Logging.debug "[gaia] route helpers failed #{e.class}: #{e.message}" if defined?(Legion::Logging)
27
28
  nil
28
29
  end
29
30
  end
@@ -74,7 +75,16 @@ module Legion
74
75
 
75
76
  def self.register_ticks_route(app)
76
77
  app.get '/api/gaia/ticks' do
77
- limit = (params[:limit] || 50).to_i.clamp(1, 200)
78
+ halt 503, json_error('gaia_unavailable', 'gaia is not started', status_code: 503) unless gaia_available?
79
+
80
+ max_limit =
81
+ if defined?(Legion::Gaia::TickHistory) && Legion::Gaia::TickHistory.const_defined?(:MAX_ENTRIES)
82
+ Legion::Gaia::TickHistory::MAX_ENTRIES
83
+ else
84
+ 200
85
+ end
86
+
87
+ limit = (params[:limit] || 50).to_i.clamp(1, max_limit)
78
88
  events = Legion::Gaia.tick_history&.recent(limit: limit) || []
79
89
  json_response({ events: events })
80
90
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'time'
4
+
3
5
  module Legion
4
6
  module Gaia
5
7
  class TickHistory
@@ -18,11 +20,11 @@ module Legion
18
20
  next unless phase_data.is_a?(Hash)
19
21
 
20
22
  {
21
- timestamp: timestamp,
22
- phase: phase_name.to_s,
23
+ timestamp: timestamp.freeze,
24
+ phase: phase_name.to_s.freeze,
23
25
  duration_ms: phase_data[:elapsed_ms],
24
26
  status: phase_data[:status]
25
- }
27
+ }.freeze
26
28
  end
27
29
 
28
30
  @mutex.synchronize do
@@ -33,7 +35,7 @@ module Legion
33
35
 
34
36
  def recent(limit: 50)
35
37
  @mutex.synchronize do
36
- @entries.last(limit).dup
38
+ @entries.last(limit).map(&:dup)
37
39
  end
38
40
  end
39
41
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Legion
4
4
  module Gaia
5
- VERSION = '0.9.37'
5
+ VERSION = '0.9.38'
6
6
  end
7
7
  end
data/lib/legion/gaia.rb CHANGED
@@ -117,7 +117,7 @@ module Legion
117
117
  end
118
118
  end
119
119
 
120
- def heartbeat(**) # rubocop:disable Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity,Metrics/AbcSize
120
+ def heartbeat(**)
121
121
  return { error: :not_started } unless started?
122
122
 
123
123
  signals = @sensory_buffer.drain
@@ -246,6 +246,7 @@ module Legion
246
246
  end
247
247
 
248
248
  def boot_router
249
+ @started_at = Time.now.utc
249
250
  boot_channels
250
251
  allowed = settings&.dig(:router, :allowed_worker_ids) || []
251
252
  @router_bridge = Router::RouterBridge.new(
@@ -293,7 +294,7 @@ module Legion
293
294
  end
294
295
  end
295
296
 
296
- def base_status # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
297
+ def base_status
297
298
  ttl = settings&.dig(:session, :ttl)
298
299
  status = {
299
300
  started: true,
@@ -323,7 +324,8 @@ module Legion
323
324
 
324
325
  last = tick_host.last_tick_result
325
326
  last.is_a?(Hash) ? (last[:mode] || :active) : :dormant
326
- rescue StandardError
327
+ rescue StandardError => e
328
+ log_debug("[gaia](tick_mode_from_host) #{e.class}: #{e.message}")
327
329
  :dormant
328
330
  end
329
331
 
@@ -405,7 +407,8 @@ module Legion
405
407
  return nil unless defined?(Legion::Apollo::Local) && Legion::Apollo::Local.started?
406
408
 
407
409
  Legion::Apollo::Local
408
- rescue StandardError
410
+ rescue StandardError => e
411
+ log_debug "[gaia](apollo_local_store) error #{e.class}: #{e.message}"
409
412
  nil
410
413
  end
411
414
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: legion-gaia
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.37
4
+ version: 0.9.38
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity