MCP: Fix get_declaration leaking internal Debug representation for Unresolved ancestors#810
Open
bnferguson wants to merge 1 commit into
Open
MCP: Fix get_declaration leaking internal Debug representation for Unresolved ancestors#810bnferguson wants to merge 1 commit into
get_declaration leaking internal Debug representation for Unresolved ancestors#810bnferguson wants to merge 1 commit into
Conversation
`get_declaration` formatted `Ancestor::Partial` entries with `{:?}`,
dumping the internal `Name` struct (`Id { value: ... }`, `PhantomData`,
`ref_count`) into the MCP response. This fires for any class whose
superclass or mixin lives outside the indexed workspace -- e.g. every
Rails base class inheriting from a gem.
Reuse `Graph::build_concatenated_name_from_name` (made `pub`) to walk
the `parent_scope` chain into a readable constant path like
`ActiveRecord::Base`. A missing name lookup now yields `<unknown>` in
the chain rather than silently dropping the ancestor.
Author
|
I have signed the CLA! |
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.
Background
While working with the MCP Claude was complaining about debug output in
get_declaration, digging into it it seems that when you have a ancestor that is unindexed (for instance, something defined in a gem), rather than say what the ancestor is rubydex prints the debug info. For instance for a class likeclass Dog < ActiveRecord::Base; endyou get:
instead of:
The latter seems to make a bit more sense to me but I don't know if perhaps there's reasoning I'm missing for the former. So feel free to close this (obvs) if this is way off base and not in fact a bug or a fix that makes total sense.
Approach
Went with a very simple/minimal fix by reusing
Graph::build_concatenated_name_from_name, which already existed instats/orphan_report.rsfor the orphan report. It walks theparent_scopechain off theNameand concatenates each segment into a qualified constant path.Buuuut to call it from the MCP crate, its visibility moves from
pub(crate)topub.The architecture docs note that
model/graph.rsis where all theGraph-y public bits are so it seems like this my make sense to be moved over there. But in the interest of keeping this PR for a bug that may not even be a bug I kept the fix narrow. Happy to move things around.There's a slight behavior change with this approach too. Previously, if
graph.names().get(name_id)returnedNone, the?would short-circuitfilter_mapand the ancestor would silently vanish from the response. After this change, that case renders as"<unknown>"(the existing fallback insidebuild_concatenated_name_from_name) and the ancestor stays in the array. TLDR; a missing name is now visible rather than swallowed. That seems preferable to me at first glance but may not be desired.I do believe old swallowing behavior could be maintained pretty easily.
Testing
Added a regression test:
cargo test -p rubydex-mcp get_declaration_unresolved_ancestor_renders_qualified_nameAlso if you want to test manually, index a workspace whose classes inherit from gem-provided base classes (any
ActiveRecordmodel should do), and callget_declaration. You should no longer see the debug output but instead seeActiveRecord::BaseNotes
(For the cross linking context sickos out there [that's me])
TODODeclarations for unresolved references), that's about why something is unresolved; this is about how theUnresolvedvariant is serialized to the MCP client.index_workspacefails withFileErroron therailsmeta-gem #803 (index_workspacedoesn't index gems) explains why these ancestors are unresolved