Module: Legion::Gaia::Gut
- Extended by:
- Logging::Helper
- Defined in:
- lib/legion/gaia/gut.rb
Overview
H5 — fast per-response conflict detection (v1: correction veto only).
Runs at the final-delivery hook (response_return). Deterministic pattern matching against high-strength correction traces and transform-tier behavioral synapses. No LLM calls. Must complete within the latency budget (default 50ms).
The gut itself is a behavioral synapse (domain: 'gut') whose autonomy_mode gates what happens: observe = audit-only, filter = restraint directives, transform+ = veto. New partners always start in observe mode (emergent confidence 0.3 → observe tier).
Class Method Summary collapse
-
.check(identity:, draft_stats:) ⇒ Hash?
Check for conflicts between draft response stats and known corrections/synapses.
-
.check_correction_traces(identity:, draft_stats:, deadline:) ⇒ Object
Compare draft_stats against high-strength correction traces for the partner.
-
.check_transform_synapses(identity:, draft_stats:, deadline:) ⇒ Object
Check transform-tier behavioral synapses for conflicts with draft stats.
- .correction_min_strength ⇒ Object
- .correction_trace?(trace) ⇒ Boolean
- .correction_trace_limit ⇒ Object
- .deadline_exceeded?(deadline) ⇒ Boolean
- .directive_from_trace(trace) ⇒ Object
-
.gut_mode_for(gut_synapse) ⇒ Object
Returns the autonomy mode for the gut synapse, or :unavailable if gut should not run.
- .latency_budget_ms ⇒ Object
- .monotonic_now ⇒ Object
- .synapse_budget_conflict?(directive, stats) ⇒ Boolean
-
.synapse_conflicts_with_draft?(synapse, draft_stats) ⇒ Boolean
Checks if a transform-tier synapse's directive conflicts with draft stats.
- .synapse_format_conflict?(directive, stats) ⇒ Boolean
-
.trace_conflicts_with_draft?(trace, draft_stats) ⇒ Boolean
Checks if a correction trace conflicts with the draft stats.
- .trace_content_flag_conflict?(payload, stats) ⇒ Boolean
- .trace_domain_conflict?(payload, stats) ⇒ Boolean
- .trace_format_conflict?(payload, stats) ⇒ Boolean
- .trace_verbosity_conflict?(payload, stats) ⇒ Boolean
Class Method Details
.check(identity:, draft_stats:) ⇒ Hash?
Check for conflicts between draft response stats and known corrections/synapses.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/legion/gaia/gut.rb', line 30 def check(identity:, draft_stats:) deadline = monotonic_now + (latency_budget_ms / 1000.0) gut_synapse = Legion::Gaia::BehavioralSynapse.for(identity: identity.to_s, domain: 'gut') gut_mode = gut_mode_for(gut_synapse) return nil if gut_mode == :unavailable violations = check_correction_traces(identity: identity.to_s, draft_stats: draft_stats, deadline: deadline) if violations.nil? log.debug("[gut] latency budget exceeded identity=#{identity}") return nil end synapse_violations = check_transform_synapses(identity: identity.to_s, draft_stats: draft_stats, deadline: deadline) if synapse_violations.nil? log.debug("[gut] latency budget exceeded (synapse phase) identity=#{identity}") return nil end all_violations = violations + synapse_violations return { conflict: false } if all_violations.empty? violated_trace_ids = all_violations.flat_map { |v| v[:trace_ids] }.uniq confidence = all_violations.map { |v| v[:strength] }.max.to_f directive = all_violations.first[:directive] || {} log.info("[gut] conflict detected identity=#{identity} " \ "violations=#{all_violations.size} confidence=#{confidence.round(3)} " \ "mode=#{gut_mode}") { conflict: true, confidence: confidence, violated_trace_ids: violated_trace_ids, directive: directive } rescue StandardError => e handle_exception(e, level: :warn, operation: 'gaia.gut.check', identity: identity) nil end |
.check_correction_traces(identity:, draft_stats:, deadline:) ⇒ Object
Compare draft_stats against high-strength correction traces for the partner. Returns array of violation hashes, or nil if deadline exceeded.
95 96 97 98 99 100 101 102 103 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 129 130 |
# File 'lib/legion/gaia/gut.rb', line 95 def check_correction_traces(identity:, draft_stats:, deadline:) return [] unless defined?(Legion::Extensions::Agentic::Memory::Trace::Runners::Traces) return nil if deadline_exceeded?(deadline) runner = Object.new runner.extend(Legion::Extensions::Agentic::Memory::Trace::Runners::Traces) result = runner.retrieve_by_domain( domain_tag: "partner:#{identity}", min_strength: correction_min_strength, limit: correction_trace_limit ) return nil if deadline_exceeded?(deadline) correction_traces = Array(result[:traces]).select { |t| correction_trace?(t) } violations = [] correction_traces.each do |trace| return nil if deadline_exceeded?(deadline) next unless trace_conflicts_with_draft?(trace, draft_stats) violations << { trace_ids: [trace[:trace_id].to_s], strength: trace[:strength].to_f, directive: directive_from_trace(trace) } end violations rescue StandardError => e handle_exception(e, level: :debug, operation: 'gaia.gut.check_correction_traces', identity: identity) [] end |
.check_transform_synapses(identity:, draft_stats:, deadline:) ⇒ Object
Check transform-tier behavioral synapses for conflicts with draft stats. Returns array of violation hashes, or nil if deadline exceeded.
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/legion/gaia/gut.rb', line 134 def check_transform_synapses(identity:, draft_stats:, deadline:) return nil if deadline_exceeded?(deadline) synapses = Legion::Gaia::BehavioralSynapse.all_for(identity: identity) transform_synapses = synapses.select do |s| mode = Legion::Gaia::BehavioralSynapse::Math.autonomy_mode(s[:confidence].to_f) %i[transform autonomous].include?(mode) end violations = [] transform_synapses.each do |synapse| return nil if deadline_exceeded?(deadline) next unless synapse_conflicts_with_draft?(synapse, draft_stats) violations << { trace_ids: Array(synapse[:evidence_trace_ids]), strength: synapse[:confidence].to_f, directive: synapse[:directive].is_a?(Hash) ? synapse[:directive] : {} } end violations rescue StandardError => e handle_exception(e, level: :debug, operation: 'gaia.gut.check_transform_synapses', identity: identity) [] end |
.correction_min_strength ⇒ Object
248 249 250 251 |
# File 'lib/legion/gaia/gut.rb', line 248 def correction_min_strength settings = Legion::Gaia.settings settings&.dig(:gut, :correction_min_strength) || 0.6 end |
.correction_trace?(trace) ⇒ Boolean
163 164 165 166 167 168 |
# File 'lib/legion/gaia/gut.rb', line 163 def correction_trace?(trace) return false unless trace.is_a?(Hash) trace[:trace_type].to_s == 'correction' || Array(trace[:domain_tags]).any? { |tag| tag.to_s == 'correction' } end |
.correction_trace_limit ⇒ Object
253 254 255 256 |
# File 'lib/legion/gaia/gut.rb', line 253 def correction_trace_limit settings = Legion::Gaia.settings settings&.dig(:gut, :correction_trace_limit) || 20 end |
.deadline_exceeded?(deadline) ⇒ Boolean
81 82 83 |
# File 'lib/legion/gaia/gut.rb', line 81 def deadline_exceeded?(deadline) monotonic_now >= deadline end |
.directive_from_trace(trace) ⇒ Object
237 238 239 240 241 242 243 244 245 246 |
# File 'lib/legion/gaia/gut.rb', line 237 def directive_from_trace(trace) payload = trace[:content_payload] return {} unless payload.is_a?(Hash) dir = {} dir[:budget_tokens] = payload[:budget_tokens] if payload[:budget_tokens] dir[:rejected_format] = payload[:rejected_format] if payload[:rejected_format] dir[:correction_type] = payload[:correction_type] if payload[:correction_type] dir end |
.gut_mode_for(gut_synapse) ⇒ Object
Returns the autonomy mode for the gut synapse, or :unavailable if gut should not run. New partners get :observe (observe = audit only, no veto action).
87 88 89 90 91 |
# File 'lib/legion/gaia/gut.rb', line 87 def gut_mode_for(gut_synapse) return :observe if gut_synapse.nil? Legion::Gaia::BehavioralSynapse::Math.autonomy_mode(gut_synapse[:confidence].to_f) end |
.latency_budget_ms ⇒ Object
72 73 74 75 |
# File 'lib/legion/gaia/gut.rb', line 72 def latency_budget_ms settings = Legion::Gaia.settings settings&.dig(:gut, :latency_budget_ms) || 50.0 end |
.monotonic_now ⇒ Object
77 78 79 |
# File 'lib/legion/gaia/gut.rb', line 77 def monotonic_now ::Process.clock_gettime(::Process::CLOCK_MONOTONIC) end |
.synapse_budget_conflict?(directive, stats) ⇒ Boolean
222 223 224 225 226 227 228 229 |
# File 'lib/legion/gaia/gut.rb', line 222 def synapse_budget_conflict?(directive, stats) return false unless directive[:budget_ratio] baseline = stats[:baseline_tokens].to_i draft_len = stats[:length_tokens].to_i allowed = (baseline * directive[:budget_ratio].to_f).to_i allowed.positive? && draft_len > allowed end |
.synapse_conflicts_with_draft?(synapse, draft_stats) ⇒ Boolean
Checks if a transform-tier synapse's directive conflicts with draft stats.
214 215 216 217 218 219 220 |
# File 'lib/legion/gaia/gut.rb', line 214 def synapse_conflicts_with_draft?(synapse, draft_stats) directive = synapse[:directive] return false unless directive.is_a?(Hash) stats = draft_stats.is_a?(Hash) ? draft_stats : {} synapse_budget_conflict?(directive, stats) || synapse_format_conflict?(directive, stats) end |
.synapse_format_conflict?(directive, stats) ⇒ Boolean
231 232 233 234 235 |
# File 'lib/legion/gaia/gut.rb', line 231 def synapse_format_conflict?(directive, stats) return false unless directive[:format] && stats[:format] stats[:format].to_s != directive[:format].to_s end |
.trace_conflicts_with_draft?(trace, draft_stats) ⇒ Boolean
Checks if a correction trace conflicts with the draft stats. Conflict = the draft exhibits a pattern that the correction explicitly negated.
172 173 174 175 176 177 178 179 180 181 |
# File 'lib/legion/gaia/gut.rb', line 172 def trace_conflicts_with_draft?(trace, draft_stats) payload = trace[:content_payload] return false unless payload.is_a?(Hash) stats = draft_stats.is_a?(Hash) ? draft_stats : {} trace_verbosity_conflict?(payload, stats) || trace_format_conflict?(payload, stats) || trace_content_flag_conflict?(payload, stats) || trace_domain_conflict?(payload, stats) end |
.trace_content_flag_conflict?(payload, stats) ⇒ Boolean
197 198 199 200 201 202 203 |
# File 'lib/legion/gaia/gut.rb', line 197 def trace_content_flag_conflict?(payload, stats) return false unless payload[:rejected_content_flags].is_a?(Array) draft_flags = Array(stats[:content_flags]).map(&:to_s) rejected = payload[:rejected_content_flags].map(&:to_s) draft_flags.intersect?(rejected) end |
.trace_domain_conflict?(payload, stats) ⇒ Boolean
205 206 207 208 209 210 211 |
# File 'lib/legion/gaia/gut.rb', line 205 def trace_domain_conflict?(payload, stats) return false unless payload[:correction_type].to_s == 'explicit_negative_feedback' applied_domains = Array(stats[:applied_domains]).map(&:to_s) blocked_domains = Array(payload[:blocked_domains]).map(&:to_s) blocked_domains.any? && applied_domains.intersect?(blocked_domains) end |
.trace_format_conflict?(payload, stats) ⇒ Boolean
191 192 193 194 195 |
# File 'lib/legion/gaia/gut.rb', line 191 def trace_format_conflict?(payload, stats) return false unless payload[:rejected_format] stats[:format].to_s == payload[:rejected_format].to_s end |
.trace_verbosity_conflict?(payload, stats) ⇒ Boolean
183 184 185 186 187 188 189 |
# File 'lib/legion/gaia/gut.rb', line 183 def trace_verbosity_conflict?(payload, stats) type = payload[:correction_type].to_s return false unless type.include?('verbosity') || type.include?('length') budget = payload[:budget_tokens] || payload[:max_tokens] budget && stats[:length_tokens].to_i > budget.to_i end |