| """Coherence Field Gamma (Γ) — System Health Stabilization
|
|
|
| Phase 5A Critical Infrastructure: Prevents three failure modes in closed-loop reasoning:
|
|
|
| 1. Weight Drift: Adapter weights concentrate; diversity collapses
|
| 2. False Convergence: System reduces conflict but converges on wrong answer
|
| 3. Feedback Lock-in: Early bad runs reinforce themselves via memory
|
|
|
| Solution: Γ (Gamma) monitors system coherence field and injects stabilizers when
|
| health drops below safe zones. Works alongside Phase 4 runaway detection.
|
|
|
| Health Score:
|
| γ ∈ [0, 1] where:
|
| - γ < 0.4: System instability → inject diverse perspective
|
| - 0.4 ≤ γ ≤ 0.8: Healthy zone (maintain status quo)
|
| - γ > 0.8: Groupthink risk → force conflict pair to create productive tension
|
|
|
| Components:
|
| 1. Conflict Distribution: Are conflicts well-distributed across perspectives?
|
| 2. Diversity Index: Are we using multiple perspectives or just 1-2 favorites?
|
| 3. Tension Health: Is ξ (epistemic tension) in productive zone [0.1, 0.4]?
|
| 4. Coherence Quality: Is coherence maintained while resolving conflicts?
|
| """
|
|
|
| import time
|
| import math
|
| from dataclasses import dataclass, field
|
| from typing import Dict, List, Optional, Tuple
|
| from enum import Enum
|
|
|
|
|
| class InterventionType(Enum):
|
| """Stabilization intervention types."""
|
| DIVERSITY_INJECTION = "diversity_injection"
|
| CONFLICT_INJECTION = "conflict_injection"
|
|
|
|
|
| @dataclass
|
| class GammaHealthMetrics:
|
| """Real-time system health snapshot."""
|
| timestamp: float
|
| avg_conflict_strength: float
|
| perspective_diversity: float
|
| resolution_rate: float
|
| adapter_weight_variance: float
|
| epistemic_tension: float
|
| coherence_score: float
|
| gamma: float
|
|
|
| def is_stable(self) -> bool:
|
| """Return True if system is in healthy zone."""
|
| return 0.4 <= self.gamma <= 0.8
|
|
|
| def is_collapsing(self) -> bool:
|
| """Return True if system shows instability signs."""
|
| return self.gamma < 0.4
|
|
|
| def is_groupthinking(self) -> bool:
|
| """Return True if system shows groupthink signs."""
|
| return self.gamma > 0.8
|
|
|
| @property
|
| def status(self) -> str:
|
| """Return human-readable status string."""
|
| if self.is_collapsing():
|
| return "collapsing"
|
| elif self.is_groupthinking():
|
| return "groupthinking"
|
| else:
|
| return "stable"
|
|
|
|
|
| @dataclass
|
| class GammaIntervention:
|
| """Record of stabilization intervention taken."""
|
| timestamp: float
|
| intervention_type: InterventionType
|
| reason: str
|
| gamma_before: float
|
| recommended_adapter: Optional[str] = None
|
| result: Optional[str] = None
|
|
|
|
|
| class CoherenceFieldGamma:
|
| """Real-time system health monitor and stabilizer.
|
|
|
| Tracks epistemic health and intervenes when system drifts toward:
|
| - Monoculture (weight drift, diversity collapse)
|
| - False convergence (low conflict, wrong answer)
|
| - Instability (oscillating weights, conflicting signals)
|
| """
|
|
|
|
|
| MAX_HEALTH_HISTORY = 1000
|
| MAX_INTERVENTION_LOG = 500
|
|
|
| def __init__(self, memory_weighting=None, target_conflict_range: Tuple[float, float] = (0.1, 0.4)):
|
| """
|
| Args:
|
| memory_weighting: MemoryWeighting instance (for analyzing adapter weights)
|
| target_conflict_range: Ideal epistemic tension zone [low, high]
|
| """
|
| self.memory_weighting = memory_weighting
|
| self.target_conflict_low, self.target_conflict_high = target_conflict_range
|
|
|
|
|
| from collections import deque
|
| self.health_history: deque = deque(maxlen=self.MAX_HEALTH_HISTORY)
|
| self.interventions: deque = deque(maxlen=self.MAX_INTERVENTION_LOG)
|
| self.last_health_check = time.time()
|
|
|
| def compute_health(self, conflicts: List, responses: Dict, adapter_weights: Optional[Dict] = None) -> GammaHealthMetrics:
|
| """Compute Γ (Gamma) health score from current debate state.
|
|
|
| Args:
|
| conflicts: List of active conflicts from current round
|
| responses: Dict of {adapter_name: response_text} from debate
|
| adapter_weights: Dict of {adapter_name: weight_float} from MemoryWeighting
|
|
|
| Returns:
|
| GammaHealthMetrics with computed gamma and health indicators
|
| """
|
|
|
| avg_conflict_strength = 0.0
|
| conflict_by_adapter = {}
|
| if conflicts:
|
| for conflict in conflicts:
|
| avg_conflict_strength += conflict.strength if hasattr(conflict, 'strength') else 0.5
|
|
|
| if hasattr(conflict, 'agent_a'):
|
| agent = conflict.agent_a.lower()
|
| conflict_by_adapter[agent] = conflict_by_adapter.get(agent, 0) + 1
|
| if hasattr(conflict, 'agent_b'):
|
| agent = conflict.agent_b.lower()
|
| conflict_by_adapter[agent] = conflict_by_adapter.get(agent, 0) + 1
|
|
|
| avg_conflict_strength /= len(conflicts)
|
| else:
|
| avg_conflict_strength = 0.5
|
|
|
|
|
| unique_perspectives = len(set(responses.keys())) if responses else 0
|
| max_perspectives = len(responses) if responses else 1
|
| perspective_diversity = unique_perspectives / max(max_perspectives, 1)
|
|
|
|
|
| resolution_rate = 0.5
|
| if conflicts:
|
| resolved = sum(1 for c in conflicts if hasattr(c, 'resolution_rate') and c.resolution_rate > 0.4)
|
| resolution_rate = resolved / len(conflicts)
|
|
|
|
|
| adapter_weight_variance = 0.0
|
| if adapter_weights:
|
| weights = list(adapter_weights.values())
|
| if len(weights) > 1:
|
| mean_weight = sum(weights) / len(weights)
|
| variance = sum((w - mean_weight) ** 2 for w in weights) / len(weights)
|
|
|
| max_variance = 4.0
|
| adapter_weight_variance = min(1.0, variance / max_variance)
|
| else:
|
| adapter_weight_variance = 0.5
|
|
|
|
|
|
|
| epistemic_tension = avg_conflict_strength
|
| tension_health = 1.0 - abs(epistemic_tension - 0.25) / 0.15
|
| tension_health = max(0.0, min(1.0, tension_health))
|
|
|
|
|
|
|
| coherence_score = 0.7
|
|
|
|
|
|
|
|
|
| gamma = (
|
| 0.25 * perspective_diversity +
|
| 0.25 * tension_health +
|
| 0.25 * (1.0 - adapter_weight_variance) +
|
| 0.25 * resolution_rate
|
| )
|
|
|
| metrics = GammaHealthMetrics(
|
| timestamp=time.time(),
|
| avg_conflict_strength=avg_conflict_strength,
|
| perspective_diversity=perspective_diversity,
|
| resolution_rate=resolution_rate,
|
| adapter_weight_variance=adapter_weight_variance,
|
| epistemic_tension=epistemic_tension,
|
| coherence_score=coherence_score,
|
| gamma=gamma,
|
| )
|
|
|
| self.health_history.append(metrics)
|
| return metrics
|
|
|
| def get_intervention(self, metrics: GammaHealthMetrics,
|
| available_adapters: List[str]) -> Optional[GammaIntervention]:
|
| """Determine if system needs stabilization intervention.
|
|
|
| Args:
|
| metrics: Current GammaHealthMetrics
|
| available_adapters: List of adapter names available
|
|
|
| Returns:
|
| GammaIntervention if action needed, else None
|
| """
|
| if metrics.is_stable():
|
| return None
|
|
|
| intervention = None
|
|
|
| if metrics.is_collapsing():
|
|
|
|
|
|
|
|
|
| unused_adapters = [a for a in available_adapters
|
| if self.memory_weighting is None or
|
| a not in self.memory_weighting.adapter_weights or
|
| self.memory_weighting.adapter_weights[a].interaction_count == 0]
|
|
|
| if not unused_adapters:
|
|
|
| if self.memory_weighting and self.memory_weighting.adapter_weights:
|
| unused_adapters = [min(self.memory_weighting.adapter_weights.items(),
|
| key=lambda x: x[1].weight)[0]]
|
| else:
|
| unused_adapters = [available_adapters[0]]
|
|
|
| intervention = GammaIntervention(
|
| timestamp=time.time(),
|
| intervention_type=InterventionType.DIVERSITY_INJECTION,
|
| reason=f"System instability detected (γ={metrics.gamma:.2f} < 0.4). "
|
| f"Diversity={metrics.perspective_diversity:.1%}, "
|
| f"Weight variance={metrics.adapter_weight_variance:.1%}. "
|
| f"Injecting diverse perspective to break monoculture.",
|
| gamma_before=metrics.gamma,
|
| recommended_adapter=unused_adapters[0],
|
| )
|
|
|
| elif metrics.is_groupthinking():
|
|
|
|
|
|
|
|
|
|
|
| if available_adapters and len(available_adapters) >= 2:
|
|
|
| sorted_adapters = sorted(available_adapters)
|
| pair = (sorted_adapters[0], sorted_adapters[-1])
|
| intervention = GammaIntervention(
|
| timestamp=time.time(),
|
| intervention_type=InterventionType.CONFLICT_INJECTION,
|
| reason=f"Groupthink risk detected (γ={metrics.gamma:.2f} > 0.8). "
|
| f"Low conflict={metrics.epistemic_tension:.2f}, "
|
| f"High diversity={metrics.perspective_diversity:.1%}. "
|
| f"Forcing debate pair to create productive tension.",
|
| gamma_before=metrics.gamma,
|
| recommended_adapter=f"{pair[0]};{pair[1]}",
|
| )
|
|
|
| if intervention:
|
| self.interventions.append(intervention)
|
|
|
| return intervention
|
|
|
| def get_summary(self) -> Dict:
|
| """Return summary of system health trends (API-consistent name)."""
|
| if not self.health_history:
|
| return {}
|
|
|
|
|
| history_list = list(self.health_history)
|
| interventions_list = list(self.interventions)
|
|
|
| recent = history_list[-10:]
|
| gammas = [m.gamma for m in recent]
|
| tensions = [m.epistemic_tension for m in recent]
|
| diversities = [m.perspective_diversity for m in recent]
|
|
|
| return {
|
| "current_gamma": recent[-1].gamma if recent else 0.0,
|
| "avg_gamma": sum(gammas) / len(gammas),
|
| "gamma_trend": "stable" if len(gammas) < 2 else (
|
| "improving" if gammas[-1] > gammas[0] else "degrading"
|
| ),
|
| "avg_tension": sum(tensions) / len(tensions),
|
| "avg_diversity": sum(diversities) / len(diversities),
|
| "interventions_total": len(interventions_list),
|
| "interventions_recent": sum(1 for i in interventions_list
|
| if time.time() - i.timestamp < 3600),
|
| "status": (
|
| "collapsing" if recent[-1].is_collapsing() else
|
| "groupthinking" if recent[-1].is_groupthinking() else
|
| "stable"
|
| ),
|
| }
|
|
|
| def export_metrics(self) -> Dict:
|
| """Export all health metrics for monitoring/logging."""
|
|
|
| health_list = list(self.health_history)
|
| interventions_list = list(self.interventions)
|
|
|
| return {
|
| "health_history": [
|
| {
|
| "timestamp": m.timestamp,
|
| "gamma": m.gamma,
|
| "conflict": m.avg_conflict_strength,
|
| "diversity": m.perspective_diversity,
|
| "resolution": m.resolution_rate,
|
| "weight_variance": m.adapter_weight_variance,
|
| }
|
| for m in health_list[-50:]
|
| ],
|
| "interventions": [
|
| {
|
| "timestamp": i.timestamp,
|
| "type": i.intervention_type.value,
|
| "reason": i.reason,
|
| "gamma_before": i.gamma_before,
|
| "recommended": i.recommended_adapter,
|
| "result": i.result,
|
| }
|
| for i in interventions_list[-20:]
|
| ],
|
| "summary": self.get_summary(),
|
| }
|
|
|