aidp 0.10.0 → 0.11.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 +194 -25
- data/lib/aidp/analyze/kb_inspector.rb +2 -15
- data/lib/aidp/analyze/progress.rb +2 -1
- data/lib/aidp/analyze/ruby_maat_integration.rb +2 -15
- data/lib/aidp/analyze/runner.rb +64 -20
- data/lib/aidp/analyze/steps.rb +10 -8
- data/lib/aidp/analyze/tree_sitter_grammar_loader.rb +2 -13
- data/lib/aidp/analyze/tree_sitter_scan.rb +2 -13
- data/lib/aidp/cli/checkpoint_command.rb +98 -0
- data/lib/aidp/cli/first_run_wizard.rb +65 -94
- data/lib/aidp/cli/jobs_command.rb +249 -34
- data/lib/aidp/cli.rb +312 -38
- data/lib/aidp/config.rb +5 -8
- data/lib/aidp/debug_logger.rb +4 -4
- data/lib/aidp/debug_mixin.rb +11 -4
- data/lib/aidp/execute/checkpoint.rb +282 -0
- data/lib/aidp/execute/checkpoint_display.rb +221 -0
- data/lib/aidp/execute/progress.rb +2 -1
- data/lib/aidp/execute/prompt_manager.rb +62 -0
- data/lib/aidp/execute/runner.rb +53 -24
- data/lib/aidp/execute/steps.rb +36 -27
- data/lib/aidp/execute/work_loop_runner.rb +308 -0
- data/lib/aidp/execute/workflow_selector.rb +26 -17
- data/lib/aidp/harness/condition_detector.rb +4 -4
- data/lib/aidp/harness/config_schema.rb +40 -0
- data/lib/aidp/harness/config_validator.rb +3 -6
- data/lib/aidp/harness/configuration.rb +35 -1
- data/lib/aidp/harness/enhanced_runner.rb +22 -1
- data/lib/aidp/harness/error_handler.rb +103 -28
- data/lib/aidp/harness/provider_factory.rb +4 -1
- data/lib/aidp/harness/provider_manager.rb +250 -15
- data/lib/aidp/harness/runner.rb +3 -14
- data/lib/aidp/harness/simple_user_interface.rb +2 -15
- data/lib/aidp/harness/status_display.rb +12 -17
- data/lib/aidp/harness/test_runner.rb +83 -0
- data/lib/aidp/harness/ui/enhanced_tui.rb +2 -0
- data/lib/aidp/harness/ui/enhanced_workflow_selector.rb +22 -4
- data/lib/aidp/harness/ui/error_handler.rb +4 -0
- data/lib/aidp/harness/ui/frame_manager.rb +10 -8
- data/lib/aidp/harness/ui/job_monitor.rb +2 -0
- data/lib/aidp/harness/ui/navigation/main_menu.rb +4 -2
- data/lib/aidp/harness/ui/navigation/menu_item.rb +1 -0
- data/lib/aidp/harness/ui/navigation/menu_state.rb +1 -0
- data/lib/aidp/harness/ui/navigation/submenu.rb +1 -0
- data/lib/aidp/harness/ui/navigation/workflow_selector.rb +2 -0
- data/lib/aidp/harness/ui/progress_display.rb +8 -12
- data/lib/aidp/harness/ui/question_collector.rb +2 -0
- data/lib/aidp/harness/ui/spinner_group.rb +2 -0
- data/lib/aidp/harness/ui/spinner_helper.rb +1 -1
- data/lib/aidp/harness/ui/status_manager.rb +4 -2
- data/lib/aidp/harness/ui/status_widget.rb +3 -1
- data/lib/aidp/harness/ui/workflow_controller.rb +2 -0
- data/lib/aidp/harness/user_interface.rb +12 -17
- data/lib/aidp/jobs/background_runner.rb +278 -0
- data/lib/aidp/message_display.rb +48 -0
- data/lib/aidp/provider_manager.rb +3 -1
- data/lib/aidp/providers/anthropic.rb +100 -17
- data/lib/aidp/providers/base.rb +42 -11
- data/lib/aidp/providers/codex.rb +248 -0
- data/lib/aidp/providers/cursor.rb +35 -42
- data/lib/aidp/providers/gemini.rb +25 -15
- data/lib/aidp/providers/github_copilot.rb +41 -42
- data/lib/aidp/providers/opencode.rb +34 -41
- data/lib/aidp/version.rb +1 -1
- data/lib/aidp/workflows/definitions.rb +357 -0
- data/lib/aidp/workflows/selector.rb +171 -0
- data/lib/aidp.rb +12 -0
- data/templates/planning/generate_llm_style_guide.md +119 -0
- metadata +38 -26
- /data/templates/{ANALYZE/02_ARCHITECTURE_ANALYSIS.md → analysis/analyze_architecture.md} +0 -0
- /data/templates/{ANALYZE/05_DOCUMENTATION_ANALYSIS.md → analysis/analyze_documentation.md} +0 -0
- /data/templates/{ANALYZE/04_FUNCTIONALITY_ANALYSIS.md → analysis/analyze_functionality.md} +0 -0
- /data/templates/{ANALYZE/01_REPOSITORY_ANALYSIS.md → analysis/analyze_repository.md} +0 -0
- /data/templates/{ANALYZE/06_STATIC_ANALYSIS.md → analysis/analyze_static_code.md} +0 -0
- /data/templates/{ANALYZE/03_TEST_ANALYSIS.md → analysis/analyze_tests.md} +0 -0
- /data/templates/{ANALYZE/07_REFACTORING_RECOMMENDATIONS.md → analysis/recommend_refactoring.md} +0 -0
- /data/templates/{ANALYZE/06a_tree_sitter_scan.md → analysis/scan_with_tree_sitter.md} +0 -0
- /data/templates/{EXECUTE/11_STATIC_ANALYSIS.md → implementation/configure_static_analysis.md} +0 -0
- /data/templates/{EXECUTE/14_DOCS_PORTAL.md → implementation/create_documentation_portal.md} +0 -0
- /data/templates/{EXECUTE/10_IMPLEMENTATION_AGENT.md → implementation/implement_features.md} +0 -0
- /data/templates/{EXECUTE/13_DELIVERY_ROLLOUT.md → implementation/plan_delivery.md} +0 -0
- /data/templates/{EXECUTE/15_POST_RELEASE.md → implementation/review_post_release.md} +0 -0
- /data/templates/{EXECUTE/09_SCAFFOLDING_DEVEX.md → implementation/setup_scaffolding.md} +0 -0
- /data/templates/{EXECUTE/02A_ARCH_GATE_QUESTIONS.md → planning/ask_architecture_questions.md} +0 -0
- /data/templates/{EXECUTE/00_PRD.md → planning/create_prd.md} +0 -0
- /data/templates/{EXECUTE/08_TASKS.md → planning/create_tasks.md} +0 -0
- /data/templates/{EXECUTE/04_DOMAIN_DECOMPOSITION.md → planning/decompose_domain.md} +0 -0
- /data/templates/{EXECUTE/01_NFRS.md → planning/define_nfrs.md} +0 -0
- /data/templates/{EXECUTE/05_CONTRACTS.md → planning/design_apis.md} +0 -0
- /data/templates/{EXECUTE/02_ARCHITECTURE.md → planning/design_architecture.md} +0 -0
- /data/templates/{EXECUTE/06_THREAT_MODEL.md → planning/design_data_model.md} +0 -0
- /data/templates/{EXECUTE/03_ADR_FACTORY.md → planning/generate_adrs.md} +0 -0
- /data/templates/{EXECUTE/12_OBSERVABILITY_SLOS.md → planning/plan_observability.md} +0 -0
- /data/templates/{EXECUTE/07_TEST_PLAN.md → planning/plan_testing.md} +0 -0
@@ -18,6 +18,10 @@ module Aidp
|
|
18
18
|
"opencode"
|
19
19
|
end
|
20
20
|
|
21
|
+
def display_name
|
22
|
+
"OpenCode"
|
23
|
+
end
|
24
|
+
|
21
25
|
def send(prompt:, session: nil)
|
22
26
|
raise "opencode not available" unless self.class.available?
|
23
27
|
|
@@ -27,6 +31,12 @@ module Aidp
|
|
27
31
|
debug_provider("opencode", "Starting execution", {timeout: timeout_seconds})
|
28
32
|
debug_log("📝 Sending prompt to opencode (length: #{prompt.length})", level: :info)
|
29
33
|
|
34
|
+
# Check if streaming mode is enabled
|
35
|
+
streaming_enabled = ENV["AIDP_STREAMING"] == "1" || ENV["DEBUG"] == "1"
|
36
|
+
if streaming_enabled
|
37
|
+
display_message("📺 Display streaming enabled - output buffering reduced (opencode does not support true streaming)", type: :info)
|
38
|
+
end
|
39
|
+
|
30
40
|
# Check if prompt is too large and warn
|
31
41
|
if prompt.length > 3000
|
32
42
|
debug_log("⚠️ Large prompt detected (#{prompt.length} chars) - this may cause rate limiting", level: :warn)
|
@@ -36,6 +46,10 @@ module Aidp
|
|
36
46
|
setup_activity_monitoring("opencode", method(:activity_callback))
|
37
47
|
record_activity("Starting opencode execution")
|
38
48
|
|
49
|
+
# Create a spinner for activity display
|
50
|
+
spinner = TTY::Spinner.new("[:spinner] :title", format: :dots, hide_cursor: true)
|
51
|
+
spinner.auto_spin
|
52
|
+
|
39
53
|
# Start activity display thread with timeout
|
40
54
|
activity_display_thread = Thread.new do
|
41
55
|
start_time = Time.now
|
@@ -46,7 +60,7 @@ module Aidp
|
|
46
60
|
# Break if we've been running too long or state changed
|
47
61
|
break if elapsed > timeout_seconds || @activity_state == :completed || @activity_state == :failed
|
48
62
|
|
49
|
-
|
63
|
+
update_spinner_status(spinner, elapsed, "🔄 opencode")
|
50
64
|
end
|
51
65
|
end
|
52
66
|
|
@@ -54,54 +68,33 @@ module Aidp
|
|
54
68
|
# Use debug_execute_command for better debugging
|
55
69
|
# opencode run command with prompt and model
|
56
70
|
model = ENV["OPENCODE_MODEL"] || "github-copilot/claude-3.5-sonnet"
|
57
|
-
result = debug_execute_command("opencode", args: ["run", "-m", model, prompt], timeout: timeout_seconds)
|
71
|
+
result = debug_execute_command("opencode", args: ["run", "-m", model, prompt], timeout: timeout_seconds, streaming: streaming_enabled)
|
58
72
|
|
59
73
|
# Log the results
|
60
74
|
debug_command("opencode", args: ["run", "-m", model, prompt], input: nil, output: result.out, error: result.err, exit_code: result.exit_status)
|
61
75
|
|
62
|
-
# Stop activity display
|
63
|
-
activity_display_thread.kill if activity_display_thread.alive?
|
64
|
-
activity_display_thread.join(0.1) # Give it 100ms to finish
|
65
|
-
clear_activity_status
|
66
|
-
|
67
76
|
if result.exit_status == 0
|
77
|
+
spinner.success("✓")
|
68
78
|
mark_completed
|
69
79
|
result.out
|
70
80
|
else
|
81
|
+
spinner.error("✗")
|
71
82
|
mark_failed("opencode failed with exit code #{result.exit_status}")
|
72
83
|
debug_error(StandardError.new("opencode failed"), {exit_code: result.exit_status, stderr: result.err})
|
73
84
|
raise "opencode failed with exit code #{result.exit_status}: #{result.err}"
|
74
85
|
end
|
75
86
|
rescue => e
|
76
|
-
|
77
|
-
activity_display_thread.kill if activity_display_thread.alive?
|
78
|
-
activity_display_thread.join(0.1) # Give it 100ms to finish
|
79
|
-
clear_activity_status
|
87
|
+
spinner&.error("✗")
|
80
88
|
mark_failed("opencode execution failed: #{e.message}")
|
81
89
|
debug_error(e, {provider: "opencode", prompt_length: prompt.length})
|
82
90
|
raise
|
91
|
+
ensure
|
92
|
+
cleanup_activity_display(activity_display_thread, spinner)
|
83
93
|
end
|
84
94
|
end
|
85
95
|
|
86
96
|
private
|
87
97
|
|
88
|
-
def print_activity_status(elapsed)
|
89
|
-
# Print activity status during opencode execution with elapsed time
|
90
|
-
minutes = (elapsed / 60).to_i
|
91
|
-
seconds = (elapsed % 60).to_i
|
92
|
-
|
93
|
-
if minutes > 0
|
94
|
-
print "\r🔄 opencode is running... (#{minutes}m #{seconds}s)"
|
95
|
-
else
|
96
|
-
print "\r🔄 opencode is running... (#{seconds}s)"
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
def clear_activity_status
|
101
|
-
# Clear the activity status line
|
102
|
-
print "\r" + " " * 50 + "\r"
|
103
|
-
end
|
104
|
-
|
105
98
|
def calculate_timeout
|
106
99
|
# Priority order for timeout calculation:
|
107
100
|
# 1. Quick mode (for testing)
|
@@ -110,8 +103,8 @@ module Aidp
|
|
110
103
|
# 4. Default timeout
|
111
104
|
|
112
105
|
if ENV["AIDP_QUICK_MODE"]
|
113
|
-
display_message("⚡ Quick mode enabled -
|
114
|
-
return
|
106
|
+
display_message("⚡ Quick mode enabled - #{TIMEOUT_QUICK_MODE / 60} minute timeout", type: :highlight)
|
107
|
+
return TIMEOUT_QUICK_MODE
|
115
108
|
end
|
116
109
|
|
117
110
|
if ENV["AIDP_OPENCODE_TIMEOUT"]
|
@@ -125,9 +118,9 @@ module Aidp
|
|
125
118
|
return step_timeout
|
126
119
|
end
|
127
120
|
|
128
|
-
# Default timeout
|
129
|
-
display_message("📋 Using default timeout:
|
130
|
-
|
121
|
+
# Default timeout
|
122
|
+
display_message("📋 Using default timeout: #{TIMEOUT_DEFAULT / 60} minutes", type: :info)
|
123
|
+
TIMEOUT_DEFAULT
|
131
124
|
end
|
132
125
|
|
133
126
|
def get_adaptive_timeout
|
@@ -136,21 +129,21 @@ module Aidp
|
|
136
129
|
|
137
130
|
case step_name
|
138
131
|
when /REPOSITORY_ANALYSIS/
|
139
|
-
|
132
|
+
TIMEOUT_REPOSITORY_ANALYSIS
|
140
133
|
when /ARCHITECTURE_ANALYSIS/
|
141
|
-
|
134
|
+
TIMEOUT_ARCHITECTURE_ANALYSIS
|
142
135
|
when /TEST_ANALYSIS/
|
143
|
-
|
136
|
+
TIMEOUT_TEST_ANALYSIS
|
144
137
|
when /FUNCTIONALITY_ANALYSIS/
|
145
|
-
|
138
|
+
TIMEOUT_FUNCTIONALITY_ANALYSIS
|
146
139
|
when /DOCUMENTATION_ANALYSIS/
|
147
|
-
|
140
|
+
TIMEOUT_DOCUMENTATION_ANALYSIS
|
148
141
|
when /STATIC_ANALYSIS/
|
149
|
-
|
142
|
+
TIMEOUT_STATIC_ANALYSIS
|
150
143
|
when /REFACTORING_RECOMMENDATIONS/
|
151
|
-
|
144
|
+
TIMEOUT_REFACTORING_RECOMMENDATIONS
|
152
145
|
else
|
153
|
-
nil
|
146
|
+
nil # Use default
|
154
147
|
end
|
155
148
|
end
|
156
149
|
|
data/lib/aidp/version.rb
CHANGED
@@ -0,0 +1,357 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Aidp
|
4
|
+
module Workflows
|
5
|
+
# Centralized workflow definitions for both Analyze and Execute modes
|
6
|
+
# Provides pre-configured workflows at various levels of depth/complexity
|
7
|
+
module Definitions
|
8
|
+
# Analyze mode workflows - from surface-level to deep analysis
|
9
|
+
ANALYZE_WORKFLOWS = {
|
10
|
+
quick_overview: {
|
11
|
+
name: "Quick Overview",
|
12
|
+
description: "Surface-level understanding - What does this project do?",
|
13
|
+
icon: "🔍",
|
14
|
+
details: [
|
15
|
+
"Repository structure scan",
|
16
|
+
"High-level functionality mapping",
|
17
|
+
"Quick documentation review"
|
18
|
+
],
|
19
|
+
steps: [
|
20
|
+
"01_REPOSITORY_ANALYSIS",
|
21
|
+
"04_FUNCTIONALITY_ANALYSIS",
|
22
|
+
"05_DOCUMENTATION_ANALYSIS"
|
23
|
+
]
|
24
|
+
},
|
25
|
+
|
26
|
+
style_guide: {
|
27
|
+
name: "Style & Patterns",
|
28
|
+
description: "Identify coding patterns and create style guide",
|
29
|
+
icon: "📐",
|
30
|
+
details: [
|
31
|
+
"Code pattern analysis",
|
32
|
+
"Style consistency review",
|
33
|
+
"Generate project style guide"
|
34
|
+
],
|
35
|
+
steps: [
|
36
|
+
"01_REPOSITORY_ANALYSIS",
|
37
|
+
"06_STATIC_ANALYSIS",
|
38
|
+
"06A_TREE_SITTER_SCAN"
|
39
|
+
]
|
40
|
+
},
|
41
|
+
|
42
|
+
architecture_review: {
|
43
|
+
name: "Architecture Review",
|
44
|
+
description: "Understand system architecture and dependencies",
|
45
|
+
icon: "🏗️",
|
46
|
+
details: [
|
47
|
+
"Architecture pattern analysis",
|
48
|
+
"Dependency mapping",
|
49
|
+
"Component relationships",
|
50
|
+
"Design principles review"
|
51
|
+
],
|
52
|
+
steps: [
|
53
|
+
"01_REPOSITORY_ANALYSIS",
|
54
|
+
"02_ARCHITECTURE_ANALYSIS",
|
55
|
+
"06A_TREE_SITTER_SCAN"
|
56
|
+
]
|
57
|
+
},
|
58
|
+
|
59
|
+
quality_assessment: {
|
60
|
+
name: "Quality Assessment",
|
61
|
+
description: "Comprehensive code quality and test coverage analysis",
|
62
|
+
icon: "✅",
|
63
|
+
details: [
|
64
|
+
"Test coverage analysis",
|
65
|
+
"Code quality metrics",
|
66
|
+
"Static analysis review",
|
67
|
+
"Refactoring opportunities"
|
68
|
+
],
|
69
|
+
steps: [
|
70
|
+
"03_TEST_ANALYSIS",
|
71
|
+
"06_STATIC_ANALYSIS",
|
72
|
+
"06A_TREE_SITTER_SCAN",
|
73
|
+
"07_REFACTORING_RECOMMENDATIONS"
|
74
|
+
]
|
75
|
+
},
|
76
|
+
|
77
|
+
deep_analysis: {
|
78
|
+
name: "Deep Analysis",
|
79
|
+
description: "Complete analysis for extension/refactoring",
|
80
|
+
icon: "🔬",
|
81
|
+
details: [
|
82
|
+
"Full repository analysis",
|
83
|
+
"Architecture deep dive",
|
84
|
+
"Complete test coverage analysis",
|
85
|
+
"Functionality mapping",
|
86
|
+
"Documentation review",
|
87
|
+
"Static analysis",
|
88
|
+
"Tree-sitter knowledge base",
|
89
|
+
"Refactoring recommendations"
|
90
|
+
],
|
91
|
+
steps: [
|
92
|
+
"01_REPOSITORY_ANALYSIS",
|
93
|
+
"02_ARCHITECTURE_ANALYSIS",
|
94
|
+
"03_TEST_ANALYSIS",
|
95
|
+
"04_FUNCTIONALITY_ANALYSIS",
|
96
|
+
"05_DOCUMENTATION_ANALYSIS",
|
97
|
+
"06_STATIC_ANALYSIS",
|
98
|
+
"06A_TREE_SITTER_SCAN",
|
99
|
+
"07_REFACTORING_RECOMMENDATIONS"
|
100
|
+
]
|
101
|
+
},
|
102
|
+
|
103
|
+
custom: {
|
104
|
+
name: "Custom Analysis",
|
105
|
+
description: "Choose specific analysis steps",
|
106
|
+
icon: "⚙️",
|
107
|
+
details: ["Select exactly which analysis steps you need"],
|
108
|
+
steps: :custom # Will be populated by user selection
|
109
|
+
}
|
110
|
+
}.freeze
|
111
|
+
|
112
|
+
# Execute mode workflows - from quick prototype to enterprise-grade
|
113
|
+
EXECUTE_WORKFLOWS = {
|
114
|
+
quick_prototype: {
|
115
|
+
name: "Quick Prototype",
|
116
|
+
description: "Rapid prototype - minimal planning, fast iteration",
|
117
|
+
icon: "⚡",
|
118
|
+
details: [
|
119
|
+
"Minimal PRD",
|
120
|
+
"Basic testing strategy",
|
121
|
+
"Direct to implementation"
|
122
|
+
],
|
123
|
+
steps: [
|
124
|
+
"00_PRD",
|
125
|
+
"10_TESTING_STRATEGY",
|
126
|
+
"16_IMPLEMENTATION"
|
127
|
+
]
|
128
|
+
},
|
129
|
+
|
130
|
+
exploration: {
|
131
|
+
name: "Exploration/Experiment",
|
132
|
+
description: "Proof of concept with basic quality checks",
|
133
|
+
icon: "🔬",
|
134
|
+
details: [
|
135
|
+
"Quick PRD generation",
|
136
|
+
"Testing strategy",
|
137
|
+
"Static analysis setup",
|
138
|
+
"Implementation with work loops"
|
139
|
+
],
|
140
|
+
steps: [
|
141
|
+
"00_PRD",
|
142
|
+
"10_TESTING_STRATEGY",
|
143
|
+
"11_STATIC_ANALYSIS",
|
144
|
+
"16_IMPLEMENTATION"
|
145
|
+
]
|
146
|
+
},
|
147
|
+
|
148
|
+
feature_development: {
|
149
|
+
name: "Feature Development",
|
150
|
+
description: "Standard feature with architecture and testing",
|
151
|
+
icon: "🚀",
|
152
|
+
details: [
|
153
|
+
"Product requirements",
|
154
|
+
"Architecture design",
|
155
|
+
"Testing strategy",
|
156
|
+
"Static analysis",
|
157
|
+
"Implementation"
|
158
|
+
],
|
159
|
+
steps: [
|
160
|
+
"00_PRD",
|
161
|
+
"02_ARCHITECTURE",
|
162
|
+
"10_TESTING_STRATEGY",
|
163
|
+
"11_STATIC_ANALYSIS",
|
164
|
+
"16_IMPLEMENTATION"
|
165
|
+
]
|
166
|
+
},
|
167
|
+
|
168
|
+
production_ready: {
|
169
|
+
name: "Production-Ready",
|
170
|
+
description: "Enterprise-grade with NFRs and compliance",
|
171
|
+
icon: "🏗️",
|
172
|
+
details: [
|
173
|
+
"Comprehensive PRD",
|
174
|
+
"Non-functional requirements",
|
175
|
+
"System architecture",
|
176
|
+
"Security review",
|
177
|
+
"Performance planning",
|
178
|
+
"Testing strategy",
|
179
|
+
"Observability & SLOs",
|
180
|
+
"Delivery planning",
|
181
|
+
"Implementation"
|
182
|
+
],
|
183
|
+
steps: [
|
184
|
+
"00_PRD",
|
185
|
+
"01_NFRS",
|
186
|
+
"02_ARCHITECTURE",
|
187
|
+
"07_SECURITY_REVIEW",
|
188
|
+
"08_PERFORMANCE_REVIEW",
|
189
|
+
"10_TESTING_STRATEGY",
|
190
|
+
"11_STATIC_ANALYSIS",
|
191
|
+
"12_OBSERVABILITY_SLOS",
|
192
|
+
"13_DELIVERY_ROLLOUT",
|
193
|
+
"16_IMPLEMENTATION"
|
194
|
+
]
|
195
|
+
},
|
196
|
+
|
197
|
+
full_enterprise: {
|
198
|
+
name: "Full Enterprise",
|
199
|
+
description: "Complete enterprise workflow with all governance",
|
200
|
+
icon: "🏢",
|
201
|
+
details: [
|
202
|
+
"All planning documents",
|
203
|
+
"Architecture decision records",
|
204
|
+
"Domain decomposition",
|
205
|
+
"API design",
|
206
|
+
"Security & performance reviews",
|
207
|
+
"Reliability planning",
|
208
|
+
"Complete observability",
|
209
|
+
"Documentation portal"
|
210
|
+
],
|
211
|
+
steps: [
|
212
|
+
"00_PRD",
|
213
|
+
"01_NFRS",
|
214
|
+
"02_ARCHITECTURE",
|
215
|
+
"03_ADR_FACTORY",
|
216
|
+
"04_DOMAIN_DECOMPOSITION",
|
217
|
+
"05_API_DESIGN",
|
218
|
+
"07_SECURITY_REVIEW",
|
219
|
+
"08_PERFORMANCE_REVIEW",
|
220
|
+
"09_RELIABILITY_REVIEW",
|
221
|
+
"10_TESTING_STRATEGY",
|
222
|
+
"11_STATIC_ANALYSIS",
|
223
|
+
"12_OBSERVABILITY_SLOS",
|
224
|
+
"13_DELIVERY_ROLLOUT",
|
225
|
+
"14_DOCS_PORTAL",
|
226
|
+
"16_IMPLEMENTATION"
|
227
|
+
]
|
228
|
+
},
|
229
|
+
|
230
|
+
custom: {
|
231
|
+
name: "Custom Workflow",
|
232
|
+
description: "Choose specific planning and implementation steps",
|
233
|
+
icon: "⚙️",
|
234
|
+
details: ["Select exactly which steps you need"],
|
235
|
+
steps: :custom # Will be populated by user selection
|
236
|
+
}
|
237
|
+
}.freeze
|
238
|
+
|
239
|
+
# Hybrid workflows - mix of analyze and execute steps
|
240
|
+
HYBRID_WORKFLOWS = {
|
241
|
+
legacy_modernization: {
|
242
|
+
name: "Legacy Modernization",
|
243
|
+
description: "Analyze existing code then plan modernization",
|
244
|
+
icon: "♻️",
|
245
|
+
details: [
|
246
|
+
"Deep code analysis",
|
247
|
+
"Refactoring recommendations",
|
248
|
+
"Architecture design for new system",
|
249
|
+
"Migration planning",
|
250
|
+
"Implementation"
|
251
|
+
],
|
252
|
+
steps: [
|
253
|
+
"01_REPOSITORY_ANALYSIS",
|
254
|
+
"02_ARCHITECTURE_ANALYSIS",
|
255
|
+
"06A_TREE_SITTER_SCAN",
|
256
|
+
"07_REFACTORING_RECOMMENDATIONS",
|
257
|
+
"00_PRD",
|
258
|
+
"02_ARCHITECTURE",
|
259
|
+
"16_IMPLEMENTATION"
|
260
|
+
]
|
261
|
+
},
|
262
|
+
|
263
|
+
style_guide_enforcement: {
|
264
|
+
name: "Style Guide Enforcement",
|
265
|
+
description: "Extract patterns then enforce them",
|
266
|
+
icon: "📏",
|
267
|
+
details: [
|
268
|
+
"Analyze existing patterns",
|
269
|
+
"Generate LLM style guide",
|
270
|
+
"Configure static analysis",
|
271
|
+
"Implement enforcement"
|
272
|
+
],
|
273
|
+
steps: [
|
274
|
+
"01_REPOSITORY_ANALYSIS",
|
275
|
+
"06_STATIC_ANALYSIS",
|
276
|
+
"06A_TREE_SITTER_SCAN",
|
277
|
+
"00_LLM_STYLE_GUIDE",
|
278
|
+
"11_STATIC_ANALYSIS",
|
279
|
+
"16_IMPLEMENTATION"
|
280
|
+
]
|
281
|
+
},
|
282
|
+
|
283
|
+
test_coverage_improvement: {
|
284
|
+
name: "Test Coverage Improvement",
|
285
|
+
description: "Analyze gaps then implement comprehensive tests",
|
286
|
+
icon: "🧪",
|
287
|
+
details: [
|
288
|
+
"Test coverage analysis",
|
289
|
+
"Functionality mapping",
|
290
|
+
"Testing strategy design",
|
291
|
+
"Test implementation"
|
292
|
+
],
|
293
|
+
steps: [
|
294
|
+
"03_TEST_ANALYSIS",
|
295
|
+
"04_FUNCTIONALITY_ANALYSIS",
|
296
|
+
"06A_TREE_SITTER_SCAN",
|
297
|
+
"10_TESTING_STRATEGY",
|
298
|
+
"16_IMPLEMENTATION"
|
299
|
+
]
|
300
|
+
},
|
301
|
+
|
302
|
+
custom_hybrid: {
|
303
|
+
name: "Custom Hybrid",
|
304
|
+
description: "Mix analyze and execute steps",
|
305
|
+
icon: "🔀",
|
306
|
+
details: ["Choose from both analyze and execute steps"],
|
307
|
+
steps: :custom # Will be populated by user selection
|
308
|
+
}
|
309
|
+
}.freeze
|
310
|
+
|
311
|
+
# Get all available steps for custom selection
|
312
|
+
def self.all_available_steps
|
313
|
+
analyze_steps = Aidp::Analyze::Steps::SPEC.keys.map do |step|
|
314
|
+
{
|
315
|
+
step: step,
|
316
|
+
mode: :analyze,
|
317
|
+
description: Aidp::Analyze::Steps::SPEC[step]["description"]
|
318
|
+
}
|
319
|
+
end
|
320
|
+
|
321
|
+
execute_steps = Aidp::Execute::Steps::SPEC.keys.map do |step|
|
322
|
+
{
|
323
|
+
step: step,
|
324
|
+
mode: :execute,
|
325
|
+
description: Aidp::Execute::Steps::SPEC[step]["description"]
|
326
|
+
}
|
327
|
+
end
|
328
|
+
|
329
|
+
(analyze_steps + execute_steps).sort_by { |s| s[:step] }
|
330
|
+
end
|
331
|
+
|
332
|
+
# Get workflow definition by key
|
333
|
+
def self.get_workflow(mode, workflow_key)
|
334
|
+
case mode
|
335
|
+
when :analyze
|
336
|
+
ANALYZE_WORKFLOWS[workflow_key]
|
337
|
+
when :execute
|
338
|
+
EXECUTE_WORKFLOWS[workflow_key]
|
339
|
+
when :hybrid
|
340
|
+
HYBRID_WORKFLOWS[workflow_key]
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
# Get all workflows for a mode
|
345
|
+
def self.workflows_for_mode(mode)
|
346
|
+
case mode
|
347
|
+
when :analyze
|
348
|
+
ANALYZE_WORKFLOWS
|
349
|
+
when :execute
|
350
|
+
EXECUTE_WORKFLOWS
|
351
|
+
when :hybrid
|
352
|
+
HYBRID_WORKFLOWS
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "tty-prompt"
|
4
|
+
require_relative "definitions"
|
5
|
+
require_relative "../message_display"
|
6
|
+
|
7
|
+
module Aidp
|
8
|
+
module Workflows
|
9
|
+
# Enhanced workflow selector with support for custom workflows
|
10
|
+
# Handles selection for analyze, execute, and hybrid modes
|
11
|
+
class Selector
|
12
|
+
include Aidp::MessageDisplay
|
13
|
+
|
14
|
+
def initialize(prompt: TTY::Prompt.new)
|
15
|
+
@prompt = prompt
|
16
|
+
end
|
17
|
+
|
18
|
+
# Select mode (analyze, execute, or hybrid)
|
19
|
+
def select_mode
|
20
|
+
display_message("\n🚀 Welcome to AI Dev Pipeline!", type: :highlight)
|
21
|
+
display_message("Choose your mode:\n", type: :highlight)
|
22
|
+
|
23
|
+
choices = {
|
24
|
+
"🔬 Analyze Mode" => :analyze,
|
25
|
+
"🏗️ Execute Mode" => :execute,
|
26
|
+
"🔀 Hybrid Mode" => :hybrid
|
27
|
+
}
|
28
|
+
|
29
|
+
@prompt.select("What would you like to do?", choices, per_page: 10)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Select workflow for the given mode
|
33
|
+
def select_workflow(mode)
|
34
|
+
workflows = Definitions.workflows_for_mode(mode)
|
35
|
+
|
36
|
+
display_message("\n#{mode_header(mode)}", type: :highlight)
|
37
|
+
display_message("Choose a workflow:\n")
|
38
|
+
|
39
|
+
# Build choices with icons and descriptions
|
40
|
+
choices = workflows.map do |key, workflow|
|
41
|
+
{
|
42
|
+
name: "#{workflow[:icon]} #{workflow[:name]} - #{workflow[:description]}",
|
43
|
+
value: key
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
selected = @prompt.select(
|
48
|
+
"Select workflow:",
|
49
|
+
choices,
|
50
|
+
per_page: 15,
|
51
|
+
help: "(↑/↓ to navigate, Enter to select)"
|
52
|
+
)
|
53
|
+
|
54
|
+
workflow = workflows[selected]
|
55
|
+
|
56
|
+
# Show workflow details
|
57
|
+
display_workflow_details(workflow)
|
58
|
+
|
59
|
+
# Handle custom workflows
|
60
|
+
if workflow[:steps] == :custom
|
61
|
+
steps = select_custom_steps(mode)
|
62
|
+
{workflow_key: selected, steps: steps, workflow: workflow}
|
63
|
+
else
|
64
|
+
{workflow_key: selected, steps: workflow[:steps], workflow: workflow}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Select custom steps for hybrid or custom workflows
|
69
|
+
def select_custom_steps(mode)
|
70
|
+
display_message("\n⚙️ Custom Step Selection", type: :highlight)
|
71
|
+
display_message("")
|
72
|
+
|
73
|
+
if mode == :hybrid
|
74
|
+
select_hybrid_steps
|
75
|
+
elsif mode == :analyze
|
76
|
+
select_steps_from_mode(:analyze)
|
77
|
+
elsif mode == :execute
|
78
|
+
select_steps_from_mode(:execute)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def mode_header(mode)
|
85
|
+
case mode
|
86
|
+
when :analyze
|
87
|
+
"🔬 Analyze Mode - Understand Your Codebase"
|
88
|
+
when :execute
|
89
|
+
"🏗️ Execute Mode - Build New Features"
|
90
|
+
when :hybrid
|
91
|
+
"🔀 Hybrid Mode - Analyze Then Execute"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def display_workflow_details(workflow)
|
96
|
+
display_message("\n#{workflow[:icon]} #{workflow[:name]}", type: :highlight)
|
97
|
+
display_message("─" * 60, type: :muted)
|
98
|
+
display_message("")
|
99
|
+
display_message("Description: #{workflow[:description]}")
|
100
|
+
display_message("")
|
101
|
+
display_message("Includes:", type: :highlight)
|
102
|
+
workflow[:details].each do |detail|
|
103
|
+
display_message(" • #{detail}", type: :info)
|
104
|
+
end
|
105
|
+
display_message("")
|
106
|
+
end
|
107
|
+
|
108
|
+
def select_steps_from_mode(mode)
|
109
|
+
spec = (mode == :analyze) ? Aidp::Analyze::Steps::SPEC : Aidp::Execute::Steps::SPEC
|
110
|
+
|
111
|
+
display_message("Available #{mode} steps:")
|
112
|
+
display_message("")
|
113
|
+
|
114
|
+
# Build step choices
|
115
|
+
step_choices = spec.map do |step_key, step_spec|
|
116
|
+
{
|
117
|
+
name: "#{step_key} - #{step_spec["description"]}",
|
118
|
+
value: step_key,
|
119
|
+
disabled: step_spec["gate"] ? "(requires manual review)" : false
|
120
|
+
}
|
121
|
+
end
|
122
|
+
|
123
|
+
selected_steps = @prompt.multi_select(
|
124
|
+
"Select steps (Space to select, Enter when done):",
|
125
|
+
step_choices,
|
126
|
+
per_page: 20,
|
127
|
+
help: "Select one or more steps"
|
128
|
+
)
|
129
|
+
|
130
|
+
if selected_steps.empty?
|
131
|
+
display_message("⚠️ No steps selected, using default workflow", type: :warning)
|
132
|
+
# Return a sensible default
|
133
|
+
(mode == :analyze) ? ["01_REPOSITORY_ANALYSIS"] : ["00_PRD", "16_IMPLEMENTATION"]
|
134
|
+
else
|
135
|
+
selected_steps.sort
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def select_hybrid_steps
|
140
|
+
display_message("You can mix analyze and execute steps for a custom hybrid workflow.")
|
141
|
+
display_message("")
|
142
|
+
|
143
|
+
all_steps = Definitions.all_available_steps
|
144
|
+
|
145
|
+
# Group steps by mode for display
|
146
|
+
step_choices = all_steps.map do |step_info|
|
147
|
+
mode_tag = (step_info[:mode] == :analyze) ? "[ANALYZE]" : "[EXECUTE]"
|
148
|
+
{
|
149
|
+
name: "#{mode_tag} #{step_info[:step]} - #{step_info[:description]}",
|
150
|
+
value: step_info[:step]
|
151
|
+
}
|
152
|
+
end
|
153
|
+
|
154
|
+
selected_steps = @prompt.multi_select(
|
155
|
+
"Select steps (Space to select, Enter when done):",
|
156
|
+
step_choices,
|
157
|
+
per_page: 25,
|
158
|
+
help: "Mix analyze and execute steps as needed"
|
159
|
+
)
|
160
|
+
|
161
|
+
if selected_steps.empty?
|
162
|
+
display_message("⚠️ No steps selected, using default hybrid workflow", type: :warning)
|
163
|
+
# Return a sensible default hybrid
|
164
|
+
["01_REPOSITORY_ANALYSIS", "00_PRD", "16_IMPLEMENTATION"]
|
165
|
+
else
|
166
|
+
selected_steps.sort
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|