Class: Aidp::Execute::FutureWorkBacklog
- Inherits:
-
Object
- Object
- Aidp::Execute::FutureWorkBacklog
- Defined in:
- lib/aidp/execute/future_work_backlog.rb
Overview
Manages a backlog of future work items discovered during work loops Captures style violations, technical debt, and refactoring opportunities that are not directly related to the current feature being implemented
Constant Summary collapse
- ENTRY_TYPES =
Entry types
{ style_violation: "Style Violation", refactor_opportunity: "Refactor Opportunity", technical_debt: "Technical Debt", todo: "TODO", performance: "Performance Issue", security: "Security Concern", documentation: "Documentation Needed" }.freeze
- PRIORITIES =
Priority levels
{ low: 1, medium: 2, high: 3, critical: 4 }.freeze
Instance Attribute Summary collapse
-
#current_context ⇒ Object
readonly
Returns the value of attribute current_context.
-
#entries ⇒ Object
readonly
Returns the value of attribute entries.
-
#project_dir ⇒ Object
readonly
Returns the value of attribute project_dir.
Instance Method Summary collapse
-
#add_entry(entry_hash) ⇒ Object
Add a new future work entry.
-
#by_file ⇒ Object
Get entries grouped by file.
-
#by_priority ⇒ Object
Get entries grouped by priority.
-
#by_type ⇒ Object
Get entries grouped by type.
-
#clear_context ⇒ Object
Clear context.
-
#clear_resolved ⇒ Object
Remove resolved entries.
-
#display_summary(output = $stdout) ⇒ Object
Display summary of backlog.
-
#entry_to_prompt(entry_id) ⇒ Object
Convert entry to work loop PROMPT.md content.
-
#filter(criteria = {}) ⇒ Object
Get entries filtered by criteria.
-
#initialize(project_dir, options = {}) ⇒ FutureWorkBacklog
constructor
A new instance of FutureWorkBacklog.
-
#resolve_entry(entry_id, resolution_note = nil) ⇒ Object
Mark entry as resolved.
-
#save ⇒ Object
Save backlog to disk (both YAML and Markdown).
-
#set_context(context_hash) ⇒ Object
Set context for subsequent entries (e.g., current work loop, step).
-
#summary ⇒ Object
Get summary statistics.
Constructor Details
#initialize(project_dir, options = {}) ⇒ FutureWorkBacklog
Returns a new instance of FutureWorkBacklog.
33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/aidp/execute/future_work_backlog.rb', line 33 def initialize(project_dir, = {}) @project_dir = project_dir @backlog_dir = File.join(project_dir, ".aidp") @backlog_file = [:backlog_file] || File.join(@backlog_dir, "future_work.yml") @markdown_file = File.join(@backlog_dir, "future_work.md") @entries = [] @current_context = {} @options = ensure_backlog_directory load_existing_backlog end |
Instance Attribute Details
#current_context ⇒ Object (readonly)
Returns the value of attribute current_context.
12 13 14 |
# File 'lib/aidp/execute/future_work_backlog.rb', line 12 def current_context @current_context end |
#entries ⇒ Object (readonly)
Returns the value of attribute entries.
12 13 14 |
# File 'lib/aidp/execute/future_work_backlog.rb', line 12 def entries @entries end |
#project_dir ⇒ Object (readonly)
Returns the value of attribute project_dir.
12 13 14 |
# File 'lib/aidp/execute/future_work_backlog.rb', line 12 def project_dir @project_dir end |
Instance Method Details
#add_entry(entry_hash) ⇒ Object
Add a new future work entry
55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/aidp/execute/future_work_backlog.rb', line 55 def add_entry(entry_hash) entry = normalize_entry(entry_hash) # Avoid duplicates return if duplicate?(entry) entry[:id] = generate_entry_id entry[:created_at] = Time.now.utc.iso8601 entry[:context] = @current_context.dup @entries << entry entry end |
#by_file ⇒ Object
Get entries grouped by file
103 104 105 |
# File 'lib/aidp/execute/future_work_backlog.rb', line 103 def by_file @entries.group_by { |e| e[:file] } end |
#by_priority ⇒ Object
Get entries grouped by priority
108 109 110 |
# File 'lib/aidp/execute/future_work_backlog.rb', line 108 def by_priority @entries.group_by { |e| e[:priority] }.sort_by { |priority, _| -PRIORITIES[priority] }.to_h end |
#by_type ⇒ Object
Get entries grouped by type
98 99 100 |
# File 'lib/aidp/execute/future_work_backlog.rb', line 98 def by_type @entries.group_by { |e| e[:type] } end |
#clear_context ⇒ Object
Clear context
75 76 77 |
# File 'lib/aidp/execute/future_work_backlog.rb', line 75 def clear_context @current_context.clear end |
#clear_resolved ⇒ Object
Remove resolved entries
133 134 135 |
# File 'lib/aidp/execute/future_work_backlog.rb', line 133 def clear_resolved @entries.reject! { |e| e[:resolved] } end |
#display_summary(output = $stdout) ⇒ Object
Display summary of backlog
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/aidp/execute/future_work_backlog.rb', line 179 def display_summary(output = $stdout) return if @entries.empty? output.puts "\n" + "=" * 80 output.puts "📝 Future Work Backlog Summary" output.puts "=" * 80 sum = summary output.puts "\nTotal Items: #{sum[:total]}" output.puts "Files Affected: #{sum[:files_affected]}" if sum[:by_type].any? output.puts "\nBy Type:" sum[:by_type].each do |type, count| output.puts " #{entry_type_display(type)}: #{count}" end end if sum[:by_priority].any? output.puts "\nBy Priority:" sum[:by_priority].each do |priority, count| output.puts " #{priority.to_s.upcase}: #{count}" end end output.puts "\n" + "-" * 80 output.puts "Review backlog: .aidp/future_work.md" output.puts "Convert to work loop: aidp backlog convert <entry-id>" output.puts "=" * 80 + "\n" end |
#entry_to_prompt(entry_id) ⇒ Object
Convert entry to work loop PROMPT.md content
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/aidp/execute/future_work_backlog.rb', line 138 def entry_to_prompt(entry_id) entry = @entries.find { |e| e[:id] == entry_id } return unless entry <<~PROMPT # Work Loop: #{entry_type_display(entry[:type])} ## Task Description **File**: #{entry[:file]} **Lines**: #{entry[:lines]} **Priority**: #{entry[:priority].to_s.upcase} ## Issue #{entry[:reason]} ## Recommended Fix #{entry[:recommendation]} ## Acceptance Criteria - [ ] #{entry[:reason]} is resolved - [ ] Code follows LLM_STYLE_GUIDE - [ ] Tests pass - [ ] No new style violations introduced ## Original Context - Work Loop: #{entry[:context][:work_loop] || "N/A"} - Step: #{entry[:context][:step] || "N/A"} - Created: #{entry[:created_at]} ## Completion Mark this complete by adding: STATUS: COMPLETE PROMPT end |
#filter(criteria = {}) ⇒ Object
Get entries filtered by criteria
86 87 88 89 90 91 92 93 94 95 |
# File 'lib/aidp/execute/future_work_backlog.rb', line 86 def filter(criteria = {}) filtered = @entries filtered = filtered.select { |e| e[:type] == criteria[:type] } if criteria[:type] filtered = filtered.select { |e| e[:file] == criteria[:file] } if criteria[:file] filtered = filtered.select { |e| e[:priority] == criteria[:priority] } if criteria[:priority] filtered = filtered.select { |e| e[:context][:work_loop] == criteria[:work_loop] } if criteria[:work_loop] filtered end |
#resolve_entry(entry_id, resolution_note = nil) ⇒ Object
Mark entry as resolved
123 124 125 126 127 128 129 130 |
# File 'lib/aidp/execute/future_work_backlog.rb', line 123 def resolve_entry(entry_id, resolution_note = nil) entry = @entries.find { |e| e[:id] == entry_id } return unless entry entry[:resolved] = true entry[:resolved_at] = Time.now.utc.iso8601 entry[:resolution_note] = resolution_note if resolution_note end |
#save ⇒ Object
Save backlog to disk (both YAML and Markdown)
80 81 82 83 |
# File 'lib/aidp/execute/future_work_backlog.rb', line 80 def save save_yaml save_markdown end |
#set_context(context_hash) ⇒ Object
Set context for subsequent entries (e.g., current work loop, step)
70 71 72 |
# File 'lib/aidp/execute/future_work_backlog.rb', line 70 def set_context(context_hash) @current_context.merge!(context_hash) end |
#summary ⇒ Object
Get summary statistics
113 114 115 116 117 118 119 120 |
# File 'lib/aidp/execute/future_work_backlog.rb', line 113 def summary { total: @entries.size, by_type: by_type.transform_values(&:size), by_priority: by_priority.transform_values(&:size), files_affected: @entries.map { |e| e[:file] }.uniq.size } end |