Repository navigation
Conversation
CacheDir.gem_dir was keyed on every plugin loaded so far in the process. Loading a workspace with plugins in .solargraph.yml switched the gem cache directory for the whole process, so a second workspace without plugins in the same language server read and wrote the plugin-keyed directory: its cached gems looked missing and were rebuilt there. Workspace now keeps the plugins its config loaded, and that key is passed explicitly to every reader and writer of gem pins: Collection::Gem (cache_file, cached?, load, uncache), External, ApiMap#external and ApiMap.load_with_cache, and Shell cache/uncache. CacheDir.gem_dir takes the key as an argument, and the process-wide plugin registry in CacheDir is removed. The cache subprocess is given the configured plugins of its workspace with --plugins. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SEntZKsZwQHhzqcwG7MTqn
ApiMap#external passes workspace&.directory, which is nil for an ApiMap that has not cataloged a workspace, and External already guards that case. Widen the directory tags to String, nil, read the reader once into a local in the two guards so the nil check narrows it, and drop the ignore marker at the ApiMap call site. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SEntZKsZwQHhzqcwG7MTqn
Library passed the cache subprocess workspace.config.plugins, read when caching starts. Workspace#merge reloads the config when a new file appears, so editing the plugins in .solargraph.yml mid-session made the subprocess key its gem_dir on a different plugin set than the parent reads, and the parent would re-cache that gem forever. Workspace now keeps the plugin require paths it loaded at creation as plugin_paths, and Library passes those with --plugins. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SEntZKsZwQHhzqcwG7MTqn
Undercover flagged External#rbs_collection_config_path, which no spec called, and the Shell cache loop, which the existing specs never reached because their gem does not exist. Spec the config lookup with and without a directory, and check that cache --rebuild loads the gem under the plugins it required. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SEntZKsZwQHhzqcwG7MTqn
Restore the original directory.nil? || directory.empty? guards in rbs_collection_config_path and rbs_collection_lockfile instead of copying the reader into a local just so the checker can narrow it. The checker does not narrow a repeated attr_reader call after a nil guard, which castwide#1258 fixes, so mark both lines with a link to it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SEntZKsZwQHhzqcwG7MTqn
Brings in castwide master's castwide#1436 rugged build fix via castwide#1407. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SEntZKsZwQHhzqcwG7MTqn
Two examples read gem pins they never cached, relying on earlier specs to warm the plugin-less cache dir. In plugin jobs those writes go to the plugin-keyed dir, so the examples found nothing. Load and update the unloaded gems first, as castwide#1237 does. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SEntZKsZwQHhzqcwG7MTqn
apiology
marked this pull request as ready for review
October 22, 2026 17:53
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Claude: This PR was written by Claude Code on behalf of @apiology.
Problem
A workspace with plugins moves every other workspace to its gem cache:
In one language server, the plain workspace finds none of its cached gems and rebuilds them into the plugin directory, which castwide/solargraph#1407 introduced.
Solution
Each Workspace keeps the plugins its own config loaded, and that key is passed explicitly to
CacheDir.gem_dir(plugins)through Collection::Gem, External, ApiMap and the cache/uncache commands, so loading a plugin changes no process-wide state.A plugin loaded by plain
requireinto a workspace without config (for example a plugin spec suite) is no longer part of any key; it reads and writes the plaingemsdirectory.