Class: RailsAiContext::Fingerprinter

Inherits:
Object
  • Object
show all
Defined in:
lib/rails_ai_context/fingerprinter.rb

Overview

Computes a SHA256 fingerprint of key application files to detect changes. Used by BaseTool to invalidate cached introspection when files change.

Constant Summary collapse

WATCHED_FILES =
%w[
  db/schema.rb
  db/structure.sql
  config/routes.rb
  config/database.yml
  Gemfile.lock
  package.json
  tsconfig.json
].freeze
WATCHED_DIRS =
%w[
  app/models
  app/controllers
  app/views
  app/jobs
  app/mailers
  app/channels
  app/components
  app/javascript/controllers
  app/middleware
  config/initializers
  db/migrate
  lib/tasks
].freeze

Class Method Summary collapse

Class Method Details

.changed?(app, previous) ⇒ Boolean

Returns:

  • (Boolean)


85
86
87
# File 'lib/rails_ai_context/fingerprinter.rb', line 85

def changed?(app, previous)
  compute(app) != previous
end

.compute(app) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/rails_ai_context/fingerprinter.rb', line 35

def compute(app)
  root = app.root.to_s
  digest = Digest::SHA256.new

  # Include the gem's own version so cache invalidates during gem development
  digest.update(RailsAiContext::VERSION)

  # Include gem lib directory mtime when using a local/path gem (development mode)
  gem_lib = File.expand_path("../../..", __FILE__)
  if gem_lib.start_with?(root) || (defined?(Bundler) && local_gem_path?)
    Dir.glob(File.join(gem_lib, "**/*.rb")).sort.each do |path|
      digest.update(File.mtime(path).to_f.to_s)
    end
  end

  WATCHED_FILES.each do |file|
    path = File.join(root, file)
    digest.update(File.mtime(path).to_f.to_s) if File.exist?(path)
  rescue Errno::ENOENT
    # File deleted between exist? check and mtime read — skip
  end

  WATCHED_DIRS.each do |dir|
    full_dir = File.join(root, dir)
    next unless Dir.exist?(full_dir)

    Dir.glob(File.join(full_dir, "**/*.{rb,rake,js,ts,erb,haml,slim,yml}")).sort.each do |path|
      digest.update(File.mtime(path).to_f.to_s)
    rescue Errno::ENOENT
      # File deleted between glob and mtime read — skip
    end
  end

  digest.hexdigest
end