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,54 @@
|
|
1
|
+
module CodeHealer
|
2
|
+
# Business Rule Applier
|
3
|
+
# Simply provides business context to AI for natural language understanding
|
4
|
+
class BusinessRuleApplier
|
5
|
+
class << self
|
6
|
+
|
7
|
+
def apply_business_rules_to_code(business_analysis, original_code, error, class_name, method_name)
|
8
|
+
puts "đ§ Providing business context to AI..."
|
9
|
+
|
10
|
+
# Extract business context from the analysis
|
11
|
+
business_context = extract_business_context(business_analysis)
|
12
|
+
|
13
|
+
if business_context.any?
|
14
|
+
puts " đ Found business context: #{business_context.join(', ')}"
|
15
|
+
puts " đ¯ AI will understand and apply these business rules naturally"
|
16
|
+
|
17
|
+
# Simply return the original code - let the AI handle everything
|
18
|
+
# The AI will see the business context and apply it naturally
|
19
|
+
puts " â
Business context provided to AI - no code manipulation needed"
|
20
|
+
original_code
|
21
|
+
else
|
22
|
+
puts " âšī¸ No business context found"
|
23
|
+
original_code
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def extract_business_context(business_analysis)
|
30
|
+
context = []
|
31
|
+
|
32
|
+
# Extract from business rules
|
33
|
+
if business_analysis[:business_context][:business_rules]&.any?
|
34
|
+
business_analysis[:business_context][:business_rules].each do |rule|
|
35
|
+
context << rule[:content]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Extract from domain specific rules
|
40
|
+
if business_analysis[:business_context][:domain_specific]&.any?
|
41
|
+
business_analysis[:business_context][:domain_specific].each do |domain, rules|
|
42
|
+
if rules.is_a?(Array)
|
43
|
+
context.concat(rules)
|
44
|
+
elsif rules.is_a?(Hash)
|
45
|
+
context.concat(rules.values.map(&:to_s))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,224 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
require 'open3'
|
3
|
+
|
4
|
+
module CodeHealer
|
5
|
+
class ClaudeCodeEvolutionHandler
|
6
|
+
class << self
|
7
|
+
def handle_error_with_claude_code(error, class_name, method_name, file_path)
|
8
|
+
puts "đ¤ Claude Code Terminal Evolution Triggered!"
|
9
|
+
puts "Error: #{error.class} - #{error.message}"
|
10
|
+
puts "Class: #{class_name}, Method: #{method_name}"
|
11
|
+
puts "File: #{file_path}"
|
12
|
+
|
13
|
+
begin
|
14
|
+
# Build comprehensive prompt
|
15
|
+
prompt = BusinessContextManager.build_claude_code_prompt(
|
16
|
+
error, class_name, method_name, file_path
|
17
|
+
)
|
18
|
+
|
19
|
+
# Execute Claude Code command
|
20
|
+
success = execute_claude_code_fix(prompt, class_name, method_name)
|
21
|
+
|
22
|
+
if success
|
23
|
+
puts "â
Claude Code evolution completed successfully!"
|
24
|
+
# Reload modified files
|
25
|
+
reload_modified_files
|
26
|
+
|
27
|
+
# đ Trigger Git operations (commit, push, PR creation)
|
28
|
+
puts "đ Starting Git operations..."
|
29
|
+
trigger_git_operations(error, class_name, method_name, file_path)
|
30
|
+
|
31
|
+
return true
|
32
|
+
else
|
33
|
+
puts "â Claude Code evolution failed"
|
34
|
+
return false
|
35
|
+
end
|
36
|
+
|
37
|
+
rescue => e
|
38
|
+
puts "â Claude Code evolution error: #{e.message}"
|
39
|
+
puts e.backtrace.first(5)
|
40
|
+
return false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def execute_claude_code_fix(prompt, class_name, method_name)
|
47
|
+
config = ConfigManager.claude_code_settings
|
48
|
+
|
49
|
+
# Build command
|
50
|
+
command = build_claude_command(prompt, config)
|
51
|
+
|
52
|
+
puts "đ Executing Claude Code fix..."
|
53
|
+
puts "Command: #{command}"
|
54
|
+
puts "Timeout: #{config['timeout']} seconds"
|
55
|
+
|
56
|
+
begin
|
57
|
+
# Execute with timeout
|
58
|
+
Timeout.timeout(config['timeout']) do
|
59
|
+
stdout, stderr, status = Open3.capture3(command)
|
60
|
+
|
61
|
+
puts "đ¤ Claude Code Output:"
|
62
|
+
if stdout && !stdout.empty?
|
63
|
+
puts "â
Response received:"
|
64
|
+
puts stdout
|
65
|
+
|
66
|
+
# Check if Claude Code is asking for permission
|
67
|
+
if stdout.include?("permission") || stdout.include?("grant") || stdout.include?("edit")
|
68
|
+
puts "đ Claude Code needs permission to edit files"
|
69
|
+
puts "đĄ Make sure to grant Edit permissions when prompted"
|
70
|
+
end
|
71
|
+
|
72
|
+
# Check if fix was applied
|
73
|
+
if stdout.include?("fix") && (stdout.include?("applied") || stdout.include?("ready"))
|
74
|
+
puts "đ¯ Fix appears to be ready - checking if files were modified..."
|
75
|
+
end
|
76
|
+
else
|
77
|
+
puts "â ī¸ No output received from Claude Code"
|
78
|
+
end
|
79
|
+
|
80
|
+
if stderr && !stderr.empty?
|
81
|
+
puts "â ī¸ Claude Code Warnings/Errors:"
|
82
|
+
puts stderr
|
83
|
+
end
|
84
|
+
|
85
|
+
if status.success?
|
86
|
+
puts "â
Claude Code execution completed successfully"
|
87
|
+
return true
|
88
|
+
else
|
89
|
+
puts "â Claude Code execution failed with status: #{status.exitstatus}"
|
90
|
+
return false
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
rescue Timeout::Error
|
95
|
+
puts "â° Claude Code execution timed out after #{config['timeout']} seconds"
|
96
|
+
return false
|
97
|
+
rescue => e
|
98
|
+
puts "â Claude Code execution error: #{e.message}"
|
99
|
+
return false
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def build_claude_command(prompt, config)
|
104
|
+
# Escape prompt for shell
|
105
|
+
escaped_prompt = prompt.gsub("'", "'\"'\"'")
|
106
|
+
|
107
|
+
# Build command template
|
108
|
+
command_template = config['command_template'] || "claude --code '{prompt}'"
|
109
|
+
|
110
|
+
# Replace placeholder
|
111
|
+
command = command_template.gsub('{prompt}', escaped_prompt)
|
112
|
+
|
113
|
+
# Add additional options if configured
|
114
|
+
if config['include_tests']
|
115
|
+
command += " --append-system-prompt 'Include tests when fixing the code'"
|
116
|
+
end
|
117
|
+
|
118
|
+
if config['max_file_changes']
|
119
|
+
command += " --append-system-prompt 'Limit changes to #{config['max_file_changes']} files maximum'"
|
120
|
+
end
|
121
|
+
|
122
|
+
# Add file editing permissions
|
123
|
+
command += " --permission-mode acceptEdits --allowedTools Edit"
|
124
|
+
|
125
|
+
# Add current directory access
|
126
|
+
command += " --add-dir ."
|
127
|
+
|
128
|
+
command
|
129
|
+
end
|
130
|
+
|
131
|
+
def reload_modified_files
|
132
|
+
puts "đ Reloading modified files..."
|
133
|
+
|
134
|
+
# Get list of recently modified files (last 5 minutes)
|
135
|
+
recent_files = get_recently_modified_files
|
136
|
+
|
137
|
+
recent_files.each do |file_path|
|
138
|
+
if file_path.include?('/app/')
|
139
|
+
begin
|
140
|
+
load file_path
|
141
|
+
puts "â
Reloaded: #{file_path}"
|
142
|
+
rescue => e
|
143
|
+
puts "â ī¸ Failed to reload #{file_path}: #{e.message}"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
puts "đ File reloading completed"
|
149
|
+
end
|
150
|
+
|
151
|
+
def get_recently_modified_files
|
152
|
+
# Get files modified in the last 5 minutes
|
153
|
+
cutoff_time = Time.now - 300 # 5 minutes ago
|
154
|
+
|
155
|
+
files = []
|
156
|
+
Dir.glob('**/*.rb').each do |file|
|
157
|
+
if File.mtime(file) > cutoff_time
|
158
|
+
files << file
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
files.sort_by { |f| File.mtime(f) }.reverse
|
163
|
+
end
|
164
|
+
|
165
|
+
def log_evolution_attempt(error, class_name, method_name, success)
|
166
|
+
log_entry = {
|
167
|
+
timestamp: Time.now.iso8601,
|
168
|
+
method: 'claude_code_terminal',
|
169
|
+
error_type: error.class.name,
|
170
|
+
error_message: error.message,
|
171
|
+
class_name: class_name,
|
172
|
+
method_name: method_name,
|
173
|
+
success: success,
|
174
|
+
execution_time: Time.now
|
175
|
+
}
|
176
|
+
|
177
|
+
# Log to file
|
178
|
+
log_file = 'log/claude_code_evolution.log'
|
179
|
+
FileUtils.mkdir_p(File.dirname(log_file))
|
180
|
+
|
181
|
+
File.open(log_file, 'a') do |f|
|
182
|
+
f.puts(log_entry.to_json)
|
183
|
+
end
|
184
|
+
|
185
|
+
puts "đ Evolution attempt logged to #{log_file}"
|
186
|
+
end
|
187
|
+
|
188
|
+
def trigger_git_operations(error, class_name, method_name, file_path)
|
189
|
+
puts "đ Triggering Git operations for Claude Code evolution..."
|
190
|
+
|
191
|
+
begin
|
192
|
+
# Use the existing SimpleEvolution Git operations
|
193
|
+
require_relative 'simple_evolution'
|
194
|
+
|
195
|
+
# Create a mock business context for Git operations
|
196
|
+
business_context = {
|
197
|
+
error_type: error.class.name,
|
198
|
+
error_message: error.message,
|
199
|
+
class_name: class_name,
|
200
|
+
method_name: method_name
|
201
|
+
}
|
202
|
+
|
203
|
+
# Trigger the Git operations through SimpleEvolution
|
204
|
+
git_success = CodeHealer::SimpleEvolution.handle_git_operations_for_claude(
|
205
|
+
error, class_name, method_name, file_path
|
206
|
+
)
|
207
|
+
|
208
|
+
if git_success
|
209
|
+
puts "â
Git operations completed successfully!"
|
210
|
+
puts " - Branch created and committed"
|
211
|
+
puts " - Changes pushed to remote"
|
212
|
+
puts " - Pull request created"
|
213
|
+
else
|
214
|
+
puts "â Git operations failed"
|
215
|
+
end
|
216
|
+
|
217
|
+
rescue => e
|
218
|
+
puts "â Error during Git operations: #{e.message}"
|
219
|
+
puts "đĄ You may need to manually commit and create PR"
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module CodeHealer
|
2
|
+
class ClaudeErrorMonitor
|
3
|
+
def self.monitor_and_fix(error, context = {})
|
4
|
+
# Send error to Claude API for analysis and fix
|
5
|
+
claude_response = send_to_claude({
|
6
|
+
error: {
|
7
|
+
type: error.class.name,
|
8
|
+
message: error.message,
|
9
|
+
backtrace: error.backtrace&.first(5)
|
10
|
+
},
|
11
|
+
context: context,
|
12
|
+
request_type: 'error_analysis_and_fix'
|
13
|
+
})
|
14
|
+
|
15
|
+
# Apply fix if Claude provides one
|
16
|
+
if claude_response[:fix_available]
|
17
|
+
apply_automated_fix(claude_response[:fix])
|
18
|
+
end
|
19
|
+
|
20
|
+
claude_response
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def self.send_to_claude(payload)
|
26
|
+
# Integration with Claude API
|
27
|
+
# This would use your preferred method to communicate with Claude
|
28
|
+
# Options:
|
29
|
+
# 1. Direct API calls to Claude
|
30
|
+
# 2. MCP server integration
|
31
|
+
# 3. WebSocket connection
|
32
|
+
# 4. File-based communication
|
33
|
+
|
34
|
+
{
|
35
|
+
analysis: "Error analyzed",
|
36
|
+
fix_available: false,
|
37
|
+
suggested_fix: nil,
|
38
|
+
user_message: "Something is wrong with your order data"
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.apply_automated_fix(fix)
|
43
|
+
# Only apply safe, non-breaking fixes automatically
|
44
|
+
# Log all changes for review
|
45
|
+
Rails.logger.info "Claude applied automated fix: #{fix}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,275 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
module CodeHealer
|
5
|
+
class ConfigManager
|
6
|
+
class << self
|
7
|
+
def config
|
8
|
+
@config ||= load_config
|
9
|
+
end
|
10
|
+
|
11
|
+
def reload_config
|
12
|
+
@config = load_config
|
13
|
+
end
|
14
|
+
|
15
|
+
def enabled?
|
16
|
+
config['enabled'] == true
|
17
|
+
end
|
18
|
+
|
19
|
+
def require_approval?
|
20
|
+
config['require_approval'] == true
|
21
|
+
end
|
22
|
+
|
23
|
+
def auto_create_pr?
|
24
|
+
# Use only the nested pull_request configuration for consistency
|
25
|
+
config.dig('pull_request', 'auto_create') == true ||
|
26
|
+
config.dig('pull_request', 'enabled') == true
|
27
|
+
end
|
28
|
+
|
29
|
+
def auto_generate_tests?
|
30
|
+
config['auto_generate_tests'] == true
|
31
|
+
end
|
32
|
+
|
33
|
+
def allowed_error_types
|
34
|
+
config['allowed_error_types'] || []
|
35
|
+
end
|
36
|
+
|
37
|
+
def allowed_classes
|
38
|
+
config['allowed_classes'] || []
|
39
|
+
end
|
40
|
+
|
41
|
+
def excluded_classes
|
42
|
+
config['excluded_classes'] || []
|
43
|
+
end
|
44
|
+
|
45
|
+
def can_evolve_class?(class_name)
|
46
|
+
return false unless enabled?
|
47
|
+
return false if excluded_classes.include?(class_name)
|
48
|
+
return true if allowed_classes.empty?
|
49
|
+
allowed_classes.include?(class_name)
|
50
|
+
end
|
51
|
+
|
52
|
+
def can_handle_error?(error)
|
53
|
+
return false unless enabled?
|
54
|
+
allowed_error_types.include?(error.class.name)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Evolution Strategy Configuration
|
58
|
+
def evolution_strategy
|
59
|
+
config['evolution_strategy'] || {}
|
60
|
+
end
|
61
|
+
|
62
|
+
def evolution_method
|
63
|
+
evolution_strategy['method'] || 'api'
|
64
|
+
end
|
65
|
+
|
66
|
+
def claude_code_enabled?
|
67
|
+
evolution_method == 'claude_code_terminal' &&
|
68
|
+
config.dig('claude_code', 'enabled') == true
|
69
|
+
end
|
70
|
+
|
71
|
+
def api_enabled?
|
72
|
+
evolution_method == 'api' ||
|
73
|
+
(evolution_method == 'hybrid' && config.dig('api', 'enabled') != false)
|
74
|
+
end
|
75
|
+
|
76
|
+
def fallback_to_api?
|
77
|
+
evolution_strategy['fallback_to_api'] == true
|
78
|
+
end
|
79
|
+
|
80
|
+
# Claude Code Configuration
|
81
|
+
def claude_code_settings
|
82
|
+
config['claude_code'] || {}
|
83
|
+
end
|
84
|
+
|
85
|
+
# Business Context Configuration
|
86
|
+
def business_context_enabled?
|
87
|
+
config.dig('business_context', 'enabled') == true
|
88
|
+
end
|
89
|
+
|
90
|
+
def business_context_settings
|
91
|
+
config['business_context'] || {}
|
92
|
+
end
|
93
|
+
|
94
|
+
# API Configuration
|
95
|
+
def api_settings
|
96
|
+
config['api'] || {}
|
97
|
+
end
|
98
|
+
|
99
|
+
def git_settings
|
100
|
+
config['git'] || {}
|
101
|
+
end
|
102
|
+
|
103
|
+
def pull_request_settings
|
104
|
+
config['pull_request'] || {}
|
105
|
+
end
|
106
|
+
|
107
|
+
def notification_settings
|
108
|
+
config['notifications'] || {}
|
109
|
+
end
|
110
|
+
|
111
|
+
def safety_settings
|
112
|
+
config['safety'] || {}
|
113
|
+
end
|
114
|
+
|
115
|
+
def evolution_patterns
|
116
|
+
config['evolution_patterns'] || {}
|
117
|
+
end
|
118
|
+
|
119
|
+
def get_evolution_pattern(error_type)
|
120
|
+
evolution_patterns[error_type.to_s]
|
121
|
+
end
|
122
|
+
|
123
|
+
def max_evolutions_per_day
|
124
|
+
config['max_evolutions_per_day'] || 10
|
125
|
+
end
|
126
|
+
|
127
|
+
# Enhanced Git Configuration Methods
|
128
|
+
def branch_prefix
|
129
|
+
git_settings['branch_prefix'] || 'evolve'
|
130
|
+
end
|
131
|
+
|
132
|
+
def pr_target_branch
|
133
|
+
git_settings['pr_target_branch'] || 'main'
|
134
|
+
end
|
135
|
+
|
136
|
+
def commit_message_template
|
137
|
+
git_settings['commit_message_template'] || 'Fix {class_name}##{method_name}: {error_type}'
|
138
|
+
end
|
139
|
+
|
140
|
+
def auto_commit?
|
141
|
+
git_settings['auto_commit'] != false
|
142
|
+
end
|
143
|
+
|
144
|
+
def auto_push?
|
145
|
+
git_settings['auto_push'] != false
|
146
|
+
end
|
147
|
+
|
148
|
+
# Enhanced Safety Configuration Methods
|
149
|
+
def backup_before_evolution?
|
150
|
+
safety_settings['backup_before_evolution'] != false
|
151
|
+
end
|
152
|
+
|
153
|
+
def rollback_on_syntax_error?
|
154
|
+
safety_settings['rollback_on_syntax_error'] != false
|
155
|
+
end
|
156
|
+
|
157
|
+
# Enhanced Pull Request Configuration Methods
|
158
|
+
def pull_request_enabled?
|
159
|
+
pull_request_settings['enabled'] != false
|
160
|
+
end
|
161
|
+
|
162
|
+
def auto_create_pr?
|
163
|
+
pull_request_settings['auto_create'] == true
|
164
|
+
end
|
165
|
+
|
166
|
+
def pr_labels
|
167
|
+
pull_request_settings['labels'] || ['auto-fix', 'self-evolving', 'bug-fix']
|
168
|
+
end
|
169
|
+
|
170
|
+
# Enhanced Claude Code Configuration Methods
|
171
|
+
def claude_code_timeout
|
172
|
+
claude_code_settings['timeout'] || 300
|
173
|
+
end
|
174
|
+
|
175
|
+
def claude_code_max_file_changes
|
176
|
+
claude_code_settings['max_file_changes'] || 10
|
177
|
+
end
|
178
|
+
|
179
|
+
def claude_code_include_tests?
|
180
|
+
claude_code_settings['include_tests'] != false
|
181
|
+
end
|
182
|
+
|
183
|
+
def claude_code_command_template
|
184
|
+
claude_code_settings['command_template'] || "claude --print '{prompt}' --output-format text"
|
185
|
+
end
|
186
|
+
|
187
|
+
private
|
188
|
+
|
189
|
+
def load_config
|
190
|
+
# Try to find config file in current directory or parent directories
|
191
|
+
config_path = find_config_file
|
192
|
+
|
193
|
+
if config_path && File.exist?(config_path)
|
194
|
+
YAML.load(ERB.new(File.read(config_path)).result)
|
195
|
+
else
|
196
|
+
default_config
|
197
|
+
end
|
198
|
+
rescue => e
|
199
|
+
puts "Failed to load code-healer config: #{e.message}" if defined?(Rails)
|
200
|
+
default_config
|
201
|
+
end
|
202
|
+
|
203
|
+
def find_config_file
|
204
|
+
# Look for config file in current directory and parent directories
|
205
|
+
current_dir = Dir.pwd
|
206
|
+
max_depth = 5
|
207
|
+
|
208
|
+
max_depth.times do |depth|
|
209
|
+
config_path = File.join(current_dir, 'config', 'code_healer.yml')
|
210
|
+
return config_path if File.exist?(config_path)
|
211
|
+
|
212
|
+
# Go up one directory
|
213
|
+
current_dir = File.dirname(current_dir)
|
214
|
+
break if current_dir == '/'
|
215
|
+
end
|
216
|
+
|
217
|
+
nil
|
218
|
+
end
|
219
|
+
|
220
|
+
def default_config
|
221
|
+
{
|
222
|
+
'enabled' => true,
|
223
|
+
'require_approval' => false,
|
224
|
+
'max_evolutions_per_day' => 10,
|
225
|
+
'auto_generate_tests' => true,
|
226
|
+
'allowed_error_types' => ['ZeroDivisionError', 'NoMethodError', 'ArgumentError', 'TypeError'],
|
227
|
+
'allowed_classes' => ['User', 'Order', 'PaymentProcessor'],
|
228
|
+
'excluded_classes' => ['ApplicationController', 'ApplicationRecord', 'ApplicationJob', 'ApplicationMailer'],
|
229
|
+
'evolution_strategy' => {
|
230
|
+
'method' => 'api',
|
231
|
+
'fallback_to_api' => true
|
232
|
+
},
|
233
|
+
'claude_code' => {
|
234
|
+
'enabled' => false,
|
235
|
+
'timeout' => 300,
|
236
|
+
'max_file_changes' => 10,
|
237
|
+
'include_tests' => true,
|
238
|
+
'command_template' => "claude --print '{prompt}' --output-format text --permission-mode acceptEdits --allowedTools Edit",
|
239
|
+
'business_context_sources' => [
|
240
|
+
'config/business_rules.yml',
|
241
|
+
'docs/business_logic.md',
|
242
|
+
'spec/business_context_specs.rb'
|
243
|
+
]
|
244
|
+
},
|
245
|
+
'business_context' => {
|
246
|
+
'enabled' => true,
|
247
|
+
'sources' => ['docs/business_rules.md']
|
248
|
+
},
|
249
|
+
'api' => {
|
250
|
+
'provider' => 'openai',
|
251
|
+
'model' => 'gpt-4',
|
252
|
+
'max_tokens' => 2000,
|
253
|
+
'temperature' => 0.1
|
254
|
+
},
|
255
|
+
'git' => {
|
256
|
+
'auto_commit' => true,
|
257
|
+
'auto_push' => true,
|
258
|
+
'branch_prefix' => 'evolve',
|
259
|
+
'commit_message_template' => 'Fix {class_name}##{method_name}: {error_type}',
|
260
|
+
'pr_target_branch' => 'main'
|
261
|
+
},
|
262
|
+
'pull_request' => {
|
263
|
+
'enabled' => true,
|
264
|
+
'auto_create' => true,
|
265
|
+
'labels' => ['auto-fix', 'self-evolving', 'bug-fix']
|
266
|
+
},
|
267
|
+
'safety' => {
|
268
|
+
'backup_before_evolution' => true,
|
269
|
+
'rollback_on_syntax_error' => true
|
270
|
+
}
|
271
|
+
}
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|