Class: Aidp::Watch::FeedbackCollector

Inherits:
Object
  • Object
show all
Defined in:
lib/aidp/watch/feedback_collector.rb

Overview

Collects user feedback via GitHub reactions and converts to evaluations

Monitors reactions on AIDP-posted comments:

  • πŸ‘ (+1) = good rating

  • πŸ‘Ž (-1) = bad rating

  • πŸ˜• (confused) = neutral rating

Examples:

collector = FeedbackCollector.new(
  repository_client: client,
  state_store: store,
  project_dir: Dir.pwd
)
collector.collect_feedback

Constant Summary collapse

REACTION_RATINGS =

Mapping from GitHub reaction content to evaluation rating

{
  "+1" => "good",
  "-1" => "bad",
  "confused" => "neutral",
  "heart" => "good",
  "hooray" => "good",
  "rocket" => "good",
  "eyes" => "neutral"
}.freeze
FEEDBACK_PROMPT =

Feedback prompt text to include in comments

"---\n**Rate this output**: React with \u{1F44D} (good), \u{1F44E} (bad), or \u{1F615} (neutral) to help improve AIDP.\n".strip

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(repository_client:, state_store:, project_dir: Dir.pwd) ⇒ FeedbackCollector

Returns a new instance of FeedbackCollector.



39
40
41
42
43
44
45
46
47
# File 'lib/aidp/watch/feedback_collector.rb', line 39

def initialize(repository_client:, state_store:, project_dir: Dir.pwd)
  @repository_client = repository_client
  @state_store = state_store
  @project_dir = project_dir
  @evaluation_storage = Evaluations::EvaluationStorage.new(project_dir: project_dir)

  Aidp.log_debug("feedback_collector", "initialize",
    repo: repository_client.full_repo, project_dir: project_dir)
end

Class Method Details

.append_feedback_prompt(body) ⇒ String

Append feedback prompt to a comment body

Parameters:

  • body (String)

    Original comment body

Returns:

  • (String)

    Comment body with feedback prompt



130
131
132
# File 'lib/aidp/watch/feedback_collector.rb', line 130

def self.append_feedback_prompt(body)
  "#{body}\n\n#{FEEDBACK_PROMPT}"
end

Instance Method Details

#collect_feedbackArray<Hash>

Collect feedback from all tracked comments

Returns:

  • (Array<Hash>)

    List of new evaluations recorded



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/aidp/watch/feedback_collector.rb', line 52

def collect_feedback
  Aidp.log_debug("feedback_collector", "collect_feedback_start")

  tracked_comments = @state_store.tracked_comments
  return [] if tracked_comments.empty?

  new_evaluations = []

  tracked_comments.each do |comment_info|
    evaluations = process_comment_reactions(comment_info)
    new_evaluations.concat(evaluations)
  end

  Aidp.log_debug("feedback_collector", "collect_feedback_complete",
    tracked_count: tracked_comments.size, new_evaluations: new_evaluations.size)

  new_evaluations
end

#process_comment_reactions(comment_info) ⇒ Array<Hash>

Process reactions on a specific comment and create evaluations

Parameters:

  • comment_info (Hash)

    Comment tracking info from state store

Returns:

  • (Array<Hash>)

    New evaluations created



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
# File 'lib/aidp/watch/feedback_collector.rb', line 75

def process_comment_reactions(comment_info)
  comment_id = comment_info[:comment_id] || comment_info["comment_id"]
  return [] unless comment_id

  processor_type = comment_info[:processor_type] || comment_info["processor_type"]
  target_number = comment_info[:number] || comment_info["number"]

  Aidp.log_debug("feedback_collector", "process_comment",
    comment_id: comment_id, processor_type: processor_type, number: target_number)

  # Fetch reactions from GitHub
  reactions = @repository_client.fetch_comment_reactions(comment_id)
  return [] if reactions.empty?

  # Get already-processed reaction IDs
  processed_ids = @state_store.processed_reaction_ids(comment_id)

  new_evaluations = []

  reactions.each do |reaction|
    reaction_id = reaction[:id]
    next if processed_ids.include?(reaction_id)

    rating = reaction_to_rating(reaction[:content])
    next unless rating

    # Create evaluation record
    evaluation = create_evaluation(
      rating: rating,
      processor_type: processor_type,
      target_number: target_number,
      reaction: reaction
    )

    if evaluation
      new_evaluations << evaluation
      @state_store.mark_reaction_processed(comment_id, reaction_id)
    end
  end

  new_evaluations
end

#reaction_to_rating(content) ⇒ String?

Convert GitHub reaction content to evaluation rating

Parameters:

  • content (String)

    GitHub reaction content (e.g., β€œ+1”, β€œ-1”, β€œconfused”)

Returns:

  • (String, nil)

    Rating or nil if not mappable



122
123
124
# File 'lib/aidp/watch/feedback_collector.rb', line 122

def reaction_to_rating(content)
  REACTION_RATINGS[content]
end