rails-ai-context 0.8.4 → 0.8.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '08211bf465556a4185faaebc25d66fffcf4bd2e54ba335708b82c5e8d81f11f2'
4
- data.tar.gz: 2ab947951eb10d48acc6d674c31cea3b2ab9104a6ca9a9f6e9c409ffa1f96a7a
3
+ metadata.gz: 8933a659a2417ef033549547e011f90f7e3e3b1cacc8d2421802b944987869f2
4
+ data.tar.gz: fd39c3dc419170ca979d1c5fc3ccf59d4da66bec27ee712bfbb0ac9e1996769c
5
5
  SHA512:
6
- metadata.gz: 4757bd5de1b215938543d138b4c4a077ff7d1cda9dc25164e03251acd81afe26cd65cae9855cf879950b7a77e1f8aa78fb86e9a02d2e640e10569a9a5fc2bb45
7
- data.tar.gz: b2ebb6584d2886ae60c587954fdd54687c9a23a74422c395ee3d1cec063d9c499c4094ea611f1b053100b27cdaa4a47c85da006d99354437e52b6459575aab7c
6
+ metadata.gz: 3cb8ffb9600a47aca301bfc4d232bb3ff08f1283a66e3f2a7b0e2b205b31d91cf0b2ec6cbab43e8c7856d79191c467662cf693b74b7a26805f11a8c6c116d7f7
7
+ data.tar.gz: fa41c1eb1d078119a807cb5e9a6558fe3f40e6523eb1e497e9662d5454c3e756de0f39dd5a0744d3f1921c368011d4e2778fd4b460dc4918adc1f9002aa45fd5
data/CHANGELOG.md CHANGED
@@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.8.5] - 2026-03-19
9
+
10
+ ### Fixed
11
+
12
+ - **Thread-safe shared tool cache** — `BaseTool.cached_context` now uses a Mutex-protected shared cache across all 9 tool subclasses. Previously, each subclass cached independently (up to 9 redundant introspections after invalidation) and had no synchronization for multi-threaded servers like Puma. ([#2](https://github.com/crisnahine/rails-ai-context/issues/2))
13
+ - **SearchCode ripgrep total result cap** — `rg --max-count N` limits matches per file, not total. A search with `max_results: 5` against a large codebase could return hundreds of results. Now capped with `.first(max_results)` after parsing, matching the Ruby fallback behavior. ([#3](https://github.com/crisnahine/rails-ai-context/issues/3))
14
+ - **JobIntrospector Proc queue fallback** — when a Proc-based `queue_name` raises during introspection, the queue now falls back to `"default"` instead of producing garbage like `"#<Proc:0x00007f...>"`. ([#4](https://github.com/crisnahine/rails-ai-context/issues/4))
15
+ - **CLI `version` command crash** — `rails-ai-context version` crashed with `LoadError` due to wrong `require_relative` path (`../rails_ai_context/version` instead of `../lib/rails_ai_context/version`). ([#5](https://github.com/crisnahine/rails-ai-context/issues/5))
16
+
17
+ ### Documentation
18
+
19
+ - **Standalone CLI documented** — the `rails-ai-context` executable (serve, context, inspect, watch, doctor, version) is now documented in README, GUIDE, and CLAUDE.md.
20
+
8
21
  ## [0.8.4] - 2026-03-19
9
22
 
10
23
  ### Added
data/CLAUDE.md CHANGED
@@ -20,6 +20,7 @@ structure to AI assistants via the Model Context Protocol (MCP).
20
20
  - `lib/rails_ai_context/watcher.rb` — File watcher for auto-regenerating context files
21
21
  - `lib/rails_ai_context/engine.rb` — Rails Engine for auto-integration
22
22
  - `lib/generators/rails_ai_context/install/` — Install generator (creates .mcp.json, initializer, context files)
23
+ - `exe/rails-ai-context` — Standalone Thor CLI (serve, context, inspect, watch, doctor, version)
23
24
 
24
25
  ## Key Design Decisions
25
26
 
@@ -39,7 +40,7 @@ structure to AI assistants via the Model Context Protocol (MCP).
39
40
  ## Testing
40
41
 
41
42
  ```bash
42
- bundle exec rspec # Run specs (392 examples)
43
+ bundle exec rspec # Run specs (403 examples)
43
44
  bundle exec rubocop # Lint
44
45
  ```
45
46
 
data/README.md CHANGED
@@ -299,6 +299,8 @@ Frontend introspectors (views, Turbo, Stimulus, assets) degrade gracefully — t
299
299
 
300
300
  ## Commands
301
301
 
302
+ ### Rake tasks (recommended)
303
+
302
304
  | Command | Description |
303
305
  |---------|-------------|
304
306
  | `rails ai:context` | Generate all 20 context files (skips unchanged) |
@@ -322,6 +324,23 @@ Frontend introspectors (views, Turbo, Stimulus, assets) degrade gracefully — t
322
324
  > CONTEXT_MODE=full rails ai:context:cursor # full dump — Cursor only
323
325
  > ```
324
326
 
327
+ ### Standalone CLI
328
+
329
+ The gem also ships a `rails-ai-context` executable — an alternative to rake tasks. Useful for `.mcp.json` configs or when you prefer a shorter command.
330
+
331
+ | Command | Equivalent rake task |
332
+ |---------|---------------------|
333
+ | `rails-ai-context serve` | `rails ai:serve` |
334
+ | `rails-ai-context serve --transport http` | `rails ai:serve_http` |
335
+ | `rails-ai-context context` | `rails ai:context` |
336
+ | `rails-ai-context context --format claude` | `rails ai:context:claude` |
337
+ | `rails-ai-context doctor` | `rails ai:doctor` |
338
+ | `rails-ai-context watch` | `rails ai:watch` |
339
+ | `rails-ai-context inspect` | `rails ai:inspect` |
340
+ | `rails-ai-context version` | — |
341
+
342
+ Run from your Rails app root. Use `rails-ai-context help` for all options.
343
+
325
344
  ---
326
345
 
327
346
  ## Works Without a Database
@@ -353,7 +372,7 @@ The gem parses `db/schema.rb` as text when no database is connected. Works in CI
353
372
  ```bash
354
373
  git clone https://github.com/crisnahine/rails-ai-context.git
355
374
  cd rails-ai-context && bundle install
356
- bundle exec rspec # 392 examples
375
+ bundle exec rspec # 403 examples
357
376
  bundle exec rubocop # Lint
358
377
  ```
359
378
 
data/demo_script.sh CHANGED
@@ -8,7 +8,7 @@ echo 'Fetching gem metadata from https://rubygems.org...'
8
8
  sleep 0.3
9
9
  echo 'Resolving dependencies...'
10
10
  sleep 0.3
11
- echo 'Installing rails-ai-context 0.8.4'
11
+ echo 'Installing rails-ai-context 0.8.5'
12
12
  echo ''
13
13
  sleep 1
14
14
 
data/docs/GUIDE.md CHANGED
@@ -217,6 +217,25 @@ Commit **all files except `.ai-context.json`** (which is gitignored). This gives
217
217
  | `rails ai:watch` | Watch for file changes and auto-regenerate context files. Requires `listen` gem. |
218
218
  | `rails ai:inspect` | Print introspection summary to stdout. Useful for debugging. |
219
219
 
220
+ ### Standalone CLI
221
+
222
+ The gem ships a `rails-ai-context` executable as an alternative to rake tasks. Useful for `.mcp.json` configs or when you prefer a shorter command.
223
+
224
+ ```bash
225
+ rails-ai-context serve # Start MCP server (stdio)
226
+ rails-ai-context serve --transport http # Start MCP server (HTTP, port 6029)
227
+ rails-ai-context serve --transport http --port 8080 # Custom port
228
+ rails-ai-context context # Generate all context files
229
+ rails-ai-context context --format claude # Generate Claude files only
230
+ rails-ai-context doctor # Run diagnostics
231
+ rails-ai-context watch # Watch for changes
232
+ rails-ai-context inspect # Print introspection JSON
233
+ rails-ai-context version # Print version
234
+ rails-ai-context help # Show all commands
235
+ ```
236
+
237
+ Must be run from your Rails app root directory (requires `config/environment.rb`).
238
+
220
239
  ### Legacy command
221
240
 
222
241
  ```bash
data/exe/rails-ai-context CHANGED
@@ -72,7 +72,7 @@ module RailsAiContext
72
72
 
73
73
  desc "version", "Print version"
74
74
  def version
75
- require_relative "../rails_ai_context/version"
75
+ require_relative "../lib/rails_ai_context/version"
76
76
  puts "rails-ai-context v#{RailsAiContext::VERSION}"
77
77
  end
78
78
 
@@ -30,7 +30,7 @@ module RailsAiContext
30
30
  job.name.start_with?("ActionMailer", "ActiveStorage::", "ActionMailbox::", "Turbo::", "Sentry::")
31
31
 
32
32
  queue = job.queue_name
33
- queue = queue.call rescue queue.to_s if queue.is_a?(Proc)
33
+ queue = begin queue.call rescue "default" end if queue.is_a?(Proc)
34
34
 
35
35
  {
36
36
  name: job.name,
@@ -8,6 +8,10 @@ module RailsAiContext
8
8
  # Inherits from the official MCP::Tool to get schema validation,
9
9
  # annotations, and protocol compliance for free.
10
10
  class BaseTool < MCP::Tool
11
+ # Shared cache across all tool subclasses, protected by a Mutex
12
+ # for thread safety in multi-threaded servers (e.g., Puma).
13
+ SHARED_CACHE = { mutex: Mutex.new }
14
+
11
15
  class << self
12
16
  # Convenience: access the Rails app and cached introspection
13
17
  def rails_app
@@ -18,31 +22,36 @@ module RailsAiContext
18
22
  RailsAiContext.configuration
19
23
  end
20
24
 
21
- # Cache introspection results with TTL + fingerprint invalidation
25
+ # Cache introspection results with TTL + fingerprint invalidation.
26
+ # Uses SHARED_CACHE so all tool subclasses share one introspection
27
+ # result instead of each caching independently.
22
28
  def cached_context
23
- now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
24
- ttl = RailsAiContext.configuration.cache_ttl
29
+ SHARED_CACHE[:mutex].synchronize do
30
+ now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
31
+ ttl = RailsAiContext.configuration.cache_ttl
25
32
 
26
- if @cached_context && (now - @cache_timestamp) < ttl && !Fingerprinter.changed?(rails_app, @cache_fingerprint)
27
- return @cached_context
28
- end
33
+ if SHARED_CACHE[:context] && (now - SHARED_CACHE[:timestamp]) < ttl && !Fingerprinter.changed?(rails_app, SHARED_CACHE[:fingerprint])
34
+ return SHARED_CACHE[:context]
35
+ end
29
36
 
30
- @cached_context = RailsAiContext.introspect
31
- @cache_timestamp = now
32
- @cache_fingerprint = Fingerprinter.compute(rails_app)
33
- @cached_context
37
+ SHARED_CACHE[:context] = RailsAiContext.introspect
38
+ SHARED_CACHE[:timestamp] = now
39
+ SHARED_CACHE[:fingerprint] = Fingerprinter.compute(rails_app)
40
+ SHARED_CACHE[:context]
41
+ end
34
42
  end
35
43
 
36
44
  def reset_cache!
37
- @cached_context = nil
38
- @cache_timestamp = nil
39
- @cache_fingerprint = nil
45
+ SHARED_CACHE[:mutex].synchronize do
46
+ SHARED_CACHE.delete(:context)
47
+ SHARED_CACHE.delete(:timestamp)
48
+ SHARED_CACHE.delete(:fingerprint)
49
+ end
40
50
  end
41
51
 
42
- # Reset cache on ALL registered tool subclasses at once.
43
- # Used by LiveReload to invalidate everything on file change.
52
+ # Reset the shared cache. Used by LiveReload to invalidate on file change.
44
53
  def reset_all_caches!
45
- RailsAiContext::Server::TOOLS.each(&:reset_cache!)
54
+ reset_cache!
46
55
  end
47
56
 
48
57
  # Helper: wrap text in an MCP::Tool::Response with safety-net truncation
@@ -99,7 +99,7 @@ module RailsAiContext
99
99
  cmd << search_path
100
100
 
101
101
  output, _status = Open3.capture2(*cmd, err: File::NULL)
102
- parse_rg_output(output, root)
102
+ parse_rg_output(output, root).first(max_results)
103
103
  rescue => e
104
104
  [ { file: "error", line_number: 0, content: e.message } ]
105
105
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsAiContext
4
- VERSION = "0.8.4"
4
+ VERSION = "0.8.5"
5
5
  end
data/server.json CHANGED
@@ -7,11 +7,11 @@
7
7
  "url": "https://github.com/crisnahine/rails-ai-context",
8
8
  "source": "github"
9
9
  },
10
- "version": "0.8.4",
10
+ "version": "0.8.5",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "mcpb",
14
- "identifier": "https://github.com/crisnahine/rails-ai-context/releases/download/v0.8.4/rails-ai-context-mcp.mcpb",
14
+ "identifier": "https://github.com/crisnahine/rails-ai-context/releases/download/v0.8.5/rails-ai-context-mcp.mcpb",
15
15
  "fileSha256": "dd711a0ad6c4de943ae4da94eaf59a6dc9494b9d57f726e24649ed4e2f156990",
16
16
  "transport": {
17
17
  "type": "stdio"
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: 0.8.4
4
+ version: 0.8.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - crisnahine