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.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +194 -25
  3. data/lib/aidp/analyze/kb_inspector.rb +2 -15
  4. data/lib/aidp/analyze/progress.rb +2 -1
  5. data/lib/aidp/analyze/ruby_maat_integration.rb +2 -15
  6. data/lib/aidp/analyze/runner.rb +64 -20
  7. data/lib/aidp/analyze/steps.rb +10 -8
  8. data/lib/aidp/analyze/tree_sitter_grammar_loader.rb +2 -13
  9. data/lib/aidp/analyze/tree_sitter_scan.rb +2 -13
  10. data/lib/aidp/cli/checkpoint_command.rb +98 -0
  11. data/lib/aidp/cli/first_run_wizard.rb +65 -94
  12. data/lib/aidp/cli/jobs_command.rb +249 -34
  13. data/lib/aidp/cli.rb +312 -38
  14. data/lib/aidp/config.rb +5 -8
  15. data/lib/aidp/debug_logger.rb +4 -4
  16. data/lib/aidp/debug_mixin.rb +11 -4
  17. data/lib/aidp/execute/checkpoint.rb +282 -0
  18. data/lib/aidp/execute/checkpoint_display.rb +221 -0
  19. data/lib/aidp/execute/progress.rb +2 -1
  20. data/lib/aidp/execute/prompt_manager.rb +62 -0
  21. data/lib/aidp/execute/runner.rb +53 -24
  22. data/lib/aidp/execute/steps.rb +36 -27
  23. data/lib/aidp/execute/work_loop_runner.rb +308 -0
  24. data/lib/aidp/execute/workflow_selector.rb +26 -17
  25. data/lib/aidp/harness/condition_detector.rb +4 -4
  26. data/lib/aidp/harness/config_schema.rb +40 -0
  27. data/lib/aidp/harness/config_validator.rb +3 -6
  28. data/lib/aidp/harness/configuration.rb +35 -1
  29. data/lib/aidp/harness/enhanced_runner.rb +22 -1
  30. data/lib/aidp/harness/error_handler.rb +103 -28
  31. data/lib/aidp/harness/provider_factory.rb +4 -1
  32. data/lib/aidp/harness/provider_manager.rb +250 -15
  33. data/lib/aidp/harness/runner.rb +3 -14
  34. data/lib/aidp/harness/simple_user_interface.rb +2 -15
  35. data/lib/aidp/harness/status_display.rb +12 -17
  36. data/lib/aidp/harness/test_runner.rb +83 -0
  37. data/lib/aidp/harness/ui/enhanced_tui.rb +2 -0
  38. data/lib/aidp/harness/ui/enhanced_workflow_selector.rb +22 -4
  39. data/lib/aidp/harness/ui/error_handler.rb +4 -0
  40. data/lib/aidp/harness/ui/frame_manager.rb +10 -8
  41. data/lib/aidp/harness/ui/job_monitor.rb +2 -0
  42. data/lib/aidp/harness/ui/navigation/main_menu.rb +4 -2
  43. data/lib/aidp/harness/ui/navigation/menu_item.rb +1 -0
  44. data/lib/aidp/harness/ui/navigation/menu_state.rb +1 -0
  45. data/lib/aidp/harness/ui/navigation/submenu.rb +1 -0
  46. data/lib/aidp/harness/ui/navigation/workflow_selector.rb +2 -0
  47. data/lib/aidp/harness/ui/progress_display.rb +8 -12
  48. data/lib/aidp/harness/ui/question_collector.rb +2 -0
  49. data/lib/aidp/harness/ui/spinner_group.rb +2 -0
  50. data/lib/aidp/harness/ui/spinner_helper.rb +1 -1
  51. data/lib/aidp/harness/ui/status_manager.rb +4 -2
  52. data/lib/aidp/harness/ui/status_widget.rb +3 -1
  53. data/lib/aidp/harness/ui/workflow_controller.rb +2 -0
  54. data/lib/aidp/harness/user_interface.rb +12 -17
  55. data/lib/aidp/jobs/background_runner.rb +278 -0
  56. data/lib/aidp/message_display.rb +48 -0
  57. data/lib/aidp/provider_manager.rb +3 -1
  58. data/lib/aidp/providers/anthropic.rb +100 -17
  59. data/lib/aidp/providers/base.rb +42 -11
  60. data/lib/aidp/providers/codex.rb +248 -0
  61. data/lib/aidp/providers/cursor.rb +35 -42
  62. data/lib/aidp/providers/gemini.rb +25 -15
  63. data/lib/aidp/providers/github_copilot.rb +41 -42
  64. data/lib/aidp/providers/opencode.rb +34 -41
  65. data/lib/aidp/version.rb +1 -1
  66. data/lib/aidp/workflows/definitions.rb +357 -0
  67. data/lib/aidp/workflows/selector.rb +171 -0
  68. data/lib/aidp.rb +12 -0
  69. data/templates/planning/generate_llm_style_guide.md +119 -0
  70. metadata +38 -26
  71. /data/templates/{ANALYZE/02_ARCHITECTURE_ANALYSIS.md → analysis/analyze_architecture.md} +0 -0
  72. /data/templates/{ANALYZE/05_DOCUMENTATION_ANALYSIS.md → analysis/analyze_documentation.md} +0 -0
  73. /data/templates/{ANALYZE/04_FUNCTIONALITY_ANALYSIS.md → analysis/analyze_functionality.md} +0 -0
  74. /data/templates/{ANALYZE/01_REPOSITORY_ANALYSIS.md → analysis/analyze_repository.md} +0 -0
  75. /data/templates/{ANALYZE/06_STATIC_ANALYSIS.md → analysis/analyze_static_code.md} +0 -0
  76. /data/templates/{ANALYZE/03_TEST_ANALYSIS.md → analysis/analyze_tests.md} +0 -0
  77. /data/templates/{ANALYZE/07_REFACTORING_RECOMMENDATIONS.md → analysis/recommend_refactoring.md} +0 -0
  78. /data/templates/{ANALYZE/06a_tree_sitter_scan.md → analysis/scan_with_tree_sitter.md} +0 -0
  79. /data/templates/{EXECUTE/11_STATIC_ANALYSIS.md → implementation/configure_static_analysis.md} +0 -0
  80. /data/templates/{EXECUTE/14_DOCS_PORTAL.md → implementation/create_documentation_portal.md} +0 -0
  81. /data/templates/{EXECUTE/10_IMPLEMENTATION_AGENT.md → implementation/implement_features.md} +0 -0
  82. /data/templates/{EXECUTE/13_DELIVERY_ROLLOUT.md → implementation/plan_delivery.md} +0 -0
  83. /data/templates/{EXECUTE/15_POST_RELEASE.md → implementation/review_post_release.md} +0 -0
  84. /data/templates/{EXECUTE/09_SCAFFOLDING_DEVEX.md → implementation/setup_scaffolding.md} +0 -0
  85. /data/templates/{EXECUTE/02A_ARCH_GATE_QUESTIONS.md → planning/ask_architecture_questions.md} +0 -0
  86. /data/templates/{EXECUTE/00_PRD.md → planning/create_prd.md} +0 -0
  87. /data/templates/{EXECUTE/08_TASKS.md → planning/create_tasks.md} +0 -0
  88. /data/templates/{EXECUTE/04_DOMAIN_DECOMPOSITION.md → planning/decompose_domain.md} +0 -0
  89. /data/templates/{EXECUTE/01_NFRS.md → planning/define_nfrs.md} +0 -0
  90. /data/templates/{EXECUTE/05_CONTRACTS.md → planning/design_apis.md} +0 -0
  91. /data/templates/{EXECUTE/02_ARCHITECTURE.md → planning/design_architecture.md} +0 -0
  92. /data/templates/{EXECUTE/06_THREAT_MODEL.md → planning/design_data_model.md} +0 -0
  93. /data/templates/{EXECUTE/03_ADR_FACTORY.md → planning/generate_adrs.md} +0 -0
  94. /data/templates/{EXECUTE/12_OBSERVABILITY_SLOS.md → planning/plan_observability.md} +0 -0
  95. /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
- print_activity_status(elapsed)
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
- # Stop activity display
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 - 2 minute timeout", type: :highlight)
114
- return 120
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 (5 minutes for interactive use)
129
- display_message("📋 Using default timeout: 5 minutes", type: :info)
130
- 300
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
- 180 # 3 minutes - repository analysis can be quick
132
+ TIMEOUT_REPOSITORY_ANALYSIS
140
133
  when /ARCHITECTURE_ANALYSIS/
141
- 600 # 10 minutes - architecture analysis needs more time
134
+ TIMEOUT_ARCHITECTURE_ANALYSIS
142
135
  when /TEST_ANALYSIS/
143
- 300 # 5 minutes - test analysis is moderate
136
+ TIMEOUT_TEST_ANALYSIS
144
137
  when /FUNCTIONALITY_ANALYSIS/
145
- 600 # 10 minutes - functionality analysis is complex
138
+ TIMEOUT_FUNCTIONALITY_ANALYSIS
146
139
  when /DOCUMENTATION_ANALYSIS/
147
- 300 # 5 minutes - documentation analysis is moderate
140
+ TIMEOUT_DOCUMENTATION_ANALYSIS
148
141
  when /STATIC_ANALYSIS/
149
- 450 # 7.5 minutes - static analysis can be intensive
142
+ TIMEOUT_STATIC_ANALYSIS
150
143
  when /REFACTORING_RECOMMENDATIONS/
151
- 600 # 10 minutes - refactoring recommendations are complex
144
+ TIMEOUT_REFACTORING_RECOMMENDATIONS
152
145
  else
153
- nil # Use default
146
+ nil # Use default
154
147
  end
155
148
  end
156
149
 
data/lib/aidp/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Aidp
4
- VERSION = "0.10.0"
4
+ VERSION = "0.11.0"
5
5
  end
@@ -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