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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +70 -0
- data/GEM_SUMMARY.md +307 -0
- data/README.md +281 -0
- data/code_healer.gemspec +77 -0
- data/config/code_healer.yml.example +104 -0
- data/docs/INSTALLATION.md +439 -0
- data/examples/basic_usage.rb +160 -0
- data/exe/code_healer-setup +7 -0
- data/lib/code_healer/application_job.rb +7 -0
- data/lib/code_healer/business_context_analyzer.rb +464 -0
- data/lib/code_healer/business_context_loader.rb +273 -0
- data/lib/code_healer/business_context_manager.rb +297 -0
- data/lib/code_healer/business_logic_generator.rb +94 -0
- data/lib/code_healer/business_rule_applier.rb +54 -0
- data/lib/code_healer/claude_code_evolution_handler.rb +224 -0
- data/lib/code_healer/claude_error_monitor.rb +48 -0
- data/lib/code_healer/config_manager.rb +275 -0
- data/lib/code_healer/context_aware_prompt_builder.rb +153 -0
- data/lib/code_healer/core.rb +513 -0
- data/lib/code_healer/error_handler.rb +141 -0
- data/lib/code_healer/evolution_job.rb +99 -0
- data/lib/code_healer/global_handler.rb +130 -0
- data/lib/code_healer/healing_job.rb +167 -0
- data/lib/code_healer/mcp.rb +108 -0
- data/lib/code_healer/mcp_prompts.rb +111 -0
- data/lib/code_healer/mcp_server.rb +389 -0
- data/lib/code_healer/mcp_tools.rb +2364 -0
- data/lib/code_healer/pull_request_creator.rb +143 -0
- data/lib/code_healer/setup.rb +390 -0
- data/lib/code_healer/simple_evolution.rb +737 -0
- data/lib/code_healer/simple_global_handler.rb +122 -0
- data/lib/code_healer/simple_healer.rb +515 -0
- data/lib/code_healer/terminal_integration.rb +87 -0
- data/lib/code_healer/usage_analyzer.rb +92 -0
- data/lib/code_healer/version.rb +5 -0
- data/lib/code_healer.rb +67 -0
- metadata +411 -0
@@ -0,0 +1,273 @@
|
|
1
|
+
module CodeHealer
|
2
|
+
# Dynamic Business Context Loader for Large Applications
|
3
|
+
# Intelligently loads and provides business context for any class/method
|
4
|
+
class BusinessContextLoader
|
5
|
+
class << self
|
6
|
+
def load_context_for_class(class_name)
|
7
|
+
context = load_base_context
|
8
|
+
domain_context = find_domain_for_class(class_name)
|
9
|
+
|
10
|
+
if domain_context
|
11
|
+
context.merge!(domain_context)
|
12
|
+
context[:class_specific] = load_class_specific_context(class_name, domain_context)
|
13
|
+
end
|
14
|
+
|
15
|
+
context
|
16
|
+
end
|
17
|
+
|
18
|
+
def load_context_for_method(class_name, method_name)
|
19
|
+
class_context = load_context_for_class(class_name)
|
20
|
+
method_context = load_method_specific_context(class_name, method_name, class_context)
|
21
|
+
|
22
|
+
class_context.merge!(method_context)
|
23
|
+
end
|
24
|
+
|
25
|
+
def find_domain_for_class(class_name)
|
26
|
+
domains = load_domains_from_config
|
27
|
+
|
28
|
+
# Direct class match
|
29
|
+
domains.each do |domain_name, domain_config|
|
30
|
+
if domain_config['classes']&.key?(class_name)
|
31
|
+
return {
|
32
|
+
domain: domain_name,
|
33
|
+
domain_config: domain_config,
|
34
|
+
class_config: domain_config['classes'][class_name]
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Pattern matching for similar classes
|
40
|
+
domains.each do |domain_name, domain_config|
|
41
|
+
if matches_domain_pattern?(class_name, domain_name)
|
42
|
+
return {
|
43
|
+
domain: domain_name,
|
44
|
+
domain_config: domain_config,
|
45
|
+
class_config: infer_class_config(class_name, domain_config)
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Default domain based on class name patterns
|
51
|
+
default_domain = infer_default_domain(class_name)
|
52
|
+
if default_domain && domains[default_domain]
|
53
|
+
return {
|
54
|
+
domain: default_domain,
|
55
|
+
domain_config: domains[default_domain],
|
56
|
+
class_config: infer_class_config(class_name, domains[default_domain])
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
nil
|
61
|
+
end
|
62
|
+
|
63
|
+
def load_method_specific_context(class_name, method_name, class_context)
|
64
|
+
return {} unless class_context[:class_config]
|
65
|
+
|
66
|
+
method_config = class_context[:class_config]['methods']&.dig(method_name)
|
67
|
+
|
68
|
+
if method_config
|
69
|
+
{
|
70
|
+
method_specific: method_config,
|
71
|
+
error_handling: method_config['error_handling'],
|
72
|
+
logging: method_config['logging'],
|
73
|
+
return_values: method_config['return_values']
|
74
|
+
}
|
75
|
+
else
|
76
|
+
# Infer method context based on method name patterns
|
77
|
+
infer_method_context(method_name, class_context)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def load_base_context
|
84
|
+
business_context_file = Rails.root.join('config', 'business_context.yml')
|
85
|
+
|
86
|
+
if File.exist?(business_context_file)
|
87
|
+
YAML.load_file(business_context_file)
|
88
|
+
else
|
89
|
+
default_context
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def load_domains_from_config
|
94
|
+
context = load_base_context
|
95
|
+
context['domains'] || {}
|
96
|
+
end
|
97
|
+
|
98
|
+
def load_class_specific_context(class_name, domain_context)
|
99
|
+
domain_context[:class_config] || infer_class_config(class_name, domain_context[:domain_config])
|
100
|
+
end
|
101
|
+
|
102
|
+
def matches_domain_pattern?(class_name, domain_name)
|
103
|
+
patterns = {
|
104
|
+
'user_management' => /User|Session|Auth|Profile/,
|
105
|
+
'inventory_management' => /Product|Inventory|Stock|Catalog/,
|
106
|
+
'order_management' => /Order|Cart|Checkout|Fulfillment/,
|
107
|
+
'payment_processing' => /Payment|Transaction|Gateway|Refund/,
|
108
|
+
'analytics_reporting' => /Analytics|Report|Metrics|Dashboard/
|
109
|
+
}
|
110
|
+
|
111
|
+
pattern = patterns[domain_name]
|
112
|
+
pattern&.match?(class_name)
|
113
|
+
end
|
114
|
+
|
115
|
+
def infer_default_domain(class_name)
|
116
|
+
case class_name
|
117
|
+
when /User|Session|Auth/
|
118
|
+
'user_management'
|
119
|
+
when /Product|Inventory|Stock/
|
120
|
+
'inventory_management'
|
121
|
+
when /Order|Cart|Checkout/
|
122
|
+
'order_management'
|
123
|
+
when /Payment|Transaction/
|
124
|
+
'payment_processing'
|
125
|
+
when /Analytics|Report|Metrics/
|
126
|
+
'analytics_reporting'
|
127
|
+
else
|
128
|
+
'general'
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def infer_class_config(class_name, domain_config)
|
133
|
+
{
|
134
|
+
'description' => "Auto-inferred configuration for #{class_name}",
|
135
|
+
'business_criticality' => domain_config['criticality'] || 'medium',
|
136
|
+
'data_privacy' => domain_config['data_sensitivity'] || 'standard',
|
137
|
+
'methods' => infer_methods_for_class(class_name, domain_config)
|
138
|
+
}
|
139
|
+
end
|
140
|
+
|
141
|
+
def infer_methods_for_class(class_name, domain_config)
|
142
|
+
# Common method patterns by domain
|
143
|
+
patterns = {
|
144
|
+
'user_management' => {
|
145
|
+
'authenticate' => {
|
146
|
+
'description' => 'User authentication',
|
147
|
+
'error_handling' => 'secure_fallback',
|
148
|
+
'logging' => 'security_audit'
|
149
|
+
},
|
150
|
+
'update_profile' => {
|
151
|
+
'description' => 'Update user profile',
|
152
|
+
'error_handling' => 'validation_errors',
|
153
|
+
'logging' => 'audit_trail'
|
154
|
+
}
|
155
|
+
},
|
156
|
+
'inventory_management' => {
|
157
|
+
'update_stock' => {
|
158
|
+
'description' => 'Update inventory stock',
|
159
|
+
'error_handling' => 'stock_validation',
|
160
|
+
'logging' => 'inventory_audit'
|
161
|
+
},
|
162
|
+
'calculate_availability' => {
|
163
|
+
'description' => 'Calculate product availability',
|
164
|
+
'error_handling' => 'graceful_fallback',
|
165
|
+
'logging' => 'inventory_metrics'
|
166
|
+
}
|
167
|
+
},
|
168
|
+
'order_management' => {
|
169
|
+
'process_payment' => {
|
170
|
+
'description' => 'Process order payment',
|
171
|
+
'error_handling' => 'payment_failure',
|
172
|
+
'logging' => 'payment_audit'
|
173
|
+
},
|
174
|
+
'update_status' => {
|
175
|
+
'description' => 'Update order status',
|
176
|
+
'error_handling' => 'status_validation',
|
177
|
+
'logging' => 'order_audit'
|
178
|
+
}
|
179
|
+
}
|
180
|
+
}
|
181
|
+
|
182
|
+
domain_name = domain_config['description']&.downcase&.gsub(/\s+/, '_')
|
183
|
+
patterns[domain_name] || {}
|
184
|
+
end
|
185
|
+
|
186
|
+
def infer_method_context(method_name, class_context)
|
187
|
+
# Infer based on method name patterns
|
188
|
+
case method_name.to_s
|
189
|
+
when /authenticate|login/
|
190
|
+
{
|
191
|
+
method_specific: {
|
192
|
+
'description' => 'Authentication method',
|
193
|
+
'error_handling' => 'secure_fallback',
|
194
|
+
'logging' => 'security_audit',
|
195
|
+
'return_values' => {
|
196
|
+
'success' => 'user_object',
|
197
|
+
'failure' => 'nil_with_logging'
|
198
|
+
}
|
199
|
+
}
|
200
|
+
}
|
201
|
+
when /update|save/
|
202
|
+
{
|
203
|
+
method_specific: {
|
204
|
+
'description' => 'Update method',
|
205
|
+
'error_handling' => 'validation_errors',
|
206
|
+
'logging' => 'audit_trail',
|
207
|
+
'return_values' => {
|
208
|
+
'success' => 'boolean',
|
209
|
+
'validation_failed' => 'errors_hash'
|
210
|
+
}
|
211
|
+
}
|
212
|
+
}
|
213
|
+
when /calculate|compute/
|
214
|
+
{
|
215
|
+
method_specific: {
|
216
|
+
'description' => 'Calculation method',
|
217
|
+
'error_handling' => 'calculation_error',
|
218
|
+
'logging' => 'metrics',
|
219
|
+
'return_values' => {
|
220
|
+
'success' => 'numeric_result',
|
221
|
+
'error' => 'nil_or_default'
|
222
|
+
}
|
223
|
+
}
|
224
|
+
}
|
225
|
+
when /process|execute/
|
226
|
+
{
|
227
|
+
method_specific: {
|
228
|
+
'description' => 'Processing method',
|
229
|
+
'error_handling' => 'process_failure',
|
230
|
+
'logging' => 'process_audit',
|
231
|
+
'return_values' => {
|
232
|
+
'success' => 'result_object',
|
233
|
+
'failure' => 'error_object'
|
234
|
+
}
|
235
|
+
}
|
236
|
+
}
|
237
|
+
else
|
238
|
+
{
|
239
|
+
method_specific: {
|
240
|
+
'description' => "Auto-inferred method: #{method_name}",
|
241
|
+
'error_handling' => 'graceful_handling',
|
242
|
+
'logging' => 'info',
|
243
|
+
'return_values' => {
|
244
|
+
'success' => 'method_result',
|
245
|
+
'error' => 'nil_or_default'
|
246
|
+
}
|
247
|
+
}
|
248
|
+
}
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
def default_context
|
253
|
+
{
|
254
|
+
'project' => {
|
255
|
+
'type' => 'Rails Application',
|
256
|
+
'business_domain' => 'General Application',
|
257
|
+
'description' => 'Default business context'
|
258
|
+
},
|
259
|
+
'coding_standards' => {
|
260
|
+
'error_handling' => 'comprehensive',
|
261
|
+
'logging' => 'structured',
|
262
|
+
'validation' => 'strict',
|
263
|
+
'performance' => 'optimized',
|
264
|
+
'security' => 'high'
|
265
|
+
},
|
266
|
+
'business_rules' => {
|
267
|
+
# Structured error_resolution removed in favor of markdown requirements
|
268
|
+
}
|
269
|
+
}
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
@@ -0,0 +1,297 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module CodeHealer
|
5
|
+
class BusinessContextManager
|
6
|
+
class << self
|
7
|
+
def get_context_for_error(error, class_name, method_name)
|
8
|
+
return {} unless ConfigManager.business_context_enabled?
|
9
|
+
|
10
|
+
# Load business context from markdown files (same as Claude Code)
|
11
|
+
markdown_context = load_business_context_from_markdown_simple
|
12
|
+
|
13
|
+
context = {
|
14
|
+
class_context: get_class_business_context(class_name),
|
15
|
+
method_context: get_method_business_context(class_name, method_name),
|
16
|
+
error_context: get_error_context(error),
|
17
|
+
related_context: get_related_context(class_name, method_name),
|
18
|
+
domain_patterns: get_domain_patterns(class_name),
|
19
|
+
markdown_requirements: markdown_context # Add markdown content
|
20
|
+
}
|
21
|
+
|
22
|
+
context.compact
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_class_business_context(class_name)
|
26
|
+
business_context = ConfigManager.business_context_settings
|
27
|
+
|
28
|
+
# Extract class-specific context
|
29
|
+
class_context = business_context[class_name] || {}
|
30
|
+
|
31
|
+
# Add domain information
|
32
|
+
domain_info = {
|
33
|
+
domain: class_context['domain'] || 'General Business Logic',
|
34
|
+
key_rules: class_context['key_rules'] || [],
|
35
|
+
validation_patterns: class_context['validation_patterns'] || []
|
36
|
+
}
|
37
|
+
|
38
|
+
domain_info
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_method_business_context(class_name, method_name)
|
42
|
+
# Method-specific business rules
|
43
|
+
method_rules = {
|
44
|
+
'calculate_discount' => {
|
45
|
+
rules: ['Discount cannot exceed 50% of subtotal', 'VIP customers get maximum 15%'],
|
46
|
+
constraints: ['Positive amounts only', 'Valid customer tier required']
|
47
|
+
},
|
48
|
+
'process_order' => {
|
49
|
+
rules: ['Orders must have valid items', 'Customer validation required'],
|
50
|
+
constraints: ['Positive quantities', 'Valid payment method']
|
51
|
+
},
|
52
|
+
'validate_payment' => {
|
53
|
+
rules: ['Card number must be valid', 'Expiry date must be future'],
|
54
|
+
constraints: ['Valid CVV format', 'Supported payment method']
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
method_rules[method_name] || {}
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_error_context(error)
|
62
|
+
{
|
63
|
+
type: error.class.name,
|
64
|
+
message: error.message,
|
65
|
+
common_causes: get_common_error_causes(error.class),
|
66
|
+
suggested_fixes: get_suggested_fixes(error.class)
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
def get_common_error_causes(error_class)
|
71
|
+
causes = {
|
72
|
+
'ArgumentError' => [
|
73
|
+
'Invalid parameter types',
|
74
|
+
'Missing required parameters',
|
75
|
+
'Parameter validation failed'
|
76
|
+
],
|
77
|
+
'NoMethodError' => [
|
78
|
+
'Method not defined',
|
79
|
+
'Incorrect method name',
|
80
|
+
'Missing method implementation'
|
81
|
+
],
|
82
|
+
'TypeError' => [
|
83
|
+
'Incompatible data types',
|
84
|
+
'Nil value where object expected',
|
85
|
+
'Type conversion failed'
|
86
|
+
],
|
87
|
+
'NameError' => [
|
88
|
+
'Undefined variable or constant',
|
89
|
+
'Scope issue with variable',
|
90
|
+
'Missing import or require'
|
91
|
+
]
|
92
|
+
}
|
93
|
+
|
94
|
+
causes[error_class.name] || ['Unknown error cause']
|
95
|
+
end
|
96
|
+
|
97
|
+
def get_suggested_fixes(error_class)
|
98
|
+
fixes = {
|
99
|
+
'ArgumentError' => [
|
100
|
+
'Add parameter validation',
|
101
|
+
'Check parameter types',
|
102
|
+
'Provide default values'
|
103
|
+
],
|
104
|
+
'NoMethodError' => [
|
105
|
+
'Implement missing method',
|
106
|
+
'Check method spelling',
|
107
|
+
'Verify method exists in parent class'
|
108
|
+
],
|
109
|
+
'TypeError' => [
|
110
|
+
'Add type checking',
|
111
|
+
'Handle nil values',
|
112
|
+
'Convert types appropriately'
|
113
|
+
],
|
114
|
+
'NameError' => [
|
115
|
+
'Define missing variable',
|
116
|
+
'Check variable scope',
|
117
|
+
'Add missing imports'
|
118
|
+
]
|
119
|
+
}
|
120
|
+
|
121
|
+
fixes[error_class.name] || ['Review error and implement appropriate fix']
|
122
|
+
end
|
123
|
+
|
124
|
+
def get_related_context(class_name, method_name)
|
125
|
+
# Find related classes and methods
|
126
|
+
related = {
|
127
|
+
'OrderProcessor' => ['User', 'Payment', 'Inventory'],
|
128
|
+
'User' => ['Order', 'Profile', 'Authentication'],
|
129
|
+
'OrderProcessorV2' => ['OrderProcessor', 'AdvancedValidation', 'BusinessRules']
|
130
|
+
}
|
131
|
+
|
132
|
+
{
|
133
|
+
related_classes: related[class_name] || [],
|
134
|
+
related_methods: get_related_methods(method_name),
|
135
|
+
dependencies: get_class_dependencies(class_name)
|
136
|
+
}
|
137
|
+
end
|
138
|
+
|
139
|
+
def get_related_methods(method_name)
|
140
|
+
# Method relationships
|
141
|
+
relationships = {
|
142
|
+
'calculate_discount' => ['validate_customer', 'calculate_loyalty_points', 'apply_coupon'],
|
143
|
+
'process_order' => ['validate_inventory', 'process_payment', 'send_confirmation'],
|
144
|
+
'validate_payment' => ['validate_card', 'check_balance', 'process_transaction']
|
145
|
+
}
|
146
|
+
|
147
|
+
relationships[method_name] || []
|
148
|
+
end
|
149
|
+
|
150
|
+
def get_class_dependencies(class_name)
|
151
|
+
# Class dependencies
|
152
|
+
dependencies = {
|
153
|
+
'OrderProcessor' => ['User', 'Payment', 'Inventory'],
|
154
|
+
'User' => ['Order', 'Profile'],
|
155
|
+
'OrderProcessorV2' => ['OrderProcessor', 'AdvancedValidation']
|
156
|
+
}
|
157
|
+
|
158
|
+
dependencies[class_name] || []
|
159
|
+
end
|
160
|
+
|
161
|
+
def get_domain_patterns(class_name)
|
162
|
+
# Domain-specific patterns
|
163
|
+
patterns = {
|
164
|
+
'OrderProcessor' => {
|
165
|
+
validation_pattern: 'Input validation → Business rule check → Processing → Result',
|
166
|
+
error_handling: 'Graceful degradation with meaningful error messages',
|
167
|
+
logging: 'Comprehensive logging for debugging and monitoring'
|
168
|
+
},
|
169
|
+
'User' => {
|
170
|
+
validation_pattern: 'Data validation → Security check → Database operation → Response',
|
171
|
+
error_handling: 'User-friendly error messages with guidance',
|
172
|
+
logging: 'Security-focused logging without sensitive data'
|
173
|
+
}
|
174
|
+
}
|
175
|
+
|
176
|
+
patterns[class_name] || {}
|
177
|
+
end
|
178
|
+
|
179
|
+
def build_claude_code_prompt(error, class_name, method_name, file_path)
|
180
|
+
# Load business context from markdown files
|
181
|
+
business_context = load_business_context_from_markdown_simple
|
182
|
+
|
183
|
+
prompt = <<~PROMPT
|
184
|
+
I have a Ruby on Rails application with an error that needs fixing.
|
185
|
+
|
186
|
+
## Error Details:
|
187
|
+
- **Type:** #{error.class.name}
|
188
|
+
- **Message:** #{error.message}
|
189
|
+
- **Class:** #{class_name}
|
190
|
+
- **Method:** #{method_name}
|
191
|
+
- **File:** #{file_path}
|
192
|
+
|
193
|
+
## Complete Backtrace (for root cause analysis):
|
194
|
+
```
|
195
|
+
#{error.backtrace&.join("\n") || "No backtrace available"}
|
196
|
+
```
|
197
|
+
|
198
|
+
## Business Context (from requirements):
|
199
|
+
#{business_context}
|
200
|
+
|
201
|
+
## Instructions:
|
202
|
+
Please:
|
203
|
+
1. Analyze the error and understand the root cause
|
204
|
+
2. **IMPORTANT: Check if the fix requires changes to multiple files or if the root cause is in a different file**
|
205
|
+
3. Fix the issue considering the business rules above
|
206
|
+
4. Ensure the fix doesn't break other functionality
|
207
|
+
5. Follow Rails conventions and patterns
|
208
|
+
6. Make sure to write testcases for the fix
|
209
|
+
|
210
|
+
## IMPORTANT: Full Codebase Access & Multi-File Fixes
|
211
|
+
You have permission to edit ANY files in the codebase. Please:
|
212
|
+
- **Don't limit yourself to just the file where the error occurred**
|
213
|
+
- **Check related files, dependencies, and the broader codebase**
|
214
|
+
- **If the fix requires multiple file changes, make ALL necessary changes**
|
215
|
+
- **Look for root causes that might be in different files**
|
216
|
+
- **Edit any file that needs to be modified to resolve the issue completely**
|
217
|
+
- Ensure the fix follows business rules and validation patterns
|
218
|
+
|
219
|
+
## Multi-File Fix Strategy:
|
220
|
+
- **Analyze the complete backtrace above** to understand the full error chain
|
221
|
+
- **Start from the bottom of the backtrace** (where the error originated)
|
222
|
+
- **Work your way up** to see how the error propagated through different files
|
223
|
+
- **Identify ALL files in the call stack** that need modification
|
224
|
+
- **Look for the root cause** - it might be in a different file than where the error was caught
|
225
|
+
- **Make comprehensive changes** across the codebase if needed
|
226
|
+
- **Don't just patch the symptom** - fix the underlying issue
|
227
|
+
- **Check each file in the backtrace** for potential fixes
|
228
|
+
|
229
|
+
Use your full codebase access to provide the best solution.
|
230
|
+
PROMPT
|
231
|
+
|
232
|
+
prompt.strip
|
233
|
+
end
|
234
|
+
|
235
|
+
def build_api_prompt(error, class_name, method_name, file_path)
|
236
|
+
context = get_context_for_error(error, class_name, method_name)
|
237
|
+
|
238
|
+
prompt = <<~PROMPT
|
239
|
+
Fix this Ruby on Rails error:
|
240
|
+
|
241
|
+
Error: #{context[:error_context][:type]} - #{context[:error_context][:message]}
|
242
|
+
Class: #{class_name}
|
243
|
+
Method: #{method_name}
|
244
|
+
File: #{file_path}
|
245
|
+
|
246
|
+
Business Context:
|
247
|
+
- Domain: #{context[:class_context][:domain]}
|
248
|
+
- Key Rules: #{context[:class_context][:key_rules].join("; ")}
|
249
|
+
- Validation: #{context[:class_context][:validation_patterns].join("; ")}
|
250
|
+
|
251
|
+
Method Rules: #{context[:method_context][:rules]&.join("; ") || "None"}
|
252
|
+
|
253
|
+
Common Causes: #{context[:error_context][:common_causes].join("; ")}
|
254
|
+
Suggested Fixes: #{context[:error_context][:suggested_fixes].join("; ")}
|
255
|
+
|
256
|
+
## Business Requirements (from markdown):
|
257
|
+
#{context[:markdown_requirements]}
|
258
|
+
|
259
|
+
Provide a production-ready fix that handles the error gracefully while maintaining business logic integrity.
|
260
|
+
PROMPT
|
261
|
+
|
262
|
+
prompt.strip
|
263
|
+
end
|
264
|
+
|
265
|
+
private
|
266
|
+
|
267
|
+
def load_business_context_from_markdown_simple
|
268
|
+
# Look for business requirements in the docs directory (created by setup script)
|
269
|
+
docs_path = 'docs'
|
270
|
+
business_rules_path = 'docs/business_rules.md'
|
271
|
+
|
272
|
+
# First try the specific business_rules.md file
|
273
|
+
if File.exist?(business_rules_path)
|
274
|
+
content = File.read(business_rules_path)
|
275
|
+
puts "📋 Loaded business context from: #{business_rules_path}"
|
276
|
+
return content.strip
|
277
|
+
end
|
278
|
+
|
279
|
+
# Fallback: look for any markdown files in docs directory
|
280
|
+
if Dir.exist?(docs_path)
|
281
|
+
markdown_files = Dir.glob("#{docs_path}/**/*.md")
|
282
|
+
|
283
|
+
if markdown_files.any?
|
284
|
+
# Load the first markdown file
|
285
|
+
content = File.read(markdown_files.first)
|
286
|
+
puts "📋 Loaded business context from: #{markdown_files.first}"
|
287
|
+
return content.strip
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
# Fallback to basic business context
|
292
|
+
puts "⚠️ No business context markdown files found, using fallback"
|
293
|
+
return "Follow standard business logic and error handling practices."
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module CodeHealer
|
2
|
+
class BusinessLogicGenerator
|
3
|
+
class << self
|
4
|
+
def generate_from_description(description, target_class, method_name)
|
5
|
+
new(description, target_class, method_name).generate
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :description, :target_class, :method_name, :logger
|
10
|
+
|
11
|
+
def initialize(description, target_class, method_name)
|
12
|
+
@description = description
|
13
|
+
@target_class = target_class
|
14
|
+
@method_name = method_name
|
15
|
+
@logger = Logger.new(Rails.root.join('log', 'self_evolving.log'))
|
16
|
+
end
|
17
|
+
|
18
|
+
def generate
|
19
|
+
return false unless valid_description?
|
20
|
+
|
21
|
+
begin
|
22
|
+
method_definition = generate_method_definition
|
23
|
+
return false unless valid_method?(method_definition)
|
24
|
+
|
25
|
+
success = Core.evolve_method(target_class, method_name, {
|
26
|
+
description: description,
|
27
|
+
generated_at: Time.current
|
28
|
+
})
|
29
|
+
|
30
|
+
if success
|
31
|
+
log_successful_generation
|
32
|
+
true
|
33
|
+
else
|
34
|
+
log_failed_generation
|
35
|
+
false
|
36
|
+
end
|
37
|
+
rescue => e
|
38
|
+
logger.error("Business logic generation failed: #{e.message}")
|
39
|
+
false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def valid_description?
|
46
|
+
# Implement your validation logic here
|
47
|
+
# For example: minimum length, required keywords, etc.
|
48
|
+
description.present? && description.length >= 10
|
49
|
+
end
|
50
|
+
|
51
|
+
def generate_method_definition
|
52
|
+
# This is where you'd integrate with your AI system
|
53
|
+
# For now, we'll return a simple placeholder
|
54
|
+
<<~RUBY
|
55
|
+
def #{method_name}
|
56
|
+
# Generated from description: #{description}
|
57
|
+
# TODO: Implement actual business logic
|
58
|
+
true
|
59
|
+
end
|
60
|
+
RUBY
|
61
|
+
end
|
62
|
+
|
63
|
+
def valid_method?(method)
|
64
|
+
# Basic syntax validation
|
65
|
+
begin
|
66
|
+
RubyVM::InstructionSequence.compile(method)
|
67
|
+
true
|
68
|
+
rescue SyntaxError => e
|
69
|
+
logger.error("Invalid method syntax: #{e.message}")
|
70
|
+
false
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def log_successful_generation
|
75
|
+
logger.info({
|
76
|
+
timestamp: Time.current,
|
77
|
+
event: 'successful_generation',
|
78
|
+
class: target_class.name,
|
79
|
+
method: method_name,
|
80
|
+
description: description
|
81
|
+
}.to_json)
|
82
|
+
end
|
83
|
+
|
84
|
+
def log_failed_generation
|
85
|
+
logger.info({
|
86
|
+
timestamp: Time.current,
|
87
|
+
event: 'failed_generation',
|
88
|
+
class: target_class.name,
|
89
|
+
method: method_name,
|
90
|
+
description: description
|
91
|
+
}.to_json)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|