Class: Aidp::StyleGuide::Selector
- Inherits:
-
Object
- Object
- Aidp::StyleGuide::Selector
- Defined in:
- lib/aidp/style_guide/selector.rb
Overview
Deterministic selector for STYLE_GUIDE sections based on task context
This class provides intelligent section selection from STYLE_GUIDE.md based on keywords in the task context. For providers with their own instruction files (Claude, GitHub Copilot), it skips style guide injection.
Constant Summary collapse
- PROVIDERS_WITH_INSTRUCTION_FILES =
Providers that have their own instruction files and don’t need the style guide injected into prompts
%w[ claude anthropic github_copilot ].freeze
- SECTION_MAPPING =
Mapping of keywords/topics to STYLE_GUIDE.md line ranges Each entry is [start_line, end_line, description]
{ # Core Engineering "code_organization" => [[25, 117, "Code Organization"]], "class" => [[25, 117, "Code Organization"], [217, 236, "Sandi Metz Rules"]], "method" => [[224, 229, "Method Design"], [217, 236, "Sandi Metz Rules"]], "composition" => [[29, 35, "Composition over Inheritance"]], "inheritance" => [[29, 35, "Composition over Inheritance"]], "small_objects" => [[25, 117, "Code Organization"]], "single_responsibility" => [[25, 117, "Code Organization"]], # Sandi Metz "sandi_metz" => [[217, 236, "Sandi Metz Rules"]], "parameter" => [[231, 236, "Parameter Limits"]], # Ruby Conventions "ruby" => [[259, 278, "Ruby Conventions"], [446, 498, "Ruby Version Management"]], "naming" => [[51, 56, "Naming Conventions"]], "convention" => [[259, 278, "Ruby Conventions"]], "style" => [[259, 278, "Ruby Conventions"]], "require" => [[263, 266, "Require Practices"]], "mise" => [[446, 498, "Ruby Version Management"]], "version" => [[446, 498, "Ruby Version Management"]], # Feature Organization "feature" => [[58, 116, "Feature Organization by Purpose"]], "workflow" => [[58, 116, "Feature Organization by Purpose"]], "template" => [[118, 210, "Template/Skill Separation"]], "skill" => [[118, 210, "Template/Skill Separation"]], # Logging "logging" => [[287, 430, "Logging Practices"]], "log" => [[287, 430, "Logging Practices"]], "debug" => [[287, 430, "Logging Practices"]], # ZFC - Zero Framework Cognition "zfc" => [[500, 797, "Zero Framework Cognition (ZFC)"]], "zero_framework" => [[500, 797, "Zero Framework Cognition (ZFC)"]], "ai_decision" => [[500, 797, "Zero Framework Cognition (ZFC)"]], "decision_engine" => [[500, 797, "Zero Framework Cognition (ZFC)"]], # AGD - AI-Generated Determinism "agd" => [[798, 855, "AI-Generated Determinism (AGD)"]], "determinism" => [[798, 855, "AI-Generated Determinism (AGD)"]], "config_time" => [[798, 855, "AI-Generated Determinism (AGD)"]], # TTY / TUI "tty" => [[856, 1105, "TTY Toolkit Guidelines"]], "tui" => [[856, 1105, "TTY Toolkit Guidelines"]], "ui" => [[856, 1105, "TTY Toolkit Guidelines"]], "prompt" => [[856, 1105, "TTY Toolkit Guidelines"], [936, 972, "TTY Output Practices"]], "progress" => [[856, 1105, "TTY Toolkit Guidelines"]], "spinner" => [[856, 1105, "TTY Toolkit Guidelines"]], "table" => [[856, 1105, "TTY Toolkit Guidelines"]], "select" => [[856, 1105, "TTY Toolkit Guidelines"]], # Testing "testing" => [[1873, 2112, "Testing Guidelines"]], "test" => [[1873, 2112, "Testing Guidelines"], [1550, 1800, "Test Coverage Philosophy"]], "spec" => [[1873, 2112, "Testing Guidelines"]], "rspec" => [[1873, 2112, "Testing Guidelines"]], "mock" => [[1873, 2112, "Testing Guidelines"], [1930, 2012, "Dependency Injection"]], "stub" => [[1873, 2112, "Testing Guidelines"]], "coverage" => [[1550, 1800, "Test Coverage Philosophy"]], "pending" => [[1816, 1870, "Pending Specs Policy"]], "expect_script" => [[1173, 1234, "expect Scripts for TUI"]], "tmux" => [[1203, 1295, "tmux Testing"]], "time_test" => [[1656, 1690, "Time-based Testing"]], "fork" => [[1718, 1778, "Forked Process Testing"]], "encoding" => [[1780, 1813, "String Encoding"]], "dependency_injection" => [[1930, 2012, "Dependency Injection"]], # Error Handling "error" => [[2113, 2168, "Error Handling"], [280, 286, "Error Handling Basics"]], "exception" => [[2113, 2168, "Error Handling"], [2130, 2140, "Error Class Pattern"]], "rescue" => [[280, 286, "Error Handling Basics"], [2113, 2168, "Error Handling"]], # Concurrency "concurrency" => [[2170, 2185, "Concurrency & Threads"]], "thread" => [[2170, 2185, "Concurrency & Threads"]], "async" => [[2170, 2185, "Concurrency & Threads"]], # Performance "performance" => [[2206, 2232, "Performance"]], "optimization" => [[2206, 2232, "Performance"]], "cache" => [[2206, 2232, "Performance"]], # Security "security" => [[2233, 2272, "Security & Safety"]], "safety" => [[2233, 2272, "Security & Safety"]], "validation" => [[2233, 2272, "Security & Safety"]], # Backward Compatibility / Pre-release "backward_compatibility" => [[2273, 2472, "Backward Compatibility"]], "deprecation" => [[2273, 2472, "Backward Compatibility"]], "legacy" => [[2273, 2472, "Backward Compatibility"]], # Commit Hygiene "commit" => [[2476, 2482, "Commit Hygiene"]], "git" => [[2476, 2482, "Commit Hygiene"]], # Prompt Optimization "prompt_optimization" => [[2523, 2854, "Prompt Optimization"]], "fragment" => [[2523, 2854, "Prompt Optimization"]], # Task Filing "task" => [[2856, 2890, "Task Filing"]], "tasklist" => [[2856, 2890, "Task Filing"]] }.freeze
- CORE_SECTIONS =
Default sections to always include (core rules)
[ [25, 117, "Code Organization"], [217, 236, "Sandi Metz Rules"], [287, 430, "Logging Practices"] ].freeze
Instance Attribute Summary collapse
-
#project_dir ⇒ Object
readonly
Returns the value of attribute project_dir.
Instance Method Summary collapse
-
#available_keywords ⇒ Array<String>
Get all available section names.
-
#extract_keywords(context) ⇒ Array<String>
Extract keywords from task context.
-
#initialize(project_dir:) ⇒ Selector
constructor
A new instance of Selector.
-
#preview_selection(keywords) ⇒ Array<Hash>
Get information about what sections would be selected for given keywords.
-
#provider_needs_style_guide?(provider_name) ⇒ Boolean
Check if a provider needs style guide injection.
-
#select_sections(keywords: [], include_core: true, max_lines: nil) ⇒ String
Select relevant sections from STYLE_GUIDE.md based on keywords.
-
#style_guide_exists? ⇒ Boolean
Check if style guide file exists.
Constructor Details
#initialize(project_dir:) ⇒ Selector
Returns a new instance of Selector.
147 148 149 150 151 |
# File 'lib/aidp/style_guide/selector.rb', line 147 def initialize(project_dir:) @project_dir = project_dir @style_guide_content = nil @style_guide_lines = nil end |
Instance Attribute Details
#project_dir ⇒ Object (readonly)
Returns the value of attribute project_dir.
145 146 147 |
# File 'lib/aidp/style_guide/selector.rb', line 145 def project_dir @project_dir end |
Instance Method Details
#available_keywords ⇒ Array<String>
Get all available section names
216 217 218 |
# File 'lib/aidp/style_guide/selector.rb', line 216 def available_keywords SECTION_MAPPING.keys.sort end |
#extract_keywords(context) ⇒ Array<String>
Extract keywords from task context
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/aidp/style_guide/selector.rb', line 195 def extract_keywords(context) text = context.is_a?(Hash) ? context.values.join(" ") : context.to_s text_lower = text.downcase keywords = [] SECTION_MAPPING.keys.each do |keyword| # Convert keyword format (snake_case to spaces/variations) patterns = build_patterns(keyword) keywords << keyword if patterns.any? { |p| text_lower.include?(p) } end Aidp.log_debug("style_guide_selector", "keywords_extracted", input_length: text.length, keywords_found: keywords.size) keywords.uniq end |
#preview_selection(keywords) ⇒ Array<Hash>
Get information about what sections would be selected for given keywords
231 232 233 234 235 236 237 238 239 240 241 242 243 |
# File 'lib/aidp/style_guide/selector.rb', line 231 def preview_selection(keywords) sections = gather_sections(keywords, false) merged = merge_and_sort_ranges(sections) merged.map do |start_line, end_line, description| { start_line: start_line, end_line: end_line, description: description, estimated_lines: end_line - start_line + 1 } end end |
#provider_needs_style_guide?(provider_name) ⇒ Boolean
Check if a provider needs style guide injection
157 158 159 160 161 162 |
# File 'lib/aidp/style_guide/selector.rb', line 157 def provider_needs_style_guide?(provider_name) return true if provider_name.nil? normalized = provider_name.to_s.downcase.strip !PROVIDERS_WITH_INSTRUCTION_FILES.include?(normalized) end |
#select_sections(keywords: [], include_core: true, max_lines: nil) ⇒ String
Select relevant sections from STYLE_GUIDE.md based on keywords
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/aidp/style_guide/selector.rb', line 170 def select_sections(keywords: [], include_core: true, max_lines: nil) Aidp.log_debug("style_guide_selector", "selecting_sections", keywords: keywords, include_core: include_core, max_lines: max_lines) return "" unless style_guide_exists? # Gather all matching sections sections = gather_sections(keywords, include_core) # Merge overlapping ranges and sort merged_ranges = merge_and_sort_ranges(sections) # Extract content from ranges content = extract_content(merged_ranges, max_lines) Aidp.log_debug("style_guide_selector", "sections_selected", section_count: merged_ranges.size, content_lines: content.lines.count) content end |
#style_guide_exists? ⇒ Boolean
Check if style guide file exists
223 224 225 |
# File 'lib/aidp/style_guide/selector.rb', line 223 def style_guide_exists? File.exist?(style_guide_path) end |