defmodule Mix.Tasks.Raxol.ErrorRecovery do @moduledoc """ Interactive Error Recovery Console - Phase 4.3 Error Experience Provides an interactive console for error investigation and recovery, integrating with Phase 3 optimizations and Phase 4.2 development tools. ## Features - Interactive error analysis and classification - Integration with Phase 4.2 tools (analyze, profile, debug) - Phase 3 optimization context and suggestions - Automated recovery workflows - Error pattern learning and prevention ## Usage # Start interactive error recovery console mix raxol.error_recovery # Analyze specific error with context mix raxol.error_recovery --error "error_description" --context "additional_info" # Recovery mode for critical errors mix raxol.error_recovery --critical --auto-analyze """ use Mix.Task alias Raxol.Core.{ErrorExperience, ErrorTemplates} require Logger @shortdoc "Interactive error recovery console with Phase 3/4 integration" @switches [ error: :string, context: :string, critical: :boolean, auto_analyze: :boolean, help: :boolean ] @aliases [h: :help, e: :error, c: :context] def run(args) do {opts, _args, _invalid} = OptionParser.parse(args, switches: @switches, aliases: @aliases) if opts[:help] do print_help() else start_recovery_console(opts) end end defp start_recovery_console(opts) do print_banner() cond do opts[:error] -> handle_specific_error(opts[:error], opts[:context] || "", opts) opts[:critical] -> start_critical_recovery_mode(opts) true -> start_interactive_mode() end end defp print_banner do IO.puts([ IO.ANSI.cyan(), """ ╔══════════════════════════════════════════════════════════════════╗ ║ Raxol Error Recovery Console ║ ║ Phase 4.3 Error Experience ║ ╠══════════════════════════════════════════════════════════════════╣ ║ Interactive error investigation and recovery with Phase 3/4 ║ ║ integration for performance-aware error handling ║ ╚══════════════════════════════════════════════════════════════════╝ """, IO.ANSI.reset() ]) end defp handle_specific_error(error_description, context, opts) do IO.puts( "\n#{IO.ANSI.yellow()}Analyzing Error:#{IO.ANSI.reset()} #{error_description}" ) context_map = parse_context_string(context) enhanced_error = ErrorExperience.classify_and_enhance(error_description, context_map) display_error_analysis(enhanced_error) if opts[:auto_analyze] do auto_trigger_tools(enhanced_error) else offer_recovery_options(enhanced_error) end end defp start_critical_recovery_mode(opts) do IO.puts([ IO.ANSI.red(), IO.ANSI.bright(), "\n⚠️ CRITICAL ERROR RECOVERY MODE ACTIVATED ⚠️\n", IO.ANSI.reset() ]) IO.puts( "This mode provides automated error analysis and recovery suggestions." ) # Check system state check_system_health() # Offer critical recovery options offer_critical_recovery_options(opts) end defp start_interactive_mode do IO.puts( "\n#{IO.ANSI.green()}Interactive Error Recovery Console#{IO.ANSI.reset()}" ) IO.puts("Enter 'help' for commands, 'quit' to exit") interactive_loop() end defp interactive_loop do prompt = IO.ANSI.blue() <> "raxol-error> " <> IO.ANSI.reset() case IO.gets(prompt) |> String.trim() do "" -> interactive_loop() "quit" -> IO.puts("Goodbye!") "help" -> print_interactive_help() interactive_loop() "status" -> show_system_status() interactive_loop() "analyze" -> run_interactive_analysis() interactive_loop() "recent" -> show_recent_errors() interactive_loop() "patterns" -> show_error_patterns() interactive_loop() "tools" -> show_available_tools() interactive_loop() "test-tools" -> test_tool_integration() interactive_loop() command -> if String.starts_with?(command, "error ") do error_text = String.replace_leading(command, "error ", "") handle_specific_error(error_text, "", %{}) else IO.puts( "Unknown command: #{command}. Type 'help' for available commands." ) end interactive_loop() end end defp display_error_analysis(enhanced_error) do IO.puts("\n#{IO.ANSI.cyan()}Error Analysis Results:#{IO.ANSI.reset()}") IO.puts("Category: #{enhanced_error.category}") IO.puts("Severity: #{enhanced_error.severity}") IO.puts("Performance Impact: #{enhanced_error.performance_impact}") if enhanced_error.related_optimizations != [] do IO.puts( "Related Phase 3 Optimizations: #{Enum.join(enhanced_error.related_optimizations, ", ")}" ) end IO.puts("\n#{IO.ANSI.green()}Suggestions:#{IO.ANSI.reset()}") enhanced_error.suggestions |> Enum.with_index(1) |> Enum.each(fn {suggestion, index} -> confidence_bar = String.duplicate("█", round(suggestion.confidence * 10)) IO.puts("#{index}. #{suggestion.description}") IO.puts( " Confidence: #{confidence_bar} (#{round(suggestion.confidence * 100)}%)" ) if suggestion.action do IO.puts( " Action: #{IO.ANSI.cyan()}#{suggestion.action}#{IO.ANSI.reset()}" ) end if suggestion.phase3_context do IO.puts(" Phase 3: #{inspect(suggestion.phase3_context)}") end IO.puts("") end) end defp offer_recovery_options(enhanced_error) do IO.puts("\n#{IO.ANSI.yellow()}Recovery Options:#{IO.ANSI.reset()}") options = [ {"Analyze with Phase 4.2 tools", :analyze_tools}, {"View detailed template", :show_template}, {"Start interactive debug", :start_debug}, {"Generate error report", :generate_report}, {"Apply automatic fixes", :auto_fix} ] options |> Enum.with_index(1) |> Enum.each(fn {{description, _action}, index} -> IO.puts("#{index}. #{description}") end) choice = IO.gets("Select option (1-#{length(options)}): ") |> String.trim() case Integer.parse(choice) do {num, ""} when num in 1..length(options)//1 -> {_desc, action} = Enum.at(options, num - 1) execute_recovery_action(action, enhanced_error) _ -> IO.puts("Invalid selection.") end end defp execute_recovery_action(action, enhanced_error) do case action do :analyze_tools -> trigger_analysis_tools(enhanced_error) :show_template -> show_detailed_template(enhanced_error) :start_debug -> start_debug_session(enhanced_error) :generate_report -> report = ErrorExperience.generate_error_report(enhanced_error) IO.puts("Error report generated: #{report.error_id}") :auto_fix -> apply_automatic_fixes(enhanced_error) end end defp trigger_analysis_tools(enhanced_error) do IO.puts( "\n#{IO.ANSI.magenta()}Triggering Phase 4.2 Analysis Tools...#{IO.ANSI.reset()}" ) case enhanced_error.category do :performance -> IO.puts("Starting performance analysis...") run_mix_task("raxol.analyze", [ "--depth", "comprehensive", "--benchmark" ]) run_mix_task("raxol.profile", ["--duration", "30"]) :ui_rendering -> IO.puts("Starting render pipeline analysis...") run_mix_task("raxol.debug", ["--trace", "Raxol.UI.Rendering.*"]) :terminal_io -> IO.puts("Starting terminal I/O analysis...") run_mix_task("raxol.analyze", ["--target", "lib/raxol/terminal/"]) _ -> IO.puts("Starting general analysis...") run_mix_task("raxol.debug", ["--trace", "*"]) end end defp show_detailed_template(enhanced_error) do template = ErrorTemplates.get_template( enhanced_error.category, enhanced_error.context ) formatted = ErrorTemplates.format_error_message(template, enhanced_error.context) IO.puts("\n#{formatted}") end defp start_debug_session(enhanced_error) do IO.puts("\n#{IO.ANSI.blue()}Starting Debug Session...#{IO.ANSI.reset()}") debug_args = case enhanced_error.category do :performance -> ["--memory", "--performance"] :ui_rendering -> ["--trace", "Raxol.UI.Rendering.*"] :terminal_io -> ["--trace", "Raxol.Terminal.*"] _ -> [] end run_mix_task("raxol.debug", debug_args) end defp apply_automatic_fixes(enhanced_error) do IO.puts("\n#{IO.ANSI.green()}Applying Automatic Fixes...#{IO.ANSI.reset()}") automatic_suggestions = enhanced_error.suggestions |> Enum.filter(&(&1.type == :automatic)) if automatic_suggestions == [] do IO.puts("No automatic fixes available for this error type.") else Enum.each(automatic_suggestions, fn suggestion -> IO.puts("Applying: #{suggestion.description}") # In a real implementation, this would execute the fix IO.puts("✓ Applied (simulation)") end) end end defp check_system_health do IO.puts("\n#{IO.ANSI.yellow()}System Health Check:#{IO.ANSI.reset()}") # Check Phase 4.2 tools availability tools_status = check_tools_availability() # Check Phase 3 optimization status phase3_status = check_phase3_optimizations() # Check memory and performance performance_status = check_performance_metrics() display_health_summary(tools_status, phase3_status, performance_status) end defp check_tools_availability do tools = [:raxol_analyze, :raxol_profile, :raxol_debug, :raxol_gen_component] Enum.map(tools, fn tool -> task_name = tool |> to_string() |> String.replace("_", ".") case System.cmd("mix", ["help", task_name], stderr_to_stdout: true) do {_output, 0} -> {tool, :available} _ -> {tool, :missing} end end) end defp check_phase3_optimizations do # Mock check - in reality would verify optimization implementations %{ parser_performance: :optimized, memory_usage: :within_target, render_batching: :active, damage_tracking: :active } end defp check_performance_metrics do # Mock metrics - in reality would get actual performance data %{ # MB memory_usage: 2.1, # μs parse_time: 2.8, # ms render_time: 0.8 } end defp display_health_summary(tools_status, phase3_status, performance_status) do IO.puts("\n📊 Tools Status:") Enum.each(tools_status, fn {tool, status} -> icon = if status == :available, do: "✓", else: "✗" color = if status == :available, do: IO.ANSI.green(), else: IO.ANSI.red() IO.puts(" #{color}#{icon} #{tool}#{IO.ANSI.reset()}") end) IO.puts("\n🚀 Phase 3 Optimizations:") Enum.each(phase3_status, fn {optimization, status} -> icon = case status do :optimized -> "✓" :active -> "✓" :within_target -> "✓" _ -> "⚠" end color = if status in [:optimized, :active, :within_target], do: IO.ANSI.green(), else: IO.ANSI.yellow() IO.puts(" #{color}#{icon} #{optimization}: #{status}#{IO.ANSI.reset()}") end) IO.puts("\n📈 Performance Metrics:") IO.puts( " Memory Usage: #{performance_status.memory_usage}MB (target: <2.8MB)" ) IO.puts(" Parse Time: #{performance_status.parse_time}μs (target: <3.3μs)") IO.puts(" Render Time: #{performance_status.render_time}ms (target: <1ms)") end defp offer_critical_recovery_options(_opts) do options = [ "Run comprehensive system analysis", "Force garbage collection and memory cleanup", "Restart with optimizations disabled", "Generate critical error report", "Start emergency debug mode" ] IO.puts("\n#{IO.ANSI.red()}Critical Recovery Options:#{IO.ANSI.reset()}") options |> Enum.with_index(1) |> Enum.each(fn {option, index} -> IO.puts("#{index}. #{option}") end) choice = IO.gets("Select critical recovery option: ") |> String.trim() case Integer.parse(choice) do {1, ""} -> IO.puts("Running comprehensive analysis...") run_mix_task("raxol.analyze", [ "--depth", "comprehensive", "--benchmark" ]) run_mix_task("raxol.profile", ["--duration", "60"]) {2, ""} -> IO.puts("Forcing garbage collection...") :erlang.garbage_collect() IO.puts("✓ Memory cleanup completed") {3, ""} -> IO.puts("Restart required with --no-optimizations flag") {4, ""} -> IO.puts("Generating critical error report...") # Would generate detailed report {5, ""} -> IO.puts("Starting emergency debug mode...") run_mix_task("raxol.debug", ["--emergency"]) _ -> IO.puts("Invalid selection.") end end defp run_interactive_analysis do IO.puts("Enter error description or paste error message:") error_input = IO.gets("> ") |> String.trim() if error_input != "" do handle_specific_error(error_input, "", %{}) else IO.puts("No error description provided.") end end defp show_recent_errors do IO.puts("\n#{IO.ANSI.cyan()}Recent Error Reports:#{IO.ANSI.reset()}") reports_dir = "/tmp/raxol_error_reports" if File.exists?(reports_dir) do File.ls!(reports_dir) |> Enum.sort(:desc) |> Enum.take(5) |> Enum.with_index(1) |> Enum.each(fn {filename, index} -> IO.puts("#{index}. #{filename}") end) else IO.puts("No recent error reports found.") end end defp show_error_patterns do IO.puts("\n#{IO.ANSI.cyan()}Known Error Patterns:#{IO.ANSI.reset()}") patterns = [ "Parser performance degradation (Phase 3 related)", "Memory usage exceeding 2.8MB target", "Render batch queue overflow", "Component missing optimization markers", "ANSI sequence parse failures", "Tool integration failures" ] Enum.with_index(patterns, 1) |> Enum.each(fn {pattern, index} -> IO.puts("#{index}. #{pattern}") end) end defp show_available_tools do IO.puts( "\n#{IO.ANSI.cyan()}Available Phase 4.2 Development Tools:#{IO.ANSI.reset()}" ) tools = [ {"mix raxol.analyze", "Performance analyzer showcasing Phase 3 optimizations"}, {"mix raxol.profile", "Interactive profiler with real-time metrics"}, {"mix raxol.debug", "Debug console with Phase 3 insights"}, {"mix raxol.gen.component", "Component generator with optimization patterns"} ] Enum.each(tools, fn {command, description} -> IO.puts(" #{IO.ANSI.green()}#{command}#{IO.ANSI.reset()}") IO.puts(" #{description}") IO.puts("") end) end defp test_tool_integration do IO.puts("\n#{IO.ANSI.cyan()}Testing Tool Integration...#{IO.ANSI.reset()}") tools = [ "raxol.analyze", "raxol.profile", "raxol.debug", "raxol.gen.component" ] Enum.each(tools, fn tool -> case System.cmd("mix", ["help", tool], stderr_to_stdout: true) do {_output, 0} -> IO.puts(" ✓ #{tool} - Available") _ -> IO.puts(" ✗ #{tool} - Not available") end end) end defp show_system_status do IO.puts("\n#{IO.ANSI.cyan()}System Status:#{IO.ANSI.reset()}") # Show memory usage memory = :erlang.memory() total_mb = memory[:total] / 1_000_000 IO.puts("Memory Usage: #{Float.round(total_mb, 2)}MB") # Show process count process_count = length(Process.list()) IO.puts("Active Processes: #{process_count}") # Show system info IO.puts("Erlang Version: #{:erlang.system_info(:otp_release)}") IO.puts("Elixir Version: #{System.version()}") end defp auto_trigger_tools(enhanced_error) do IO.puts( "\n#{IO.ANSI.magenta()}Auto-triggering analysis tools...#{IO.ANSI.reset()}" ) case enhanced_error.performance_impact do impact when impact in [:high, :critical] -> run_mix_task("raxol.analyze", ["--depth", "comprehensive"]) run_mix_task("raxol.profile", ["--duration", "30"]) :medium -> run_mix_task("raxol.debug", ["--trace", "*"]) _ -> IO.puts("Low impact error - manual investigation recommended") end end defp run_mix_task(task, args) do case System.cmd("mix", [task | args]) do {output, 0} -> IO.puts("✓ #{task} completed successfully") if String.length(output) > 0 do IO.puts(String.slice(output, 0..500) <> "...") end {error, _} -> IO.puts("✗ #{task} failed: #{String.slice(error, 0..200)}") end end defp parse_context_string(context_string) do context_string |> String.split(",") |> Enum.reduce(%{}, fn pair, acc -> case String.split(pair, ":") do [key, value] -> Map.put(acc, String.trim(key) |> String.to_atom(), String.trim(value)) _ -> acc end end) end defp print_interactive_help do IO.puts(""" #{IO.ANSI.cyan()}Interactive Error Recovery Console Commands:#{IO.ANSI.reset()} #{IO.ANSI.green()}General:#{IO.ANSI.reset()} help - Show this help message quit - Exit the console status - Show current system status #{IO.ANSI.green()}Error Analysis:#{IO.ANSI.reset()} analyze - Interactive error analysis recent - Show recent error reports patterns - Show known error patterns error - Analyze specific error #{IO.ANSI.green()}Tools:#{IO.ANSI.reset()} tools - Show available Phase 4.2 tools test-tools - Test tool integration #{IO.ANSI.green()}Examples:#{IO.ANSI.reset()} error Parser timeout in ANSI sequence error Memory allocation failed error Component render batch overflow """) end defp print_help do IO.puts(""" mix raxol.error_recovery - Interactive Error Recovery Console Phase 4.3 Error Experience tool that provides intelligent error handling with integration to Phase 3 optimizations and Phase 4.2 development tools. Usage: mix raxol.error_recovery [options] Options: --error ERROR Analyze specific error message --context CONTEXT Additional context (key:value,key2:value2) --critical Start in critical recovery mode --auto-analyze Automatically trigger analysis tools --help Show this help Interactive Mode Commands: help Show available commands analyze Interactive error analysis recent Show recent error reports patterns Show known error patterns tools Show available Phase 4.2 tools status Show system status quit Exit console Examples: mix raxol.error_recovery mix raxol.error_recovery --error "Parser timeout" --context "component:UserCard" mix raxol.error_recovery --critical --auto-analyze Phase 3 Integration: - Performance targets: Parser <3.3μs/op, Memory <2.8MB - Optimization context in error suggestions - Automatic tool triggering for performance issues Phase 4.2 Tool Integration: - mix raxol.analyze for performance analysis - mix raxol.profile for real-time profiling - mix raxol.debug for interactive debugging - mix raxol.gen.component for optimized component generation """) end end