"""Phase 7: Executive Control Architecture — Intelligent component routing This module implements the decision-making layer that routes queries to the optimal combination of Phase 1-6 components, preventing wasteful activation and improving latency while maintaining reasoning quality. Core Philosophy: "Right-sized reasoning for right-sized questions" - SIMPLE queries bypass heavy machinery - MEDIUM queries activate selective components - COMPLEX queries use full Phase 1-6 capabilities Author: Jonathan Harrison (Codette Framework) """ import time from typing import Dict, List, Optional, Set from dataclasses import dataclass, field, asdict from reasoning_forge.query_classifier import QueryComplexity @dataclass class ComponentDecision: """Routing decision for which Phase 1-6 components to activate.""" # Routing metadata query_complexity: QueryComplexity component_activation: Dict[str, bool] # e.g., {"debate": True, "semantic_tension": False} component_config: Dict[str, any] = field(default_factory=dict) # e.g., {"debate_rounds": 1} reasoning: str = "" # Why this routing was chosen # Transparency estimated_latency_ms: float = 0.0 # Expected latency estimated_correctness: float = 0.5 # Expected correctness (0-1) estimated_compute_cost: float = 0.0 # Relative cost (1-100) class ExecutiveController: """Phase 7: Intelligent routing of queries to optimal component combinations. This replaces the "all-systems-go" approach with targeted component activation. Simple factual queries skip heavy machinery; complex queries use full power. Usage: exec_ctrl = ExecutiveController() decision = exec_ctrl.route_query(query) # Use decision to activate only selected components if decision.component_activation['debate']: result = forge.forge_with_debate(query, rounds=decision.component_config.get('debate_rounds', 1)) """ def __init__(self, verbose: bool = False): self.verbose = verbose # Learned routing patterns (initially empty, updated from memory) self.routing_patterns: Dict[str, ComponentDecision] = {} # Statistics self.queries_routed = 0 self.route_activation_counts = {} # Track which components get used def route_query(self, query: str, complexity: QueryComplexity) -> ComponentDecision: """Route a query to optimal component combination. Args: query: The user query complexity: QueryComplexity classification from Phase 6 Returns: ComponentDecision with activation flags and configuration """ self.queries_routed += 1 if complexity == QueryComplexity.SIMPLE: return self._route_simple(query) elif complexity == QueryComplexity.MEDIUM: return self._route_medium(query) else: # COMPLEX return self._route_complex(query) def _route_simple(self, query: str) -> ComponentDecision: """Route SIMPLE queries: skip heavy machinery. SIMPLE queries are factual (e.g., "speed of light", "definition of entropy"). They should get fast, direct answers without debate or heavy synthesis. Cost: ~3 units (classifier + router) Latency: ~150ms Correctness: 0.95 (factual answers are well-established) """ decision = ComponentDecision( query_complexity=QueryComplexity.SIMPLE, component_activation={ 'debate': False, 'semantic_tension': False, 'specialization_tracking': False, 'preflight_predictor': False, 'memory_weighting': False, 'gamma_monitoring': False, 'synthesis': False, # Direct answer only }, component_config={}, reasoning="SIMPLE factual query - avoided heavy machinery for speed", estimated_latency_ms=150, estimated_correctness=0.95, estimated_compute_cost=3, ) self._record_routing(decision) return decision def _route_medium(self, query: str) -> ComponentDecision: """Route MEDIUM queries: selective Phase 1-6 components. MEDIUM queries need some reasoning depth but don't require full debate. Examples: "How does X relate to Y", "What are the implications of Z" Activate: - semantic_tension: Continuous conflict strength (vs discrete) - debate: 1 round only (faster than 3) - specialization_tracking: Measure adapter fit - memory_weighting: Use learned adapter weights Skip: - preflight_predictor: Unnecessary for simpler queries Cost: ~25 units Latency: ~900ms (1-round debate) Correctness: 0.80 """ decision = ComponentDecision( query_complexity=QueryComplexity.MEDIUM, component_activation={ 'debate': True, 'semantic_tension': True, 'specialization_tracking': True, 'preflight_predictor': False, # Skip for speed 'memory_weighting': True, 'gamma_monitoring': True, 'synthesis': True, }, component_config={ 'debate_rounds': 1, # Single round for speed 'max_conflicts': 12, # Cap conflicts 'min_conflict_threshold': 0.2, }, reasoning="MEDIUM complexity - selective debate with semantic tension", estimated_latency_ms=900, estimated_correctness=0.80, estimated_compute_cost=25, ) self._record_routing(decision) return decision def _route_complex(self, query: str) -> ComponentDecision: """Route COMPLEX queries: full Phase 1-6 machinery. COMPLEX queries need deep reasoning, multiple perspectives, and conflict analysis. Examples: "Can machines be conscious?", "Ethical implications of AGI" Activate all Phase 1-6 components: - debate: 3 rounds for deep exploration - semantic_tension: Advanced conflict strength calculation - preflight_predictor: Predict conflicts before debate - specialization_tracking: Measure domain expertise - memory_weighting: Apply learned adapter weights - gamma_monitoring: Real-time coherence monitoring Cost: ~50+ units Latency: ~2500ms (3-round debate) Correctness: 0.85+ """ decision = ComponentDecision( query_complexity=QueryComplexity.COMPLEX, component_activation={ 'debate': True, 'semantic_tension': True, 'specialization_tracking': True, 'preflight_predictor': True, 'memory_weighting': True, 'gamma_monitoring': True, 'synthesis': True, }, component_config={ 'debate_rounds': 3, # Full exploration 'max_conflicts': 20, # Allow more conflicts for complex problems 'min_conflict_threshold': 0.15, 'semantic_tension_threshold': 0.3, }, reasoning="COMPLEX query - full Phase 1-6 machinery for deep synthesis", estimated_latency_ms=2500, estimated_correctness=0.85, estimated_compute_cost=50, ) self._record_routing(decision) return decision def _record_routing(self, decision: ComponentDecision): """Track which routing decisions are being made.""" for component, active in decision.component_activation.items(): if active: self.route_activation_counts[component] = \ self.route_activation_counts.get(component, 0) + 1 def get_routing_statistics(self) -> Dict: """Get statistics about routing decisions made so far. Returns: { 'total_queries_routed': int, 'component_activation_counts': {component: count, ...}, 'avg_latency_by_complexity': {SIMPLE: ms, MEDIUM: ms, COMPLEX: ms}, 'efficiency_gain': float (expected compute savings) } """ total_cost_full_stack = self.queries_routed * 50 # All queries with full machinery # Estimate cost savings from actual routing estimated_cost_actual = 0 return { 'total_queries_routed': self.queries_routed, 'component_activation_counts': self.route_activation_counts.copy(), 'efficiency_gain': f"Estimated {((total_cost_full_stack - estimated_cost_actual) / total_cost_full_stack * 100):.1f}% compute savings", } @staticmethod def create_route_metadata(decision: ComponentDecision, actual_latency_ms: float, actual_conflicts: int = 0, gamma: float = 0.5) -> Dict: """Create metadata dictionary for response transparency. This metadata tells users which components ran and why, making the system's reasoning transparent. Args: decision: The ComponentDecision that was executed actual_latency_ms: Measured latency from execution actual_conflicts: Number of conflicts detected gamma: Coherence score from ConflenceField Returns: Dictionary with routing transparency info for response """ return { 'phase7_routing': { 'query_complexity': decision.query_complexity.value, 'components_activated': { k: v for k, v in decision.component_activation.items() }, 'reasoning': decision.reasoning, 'latency_analysis': { 'estimated_ms': decision.estimated_latency_ms, 'actual_ms': actual_latency_ms, 'savings_ms': max(0, decision.estimated_latency_ms - actual_latency_ms), }, 'correctness_estimate': decision.estimated_correctness, 'compute_cost': { 'estimated_units': decision.estimated_compute_cost, 'unit_scale': '1=classifier, 50=full_machinery', }, 'metrics': { 'conflicts_detected': actual_conflicts, 'gamma_coherence': gamma, } } } class ExecutiveControllerWithLearning(ExecutiveController): """Extended Executive Controller with learning from historical routing decisions. This version learns which component combinations work best and adapts routing over time based on actual correctness measurements. Usage: ctrl = ExecutiveControllerWithLearning(living_memory=memory) ctrl.update_routes_from_history() # Weekly job """ def __init__(self, living_memory=None, verbose: bool = False): super().__init__(verbose) self.living_memory = living_memory self.learned_routes: Dict[str, float] = {} # Query type -> success rate def update_routes_from_history(self, window_days: int = 7): """Update routing patterns based on historical correctness data. This job should run periodically (e.g., daily) to learn which routes work best. Args: window_days: Look back this many days for historical data """ if not self.living_memory: if self.verbose: print("[EXEC] No living_memory available - skipping learned routing") return if self.verbose: print(f"[EXEC] Analyzing routing history ({window_days} days)...") # In a full implementation, this would: # 1. Query living_memory for recent debate results # 2. Correlate component_selection with correctness # 3. Update success rates for each route # 4. Adjust future routing based on evidence # For now, placeholder implementation self.learned_routes = { 'SIMPLE': 0.95, # High confidence in simple routing 'MEDIUM': 0.80, # Good but room for improvement 'COMPLEX': 0.85, # Good on complex routing } if self.verbose: print(f"[EXEC] Routing routes updated: {self.learned_routes}") def get_route_confidence(self, complexity: QueryComplexity) -> float: """Get learned confidence score for a routing decision. Returns: 0-1 confidence score (higher = more reliable route) """ return self.learned_routes.get(complexity.value, 0.5) def should_explore_alternate_route(self, complexity: QueryComplexity) -> bool: """Decide if we should try an alternate route (ε-greedy exploration). Args: complexity: Query complexity Returns: True if we should try a different route for learning """ confidence = self.get_route_confidence(complexity) # If very confident, stick with known good route if confidence > 0.90: return False # If moderate confidence, 10% of time try alternate if confidence > 0.70: return __import__('random').random() < 0.1 # If low confidence, 25% of time try alternate return __import__('random').random() < 0.25