Class: Aidp::Watch::GitHubStateExtractor
- Inherits:
-
Object
- Object
- Aidp::Watch::GitHubStateExtractor
- Defined in:
- lib/aidp/watch/github_state_extractor.rb
Overview
Extracts state information from GitHub issues/PRs using labels and comments as the single source of truth, enabling multiple AIDP instances to coordinate without local state files.
Constant Summary collapse
- COMPLETION_PATTERN =
Pattern for detecting completion comments
/✅ Implementation complete for #(\d+)/i- DETECTION_PATTERN =
Pattern for detecting detection comments
/aidp detected `([^`]+)` at ([^\n]+) and is working on it/i- PLAN_PROPOSAL_PATTERN =
Pattern for detecting plan proposal comments
/<!-- PLAN_SUMMARY_START -->/i
Instance Method Summary collapse
-
#build_completed?(issue) ⇒ Boolean
Check if build is already completed for an issue Looks for completion comment from AIDP.
-
#change_request_processed?(pr) ⇒ Boolean
Check if change request has been processed for a PR.
-
#ci_fix_completed?(pr) ⇒ Boolean
Check if CI fix has been completed for a PR.
-
#detection_comment_posted?(item, label) ⇒ Boolean
Check if detection comment was already posted for this label.
-
#extract_linked_issue(pr_body) ⇒ Object
Extract linked issue number from PR description Looks for patterns like "Fixes #123", "Closes #456", "Resolves #789" Returns the issue number as an integer, or nil if not found.
-
#extract_plan_data(issue) ⇒ Object
Extract the most recent plan data from comments.
-
#initialize(repository_client:) ⇒ GitHubStateExtractor
constructor
A new instance of GitHubStateExtractor.
-
#plan_posted?(issue) ⇒ Boolean
Check if a plan has been posted for an issue.
-
#review_completed?(pr) ⇒ Boolean
Check if review has been completed for a PR.
Constructor Details
#initialize(repository_client:) ⇒ GitHubStateExtractor
Returns a new instance of GitHubStateExtractor.
20 21 22 |
# File 'lib/aidp/watch/github_state_extractor.rb', line 20 def initialize(repository_client:) @repository_client = repository_client end |
Instance Method Details
#build_completed?(issue) ⇒ Boolean
Check if build is already completed for an issue Looks for completion comment from AIDP
26 27 28 29 30 31 32 |
# File 'lib/aidp/watch/github_state_extractor.rb', line 26 def build_completed?(issue) return false unless issue[:comments] issue[:comments].any? do |comment| comment["body"]&.match?(COMPLETION_PATTERN) end end |
#change_request_processed?(pr) ⇒ Boolean
Check if change request has been processed for a PR
104 105 106 107 108 109 110 111 112 113 |
# File 'lib/aidp/watch/github_state_extractor.rb', line 104 def change_request_processed?(pr) return false unless pr[:comments] pr[:comments].any? do |comment| body = comment["body"] next false unless body body.include?("✅") && body.match?(/Change requests? (?:addressed|applied|complete)/i) end end |
#ci_fix_completed?(pr) ⇒ Boolean
Check if CI fix has been completed for a PR
89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/aidp/watch/github_state_extractor.rb', line 89 def ci_fix_completed?(pr) return false unless pr[:comments] pr[:comments].any? do |comment| body = comment["body"] next false unless body body.include?("✅") && ( body.match?(/CI fixes applied/i) || (body.match?(/CI check/i) && body.match?(/passed/i)) ) end end |
#detection_comment_posted?(item, label) ⇒ Boolean
Check if detection comment was already posted for this label
68 69 70 71 72 73 74 75 76 77 |
# File 'lib/aidp/watch/github_state_extractor.rb', line 68 def detection_comment_posted?(item, label) return false unless item[:comments] item[:comments].any? do |comment| next unless comment["body"] match = comment["body"].match(DETECTION_PATTERN) match && match[1] == label end end |
#extract_linked_issue(pr_body) ⇒ Object
Extract linked issue number from PR description Looks for patterns like "Fixes #123", "Closes #456", "Resolves #789" Returns the issue number as an integer, or nil if not found
118 119 120 121 122 123 124 125 |
# File 'lib/aidp/watch/github_state_extractor.rb', line 118 def extract_linked_issue(pr_body) return nil unless pr_body # Match common GitHub issue linking patterns # https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue match = pr_body.match(/(?:Fixes|Closes|Resolves|Close|Fix|Resolve)\s+#(\d+)/i) match ? match[1].to_i : nil end |
#extract_plan_data(issue) ⇒ Object
Extract the most recent plan data from comments
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/aidp/watch/github_state_extractor.rb', line 44 def extract_plan_data(issue) return nil unless issue[:comments] # Find the most recent plan proposal comment plan_comment = issue[:comments].reverse.find do |comment| comment["body"]&.match?(PLAN_PROPOSAL_PATTERN) end return nil unless plan_comment body = plan_comment["body"] { summary: extract_section(body, "PLAN_SUMMARY"), tasks: extract_tasks(body), questions: extract_questions(body), comment_body: body, comment_hint: "## 🤖 AIDP Plan Proposal", comment_id: plan_comment["id"], posted_at: plan_comment["createdAt"] || Time.now.utc.iso8601 } end |
#plan_posted?(issue) ⇒ Boolean
Check if a plan has been posted for an issue
35 36 37 38 39 40 41 |
# File 'lib/aidp/watch/github_state_extractor.rb', line 35 def plan_posted?(issue) return false unless issue[:comments] issue[:comments].any? do |comment| comment["body"]&.match?(PLAN_PROPOSAL_PATTERN) end end |
#review_completed?(pr) ⇒ Boolean
Check if review has been completed for a PR
80 81 82 83 84 85 86 |
# File 'lib/aidp/watch/github_state_extractor.rb', line 80 def review_completed?(pr) return false unless pr[:comments] pr[:comments].any? do |comment| comment["body"]&.match?(/🔍.*Review complete/i) end end |