aidp 0.5.0 → 0.8.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 (122) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +128 -151
  3. data/bin/aidp +1 -1
  4. data/lib/aidp/analysis/kb_inspector.rb +471 -0
  5. data/lib/aidp/analysis/seams.rb +159 -0
  6. data/lib/aidp/analysis/tree_sitter_grammar_loader.rb +480 -0
  7. data/lib/aidp/analysis/tree_sitter_scan.rb +686 -0
  8. data/lib/aidp/analyze/error_handler.rb +2 -78
  9. data/lib/aidp/analyze/json_file_storage.rb +292 -0
  10. data/lib/aidp/analyze/progress.rb +12 -0
  11. data/lib/aidp/analyze/progress_visualizer.rb +12 -17
  12. data/lib/aidp/analyze/ruby_maat_integration.rb +13 -31
  13. data/lib/aidp/analyze/runner.rb +256 -87
  14. data/lib/aidp/analyze/steps.rb +6 -0
  15. data/lib/aidp/cli/jobs_command.rb +103 -435
  16. data/lib/aidp/cli.rb +317 -191
  17. data/lib/aidp/config.rb +298 -10
  18. data/lib/aidp/debug_logger.rb +195 -0
  19. data/lib/aidp/debug_mixin.rb +187 -0
  20. data/lib/aidp/execute/progress.rb +9 -0
  21. data/lib/aidp/execute/runner.rb +221 -40
  22. data/lib/aidp/execute/steps.rb +17 -7
  23. data/lib/aidp/execute/workflow_selector.rb +211 -0
  24. data/lib/aidp/harness/completion_checker.rb +268 -0
  25. data/lib/aidp/harness/condition_detector.rb +1526 -0
  26. data/lib/aidp/harness/config_loader.rb +373 -0
  27. data/lib/aidp/harness/config_manager.rb +382 -0
  28. data/lib/aidp/harness/config_schema.rb +1006 -0
  29. data/lib/aidp/harness/config_validator.rb +355 -0
  30. data/lib/aidp/harness/configuration.rb +477 -0
  31. data/lib/aidp/harness/enhanced_runner.rb +494 -0
  32. data/lib/aidp/harness/error_handler.rb +616 -0
  33. data/lib/aidp/harness/provider_config.rb +423 -0
  34. data/lib/aidp/harness/provider_factory.rb +306 -0
  35. data/lib/aidp/harness/provider_manager.rb +1269 -0
  36. data/lib/aidp/harness/provider_type_checker.rb +88 -0
  37. data/lib/aidp/harness/runner.rb +411 -0
  38. data/lib/aidp/harness/state/errors.rb +28 -0
  39. data/lib/aidp/harness/state/metrics.rb +219 -0
  40. data/lib/aidp/harness/state/persistence.rb +128 -0
  41. data/lib/aidp/harness/state/provider_state.rb +132 -0
  42. data/lib/aidp/harness/state/ui_state.rb +68 -0
  43. data/lib/aidp/harness/state/workflow_state.rb +123 -0
  44. data/lib/aidp/harness/state_manager.rb +586 -0
  45. data/lib/aidp/harness/status_display.rb +888 -0
  46. data/lib/aidp/harness/ui/base.rb +16 -0
  47. data/lib/aidp/harness/ui/enhanced_tui.rb +545 -0
  48. data/lib/aidp/harness/ui/enhanced_workflow_selector.rb +252 -0
  49. data/lib/aidp/harness/ui/error_handler.rb +132 -0
  50. data/lib/aidp/harness/ui/frame_manager.rb +361 -0
  51. data/lib/aidp/harness/ui/job_monitor.rb +500 -0
  52. data/lib/aidp/harness/ui/navigation/main_menu.rb +311 -0
  53. data/lib/aidp/harness/ui/navigation/menu_formatter.rb +120 -0
  54. data/lib/aidp/harness/ui/navigation/menu_item.rb +142 -0
  55. data/lib/aidp/harness/ui/navigation/menu_state.rb +139 -0
  56. data/lib/aidp/harness/ui/navigation/submenu.rb +202 -0
  57. data/lib/aidp/harness/ui/navigation/workflow_selector.rb +176 -0
  58. data/lib/aidp/harness/ui/progress_display.rb +280 -0
  59. data/lib/aidp/harness/ui/question_collector.rb +141 -0
  60. data/lib/aidp/harness/ui/spinner_group.rb +184 -0
  61. data/lib/aidp/harness/ui/spinner_helper.rb +152 -0
  62. data/lib/aidp/harness/ui/status_manager.rb +312 -0
  63. data/lib/aidp/harness/ui/status_widget.rb +280 -0
  64. data/lib/aidp/harness/ui/workflow_controller.rb +312 -0
  65. data/lib/aidp/harness/user_interface.rb +2381 -0
  66. data/lib/aidp/provider_manager.rb +131 -7
  67. data/lib/aidp/providers/anthropic.rb +28 -109
  68. data/lib/aidp/providers/base.rb +170 -0
  69. data/lib/aidp/providers/cursor.rb +52 -183
  70. data/lib/aidp/providers/gemini.rb +24 -109
  71. data/lib/aidp/providers/macos_ui.rb +99 -5
  72. data/lib/aidp/providers/opencode.rb +194 -0
  73. data/lib/aidp/storage/csv_storage.rb +172 -0
  74. data/lib/aidp/storage/file_manager.rb +214 -0
  75. data/lib/aidp/storage/json_storage.rb +140 -0
  76. data/lib/aidp/version.rb +1 -1
  77. data/lib/aidp.rb +56 -35
  78. data/templates/ANALYZE/06a_tree_sitter_scan.md +217 -0
  79. data/templates/COMMON/AGENT_BASE.md +11 -0
  80. data/templates/EXECUTE/00_PRD.md +4 -4
  81. data/templates/EXECUTE/02_ARCHITECTURE.md +5 -4
  82. data/templates/EXECUTE/07_TEST_PLAN.md +4 -1
  83. data/templates/EXECUTE/08_TASKS.md +4 -4
  84. data/templates/EXECUTE/10_IMPLEMENTATION_AGENT.md +4 -4
  85. data/templates/README.md +279 -0
  86. data/templates/aidp-development.yml.example +373 -0
  87. data/templates/aidp-minimal.yml.example +48 -0
  88. data/templates/aidp-production.yml.example +475 -0
  89. data/templates/aidp.yml.example +598 -0
  90. metadata +106 -64
  91. data/lib/aidp/analyze/agent_personas.rb +0 -71
  92. data/lib/aidp/analyze/agent_tool_executor.rb +0 -445
  93. data/lib/aidp/analyze/data_retention_manager.rb +0 -426
  94. data/lib/aidp/analyze/database.rb +0 -260
  95. data/lib/aidp/analyze/dependencies.rb +0 -335
  96. data/lib/aidp/analyze/export_manager.rb +0 -425
  97. data/lib/aidp/analyze/focus_guidance.rb +0 -517
  98. data/lib/aidp/analyze/incremental_analyzer.rb +0 -543
  99. data/lib/aidp/analyze/language_analysis_strategies.rb +0 -897
  100. data/lib/aidp/analyze/large_analysis_progress.rb +0 -504
  101. data/lib/aidp/analyze/memory_manager.rb +0 -365
  102. data/lib/aidp/analyze/metrics_storage.rb +0 -336
  103. data/lib/aidp/analyze/parallel_processor.rb +0 -460
  104. data/lib/aidp/analyze/performance_optimizer.rb +0 -694
  105. data/lib/aidp/analyze/repository_chunker.rb +0 -704
  106. data/lib/aidp/analyze/static_analysis_detector.rb +0 -577
  107. data/lib/aidp/analyze/storage.rb +0 -662
  108. data/lib/aidp/analyze/tool_configuration.rb +0 -456
  109. data/lib/aidp/analyze/tool_modernization.rb +0 -750
  110. data/lib/aidp/database/pg_adapter.rb +0 -148
  111. data/lib/aidp/database_config.rb +0 -69
  112. data/lib/aidp/database_connection.rb +0 -72
  113. data/lib/aidp/database_migration.rb +0 -158
  114. data/lib/aidp/job_manager.rb +0 -41
  115. data/lib/aidp/jobs/base_job.rb +0 -47
  116. data/lib/aidp/jobs/provider_execution_job.rb +0 -96
  117. data/lib/aidp/project_detector.rb +0 -117
  118. data/lib/aidp/providers/agent_supervisor.rb +0 -348
  119. data/lib/aidp/providers/supervised_base.rb +0 -317
  120. data/lib/aidp/providers/supervised_cursor.rb +0 -22
  121. data/lib/aidp/sync.rb +0 -13
  122. data/lib/aidp/workspace.rb +0 -19
@@ -0,0 +1,268 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aidp
4
+ module Harness
5
+ # Checks completion criteria for the workflow
6
+ class CompletionChecker
7
+ def initialize(project_dir, workflow_type = :exploration)
8
+ @project_dir = project_dir
9
+ @workflow_type = workflow_type
10
+ @completion_results = {}
11
+ end
12
+
13
+ # Check if all completion criteria are met
14
+ def all_criteria_met?
15
+ criteria = completion_criteria
16
+
17
+ criteria.all? do |criterion, checker|
18
+ result = send(checker)
19
+ @completion_results[criterion] = result
20
+ result
21
+ end
22
+ end
23
+
24
+ # Get completion criteria based on workflow type
25
+ def completion_criteria
26
+ base_criteria = {
27
+ steps_completed: :all_steps_completed?,
28
+ tests_passing: :tests_passing?,
29
+ linting_clean: :linting_clean?
30
+ }
31
+
32
+ if @workflow_type == :full
33
+ base_criteria.merge({
34
+ build_successful: :build_successful?,
35
+ documentation_complete: :documentation_complete?
36
+ })
37
+ else
38
+ base_criteria
39
+ end
40
+ end
41
+
42
+ # Get completion status report
43
+ def completion_status
44
+ all_criteria_met? # This populates @completion_results
45
+
46
+ {
47
+ all_complete: @completion_results.values.all?,
48
+ criteria: @completion_results,
49
+ summary: generate_summary
50
+ }
51
+ end
52
+
53
+ private
54
+
55
+ def all_steps_completed?
56
+ # This will be checked by the harness runner
57
+ true
58
+ end
59
+
60
+ def tests_passing?
61
+ return true unless has_tests?
62
+
63
+ # Check common test commands
64
+ test_commands = detect_test_commands
65
+ return true if test_commands.empty?
66
+
67
+ test_commands.any? do |cmd|
68
+ system("cd #{@project_dir} && #{cmd} > /dev/null 2>&1")
69
+ end
70
+ end
71
+
72
+ def linting_clean?
73
+ lint_commands = detect_lint_commands
74
+ return true if lint_commands.empty?
75
+
76
+ lint_commands.all? do |cmd|
77
+ system("cd #{@project_dir} && #{cmd} > /dev/null 2>&1")
78
+ end
79
+ end
80
+
81
+ def build_successful?
82
+ build_commands = detect_build_commands
83
+ return true if build_commands.empty?
84
+
85
+ build_commands.any? do |cmd|
86
+ system("cd #{@project_dir} && #{cmd} > /dev/null 2>&1")
87
+ end
88
+ end
89
+
90
+ def documentation_complete?
91
+ # Check if key documentation files exist
92
+ required_docs = %w[README.md docs/PRD.md]
93
+ required_docs.all? { |doc| File.exist?(File.join(@project_dir, doc)) }
94
+ end
95
+
96
+ def has_tests?
97
+ test_dirs = %w[test tests spec]
98
+ test_files = %w[*_test.rb *_spec.rb test_*.rb]
99
+
100
+ test_dirs.any? { |dir| Dir.exist?(File.join(@project_dir, dir)) } ||
101
+ test_files.any? { |pattern| Dir.glob(File.join(@project_dir, "**", pattern)).any? }
102
+ end
103
+
104
+ def detect_test_commands
105
+ commands = []
106
+
107
+ # Ruby
108
+ if File.exist?(File.join(@project_dir, "Gemfile"))
109
+ commands << "bundle exec rspec" if has_rspec?
110
+ commands << "bundle exec rake test" if has_rake_test?
111
+ commands << "ruby -Itest test/**/*_test.rb" if has_minitest?
112
+ end
113
+
114
+ # Node.js
115
+ if File.exist?(File.join(@project_dir, "package.json"))
116
+ package = begin
117
+ JSON.parse(File.read(File.join(@project_dir, "package.json")))
118
+ rescue
119
+ {}
120
+ end
121
+ if package.dig("scripts", "test")
122
+ commands << "npm test"
123
+ end
124
+ end
125
+
126
+ # Python
127
+ if File.exist?(File.join(@project_dir, "requirements.txt")) || File.exist?(File.join(@project_dir, "pyproject.toml"))
128
+ commands << "pytest" if has_pytest?
129
+ commands << "python -m unittest" if has_unittest?
130
+ end
131
+
132
+ commands
133
+ end
134
+
135
+ def detect_lint_commands
136
+ commands = []
137
+
138
+ # Ruby
139
+ if File.exist?(File.join(@project_dir, "Gemfile"))
140
+ commands << "bundle exec standardrb --no-fix" if has_standard?
141
+ commands << "bundle exec rubocop" if has_rubocop?
142
+ end
143
+
144
+ # Node.js
145
+ if File.exist?(File.join(@project_dir, "package.json"))
146
+ package = begin
147
+ JSON.parse(File.read(File.join(@project_dir, "package.json")))
148
+ rescue
149
+ {}
150
+ end
151
+ if package.dig("scripts", "lint")
152
+ commands << "npm run lint"
153
+ elsif has_eslint?
154
+ commands << "npx eslint ."
155
+ end
156
+ end
157
+
158
+ # Python
159
+ if File.exist?(File.join(@project_dir, "requirements.txt")) || File.exist?(File.join(@project_dir, "pyproject.toml"))
160
+ commands << "flake8 ." if has_flake8?
161
+ commands << "black --check ." if has_black?
162
+ end
163
+
164
+ commands
165
+ end
166
+
167
+ def detect_build_commands
168
+ commands = []
169
+
170
+ # Ruby gem
171
+ if File.exist?(File.join(@project_dir, "*.gemspec"))
172
+ commands << "bundle exec rake build"
173
+ end
174
+
175
+ # Node.js
176
+ if File.exist?(File.join(@project_dir, "package.json"))
177
+ package = begin
178
+ JSON.parse(File.read(File.join(@project_dir, "package.json")))
179
+ rescue
180
+ {}
181
+ end
182
+ if package.dig("scripts", "build")
183
+ commands << "npm run build"
184
+ end
185
+ end
186
+
187
+ # Python
188
+ if File.exist?(File.join(@project_dir, "setup.py")) || File.exist?(File.join(@project_dir, "pyproject.toml"))
189
+ commands << "python setup.py build" if File.exist?(File.join(@project_dir, "setup.py"))
190
+ commands << "python -m build" if File.exist?(File.join(@project_dir, "pyproject.toml"))
191
+ end
192
+
193
+ commands
194
+ end
195
+
196
+ def has_rspec?
197
+ gemfile_content = begin
198
+ File.read(File.join(@project_dir, "Gemfile"))
199
+ rescue
200
+ ""
201
+ end
202
+ gemfile_content.include?("rspec") || Dir.exist?(File.join(@project_dir, "spec"))
203
+ end
204
+
205
+ def has_rake_test?
206
+ File.exist?(File.join(@project_dir, "Rakefile")) && Dir.exist?(File.join(@project_dir, "test"))
207
+ end
208
+
209
+ def has_minitest?
210
+ Dir.exist?(File.join(@project_dir, "test"))
211
+ end
212
+
213
+ def has_standard?
214
+ gemfile_content = begin
215
+ File.read(File.join(@project_dir, "Gemfile"))
216
+ rescue
217
+ ""
218
+ end
219
+ gemfile_content.include?("standard")
220
+ end
221
+
222
+ def has_rubocop?
223
+ gemfile_content = begin
224
+ File.read(File.join(@project_dir, "Gemfile"))
225
+ rescue
226
+ ""
227
+ end
228
+ gemfile_content.include?("rubocop")
229
+ end
230
+
231
+ def has_eslint?
232
+ File.exist?(File.join(@project_dir, ".eslintrc")) ||
233
+ File.exist?(File.join(@project_dir, ".eslintrc.js")) ||
234
+ File.exist?(File.join(@project_dir, ".eslintrc.json"))
235
+ end
236
+
237
+ def has_pytest?
238
+ File.exist?(File.join(@project_dir, "pytest.ini")) ||
239
+ Dir.glob(File.join(@project_dir, "**", "*_test.py")).any?
240
+ end
241
+
242
+ def has_unittest?
243
+ Dir.glob(File.join(@project_dir, "**", "test_*.py")).any?
244
+ end
245
+
246
+ def has_flake8?
247
+ File.exist?(File.join(@project_dir, ".flake8")) ||
248
+ File.exist?(File.join(@project_dir, "setup.cfg"))
249
+ end
250
+
251
+ def has_black?
252
+ File.exist?(File.join(@project_dir, "pyproject.toml"))
253
+ end
254
+
255
+ def generate_summary
256
+ passed = @completion_results.count { |_, result| result }
257
+ total = @completion_results.size
258
+
259
+ if passed == total
260
+ "✅ All #{total} completion criteria met"
261
+ else
262
+ failed_criteria = @completion_results.select { |_, result| !result }.keys
263
+ "❌ #{total - passed}/#{total} criteria failed: #{failed_criteria.join(", ")}"
264
+ end
265
+ end
266
+ end
267
+ end
268
+ end