aidp 0.7.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 (119) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +60 -214
  3. data/bin/aidp +1 -1
  4. data/lib/aidp/analysis/kb_inspector.rb +38 -23
  5. data/lib/aidp/analysis/seams.rb +2 -31
  6. data/lib/aidp/analysis/tree_sitter_grammar_loader.rb +0 -13
  7. data/lib/aidp/analysis/tree_sitter_scan.rb +3 -20
  8. data/lib/aidp/analyze/error_handler.rb +2 -75
  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/cli/jobs_command.rb +100 -432
  15. data/lib/aidp/cli.rb +309 -239
  16. data/lib/aidp/config.rb +298 -10
  17. data/lib/aidp/debug_logger.rb +195 -0
  18. data/lib/aidp/debug_mixin.rb +187 -0
  19. data/lib/aidp/execute/progress.rb +9 -0
  20. data/lib/aidp/execute/runner.rb +221 -40
  21. data/lib/aidp/execute/steps.rb +17 -7
  22. data/lib/aidp/execute/workflow_selector.rb +211 -0
  23. data/lib/aidp/harness/completion_checker.rb +268 -0
  24. data/lib/aidp/harness/condition_detector.rb +1526 -0
  25. data/lib/aidp/harness/config_loader.rb +373 -0
  26. data/lib/aidp/harness/config_manager.rb +382 -0
  27. data/lib/aidp/harness/config_schema.rb +1006 -0
  28. data/lib/aidp/harness/config_validator.rb +355 -0
  29. data/lib/aidp/harness/configuration.rb +477 -0
  30. data/lib/aidp/harness/enhanced_runner.rb +494 -0
  31. data/lib/aidp/harness/error_handler.rb +616 -0
  32. data/lib/aidp/harness/provider_config.rb +423 -0
  33. data/lib/aidp/harness/provider_factory.rb +306 -0
  34. data/lib/aidp/harness/provider_manager.rb +1269 -0
  35. data/lib/aidp/harness/provider_type_checker.rb +88 -0
  36. data/lib/aidp/harness/runner.rb +411 -0
  37. data/lib/aidp/harness/state/errors.rb +28 -0
  38. data/lib/aidp/harness/state/metrics.rb +219 -0
  39. data/lib/aidp/harness/state/persistence.rb +128 -0
  40. data/lib/aidp/harness/state/provider_state.rb +132 -0
  41. data/lib/aidp/harness/state/ui_state.rb +68 -0
  42. data/lib/aidp/harness/state/workflow_state.rb +123 -0
  43. data/lib/aidp/harness/state_manager.rb +586 -0
  44. data/lib/aidp/harness/status_display.rb +888 -0
  45. data/lib/aidp/harness/ui/base.rb +16 -0
  46. data/lib/aidp/harness/ui/enhanced_tui.rb +545 -0
  47. data/lib/aidp/harness/ui/enhanced_workflow_selector.rb +252 -0
  48. data/lib/aidp/harness/ui/error_handler.rb +132 -0
  49. data/lib/aidp/harness/ui/frame_manager.rb +361 -0
  50. data/lib/aidp/harness/ui/job_monitor.rb +500 -0
  51. data/lib/aidp/harness/ui/navigation/main_menu.rb +311 -0
  52. data/lib/aidp/harness/ui/navigation/menu_formatter.rb +120 -0
  53. data/lib/aidp/harness/ui/navigation/menu_item.rb +142 -0
  54. data/lib/aidp/harness/ui/navigation/menu_state.rb +139 -0
  55. data/lib/aidp/harness/ui/navigation/submenu.rb +202 -0
  56. data/lib/aidp/harness/ui/navigation/workflow_selector.rb +176 -0
  57. data/lib/aidp/harness/ui/progress_display.rb +280 -0
  58. data/lib/aidp/harness/ui/question_collector.rb +141 -0
  59. data/lib/aidp/harness/ui/spinner_group.rb +184 -0
  60. data/lib/aidp/harness/ui/spinner_helper.rb +152 -0
  61. data/lib/aidp/harness/ui/status_manager.rb +312 -0
  62. data/lib/aidp/harness/ui/status_widget.rb +280 -0
  63. data/lib/aidp/harness/ui/workflow_controller.rb +312 -0
  64. data/lib/aidp/harness/user_interface.rb +2381 -0
  65. data/lib/aidp/provider_manager.rb +131 -7
  66. data/lib/aidp/providers/anthropic.rb +28 -103
  67. data/lib/aidp/providers/base.rb +170 -0
  68. data/lib/aidp/providers/cursor.rb +52 -181
  69. data/lib/aidp/providers/gemini.rb +24 -107
  70. data/lib/aidp/providers/macos_ui.rb +99 -5
  71. data/lib/aidp/providers/opencode.rb +194 -0
  72. data/lib/aidp/storage/csv_storage.rb +172 -0
  73. data/lib/aidp/storage/file_manager.rb +214 -0
  74. data/lib/aidp/storage/json_storage.rb +140 -0
  75. data/lib/aidp/version.rb +1 -1
  76. data/lib/aidp.rb +54 -39
  77. data/templates/COMMON/AGENT_BASE.md +11 -0
  78. data/templates/EXECUTE/00_PRD.md +4 -4
  79. data/templates/EXECUTE/02_ARCHITECTURE.md +5 -4
  80. data/templates/EXECUTE/07_TEST_PLAN.md +4 -1
  81. data/templates/EXECUTE/08_TASKS.md +4 -4
  82. data/templates/EXECUTE/10_IMPLEMENTATION_AGENT.md +4 -4
  83. data/templates/README.md +279 -0
  84. data/templates/aidp-development.yml.example +373 -0
  85. data/templates/aidp-minimal.yml.example +48 -0
  86. data/templates/aidp-production.yml.example +475 -0
  87. data/templates/aidp.yml.example +598 -0
  88. metadata +93 -69
  89. data/lib/aidp/analyze/agent_personas.rb +0 -71
  90. data/lib/aidp/analyze/agent_tool_executor.rb +0 -439
  91. data/lib/aidp/analyze/data_retention_manager.rb +0 -421
  92. data/lib/aidp/analyze/database.rb +0 -260
  93. data/lib/aidp/analyze/dependencies.rb +0 -335
  94. data/lib/aidp/analyze/export_manager.rb +0 -418
  95. data/lib/aidp/analyze/focus_guidance.rb +0 -517
  96. data/lib/aidp/analyze/incremental_analyzer.rb +0 -533
  97. data/lib/aidp/analyze/language_analysis_strategies.rb +0 -897
  98. data/lib/aidp/analyze/large_analysis_progress.rb +0 -499
  99. data/lib/aidp/analyze/memory_manager.rb +0 -339
  100. data/lib/aidp/analyze/metrics_storage.rb +0 -336
  101. data/lib/aidp/analyze/parallel_processor.rb +0 -454
  102. data/lib/aidp/analyze/performance_optimizer.rb +0 -691
  103. data/lib/aidp/analyze/repository_chunker.rb +0 -697
  104. data/lib/aidp/analyze/static_analysis_detector.rb +0 -577
  105. data/lib/aidp/analyze/storage.rb +0 -655
  106. data/lib/aidp/analyze/tool_configuration.rb +0 -441
  107. data/lib/aidp/analyze/tool_modernization.rb +0 -750
  108. data/lib/aidp/database/pg_adapter.rb +0 -148
  109. data/lib/aidp/database_config.rb +0 -69
  110. data/lib/aidp/database_connection.rb +0 -72
  111. data/lib/aidp/job_manager.rb +0 -41
  112. data/lib/aidp/jobs/base_job.rb +0 -45
  113. data/lib/aidp/jobs/provider_execution_job.rb +0 -83
  114. data/lib/aidp/project_detector.rb +0 -117
  115. data/lib/aidp/providers/agent_supervisor.rb +0 -348
  116. data/lib/aidp/providers/supervised_base.rb +0 -317
  117. data/lib/aidp/providers/supervised_cursor.rb +0 -22
  118. data/lib/aidp/sync.rb +0 -13
  119. 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