code_healer 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +70 -0
  3. data/GEM_SUMMARY.md +307 -0
  4. data/README.md +281 -0
  5. data/code_healer.gemspec +77 -0
  6. data/config/code_healer.yml.example +104 -0
  7. data/docs/INSTALLATION.md +439 -0
  8. data/examples/basic_usage.rb +160 -0
  9. data/exe/code_healer-setup +7 -0
  10. data/lib/code_healer/application_job.rb +7 -0
  11. data/lib/code_healer/business_context_analyzer.rb +464 -0
  12. data/lib/code_healer/business_context_loader.rb +273 -0
  13. data/lib/code_healer/business_context_manager.rb +297 -0
  14. data/lib/code_healer/business_logic_generator.rb +94 -0
  15. data/lib/code_healer/business_rule_applier.rb +54 -0
  16. data/lib/code_healer/claude_code_evolution_handler.rb +224 -0
  17. data/lib/code_healer/claude_error_monitor.rb +48 -0
  18. data/lib/code_healer/config_manager.rb +275 -0
  19. data/lib/code_healer/context_aware_prompt_builder.rb +153 -0
  20. data/lib/code_healer/core.rb +513 -0
  21. data/lib/code_healer/error_handler.rb +141 -0
  22. data/lib/code_healer/evolution_job.rb +99 -0
  23. data/lib/code_healer/global_handler.rb +130 -0
  24. data/lib/code_healer/healing_job.rb +167 -0
  25. data/lib/code_healer/mcp.rb +108 -0
  26. data/lib/code_healer/mcp_prompts.rb +111 -0
  27. data/lib/code_healer/mcp_server.rb +389 -0
  28. data/lib/code_healer/mcp_tools.rb +2364 -0
  29. data/lib/code_healer/pull_request_creator.rb +143 -0
  30. data/lib/code_healer/setup.rb +390 -0
  31. data/lib/code_healer/simple_evolution.rb +737 -0
  32. data/lib/code_healer/simple_global_handler.rb +122 -0
  33. data/lib/code_healer/simple_healer.rb +515 -0
  34. data/lib/code_healer/terminal_integration.rb +87 -0
  35. data/lib/code_healer/usage_analyzer.rb +92 -0
  36. data/lib/code_healer/version.rb +5 -0
  37. data/lib/code_healer.rb +67 -0
  38. metadata +411 -0
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodeHealer
4
+ # MCP Prompt for error fixing workflow
5
+ class ErrorFixPrompt < MCP::Prompt
6
+ prompt_name "error_fix_workflow"
7
+ description "Complete workflow for analyzing and fixing errors with context awareness"
8
+ arguments [
9
+ MCP::Prompt::Argument.new(
10
+ name: "error_type",
11
+ description: "Type of error to fix",
12
+ required: true
13
+ ),
14
+ MCP::Prompt::Argument.new(
15
+ name: "error_message",
16
+ description: "Error message details",
17
+ required: true
18
+ ),
19
+ MCP::Prompt::Argument.new(
20
+ name: "class_name",
21
+ description: "Class where error occurred",
22
+ required: true
23
+ ),
24
+ MCP::Prompt::Argument.new(
25
+ name: "method_name",
26
+ description: "Method where error occurred",
27
+ required: true
28
+ )
29
+ ]
30
+
31
+ class << self
32
+ def template(args, server_context:)
33
+ context = server_context[:codebase_context]
34
+
35
+ MCP::Prompt::Result.new(
36
+ description: "Error Fix Workflow for #{args['class_name']}##{args['method_name']}",
37
+ messages: [
38
+ MCP::Prompt::Message.new(
39
+ role: "system",
40
+ content: MCP::Content::Text.new(build_system_prompt(args, context))
41
+ ),
42
+ MCP::Prompt::Message.new(
43
+ role: "user",
44
+ content: MCP::Content::Text.new(build_user_prompt(args, context))
45
+ ),
46
+ MCP::Prompt::Message.new(
47
+ role: "assistant",
48
+ content: MCP::Content::Text.new(build_assistant_response(args, context))
49
+ )
50
+ ]
51
+ )
52
+ end
53
+
54
+ private
55
+
56
+ def build_system_prompt(args, context)
57
+ <<~PROMPT
58
+ You are an expert Ruby developer and code evolution specialist. You have access to a comprehensive error analysis and code generation system.
59
+
60
+ Your role is to:
61
+ 1. Analyze errors with rich context
62
+ 2. Generate intelligent, production-ready fixes
63
+ 3. Validate fixes against business requirements
64
+ 4. Provide recommendations for testing and monitoring
65
+
66
+ Available tools:
67
+ - ErrorAnalysisTool: Analyzes errors with context
68
+ - CodeFixTool: Generates intelligent code fixes
69
+ - ContextAnalysisTool: Validates fixes and provides recommendations
70
+
71
+ Business Context:
72
+ - Project Type: #{context[:project_type]}
73
+ - Business Domain: #{context[:business_domain]}
74
+ - Coding Standards: #{context[:coding_standards]}
75
+ - Common Patterns: #{context[:common_patterns]}
76
+ PROMPT
77
+ end
78
+
79
+ def build_user_prompt(args, context)
80
+ <<~PROMPT
81
+ Please analyze and fix the following error:
82
+
83
+ Error Type: #{args['error_type']}
84
+ Error Message: #{args['error_message']}
85
+ Class: #{args['class_name']}
86
+ Method: #{args['method_name']}
87
+
88
+ Please provide:
89
+ 1. Error analysis with severity and impact assessment
90
+ 2. Intelligent code fix that addresses the specific error
91
+ 3. Validation of the fix against business requirements
92
+ 4. Recommendations for testing and monitoring
93
+ PROMPT
94
+ end
95
+
96
+ def build_assistant_response(args, context)
97
+ <<~RESPONSE
98
+ I'll help you analyze and fix this error using our intelligent evolution system.
99
+
100
+ Let me start by analyzing the error with rich context, then generate an intelligent fix, and finally validate it against our business requirements.
101
+
102
+ This workflow will ensure the fix is:
103
+ - Context-aware and business-appropriate
104
+ - Production-ready with proper error handling
105
+ - Validated for syntax, performance, and security
106
+ - Accompanied by testing and monitoring recommendations
107
+ RESPONSE
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,389 @@
1
+ require_relative 'mcp_tools'
2
+ require_relative 'mcp_prompts'
3
+
4
+ module CodeHealer
5
+ class McpServer
6
+ class << self
7
+ def initialize_server
8
+ puts "🤖 Initializing MCP Server for intelligent evolution..."
9
+
10
+ # Load context and business rules
11
+ @codebase_context = load_codebase_context
12
+ @business_rules = load_business_rules
13
+
14
+ # Initialize MCP server with tools (simplified for now)
15
+ @server = CodeHealer::MCP::Server.new(
16
+ name: "code_healer_server",
17
+ version: "1.0.0",
18
+ tools: [
19
+ ErrorAnalysisTool,
20
+ CodeFixTool,
21
+ ContextAnalysisTool
22
+ ],
23
+ server_context: {
24
+ codebase_context: @codebase_context,
25
+ business_rules: @business_rules
26
+ }
27
+ )
28
+
29
+ puts "✅ MCP Server initialized successfully with tools"
30
+ end
31
+
32
+ def get_codebase_context(class_name, method_name)
33
+ # Get rich context for a class and method
34
+ {
35
+ class_info: analyze_class(class_name),
36
+ method_info: analyze_method(class_name, method_name),
37
+ dependencies: find_dependencies(class_name),
38
+ business_context: get_business_context(class_name),
39
+ evolution_history: get_evolution_history(class_name, method_name),
40
+ similar_patterns: find_similar_patterns(class_name, method_name),
41
+ markdown_requirements: load_business_requirements_from_markdown
42
+ }
43
+ end
44
+
45
+ def analyze_error(error, context)
46
+ puts "🧠 MCP analyzing error: #{error.class} - #{error.message}"
47
+
48
+ # Extract class and method names from context
49
+ class_name = context[:class_name] || 'UnknownClass'
50
+ method_name = context[:method_name] || 'unknown_method'
51
+
52
+ # Use MCP tool to analyze error
53
+ if defined?(ErrorAnalysisTool)
54
+ result = ErrorAnalysisTool.call(
55
+ error_type: error.class.name,
56
+ error_message: error.message,
57
+ class_name: class_name,
58
+ method_name: method_name,
59
+ server_context: { codebase_context: context }
60
+ )
61
+
62
+ puts "✅ MCP analysis complete"
63
+ # Parse the JSON response from MCP tool
64
+ JSON.parse(result.content.first[:text])
65
+ else
66
+ puts "⚠️ ErrorAnalysisTool not available, using fallback analysis"
67
+ # Fallback analysis
68
+ {
69
+ severity: 'medium',
70
+ impact: 'moderate',
71
+ root_cause: 'division by zero',
72
+ suggested_fixes: ['add_zero_division_check', 'add_input_validation'],
73
+ risks: 'low'
74
+ }
75
+ end
76
+ end
77
+
78
+ def generate_contextual_fix(error, analysis, context)
79
+ puts "🧠 MCP generating contextual fix..."
80
+
81
+ # Extract class and method names from context
82
+ class_name = context[:class_name] || 'UnknownClass'
83
+ method_name = context[:method_name] || 'unknown_method'
84
+
85
+ puts "🔍 Debug: class_name = #{class_name}, method_name = #{method_name}"
86
+
87
+ # Use MCP tool to generate fix
88
+ if defined?(CodeFixTool)
89
+ result = CodeFixTool.call(
90
+ error_type: error.class.name,
91
+ error_message: error.message,
92
+ class_name: class_name,
93
+ method_name: method_name,
94
+ analysis: analysis,
95
+ context: context,
96
+ server_context: {
97
+ codebase_context: @codebase_context,
98
+ business_rules: @business_rules
99
+ }
100
+ )
101
+
102
+ puts "✅ MCP generated intelligent fix"
103
+ # Parse the JSON response from MCP tool
104
+ JSON.parse(result.content.first[:text])
105
+ else
106
+ puts "⚠️ CodeFixTool not available, using fallback fix generation"
107
+ # Fallback fix generation
108
+ generate_fallback_fix(error, class_name, method_name)
109
+ end
110
+ end
111
+
112
+ private
113
+
114
+ def generate_fallback_fix(error, class_name, method_name)
115
+ case error.class.name
116
+ when 'ZeroDivisionError'
117
+ {
118
+ fix_type: 'input_validation',
119
+ code: "def #{method_name}(a, b)\n return 0 if b == 0\n a / b\nend",
120
+ description: "Added zero division check",
121
+ risk_level: 'low'
122
+ }
123
+ when 'NoMethodError'
124
+ {
125
+ fix_type: 'nil_check',
126
+ code: "def #{method_name}(items)\n return 0 if items.nil? || items.empty?\n items.sum { |item| item[:price] * item[:quantity] }\nend",
127
+ description: "Added nil and empty checks",
128
+ risk_level: 'low'
129
+ }
130
+ else
131
+ {
132
+ fix_type: 'error_handling',
133
+ code: "def #{method_name}(*args)\n begin\n # Original implementation\n super\n rescue => e\n Rails.logger.error(\"Error in #{method_name}: \#{e.message}\")\n raise e\n end\nend",
134
+ description: "Added error handling wrapper",
135
+ risk_level: 'medium'
136
+ }
137
+ end
138
+ end
139
+
140
+ def load_codebase_context
141
+ business_context_file = Rails.root.join('config', 'business_context.yml')
142
+
143
+ if File.exist?(business_context_file)
144
+ YAML.load_file(business_context_file)
145
+ else
146
+ # Fallback to default context
147
+ {
148
+ project_type: 'Rails Application',
149
+ business_domain: 'Self-Evolving System',
150
+ coding_standards: {
151
+ error_handling: 'comprehensive',
152
+ logging: 'detailed',
153
+ validation: 'strict',
154
+ performance: 'optimized'
155
+ },
156
+ common_patterns: {
157
+ calculator_operations: {
158
+ divide: 'should handle zero division gracefully',
159
+ multiply: 'should handle overflow',
160
+ add: 'should handle type conversion'
161
+ }
162
+ }
163
+ }
164
+ end
165
+ end
166
+
167
+ def load_business_rules
168
+ # Load from YAML config
169
+ business_context_file = Rails.root.join('config', 'business_context.yml')
170
+ yaml_rules = {}
171
+
172
+ # Also load from business requirements documents
173
+ markdown_rules = load_business_requirements_from_markdown
174
+
175
+ # Prefer only markdown-derived requirements
176
+ yaml_rules.merge(markdown_rules)
177
+ end
178
+
179
+ def load_business_requirements_from_markdown
180
+ requirements = {}
181
+
182
+ # Look for business requirements in various locations
183
+ search_paths = [
184
+ 'business_requirements',
185
+ 'docs/business_requirements',
186
+ 'requirements',
187
+ 'docs/requirements'
188
+ ]
189
+
190
+ search_paths.each do |path|
191
+ if Dir.exist?(path)
192
+ Dir.glob("#{path}/**/*.md").each do |file|
193
+ content = File.read(file)
194
+ # Simply include the content without rigid pattern matching
195
+ requirements['markdown_requirements'] ||= []
196
+ requirements['markdown_requirements'] << {
197
+ file: file,
198
+ content: content.strip
199
+ }
200
+ end
201
+ end
202
+ end
203
+
204
+ requirements
205
+ end
206
+
207
+ def analyze_class(class_name)
208
+ {
209
+ name: class_name,
210
+ type: determine_class_type(class_name),
211
+ responsibilities: analyze_class_responsibilities(class_name),
212
+ complexity: calculate_class_complexity(class_name),
213
+ test_coverage: get_test_coverage(class_name),
214
+ documentation: get_documentation_status(class_name)
215
+ }
216
+ end
217
+
218
+ def analyze_method(class_name, method_name)
219
+ {
220
+ name: method_name,
221
+ signature: get_method_signature(class_name, method_name),
222
+ complexity: calculate_method_complexity(class_name, method_name),
223
+ usage_patterns: analyze_usage_patterns(class_name, method_name),
224
+ performance: analyze_performance_characteristics(class_name, method_name),
225
+ error_prone_areas: identify_error_prone_areas(class_name, method_name)
226
+ }
227
+ end
228
+
229
+ def find_dependencies(class_name)
230
+ {
231
+ models: find_model_dependencies(class_name),
232
+ services: find_service_dependencies(class_name),
233
+ external_apis: find_external_api_dependencies(class_name),
234
+ database: find_database_dependencies(class_name),
235
+ gems: find_gem_dependencies(class_name)
236
+ }
237
+ end
238
+
239
+ def get_business_context(class_name)
240
+ {
241
+ domain: determine_business_domain(class_name),
242
+ criticality: assess_business_criticality(class_name),
243
+ regulatory_requirements: identify_regulatory_requirements(class_name),
244
+ sla_requirements: get_sla_requirements(class_name),
245
+ user_impact: assess_user_impact(class_name)
246
+ }
247
+ end
248
+
249
+ def get_evolution_history(class_name, method_name)
250
+ {
251
+ previous_evolutions: get_previous_evolutions(class_name, method_name),
252
+ success_rate: calculate_evolution_success_rate(class_name, method_name),
253
+ common_patterns: identify_common_evolution_patterns(class_name, method_name),
254
+ performance_impact: analyze_historical_performance_impact(class_name, method_name)
255
+ }
256
+ end
257
+
258
+ def find_similar_patterns(class_name, method_name)
259
+ {
260
+ similar_methods: find_similar_methods(class_name, method_name),
261
+ similar_errors: find_similar_errors(class_name, method_name),
262
+ best_practices: find_best_practices(class_name, method_name),
263
+ anti_patterns: identify_anti_patterns(class_name, method_name)
264
+ }
265
+ end
266
+
267
+ # Helper methods (simplified for brevity)
268
+ def determine_class_type(class_name)
269
+ if class_name.include?('Controller')
270
+ 'controller'
271
+ elsif class_name.include?('Service')
272
+ 'service'
273
+ elsif class_name.include?('Model')
274
+ 'model'
275
+ else
276
+ 'utility'
277
+ end
278
+ end
279
+
280
+ def analyze_class_responsibilities(class_name)
281
+ ['data_processing', 'business_logic', 'error_handling']
282
+ end
283
+
284
+ def calculate_class_complexity(class_name)
285
+ rand(1..10)
286
+ end
287
+
288
+ def get_test_coverage(class_name)
289
+ rand(0..100)
290
+ end
291
+
292
+ def get_documentation_status(class_name)
293
+ ['well_documented', 'partially_documented', 'undocumented'].sample
294
+ end
295
+
296
+ def get_method_signature(class_name, method_name)
297
+ "def #{method_name}(*args, **kwargs, &block)"
298
+ end
299
+
300
+ def calculate_method_complexity(class_name, method_name)
301
+ rand(1..5)
302
+ end
303
+
304
+ def analyze_usage_patterns(class_name, method_name)
305
+ ['frequently_called', 'rarely_called', 'critical_path'].sample
306
+ end
307
+
308
+ def analyze_performance_characteristics(class_name, method_name)
309
+ ['fast', 'moderate', 'slow'].sample
310
+ end
311
+
312
+ def identify_error_prone_areas(class_name, method_name)
313
+ ['input_validation', 'external_dependencies', 'data_processing'].sample
314
+ end
315
+
316
+ def find_model_dependencies(class_name)
317
+ []
318
+ end
319
+
320
+ def find_service_dependencies(class_name)
321
+ []
322
+ end
323
+
324
+ def find_external_api_dependencies(class_name)
325
+ []
326
+ end
327
+
328
+ def find_database_dependencies(class_name)
329
+ []
330
+ end
331
+
332
+ def find_gem_dependencies(class_name)
333
+ []
334
+ end
335
+
336
+ def determine_business_domain(class_name)
337
+ ['finance', 'ecommerce', 'user_management', 'data_processing'].sample
338
+ end
339
+
340
+ def assess_business_criticality(class_name)
341
+ ['high', 'medium', 'low'].sample
342
+ end
343
+
344
+ def identify_regulatory_requirements(class_name)
345
+ []
346
+ end
347
+
348
+ def get_sla_requirements(class_name)
349
+ '99.9%'
350
+ end
351
+
352
+ def assess_user_impact(class_name)
353
+ ['high', 'medium', 'low'].sample
354
+ end
355
+
356
+ def get_previous_evolutions(class_name, method_name)
357
+ []
358
+ end
359
+
360
+ def calculate_evolution_success_rate(class_name, method_name)
361
+ rand(0.7..1.0)
362
+ end
363
+
364
+ def identify_common_evolution_patterns(class_name, method_name)
365
+ []
366
+ end
367
+
368
+ def analyze_historical_performance_impact(class_name, method_name)
369
+ 'improved'
370
+ end
371
+
372
+ def find_similar_methods(class_name, method_name)
373
+ []
374
+ end
375
+
376
+ def find_similar_errors(class_name, method_name)
377
+ []
378
+ end
379
+
380
+ def find_best_practices(class_name, method_name)
381
+ []
382
+ end
383
+
384
+ def identify_anti_patterns(class_name, method_name)
385
+ []
386
+ end
387
+ end
388
+ end
389
+ end