Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions internal/mcp/id_resolve.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,21 @@ func (s *Server) resolveSymbolID(ctx context.Context, id string) string {
if id == "" || s.graph == nil || s.graph.GetNode(id) != nil {
return id
}
if s.multiIndexer == nil {
return id
}
cwd := SessionCWDFromContext(ctx)
if cwd != "" {
if _, _, prefix, ok := s.multiIndexer.ScopeForCWD(cwd); ok && prefix != "" {
if cand := prefix + "/" + id; s.graph.GetNode(cand) != nil {
return cand
// The cwd rung needs the multi-repo index to map a directory to a repo
// prefix; the graphRelID rung below does not. Returning early on a nil
// multiIndexer skipped both, which cost a server built without
// MultiRepoOptions (cmd/gortex eval_recall.go, eval_server.go) the
// separator normalization graphPathSpelling exists to provide: on Windows
// the stored id is `pkga\a.go::Foo` while every agent writes
// `pkga/a.go::Foo`, and the tool answered "symbol not found" for an
// indexed symbol.
if s.multiIndexer != nil {
cwd := SessionCWDFromContext(ctx)
if cwd != "" {
if _, _, prefix, ok := s.multiIndexer.ScopeForCWD(cwd); ok && prefix != "" {
if cand := prefix + "/" + id; s.graph.GetNode(cand) != nil {
return cand
}
}
}
}
Expand Down
35 changes: 35 additions & 0 deletions internal/mcp/id_resolve_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package mcp

import (
"context"
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
Expand All @@ -22,6 +23,40 @@ func nameResolveServer(t *testing.T) *Server {
return s
}

// TestResolveSymbolID_WithoutMultiIndexer_StillAnchorsThePath pins the rung
// order inside resolveSymbolID: the cwd rung needs the multi-repo index to map
// a directory to a repo prefix, the graphRelID rung does not. Returning early
// on a nil multiIndexer skipped both, so a server built without
// MultiRepoOptions — cmd/gortex's eval_recall.go and eval_server.go — lost path
// anchoring entirely.
//
// The absolute-path spelling is deliberate: it exercises the rung on every
// platform, so the linux/macos matrix protects this. On Windows the same rung
// additionally reconciles the separator, which is what graphPathSpelling exists
// for — the store holds `pkga\a.go::Foo` while every agent writes
// `pkga/a.go::Foo`, and move_symbol answered "symbol not found" for an indexed
// symbol.
func TestResolveSymbolID_WithoutMultiIndexer_StillAnchorsThePath(t *testing.T) {
srv, dir := setupMoveInlineRepo(t, map[string]string{
"pkga/a.go": "package pkga\n\nfunc Foo() int { return 42 }\n",
})
require.Nil(t, srv.multiIndexer, "fixture must exercise the nil-multiIndexer path")

var stored string
for _, n := range srv.graph.FindNodesByName("Foo") {
if n != nil && n.Kind == graph.KindFunction {
stored = n.ID
}
}
require.NotEmpty(t, stored, "fixture must index Foo")

absID := filepath.Join(dir, "pkga", "a.go") + "::Foo"
require.Nil(t, srv.graph.GetNode(absID), "the absolute spelling must not be a stored id")

assert.Equal(t, stored, srv.resolveSymbolID(context.Background(), absID),
"an absolute-path id must anchor back to the stored id without a multiIndexer")
}

func TestResolveNameToIDs(t *testing.T) {
s := nameResolveServer(t)
got := s.resolveNameToIDs("Bar")
Expand Down
Loading