aidp 0.3.0 → 0.7.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 +4 -4
- data/README.md +191 -5
- data/lib/aidp/analysis/kb_inspector.rb +456 -0
- data/lib/aidp/analysis/seams.rb +188 -0
- data/lib/aidp/analysis/tree_sitter_grammar_loader.rb +493 -0
- data/lib/aidp/analysis/tree_sitter_scan.rb +703 -0
- data/lib/aidp/analyze/agent_personas.rb +1 -1
- data/lib/aidp/analyze/agent_tool_executor.rb +5 -11
- data/lib/aidp/analyze/data_retention_manager.rb +0 -5
- data/lib/aidp/analyze/database.rb +99 -82
- data/lib/aidp/analyze/error_handler.rb +12 -79
- data/lib/aidp/analyze/export_manager.rb +0 -7
- data/lib/aidp/analyze/focus_guidance.rb +2 -2
- data/lib/aidp/analyze/incremental_analyzer.rb +1 -11
- data/lib/aidp/analyze/large_analysis_progress.rb +0 -5
- data/lib/aidp/analyze/memory_manager.rb +34 -60
- data/lib/aidp/analyze/metrics_storage.rb +336 -0
- data/lib/aidp/analyze/parallel_processor.rb +0 -6
- data/lib/aidp/analyze/performance_optimizer.rb +0 -3
- data/lib/aidp/analyze/prioritizer.rb +2 -2
- data/lib/aidp/analyze/repository_chunker.rb +14 -21
- data/lib/aidp/analyze/ruby_maat_integration.rb +6 -102
- data/lib/aidp/analyze/runner.rb +107 -191
- data/lib/aidp/analyze/steps.rb +35 -30
- data/lib/aidp/analyze/storage.rb +233 -178
- data/lib/aidp/analyze/tool_configuration.rb +21 -36
- data/lib/aidp/cli/jobs_command.rb +489 -0
- data/lib/aidp/cli/terminal_io.rb +52 -0
- data/lib/aidp/cli.rb +160 -45
- data/lib/aidp/core_ext/class_attribute.rb +36 -0
- data/lib/aidp/database/pg_adapter.rb +148 -0
- data/lib/aidp/database_config.rb +69 -0
- data/lib/aidp/database_connection.rb +72 -0
- data/lib/aidp/execute/runner.rb +65 -92
- data/lib/aidp/execute/steps.rb +81 -82
- data/lib/aidp/job_manager.rb +41 -0
- data/lib/aidp/jobs/base_job.rb +45 -0
- data/lib/aidp/jobs/provider_execution_job.rb +83 -0
- data/lib/aidp/provider_manager.rb +25 -0
- data/lib/aidp/providers/agent_supervisor.rb +348 -0
- data/lib/aidp/providers/anthropic.rb +160 -3
- data/lib/aidp/providers/base.rb +153 -6
- data/lib/aidp/providers/cursor.rb +245 -43
- data/lib/aidp/providers/gemini.rb +164 -3
- data/lib/aidp/providers/supervised_base.rb +317 -0
- data/lib/aidp/providers/supervised_cursor.rb +22 -0
- data/lib/aidp/version.rb +1 -1
- data/lib/aidp.rb +31 -34
- data/templates/ANALYZE/01_REPOSITORY_ANALYSIS.md +4 -4
- data/templates/ANALYZE/06a_tree_sitter_scan.md +217 -0
- metadata +91 -36
@@ -0,0 +1,317 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "agent_supervisor"
|
4
|
+
|
5
|
+
module Aidp
|
6
|
+
module Providers
|
7
|
+
# Base class for providers that use the agent supervisor
|
8
|
+
class SupervisedBase
|
9
|
+
# Timeout constants are now configurable via environment variables for flexibility
|
10
|
+
DEFAULT_TIMEOUT = Integer(ENV.fetch("AIDP_DEFAULT_TIMEOUT", "300")) # 5 minutes for general operations
|
11
|
+
QUICK_MODE_TIMEOUT = Integer(ENV.fetch("AIDP_QUICK_MODE_TIMEOUT", "120")) # 2 minutes for testing
|
12
|
+
REPOSITORY_ANALYSIS_TIMEOUT = Integer(ENV.fetch("AIDP_REPOSITORY_ANALYSIS_TIMEOUT", "180")) # 3 minutes
|
13
|
+
ARCHITECTURE_ANALYSIS_TIMEOUT = Integer(ENV.fetch("AIDP_ARCHITECTURE_ANALYSIS_TIMEOUT", "600")) # 10 minutes
|
14
|
+
TEST_ANALYSIS_TIMEOUT = Integer(ENV.fetch("AIDP_TEST_ANALYSIS_TIMEOUT", "300")) # 5 minutes
|
15
|
+
FUNCTIONALITY_ANALYSIS_TIMEOUT = Integer(ENV.fetch("AIDP_FUNCTIONALITY_ANALYSIS_TIMEOUT", "600")) # 10 minutes
|
16
|
+
DOCUMENTATION_ANALYSIS_TIMEOUT = Integer(ENV.fetch("AIDP_DOCUMENTATION_ANALYSIS_TIMEOUT", "300")) # 5 minutes
|
17
|
+
STATIC_ANALYSIS_TIMEOUT = Integer(ENV.fetch("AIDP_STATIC_ANALYSIS_TIMEOUT", "450")) # 7.5 minutes
|
18
|
+
REFACTORING_RECOMMENDATIONS_TIMEOUT = Integer(ENV.fetch("AIDP_REFACTORING_RECOMMENDATIONS_TIMEOUT", "600")) # 10 minutes
|
19
|
+
ADAPTIVE_TIMEOUT_BUFFER = Float(ENV.fetch("AIDP_ADAPTIVE_TIMEOUT_BUFFER", "1.2")) # 20% buffer for adaptive timeouts
|
20
|
+
attr_reader :name, :last_execution_result, :metrics
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
@last_execution_result = nil
|
24
|
+
@metrics = {
|
25
|
+
total_executions: 0,
|
26
|
+
successful_executions: 0,
|
27
|
+
timeout_count: 0,
|
28
|
+
failure_count: 0,
|
29
|
+
average_duration: 0.0,
|
30
|
+
total_duration: 0.0
|
31
|
+
}
|
32
|
+
@job_context = nil
|
33
|
+
end
|
34
|
+
|
35
|
+
# Abstract method - must be implemented by subclasses
|
36
|
+
def command
|
37
|
+
raise NotImplementedError, "#{self.class} must implement #command"
|
38
|
+
end
|
39
|
+
|
40
|
+
# Abstract method - must be implemented by subclasses
|
41
|
+
def provider_name
|
42
|
+
raise NotImplementedError, "#{self.class} must implement #provider_name"
|
43
|
+
end
|
44
|
+
|
45
|
+
# Set job context for background execution
|
46
|
+
def set_job_context(job_id:, execution_id:, job_manager:)
|
47
|
+
@job_context = {
|
48
|
+
job_id: job_id,
|
49
|
+
execution_id: execution_id,
|
50
|
+
job_manager: job_manager
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
# Execute with supervision and recovery
|
55
|
+
def send(prompt:, session: nil)
|
56
|
+
timeout_seconds = calculate_timeout
|
57
|
+
debug = ENV["AIDP_DEBUG"] == "1"
|
58
|
+
|
59
|
+
log_info("Executing with #{provider_name} provider (timeout: #{timeout_seconds}s)")
|
60
|
+
|
61
|
+
# Create supervisor
|
62
|
+
supervisor = AgentSupervisor.new(
|
63
|
+
command,
|
64
|
+
timeout_seconds: timeout_seconds,
|
65
|
+
debug: debug
|
66
|
+
)
|
67
|
+
|
68
|
+
begin
|
69
|
+
# Execute with supervision
|
70
|
+
result = supervisor.execute(prompt)
|
71
|
+
|
72
|
+
# Update metrics
|
73
|
+
update_metrics(supervisor, result)
|
74
|
+
|
75
|
+
# Store result for debugging
|
76
|
+
@last_execution_result = result
|
77
|
+
|
78
|
+
if result[:success]
|
79
|
+
log_info("#{provider_name} completed successfully in #{format_duration(result[:duration])}")
|
80
|
+
result[:output]
|
81
|
+
else
|
82
|
+
handle_execution_failure(result, supervisor)
|
83
|
+
end
|
84
|
+
rescue => e
|
85
|
+
log_error("#{provider_name} execution error: #{e.message}")
|
86
|
+
|
87
|
+
# Try to kill the process if it's still running
|
88
|
+
supervisor.kill! if supervisor.active?
|
89
|
+
|
90
|
+
raise
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Get execution statistics
|
95
|
+
def stats
|
96
|
+
@metrics.dup
|
97
|
+
end
|
98
|
+
|
99
|
+
# Reset statistics
|
100
|
+
def reset_stats!
|
101
|
+
@metrics = {
|
102
|
+
total_executions: 0,
|
103
|
+
successful_executions: 0,
|
104
|
+
timeout_count: 0,
|
105
|
+
failure_count: 0,
|
106
|
+
average_duration: 0.0,
|
107
|
+
total_duration: 0.0
|
108
|
+
}
|
109
|
+
end
|
110
|
+
|
111
|
+
# Check if provider supports activity monitoring
|
112
|
+
def supports_activity_monitoring?
|
113
|
+
true # Supervised providers always support activity monitoring
|
114
|
+
end
|
115
|
+
|
116
|
+
# Get activity summary for metrics (compatibility with old interface)
|
117
|
+
def activity_summary
|
118
|
+
return {} unless @last_execution_result
|
119
|
+
|
120
|
+
{
|
121
|
+
provider: provider_name,
|
122
|
+
step_name: ENV["AIDP_CURRENT_STEP"],
|
123
|
+
start_time: @last_execution_result[:start_time],
|
124
|
+
end_time: @last_execution_result[:end_time],
|
125
|
+
duration: @last_execution_result[:duration],
|
126
|
+
final_state: @last_execution_result[:state],
|
127
|
+
stuck_detected: false, # Supervisor handles this differently
|
128
|
+
output_count: @last_execution_result[:output_count] || 0
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
132
|
+
# Compatibility methods for old activity monitoring interface
|
133
|
+
def setup_activity_monitoring(step_name, callback = nil, timeout = nil)
|
134
|
+
# No-op for supervised providers - supervisor handles this
|
135
|
+
end
|
136
|
+
|
137
|
+
def record_activity(message = nil)
|
138
|
+
# No-op for supervised providers - supervisor handles this
|
139
|
+
end
|
140
|
+
|
141
|
+
def mark_completed
|
142
|
+
# No-op for supervised providers - supervisor handles this
|
143
|
+
end
|
144
|
+
|
145
|
+
def mark_failed(message = nil)
|
146
|
+
# No-op for supervised providers - supervisor handles this
|
147
|
+
end
|
148
|
+
|
149
|
+
private
|
150
|
+
|
151
|
+
def calculate_timeout
|
152
|
+
# Priority order for timeout calculation:
|
153
|
+
# 1. Quick mode (for testing)
|
154
|
+
# 2. Environment variable override
|
155
|
+
# 3. Adaptive timeout based on step type
|
156
|
+
# 4. Default timeout
|
157
|
+
|
158
|
+
if ENV["AIDP_QUICK_MODE"]
|
159
|
+
log_info("Quick mode enabled - #{QUICK_MODE_TIMEOUT / 60} minute timeout")
|
160
|
+
return QUICK_MODE_TIMEOUT
|
161
|
+
end
|
162
|
+
|
163
|
+
provider_timeout_var = "AIDP_#{provider_name.upcase}_TIMEOUT"
|
164
|
+
if ENV[provider_timeout_var]
|
165
|
+
return ENV[provider_timeout_var].to_i
|
166
|
+
end
|
167
|
+
|
168
|
+
# Adaptive timeout based on step type
|
169
|
+
step_timeout = get_adaptive_timeout
|
170
|
+
if step_timeout
|
171
|
+
log_info("Using adaptive timeout: #{step_timeout} seconds")
|
172
|
+
return step_timeout
|
173
|
+
end
|
174
|
+
|
175
|
+
# Default timeout for interactive use
|
176
|
+
log_info("Using default timeout: #{DEFAULT_TIMEOUT / 60} minutes")
|
177
|
+
DEFAULT_TIMEOUT
|
178
|
+
end
|
179
|
+
|
180
|
+
def get_adaptive_timeout
|
181
|
+
# Try to get timeout recommendations from metrics storage
|
182
|
+
begin
|
183
|
+
require_relative "../analyze/metrics_storage"
|
184
|
+
storage = Aidp::Analyze::MetricsStorage.new(Dir.pwd)
|
185
|
+
recommendations = storage.calculate_timeout_recommendations
|
186
|
+
|
187
|
+
# Get current step name from environment or context
|
188
|
+
step_name = ENV["AIDP_CURRENT_STEP"] || "unknown"
|
189
|
+
|
190
|
+
if recommendations[step_name]
|
191
|
+
recommended = recommendations[step_name][:recommended_timeout]
|
192
|
+
# Add buffer for safety
|
193
|
+
return (recommended * ADAPTIVE_TIMEOUT_BUFFER).ceil
|
194
|
+
end
|
195
|
+
rescue => e
|
196
|
+
log_warning("Could not get adaptive timeout: #{e.message}") if ENV["AIDP_DEBUG"]
|
197
|
+
end
|
198
|
+
|
199
|
+
# Fallback timeouts based on step type patterns
|
200
|
+
step_name = ENV["AIDP_CURRENT_STEP"] || ""
|
201
|
+
|
202
|
+
case step_name
|
203
|
+
when /REPOSITORY_ANALYSIS/
|
204
|
+
REPOSITORY_ANALYSIS_TIMEOUT
|
205
|
+
when /ARCHITECTURE_ANALYSIS/
|
206
|
+
ARCHITECTURE_ANALYSIS_TIMEOUT
|
207
|
+
when /TEST_ANALYSIS/
|
208
|
+
TEST_ANALYSIS_TIMEOUT
|
209
|
+
when /FUNCTIONALITY_ANALYSIS/
|
210
|
+
FUNCTIONALITY_ANALYSIS_TIMEOUT
|
211
|
+
when /DOCUMENTATION_ANALYSIS/
|
212
|
+
DOCUMENTATION_ANALYSIS_TIMEOUT
|
213
|
+
when /STATIC_ANALYSIS/
|
214
|
+
STATIC_ANALYSIS_TIMEOUT
|
215
|
+
when /REFACTORING_RECOMMENDATIONS/
|
216
|
+
REFACTORING_RECOMMENDATIONS_TIMEOUT
|
217
|
+
else
|
218
|
+
nil # Use default
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def update_metrics(supervisor, result)
|
223
|
+
@metrics[:total_executions] += 1
|
224
|
+
@metrics[:total_duration] += supervisor.duration
|
225
|
+
@metrics[:average_duration] = @metrics[:total_duration] / @metrics[:total_executions]
|
226
|
+
|
227
|
+
case result[:state]
|
228
|
+
when :completed
|
229
|
+
@metrics[:successful_executions] += 1
|
230
|
+
when :timeout
|
231
|
+
@metrics[:timeout_count] += 1
|
232
|
+
when :failed, :killed
|
233
|
+
@metrics[:failure_count] += 1
|
234
|
+
end
|
235
|
+
|
236
|
+
# Log metrics update if in job context
|
237
|
+
if @job_context
|
238
|
+
@job_context[:job_manager].log_message(
|
239
|
+
@job_context[:job_id],
|
240
|
+
@job_context[:execution_id],
|
241
|
+
"Updated execution metrics",
|
242
|
+
"debug",
|
243
|
+
@metrics
|
244
|
+
)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
def handle_execution_failure(result, supervisor)
|
249
|
+
case result[:reason]
|
250
|
+
when "user_aborted"
|
251
|
+
message = "#{provider_name} was aborted by user after #{format_duration(result[:duration])}"
|
252
|
+
log_error(message)
|
253
|
+
raise Interrupt, message
|
254
|
+
when "non_zero_exit"
|
255
|
+
error_msg = result[:error_output].empty? ? "Unknown error" : result[:error_output].strip
|
256
|
+
message = "#{provider_name} failed with exit code #{result[:exit_code]}: #{error_msg}"
|
257
|
+
log_error(message)
|
258
|
+
raise message
|
259
|
+
else
|
260
|
+
message = "#{provider_name} failed: #{result[:reason] || "Unknown error"}"
|
261
|
+
log_error(message)
|
262
|
+
raise message
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
def format_duration(seconds)
|
267
|
+
minutes = (seconds / 60).to_i
|
268
|
+
secs = (seconds % 60).to_i
|
269
|
+
|
270
|
+
if minutes > 0
|
271
|
+
"#{minutes}m #{secs}s"
|
272
|
+
else
|
273
|
+
"#{secs}s"
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
def log_info(message)
|
278
|
+
if @job_context
|
279
|
+
@job_context[:job_manager].log_message(
|
280
|
+
@job_context[:job_id],
|
281
|
+
@job_context[:execution_id],
|
282
|
+
message,
|
283
|
+
"info"
|
284
|
+
)
|
285
|
+
else
|
286
|
+
puts message
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
def log_warning(message)
|
291
|
+
if @job_context
|
292
|
+
@job_context[:job_manager].log_message(
|
293
|
+
@job_context[:job_id],
|
294
|
+
@job_context[:execution_id],
|
295
|
+
message,
|
296
|
+
"warning"
|
297
|
+
)
|
298
|
+
else
|
299
|
+
puts "⚠️ #{message}"
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
def log_error(message)
|
304
|
+
if @job_context
|
305
|
+
@job_context[:job_manager].log_message(
|
306
|
+
@job_context[:job_id],
|
307
|
+
@job_context[:execution_id],
|
308
|
+
message,
|
309
|
+
"error"
|
310
|
+
)
|
311
|
+
else
|
312
|
+
puts "❌ #{message}"
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "supervised_base"
|
4
|
+
require_relative "../util"
|
5
|
+
|
6
|
+
module Aidp
|
7
|
+
module Providers
|
8
|
+
class SupervisedCursor < SupervisedBase
|
9
|
+
def self.available?
|
10
|
+
!!Aidp::Util.which("cursor-agent")
|
11
|
+
end
|
12
|
+
|
13
|
+
def provider_name
|
14
|
+
"cursor"
|
15
|
+
end
|
16
|
+
|
17
|
+
def command
|
18
|
+
["cursor-agent", "-p"]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/aidp/version.rb
CHANGED
data/lib/aidp.rb
CHANGED
@@ -1,53 +1,50 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# Core extensions
|
4
|
+
require "aidp/core_ext/class_attribute"
|
5
|
+
|
3
6
|
# Shared modules
|
4
7
|
require "aidp/version"
|
5
8
|
require "aidp/config"
|
6
9
|
require "aidp/workspace"
|
7
10
|
require "aidp/util"
|
8
11
|
require "aidp/cli"
|
12
|
+
require "aidp/cli/jobs_command"
|
9
13
|
require "aidp/project_detector"
|
10
14
|
require "aidp/sync"
|
15
|
+
|
16
|
+
# Database
|
17
|
+
require "aidp/database_connection"
|
18
|
+
|
19
|
+
# Job infrastructure
|
20
|
+
require "aidp/job_manager"
|
21
|
+
require "aidp/jobs/base_job"
|
22
|
+
require "aidp/jobs/provider_execution_job"
|
23
|
+
|
24
|
+
# Providers
|
11
25
|
require "aidp/providers/base"
|
12
26
|
require "aidp/providers/cursor"
|
13
27
|
require "aidp/providers/anthropic"
|
14
28
|
require "aidp/providers/gemini"
|
15
29
|
require "aidp/providers/macos_ui"
|
30
|
+
require "aidp/provider_manager"
|
16
31
|
|
17
|
-
#
|
18
|
-
require "aidp/
|
19
|
-
require "aidp/
|
20
|
-
require "aidp/
|
21
|
-
|
22
|
-
# Analyze mode modules
|
23
|
-
require "aidp/analyze/steps"
|
32
|
+
# Analyze mode
|
33
|
+
require "aidp/analyze/error_handler"
|
34
|
+
require "aidp/analyze/parallel_processor"
|
35
|
+
require "aidp/analyze/repository_chunker"
|
36
|
+
require "aidp/analyze/ruby_maat_integration"
|
24
37
|
require "aidp/analyze/runner"
|
38
|
+
require "aidp/analyze/steps"
|
25
39
|
require "aidp/analyze/progress"
|
26
|
-
require "aidp/analyze/dependencies"
|
27
|
-
require "aidp/analyze/storage"
|
28
|
-
require "aidp/analyze/prioritizer"
|
29
|
-
require "aidp/analyze/database"
|
30
|
-
require "aidp/analyze/ruby_maat_integration"
|
31
|
-
require "aidp/analyze/feature_analyzer"
|
32
|
-
require "aidp/analyze/focus_guidance"
|
33
|
-
require "aidp/analyze/agent_personas"
|
34
|
-
require "aidp/analyze/agent_tool_executor"
|
35
|
-
require "aidp/analyze/static_analysis_detector"
|
36
|
-
require "aidp/analyze/tool_configuration"
|
37
|
-
require "aidp/analyze/tool_modernization"
|
38
|
-
require "aidp/analyze/language_analysis_strategies"
|
39
|
-
require "aidp/analyze/report_generator"
|
40
|
-
require "aidp/analyze/export_manager"
|
41
|
-
require "aidp/analyze/incremental_analyzer"
|
42
|
-
require "aidp/analyze/progress_visualizer"
|
43
|
-
require "aidp/analyze/data_retention_manager"
|
44
|
-
require "aidp/analyze/repository_chunker"
|
45
|
-
require "aidp/analyze/parallel_processor"
|
46
|
-
require "aidp/analyze/memory_manager"
|
47
|
-
require "aidp/analyze/large_analysis_progress"
|
48
|
-
require "aidp/analyze/performance_optimizer"
|
49
|
-
require "aidp/analyze/error_handler"
|
50
40
|
|
51
|
-
|
52
|
-
|
53
|
-
|
41
|
+
# Tree-sitter analysis
|
42
|
+
require "aidp/analysis/tree_sitter_grammar_loader"
|
43
|
+
require "aidp/analysis/seams"
|
44
|
+
require "aidp/analysis/tree_sitter_scan"
|
45
|
+
require "aidp/analysis/kb_inspector"
|
46
|
+
|
47
|
+
# Execute mode
|
48
|
+
require "aidp/execute/steps"
|
49
|
+
require "aidp/execute/runner"
|
50
|
+
require "aidp/execute/progress"
|
@@ -13,7 +13,7 @@ You are a **Repository Analyst**, an expert in version control analysis and code
|
|
13
13
|
|
14
14
|
## Analysis Objectives
|
15
15
|
|
16
|
-
1. **Repository Mining**: Use
|
16
|
+
1. **Repository Mining**: Use ruby-maat gem to analyze repository activity
|
17
17
|
2. **Churn Analysis**: Identify high-activity areas that may indicate technical debt
|
18
18
|
3. **Coupling Analysis**: Understand dependencies between modules/components
|
19
19
|
4. **Authorship Patterns**: Analyze code ownership and knowledge distribution
|
@@ -21,10 +21,10 @@ You are a **Repository Analyst**, an expert in version control analysis and code
|
|
21
21
|
|
22
22
|
## Required Analysis Steps
|
23
23
|
|
24
|
-
### 1.
|
24
|
+
### 1. Ruby Maat Integration
|
25
25
|
|
26
|
-
-
|
27
|
-
- Run
|
26
|
+
- Use the ruby-maat gem for repository analysis (no Docker required)
|
27
|
+
- Run ruby-maat analysis for the repository
|
28
28
|
- Parse and interpret the results
|
29
29
|
|
30
30
|
### 2. Repository Activity Analysis
|
@@ -0,0 +1,217 @@
|
|
1
|
+
# Tree-sitter Static Analysis Template
|
2
|
+
|
3
|
+
You are a **Tree-sitter Static Analysis Expert**, specializing in advanced static code analysis using Tree-sitter parsers. Your role is to analyze the codebase using Tree-sitter-powered static analysis, build a comprehensive knowledge base, and provide insights based on Michael Feathers' "Working Effectively with Legacy Code" strategies.
|
4
|
+
|
5
|
+
## Your Expertise
|
6
|
+
|
7
|
+
- Tree-sitter parser technology and AST analysis
|
8
|
+
- Static code analysis and metrics calculation
|
9
|
+
- Legacy code refactoring strategies (Feathers' techniques)
|
10
|
+
- Seam detection and dependency analysis
|
11
|
+
- Code complexity and hotspot identification
|
12
|
+
- Test coverage analysis and characterization test recommendations
|
13
|
+
|
14
|
+
## Analysis Objectives
|
15
|
+
|
16
|
+
1. **Knowledge Base Construction**: Build a comprehensive machine-readable knowledge base of the codebase structure
|
17
|
+
2. **Seam Detection**: Identify integration points and dependency injection opportunities using Feathers' strategies
|
18
|
+
3. **Hotspot Analysis**: Identify high-change, high-complexity areas that need attention
|
19
|
+
4. **Dependency Mapping**: Map import/require relationships and detect cycles
|
20
|
+
5. **Test Gap Analysis**: Identify untested public APIs and recommend characterization tests
|
21
|
+
6. **Refactoring Opportunities**: Provide specific, actionable refactoring recommendations
|
22
|
+
|
23
|
+
## Required Analysis Steps
|
24
|
+
|
25
|
+
### 1. Tree-sitter Knowledge Base Generation
|
26
|
+
|
27
|
+
Run the Tree-sitter analysis to generate the knowledge base:
|
28
|
+
|
29
|
+
```bash
|
30
|
+
aidp analyze code --langs ruby,js,ts,py --threads 4
|
31
|
+
```
|
32
|
+
|
33
|
+
This will generate the following KB files in `.aidp/kb/`:
|
34
|
+
|
35
|
+
- `symbols.json` - Classes, modules, methods with metadata
|
36
|
+
- `imports.json` - Require/import statements and dependencies
|
37
|
+
- `calls.json` - Method call relationships
|
38
|
+
- `metrics.json` - Complexity and size metrics
|
39
|
+
- `seams.json` - Integration points and dependency injection opportunities
|
40
|
+
- `hotspots.json` - High-change, high-complexity areas
|
41
|
+
- `tests.json` - Test coverage mapping
|
42
|
+
- `cycles.json` - Import/dependency cycles
|
43
|
+
|
44
|
+
### 2. Seam Analysis and Feathers' Strategy Application
|
45
|
+
|
46
|
+
Analyze the seams data to identify refactoring opportunities:
|
47
|
+
|
48
|
+
#### I/O Integration Seams
|
49
|
+
|
50
|
+
- **File Operations**: `File.*`, `IO.*`, `Dir.*` calls
|
51
|
+
- **Network Operations**: `Net::HTTP.*`, `Socket.*` calls
|
52
|
+
- **System Operations**: `Kernel.system`, `Process.*` calls
|
53
|
+
- **Database Operations**: `ActiveRecord.*`, `Sequel.*` calls
|
54
|
+
|
55
|
+
**Feathers' Recommendations**:
|
56
|
+
|
57
|
+
- Extract I/O operations to separate service classes
|
58
|
+
- Use dependency injection for external dependencies
|
59
|
+
- Create adapter interfaces for external services
|
60
|
+
|
61
|
+
#### Global State and Singleton Seams
|
62
|
+
|
63
|
+
- **Global Variables**: `$var`, `@@var` usage
|
64
|
+
- **Singleton Patterns**: `include Singleton`, `extend Singleton`
|
65
|
+
- **Module-level State**: Mutable state in modules
|
66
|
+
|
67
|
+
**Feathers' Recommendations**:
|
68
|
+
|
69
|
+
- Replace singletons with dependency injection
|
70
|
+
- Encapsulate global state in configuration objects
|
71
|
+
- Use constructor injection for dependencies
|
72
|
+
|
73
|
+
#### Constructor with Work Seams
|
74
|
+
|
75
|
+
- **Complex Initialization**: Constructors with significant logic
|
76
|
+
- **External Dependencies**: I/O or service calls in constructors
|
77
|
+
- **High Complexity**: Constructors with multiple branches
|
78
|
+
|
79
|
+
**Feathers' Recommendations**:
|
80
|
+
|
81
|
+
- Extract initialization logic to factory methods
|
82
|
+
- Use builder pattern for complex object creation
|
83
|
+
- Separate construction from initialization
|
84
|
+
|
85
|
+
### 3. Hotspot Analysis and Prioritization
|
86
|
+
|
87
|
+
Analyze the hotspots data to prioritize refactoring efforts:
|
88
|
+
|
89
|
+
#### Hotspot Scoring
|
90
|
+
|
91
|
+
- **Change Frequency**: Number of times files have been modified
|
92
|
+
- **Complexity**: Cyclomatic complexity and nesting depth
|
93
|
+
- **Size**: Lines of code and method count
|
94
|
+
- **Dependencies**: Fan-in and fan-out metrics
|
95
|
+
|
96
|
+
#### Top 20 Hotspots Analysis
|
97
|
+
|
98
|
+
For each hotspot, provide:
|
99
|
+
|
100
|
+
- **Rationale**: Why this area is a hotspot
|
101
|
+
- **Risk Assessment**: Potential impact of changes
|
102
|
+
- **Refactoring Strategy**: Specific Feathers' techniques to apply
|
103
|
+
- **Test Strategy**: Characterization test recommendations
|
104
|
+
|
105
|
+
### 4. Dependency Cycle Detection
|
106
|
+
|
107
|
+
Analyze import cycles and provide breaking strategies:
|
108
|
+
|
109
|
+
#### Cycle Types
|
110
|
+
|
111
|
+
- **Import Cycles**: Circular require/import dependencies
|
112
|
+
- **Call Cycles**: Circular method call dependencies
|
113
|
+
- **Inheritance Cycles**: Circular class inheritance
|
114
|
+
|
115
|
+
#### Breaking Strategies
|
116
|
+
|
117
|
+
- **Dependency Inversion**: Extract interfaces and invert dependencies
|
118
|
+
- **Event-Driven Architecture**: Use events to decouple components
|
119
|
+
- **Facade Pattern**: Create facades to break direct dependencies
|
120
|
+
|
121
|
+
### 5. Test Coverage Analysis
|
122
|
+
|
123
|
+
Analyze untested public APIs and recommend characterization tests:
|
124
|
+
|
125
|
+
#### Characterization Test Strategy
|
126
|
+
|
127
|
+
- **Public API Mapping**: Identify all public methods and classes
|
128
|
+
- **Test Coverage**: Map existing tests to public APIs
|
129
|
+
- **Gap Analysis**: Identify untested public APIs
|
130
|
+
- **Test Recommendations**: Suggest specific characterization tests
|
131
|
+
|
132
|
+
#### Test Implementation Guidelines
|
133
|
+
|
134
|
+
- **Golden Master Tests**: Capture current behavior before refactoring
|
135
|
+
- **Parameterized Tests**: Test with various inputs
|
136
|
+
- **Integration Tests**: Test with real dependencies
|
137
|
+
- **Mock Tests**: Test with controlled dependencies
|
138
|
+
|
139
|
+
## Output Requirements
|
140
|
+
|
141
|
+
### 1. Knowledge Base Summary
|
142
|
+
|
143
|
+
- Total files analyzed
|
144
|
+
- Symbol counts by type (classes, modules, methods)
|
145
|
+
- Import/dependency statistics
|
146
|
+
- Complexity metrics summary
|
147
|
+
|
148
|
+
### 2. Seam Analysis Report
|
149
|
+
|
150
|
+
- **I/O Integration Seams**: List with file locations and refactoring suggestions
|
151
|
+
- **Global State Seams**: List with specific global usage and encapsulation strategies
|
152
|
+
- **Constructor Work Seams**: List with complexity metrics and extraction recommendations
|
153
|
+
|
154
|
+
### 3. Hotspot Analysis Report
|
155
|
+
|
156
|
+
- **Top 20 Hotspots**: Ranked list with scores and rationale
|
157
|
+
- **Refactoring Priorities**: Recommended order for addressing hotspots
|
158
|
+
- **Risk Assessment**: Impact analysis for each hotspot
|
159
|
+
|
160
|
+
### 4. Dependency Analysis Report
|
161
|
+
|
162
|
+
- **Import Graph**: Visualization of file dependencies
|
163
|
+
- **Cycle Detection**: List of detected cycles with breaking strategies
|
164
|
+
- **Coupling Analysis**: High-coupling areas and decoupling recommendations
|
165
|
+
|
166
|
+
### 5. Test Strategy Report
|
167
|
+
|
168
|
+
- **Untested APIs**: List of public APIs without tests
|
169
|
+
- **Characterization Test Plan**: Specific test recommendations
|
170
|
+
- **Test Implementation Guide**: Step-by-step test creation process
|
171
|
+
|
172
|
+
### 6. Refactoring Roadmap
|
173
|
+
|
174
|
+
- **Phase 1**: Address highest-priority seams and hotspots
|
175
|
+
- **Phase 2**: Break dependency cycles
|
176
|
+
- **Phase 3**: Implement characterization tests
|
177
|
+
- **Phase 4**: Apply systematic refactoring techniques
|
178
|
+
|
179
|
+
## Technical Implementation Notes
|
180
|
+
|
181
|
+
### Tree-sitter Integration
|
182
|
+
|
183
|
+
- Use `aidp analyze code` command to generate KB
|
184
|
+
- Leverage `aidp kb show` commands for data inspection
|
185
|
+
- Generate graphs with `aidp kb graph` for visualization
|
186
|
+
|
187
|
+
### Feathers' Techniques Application
|
188
|
+
|
189
|
+
- **Sprout Method**: Extract small methods from large ones
|
190
|
+
- **Sprout Class**: Extract new classes for specific responsibilities
|
191
|
+
- **Extract Interface**: Create interfaces for dependency injection
|
192
|
+
- **Move Method**: Move methods to appropriate classes
|
193
|
+
- **Extract Method**: Break down large methods
|
194
|
+
|
195
|
+
### Quality Metrics
|
196
|
+
|
197
|
+
- **Cyclomatic Complexity**: Target < 10 per method
|
198
|
+
- **Lines of Code**: Target < 20 per method
|
199
|
+
- **Fan-out**: Target < 7 per method
|
200
|
+
- **Nesting Depth**: Target < 4 levels
|
201
|
+
|
202
|
+
## Success Criteria
|
203
|
+
|
204
|
+
1. **Complete KB Generation**: All source files parsed and analyzed
|
205
|
+
2. **Seam Identification**: All integration points identified with specific recommendations
|
206
|
+
3. **Hotspot Prioritization**: Top 20 hotspots identified with actionable strategies
|
207
|
+
4. **Cycle Detection**: All dependency cycles identified with breaking strategies
|
208
|
+
5. **Test Gap Analysis**: All untested public APIs identified with test recommendations
|
209
|
+
6. **Refactoring Roadmap**: Prioritized, actionable refactoring plan provided
|
210
|
+
|
211
|
+
## Deliverables
|
212
|
+
|
213
|
+
1. **Knowledge Base Files**: Complete `.aidp/kb/` directory with all JSON files
|
214
|
+
2. **Analysis Report**: Comprehensive markdown report with all findings
|
215
|
+
3. **Visualization Files**: Graph files for dependency visualization
|
216
|
+
4. **Refactoring Plan**: Detailed, prioritized refactoring roadmap
|
217
|
+
5. **Test Strategy**: Specific characterization test recommendations
|