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
@@ -490,7 +490,8 @@ module RailsAiContext
490
490
  match = line.match(/broadcasts_refreshes_to\s+:?(\w+)/)
491
491
  match ? match[1] : nil
492
492
  end
493
- rescue
493
+ rescue => e
494
+ $stderr.puts "[rails-ai-context] extract_stream_name_from_macro failed: #{e.message}" if ENV["DEBUG"]
494
495
  nil
495
496
  end
496
497
 
@@ -515,7 +516,8 @@ module RailsAiContext
515
516
  pattern = /#{Regexp.escape(method)}\s*\(?\s*:?["']?(\w+)["']?/
516
517
  match = line.match(pattern)
517
518
  match ? match[1] : "(dynamic)"
518
- rescue
519
+ rescue => e
520
+ $stderr.puts "[rails-ai-context] extract_stream_from_broadcast failed: #{e.message}" if ENV["DEBUG"]
519
521
  "(dynamic)"
520
522
  end
521
523
 
@@ -523,7 +525,8 @@ module RailsAiContext
523
525
  private_class_method def self.extract_target_from_broadcast(line)
524
526
  match = line.match(/target:\s*["'](\w+)["']/)
525
527
  match ? match[1] : nil
526
- rescue
528
+ rescue => e
529
+ $stderr.puts "[rails-ai-context] extract_target_from_broadcast failed: #{e.message}" if ENV["DEBUG"]
527
530
  nil
528
531
  end
529
532
 
@@ -531,7 +534,8 @@ module RailsAiContext
531
534
  private_class_method def self.extract_partial_from_broadcast(line)
532
535
  match = line.match(/partial:\s*["']([^"']+)["']/)
533
536
  match ? match[1] : nil
534
- rescue
537
+ rescue => e
538
+ $stderr.puts "[rails-ai-context] extract_partial_from_broadcast failed: #{e.message}" if ENV["DEBUG"]
535
539
  nil
536
540
  end
537
541
 
@@ -559,7 +563,8 @@ module RailsAiContext
559
563
 
560
564
  # Clean up and return meaningful stream name
561
565
  args.gsub(/["']/, "").gsub(/\s*,\s*/, ", ").strip
562
- rescue
566
+ rescue => e
567
+ $stderr.puts "[rails-ai-context] extract_stream_from_subscription failed: #{e.message}" if ENV["DEBUG"]
563
568
  "(dynamic)"
564
569
  end
565
570
 
@@ -570,7 +575,8 @@ module RailsAiContext
570
575
  # turbo_frame_tag dom_id(@model)
571
576
  match = line.match(/turbo_frame_tag\s+["':]*([^"',\s)]+)/)
572
577
  match ? match[1] : "(dynamic)"
573
- rescue
578
+ rescue => e
579
+ $stderr.puts "[rails-ai-context] extract_frame_id failed: #{e.message}" if ENV["DEBUG"]
574
580
  "(dynamic)"
575
581
  end
576
582
 
@@ -578,7 +584,8 @@ module RailsAiContext
578
584
  private_class_method def self.extract_frame_src(line)
579
585
  match = line.match(/src:\s*["']?([^"',\s)]+)["']?/)
580
586
  match ? match[1] : nil
581
- rescue
587
+ rescue => e
588
+ $stderr.puts "[rails-ai-context] extract_frame_src failed: #{e.message}" if ENV["DEBUG"]
582
589
  nil
583
590
  end
584
591
 
@@ -618,7 +625,8 @@ module RailsAiContext
618
625
  end
619
626
 
620
627
  warnings.sort
621
- rescue
628
+ rescue => e
629
+ $stderr.puts "[rails-ai-context] detect_mismatches failed: #{e.message}" if ENV["DEBUG"]
622
630
  []
623
631
  end
624
632
 
@@ -660,20 +668,23 @@ module RailsAiContext
660
668
  end
661
669
 
662
670
  wiring.sort_by { |k, _| k }.to_h
663
- rescue
671
+ rescue => e
672
+ $stderr.puts "[rails-ai-context] build_stream_wiring failed: #{e.message}" if ENV["DEBUG"]
664
673
  {}
665
674
  end
666
675
 
667
676
  private_class_method def self.extract_class_name(source)
668
677
  match = source.match(/class\s+([\w:]+)/)
669
678
  match[1] if match
670
- rescue
679
+ rescue => e
680
+ $stderr.puts "[rails-ai-context] extract_class_name failed: #{e.message}" if ENV["DEBUG"]
671
681
  nil
672
682
  end
673
683
 
674
684
  private_class_method def self.safe_read(path)
675
685
  File.read(path, encoding: "UTF-8", invalid: :replace, undef: :replace)
676
- rescue
686
+ rescue => e
687
+ $stderr.puts "[rails-ai-context] safe_read failed: #{e.message}" if ENV["DEBUG"]
677
688
  nil
678
689
  end
679
690
 
@@ -280,7 +280,8 @@ module RailsAiContext
280
280
  private_class_method def self.read_view_content(relative_path)
281
281
  full_path = Rails.root.join("app", "views", relative_path)
282
282
  File.exist?(full_path) ? File.read(full_path) : "(file not found)"
283
- rescue
283
+ rescue => e
284
+ $stderr.puts "[rails-ai-context] read_view_content failed: #{e.message}" if ENV["DEBUG"]
284
285
  "(error reading file)"
285
286
  end
286
287
 
@@ -311,7 +312,8 @@ module RailsAiContext
311
312
  end
312
313
 
313
314
  result
314
- rescue
315
+ rescue => e
316
+ $stderr.puts "[rails-ai-context] extract_view_metadata failed: #{e.message}" if ENV["DEBUG"]
315
317
  { ivars: [], turbo: [], components: [], helpers: [] }
316
318
  end
317
319
 
@@ -361,7 +363,8 @@ module RailsAiContext
361
363
  end
362
364
 
363
365
  locals.to_a.sort
364
- rescue
366
+ rescue => e
367
+ $stderr.puts "[rails-ai-context] extract_partial_locals failed: #{e.message}" if ENV["DEBUG"]
365
368
  []
366
369
  end
367
370
 
@@ -401,7 +401,8 @@ module RailsAiContext
401
401
 
402
402
  def rails_version
403
403
  Rails.version.split(".").first(2).join(".")
404
- rescue
404
+ rescue => e
405
+ $stderr.puts "[rails-ai-context] rails_version failed: #{e.message}" if ENV["DEBUG"]
405
406
  "7.1"
406
407
  end
407
408
  end
@@ -638,7 +638,8 @@ module RailsAiContext
638
638
  name = File.basename(path, ".rb").camelize
639
639
  name unless name == "ApplicationService" || name == "BaseService"
640
640
  end
641
- rescue
641
+ rescue => e
642
+ $stderr.puts "[rails-ai-context] extract_service_names failed: #{e.message}" if ENV["DEBUG"]
642
643
  []
643
644
  end
644
645
 
@@ -115,7 +115,8 @@ module RailsAiContext
115
115
  filter_lower = model_filter.downcase
116
116
  table_form = begin
117
117
  model_filter.underscore.pluralize.downcase
118
- rescue
118
+ rescue => e
119
+ $stderr.puts "[rails-ai-context] filter_items failed: #{e.message}" if ENV["DEBUG"]
119
120
  filter_lower
120
121
  end
121
122
  items.select { |i|
@@ -144,7 +144,8 @@ module RailsAiContext
144
144
  begin
145
145
  result = conn.select_all("SELECT name, SUM(pgsize) AS bytes FROM dbstat GROUP BY name ORDER BY bytes DESC")
146
146
  return result.map { |r| { name: r["name"], bytes: r["bytes"].to_i } } if result.any?
147
- rescue
147
+ rescue => e
148
+ $stderr.puts "[rails-ai-context] gather_table_sizes failed: #{e.message}" if ENV["DEBUG"]
148
149
  nil
149
150
  end
150
151
  # Fallback: whole database size
@@ -156,7 +157,8 @@ module RailsAiContext
156
157
  else
157
158
  nil
158
159
  end
159
- rescue
160
+ rescue => e
161
+ $stderr.puts "[rails-ai-context] gather_table_sizes failed: #{e.message}" if ENV["DEBUG"]
160
162
  nil
161
163
  end
162
164
 
@@ -171,7 +173,8 @@ module RailsAiContext
171
173
  ActiveRecord::Migrator.new(:up, context.migrations).pending_migrations
172
174
  end
173
175
  pending.map { |m| "#{m.version} — #{m.name}" }
174
- rescue
176
+ rescue => e
177
+ $stderr.puts "[rails-ai-context] gather_pending_migrations failed: #{e.message}" if ENV["DEBUG"]
175
178
  nil
176
179
  end
177
180
 
@@ -183,7 +186,8 @@ module RailsAiContext
183
186
  else
184
187
  nil
185
188
  end
186
- rescue
189
+ rescue => e
190
+ $stderr.puts "[rails-ai-context] gather_index_usage failed: #{e.message}" if ENV["DEBUG"]
187
191
  nil
188
192
  end
189
193
 
@@ -228,7 +232,8 @@ module RailsAiContext
228
232
  adapter_name = begin
229
233
  name = ActiveJob::Base.queue_adapter_name
230
234
  name.empty? ? "not configured" : name
231
- rescue
235
+ rescue => e
236
+ $stderr.puts "[rails-ai-context] gather_jobs failed: #{e.message}" if ENV["DEBUG"]
232
237
  "not available"
233
238
  end
234
239
  lines << "**Adapter:** #{adapter_name}"
@@ -454,7 +454,8 @@ module RailsAiContext
454
454
  end
455
455
  end
456
456
  nil
457
- rescue
457
+ rescue => e
458
+ $stderr.puts "[rails-ai-context] extract_class_context failed: #{e.message}" if ENV["DEBUG"]
458
459
  nil
459
460
  end
460
461
 
@@ -474,7 +475,8 @@ module RailsAiContext
474
475
  end
475
476
  end
476
477
  methods
477
- rescue
478
+ rescue => e
479
+ $stderr.puts "[rails-ai-context] extract_sibling_methods failed: #{e.message}" if ENV["DEBUG"]
478
480
  []
479
481
  end
480
482
 
@@ -499,7 +501,8 @@ module RailsAiContext
499
501
  return nil unless ctrl_routes&.any?
500
502
  # Show the first 2 routes as hints
501
503
  ctrl_routes.first(2).map { |r| "`#{r[:verb]} #{r[:path]}`" }.join(", ")
502
- rescue
504
+ rescue => e
505
+ $stderr.puts "[rails-ai-context] find_routes_for_controller failed: #{e.message}" if ENV["DEBUG"]
503
506
  nil
504
507
  end
505
508
 
@@ -521,7 +524,8 @@ module RailsAiContext
521
524
  end
522
525
 
523
526
  result.join("\n")
524
- rescue
527
+ rescue => e
528
+ $stderr.puts "[rails-ai-context] extract_method_body failed: #{e.message}" if ENV["DEBUG"]
525
529
  nil
526
530
  end
527
531
  end
@@ -135,7 +135,8 @@ module RailsAiContext
135
135
  else
136
136
  "main"
137
137
  end
138
- rescue
138
+ rescue => e
139
+ $stderr.puts "[rails-ai-context] detect_rails_branch failed: #{e.message}" if ENV["DEBUG"]
139
140
  "main"
140
141
  end
141
142
 
@@ -128,7 +128,8 @@ module RailsAiContext
128
128
  else
129
129
  "#{(diff / 3600).to_i}h ago"
130
130
  end
131
- rescue
131
+ rescue => e
132
+ $stderr.puts "[rails-ai-context] time_ago failed: #{e.message}" if ENV["DEBUG"]
132
133
  iso_timestamp
133
134
  end
134
135
  end
@@ -146,7 +146,8 @@ module RailsAiContext
146
146
  return matches.first.sub("#{Rails.root}/", "") if matches.any?
147
147
 
148
148
  nil
149
- rescue
149
+ rescue => e
150
+ $stderr.puts "[rails-ai-context] find_file_suggestion failed: #{e.message}" if ENV["DEBUG"]
150
151
  nil
151
152
  end
152
153
 
@@ -460,7 +461,8 @@ module RailsAiContext
460
461
  visitor = RailsSemanticVisitor.new
461
462
  result.value.accept(visitor)
462
463
  visitor
463
- rescue
464
+ rescue => e
465
+ $stderr.puts "[rails-ai-context] parse_and_visit failed: #{e.message}" if ENV["DEBUG"]
464
466
  nil
465
467
  end
466
468
 
@@ -900,7 +902,8 @@ module RailsAiContext
900
902
  warnings << "@#{ivar} used in view but not set in #{ctrl_class}. Fix: add `@#{ivar} = ...` to action"
901
903
  end
902
904
  warnings
903
- rescue
905
+ rescue => e
906
+ $stderr.puts "[rails-ai-context] check_instance_variable_usage failed: #{e.message}" if ENV["DEBUG"]
904
907
  []
905
908
  end
906
909
 
@@ -934,7 +937,8 @@ module RailsAiContext
934
937
  end
935
938
  end
936
939
  warnings
937
- rescue
940
+ rescue => e
941
+ $stderr.puts "[rails-ai-context] check_turbo_stream_channels failed: #{e.message}" if ENV["DEBUG"]
938
942
  []
939
943
  end
940
944
 
@@ -959,7 +963,8 @@ module RailsAiContext
959
963
  warnings << "#{file} uses turbo_stream_from but #{turbo_template} doesn't exist (Turbo Stream updates may need this)"
960
964
  end
961
965
  warnings
962
- rescue
966
+ rescue => e
967
+ $stderr.puts "[rails-ai-context] check_respond_to_template_existence failed: #{e.message}" if ENV["DEBUG"]
963
968
  []
964
969
  end
965
970
 
@@ -984,7 +989,8 @@ module RailsAiContext
984
989
  end
985
990
  end
986
991
  warnings.first(3) # cap at 3 to avoid noise
987
- rescue
992
+ rescue => e
993
+ $stderr.puts "[rails-ai-context] check_memory_loading failed: #{e.message}" if ENV["DEBUG"]
988
994
  []
989
995
  end
990
996
 
@@ -1013,7 +1019,8 @@ module RailsAiContext
1013
1019
  end
1014
1020
 
1015
1021
  warnings.first(5)
1016
- rescue
1022
+ rescue => e
1023
+ $stderr.puts "[rails-ai-context] check_performance_warnings failed: #{e.message}" if ENV["DEBUG"]
1017
1024
  []
1018
1025
  end
1019
1026
 
@@ -1044,7 +1051,8 @@ module RailsAiContext
1044
1051
  loc = w.line ? "#{w.file.relative}:#{w.line}" : w.file.relative
1045
1052
  "[#{w.confidence_name}] #{w.warning_type} — #{loc}: #{w.message}"
1046
1053
  end
1047
- rescue
1054
+ rescue => e
1055
+ $stderr.puts "[rails-ai-context] check_brakeman_security failed: #{e.message}" if ENV["DEBUG"]
1048
1056
  []
1049
1057
  end
1050
1058
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsAiContext
4
- VERSION = "4.3.2"
4
+ VERSION = "4.3.3"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-ai-context
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.3.2
4
+ version: 4.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - crisnahine
@@ -193,6 +193,10 @@ files:
193
193
  - README.md
194
194
  - Rakefile
195
195
  - SECURITY.md
196
+ - demo-trace.gif
197
+ - demo-trace.tape
198
+ - demo.gif
199
+ - demo.tape
196
200
  - docs/GUIDE.md
197
201
  - docs/token-comparison.jpeg
198
202
  - exe/rails-ai-context