Module: Legion::Gaia::BondRegistry

Extended by:
Logging::Helper
Defined in:
lib/legion/gaia/bond_registry.rb

Class Method Summary collapse

Class Method Details

.all_bondsObject



52
53
54
# File 'lib/legion/gaia/bond_registry.rb', line 52

def all_bonds
  @bonds.values
end

.bond(identity) ⇒ Object



28
29
30
31
# File 'lib/legion/gaia/bond_registry.rb', line 28

def bond(identity)
  entry = @bonds[identity.to_s]
  entry ? entry[:bond] : :unknown
end

.channel_identity(identity) ⇒ Object

Returns the channel-native identity for the given principal identity. Falls back to the principal identity itself when no channel_identity was stored. Proactive delivery paths MUST use this method to avoid sending messages to a UUID that channel APIs (Teams, Slack) do not recognize.



41
42
43
44
45
46
# File 'lib/legion/gaia/bond_registry.rb', line 41

def channel_identity(identity)
  entry = @bonds[identity.to_s]
  return nil unless entry

  entry[:channel_identity] || entry[:identity]
end

.hydrate_from_apollo(store: nil) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/legion/gaia/bond_registry.rb', line 72

def hydrate_from_apollo(store: nil)
  return unless store

  result = store.query(text: 'partner', tags: %w[self-knowledge])
  return unless result.is_a?(Hash) && result[:success] && result[:results]&.any?

  result[:results].each do |entry|
    content = entry[:content].to_s
    next unless content.match?(/partner/i)

    identities = extract_identity_keys(content)
    priority = content.match?(/primary/i) ? :primary : :normal

    identities.each { |id| register(id, bond: :partner, priority: priority) }
  end
  log.info("BondRegistry hydrated entries=#{result[:results].size}")
rescue StandardError => e
  handle_exception(e, level: :warn, operation: 'gaia.bond_registry.hydrate_from_apollo')
end

.partner?(identity) ⇒ Boolean

Returns:

  • (Boolean)


48
49
50
# File 'lib/legion/gaia/bond_registry.rb', line 48

def partner?(identity)
  bond(identity) == :partner
end

.partner_entryObject

Returns the single best partner bond entry using deterministic selection:

1. Prefer entries that have an explicit channel_identity stored (ยง9.6 guarantee)
2. Then prefer entries with priority: :primary
3. Otherwise return the earliest-registered entry (sort by :since, then :identity)

Sorting by :since then :identity ensures a stable result regardless of Concurrent::Hash enumeration order, which is not guaranteed.



62
63
64
65
66
67
68
69
70
# File 'lib/legion/gaia/bond_registry.rb', line 62

def partner_entry
  partners = @bonds.values.select { |b| b[:bond] == :partner }
  return nil if partners.empty?

  sorted = partners.sort_by { |b| [b[:since], b[:identity]] }
  sorted.find { |b| b[:channel_identity] } ||
    sorted.find { |b| b[:priority] == :primary } ||
    sorted.first
end

.register(identity, bond: nil, role: nil, priority: :normal, channel_identity: nil) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/legion/gaia/bond_registry.rb', line 15

def register(identity, bond: nil, role: nil, priority: :normal, channel_identity: nil)
  effective_bond = (bond || role || :unknown).to_sym
  @bonds[identity.to_s] = {
    identity: identity.to_s,
    bond: effective_bond,
    role: effective_bond,
    priority: priority.to_sym,
    since: Time.now.utc,
    channel_identity: channel_identity&.to_s
  }
  log.info("BondRegistry registered identity=#{identity} bond=#{effective_bond} priority=#{priority}")
end

.reset!Object



92
93
94
95
# File 'lib/legion/gaia/bond_registry.rb', line 92

def reset!
  @bonds = Concurrent::Hash.new
  log.debug('BondRegistry reset')
end

.role(identity) ⇒ Object



33
34
35
# File 'lib/legion/gaia/bond_registry.rb', line 33

def role(identity)
  bond(identity)
end