Module: Legion::Gaia::BondRegistry
- Extended by:
- Logging::Helper
- Defined in:
- lib/legion/gaia/bond_registry.rb
Class Method Summary collapse
- .all_bonds ⇒ Object
- .bond(identity) ⇒ Object
-
.channel_identity(identity) ⇒ Object
Returns the channel-native identity for the given principal identity.
- .hydrate_from_apollo(store: nil) ⇒ Object
- .partner?(identity) ⇒ Boolean
-
.partner_entry ⇒ Object
Returns the single best partner bond entry using deterministic selection: 1.
- .record_channel(identity, channel_id:, channel_identity: nil) ⇒ Object
- .register(identity, bond: nil, role: nil, priority: :normal, channel_identity: nil, preferred_channel: nil, last_channel: nil) ⇒ Object
- .reset! ⇒ Object
- .role(identity) ⇒ Object
Class Method Details
.all_bonds ⇒ Object
69 70 71 |
# File 'lib/legion/gaia/bond_registry.rb', line 69 def all_bonds @bonds.values end |
.bond(identity) ⇒ Object
45 46 47 48 |
# File 'lib/legion/gaia/bond_registry.rb', line 45 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.
58 59 60 61 62 63 |
# File 'lib/legion/gaia/bond_registry.rb', line 58 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
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/legion/gaia/bond_registry.rb', line 104 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 channel_identity = extract_channel_identity(content) preferred_channel = extract_channel(content, 'preferred') last_channel = extract_channel(content, 'last') identities.each do |id| register(id, bond: :partner, priority: priority, channel_identity: channel_identity, preferred_channel: preferred_channel, last_channel: last_channel) end 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
65 66 67 |
# File 'lib/legion/gaia/bond_registry.rb', line 65 def partner?(identity) bond(identity) == :partner end |
.partner_entry ⇒ Object
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.
94 95 96 97 98 99 100 101 102 |
# File 'lib/legion/gaia/bond_registry.rb', line 94 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 |
.record_channel(identity, channel_id:, channel_identity: nil) ⇒ Object
73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/legion/gaia/bond_registry.rb', line 73 def record_channel(identity, channel_id:, channel_identity: nil) @mutex.synchronize do entry = @bonds[identity.to_s] return nil unless entry channel = channel_id&.to_sym updated = entry.merge( last_channel: channel || entry[:last_channel], preferred_channel: entry[:preferred_channel] || channel, channel_identity: entry[:channel_identity] || channel_identity&.to_s ) @bonds[identity.to_s] = updated end end |
.register(identity, bond: nil, role: nil, priority: :normal, channel_identity: nil, preferred_channel: nil, last_channel: nil) ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/legion/gaia/bond_registry.rb', line 16 def register(identity, bond: nil, role: nil, priority: :normal, channel_identity: nil, preferred_channel: nil, last_channel: nil) effective_bond = (bond || role || :unknown).to_sym @mutex.synchronize do @bonds[identity.to_s] = build_entry( identity, bond: effective_bond, priority: priority, channel_identity: channel_identity, preferred_channel: preferred_channel, last_channel: last_channel ) end log.info("BondRegistry registered identity=#{identity} bond=#{effective_bond} priority=#{priority}") end |
.reset! ⇒ Object
130 131 132 133 |
# File 'lib/legion/gaia/bond_registry.rb', line 130 def reset! @mutex.synchronize { @bonds = Concurrent::Hash.new } log.debug('BondRegistry reset') end |
.role(identity) ⇒ Object
50 51 52 |
# File 'lib/legion/gaia/bond_registry.rb', line 50 def role(identity) bond(identity) end |