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- IN_PROGRESS_LABEL =
Pattern for detecting in-progress label
"aidp-in-progress"
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.
-
#in_progress?(item) ⇒ Boolean
Check if an issue/PR is currently being worked on by another instance.
-
#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.
23 24 25 |
# File 'lib/aidp/watch/github_state_extractor.rb', line 23 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
34 35 36 37 38 39 40 |
# File 'lib/aidp/watch/github_state_extractor.rb', line 34 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
112 113 114 115 116 117 118 119 120 121 |
# File 'lib/aidp/watch/github_state_extractor.rb', line 112 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
97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/aidp/watch/github_state_extractor.rb', line 97 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
76 77 78 79 80 81 82 83 84 85 |
# File 'lib/aidp/watch/github_state_extractor.rb', line 76 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
126 127 128 129 130 131 132 133 |
# File 'lib/aidp/watch/github_state_extractor.rb', line 126 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
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/aidp/watch/github_state_extractor.rb', line 52 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 |
#in_progress?(item) ⇒ Boolean
Check if an issue/PR is currently being worked on by another instance
28 29 30 |
# File 'lib/aidp/watch/github_state_extractor.rb', line 28 def in_progress?(item) has_label?(item, IN_PROGRESS_LABEL) end |
#plan_posted?(issue) ⇒ Boolean
Check if a plan has been posted for an issue
43 44 45 46 47 48 49 |
# File 'lib/aidp/watch/github_state_extractor.rb', line 43 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
88 89 90 91 92 93 94 |
# File 'lib/aidp/watch/github_state_extractor.rb', line 88 def review_completed?(pr) return false unless pr[:comments] pr[:comments].any? do |comment| comment["body"]&.match?(/🔍.*Review complete/i) end end |