rails-ai-context 4.3.2 → 4.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +72 -53
  3. data/CLAUDE.md +1 -1
  4. data/README.md +268 -197
  5. data/demo-trace.gif +0 -0
  6. data/demo-trace.tape +21 -0
  7. data/demo.gif +0 -0
  8. data/demo.tape +33 -0
  9. data/docs/GUIDE.md +9 -9
  10. data/lib/generators/rails_ai_context/install/install_generator.rb +2 -1
  11. data/lib/rails_ai_context/configuration.rb +1 -1
  12. data/lib/rails_ai_context/doctor.rb +4 -2
  13. data/lib/rails_ai_context/fingerprinter.rb +2 -1
  14. data/lib/rails_ai_context/introspectors/accessibility_introspector.rb +2 -1
  15. data/lib/rails_ai_context/introspectors/action_mailbox_introspector.rb +2 -1
  16. data/lib/rails_ai_context/introspectors/action_text_introspector.rb +2 -1
  17. data/lib/rails_ai_context/introspectors/active_storage_introspector.rb +6 -3
  18. data/lib/rails_ai_context/introspectors/api_introspector.rb +8 -4
  19. data/lib/rails_ai_context/introspectors/asset_pipeline_introspector.rb +6 -3
  20. data/lib/rails_ai_context/introspectors/auth_introspector.rb +14 -7
  21. data/lib/rails_ai_context/introspectors/config_introspector.rb +12 -6
  22. data/lib/rails_ai_context/introspectors/controller_introspector.rb +20 -10
  23. data/lib/rails_ai_context/introspectors/convention_detector.rb +2 -1
  24. data/lib/rails_ai_context/introspectors/design_token_introspector.rb +8 -4
  25. data/lib/rails_ai_context/introspectors/devops_introspector.rb +6 -3
  26. data/lib/rails_ai_context/introspectors/engine_introspector.rb +4 -2
  27. data/lib/rails_ai_context/introspectors/frontend_framework_introspector.rb +2 -1
  28. data/lib/rails_ai_context/introspectors/i18n_introspector.rb +2 -1
  29. data/lib/rails_ai_context/introspectors/job_introspector.rb +8 -4
  30. data/lib/rails_ai_context/introspectors/middleware_introspector.rb +4 -2
  31. data/lib/rails_ai_context/introspectors/migration_introspector.rb +2 -1
  32. data/lib/rails_ai_context/introspectors/model_introspector.rb +20 -10
  33. data/lib/rails_ai_context/introspectors/multi_database_introspector.rb +12 -6
  34. data/lib/rails_ai_context/introspectors/performance_introspector.rb +6 -3
  35. data/lib/rails_ai_context/introspectors/route_introspector.rb +4 -2
  36. data/lib/rails_ai_context/introspectors/schema_introspector.rb +14 -7
  37. data/lib/rails_ai_context/introspectors/seeds_introspector.rb +2 -1
  38. data/lib/rails_ai_context/introspectors/stimulus_introspector.rb +8 -4
  39. data/lib/rails_ai_context/introspectors/test_introspector.rb +8 -4
  40. data/lib/rails_ai_context/introspectors/turbo_introspector.rb +22 -11
  41. data/lib/rails_ai_context/introspectors/view_introspector.rb +8 -4
  42. data/lib/rails_ai_context/introspectors/view_template_introspector.rb +10 -5
  43. data/lib/rails_ai_context/tasks/rails_ai_context.rake +8 -4
  44. data/lib/rails_ai_context/tools/analyze_feature.rb +66 -19
  45. data/lib/rails_ai_context/tools/diagnose.rb +4 -2
  46. data/lib/rails_ai_context/tools/get_callbacks.rb +4 -2
  47. data/lib/rails_ai_context/tools/get_concern.rb +12 -6
  48. data/lib/rails_ai_context/tools/get_controllers.rb +10 -5
  49. data/lib/rails_ai_context/tools/get_conventions.rb +4 -2
  50. data/lib/rails_ai_context/tools/get_design_system.rb +2 -1
  51. data/lib/rails_ai_context/tools/get_env.rb +8 -4
  52. data/lib/rails_ai_context/tools/get_helper_methods.rb +6 -3
  53. data/lib/rails_ai_context/tools/get_job_pattern.rb +2 -1
  54. data/lib/rails_ai_context/tools/get_model_details.rb +10 -5
  55. data/lib/rails_ai_context/tools/get_partial_interface.rb +14 -7
  56. data/lib/rails_ai_context/tools/get_schema.rb +2 -1
  57. data/lib/rails_ai_context/tools/get_service_pattern.rb +2 -1
  58. data/lib/rails_ai_context/tools/get_stimulus.rb +2 -1
  59. data/lib/rails_ai_context/tools/get_test_info.rb +4 -2
  60. data/lib/rails_ai_context/tools/get_turbo_map.rb +22 -11
  61. data/lib/rails_ai_context/tools/get_view.rb +6 -3
  62. data/lib/rails_ai_context/tools/migration_advisor.rb +2 -1
  63. data/lib/rails_ai_context/tools/onboard.rb +2 -1
  64. data/lib/rails_ai_context/tools/performance_check.rb +2 -1
  65. data/lib/rails_ai_context/tools/runtime_info.rb +10 -5
  66. data/lib/rails_ai_context/tools/search_code.rb +8 -4
  67. data/lib/rails_ai_context/tools/search_docs.rb +2 -1
  68. data/lib/rails_ai_context/tools/session_context.rb +2 -1
  69. data/lib/rails_ai_context/tools/validate.rb +16 -8
  70. data/lib/rails_ai_context/version.rb +1 -1
  71. metadata +5 -1
data/demo.tape ADDED
@@ -0,0 +1,33 @@
1
+ # VHS demo tape for rails-ai-context install
2
+ Output demo.gif
3
+
4
+ Set Shell zsh
5
+ Set FontSize 14
6
+ Set Width 950
7
+ Set Height 520
8
+ Set Padding 12
9
+ Set Theme "Catppuccin Mocha"
10
+ Set TypingSpeed 35ms
11
+
12
+ Type "cd /Users/crisjosephnahine/Documents/Projects/daily-content-chef"
13
+ Enter
14
+ Sleep 1s
15
+
16
+ Type "rails generate rails_ai_context:install"
17
+ Sleep 400ms
18
+ Enter
19
+ Sleep 3s
20
+
21
+ # Select Claude Code + Cursor
22
+ Type "1,2"
23
+ Sleep 300ms
24
+ Enter
25
+ Sleep 2s
26
+
27
+ # Select MCP mode (yes)
28
+ Type "1"
29
+ Sleep 300ms
30
+ Enter
31
+ Sleep 4s
32
+
33
+ Sleep 2s
data/docs/GUIDE.md CHANGED
@@ -1128,7 +1128,7 @@ Both transports are **read-only** — they expose the same 39 tools and never mo
1128
1128
  RailsAiContext.configure do |config|
1129
1129
  # --- Introspectors ---
1130
1130
 
1131
- # Presets: :full (32 introspectors, default) or :standard (14 core)
1131
+ # Presets: :full (33 introspectors, default) or :standard (19)
1132
1132
  config.preset = :full
1133
1133
 
1134
1134
  # Cherry-pick on top of a preset
@@ -1300,7 +1300,7 @@ All split rules include an app overview file, so no context is lost when root fi
1300
1300
 
1301
1301
  ## Introspectors — Full List
1302
1302
 
1303
- ### Standard preset (14 introspectors)
1303
+ ### Standard preset (19 introspectors)
1304
1304
 
1305
1305
  Core Rails structure only. Use `config.preset = :standard` for a lighter footprint.
1306
1306
 
@@ -1320,19 +1320,21 @@ Core Rails structure only. Use `config.preset = :standard` for a lighter footpri
1320
1320
  | `view_templates` | View file contents, partial references, Stimulus data attributes, UI pattern extraction, model field usage in partials. |
1321
1321
  | `design_tokens` | Auto-detects CSS framework (Tailwind v3/v4, Bootstrap, Sass, plain CSS) and extracts design tokens from config files and built CSS. |
1322
1322
  | `components` | ViewComponent/Phlex components: props, slots, previews, sidecar assets, usage examples. |
1323
+ | `turbo` | Turbo Frames (IDs and files), Turbo Stream templates, model broadcasts (`broadcasts_to`, `broadcasts`). |
1324
+ | `auth` | Devise models with modules, Rails 8 built-in auth, has_secure_password, Pundit policies, CanCanCan, CORS config, CSP config. |
1325
+ | `accessibility` | ARIA attributes, semantic HTML elements, screen reader text, alt text coverage, landmark roles, accessibility score. |
1326
+ | `performance` | N+1 query risks, missing counter_cache, missing FK indexes, Model.all anti-patterns, eager load candidates. |
1327
+ | `i18n` | Default locale, available locales, locale files with key counts, backend class, parse errors. |
1323
1328
 
1324
- ### Full preset (32 introspectors) — default
1329
+ ### Full preset (33 introspectors) — default
1325
1330
 
1326
1331
  Includes all standard introspectors plus:
1327
1332
 
1328
1333
  | Introspector | What it discovers |
1329
1334
  |-------------|-------------------|
1330
1335
  | `views` | Layouts, templates grouped by controller, partials (per-controller and shared), helpers with methods, template engines (erb, haml, slim), view components. |
1331
- | `turbo` | Turbo Frames (IDs and files), Turbo Stream templates, model broadcasts (`broadcasts_to`, `broadcasts`). |
1332
- | `i18n` | Default locale, available locales, locale files with key counts, backend class, parse errors. |
1333
1336
  | `active_storage` | Attachments (has_one_attached, has_many_attached per model), storage services, direct upload config. |
1334
1337
  | `action_text` | Rich text fields (has_rich_text per model), Action Text installation status. |
1335
- | `auth` | Devise models with modules, Rails 8 built-in auth, has_secure_password, Pundit policies, CanCanCan, CORS config, CSP config. |
1336
1338
  | `api` | API-only mode, API versioning (from directory structure), serializers (Jbuilder, AMS, etc.), GraphQL (types, mutations), rate limiting (Rack::Attack). |
1337
1339
  | `rake_tasks` | Custom rake tasks in `lib/tasks/` with names, descriptions, namespaces, file paths. |
1338
1340
  | `assets` | Asset pipeline (Propshaft/Sprockets), JS bundler (importmap/esbuild/webpack/vite), CSS framework, importmap pins, manifest files. |
@@ -1342,10 +1344,8 @@ Includes all standard introspectors plus:
1342
1344
  | `middleware` | Custom Rack middleware in app/middleware/ with detected patterns (auth, rate limiting, tenant isolation, logging). Full middleware stack. |
1343
1345
  | `engines` | Mounted Rails engines from routes.rb with paths and descriptions for 23+ known engines (Sidekiq::Web, Flipper::UI, PgHero, ActiveAdmin, etc.). |
1344
1346
  | `multi_database` | Multiple databases, replicas, sharding config, model-specific `connects_to` declarations. database.yml parsing fallback. |
1345
- | `accessibility` | ARIA attributes, semantic HTML elements, screen reader text, alt text coverage, landmark roles, accessibility score. |
1346
- | `performance` | N+1 query risks, missing counter_cache, missing FK indexes, Model.all anti-patterns, eager load candidates. |
1347
1347
  | `frontend_frameworks` | Frontend JS framework detection (React/Vue/Svelte/Angular), mounting strategy (Inertia/react-rails), TypeScript config, state management, package manager. |
1348
- | `database_stats` | PostgreSQL approximate row counts via `pg_stat_user_tables`. **Opt-in only** not in any preset, add manually: `config.introspectors += [:database_stats]`. |
1348
+ | `database_stats` | PostgreSQL approximate row counts via `pg_stat_user_tables`. Gracefully skips on non-PostgreSQL adapters. |
1349
1349
 
1350
1350
  ### Using the standard preset
1351
1351
 
@@ -377,7 +377,8 @@ module RailsAiContext
377
377
  return nil unless match
378
378
 
379
379
  match[1].split.map(&:to_sym)
380
- rescue
380
+ rescue => e
381
+ $stderr.puts "[rails-ai-context] read_previous_ai_tools failed: #{e.message}" if ENV["DEBUG"]
381
382
  nil
382
383
  end
383
384
  end # no_tasks
@@ -6,7 +6,7 @@ module RailsAiContext
6
6
  standard: %i[schema models routes jobs gems conventions controllers tests migrations stimulus
7
7
  view_templates design_tokens config components
8
8
  turbo auth accessibility performance i18n],
9
- full: %i[schema models routes jobs gems conventions stimulus controllers views view_templates design_tokens turbo
9
+ full: %i[schema models routes jobs gems conventions stimulus database_stats controllers views view_templates design_tokens turbo
10
10
  i18n config active_storage action_text auth api tests rake_tasks assets
11
11
  devops action_mailbox migrations seeds middleware engines multi_database
12
12
  components accessibility performance frontend_frameworks]
@@ -84,7 +84,8 @@ module RailsAiContext
84
84
  message: "#{pending.size} pending migration(s) — schema data will be stale",
85
85
  fix: "Run `rails db:migrate`")
86
86
  end
87
- rescue
87
+ rescue => e
88
+ $stderr.puts "[rails-ai-context] check_pending_migrations failed: #{e.message}" if ENV["DEBUG"]
88
89
  # Can't check pending migrations in this environment
89
90
  nil
90
91
  end
@@ -234,7 +235,8 @@ module RailsAiContext
234
235
  message: "#{errors.size} introspector(s) returned errors: #{errors.join(', ')}",
235
236
  fix: "Check if the app has the required features (e.g., stimulus needs app/javascript/controllers/)")
236
237
  end
237
- rescue
238
+ rescue => e
239
+ $stderr.puts "[rails-ai-context] check_introspector_health failed: #{e.message}" if ENV["DEBUG"]
238
240
  nil
239
241
  end
240
242
 
@@ -71,7 +71,8 @@ module RailsAiContext
71
71
  spec = Bundler.rubygems.find_name("rails-ai-context").first
72
72
  return false unless spec
73
73
  spec.source.is_a?(Bundler::Source::Path)
74
- rescue
74
+ rescue => e
75
+ $stderr.puts "[rails-ai-context] local_gem_path? failed: #{e.message}" if ENV["DEBUG"]
75
76
  false
76
77
  end
77
78
 
@@ -50,7 +50,8 @@ module RailsAiContext
50
50
  Dir.glob(File.join(dir, "**/*.{erb,haml,slim,html}")).each do |path|
51
51
  content = File.read(path, encoding: "UTF-8", invalid: :replace, undef: :replace)
52
52
  views << { file: path.sub("#{root}/", ""), content: content }
53
- rescue
53
+ rescue => e
54
+ $stderr.puts "[rails-ai-context] collect_view_content failed: #{e.message}" if ENV["DEBUG"]
54
55
  next
55
56
  end
56
57
  end
@@ -41,7 +41,8 @@ module RailsAiContext
41
41
  end
42
42
 
43
43
  { name: name, file: relative, routing: routing }
44
- rescue
44
+ rescue => e
45
+ $stderr.puts "[rails-ai-context] extract_mailboxes failed: #{e.message}" if ENV["DEBUG"]
45
46
  nil
46
47
  end.sort_by { |m| m[:name] }
47
48
  end
@@ -40,7 +40,8 @@ module RailsAiContext
40
40
  end
41
41
 
42
42
  fields.sort_by { |f| [ f[:model], f[:field] ] }
43
- rescue
43
+ rescue => e
44
+ $stderr.puts "[rails-ai-context] extract_rich_text_fields failed: #{e.message}" if ENV["DEBUG"]
44
45
  []
45
46
  end
46
47
  end
@@ -47,7 +47,8 @@ module RailsAiContext
47
47
  end
48
48
 
49
49
  attachments.sort_by { |a| [ a[:model], a[:name] ] }
50
- rescue
50
+ rescue => e
51
+ $stderr.puts "[rails-ai-context] extract_attachments failed: #{e.message}" if ENV["DEBUG"]
51
52
  []
52
53
  end
53
54
 
@@ -58,7 +59,8 @@ module RailsAiContext
58
59
  require "yaml"
59
60
  config = YAML.load_file(config_path, permitted_classes: [ Symbol ], aliases: true) || {}
60
61
  config.keys.sort
61
- rescue
62
+ rescue => e
63
+ $stderr.puts "[rails-ai-context] extract_storage_services failed: #{e.message}" if ENV["DEBUG"]
62
64
  []
63
65
  end
64
66
 
@@ -71,7 +73,8 @@ module RailsAiContext
71
73
  Dir.glob(File.join(dir, "**/*")).any? do |f|
72
74
  next false if File.directory?(f)
73
75
  File.read(f).match?(/direct.upload|DirectUpload|direct_upload/)
74
- rescue
76
+ rescue => e
77
+ $stderr.puts "[rails-ai-context] detect_direct_upload failed: #{e.message}" if ENV["DEBUG"]
75
78
  false
76
79
  end
77
80
  end
@@ -85,7 +85,8 @@ module RailsAiContext
85
85
  .map { |path| path.sub("#{root}/", "") }
86
86
  .sort
87
87
  .uniq
88
- rescue
88
+ rescue => e
89
+ $stderr.puts "[rails-ai-context] detect_openapi_specs failed: #{e.message}" if ENV["DEBUG"]
89
90
  []
90
91
  end
91
92
 
@@ -99,7 +100,8 @@ module RailsAiContext
99
100
  end
100
101
 
101
102
  { file: "config/initializers/cors.rb", origins: origins }
102
- rescue
103
+ rescue => e
104
+ $stderr.puts "[rails-ai-context] detect_cors_config failed: #{e.message}" if ENV["DEBUG"]
103
105
  nil
104
106
  end
105
107
 
@@ -111,7 +113,8 @@ module RailsAiContext
111
113
  codegen_tools = %w[openapi-typescript @graphql-codegen/cli orval]
112
114
 
113
115
  codegen_tools.select { |tool| content.include?(%("#{tool}")) }
114
- rescue
116
+ rescue => e
117
+ $stderr.puts "[rails-ai-context] detect_api_client_generation failed: #{e.message}" if ENV["DEBUG"]
115
118
  []
116
119
  end
117
120
 
@@ -126,7 +129,8 @@ module RailsAiContext
126
129
  Dir.glob(File.join(controllers_dir, "**/*.rb")).each do |path|
127
130
  content = File.read(path)
128
131
  return { rails_rate_limiting: true } if content.match?(/rate_limit\b/)
129
- rescue
132
+ rescue => e
133
+ $stderr.puts "[rails-ai-context] detect_rate_limiting failed: #{e.message}" if ENV["DEBUG"]
130
134
  next
131
135
  end
132
136
  end
@@ -42,7 +42,8 @@ module RailsAiContext
42
42
 
43
43
  content = File.read(path)
44
44
  content.scan(/pin\s+["']([^"']+)["']/).flatten.sort
45
- rescue
45
+ rescue => e
46
+ $stderr.puts "[rails-ai-context] extract_importmap_pins failed: #{e.message}" if ENV["DEBUG"]
46
47
  []
47
48
  end
48
49
 
@@ -76,7 +77,8 @@ module RailsAiContext
76
77
  def read_gemfile_lock
77
78
  path = File.join(root, "Gemfile.lock")
78
79
  File.exist?(path) ? File.read(path) : nil
79
- rescue
80
+ rescue => e
81
+ $stderr.puts "[rails-ai-context] read_gemfile_lock failed: #{e.message}" if ENV["DEBUG"]
80
82
  nil
81
83
  end
82
84
 
@@ -84,7 +86,8 @@ module RailsAiContext
84
86
  path = File.join(root, "package.json")
85
87
  return false unless File.exist?(path)
86
88
  File.read(path).include?("\"#{package}\"")
87
- rescue
89
+ rescue => e
90
+ $stderr.puts "[rails-ai-context] package_json_has? failed: #{e.message}" if ENV["DEBUG"]
88
91
  false
89
92
  end
90
93
  end
@@ -103,7 +103,8 @@ module RailsAiContext
103
103
  end
104
104
 
105
105
  result
106
- rescue
106
+ rescue => e
107
+ $stderr.puts "[rails-ai-context] detect_devise_modules_per_model failed: #{e.message}" if ENV["DEBUG"]
107
108
  {}
108
109
  end
109
110
 
@@ -115,7 +116,8 @@ module RailsAiContext
115
116
  token_auth[:http_token_auth] = detect_http_token_auth
116
117
 
117
118
  token_auth
118
- rescue
119
+ rescue => e
120
+ $stderr.puts "[rails-ai-context] detect_token_auth failed: #{e.message}" if ENV["DEBUG"]
119
121
  {}
120
122
  end
121
123
 
@@ -129,7 +131,8 @@ module RailsAiContext
129
131
  end
130
132
 
131
133
  { detected: true }
132
- rescue
134
+ rescue => e
135
+ $stderr.puts "[rails-ai-context] detect_devise_jwt failed: #{e.message}" if ENV["DEBUG"]
133
136
  { detected: false }
134
137
  end
135
138
 
@@ -150,7 +153,8 @@ module RailsAiContext
150
153
  result[:grant_flows] = grant_flows if grant_flows
151
154
  result[:access_token_expires_in] = expires_in if expires_in
152
155
  result
153
- rescue
156
+ rescue => e
157
+ $stderr.puts "[rails-ai-context] detect_doorkeeper failed: #{e.message}" if ENV["DEBUG"]
154
158
  nil
155
159
  end
156
160
 
@@ -164,7 +168,8 @@ module RailsAiContext
164
168
  path.sub("#{root}/", "")
165
169
  end
166
170
  end.sort
167
- rescue
171
+ rescue => e
172
+ $stderr.puts "[rails-ai-context] detect_http_token_auth failed: #{e.message}" if ENV["DEBUG"]
168
173
  []
169
174
  end
170
175
 
@@ -182,7 +187,8 @@ module RailsAiContext
182
187
  results << { model: model_name, matches: matches.flatten.map(&:strip) }
183
188
  end
184
189
  results.sort_by { |r| r[:model] }
185
- rescue
190
+ rescue => e
191
+ $stderr.puts "[rails-ai-context] scan_models_for failed: #{e.message}" if ENV["DEBUG"]
186
192
  []
187
193
  end
188
194
 
@@ -190,7 +196,8 @@ module RailsAiContext
190
196
  lock_path = File.join(root, "Gemfile.lock")
191
197
  return false unless File.exist?(lock_path)
192
198
  File.read(lock_path).include?(" #{name} (")
193
- rescue
199
+ rescue => e
200
+ $stderr.puts "[rails-ai-context] gem_present? failed: #{e.message}" if ENV["DEBUG"]
194
201
  false
195
202
  end
196
203
 
@@ -40,7 +40,8 @@ module RailsAiContext
40
40
  when Array then store.first.to_s
41
41
  else store.class.name
42
42
  end
43
- rescue
43
+ rescue => e
44
+ $stderr.puts "[rails-ai-context] detect_cache_store failed: #{e.message}" if ENV["DEBUG"]
44
45
  "unknown"
45
46
  end
46
47
 
@@ -55,7 +56,8 @@ module RailsAiContext
55
56
  when Class then adapter.name
56
57
  else adapter.to_s
57
58
  end
58
- rescue
59
+ rescue => e
60
+ $stderr.puts "[rails-ai-context] detect_queue_adapter failed: #{e.message}" if ENV["DEBUG"]
59
61
  "unknown"
60
62
  end
61
63
 
@@ -78,13 +80,15 @@ module RailsAiContext
78
80
  end
79
81
 
80
82
  settings.empty? ? nil : settings
81
- rescue
83
+ rescue => e
84
+ $stderr.puts "[rails-ai-context] detect_mailer_settings failed: #{e.message}" if ENV["DEBUG"]
82
85
  nil
83
86
  end
84
87
 
85
88
  def extract_middleware
86
89
  app.middleware.map { |m| m.name || m.klass.to_s }.uniq
87
- rescue
90
+ rescue => e
91
+ $stderr.puts "[rails-ai-context] extract_middleware failed: #{e.message}" if ENV["DEBUG"]
88
92
  []
89
93
  end
90
94
 
@@ -100,7 +104,8 @@ module RailsAiContext
100
104
  def credentials_configured?
101
105
  creds = app.credentials
102
106
  creds.respond_to?(:config) && creds.config.keys.any?
103
- rescue
107
+ rescue => e
108
+ $stderr.puts "[rails-ai-context] credentials_configured? failed: #{e.message}" if ENV["DEBUG"]
104
109
  false
105
110
  end
106
111
 
@@ -113,7 +118,8 @@ module RailsAiContext
113
118
  if content.match?(/< ActiveSupport::CurrentAttributes|< Rails::CurrentAttributes/)
114
119
  File.basename(path, ".rb").camelize
115
120
  end
116
- rescue
121
+ rescue => e
122
+ $stderr.puts "[rails-ai-context] detect_current_attributes failed: #{e.message}" if ENV["DEBUG"]
117
123
  nil
118
124
  end
119
125
  end
@@ -51,7 +51,8 @@ module RailsAiContext
51
51
  else
52
52
  Rails.application.eager_load!
53
53
  end
54
- rescue
54
+ rescue => e
55
+ $stderr.puts "[rails-ai-context] eager_load_controllers! failed: #{e.message}" if ENV["DEBUG"]
55
56
  nil
56
57
  end
57
58
 
@@ -131,7 +132,8 @@ module RailsAiContext
131
132
  return actions if actions.any?
132
133
  end
133
134
  ctrl.action_methods.to_a.sort
134
- rescue
135
+ rescue => e
136
+ $stderr.puts "[rails-ai-context] extract_actions failed: #{e.message}" if ENV["DEBUG"]
135
137
  []
136
138
  end
137
139
 
@@ -192,7 +194,8 @@ module RailsAiContext
192
194
  end
193
195
 
194
196
  []
195
- rescue
197
+ rescue => e
198
+ $stderr.puts "[rails-ai-context] extract_filters failed: #{e.message}" if ENV["DEBUG"]
196
199
  []
197
200
  end
198
201
 
@@ -215,7 +218,8 @@ module RailsAiContext
215
218
  klass = klass.superclass
216
219
  end
217
220
  constraints
218
- rescue
221
+ rescue => e
222
+ $stderr.puts "[rails-ai-context] collect_source_constraints failed: #{e.message}" if ENV["DEBUG"]
219
223
  {}
220
224
  end
221
225
 
@@ -287,7 +291,8 @@ module RailsAiContext
287
291
  def devise_controller?(ctrl)
288
292
  return false unless defined?(::DeviseController)
289
293
  ctrl < ::DeviseController || ctrl.ancestors.any? { |a| a.name&.start_with?("Devise::") }
290
- rescue
294
+ rescue => e
295
+ $stderr.puts "[rails-ai-context] devise_controller? failed: #{e.message}" if ENV["DEBUG"]
291
296
  false
292
297
  end
293
298
 
@@ -303,7 +308,8 @@ module RailsAiContext
303
308
  .reject { |mod| mod.name&.start_with?("ActionController", "ActionDispatch", "ActiveSupport", "AbstractController") }
304
309
  .map(&:name)
305
310
  .compact
306
- rescue
311
+ rescue => e
312
+ $stderr.puts "[rails-ai-context] extract_concerns failed: #{e.message}" if ENV["DEBUG"]
307
313
  []
308
314
  end
309
315
 
@@ -338,7 +344,8 @@ module RailsAiContext
338
344
  exceptions = exception_part&.scan(/([A-Z][\w:]+)/)&.flatten || []
339
345
  exceptions.map { |ex| { exception: ex, handler: handler }.compact }
340
346
  end.flatten
341
- rescue
347
+ rescue => e
348
+ $stderr.puts "[rails-ai-context] extract_rescue_from failed: #{e.message}" if ENV["DEBUG"]
342
349
  []
343
350
  end
344
351
 
@@ -349,7 +356,8 @@ module RailsAiContext
349
356
  return nil unless match
350
357
 
351
358
  match[1].strip
352
- rescue
359
+ rescue => e
360
+ $stderr.puts "[rails-ai-context] extract_rate_limit failed: #{e.message}" if ENV["DEBUG"]
353
361
  nil
354
362
  end
355
363
 
@@ -369,7 +377,8 @@ module RailsAiContext
369
377
  end
370
378
  end
371
379
  actions.uniq.sort
372
- rescue
380
+ rescue => e
381
+ $stderr.puts "[rails-ai-context] extract_turbo_stream_actions failed: #{e.message}" if ENV["DEBUG"]
373
382
  []
374
383
  end
375
384
 
@@ -377,7 +386,8 @@ module RailsAiContext
377
386
  path = source_path(ctrl)
378
387
  return nil unless path && File.exist?(path)
379
388
  File.read(path)
380
- rescue
389
+ rescue => e
390
+ $stderr.puts "[rails-ai-context] read_source failed: #{e.message}" if ENV["DEBUG"]
381
391
  nil
382
392
  end
383
393
 
@@ -146,7 +146,8 @@ module RailsAiContext
146
146
  .select { |d| File.directory?(File.join(app_dir, d)) }
147
147
  .reject { |d| STANDARD_APP_DIRS.include?(d) }
148
148
  .sort
149
- rescue
149
+ rescue => e
150
+ $stderr.puts "[rails-ai-context] detect_custom_directories failed: #{e.message}" if ENV["DEBUG"]
150
151
  []
151
152
  end
152
153
 
@@ -75,7 +75,8 @@ module RailsAiContext
75
75
  plugins << "headlessui" if pkg_content.include?("headlessui") || pkg_content.include?("@headlessui")
76
76
 
77
77
  plugins.any? ? "#{framework}+#{plugins.join('+')}" : framework
78
- rescue
78
+ rescue => e
79
+ $stderr.puts "[rails-ai-context] detect_framework failed: #{e.message}" if ENV["DEBUG"]
79
80
  "unknown"
80
81
  end
81
82
 
@@ -288,7 +289,8 @@ module RailsAiContext
288
289
  end
289
290
 
290
291
  result
291
- rescue
292
+ rescue => e
293
+ $stderr.puts "[rails-ai-context] extract_font_loading failed: #{e.message}" if ENV["DEBUG"]
292
294
  { font_face: 0, google_fonts: false, system_fonts: false }
293
295
  end
294
296
 
@@ -304,7 +306,8 @@ module RailsAiContext
304
306
  end
305
307
  end
306
308
  layers.uniq
307
- rescue
309
+ rescue => e
310
+ $stderr.puts "[rails-ai-context] extract_css_layers failed: #{e.message}" if ENV["DEBUG"]
308
311
  []
309
312
  end
310
313
 
@@ -325,7 +328,8 @@ module RailsAiContext
325
328
  end
326
329
  end
327
330
  plugins.uniq
328
- rescue
331
+ rescue => e
332
+ $stderr.puts "[rails-ai-context] extract_postcss_plugins failed: #{e.message}" if ENV["DEBUG"]
329
333
  []
330
334
  end
331
335
 
@@ -50,7 +50,8 @@ module RailsAiContext
50
50
  end
51
51
 
52
52
  config.empty? ? nil : config
53
- rescue
53
+ rescue => e
54
+ $stderr.puts "[rails-ai-context] extract_puma_config failed: #{e.message}" if ENV["DEBUG"]
54
55
  nil
55
56
  end
56
57
 
@@ -77,7 +78,8 @@ module RailsAiContext
77
78
  content = File.read(routes_path)
78
79
  return true if content.match?(/\b(?:health|up|ping|status)\b/)
79
80
  nil
80
- rescue
81
+ rescue => e
82
+ $stderr.puts "[rails-ai-context] detect_health_check failed: #{e.message}" if ENV["DEBUG"]
81
83
  nil
82
84
  end
83
85
 
@@ -96,7 +98,8 @@ module RailsAiContext
96
98
  info[:compose] = compose
97
99
 
98
100
  info
99
- rescue
101
+ rescue => e
102
+ $stderr.puts "[rails-ai-context] extract_docker_info failed: #{e.message}" if ENV["DEBUG"]
100
103
  nil
101
104
  end
102
105
 
@@ -100,10 +100,12 @@ module RailsAiContext
100
100
  next if engine.name.start_with?("Rails::", "ActionPack::", "ActionView::", "ActiveModel::")
101
101
 
102
102
  { name: engine.name, root: engine.root.to_s.sub("#{Gem.dir}/gems/", "") }
103
- rescue
103
+ rescue => e
104
+ $stderr.puts "[rails-ai-context] discover_rails_engines failed: #{e.message}" if ENV["DEBUG"]
104
105
  nil
105
106
  end.sort_by { |e| e[:name] }
106
- rescue
107
+ rescue => e
108
+ $stderr.puts "[rails-ai-context] discover_rails_engines failed: #{e.message}" if ENV["DEBUG"]
107
109
  []
108
110
  end
109
111
  end
@@ -418,7 +418,8 @@ module RailsAiContext
418
418
  return false unless File.exist?(path)
419
419
  content = File.read(path, encoding: "bom|utf-8")
420
420
  content.include?("\"#{name}\"")
421
- rescue
421
+ rescue => e
422
+ $stderr.puts "[rails-ai-context] package_json_has_script? failed: #{e.message}" if ENV["DEBUG"]
422
423
  false
423
424
  end
424
425
  end
@@ -42,7 +42,8 @@ module RailsAiContext
42
42
  begin
43
43
  data = YAML.load_file(path, permitted_classes: [ Symbol ], aliases: true) || {}
44
44
  info[:key_count] = count_keys(data)
45
- rescue
45
+ rescue => e
46
+ $stderr.puts "[rails-ai-context] extract_locale_files failed: #{e.message}" if ENV["DEBUG"]
46
47
  info[:parse_error] = true
47
48
  end
48
49
  end
@@ -42,7 +42,8 @@ module RailsAiContext
42
42
  priority: job.priority
43
43
  }.compact
44
44
  end.sort_by { |j| j[:name] }
45
- rescue
45
+ rescue => e
46
+ $stderr.puts "[rails-ai-context] extract_jobs failed: #{e.message}" if ENV["DEBUG"]
46
47
  []
47
48
  end
48
49
 
@@ -80,7 +81,8 @@ module RailsAiContext
80
81
  job[:perform_signature] = perform_signature if perform_signature
81
82
  job
82
83
  end.sort_by { |j| j[:name] }
83
- rescue
84
+ rescue => e
85
+ $stderr.puts "[rails-ai-context] extract_jobs_from_source failed: #{e.message}" if ENV["DEBUG"]
84
86
  []
85
87
  end
86
88
 
@@ -99,7 +101,8 @@ module RailsAiContext
99
101
  delivery_method: mailer.delivery_method.to_s
100
102
  }
101
103
  end.sort_by { |m| m[:name] }
102
- rescue
104
+ rescue => e
105
+ $stderr.puts "[rails-ai-context] extract_mailers failed: #{e.message}" if ENV["DEBUG"]
103
106
  []
104
107
  end
105
108
 
@@ -116,7 +119,8 @@ module RailsAiContext
116
119
  .map(&:to_s)
117
120
  }
118
121
  end.sort_by { |c| c[:name] }
119
- rescue
122
+ rescue => e
123
+ $stderr.puts "[rails-ai-context] extract_channels failed: #{e.message}" if ENV["DEBUG"]
120
124
  []
121
125
  end
122
126
  end