code_healer 0.1.24 → 0.1.32

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.
@@ -1,20 +1,18 @@
1
1
  require 'fileutils'
2
2
  require 'securerandom'
3
+ require_relative 'presentation_logger'
3
4
 
4
5
  module CodeHealer
5
6
  # Manages isolated healing workspaces for safe code evolution
6
7
  class HealingWorkspaceManager
7
8
  class << self
8
9
  def create_healing_workspace(repo_path, branch_name = nil)
9
- puts "🏥 [WORKSPACE] Starting workspace creation..."
10
- puts "🏥 [WORKSPACE] Repo path: #{repo_path}"
11
- puts "🏥 [WORKSPACE] Target branch: #{branch_name || 'default'}"
10
+ PresentationLogger.workspace_action("Preparing isolated workspace")
11
+ PresentationLogger.detail("Repo: #{repo_path}")
12
+ PresentationLogger.detail("Target branch: #{branch_name || 'default'}")
12
13
 
13
14
  config = CodeHealer::ConfigManager.code_heal_directory_config
14
- puts "🏥 [WORKSPACE] Raw config: #{config.inspect}"
15
-
16
15
  base_path = config['path'] || config[:path] || '/tmp/code_healer_workspaces'
17
- puts "🏥 [WORKSPACE] Base heal dir: #{base_path}"
18
16
 
19
17
  # Use persistent workspace ID based on repo (if enabled)
20
18
  if CodeHealer::ConfigManager.persistent_workspaces_enabled?
@@ -28,82 +26,79 @@ module CodeHealer
28
26
  end
29
27
 
30
28
  if CodeHealer::ConfigManager.persistent_workspaces_enabled?
31
- puts "🏥 [WORKSPACE] Persistent workspace ID: #{workspace_id}"
29
+ PresentationLogger.detail("Using persistent workspace: #{workspace_id}")
32
30
  else
33
- puts "🏥 [WORKSPACE] Temporary workspace ID: #{workspace_id}"
31
+ PresentationLogger.detail("Creating temporary workspace: #{workspace_id}")
34
32
  end
35
- puts "🏥 [WORKSPACE] Full workspace path: #{workspace_path}"
36
33
 
37
34
  begin
38
- puts "🏥 [WORKSPACE] Creating base directory..."
39
35
  # Ensure code heal directory exists
40
36
  FileUtils.mkdir_p(base_path)
41
- puts "🏥 [WORKSPACE] Base directory created/verified: #{base_path}"
42
37
 
43
38
  # Check if workspace already exists
44
39
  if Dir.exist?(workspace_path) && Dir.exist?(File.join(workspace_path, '.git'))
45
40
  if CodeHealer::ConfigManager.persistent_workspaces_enabled?
46
- puts "🏥 [WORKSPACE] Persistent workspace exists, checking out to target branch..."
41
+ PresentationLogger.detail("Reusing existing workspace, checking out target branch")
47
42
  checkout_to_branch(workspace_path, branch_name, repo_path)
48
43
  else
49
- puts "🏥 [WORKSPACE] Workspace exists but persistent mode disabled, creating new one..."
44
+ PresentationLogger.detail("Recreating workspace (persistent mode disabled)")
50
45
  cleanup_workspace(workspace_path, true)
51
46
  create_persistent_workspace(repo_path, workspace_path, branch_name)
52
47
  end
53
48
  else
54
- puts "🏥 [WORKSPACE] Creating new workspace..."
49
+ PresentationLogger.detail("Creating new workspace")
55
50
  create_persistent_workspace(repo_path, workspace_path, branch_name)
56
51
  end
57
52
 
58
- puts "🏥 [WORKSPACE] Workspace ready successfully!"
59
- puts "🏥 [WORKSPACE] Final workspace path: #{workspace_path}"
60
- puts "🏥 [WORKSPACE] Current branch: #{get_current_branch(workspace_path)}"
53
+ PresentationLogger.success("Workspace ready")
54
+ PresentationLogger.detail("Path: #{workspace_path}")
55
+ PresentationLogger.detail("Branch: #{get_current_branch(workspace_path)}")
61
56
  workspace_path
62
57
  rescue => e
63
- puts "Failed to create/prepare healing workspace: #{e.message}"
58
+ PresentationLogger.error("Failed to create workspace: #{e.message}")
64
59
  # Don't cleanup persistent workspace on error
65
60
  raise e
66
61
  end
67
62
  end
68
63
 
69
64
  def apply_fixes_in_workspace(workspace_path, fixes, class_name, method_name)
70
- puts "🔧 [WORKSPACE] Starting fix application..."
71
- puts "🔧 [WORKSPACE] Workspace: #{workspace_path}"
72
- puts "🔧 [WORKSPACE] Class: #{class_name}, Method: #{method_name}"
73
- puts "🔧 [WORKSPACE] Fixes to apply: #{fixes.inspect}"
65
+ PresentationLogger.detail("Starting fix application...")
66
+ PresentationLogger.detail("Workspace: #{workspace_path}")
67
+ PresentationLogger.detail("Class: #{class_name}, Method: #{method_name}")
68
+ PresentationLogger.detail("Fixes to apply: #{fixes.inspect}")
74
69
 
75
70
  begin
76
- puts "🔧 [WORKSPACE] Processing #{fixes.length} fixes..."
71
+ PresentationLogger.detail("Processing #{fixes.length} fixes...")
77
72
  # Apply each fix to the workspace
78
73
  fixes.each_with_index do |fix, index|
79
- puts "🔧 [WORKSPACE] Processing fix #{index + 1}: #{fix.inspect}"
74
+ PresentationLogger.detail("Processing fix #{index + 1}: #{fix.inspect}")
80
75
  file_path = File.join(workspace_path, fix[:file_path])
81
- puts "🔧 [WORKSPACE] Target file: #{file_path}"
82
- puts "🔧 [WORKSPACE] File exists: #{File.exist?(file_path)}"
76
+ PresentationLogger.detail("Target file: #{file_path}")
77
+ PresentationLogger.detail("File exists: #{File.exist?(file_path)}")
83
78
 
84
79
  next unless File.exist?(file_path)
85
80
 
86
- puts "🔧 [WORKSPACE] Creating backup..."
81
+ PresentationLogger.detail("Creating backup...")
87
82
  # Backup original file
88
83
  backup_file(file_path)
89
84
 
90
- puts "🔧 [WORKSPACE] Applying fix to file..."
85
+ PresentationLogger.detail("Applying fix to file...")
91
86
  # Apply the fix
92
87
  apply_fix_to_file(file_path, fix[:new_code], class_name, method_name)
93
88
  end
94
89
 
95
90
  # Show workspace Git status after applying fixes
96
91
  Dir.chdir(workspace_path) do
97
- puts "🔧 [WORKSPACE] Git status after fixes:"
92
+ PresentationLogger.detail("Git status after fixes:")
98
93
  system("git status --porcelain")
99
- puts "🔧 [WORKSPACE] Git diff after fixes:"
94
+ PresentationLogger.detail("Git diff after fixes:")
100
95
  system("git diff")
101
96
  end
102
97
 
103
- puts "Fixes applied successfully in workspace"
98
+ PresentationLogger.success("Fixes applied successfully in workspace")
104
99
  true
105
100
  rescue => e
106
- puts "Failed to apply fixes in workspace: #{e.message}"
101
+ PresentationLogger.error("Failed to apply fixes in workspace: #{e.message}")
107
102
  false
108
103
  end
109
104
  end
@@ -111,42 +106,47 @@ module CodeHealer
111
106
  def test_fixes_in_workspace(workspace_path)
112
107
  config = CodeHealer::ConfigManager.code_heal_directory_config
113
108
 
114
- puts "🧪 Testing fixes in workspace: #{workspace_path}"
109
+ PresentationLogger.step("Validating fixes")
115
110
 
116
111
  begin
117
112
  # Change to workspace directory
118
113
  Dir.chdir(workspace_path) do
119
114
  # Run basic syntax check
120
115
  syntax_check = system("ruby -c #{find_ruby_files.join(' ')} 2>/dev/null")
121
- return false unless syntax_check
116
+ unless syntax_check
117
+ PresentationLogger.error("Syntax validation failed")
118
+ return false
119
+ end
122
120
 
123
- # Optionally skip heavy tests in demo mode
124
- unless CodeHealer::ConfigManager.demo_skip_tests?
121
+ # Run tests if available
125
122
  # Run tests if available
126
123
  if File.exist?('Gemfile')
127
124
  bundle_check = system("bundle check >/dev/null 2>&1")
128
- return false unless bundle_check
125
+ unless bundle_check
126
+ PresentationLogger.error("Bundle check failed")
127
+ return false
128
+ end
129
129
 
130
130
  # Run tests if RSpec is available
131
131
  if File.exist?('spec') || File.exist?('test')
132
132
  test_result = system("bundle exec rspec --dry-run >/dev/null 2>&1") ||
133
133
  system("bundle exec rake test:prepare >/dev/null 2>&1")
134
- puts "🧪 Test preparation: #{test_result ? '' : '⚠️'}"
134
+ PresentationLogger.detail("Test preparation: #{test_result ? 'passed' : 'skipped'}")
135
135
  end
136
136
  end
137
137
  end
138
138
 
139
- puts " Workspace validation passed"
139
+ PresentationLogger.success("Validation passed")
140
140
  true
141
141
  end
142
142
  rescue => e
143
- puts " Workspace validation failed: #{e.message}"
143
+ PresentationLogger.error("Validation failed: #{e.message}")
144
144
  false
145
145
  end
146
146
  end
147
147
 
148
148
  def validate_workspace_for_commit(workspace_path)
149
- puts "🔍 [WORKSPACE] Validating workspace for commit..."
149
+ PresentationLogger.detail("Validating workspace for commit...")
150
150
 
151
151
  Dir.chdir(workspace_path) do
152
152
  # Check for any temporary files that might have been added
@@ -155,44 +155,42 @@ module CodeHealer
155
155
 
156
156
  all_files = (staged_files + working_files).uniq.reject(&:empty?)
157
157
 
158
- puts "🔍 [WORKSPACE] Files to be committed: #{all_files.join(', ')}"
158
+ PresentationLogger.detail("Files to be committed: #{all_files.join(', ')}")
159
159
 
160
160
  # Check for any temporary files
161
161
  temp_files = all_files.select { |file| should_skip_file?(file) }
162
162
 
163
163
  if temp_files.any?
164
- puts "⚠️ [WORKSPACE] WARNING: Temporary files detected in commit:"
165
- temp_files.each { |file| puts " - #{file}" }
164
+ PresentationLogger.warn("Temporary files detected in commit:")
165
+ temp_files.each { |file| PresentationLogger.detail(" - #{file}") }
166
166
 
167
167
  # Remove them from staging
168
168
  temp_files.each do |file|
169
- puts "🗑️ [WORKSPACE] Removing temporary file from staging: #{file}"
169
+ PresentationLogger.detail("Removing temporary file from staging: #{file}")
170
170
  system("git reset HEAD '#{file}' 2>/dev/null || true")
171
171
  end
172
172
 
173
- puts "🔍 [WORKSPACE] Temporary files removed from staging"
173
+ PresentationLogger.detail("Temporary files removed from staging")
174
174
  return false
175
175
  end
176
176
 
177
- puts "✅ [WORKSPACE] Workspace validation passed - no temporary files detected"
177
+ PresentationLogger.detail("Workspace validation passed - no temporary files detected")
178
178
  return true
179
179
  end
180
180
  rescue => e
181
- puts "❌ [WORKSPACE] Workspace validation failed: #{e.message}"
181
+ PresentationLogger.error("Workspace validation failed: #{e.message}")
182
182
  return false
183
183
  end
184
184
 
185
185
  def create_healing_branch(repo_path, workspace_path, branch_name)
186
- puts "🔄 Creating healing branch and PR from isolated workspace"
186
+ PresentationLogger.git_action("Creating healing branch and PR")
187
187
 
188
188
  begin
189
189
  # All Git operations happen in the isolated workspace
190
190
  Dir.chdir(workspace_path) do
191
- puts "🌿 [WORKSPACE] Working in isolated workspace: #{workspace_path}"
192
-
193
- # Debug Git configuration
194
- puts "🌿 [WORKSPACE] Git remote origin: #{`git config --get remote.origin.url`.strip}"
195
- puts "🌿 [WORKSPACE] Current branch: #{`git branch --show-current`.strip}"
191
+ PresentationLogger.detail("Working in isolated workspace")
192
+ PresentationLogger.detail("Remote: #{`git config --get remote.origin.url`.strip}")
193
+ PresentationLogger.detail("Current branch: #{`git branch --show-current`.strip}")
196
194
 
197
195
  # Ensure we're on the target branch
198
196
  system("git checkout #{branch_name}")
@@ -202,94 +200,80 @@ module CodeHealer
202
200
  healing_branch = "code-healer-fix-#{Time.now.to_i}"
203
201
  system("git checkout -b #{healing_branch}")
204
202
 
205
- # Check Git status
206
- puts "📊 [WORKSPACE] Git status in workspace:"
207
- system("git status --porcelain")
208
-
209
203
  # Add all changes (the fixes are already applied in the workspace)
210
204
  add_only_relevant_files(workspace_path)
211
205
 
212
206
  # Validate workspace before commit to ensure no temporary files
213
207
  unless validate_workspace_for_commit(workspace_path)
214
- puts "⚠️ [WORKSPACE] Workspace validation failed, retrying file addition..."
208
+ PresentationLogger.detail("Retrying file addition after validation")
215
209
  add_only_relevant_files(workspace_path)
216
210
  end
217
211
 
218
212
  # Check if there are changes to commit
219
213
  if system("git diff --cached --quiet") == false
220
- puts "📝 [WORKSPACE] Changes detected, committing to healing branch..."
214
+ PresentationLogger.detail("Committing changes to healing branch")
221
215
  commit_message = "Fix applied by CodeHealer: #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}"
222
216
  system("git commit -m '#{commit_message}'")
223
217
 
224
218
  # Push healing branch from workspace
225
- puts "🚀 [WORKSPACE] Pushing healing branch from workspace..."
219
+ PresentationLogger.detail("Pushing healing branch")
226
220
  system("git push origin #{healing_branch}")
227
221
 
228
- puts " [WORKSPACE] Healing branch created and pushed: #{healing_branch}"
229
- puts "🔒 Main repository (#{repo_path}) remains completely untouched"
230
- puts "📝 All changes committed in isolated workspace"
222
+ PresentationLogger.success("Branch created and pushed: #{healing_branch}")
223
+ PresentationLogger.detail("Main repository remains untouched")
231
224
 
232
- # Create pull request if auto-create is enabled
233
- if should_create_pull_request?
234
- puts "🔍 [WORKSPACE] Auto-creating pull request..."
235
- pr_url = create_pull_request(healing_branch, branch_name)
236
- if pr_url
237
- puts "✅ [WORKSPACE] Pull request created: #{pr_url}"
238
- else
239
- puts "⚠️ [WORKSPACE] Failed to create pull request"
240
- end
241
- else
242
- puts "🔍 [WORKSPACE] Review the changes and create a pull request when ready"
243
- end
225
+ # Create pull request if auto-create is enabled
226
+ if should_create_pull_request?
227
+ PresentationLogger.detail("Creating pull request")
228
+ pr_url = create_pull_request(healing_branch, branch_name)
229
+ if pr_url
230
+ PresentationLogger.success("Pull request created: #{pr_url}")
231
+ else
232
+ PresentationLogger.warn("Failed to create pull request")
233
+ end
234
+ else
235
+ PresentationLogger.info("Review changes and create PR when ready")
236
+ end
244
237
 
245
238
  healing_branch
246
239
  else
247
- puts "⚠️ [WORKSPACE] No changes detected in workspace"
248
- puts "🔍 This might indicate that:"
249
- puts " - The fixes were not applied to the workspace"
250
- puts " - There was an issue with the healing process"
240
+ PresentationLogger.warn("No changes detected in workspace")
241
+ PresentationLogger.detail("This might indicate fixes were not applied or there was an issue")
251
242
 
252
243
  # Delete the empty branch
253
244
  system("git checkout #{branch_name}")
254
245
  system("git branch -D #{healing_branch}")
255
- puts "🗑️ [WORKSPACE] Deleted empty healing branch: #{healing_branch}"
246
+ PresentationLogger.detail("Deleted empty healing branch: #{healing_branch}")
256
247
  nil
257
248
  end
258
249
  end
259
250
  rescue => e
260
- puts "Failed to create healing branch from workspace: #{e.message}"
251
+ PresentationLogger.error("Failed to create healing branch: #{e.message}")
261
252
  nil
262
253
  end
263
254
  end
264
255
 
265
256
  def cleanup_workspace(workspace_path, force = false)
266
- puts "🧹 [WORKSPACE] Starting workspace cleanup..."
267
- puts "🧹 [WORKSPACE] Target: #{workspace_path}"
268
- puts "🧹 [WORKSPACE] Force cleanup: #{force}"
269
- puts "🧹 [WORKSPACE] Exists: #{Dir.exist?(workspace_path)}"
270
-
271
257
  return unless Dir.exist?(workspace_path)
272
258
 
273
259
  # Check if this is a persistent workspace
274
260
  is_persistent = workspace_path.include?('persistent_')
275
261
 
276
262
  if is_persistent && !force
277
- puts "🧹 [WORKSPACE] This is a persistent workspace - skipping cleanup"
278
- puts "🧹 [WORKSPACE] Use force=true to override"
263
+ PresentationLogger.detail("Skipping cleanup of persistent workspace")
279
264
  return
280
265
  end
281
266
 
267
+ PresentationLogger.detail("Cleaning up workspace")
268
+
282
269
  # Remove .git directory first to avoid conflicts
283
270
  git_dir = File.join(workspace_path, '.git')
284
271
  if Dir.exist?(git_dir)
285
- puts "🧹 [WORKSPACE] Removing .git directory to prevent conflicts..."
286
272
  FileUtils.rm_rf(git_dir)
287
273
  end
288
274
 
289
- puts "🧹 [WORKSPACE] Removing workspace directory..."
290
275
  FileUtils.rm_rf(workspace_path)
291
- puts "🧹 [WORKSPACE] Workspace cleanup completed"
292
- puts "🧹 [WORKSPACE] Directory still exists: #{Dir.exist?(workspace_path)}"
276
+ PresentationLogger.detail("Workspace cleanup completed")
293
277
  end
294
278
 
295
279
  def cleanup_expired_workspaces
@@ -348,7 +332,23 @@ module CodeHealer
348
332
 
349
333
  puts "🔗 Creating PR for repository: #{repo_name}"
350
334
 
351
- client = Octokit::Client.new(access_token: github_token)
335
+ # Configure Octokit with better error handling
336
+ client = Octokit::Client.new(
337
+ access_token: github_token,
338
+ api_endpoint: 'https://api.github.com',
339
+ web_endpoint: 'https://github.com',
340
+ auto_paginate: true,
341
+ per_page: 100
342
+ )
343
+
344
+ # Test the connection first
345
+ begin
346
+ user = client.user
347
+ puts "✅ GitHub authentication successful for user: #{user.login}"
348
+ rescue => auth_error
349
+ puts "❌ GitHub authentication failed: #{auth_error.message}"
350
+ return nil
351
+ end
352
352
 
353
353
  # Create pull request
354
354
  pr = client.create_pull_request(
@@ -363,8 +363,21 @@ module CodeHealer
363
363
 
364
364
  puts "✅ Pull request created successfully: #{pr.html_url}"
365
365
  pr.html_url
366
+ rescue Octokit::Unauthorized => e
367
+ puts "❌ GitHub authentication failed: #{e.message}"
368
+ puts "💡 Check your GitHub token permissions and validity"
369
+ nil
370
+ rescue Octokit::NotFound => e
371
+ puts "❌ Repository not found: #{e.message}"
372
+ puts "💡 Check repository name and access permissions"
373
+ nil
374
+ rescue Octokit::UnprocessableEntity => e
375
+ puts "❌ Invalid pull request data: #{e.message}"
376
+ puts "💡 Check branch names and repository state"
377
+ nil
366
378
  rescue => e
367
379
  puts "❌ Failed to create pull request: #{e.message}"
380
+ puts "💡 Error class: #{e.class}"
368
381
  puts "💡 Check your GitHub token and repository access"
369
382
  nil
370
383
  end
@@ -413,66 +426,66 @@ module CodeHealer
413
426
  end
414
427
 
415
428
  def create_persistent_workspace(repo_path, workspace_path, branch_name)
416
- puts "🏥 [WORKSPACE] Creating new persistent workspace..."
429
+ PresentationLogger.detail("Creating new persistent workspace...")
417
430
 
418
431
  # Get the GitHub remote URL
419
432
  Dir.chdir(repo_path) do
420
433
  remote_url = `git config --get remote.origin.url`.strip
421
434
  if remote_url.empty?
422
- puts "❌ [WORKSPACE] No remote origin found in #{repo_path}"
435
+ PresentationLogger.error("No remote origin found in #{repo_path}")
423
436
  return false
424
437
  end
425
438
 
426
- puts "🏥 [WORKSPACE] Cloning from: #{remote_url}"
427
- puts "🏥 [WORKSPACE] To workspace: #{workspace_path}"
439
+ PresentationLogger.detail("Cloning from: #{remote_url}")
440
+ PresentationLogger.detail("To workspace: #{workspace_path}")
428
441
 
429
442
  # Clone the full repository for persistent use
430
443
  result = system("git clone #{remote_url} #{workspace_path}")
431
444
  if result
432
- puts "🏥 [WORKSPACE] Repository cloned successfully"
445
+ PresentationLogger.detail("Repository cloned successfully")
433
446
  # Now checkout to the target branch
434
447
  checkout_to_branch(workspace_path, branch_name, repo_path)
435
448
  else
436
- puts "❌ [WORKSPACE] Failed to clone repository"
449
+ PresentationLogger.error("Failed to clone repository")
437
450
  return false
438
451
  end
439
452
  end
440
453
  end
441
454
 
442
455
  def checkout_to_branch(workspace_path, branch_name, repo_path)
443
- puts "🏥 [WORKSPACE] Checking out to target branch..."
456
+ PresentationLogger.detail("Checking out to target branch...")
444
457
 
445
458
  # Determine target branch
446
459
  target_branch = branch_name || CodeHealer::ConfigManager.pr_target_branch || get_default_branch(repo_path)
447
- puts "🏥 [WORKSPACE] Target branch: #{target_branch}"
460
+ PresentationLogger.detail("Target branch: #{target_branch}")
448
461
 
449
462
  Dir.chdir(workspace_path) do
450
463
  # Fetch latest changes
451
- puts "🏥 [WORKSPACE] Fetching latest changes..."
464
+ PresentationLogger.detail("Fetching latest changes...")
452
465
  system("git fetch origin")
453
466
 
454
467
  # Check if branch exists locally
455
468
  local_branch_exists = system("git show-ref --verify --quiet refs/heads/#{target_branch}")
456
469
 
457
470
  if local_branch_exists
458
- puts "🏥 [WORKSPACE] Checking out existing local branch: #{target_branch}"
471
+ PresentationLogger.detail("Checking out existing local branch: #{target_branch}")
459
472
  system("git checkout #{target_branch}")
460
473
  else
461
- puts "🏥 [WORKSPACE] Checking out remote branch: #{target_branch}"
474
+ PresentationLogger.detail("Checking out remote branch: #{target_branch}")
462
475
  system("git checkout -b #{target_branch} origin/#{target_branch}")
463
476
  end
464
477
 
465
478
  # Pull latest changes
466
- puts "🏥 [WORKSPACE] Pulling latest changes..."
479
+ PresentationLogger.detail("Pulling latest changes...")
467
480
  system("git pull origin #{target_branch}")
468
481
 
469
482
  # Ensure workspace is clean
470
- puts "🏥 [WORKSPACE] Ensuring workspace is clean..."
483
+ PresentationLogger.detail("Ensuring workspace is clean...")
471
484
  system("git reset --hard HEAD")
472
485
  system("git clean -fd")
473
486
 
474
487
  # Remove any tracked temporary files that shouldn't be committed - AGGRESSIVE cleanup
475
- puts "🏥 [WORKSPACE] Removing tracked temporary files..."
488
+ PresentationLogger.detail("Removing tracked temporary files...")
476
489
 
477
490
  # Remove root level temporary directories
478
491
  system("git rm -r --cached tmp/ 2>/dev/null || true")
@@ -492,7 +505,7 @@ module CodeHealer
492
505
  system("find . -name '*.log' -exec git rm --cached {} + 2>/dev/null || true")
493
506
  system("find . -name '*.cache' -exec git rm --cached {} + 2>/dev/null || true")
494
507
 
495
- puts "🏥 [WORKSPACE] Successfully checked out to: #{target_branch}"
508
+ PresentationLogger.detail("Successfully checked out to: #{target_branch}")
496
509
  end
497
510
  end
498
511
 
@@ -518,25 +531,26 @@ module CodeHealer
518
531
  end
519
532
 
520
533
  def add_only_relevant_files(workspace_path)
521
- puts "📁 [WORKSPACE] Adding only relevant files, respecting .gitignore..."
534
+ PresentationLogger.detail("Adding only relevant files, respecting .gitignore...")
522
535
 
523
536
  Dir.chdir(workspace_path) do
524
537
  # First, ensure .gitignore is respected
525
538
  if File.exist?('.gitignore')
526
- puts "📁 [WORKSPACE] Using repository's .gitignore file"
539
+ PresentationLogger.detail("Using repository's .gitignore file")
527
540
  else
528
- puts "📁 [WORKSPACE] No .gitignore found, using default patterns"
541
+ PresentationLogger.detail("No .gitignore found, using default patterns")
529
542
  end
530
543
 
531
544
  # Get list of modified files
532
545
  modified_files = `git status --porcelain | grep '^ M\\|^M \\|^A ' | awk '{print $2}'`.strip.split("\n")
546
+
533
547
 
534
548
  if modified_files.empty?
535
- puts "📁 [WORKSPACE] No modified files to add"
549
+ PresentationLogger.detail("No modified files to add")
536
550
  return
537
551
  end
538
552
 
539
- puts "📁 [WORKSPACE] Modified files: #{modified_files.join(', ')}"
553
+ PresentationLogger.detail("Modified files: #{modified_files.join(', ')}")
540
554
 
541
555
  # Add each modified file individually
542
556
  modified_files.each do |file|
@@ -544,15 +558,15 @@ module CodeHealer
544
558
 
545
559
  # Skip temporary and generated files
546
560
  if should_skip_file?(file)
547
- puts "📁 [WORKSPACE] Skipping temporary file: #{file}"
561
+ PresentationLogger.detail("Skipping temporary file: #{file}")
548
562
  next
549
563
  end
550
564
 
551
- puts "📁 [WORKSPACE] Adding file: #{file}"
565
+ PresentationLogger.detail("Adding file: #{file}")
552
566
  system("git add '#{file}'")
553
567
  end
554
568
 
555
- puts "📁 [WORKSPACE] File addition completed"
569
+ PresentationLogger.detail("File addition completed")
556
570
  end
557
571
  end
558
572
 
@@ -609,7 +623,7 @@ module CodeHealer
609
623
 
610
624
  # Additional check: if path contains 'tmp' or 'log' anywhere, skip it
611
625
  if file_path.include?('tmp') || file_path.include?('log')
612
- puts "📁 [WORKSPACE] Skipping file containing 'tmp' or 'log': #{file_path}"
626
+ PresentationLogger.detail("Skipping file containing 'tmp' or 'log': #{file_path}")
613
627
  return true
614
628
  end
615
629
 
@@ -1,5 +1,6 @@
1
1
  require_relative 'mcp_tools'
2
2
  require_relative 'mcp_prompts'
3
+ require_relative 'presentation_logger'
3
4
 
4
5
  module CodeHealer
5
6
  class McpServer
@@ -45,7 +46,7 @@ module CodeHealer
45
46
  end
46
47
 
47
48
  def analyze_error(error, context)
48
- puts "🧠 MCP analyzing error: #{error.class} - #{error.message}"
49
+ PresentationLogger.detail("MCP analyzing error: #{error.class} - #{error.message}")
49
50
 
50
51
  # Extract class and method names from context
51
52
  class_name = context[:class_name] || 'UnknownClass'
@@ -61,11 +62,11 @@ module CodeHealer
61
62
  server_context: { codebase_context: context }
62
63
  )
63
64
 
64
- puts "MCP analysis complete"
65
+ PresentationLogger.detail("MCP analysis complete")
65
66
  # Parse the JSON response from MCP tool
66
67
  JSON.parse(result.content.first[:text])
67
68
  else
68
- puts "⚠️ ErrorAnalysisTool not available, using fallback analysis"
69
+ PresentationLogger.detail("ErrorAnalysisTool not available, using fallback analysis")
69
70
  # Fallback analysis
70
71
  {
71
72
  severity: 'medium',
@@ -78,13 +79,13 @@ module CodeHealer
78
79
  end
79
80
 
80
81
  def generate_contextual_fix(error, analysis, context)
81
- puts "🧠 MCP generating contextual fix..."
82
+ PresentationLogger.detail("MCP generating contextual fix...")
82
83
 
83
84
  # Extract class and method names from context
84
85
  class_name = context[:class_name] || 'UnknownClass'
85
86
  method_name = context[:method_name] || 'unknown_method'
86
87
 
87
- puts "🔍 Debug: class_name = #{class_name}, method_name = #{method_name}"
88
+ PresentationLogger.detail("Debug: class_name = #{class_name}, method_name = #{method_name}")
88
89
 
89
90
  # Use MCP tool to generate fix
90
91
  if defined?(CodeFixTool)
@@ -101,11 +102,11 @@ module CodeHealer
101
102
  }
102
103
  )
103
104
 
104
- puts "MCP generated intelligent fix"
105
+ PresentationLogger.detail("MCP generated intelligent fix")
105
106
  # Parse the JSON response from MCP tool
106
107
  JSON.parse(result.content.first[:text])
107
108
  else
108
- puts "⚠️ CodeFixTool not available, using fallback fix generation"
109
+ PresentationLogger.detail("CodeFixTool not available, using fallback fix generation")
109
110
  # Fallback fix generation
110
111
  generate_fallback_fix(error, class_name, method_name)
111
112
  end