Class: RubynCode::Config::ProjectProfile

Inherits:
Object
  • Object
show all
Defined in:
lib/rubyn_code/config/project_profile.rb

Overview

Auto-generated project profile that caches detected project stack information. First session pays the detection cost; subsequent sessions load a compact ~500-token profile instead of re-exploring.

Constant Summary collapse

PROFILE_FILENAME =
'project_profile.yml'
DETECTABLE_KEYS =
%w[
  framework ruby_version database test_framework
  factories auth background_jobs api frontend
  key_models service_pattern custom_conventions
].freeze
FRAMEWORK_GEMS =
{ 'rails' => 'rails', 'sinatra' => 'sinatra', 'hanami' => 'hanami' }.freeze
API_GEMS =
{ 'grape' => 'grape', 'graphql' => 'graphql' }.freeze
FRONTEND_GEMS =
{ 'turbo-rails' => 'hotwire', 'react-rails' => 'react' }.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(project_root:) ⇒ ProjectProfile

Returns a new instance of ProjectProfile.



22
23
24
25
26
27
# File 'lib/rubyn_code/config/project_profile.rb', line 22

def initialize(project_root:)
  @project_root = File.expand_path(project_root)
  @project_dir = File.join(@project_root, '.rubyn-code')
  @profile_path = File.join(@project_dir, PROFILE_FILENAME)
  @data = {}
end

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data.



20
21
22
# File 'lib/rubyn_code/config/project_profile.rb', line 20

def data
  @data
end

#profile_pathObject (readonly)

Returns the value of attribute profile_path.



20
21
22
# File 'lib/rubyn_code/config/project_profile.rb', line 20

def profile_path
  @profile_path
end

Instance Method Details

#detect_and_save!Object

Detect project stack and save profile.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/rubyn_code/config/project_profile.rb', line 41

def detect_and_save!
  @data = {}
  detect_framework
  detect_ruby_version
  detect_database
  detect_test_framework
  detect_auth
  detect_background_jobs
  detect_api_framework
  detect_key_models
  detect_service_pattern
  save!
  self
end

#loadObject

Load existing profile or return nil if none exists.



30
31
32
33
34
35
36
37
38
# File 'lib/rubyn_code/config/project_profile.rb', line 30

def load
  return nil unless File.exist?(@profile_path)

  raw = YAML.safe_load_file(@profile_path, permitted_classes: [Symbol])
  @data = raw.is_a?(Hash) ? raw : {}
  self
rescue StandardError
  nil
end

#load_or_detect!Object

Load if exists, otherwise detect and save.



57
58
59
# File 'lib/rubyn_code/config/project_profile.rb', line 57

def load_or_detect!
  load || detect_and_save!
end

#save!Object

Save the current profile data to disk.



74
75
76
77
# File 'lib/rubyn_code/config/project_profile.rb', line 74

def save!
  FileUtils.mkdir_p(@project_dir)
  File.write(@profile_path, YAML.dump(@data))
end

#stale?Boolean

Check if the profile is stale (older than 7 days).

Returns:

  • (Boolean)


80
81
82
83
84
# File 'lib/rubyn_code/config/project_profile.rb', line 80

def stale?
  return true unless File.exist?(@profile_path)

  (Time.now - File.mtime(@profile_path)) > 604_800
end

#to_promptObject

Compact string representation for system prompt injection (~500 tokens).



62
63
64
65
66
67
68
69
70
71
# File 'lib/rubyn_code/config/project_profile.rb', line 62

def to_prompt
  return '' if @data.empty?

  lines = ['Project Profile:']
  @data.each do |key, value|
    formatted = value.is_a?(Array) ? value.join(', ') : value.to_s
    lines << "  #{key}: #{formatted}" unless formatted.empty?
  end
  lines.join("\n")
end