#!/usr/bin/env python3 """ Session Finalizer Hook - Stop hook Finalizes session, creates documentation, and saves state """ import sys import json import os from pathlib import Path # Add lib directory to path sys.path.insert(0, str(Path(__file__).parent.parent / "lib")) from session_state import SessionStateManager from shadow_learner import ShadowLearner from context_monitor import ContextMonitor def main(): """Main hook entry point""" try: # Read input from Claude Code (if any) try: input_data = json.loads(sys.stdin.read()) except: input_data = {} # Initialize components session_manager = SessionStateManager() shadow_learner = ShadowLearner() context_monitor = ContextMonitor() # Create session documentation session_manager.create_continuation_docs() # Save all learned patterns shadow_learner.save_database() # Get session summary for logging session_summary = session_manager.get_session_summary() # Create recovery guide if session was interrupted create_recovery_info(session_summary, context_monitor) # Clean up session session_manager.cleanup_session() # Log session completion log_session_completion(session_summary) # Always allow - this is a cleanup hook response = { "allow": True, "message": f"Session finalized. Modified {len(session_summary.get('modified_files', []))} files, used {session_summary.get('session_stats', {}).get('total_tool_calls', 0)} tools." } print(json.dumps(response)) sys.exit(0) except Exception as e: # Session finalization should never block response = { "allow": True, "message": f"Session finalization error: {str(e)}" } print(json.dumps(response)) sys.exit(0) def create_recovery_info(session_summary: dict, context_monitor: ContextMonitor): """Create recovery information if needed""" try: context_usage = context_monitor.get_context_usage_ratio() # If context was high when session ended, create recovery guide if context_usage > 0.8: recovery_content = f"""# Session Recovery Information ## Context Status - **Context Usage**: {context_usage:.1%} when session ended - **Reason**: Session ended with high context usage ## What This Means Your Claude session ended while using a significant amount of context. This could mean: 1. You were working on a complex task 2. Context limits were approaching 3. Session was interrupted ## Recovery Steps ### 1. Check Your Progress Review these recently modified files: """ for file_path in session_summary.get('modified_files', []): recovery_content += f"- {file_path}\n" recovery_content += f""" ### 2. Review Last Actions Recent commands executed: """ recent_commands = session_summary.get('commands_executed', [])[-5:] for cmd_info in recent_commands: recovery_content += f"- `{cmd_info['command']}`\n" recovery_content += f""" ### 3. Continue Your Work 1. Check `ACTIVE_TODOS.md` for pending tasks 2. Review `LAST_SESSION.md` for complete session history 3. Use `git status` to see current file changes 4. Consider committing your progress: `git add -A && git commit -m "Work in progress"` ### 4. Available Backups """ for backup in session_summary.get('backup_history', []): status = "✅" if backup['success'] else "❌" recovery_content += f"- {status} {backup['backup_id']} - {backup['reason']}\n" recovery_content += f""" ## Quick Recovery Commands ```bash # Check current status git status # View recent changes git diff # List available backups ls .claude_hooks/backups/ # View active todos cat ACTIVE_TODOS.md # View last session summary cat LAST_SESSION.md ``` *This recovery guide was created because your session ended with {context_usage:.1%} context usage.* """ with open("RECOVERY_GUIDE.md", 'w') as f: f.write(recovery_content) except Exception: pass # Don't let recovery guide creation break session finalization def log_session_completion(session_summary: dict): """Log session completion for analysis""" try: log_dir = Path(".claude_hooks/logs") log_dir.mkdir(parents=True, exist_ok=True) from datetime import datetime completion_log = { "timestamp": datetime.now().isoformat(), "type": "session_completion", "session_id": session_summary.get("session_id", "unknown"), "duration_minutes": session_summary.get("session_stats", {}).get("duration_minutes", 0), "total_tools": session_summary.get("session_stats", {}).get("total_tool_calls", 0), "files_modified": len(session_summary.get("modified_files", [])), "commands_executed": session_summary.get("session_stats", {}).get("total_commands", 0), "backups_created": len(session_summary.get("backup_history", [])) } log_file = log_dir / "session_completions.jsonl" with open(log_file, 'a') as f: f.write(json.dumps(completion_log) + "\n") except Exception: pass # Don't let logging errors break finalization if __name__ == "__main__": main()