Class: RailsAiBridge::Serializers::Providers::BaseProviderSerializer
- Inherits:
-
Object
- Object
- RailsAiBridge::Serializers::Providers::BaseProviderSerializer
- Defined in:
- lib/rails_ai_bridge/serializers/providers/base_provider_serializer.rb
Overview
Base class for AI assistant provider serializers (Claude, Copilot, Gemini, Codex, Cursor). Shared compact-mode sections: header, stack, models, gems, architecture, MCP guide, commands, footer.
Direct Known Subclasses
ClaudeSerializer, CodexSerializer, CopilotSerializer, DevinSerializer, GeminiSerializer, RulesSerializer
Defined Under Namespace
Classes: ModelEntries, NotableGemPayload
Constant Summary collapse
- MAX_KEY_MODELS =
Maximum number of key models to display in compact mode Models beyond this count are truncated with an overflow hint
15- MAX_PATTERNS =
Maximum number of architectural patterns to display Limits the patterns section to prevent excessive output
8- MAX_CONFIG_FILES =
Maximum number of configuration files to list Shows only the most important config files
5
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#context ⇒ Object
readonly
Returns the value of attribute context.
Instance Method Summary collapse
-
#initialize(context, config: RailsAiBridge.configuration) ⇒ BaseProviderSerializer
constructor
A new instance of BaseProviderSerializer.
-
#intro_sections ⇒ Array<String>
Document intro: header followed by the anti-hallucination rules, which must sit near the top so bottom-trimming never drops them.
-
#render_architecture ⇒ Array<String>
Renders the architecture section with detected styles and common patterns.
-
#render_commands ⇒ Array<String>
Renders the command reference section with common dev, test, lint and migration commands.
-
#render_compact ⇒ String
Renders the default compact AI context document (newline-joined sections).
-
#render_footer ⇒ Array<String>
Renders the closing engineering rules and regeneration attribution footer.
-
#render_header ⇒ Array<String>
Renders the header section of the context file.
-
#render_key_config_files ⇒ Array<String>
Renders the key configuration files section.
-
#render_key_considerations ⇒ Array<String>
Renders the static key considerations section covering performance, security, data drift, and MCP exposure.
-
#render_key_models ⇒ Array<String>
Renders the key models section, sorted by task relevance (semantic tier, complexity, route density, recent migrations, and optional DB size hints).
-
#render_notable_gems ⇒ Array<String>
Renders the notable gems section grouped by category.
-
#render_semantic_insights ⇒ Array<String>
Renders semantic insights from rubydex analysis when available.
-
#render_stack_overview ⇒ Array<String>
Renders the stack overview section.
Constructor Details
#initialize(context, config: RailsAiBridge.configuration) ⇒ BaseProviderSerializer
Returns a new instance of BaseProviderSerializer.
25 26 27 28 |
# File 'lib/rails_ai_bridge/serializers/providers/base_provider_serializer.rb', line 25 def initialize(context, config: RailsAiBridge.configuration) @context = context @config = config end |
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
21 22 23 |
# File 'lib/rails_ai_bridge/serializers/providers/base_provider_serializer.rb', line 21 def config @config end |
#context ⇒ Object (readonly)
Returns the value of attribute context.
21 22 23 |
# File 'lib/rails_ai_bridge/serializers/providers/base_provider_serializer.rb', line 21 def context @context end |
Instance Method Details
#intro_sections ⇒ Array<String>
Document intro: header followed by the anti-hallucination rules, which must sit near the top so bottom-trimming never drops them.
56 57 58 59 60 61 62 |
# File 'lib/rails_ai_bridge/serializers/providers/base_provider_serializer.rb', line 56 def intro_sections [ *render_header, '', *SharedAssistantGuidance.anti_hallucination_rules_lines ] end |
#render_architecture ⇒ Array<String>
Renders the architecture section with detected styles and common patterns.
Caps patterns at MAX_PATTERNS entries. Returns [] when conventions are absent,
have an :error key, or both :architecture and :patterns are empty.
139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/rails_ai_bridge/serializers/providers/base_provider_serializer.rb', line 139 def render_architecture conv = context[:conventions] return [] unless conv.is_a?(Hash) && !conv[:error] arch = conv[:architecture] || [] patterns = conv[:patterns] || [] return [] if arch.empty? && patterns.empty? lines = ['## Architecture', 'Detected architectural styles and common patterns:'] arch.each { |p| lines << "- #{p}" } patterns.first(MAX_PATTERNS).each { |p| lines << "- #{p}" } lines << '' lines end |
#render_commands ⇒ Array<String>
Renders the command reference section with common dev, test, lint and migration commands. The test command is resolved via ContextSummary.test_command.
226 227 228 229 230 231 232 233 234 235 |
# File 'lib/rails_ai_bridge/serializers/providers/base_provider_serializer.rb', line 226 def render_commands [ '## Commands', '- `bin/dev` — start dev server', "- `#{ContextSummary.test_command(context)}` — run tests", '- `bundle exec rubocop` — run linter', '- `rails db:migrate` — run pending migrations', '' ] end |
#render_compact ⇒ String
Renders the default compact AI context document (newline-joined sections).
Enforces Configuration#claude_max_lines by trimming with an MCP pointer when exceeded.
Subclasses may override entirely or compose with individual #render_* helpers.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/rails_ai_bridge/serializers/providers/base_provider_serializer.rb', line 35 def render_compact lines = [] lines.concat(intro_sections) lines.concat(render_stack_overview) lines.concat(render_key_models) lines.concat(render_notable_gems) lines.concat(render_architecture) lines.concat(render_semantic_insights) lines.concat(render_key_considerations) lines.concat(Formatters::Providers::McpGuideFormatter.new(context).call.split("\n")) lines.concat(render_key_config_files) lines.concat(render_commands) lines.concat() line_enforcer.enforce(lines).join("\n") end |
#render_footer ⇒ Array<String>
Renders the closing engineering rules and regeneration attribution footer. Delegates to SharedAssistantGuidance.compact_engineering_rules_footer_lines.
241 242 243 |
# File 'lib/rails_ai_bridge/serializers/providers/base_provider_serializer.rb', line 241 def SharedAssistantGuidance.(context, include_anti_hallucination: false) end |
#render_header ⇒ Array<String>
Renders the header section of the context file.
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/rails_ai_bridge/serializers/providers/base_provider_serializer.rb', line 66 def render_header [ "# #{context[:app_name]} — AI Context", '', "> Auto-generated by rails-ai-bridge v#{RailsAiBridge::VERSION}", "> Generated: #{context[:generated_at]}", "> Rails #{context[:rails_version]} | Ruby #{context[:ruby_version]}", '', "This file provides a high-level overview of this Rails application's", 'structure, patterns, and conventions. As an AI assistant, use this context', 'to quickly understand the project and generate idiomatic code that', 'adheres to its design decisions. For deeper dives, use the live', 'MCP tools referenced throughout this document.' ] end |
#render_key_config_files ⇒ Array<String>
Renders the key configuration files section.
Caps display at MAX_CONFIG_FILES files. Returns [] when conventions are absent,
have an :error key, or :config_files is empty.
209 210 211 212 213 214 215 216 217 218 219 220 |
# File 'lib/rails_ai_bridge/serializers/providers/base_provider_serializer.rb', line 209 def render_key_config_files conv = context[:conventions] return [] unless conv.is_a?(Hash) && !conv[:error] config_files = ContextSummary.safe_config_files(conv[:config_files], limit: MAX_CONFIG_FILES) return [] if config_files.empty? lines = ['## Key Config Files', 'Core configuration files for this application:'] config_files.each { |f| lines << "- `#{f}`" } lines << '' lines end |
#render_key_considerations ⇒ Array<String>
Renders the static key considerations section covering performance, security, data drift, and MCP exposure. Content is fixed and does not depend on context.
191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/rails_ai_bridge/serializers/providers/base_provider_serializer.rb', line 191 def render_key_considerations [ '## Key Considerations', '- **Performance:** For large or frequently accessed tables, always consider database performance. ' \ 'Use the `rails_get_schema` tool to verify indexes and be mindful of N+1 queries by using `includes` and other ActiveRecord optimizations.', '- **Security:** Treat all user-provided input as untrusted. Always use strong parameters in controllers ' \ 'and be aware of potential security vulnerabilities when using gems like `ransack` or `pg_search`.', '- **Data Drift:** This document is a snapshot. For the most up-to-date information, especially regarding schema and routes, use the live MCP tools.', '- **MCP Exposure:** The MCP tools are read-only but expose sensitive application structure. Avoid exposing the HTTP transport on untrusted networks.', '' ] end |
#render_key_models ⇒ Array<String>
Renders the key models section, sorted by task relevance (semantic tier,
complexity, route density, recent migrations, and optional DB size hints).
Caps display at MAX_KEY_MODELS models and appends an overflow hint when more exist.
Returns [] when context[:models] is nil, non-Hash, or has an :error key.
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/rails_ai_bridge/serializers/providers/base_provider_serializer.rb', line 98 def render_key_models models = context[:models] return [] unless models.is_a?(Hash) && !models[:error] && models.any? max_show = MAX_KEY_MODELS lines = ['## Key Models', 'The following are the most architecturally significant models, ordered by relevance:'] model_entries = ModelEntries.new(models, context: context).sorted_by_relevance model_entries.first(max_show).each do |name, data| lines << model_line_formatter.format_line(name, data) end lines << "- _...#{model_entries.size - max_show} more (use `rails_get_model_details` tool)_" if model_entries.size > max_show lines << '' lines end |
#render_notable_gems ⇒ Array<String>
Renders the notable gems section grouped by category.
Looks for notable gems under :notable_gems, :notable, or :detected keys.
Returns [] when gems are absent, have an :error key, or the list is empty.
120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/rails_ai_bridge/serializers/providers/base_provider_serializer.rb', line 120 def render_notable_gems notable = extract_notable_gems(context[:gems]) return [] if notable.empty? lines = ['## Gems', 'Key gems, categorized by their primary function:'] grouped = notable.group_by { |g| g[:category]&.to_s || 'other' } grouped.each do |category, gem_list| names = gem_list.map { |g| g[:name] }.join(', ') lines << "- **#{category}**: #{names}" end lines << '' lines end |
#render_semantic_insights ⇒ Array<String>
Renders semantic insights from rubydex analysis when available.
Includes pattern detection results and complexity hotspot warnings.
Returns [] when semantic data is absent or has an :error or :info key.
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/rails_ai_bridge/serializers/providers/base_provider_serializer.rb', line 159 def render_semantic_insights semantic = context[:semantic] return [] unless semantic.is_a?(Hash) && !semantic[:error] && !semantic[:info] lines = ['## Semantic Analysis (rubydex)'] # Codebase stats stats = semantic[:codebase_stats] if stats.is_a?(Hash) && stats.any? lines << "- **Files:** #{stats[:total_files]}, **Classes:** #{stats[:total_classes]}, " \ "**Modules:** #{stats[:total_modules]}, **Methods:** #{stats[:total_methods]}" end # Detected patterns patterns = semantic.dig(:patterns, :common_patterns) lines << "- **Patterns:** #{patterns.join(', ')}" if patterns.is_a?(Array) && patterns.any? # Complexity hotspots hotspots = semantic[:complexity_hotspots] if hotspots.is_a?(Array) && hotspots.any? hotspot_list = hotspots.first(5).map { |h| "#{h[:name]} (score: #{h[:complexity_score]})" }.join(', ') lines << "- **Complexity hotspots:** #{hotspot_list}" end lines << '' lines end |
#render_stack_overview ⇒ Array<String>
Renders the stack overview section.
Includes database adapter/table count, model count, routes, auth gems,
async jobs/mailers/channels, and pending migrations when available.
Silently skips any sub-section whose context key is missing or has an :error key.
88 89 90 |
# File 'lib/rails_ai_bridge/serializers/providers/base_provider_serializer.rb', line 88 def render_stack_overview stack_overview_builder.build end |