Refactor cockpit to use DockerTmuxController pattern
Based on claude-code-tools TmuxCLIController, this refactor: - Added DockerTmuxController class for robust tmux session management - Implements send_keys() with configurable delay_enter - Implements capture_pane() for output retrieval - Implements wait_for_prompt() for pattern-based completion detection - Implements wait_for_idle() for content-hash-based idle detection - Implements wait_for_shell_prompt() for shell prompt detection Also includes workflow improvements: - Pre-task git snapshot before agent execution - Post-task commit protocol in agent guidelines Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
187
lib/maintenance_orchestrator.py
Normal file
187
lib/maintenance_orchestrator.py
Normal file
@@ -0,0 +1,187 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Maintenance Orchestrator
|
||||
|
||||
Coordinates all maintenance operations across systems:
|
||||
- KG maintenance
|
||||
- Conductor cleanup
|
||||
- Context tuning
|
||||
- Summary reporting
|
||||
"""
|
||||
|
||||
import time
|
||||
from typing import List, Dict
|
||||
|
||||
from kg_maintainer import KGMaintainer
|
||||
from conductor_maintainer import ConductorMaintainer
|
||||
from context_maintainer import ContextMaintainer
|
||||
|
||||
|
||||
class MaintenanceOrchestrator:
|
||||
"""Orchestrate all system maintenance operations."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize maintenance orchestrator."""
|
||||
self.kg_maintainer = KGMaintainer()
|
||||
self.conductor_maintainer = ConductorMaintainer()
|
||||
self.context_maintainer = ContextMaintainer()
|
||||
|
||||
def run_full_system_maintenance(self, dry_run: bool = True) -> Dict:
|
||||
"""
|
||||
Run comprehensive system maintenance.
|
||||
|
||||
Args:
|
||||
dry_run: If True, preview only
|
||||
|
||||
Returns:
|
||||
Dict with maintenance summary
|
||||
"""
|
||||
result = {
|
||||
'timestamp': time.time(),
|
||||
'dry_run': dry_run,
|
||||
'status': 'success',
|
||||
'modules': {},
|
||||
'total_space_freed_mb': 0,
|
||||
'actions_completed': []
|
||||
}
|
||||
|
||||
# 1. KG Maintenance
|
||||
kg_result = self.kg_maintainer.run_full_kg_maintenance(dry_run=dry_run)
|
||||
result['modules']['kg'] = {
|
||||
'duplicates_found': kg_result['duplicates_found'],
|
||||
'duplicates_merged': kg_result['duplicates_merged'],
|
||||
'indexes_optimized': kg_result['indexes_optimized'],
|
||||
'relations_strengthened': kg_result['relations_strengthened'],
|
||||
'status': 'success'
|
||||
}
|
||||
result['actions_completed'].append(f"KG: Merged {kg_result['duplicates_merged']} duplicates")
|
||||
|
||||
# 2. Conductor Maintenance
|
||||
conductor_result = self.conductor_maintainer.run_full_conductor_maintenance(dry_run=dry_run)
|
||||
result['modules']['conductor'] = conductor_result['summary']
|
||||
result['total_space_freed_mb'] += conductor_result['summary'].get('space_freed_mb', 0)
|
||||
result['total_space_freed_mb'] += conductor_result['summary'].get('space_freed_temp_mb', 0)
|
||||
result['actions_completed'].append(
|
||||
f"Conductor: Archived {conductor_result['summary']['tasks_archived']} tasks, "
|
||||
f"freed {conductor_result['summary']['space_freed_mb']:.1f}MB"
|
||||
)
|
||||
|
||||
# 3. Context Maintenance
|
||||
context_result = self.context_maintainer.run_full_context_maintenance(dry_run=dry_run)
|
||||
result['modules']['context'] = {
|
||||
'performance_metrics': context_result.get('performance_metrics', {}),
|
||||
'actions': context_result['actions_completed'],
|
||||
'status': 'success'
|
||||
}
|
||||
result['actions_completed'].append(f"Context: Tuned retrieval and buckets")
|
||||
|
||||
return result
|
||||
|
||||
def run_kg_only_maintenance(self, dry_run: bool = True) -> Dict:
|
||||
"""Run KG maintenance only."""
|
||||
result = self.kg_maintainer.run_full_kg_maintenance(dry_run=dry_run)
|
||||
return {
|
||||
'module': 'kg',
|
||||
'result': result,
|
||||
'timestamp': time.time()
|
||||
}
|
||||
|
||||
def run_conductor_only_maintenance(self, dry_run: bool = True) -> Dict:
|
||||
"""Run conductor maintenance only."""
|
||||
result = self.conductor_maintainer.run_full_conductor_maintenance(dry_run=dry_run)
|
||||
return {
|
||||
'module': 'conductor',
|
||||
'result': result,
|
||||
'timestamp': time.time()
|
||||
}
|
||||
|
||||
def run_context_only_maintenance(self, dry_run: bool = True) -> Dict:
|
||||
"""Run context maintenance only."""
|
||||
result = self.context_maintainer.run_full_context_maintenance(dry_run=dry_run)
|
||||
return {
|
||||
'module': 'context',
|
||||
'result': result,
|
||||
'timestamp': time.time()
|
||||
}
|
||||
|
||||
def run_targeted_maintenance(self, target: str, dry_run: bool = True) -> Dict:
|
||||
"""
|
||||
Run targeted maintenance on specific subsystem.
|
||||
|
||||
Args:
|
||||
target: 'kg' | 'conductor' | 'context' | 'all'
|
||||
dry_run: If True, preview only
|
||||
|
||||
Returns:
|
||||
Maintenance result
|
||||
"""
|
||||
if target == 'kg':
|
||||
return self.run_kg_only_maintenance(dry_run=dry_run)
|
||||
elif target == 'conductor':
|
||||
return self.run_conductor_only_maintenance(dry_run=dry_run)
|
||||
elif target == 'context':
|
||||
return self.run_context_only_maintenance(dry_run=dry_run)
|
||||
elif target == 'all':
|
||||
return self.run_full_system_maintenance(dry_run=dry_run)
|
||||
else:
|
||||
return {
|
||||
'error': f'Unknown target: {target}',
|
||||
'valid_targets': ['kg', 'conductor', 'context', 'all']
|
||||
}
|
||||
|
||||
def generate_maintenance_report(self, maintenance_data: Dict) -> str:
|
||||
"""
|
||||
Generate formatted maintenance report.
|
||||
|
||||
Args:
|
||||
maintenance_data: Result from maintenance operation
|
||||
|
||||
Returns:
|
||||
Formatted report string
|
||||
"""
|
||||
import datetime
|
||||
|
||||
timestamp = datetime.datetime.fromtimestamp(maintenance_data['timestamp']).strftime('%Y-%m-%d %H:%M UTC')
|
||||
|
||||
report = f"""
|
||||
╔════════════════════════════════════════════════════════════════════╗
|
||||
║ SYSTEM MAINTENANCE REPORT ║
|
||||
║ {timestamp:42} ║
|
||||
╚════════════════════════════════════════════════════════════════════╝
|
||||
|
||||
MODE: {'DRY RUN (preview only)' if maintenance_data['dry_run'] else 'ACTUAL (changes applied)'}
|
||||
STATUS: {maintenance_data['status'].upper()}
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
ACTIONS COMPLETED:
|
||||
|
||||
"""
|
||||
for action in maintenance_data['actions_completed']:
|
||||
report += f" ✓ {action}\n"
|
||||
|
||||
if 'total_space_freed_mb' in maintenance_data:
|
||||
report += f"\nSpace Freed: {maintenance_data['total_space_freed_mb']:.1f}MB\n"
|
||||
|
||||
report += f"\n{'━' * 70}\n"
|
||||
|
||||
return report
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
orchestrator = MaintenanceOrchestrator()
|
||||
|
||||
print("=" * 70)
|
||||
print("FULL SYSTEM MAINTENANCE DRY RUN")
|
||||
print("=" * 70)
|
||||
|
||||
result = orchestrator.run_full_system_maintenance(dry_run=True)
|
||||
|
||||
print(orchestrator.generate_maintenance_report(result))
|
||||
|
||||
print("\nDetailed Results by Module:")
|
||||
for module, data in result['modules'].items():
|
||||
print(f"\n{module.upper()}:")
|
||||
for key, value in data.items():
|
||||
if key != 'status':
|
||||
print(f" {key}: {value}")
|
||||
Reference in New Issue
Block a user