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>
188 lines
6.8 KiB
Python
188 lines
6.8 KiB
Python
#!/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}")
|