Module: Legion::Gaia::VisibleGrowth

Defined in:
lib/legion/gaia/visible_growth.rb

Constant Summary collapse

TIER_LABELS =
{
  observe: 'noticing patterns',
  filter: 'adjusting my approach',
  transform: 'actively shaping my responses',
  autonomous: 'acting on this without asking'
}.freeze
DOMAIN_PHRASES =
{
  'brevity' => 'shorter answers',
  'verbosity' => 'longer, more detailed answers',
  'tone' => 'the tone',
  'format' => 'the format',
  'code' => 'code style',
  'detail' => 'the level of detail'
}.freeze

Class Method Summary collapse

Class Method Details

.build_onboarding_text(identity:) ⇒ Object



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/legion/gaia/visible_growth.rb', line 174

def build_onboarding_text(identity:)
  lines = [
    "I'll be learning as we work together — what you prefer, how you like information, " \
    'what lands and what misses.',
    'Everything stays on this machine — nothing is sent anywhere else.',
    'You can end this at any time — your data goes with it, completely.'
  ]

  bond = Legion::Gaia::BondRegistry.bond(identity.to_s)
  lines << "You're the partner on this node, so I'll pay closer attention." if bond == :partner

  lines.join(' ')
rescue StandardError => e
  VisibleGrowth.log_quietly(e, 'visible_growth.build_onboarding_text')
  "I'm learning as we go. Everything stays local. You can end this any time."
end

.domain_phrase(domain) ⇒ Object

--- private helpers ---



133
134
135
# File 'lib/legion/gaia/visible_growth.rb', line 133

def domain_phrase(domain)
  DOMAIN_PHRASES.fetch(domain.to_s, domain.to_s.tr('_', ' '))
end

.epistemic_qualifier(identity:, domain: nil) ⇒ String?

Epistemic honesty surface — returns a hedge/qualifier to append to a response, or nil. Returns nil when confident (should be most of the time post-imprint).

Parameters:

  • identity (String)
  • domain (String, nil) (defaults to: nil)

    current exchange domain, if known

Returns:

  • (String, nil)


109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/legion/gaia/visible_growth.rb', line 109

def epistemic_qualifier(identity:, domain: nil)
  imprint_active = imprint_active_for?
  synapse = domain ? Legion::Gaia::BehavioralSynapse.for(identity: identity.to_s, domain: domain.to_s) : nil

  return imprint_qualifier if imprint_active
  return observe_qualifier(domain) if synapse_observe_tier?(synapse)

  nil
rescue StandardError => e
  VisibleGrowth.log_quietly(e, 'visible_growth.epistemic_qualifier')
  nil
end

.graduation_acknowledgment(identity:) ⇒ String?

Called at imprint graduation (imprint window closes). Fires once per identity.

Parameters:

  • identity (String)

Returns:

  • (String, nil)


72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/legion/gaia/visible_growth.rb', line 72

def graduation_acknowledgment(identity:)
  @mutex.synchronize do
    return nil if @graduated_identities.include?(identity.to_s)

    @graduated_identities.add(identity.to_s)
  end

  "I feel like I know how you work now — I'll ask less and do more. Correct me if I drift."
rescue StandardError => e
  VisibleGrowth.log_quietly(e, 'visible_growth.graduation_acknowledgment')
  nil
end

.imprint_active_for?Object



137
138
139
140
141
142
143
144
145
146
# File 'lib/legion/gaia/visible_growth.rb', line 137

def imprint_active_for?
  return false unless defined?(Legion::Extensions::Coldstart)
  return false unless Legion::Extensions::Coldstart.respond_to?(:connected?) &&
                      Legion::Extensions::Coldstart.connected?

  bootstrap = Legion::Extensions::Coldstart::Helpers::Bootstrap.instance
  bootstrap.respond_to?(:imprint_active?) && bootstrap.imprint_active?
rescue StandardError
  false
end

.imprint_observation_countObject



148
149
150
151
152
153
154
155
# File 'lib/legion/gaia/visible_growth.rb', line 148

def imprint_observation_count
  return nil unless defined?(Legion::Extensions::Coldstart)

  bootstrap = Legion::Extensions::Coldstart::Helpers::Bootstrap.instance
  bootstrap.respond_to?(:observation_count) ? bootstrap.observation_count : nil
rescue StandardError
  nil
end

.imprint_qualifierObject



157
158
159
160
161
162
# File 'lib/legion/gaia/visible_growth.rb', line 157

def imprint_qualifier
  count = imprint_observation_count
  return "I'm still figuring out how you like things — was this right?" if count.nil? || count < 5

  "I'm still learning your style — let me know if this missed."
end

.log_quietly(exception, operation) ⇒ Object



191
192
193
194
195
# File 'lib/legion/gaia/visible_growth.rb', line 191

def log_quietly(exception, operation)
  return unless defined?(Legion::Logging)

  Legion::Logging.debug("[gaia] #{operation} rescued: #{exception.class}: #{exception.message}")
end

.milestone_acknowledgment(identity:, domain:, new_mode:, old_mode:) ⇒ String?

Called when a synapse confidence crosses into a new autonomy tier. Fires ONCE per (identity, domain, tier transition).

Parameters:

  • identity (String)
  • domain (String)
  • new_mode (Symbol)

    :observe | :filter | :transform | :autonomous

  • old_mode (Symbol)

Returns:

  • (String, nil)

    acknowledgment message, or nil if already fired



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/legion/gaia/visible_growth.rb', line 38

def milestone_acknowledgment(identity:, domain:, new_mode:, old_mode:)
  key = "#{identity}:#{domain}:#{old_mode}->#{new_mode}"
  @mutex.synchronize do
    return nil if @acknowledged_milestones.include?(key)

    @acknowledged_milestones.add(key)
  end

  phrase = domain_phrase(domain)
  tier_desc = TIER_LABELS.fetch(new_mode.to_sym, new_mode.to_s)

  "I've noticed you prefer #{phrase} — I'm now #{tier_desc}. Tell me if I've got that wrong."
rescue StandardError => e
  VisibleGrowth.log_quietly(e, 'visible_growth.milestone_acknowledgment')
  nil
end

.observe_qualifier(domain) ⇒ Object



170
171
172
# File 'lib/legion/gaia/visible_growth.rb', line 170

def observe_qualifier(domain)
  "I have a hunch about #{domain_phrase(domain)} — tell me if I'm off."
end

.onboarding_frame(identity:) ⇒ String?

Onboarding honesty — first frame at imprint open. Plain language about what's happening. Fires once per identity.

Parameters:

  • identity (String)

Returns:

  • (String, nil)

    content string for OutputFrame, or nil if already sent



90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/legion/gaia/visible_growth.rb', line 90

def onboarding_frame(identity:)
  @mutex.synchronize do
    return nil if @onboarded_identities.include?(identity.to_s)

    @onboarded_identities.add(identity.to_s)
  end

  build_onboarding_text(identity: identity)
rescue StandardError => e
  VisibleGrowth.log_quietly(e, 'visible_growth.onboarding_frame')
  nil
end

.pain_revert_acknowledgment(domain:, identity: nil) ⇒ String

Called when pain fires (3 consecutive failures → dampened status).

Parameters:

  • identity (String) (defaults to: nil)

    (unused, reserved for future per-identity routing)

  • domain (String)

Returns:

  • (String)


60
61
62
63
64
65
66
# File 'lib/legion/gaia/visible_growth.rb', line 60

def pain_revert_acknowledgment(domain:, identity: nil) # rubocop:disable Lint/UnusedMethodArgument
  phrase = domain_phrase(domain)
  "I've been getting #{phrase} wrong — I've reset that. What works for you?"
rescue StandardError => e
  VisibleGrowth.log_quietly(e, 'visible_growth.pain_revert_acknowledgment')
  "I reset something that wasn't working — what would you prefer?"
end

.reset!Object

Reset in-memory state (for tests)



123
124
125
126
127
128
129
# File 'lib/legion/gaia/visible_growth.rb', line 123

def reset!
  @mutex.synchronize do
    @acknowledged_milestones = Set.new
    @graduated_identities    = Set.new
    @onboarded_identities    = Set.new
  end
end

.synapse_observe_tier?(synapse) ⇒ Object



164
165
166
167
168
# File 'lib/legion/gaia/visible_growth.rb', line 164

def synapse_observe_tier?(synapse)
  return false unless synapse.is_a?(Hash)

  Legion::Gaia::BehavioralSynapse::Math.autonomy_mode(synapse[:confidence].to_f) == :observe
end