aidp 0.32.0 → 0.34.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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +35 -0
  3. data/lib/aidp/analyze/feature_analyzer.rb +322 -320
  4. data/lib/aidp/analyze/tree_sitter_scan.rb +3 -0
  5. data/lib/aidp/auto_update/coordinator.rb +97 -7
  6. data/lib/aidp/auto_update.rb +0 -12
  7. data/lib/aidp/cli/devcontainer_commands.rb +0 -5
  8. data/lib/aidp/cli/eval_command.rb +399 -0
  9. data/lib/aidp/cli/harness_command.rb +1 -1
  10. data/lib/aidp/cli/security_command.rb +416 -0
  11. data/lib/aidp/cli/tools_command.rb +6 -4
  12. data/lib/aidp/cli.rb +172 -4
  13. data/lib/aidp/comment_consolidator.rb +78 -0
  14. data/lib/aidp/concurrency/exec.rb +3 -0
  15. data/lib/aidp/concurrency.rb +0 -3
  16. data/lib/aidp/config.rb +113 -1
  17. data/lib/aidp/config_paths.rb +91 -0
  18. data/lib/aidp/daemon/runner.rb +8 -4
  19. data/lib/aidp/errors.rb +134 -0
  20. data/lib/aidp/evaluations/context_capture.rb +205 -0
  21. data/lib/aidp/evaluations/evaluation_record.rb +114 -0
  22. data/lib/aidp/evaluations/evaluation_storage.rb +250 -0
  23. data/lib/aidp/evaluations.rb +23 -0
  24. data/lib/aidp/execute/async_work_loop_runner.rb +4 -1
  25. data/lib/aidp/execute/interactive_repl.rb +6 -2
  26. data/lib/aidp/execute/prompt_evaluator.rb +359 -0
  27. data/lib/aidp/execute/repl_macros.rb +100 -1
  28. data/lib/aidp/execute/work_loop_runner.rb +719 -58
  29. data/lib/aidp/execute/work_loop_state.rb +4 -1
  30. data/lib/aidp/execute/workflow_selector.rb +3 -0
  31. data/lib/aidp/harness/ai_decision_engine.rb +79 -0
  32. data/lib/aidp/harness/ai_filter_factory.rb +285 -0
  33. data/lib/aidp/harness/capability_registry.rb +2 -0
  34. data/lib/aidp/harness/condition_detector.rb +3 -0
  35. data/lib/aidp/harness/config_loader.rb +3 -0
  36. data/lib/aidp/harness/config_schema.rb +97 -1
  37. data/lib/aidp/harness/config_validator.rb +1 -1
  38. data/lib/aidp/harness/configuration.rb +61 -5
  39. data/lib/aidp/harness/enhanced_runner.rb +14 -11
  40. data/lib/aidp/harness/error_handler.rb +3 -0
  41. data/lib/aidp/harness/filter_definition.rb +212 -0
  42. data/lib/aidp/harness/generated_filter_strategy.rb +197 -0
  43. data/lib/aidp/harness/output_filter.rb +50 -25
  44. data/lib/aidp/harness/output_filter_config.rb +129 -0
  45. data/lib/aidp/harness/provider_factory.rb +3 -0
  46. data/lib/aidp/harness/provider_manager.rb +96 -2
  47. data/lib/aidp/harness/runner.rb +5 -12
  48. data/lib/aidp/harness/state/persistence.rb +3 -0
  49. data/lib/aidp/harness/state_manager.rb +3 -0
  50. data/lib/aidp/harness/status_display.rb +28 -20
  51. data/lib/aidp/harness/test_runner.rb +179 -41
  52. data/lib/aidp/harness/thinking_depth_manager.rb +44 -28
  53. data/lib/aidp/harness/ui/enhanced_tui.rb +4 -0
  54. data/lib/aidp/harness/ui/enhanced_workflow_selector.rb +4 -0
  55. data/lib/aidp/harness/ui/error_handler.rb +3 -0
  56. data/lib/aidp/harness/ui/job_monitor.rb +4 -0
  57. data/lib/aidp/harness/ui/navigation/submenu.rb +2 -2
  58. data/lib/aidp/harness/ui/navigation/workflow_selector.rb +6 -0
  59. data/lib/aidp/harness/ui/spinner_helper.rb +3 -0
  60. data/lib/aidp/harness/ui/workflow_controller.rb +3 -0
  61. data/lib/aidp/harness/user_interface.rb +3 -0
  62. data/lib/aidp/loader.rb +195 -0
  63. data/lib/aidp/logger.rb +3 -0
  64. data/lib/aidp/message_display.rb +31 -0
  65. data/lib/aidp/metadata/compiler.rb +29 -17
  66. data/lib/aidp/metadata/query.rb +1 -1
  67. data/lib/aidp/metadata/scanner.rb +8 -1
  68. data/lib/aidp/metadata/tool_metadata.rb +13 -13
  69. data/lib/aidp/metadata/validator.rb +10 -0
  70. data/lib/aidp/metadata.rb +16 -0
  71. data/lib/aidp/pr_worktree_manager.rb +20 -8
  72. data/lib/aidp/provider_manager.rb +4 -7
  73. data/lib/aidp/providers/base.rb +2 -0
  74. data/lib/aidp/security/rule_of_two_enforcer.rb +210 -0
  75. data/lib/aidp/security/secrets_proxy.rb +328 -0
  76. data/lib/aidp/security/secrets_registry.rb +227 -0
  77. data/lib/aidp/security/trifecta_state.rb +220 -0
  78. data/lib/aidp/security/watch_mode_handler.rb +306 -0
  79. data/lib/aidp/security/work_loop_adapter.rb +277 -0
  80. data/lib/aidp/security.rb +56 -0
  81. data/lib/aidp/setup/wizard.rb +283 -11
  82. data/lib/aidp/skills.rb +0 -5
  83. data/lib/aidp/storage/csv_storage.rb +3 -0
  84. data/lib/aidp/style_guide/selector.rb +360 -0
  85. data/lib/aidp/tooling_detector.rb +283 -16
  86. data/lib/aidp/version.rb +1 -1
  87. data/lib/aidp/watch/auto_merger.rb +274 -0
  88. data/lib/aidp/watch/auto_pr_processor.rb +125 -7
  89. data/lib/aidp/watch/build_processor.rb +16 -1
  90. data/lib/aidp/watch/change_request_processor.rb +682 -150
  91. data/lib/aidp/watch/ci_fix_processor.rb +262 -4
  92. data/lib/aidp/watch/feedback_collector.rb +191 -0
  93. data/lib/aidp/watch/hierarchical_pr_strategy.rb +256 -0
  94. data/lib/aidp/watch/implementation_verifier.rb +142 -1
  95. data/lib/aidp/watch/plan_generator.rb +70 -13
  96. data/lib/aidp/watch/plan_processor.rb +12 -5
  97. data/lib/aidp/watch/projects_processor.rb +286 -0
  98. data/lib/aidp/watch/repository_client.rb +871 -22
  99. data/lib/aidp/watch/review_processor.rb +33 -6
  100. data/lib/aidp/watch/runner.rb +80 -29
  101. data/lib/aidp/watch/state_store.rb +233 -0
  102. data/lib/aidp/watch/sub_issue_creator.rb +221 -0
  103. data/lib/aidp/watch.rb +5 -7
  104. data/lib/aidp/workflows/guided_agent.rb +4 -0
  105. data/lib/aidp/workstream_cleanup.rb +0 -2
  106. data/lib/aidp/workstream_executor.rb +3 -4
  107. data/lib/aidp/worktree.rb +61 -12
  108. data/lib/aidp/worktree_branch_manager.rb +347 -101
  109. data/lib/aidp.rb +21 -106
  110. data/templates/implementation/iterative_implementation.md +46 -3
  111. metadata +91 -36
  112. data/lib/aidp/config/paths.rb +0 -131
@@ -7,19 +7,35 @@ module Aidp
7
7
  module Watch
8
8
  # Handles the aidp-auto label on PRs by chaining review and CI-fix flows
9
9
  # until the PR is ready for human review.
10
+ #
11
+ # Completion criteria:
12
+ # - Automated review completed (or already processed)
13
+ # - CI passing (success or skipped states accepted)
14
+ # - Iteration cap not exceeded (default: 20)
15
+ #
16
+ # When complete:
17
+ # - Converts draft PR to ready for review
18
+ # - Requests the label-adder as reviewer
19
+ # - Posts completion comment
20
+ # - Removes aidp-auto label
10
21
  class AutoPrProcessor
11
22
  include Aidp::MessageDisplay
12
23
 
13
24
  DEFAULT_AUTO_LABEL = "aidp-auto"
25
+ DEFAULT_ITERATION_CAP = 20
26
+ PASSING_CI_STATES = %w[success skipped].freeze
14
27
 
15
- def initialize(repository_client:, state_store:, review_processor:, ci_fix_processor:, label_config: {}, verbose: false)
28
+ def initialize(repository_client:, state_store:, review_processor:, ci_fix_processor:,
29
+ label_config: {}, iteration_cap: nil, verbose: false, prompt: nil)
16
30
  @repository_client = repository_client
17
31
  @state_store = state_store
18
32
  @review_processor = review_processor
19
33
  @ci_fix_processor = ci_fix_processor
20
34
  @state_extractor = GitHubStateExtractor.new(repository_client: repository_client)
21
35
  @verbose = verbose
36
+ @prompt = prompt
22
37
  @auto_label = label_config[:auto_trigger] || label_config["auto_trigger"] || DEFAULT_AUTO_LABEL
38
+ @iteration_cap = iteration_cap || DEFAULT_ITERATION_CAP
23
39
  end
24
40
 
25
41
  def process(pr)
@@ -27,6 +43,19 @@ module Aidp
27
43
  Aidp.log_debug("auto_pr_processor", "process_started", pr: number, title: pr[:title])
28
44
  display_message("🤖 Running autonomous review/CI loop for PR ##{number}", type: :info)
29
45
 
46
+ # Record this iteration
47
+ iteration = @state_store.record_auto_pr_iteration(number)
48
+ Aidp.log_debug("auto_pr_processor", "iteration_recorded", pr: number, iteration: iteration, cap: @iteration_cap)
49
+
50
+ # Check iteration cap
51
+ if iteration > @iteration_cap
52
+ Aidp.log_warn("auto_pr_processor", "iteration_cap_reached",
53
+ pr: number, iteration: iteration, cap: @iteration_cap)
54
+ display_message("⚠️ PR ##{number} reached iteration cap (#{@iteration_cap}), marking ready", type: :warn)
55
+ finalize_pr(pr_number: number, reason: :iteration_cap_reached)
56
+ return
57
+ end
58
+
30
59
  # Run review and CI fix flows. Each processor is responsible for its own guards.
31
60
  @review_processor.process(pr)
32
61
  @ci_fix_processor.process(pr)
@@ -37,7 +66,7 @@ module Aidp
37
66
  display_message("❌ aidp-auto failed on PR ##{pr[:number]}: #{e.message}", type: :error)
38
67
  end
39
68
 
40
- attr_reader :auto_label
69
+ attr_reader :auto_label, :iteration_cap
41
70
 
42
71
  private
43
72
 
@@ -46,25 +75,114 @@ module Aidp
46
75
  ci_status = @repository_client.fetch_ci_status(pr_number)
47
76
 
48
77
  review_done = @state_extractor.review_completed?(pr_data) || @state_store.review_processed?(pr_number)
49
- ci_passing = ci_status[:state] == "success"
78
+ ci_passing = ci_state_passing?(ci_status)
50
79
 
51
80
  Aidp.log_debug("auto_pr_processor", "completion_check",
52
81
  pr: pr_number,
53
82
  review_done: review_done,
54
- ci_state: ci_status[:state])
83
+ ci_state: ci_status[:state],
84
+ ci_passing: ci_passing)
55
85
 
56
86
  return unless review_done && ci_passing
57
87
 
58
- post_completion_comment(pr_number)
88
+ finalize_pr(pr_number: pr_number, reason: :completion_criteria_met)
89
+ end
90
+
91
+ # Check if CI state indicates passing (success or skipped)
92
+ # @param ci_status [Hash] CI status from repository_client
93
+ # @return [Boolean] True if CI is considered passing
94
+ def ci_state_passing?(ci_status)
95
+ state = ci_status[:state]
96
+
97
+ # Direct state match
98
+ return true if PASSING_CI_STATES.include?(state)
99
+
100
+ # Check individual checks - all must be success or skipped
101
+ checks = ci_status[:checks] || []
102
+ return false if checks.empty?
103
+
104
+ checks.all? do |check|
105
+ conclusion = check[:conclusion]
106
+ PASSING_CI_STATES.include?(conclusion)
107
+ end
108
+ end
109
+
110
+ def finalize_pr(pr_number:, reason:)
111
+ Aidp.log_info("auto_pr_processor", "finalizing_pr",
112
+ pr: pr_number, reason: reason)
113
+
114
+ # Convert draft to ready if needed
115
+ convert_draft_to_ready(pr_number)
116
+
117
+ # Request reviewer (label-adder)
118
+ request_label_adder_as_reviewer(pr_number)
119
+
120
+ # Post completion comment
121
+ post_completion_comment(pr_number, reason: reason)
122
+
123
+ # Remove auto label
59
124
  remove_auto_label(pr_number)
125
+
126
+ # Mark as completed in state store
127
+ @state_store.complete_auto_pr(pr_number, reason: reason.to_s)
128
+
129
+ display_message("✅ PR ##{pr_number} ready for human review", type: :success)
130
+ end
131
+
132
+ def convert_draft_to_ready(pr_number)
133
+ # Attempt the conversion and let it fail gracefully if already ready
134
+ # The gh CLI will return an error if PR is not a draft
135
+ success = @repository_client.mark_pr_ready_for_review(pr_number)
136
+ if success
137
+ display_message("📋 Converted PR ##{pr_number} from draft to ready", type: :info)
138
+ else
139
+ Aidp.log_debug("auto_pr_processor", "draft_conversion_skipped",
140
+ pr: pr_number, message: "PR may already be ready for review")
141
+ end
142
+ rescue => e
143
+ Aidp.log_warn("auto_pr_processor", "draft_conversion_failed",
144
+ pr: pr_number, error: e.message)
60
145
  end
61
146
 
62
- def post_completion_comment(pr_number)
147
+ def request_label_adder_as_reviewer(pr_number)
148
+ label_actor = @repository_client.most_recent_pr_label_actor(pr_number)
149
+
150
+ unless label_actor
151
+ Aidp.log_debug("auto_pr_processor", "no_label_actor_found", pr: pr_number)
152
+ return
153
+ end
154
+
155
+ success = @repository_client.request_reviewers(pr_number, reviewers: [label_actor])
156
+ if success
157
+ display_message("👤 Requested @#{label_actor} as reviewer on PR ##{pr_number}", type: :info)
158
+ else
159
+ Aidp.log_warn("auto_pr_processor", "reviewer_request_failed",
160
+ pr: pr_number, reviewer: label_actor)
161
+ end
162
+ rescue => e
163
+ Aidp.log_warn("auto_pr_processor", "reviewer_request_exception",
164
+ pr: pr_number, error: e.message)
165
+ end
166
+
167
+ def post_completion_comment(pr_number, reason:)
168
+ iteration = @state_store.auto_pr_iteration_count(pr_number)
169
+
170
+ reason_text = case reason
171
+ when :iteration_cap_reached
172
+ "Iteration cap (#{@iteration_cap}) reached"
173
+ when :completion_criteria_met
174
+ "All completion criteria met"
175
+ else
176
+ "Processing complete"
177
+ end
178
+
63
179
  comment = <<~COMMENT
64
180
  ## 🤖 aidp-auto
65
181
 
182
+ #{reason_text} after #{iteration} iteration(s).
183
+
66
184
  - Automated review completed
67
- - CI is passing
185
+ - CI is passing (success/skipped)
68
186
 
69
187
  Marking this PR ready for human review and removing the `#{@auto_label}` label.
70
188
  COMMENT
@@ -12,6 +12,7 @@ require_relative "../worktree"
12
12
  require_relative "../execute/progress"
13
13
  require_relative "github_state_extractor"
14
14
  require_relative "implementation_verifier"
15
+ require_relative "feedback_collector"
15
16
 
16
17
  module Aidp
17
18
  module Watch
@@ -25,6 +26,8 @@ module Aidp
25
26
  IMPLEMENTATION_STEP = "16_IMPLEMENTATION"
26
27
 
27
28
  attr_reader :build_label, :needs_input_label
29
+ # Expose state for testability
30
+ attr_writer :config, :verifier
28
31
 
29
32
  def initialize(repository_client:, state_store:, project_dir: Dir.pwd, use_workstreams: true, verbose: false, label_config: {})
30
33
  @repository_client = repository_client
@@ -525,7 +528,19 @@ module Aidp
525
528
  #{plan_value(plan_data, "summary")}
526
529
  COMMENT
527
530
 
528
- @repository_client.post_comment(issue[:number], comment)
531
+ comment_with_feedback = FeedbackCollector.append_feedback_prompt(comment)
532
+ result = @repository_client.post_comment(issue[:number], comment_with_feedback)
533
+ comment_id = result[:id] if result.is_a?(Hash)
534
+
535
+ # Track comment for feedback collection
536
+ if comment_id
537
+ @state_store.track_comment_for_feedback(
538
+ comment_id: comment_id,
539
+ processor_type: "build",
540
+ number: issue[:number]
541
+ )
542
+ end
543
+
529
544
  display_message("🎉 Posted completion comment for issue ##{issue[:number]}", type: :success)
530
545
 
531
546
  # Keep workstream for review - don't auto-cleanup on success