code_healer 0.1.18 → 0.1.20
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 +4 -4
- data/CHANGELOG.md +29 -1
- data/bin/start_claude_session +16 -0
- data/code_healer.gemspec +2 -0
- data/config/code_healer.yml.example +33 -1
- data/lib/code_healer/business_context_manager.rb +57 -3
- data/lib/code_healer/claude_code_evolution_handler.rb +16 -14
- data/lib/code_healer/config_manager.rb +53 -1
- data/lib/code_healer/evolution_job.rb +1 -1
- data/lib/code_healer/healing_job.rb +45 -1
- data/lib/code_healer/mcp_server.rb +222 -2
- data/lib/code_healer/mcp_tools.rb +390 -5
- data/lib/code_healer/pull_request_creator.rb +1 -1
- data/lib/code_healer/setup.rb +155 -4
- data/lib/code_healer/version.rb +1 -1
- data/lib/code_healer.rb +4 -1
- metadata +23 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c54944cc1cad8a6a188bbf5b5a50a216b0719046339b59eccc12447aff916582
|
4
|
+
data.tar.gz: f190123758f3d4b73a7c7f53ccf8b275347819e5a7b60008085a62a79c239751
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 050def7293a77fb6204fb51f9fc5640caf036903b765c34be1b9c9163300e1034ae880ad3855d92480df40fe813c4590df6c1a86b812d80c9e541b8d7df8d9ef
|
7
|
+
data.tar.gz: 1d2874cf1817fdf4825d189f666c5fd9e9a300966892118dd79e254a4b528251d8cb85e587525735a3749f07ad75711e1ac1cdd444f30ba0c76852d4d4f62504
|
data/CHANGELOG.md
CHANGED
@@ -5,7 +5,35 @@ All notable changes to this project will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
|
-
## [
|
8
|
+
## [0.1.20] - 2025-08-27
|
9
|
+
|
10
|
+
### Added
|
11
|
+
- **Confluence MCP Integration**: Added direct Confluence MCP tools for business context fetching (optional usage)
|
12
|
+
- **Flexible MCP Usage**: Enhanced prompts to optionally use Confluence MCP tools when available
|
13
|
+
- **Non-interactive MCP**: Fixed Claude Terminal flags to avoid manual approval prompts
|
14
|
+
- **Business Context Strategy**: Added `confluence_only` strategy for focused Confluence documentation usage
|
15
|
+
|
16
|
+
### Fixed
|
17
|
+
- **MCP Tool Access**: Removed restrictive tool flags that blocked MCP tool usage
|
18
|
+
- **Debug Logging**: Cleaned up unnecessary MCP debugging logs from initialization and job startup
|
19
|
+
- **Command Optimization**: Fixed Claude Terminal command flags for proper MCP integration
|
20
|
+
|
21
|
+
### Changed
|
22
|
+
- **Prompt Strategy**: Updated business context prompts to optionally use MCP tools when available
|
23
|
+
- **Initialization**: Streamlined gem startup without MCP availability checks
|
24
|
+
- **Dependencies**: Maintained `httparty` for MCP API integration while removing debug overhead
|
25
|
+
|
26
|
+
## [0.1.19] - 2025-08-21
|
27
|
+
|
28
|
+
### Fixed
|
29
|
+
- **Critical Git Operations Duplication**: Fixed duplicate Git operations between evolution handler and workspace manager.
|
30
|
+
- **Branch Detection**: Fixed automatic detection of repository's default branch (master vs main).
|
31
|
+
- **Configuration Loading**: Fixed pr_target_branch configuration loading from both git section and root level.
|
32
|
+
- **Workspace Isolation**: Improved Git operations to occur only in isolated workspace, preventing conflicts.
|
33
|
+
|
34
|
+
### Changed
|
35
|
+
- **Evolution Handler**: Removed duplicate Git operations to prevent conflicts with workspace manager.
|
36
|
+
- **Setup Script**: Enhanced with automatic branch detection and better configuration structure.
|
9
37
|
|
10
38
|
## [0.1.18] - 2025-08-21
|
11
39
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Start Claude Terminal with code_healer_session for MCP tools access
|
4
|
+
# This session will be used by CodeHealer for healing jobs
|
5
|
+
|
6
|
+
puts "🚀 Starting Claude Terminal with code_healer_session for MCP tools..."
|
7
|
+
puts "This session will be used by CodeHealer for healing jobs with Jira/Confluence access"
|
8
|
+
puts ""
|
9
|
+
puts "Session name: code_healer_session"
|
10
|
+
puts "MCP tools: Jira, Confluence, and other Atlassian integrations"
|
11
|
+
puts ""
|
12
|
+
puts "Keep this terminal open while running healing jobs!"
|
13
|
+
puts "=" * 60
|
14
|
+
|
15
|
+
# Start Claude Terminal with the session
|
16
|
+
exec "claude --session code_healer_session"
|
data/code_healer.gemspec
CHANGED
@@ -60,6 +60,8 @@ Gem::Specification.new do |spec|
|
|
60
60
|
spec.add_runtime_dependency 'activesupport', '>= 6.0.0'
|
61
61
|
spec.add_runtime_dependency 'actionpack', '>= 6.0.0'
|
62
62
|
spec.add_runtime_dependency 'activemodel', '>= 6.0.0'
|
63
|
+
spec.add_runtime_dependency 'httparty', '~> 0.21.0', '>= 0.21.0'
|
64
|
+
|
63
65
|
|
64
66
|
# Development dependencies
|
65
67
|
spec.add_development_dependency "bundler", ">= 2.0.0"
|
@@ -49,7 +49,39 @@ claude_code:
|
|
49
49
|
business_context:
|
50
50
|
enabled: true
|
51
51
|
|
52
|
-
#
|
52
|
+
# Business Context Strategy
|
53
|
+
strategy: "jira_mcp" # Options: "jira_mcp", "markdown", "hybrid"
|
54
|
+
|
55
|
+
# Jira MCP Configuration (when strategy is "jira_mcp" or "hybrid")
|
56
|
+
jira_mcp:
|
57
|
+
enabled: true
|
58
|
+
project_key: "DGTL" # Your Jira project key
|
59
|
+
search_tickets_on_error: true
|
60
|
+
include_business_rules: true
|
61
|
+
system_prompt: |
|
62
|
+
When fixing code, ALWAYS check Jira MCP for business context:
|
63
|
+
1. Search for tickets about the class/method you're fixing
|
64
|
+
2. Use Jira requirements to ensure your fix follows business rules
|
65
|
+
3. Reference specific Jira tickets in your explanation
|
66
|
+
4. Make sure fixes align with business requirements
|
67
|
+
|
68
|
+
# Markdown Configuration (when strategy is "markdown" or "hybrid")
|
69
|
+
markdown:
|
70
|
+
enabled: true
|
71
|
+
search_paths:
|
72
|
+
- "docs/business_rules.md"
|
73
|
+
- "docs/requirements.md"
|
74
|
+
- "business_requirements/"
|
75
|
+
include_patterns:
|
76
|
+
- "*.md"
|
77
|
+
- "*.txt"
|
78
|
+
|
79
|
+
# Hybrid Configuration (when strategy is "hybrid")
|
80
|
+
hybrid:
|
81
|
+
priority: ["jira_mcp", "markdown"] # Which source to check first
|
82
|
+
combine_results: true # Merge results from both sources
|
83
|
+
|
84
|
+
# Define business rules for specific classes (fallback when MCP unavailable)
|
53
85
|
User:
|
54
86
|
domain: "User Management"
|
55
87
|
key_rules:
|
@@ -177,8 +177,44 @@ module CodeHealer
|
|
177
177
|
end
|
178
178
|
|
179
179
|
def build_claude_code_prompt(error, class_name, method_name, file_path)
|
180
|
-
#
|
181
|
-
business_context =
|
180
|
+
# Get business context based on configured strategy
|
181
|
+
business_context = case CodeHealer::ConfigManager.business_context_strategy
|
182
|
+
when 'confluence_only'
|
183
|
+
"## Business Context Instructions:\n" \
|
184
|
+
"OPTIONAL: You can use Confluence MCP tools to enhance business context if available.\n\n" \
|
185
|
+
"1. If Confluence MCP is available:\n" \
|
186
|
+
" - Search for PRDs/specs related to '#{class_name}' / '#{method_name}'.\n" \
|
187
|
+
" - Query terms: '#{class_name}', '#{method_name}', 'business rules', 'validation patterns'.\n" \
|
188
|
+
" - Apply any found documentation to your fix.\n\n" \
|
189
|
+
"2. If Confluence MCP is not available:\n" \
|
190
|
+
" - Proceed with standard business logic and error handling practices.\n" \
|
191
|
+
" - Use common validation patterns and best practices.\n\n" \
|
192
|
+
"Note: MCP usage is optional - proceed with or without it."
|
193
|
+
when 'claude_atlassian_mcp'
|
194
|
+
"## Business Context Instructions:\n" \
|
195
|
+
"OPTIONAL: You can use Atlassian MCP tools to enhance business context if available.\n\n" \
|
196
|
+
"1. **If Jira MCP is available:**\n" \
|
197
|
+
" - Search for tickets related to '#{class_name}' or '#{method_name}'\n" \
|
198
|
+
" - Look for bug reports, requirements, or business rules\n" \
|
199
|
+
" - Apply any found ticket context to your fix\n\n" \
|
200
|
+
"2. **If Confluence MCP is available:**\n" \
|
201
|
+
" - Search for PRDs, technical specs, or business process docs\n" \
|
202
|
+
" - Look for domain-specific business rules related to '#{class_name}'\n" \
|
203
|
+
" - Apply any found documentation to your fix\n\n" \
|
204
|
+
"3. **If MCP tools are not available:**\n" \
|
205
|
+
" - Proceed with standard business logic and error handling practices\n" \
|
206
|
+
" - Use common validation patterns and best practices\n\n" \
|
207
|
+
"Note: MCP usage is optional - proceed with or without it."
|
208
|
+
when 'jira_mcp'
|
209
|
+
# Use Jira MCP context
|
210
|
+
get_jira_business_context(class_name)
|
211
|
+
when 'markdown'
|
212
|
+
# Use markdown files
|
213
|
+
load_business_context_from_markdown_simple
|
214
|
+
else
|
215
|
+
# Default fallback
|
216
|
+
load_business_context_from_markdown_simple
|
217
|
+
end
|
182
218
|
|
183
219
|
prompt = <<~PROMPT
|
184
220
|
I have a Ruby on Rails application with an error that needs fixing.
|
@@ -195,7 +231,7 @@ module CodeHealer
|
|
195
231
|
#{error.backtrace&.join("\n") || "No backtrace available"}
|
196
232
|
```
|
197
233
|
|
198
|
-
## Business Context
|
234
|
+
## Business Context:
|
199
235
|
#{business_context}
|
200
236
|
|
201
237
|
## Instructions:
|
@@ -262,6 +298,24 @@ module CodeHealer
|
|
262
298
|
prompt.strip
|
263
299
|
end
|
264
300
|
|
301
|
+
def get_jira_business_context(class_name)
|
302
|
+
# Get Jira business context using MCP tools
|
303
|
+
begin
|
304
|
+
# This would integrate with Jira MCP tools
|
305
|
+
# For now, return instructions to use Jira MCP
|
306
|
+
"## Jira Business Context Instructions:\n" \
|
307
|
+
"Use Jira MCP tools to fetch business context:\n" \
|
308
|
+
"1. Search for tickets related to '#{class_name}'\n" \
|
309
|
+
"2. Look for business requirements and rules\n" \
|
310
|
+
"3. Apply the context to your fix\n" \
|
311
|
+
"4. Reference specific Jira tickets in your explanation"
|
312
|
+
rescue => e
|
313
|
+
"## Jira Business Context:\n" \
|
314
|
+
"Unable to fetch Jira context: #{e.message}\n" \
|
315
|
+
"Please use Jira MCP tools manually to get business context."
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
265
319
|
private
|
266
320
|
|
267
321
|
def load_business_context_from_markdown_simple
|
@@ -31,8 +31,9 @@ module CodeHealer
|
|
31
31
|
reload_modified_files
|
32
32
|
|
33
33
|
# 🚀 Trigger Git operations (commit, push, PR creation)
|
34
|
-
|
35
|
-
|
34
|
+
# Note: Git operations are now handled by the isolated workspace manager
|
35
|
+
# to prevent duplication and ensure proper isolation
|
36
|
+
puts "🔄 Git operations will be handled by isolated workspace manager..."
|
36
37
|
|
37
38
|
return true
|
38
39
|
else
|
@@ -109,31 +110,30 @@ module CodeHealer
|
|
109
110
|
def build_claude_command(prompt, config)
|
110
111
|
# Escape prompt for shell
|
111
112
|
escaped_prompt = prompt.gsub("'", "'\"'\"'")
|
112
|
-
|
113
|
-
# Build command template
|
113
|
+
|
114
|
+
# Build command template for MCP tools access
|
114
115
|
command_template = config['command_template'] || "claude --code '{prompt}'"
|
115
|
-
|
116
|
+
|
116
117
|
# Replace placeholder
|
117
118
|
command = command_template.gsub('{prompt}', escaped_prompt)
|
118
|
-
|
119
|
-
#
|
119
|
+
|
120
|
+
# [rest of your existing code remains the same]
|
120
121
|
if config['include_tests'] && !CodeHealer::ConfigManager.demo_mode?
|
121
122
|
command += " --append-system-prompt 'Include tests when fixing the code'"
|
122
123
|
else
|
123
124
|
command += " --append-system-prompt 'Do NOT create or modify tests'"
|
124
125
|
end
|
125
|
-
|
126
|
+
|
126
127
|
if config['max_file_changes']
|
127
128
|
command += " --append-system-prompt 'Limit changes to #{config['max_file_changes']} files maximum'"
|
128
129
|
end
|
129
|
-
|
130
|
-
# Add file editing permissions
|
130
|
+
|
131
131
|
command += " --permission-mode acceptEdits --allowedTools Edit"
|
132
|
-
|
133
|
-
# Add current directory access but advise not to scan everything
|
132
|
+
command += " --append-system-prompt 'Optionally use Confluence MCP tools if available to enhance business context, but proceed regardless.'"
|
134
133
|
command += " --add-dir . --append-system-prompt 'Do not scan the whole repo; open only files explicitly referenced.'"
|
135
|
-
|
136
|
-
command
|
134
|
+
|
135
|
+
# Return combined command
|
136
|
+
mcp_setup + command
|
137
137
|
end
|
138
138
|
|
139
139
|
def reload_modified_files
|
@@ -193,6 +193,8 @@ module CodeHealer
|
|
193
193
|
puts "📝 Evolution attempt logged to #{log_file}"
|
194
194
|
end
|
195
195
|
|
196
|
+
|
197
|
+
|
196
198
|
def trigger_git_operations(error, class_name, method_name, file_path)
|
197
199
|
puts "🚀 Triggering Git operations for Claude Code evolution..."
|
198
200
|
|
@@ -107,6 +107,57 @@ module CodeHealer
|
|
107
107
|
config['business_context'] || {}
|
108
108
|
end
|
109
109
|
|
110
|
+
# Business Context Strategy Configuration
|
111
|
+
def business_context_strategy
|
112
|
+
business_context_settings['strategy'] || 'markdown'
|
113
|
+
end
|
114
|
+
|
115
|
+
def use_jira_mcp?
|
116
|
+
business_context_strategy == 'jira_mcp' || business_context_strategy == 'hybrid'
|
117
|
+
end
|
118
|
+
|
119
|
+
def use_markdown_context?
|
120
|
+
business_context_strategy == 'markdown' || business_context_strategy == 'hybrid'
|
121
|
+
end
|
122
|
+
|
123
|
+
def use_hybrid_context?
|
124
|
+
business_context_strategy == 'hybrid'
|
125
|
+
end
|
126
|
+
|
127
|
+
def jira_mcp_settings
|
128
|
+
business_context_settings['jira_mcp'] || {}
|
129
|
+
end
|
130
|
+
|
131
|
+
def markdown_settings
|
132
|
+
business_context_settings['markdown'] || {}
|
133
|
+
end
|
134
|
+
|
135
|
+
def hybrid_settings
|
136
|
+
business_context_settings['hybrid'] || {}
|
137
|
+
end
|
138
|
+
|
139
|
+
def jira_mcp_enabled?
|
140
|
+
use_jira_mcp? && jira_mcp_settings['enabled'] != false
|
141
|
+
end
|
142
|
+
|
143
|
+
def markdown_enabled?
|
144
|
+
use_markdown_context? && markdown_settings['enabled'] != false
|
145
|
+
end
|
146
|
+
|
147
|
+
def jira_mcp_system_prompt
|
148
|
+
jira_mcp_settings['system_prompt'] || default_jira_mcp_prompt
|
149
|
+
end
|
150
|
+
|
151
|
+
def default_jira_mcp_prompt
|
152
|
+
<<~PROMPT
|
153
|
+
When fixing code, ALWAYS check Jira MCP for business context:
|
154
|
+
1. Search for tickets about the class/method you're fixing
|
155
|
+
2. Use Jira requirements to ensure your fix follows business rules
|
156
|
+
3. Reference specific Jira tickets in your explanation
|
157
|
+
4. Make sure fixes align with business requirements
|
158
|
+
PROMPT
|
159
|
+
end
|
160
|
+
|
110
161
|
# API Configuration
|
111
162
|
def api_settings
|
112
163
|
config['api'] || {}
|
@@ -189,7 +240,8 @@ module CodeHealer
|
|
189
240
|
end
|
190
241
|
|
191
242
|
def pr_target_branch
|
192
|
-
|
243
|
+
# Check both git section and root level for backward compatibility
|
244
|
+
git_settings['pr_target_branch'] || config['pr_target_branch'] || 'main'
|
193
245
|
end
|
194
246
|
|
195
247
|
def commit_message_template
|
@@ -25,7 +25,7 @@ class EvolutionJob
|
|
25
25
|
healing_branch = CodeHealer::HealingWorkspaceManager.create_healing_branch(
|
26
26
|
Rails.root.to_s,
|
27
27
|
workspace_path,
|
28
|
-
CodeHealer::ConfigManager.
|
28
|
+
CodeHealer::ConfigManager.pr_target_branch
|
29
29
|
)
|
30
30
|
|
31
31
|
if healing_branch
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'sidekiq'
|
2
|
+
require 'open3'
|
2
3
|
|
3
4
|
module CodeHealer
|
4
5
|
class HealingJob
|
@@ -9,6 +10,8 @@ module CodeHealer
|
|
9
10
|
def perform(*args)
|
10
11
|
puts "🚀 [HEALING_JOB] Starting job with args: #{args.inspect}"
|
11
12
|
|
13
|
+
|
14
|
+
|
12
15
|
# Support both legacy and new invocation styles
|
13
16
|
error, class_name, method_name, evolution_method, backtrace = parse_args(args)
|
14
17
|
|
@@ -68,7 +71,7 @@ module CodeHealer
|
|
68
71
|
healing_branch = CodeHealer::HealingWorkspaceManager.create_healing_branch(
|
69
72
|
Rails.root.to_s,
|
70
73
|
workspace_path,
|
71
|
-
CodeHealer::ConfigManager.
|
74
|
+
CodeHealer::ConfigManager.pr_target_branch
|
72
75
|
)
|
73
76
|
git_time_ms = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - git_started_at) * 1000).round
|
74
77
|
|
@@ -127,6 +130,47 @@ module CodeHealer
|
|
127
130
|
end
|
128
131
|
|
129
132
|
private
|
133
|
+
|
134
|
+
def log_mcp_tools_availability
|
135
|
+
puts "🔍 [HEALING_JOB] Checking MCP tools availability..."
|
136
|
+
|
137
|
+
begin
|
138
|
+
# Check if Claude has MCP tools available
|
139
|
+
mcp_check_command = "claude --print 'List all available MCP tools' --output-format text"
|
140
|
+
stdout, stderr, status = Open3.capture3(mcp_check_command)
|
141
|
+
|
142
|
+
if status.success?
|
143
|
+
puts "✅ [HEALING_JOB] Claude Terminal is available"
|
144
|
+
|
145
|
+
# Extract MCP tools from output
|
146
|
+
if stdout.include?("MCP tools available") || stdout.include?("mcp__")
|
147
|
+
puts "🔧 [HEALING_JOB] MCP tools detected in Claude Terminal"
|
148
|
+
|
149
|
+
# Log specific MCP tools if found
|
150
|
+
if stdout.include?("mcp__atlassian")
|
151
|
+
puts " - Atlassian MCP tools: Available"
|
152
|
+
puts " - Jira integration: Available"
|
153
|
+
puts " - Confluence integration: Available"
|
154
|
+
end
|
155
|
+
|
156
|
+
if stdout.include?("mcp__")
|
157
|
+
puts " - Other MCP tools: Available"
|
158
|
+
end
|
159
|
+
else
|
160
|
+
puts "⚠️ [HEALING_JOB] No MCP tools detected in Claude Terminal"
|
161
|
+
puts "💡 Make sure Claude Terminal has MCP tools configured"
|
162
|
+
end
|
163
|
+
else
|
164
|
+
puts "❌ [HEALING_JOB] Claude Terminal is not available"
|
165
|
+
puts "💡 Make sure Claude Terminal is installed and accessible"
|
166
|
+
end
|
167
|
+
rescue => e
|
168
|
+
puts "⚠️ [HEALING_JOB] Could not check MCP tools: #{e.message}"
|
169
|
+
puts "💡 Make sure Claude Terminal is properly installed"
|
170
|
+
end
|
171
|
+
|
172
|
+
puts "🔍 [HEALING_JOB] MCP tools check complete"
|
173
|
+
end
|
130
174
|
|
131
175
|
def parse_args(args)
|
132
176
|
# Formats supported:
|
@@ -18,7 +18,9 @@ module CodeHealer
|
|
18
18
|
tools: [
|
19
19
|
ErrorAnalysisTool,
|
20
20
|
CodeFixTool,
|
21
|
-
ContextAnalysisTool
|
21
|
+
ContextAnalysisTool,
|
22
|
+
JIRAIntegrationTool, # Add Jira integration tool
|
23
|
+
ConfluenceIntegrationTool # Add Confluence integration tool
|
22
24
|
],
|
23
25
|
server_context: {
|
24
26
|
codebase_context: @codebase_context,
|
@@ -237,13 +239,231 @@ module CodeHealer
|
|
237
239
|
end
|
238
240
|
|
239
241
|
def get_business_context(class_name)
|
240
|
-
{
|
242
|
+
base_context = {
|
241
243
|
domain: determine_business_domain(class_name),
|
242
244
|
criticality: assess_business_criticality(class_name),
|
243
245
|
regulatory_requirements: identify_regulatory_requirements(class_name),
|
244
246
|
sla_requirements: get_sla_requirements(class_name),
|
245
247
|
user_impact: assess_user_impact(class_name)
|
246
248
|
}
|
249
|
+
|
250
|
+
# Get business context based on configured sources
|
251
|
+
business_context = get_configured_business_context(class_name)
|
252
|
+
base_context.merge!(business_context)
|
253
|
+
|
254
|
+
base_context
|
255
|
+
end
|
256
|
+
|
257
|
+
def get_configured_business_context(class_name)
|
258
|
+
context = {}
|
259
|
+
|
260
|
+
# Get business context based on configured strategy
|
261
|
+
case CodeHealer::ConfigManager.business_context_strategy
|
262
|
+
when 'jira_mcp'
|
263
|
+
if CodeHealer::ConfigManager.jira_mcp_enabled?
|
264
|
+
context[:strategy] = 'jira_mcp'
|
265
|
+
context[:instructions] = CodeHealer::ConfigManager.jira_mcp_system_prompt
|
266
|
+
context[:project_key] = CodeHealer::ConfigManager.jira_mcp_settings['project_key']
|
267
|
+
end
|
268
|
+
when 'markdown'
|
269
|
+
if CodeHealer::ConfigManager.markdown_enabled?
|
270
|
+
markdown_context = get_markdown_business_context(class_name)
|
271
|
+
context[:strategy] = 'markdown'
|
272
|
+
context[:markdown_context] = markdown_context
|
273
|
+
end
|
274
|
+
when 'hybrid'
|
275
|
+
# Combine both approaches
|
276
|
+
context[:strategy] = 'hybrid'
|
277
|
+
if CodeHealer::ConfigManager.jira_mcp_enabled?
|
278
|
+
context[:jira_mcp_instructions] = CodeHealer::ConfigManager.jira_mcp_system_prompt
|
279
|
+
context[:project_key] = CodeHealer::ConfigManager.jira_mcp_settings['project_key']
|
280
|
+
end
|
281
|
+
if CodeHealer::ConfigManager.markdown_enabled?
|
282
|
+
markdown_context = get_markdown_business_context(class_name)
|
283
|
+
context[:markdown_context] = markdown_context
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
context
|
288
|
+
end
|
289
|
+
|
290
|
+
def get_jira_business_context(class_name)
|
291
|
+
return {} unless defined?(JIRAIntegrationTool)
|
292
|
+
|
293
|
+
begin
|
294
|
+
# Use MCP tool to get Jira context
|
295
|
+
result = JIRAIntegrationTool.call(
|
296
|
+
action: "search_tickets",
|
297
|
+
search_query: "#{class_name} business rules requirements",
|
298
|
+
project_key: get_default_jira_project_key,
|
299
|
+
server_context: {}
|
300
|
+
)
|
301
|
+
|
302
|
+
if result && result.content.any?
|
303
|
+
data = JSON.parse(result.content.first[:text])
|
304
|
+
return {} if data['error']
|
305
|
+
|
306
|
+
# Extract business context from Jira tickets
|
307
|
+
{
|
308
|
+
related_tickets: data['tickets']&.first(3) || [],
|
309
|
+
business_rules: extract_business_rules_from_tickets(data['tickets']),
|
310
|
+
requirements: extract_requirements_from_tickets(data['tickets'])
|
311
|
+
}
|
312
|
+
end
|
313
|
+
rescue => e
|
314
|
+
puts "⚠️ Failed to get Jira business context: #{e.message}"
|
315
|
+
end
|
316
|
+
|
317
|
+
{}
|
318
|
+
end
|
319
|
+
|
320
|
+
def get_default_jira_project_key
|
321
|
+
# Extract from environment or use default
|
322
|
+
ENV['JIRA_PROJECT_KEY'] || 'DGTL'
|
323
|
+
end
|
324
|
+
|
325
|
+
def extract_business_rules_from_tickets(tickets)
|
326
|
+
return [] unless tickets
|
327
|
+
|
328
|
+
tickets.flat_map do |ticket|
|
329
|
+
# Extract business rules from ticket summary, description, labels
|
330
|
+
rules = []
|
331
|
+
rules << ticket['summary'] if ticket['summary']&.include?('rule')
|
332
|
+
rules << ticket['summary'] if ticket['summary']&.include?('policy')
|
333
|
+
rules << ticket['summary'] if ticket['summary']&.include?('requirement')
|
334
|
+
rules
|
335
|
+
end.compact.uniq
|
336
|
+
end
|
337
|
+
|
338
|
+
def extract_requirements_from_tickets(tickets)
|
339
|
+
return [] unless tickets
|
340
|
+
|
341
|
+
tickets.flat_map do |ticket|
|
342
|
+
# Extract business context from ticket content
|
343
|
+
requirements = []
|
344
|
+
requirements << ticket['summary'] if ticket['summary']&.include?('requirement')
|
345
|
+
requirements << ticket['summary'] if ticket['summary']&.include?('should')
|
346
|
+
requirements << ticket['summary'] if ticket['summary']&.include?('need')
|
347
|
+
requirements
|
348
|
+
end.compact.uniq
|
349
|
+
end
|
350
|
+
|
351
|
+
# Public method for Claude Terminal to access Confluence business context
|
352
|
+
def get_confluence_business_context(class_name)
|
353
|
+
return {} unless defined?(ConfluenceIntegrationTool)
|
354
|
+
|
355
|
+
begin
|
356
|
+
# Use MCP tool to get Confluence context
|
357
|
+
result = ConfluenceIntegrationTool.call(
|
358
|
+
action: "search_documents",
|
359
|
+
search_query: "#{class_name} PRD requirements business rules",
|
360
|
+
space_key: get_default_confluence_space_key,
|
361
|
+
server_context: {}
|
362
|
+
)
|
363
|
+
|
364
|
+
if result && result.content.any?
|
365
|
+
data = JSON.parse(result.content.first[:text])
|
366
|
+
return {} if data['error']
|
367
|
+
|
368
|
+
# Extract business context from Confluence documents
|
369
|
+
{
|
370
|
+
related_documents: data['documents']&.first(3) || [],
|
371
|
+
prd_content: extract_prd_content(data['documents']),
|
372
|
+
business_processes: extract_business_processes(data['documents'])
|
373
|
+
}
|
374
|
+
end
|
375
|
+
rescue => e
|
376
|
+
puts "⚠️ Failed to get Confluence business context: #{e.message}"
|
377
|
+
end
|
378
|
+
|
379
|
+
{}
|
380
|
+
end
|
381
|
+
|
382
|
+
# Public method for Claude Terminal to get Confluence space key
|
383
|
+
def get_default_confluence_space_key
|
384
|
+
# Extract from environment or use default
|
385
|
+
ENV['CONFLUENCE_SPACE_KEY'] || 'DGTL'
|
386
|
+
end
|
387
|
+
|
388
|
+
# Public method for Claude Terminal to extract PRD content
|
389
|
+
def extract_prd_content(documents)
|
390
|
+
return [] unless documents
|
391
|
+
|
392
|
+
documents.flat_map do |doc|
|
393
|
+
# Extract PRD content from document title, content, labels
|
394
|
+
content = []
|
395
|
+
content << doc['title'] if doc['title']&.include?('PRD')
|
396
|
+
content << doc['title'] if doc['title']&.include?('Product Requirements')
|
397
|
+
content << doc['title'] if doc['title']&.include?('Requirements')
|
398
|
+
content << doc['content']&.truncate(200) if doc['content']
|
399
|
+
content
|
400
|
+
end.compact.uniq
|
401
|
+
end
|
402
|
+
|
403
|
+
# Public method for Claude Terminal to extract business processes
|
404
|
+
def extract_business_processes(documents)
|
405
|
+
return [] unless documents
|
406
|
+
|
407
|
+
documents.flat_map do |doc|
|
408
|
+
# Extract business process information from document content
|
409
|
+
processes = []
|
410
|
+
processes << doc['title'] if doc['title']&.include?('Process')
|
411
|
+
processes << doc['title'] if doc['title']&.include?('Workflow')
|
412
|
+
processes << doc['title'] if doc['title']&.include?('Procedure')
|
413
|
+
processes << doc['content']&.truncate(200) if doc['content']
|
414
|
+
processes
|
415
|
+
end.compact.uniq
|
416
|
+
end
|
417
|
+
|
418
|
+
# Public method for Claude Terminal to access Markdown business context
|
419
|
+
def get_markdown_business_context(class_name)
|
420
|
+
return {} unless CodeHealer::ConfigManager.use_markdown_context?
|
421
|
+
|
422
|
+
begin
|
423
|
+
# Load from existing markdown business context
|
424
|
+
markdown_context = load_business_requirements_from_markdown
|
425
|
+
|
426
|
+
if markdown_context.any?
|
427
|
+
{
|
428
|
+
markdown_files: markdown_context['markdown_requirements'] || [],
|
429
|
+
business_rules: extract_business_rules_from_markdown(markdown_context),
|
430
|
+
requirements: extract_requirements_from_markdown(markdown_context)
|
431
|
+
}
|
432
|
+
end
|
433
|
+
rescue => e
|
434
|
+
puts "⚠️ Failed to get Markdown business context: #{e.message}"
|
435
|
+
end
|
436
|
+
|
437
|
+
{}
|
438
|
+
end
|
439
|
+
|
440
|
+
# Public method for Claude Terminal to extract business rules from markdown
|
441
|
+
def extract_business_rules_from_markdown(markdown_context)
|
442
|
+
return [] unless markdown_context['markdown_requirements']
|
443
|
+
|
444
|
+
markdown_context['markdown_requirements'].flat_map do |file_info|
|
445
|
+
content = file_info[:content]
|
446
|
+
rules = []
|
447
|
+
rules << content if content.include?('rule')
|
448
|
+
rules << content if content.include?('policy')
|
449
|
+
rules << content if content.include?('requirement')
|
450
|
+
rules
|
451
|
+
end.compact.uniq
|
452
|
+
end
|
453
|
+
|
454
|
+
# Public method for Claude Terminal to extract requirements from markdown
|
455
|
+
def extract_requirements_from_markdown(markdown_context)
|
456
|
+
return [] unless markdown_context['markdown_requirements']
|
457
|
+
|
458
|
+
markdown_context['markdown_requirements'].flat_map do |file_info|
|
459
|
+
content = file_info[:content]
|
460
|
+
requirements = []
|
461
|
+
requirements << content if content.include?('requirement')
|
462
|
+
requirements << content if content.include?('must')
|
463
|
+
requirements << content if content.include?('should')
|
464
|
+
requirements << content if content.include?('need')
|
465
|
+
requirements
|
466
|
+
end.compact.uniq
|
247
467
|
end
|
248
468
|
|
249
469
|
def get_evolution_history(class_name, method_name)
|