Class: Aidp::Watch::ChangeRequestProcessor
- Inherits:
-
Object
- Object
- Aidp::Watch::ChangeRequestProcessor
- Includes:
- MessageDisplay
- Defined in:
- lib/aidp/watch/change_request_processor.rb
Overview
Handles the aidp-request-changes label trigger by analyzing PR comments and automatically implementing the requested changes.
Constant Summary collapse
- DEFAULT_CHANGE_REQUEST_LABEL =
Default label names
"aidp-request-changes"- DEFAULT_NEEDS_INPUT_LABEL =
"aidp-needs-input"- COMMENT_HEADER =
"## đ¤ AIDP Change Request"- MAX_CLARIFICATION_ROUNDS =
3
Constants included from MessageDisplay
Instance Attribute Summary collapse
-
#change_request_label ⇒ Object
readonly
Returns the value of attribute change_request_label.
-
#needs_input_label ⇒ Object
readonly
Returns the value of attribute needs_input_label.
Instance Method Summary collapse
-
#initialize(repository_client:, state_store:, provider_name: nil, project_dir: Dir.pwd, label_config: {}, change_request_config: {}, safety_config: {}, verbose: false) ⇒ ChangeRequestProcessor
constructor
A new instance of ChangeRequestProcessor.
- #process(pr) ⇒ Object
Methods included from MessageDisplay
#display_message, included, #message_display_prompt
Constructor Details
#initialize(repository_client:, state_store:, provider_name: nil, project_dir: Dir.pwd, label_config: {}, change_request_config: {}, safety_config: {}, verbose: false) ⇒ ChangeRequestProcessor
Returns a new instance of ChangeRequestProcessor.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/aidp/watch/change_request_processor.rb', line 35 def initialize(repository_client:, state_store:, provider_name: nil, project_dir: Dir.pwd, label_config: {}, change_request_config: {}, safety_config: {}, verbose: false) @repository_client = repository_client @state_store = state_store @state_extractor = GitHubStateExtractor.new(repository_client: repository_client) @provider_name = provider_name @project_dir = project_dir @verbose = verbose # Initialize verifier @verifier = ImplementationVerifier.new( repository_client: repository_client, project_dir: project_dir ) # Load label configuration @change_request_label = label_config[:change_request_trigger] || label_config["change_request_trigger"] || DEFAULT_CHANGE_REQUEST_LABEL @needs_input_label = label_config[:needs_input] || label_config["needs_input"] || DEFAULT_NEEDS_INPUT_LABEL # Load change request configuration @config = { enabled: true, allow_multi_file_edits: true, run_tests_before_push: true, commit_message_prefix: "aidp: pr-change", require_comment_reference: true, max_diff_size: 2000, allow_large_pr_worktree_bypass: true # Default to always using worktree for large PRs }.merge(symbolize_keys(change_request_config)) # Load safety configuration @safety_config = safety_config = Array(@safety_config[:author_allowlist] || @safety_config["author_allowlist"]) end |
Instance Attribute Details
#change_request_label ⇒ Object (readonly)
Returns the value of attribute change_request_label.
33 34 35 |
# File 'lib/aidp/watch/change_request_processor.rb', line 33 def change_request_label @change_request_label end |
#needs_input_label ⇒ Object (readonly)
Returns the value of attribute needs_input_label.
33 34 35 |
# File 'lib/aidp/watch/change_request_processor.rb', line 33 def needs_input_label @needs_input_label end |
Instance Method Details
#process(pr) ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/aidp/watch/change_request_processor.rb', line 69 def process(pr) number = pr[:number] unless @config[:enabled] ("âšī¸ PR change requests are disabled in configuration. Skipping PR ##{number}.", type: :muted) return end # Check clarification round limit existing_data = @state_store.change_request_data(number) if existing_data && existing_data["clarification_count"].to_i >= MAX_CLARIFICATION_ROUNDS ("â ī¸ Max clarification rounds (#{MAX_CLARIFICATION_ROUNDS}) reached for PR ##{number}. Skipping.", type: :warn) post_max_rounds_comment(pr) return end ("đ Processing change request for PR ##{number} (#{pr[:title]})", type: :info) # Fetch PR details pr_data = @repository_client.fetch_pull_request(number) comments = @repository_client.fetch_pr_comments(number) # Filter comments from authorized users = (comments, pr_data) if .empty? ("âšī¸ No authorized comments found for PR ##{number}. Skipping.", type: :muted) return end # If max_diff_size is set, attempt to fetch and check diff # But bypass restriction for worktree-based workflows diff = @repository_client.fetch_pull_request_diff(number) diff_size = diff.lines.count # Check if we want to use the worktree bypass use_worktree_bypass = @config[:allow_large_pr_worktree_bypass] || @config[:allow_large_pr_worktree_bypass].nil? if diff_size > @config[:max_diff_size] && !use_worktree_bypass ("â ī¸ PR ##{number} diff too large (#{diff_size} lines > #{@config[:max_diff_size]}). Skipping.", type: :warn) post_diff_too_large_comment(pr, diff_size) return end # Log the diff size for observability Aidp.log_debug("change_request_processor", "PR diff size", number: number, size: diff_size, max_allowed: @config[:max_diff_size], worktree_bypass: use_worktree_bypass) # Analyze change requests analysis_result = analyze_change_requests(pr_data: pr_data, comments: , diff: diff) if analysis_result[:needs_clarification] handle_clarification_needed(pr: pr_data, analysis: analysis_result) elsif analysis_result[:can_implement] implement_changes(pr: pr_data, analysis: analysis_result, diff: diff) else handle_cannot_implement(pr: pr_data, analysis: analysis_result) end rescue => e ("â Change request processing failed: #{e.message}", type: :error) Aidp.log_error("change_request_processor", "Change request failed", pr: pr[:number], error: e., backtrace: e.backtrace&.first(10)) # Record failure state internally but DON'T post error to GitHub # (per issue #280 - error messages should never appear on issues) @state_store.record_change_request(pr[:number], { status: "error", error: e., error_class: e.class.name, timestamp: Time.now.utc.iso8601 }) end |