diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8c51d3dc9..bc5519bfd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: run: go build -o gortex ./cmd/gortex/ - name: Test - run: go test -race -coverprofile=coverage.out ./... + run: go test -race -timeout=20m -coverprofile=coverage.out ./... - name: Upload coverage if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.26' @@ -116,4 +116,4 @@ jobs: go-version-file: go.mod - name: Run benchmarks - run: go test -bench=. -benchmem -count=1 -benchtime=1s ./internal/parser/languages/ ./internal/query/ ./internal/graph/ + run: go test -bench=. -benchmem -count=1 -benchtime=1s -timeout=20m ./internal/parser/languages/ ./internal/query/ ./internal/graph/ diff --git a/internal/mcp/analyze_scope_test.go b/internal/mcp/analyze_scope_test.go index d1dd8585c..1dfaf3c25 100644 --- a/internal/mcp/analyze_scope_test.go +++ b/internal/mcp/analyze_scope_test.go @@ -30,8 +30,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" "github.com/zzet/gortex/internal/search" ) @@ -81,8 +79,7 @@ func newAnalyzeServer(t *testing.T, flagOn bool, repos ...analyzeRepoSpec) (*Ser require.NoError(t, err) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() bm := search.NewBM25() mi := indexer.NewMultiIndexer(g, reg, bm, cm, zap.NewNop()) _, err = mi.IndexScoped("", "") diff --git a/internal/mcp/callback_callers_test.go b/internal/mcp/callback_callers_test.go index 554c36218..8209b8fc4 100644 --- a/internal/mcp/callback_callers_test.go +++ b/internal/mcp/callback_callers_test.go @@ -12,9 +12,9 @@ import ( // navTestEng adapts a graph.Store to the engineLike surface navCallers needs. type navTestEng struct{ g graph.Store } -func (e navTestEng) GetSymbol(id string) *graph.Node { return e.g.GetNode(id) } -func (e navTestEng) GetOutEdges(id string) []*graph.Edge { return e.g.GetOutEdges(id) } -func (e navTestEng) GetInEdges(id string) []*graph.Edge { return e.g.GetInEdges(id) } +func (e navTestEng) GetSymbol(id string) *graph.Node { return e.g.GetNode(id) } +func (e navTestEng) GetOutEdges(id string) []*graph.Edge { return e.g.GetOutEdges(id) } +func (e navTestEng) GetInEdges(id string) []*graph.Edge { return e.g.GetInEdges(id) } // TestCallbackRegistrationCallers is part of the C3 named set: a function // registered as a callback (a callback-registration reference edge) shows up diff --git a/internal/mcp/change_contract_lenses_test.go b/internal/mcp/change_contract_lenses_test.go index ddd87c342..dfd926bc8 100644 --- a/internal/mcp/change_contract_lenses_test.go +++ b/internal/mcp/change_contract_lenses_test.go @@ -14,8 +14,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) @@ -65,8 +63,7 @@ func Bar() int { return Foo(21) } `), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) diff --git a/internal/mcp/change_contract_strategy_test.go b/internal/mcp/change_contract_strategy_test.go index 9d559a4fb..4142326f3 100644 --- a/internal/mcp/change_contract_strategy_test.go +++ b/internal/mcp/change_contract_strategy_test.go @@ -14,8 +14,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) @@ -53,8 +51,7 @@ func Wide(a, b, c, d, e, f int) int { require.NoError(t, os.WriteFile(filepath.Join(dir, "big.go"), []byte(src), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) diff --git a/internal/mcp/determinism_test.go b/internal/mcp/determinism_test.go index b8cd2fc9f..fdba8febc 100644 --- a/internal/mcp/determinism_test.go +++ b/internal/mcp/determinism_test.go @@ -14,8 +14,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) @@ -40,8 +38,7 @@ func setupDeterminismServer(t *testing.T) *Server { require.NoError(t, os.WriteFile(filepath.Join(dir, "handlers.go"), []byte(src.String()), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) diff --git a/internal/mcp/dynamic_boundary_test.go b/internal/mcp/dynamic_boundary_test.go index 9b93147e7..07f80ce37 100644 --- a/internal/mcp/dynamic_boundary_test.go +++ b/internal/mcp/dynamic_boundary_test.go @@ -12,10 +12,10 @@ import ( func TestDynamicBoundaryEmitsSiteFormKeyCandidates(t *testing.T) { body := strings.Join([]string{ "def route(self, name, payload):", // line 10 (startLine) - " handler = getattr(self, name)", // 11 reflection, key=name - " return self.handlers[action](payload)", // 12 computed_member, key=action - " # self.bus.emit('ignored.in.comment')", // 13 comment — must be skipped - " self.bus.emit('user.created', payload)", // 14 event_bus, key=user.created + " handler = getattr(self, name)", // 11 reflection, key=name + " return self.handlers[action](payload)", // 12 computed_member, key=action + " # self.bus.emit('ignored.in.comment')", // 13 comment — must be skipped + " self.bus.emit('user.created', payload)", // 14 event_bus, key=user.created }, "\n") // Stub candidate resolver: 'name' resolves to two handler symbols, one of diff --git a/internal/mcp/ensure_fresh_self_heal_test.go b/internal/mcp/ensure_fresh_self_heal_test.go index 2af049b42..dc1e8476b 100644 --- a/internal/mcp/ensure_fresh_self_heal_test.go +++ b/internal/mcp/ensure_fresh_self_heal_test.go @@ -7,6 +7,9 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap" + "os" + "path/filepath" + "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" @@ -14,8 +17,6 @@ import ( "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" "github.com/zzet/gortex/internal/search" - "os" - "path/filepath" ) // TestEnsureFresh_MultiRepoSelfHealsStaleFile is the regression test for the @@ -82,8 +83,7 @@ func TestEnsureFresh_SingleRepoSelfHealsStaleFile(t *testing.T) { []byte("package main\n\nfunc Hello() {}\n"), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() idx := indexer.New(g, reg, config.Default().Index, zap.NewNop()) _, err := idx.Index(dir) require.NoError(t, err) diff --git a/internal/mcp/memories_test.go b/internal/mcp/memories_test.go index 70a85bbc9..b64617457 100644 --- a/internal/mcp/memories_test.go +++ b/internal/mcp/memories_test.go @@ -198,8 +198,8 @@ func TestSurface_RanksSymbolAnchorAbovePinned(t *testing.T) { }) // Symbol anchor match — should rank above pinned. anchorID, _ := mm.Save(persistence.MemoryEntry{ - Body: "anchor match", - SymbolIDs: []string{"pkg/foo.go::Bar"}, + Body: "anchor match", + SymbolIDs: []string{"pkg/foo.go::Bar"}, Importance: 3, }) diff --git a/internal/mcp/overlay_e2e_test.go b/internal/mcp/overlay_e2e_test.go index 0db8d4060..d8629268f 100644 --- a/internal/mcp/overlay_e2e_test.go +++ b/internal/mcp/overlay_e2e_test.go @@ -20,8 +20,6 @@ import ( "github.com/zzet/gortex/internal/daemon" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) @@ -49,8 +47,7 @@ func Caller() { `), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) @@ -348,8 +345,8 @@ func Target() {} ctx := WithSessionID(context.Background(), sessID) res := callToolByName(t, srv, ctx, "get_symbol_source", map[string]any{ - "id": "target.go::Target", - "context_lines": 10, + "id": "target.go::Target", + "context_lines": 10, }) require.False(t, res.IsError, "get_symbol_source: %s", toolText(res)) require.Contains(t, toolText(res), "EditorSentinel", diff --git a/internal/mcp/pack_delta_test.go b/internal/mcp/pack_delta_test.go index 65bbfa232..72045c100 100644 --- a/internal/mcp/pack_delta_test.go +++ b/internal/mcp/pack_delta_test.go @@ -23,9 +23,9 @@ func TestExtractPackViewAndDiff(t *testing.T) { ), false) current := extractPackView(packResult( - symEntry("a.go::A", 1, "func A() {}"), // unchanged - symEntry("b.go::B", 5, "func B() { changed }"), // changed body - symEntry("c.go::C", 9, "func C() {}"), // added + symEntry("a.go::A", 1, "func A() {}"), // unchanged + symEntry("b.go::B", 5, "func B() { changed }"), // changed body + symEntry("c.go::C", 9, "func C() {}"), // added ), true) delta := diffPackViews(prior, current, "root1", "root2") diff --git a/internal/mcp/read_security_test.go b/internal/mcp/read_security_test.go index 664939a78..a793e44d9 100644 --- a/internal/mcp/read_security_test.go +++ b/internal/mcp/read_security_test.go @@ -13,16 +13,13 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) func newReadGuardServer(t *testing.T, repoRoot string) *Server { t.Helper() g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() idx := indexer.New(g, reg, config.IndexConfig{}, zap.NewNop()) idx.SetRootPath(repoRoot) return NewServer(query.NewEngine(g), g, idx, nil, zap.NewNop(), nil) diff --git a/internal/mcp/return_usage_test.go b/internal/mcp/return_usage_test.go index 36cabf28f..5f6882cc4 100644 --- a/internal/mcp/return_usage_test.go +++ b/internal/mcp/return_usage_test.go @@ -42,17 +42,17 @@ func returnUsageServer(t *testing.T) (*Server, string) { g.AddEdge(&graph.Edge{ From: "pkg/a.go::drop", To: fetch.ID, Kind: graph.EdgeCalls, FilePath: "pkg/a.go", Line: 3, - Meta: map[string]any{graph.MetaReturnUsage: graph.ReturnUsageDiscarded}, + Meta: map[string]any{graph.MetaReturnUsage: graph.ReturnUsageDiscarded}, }) g.AddEdge(&graph.Edge{ From: "pkg/a.go::keep", To: fetch.ID, Kind: graph.EdgeCalls, FilePath: "pkg/a.go", Line: 9, - Meta: map[string]any{graph.MetaReturnUsage: graph.ReturnUsageAssigned}, + Meta: map[string]any{graph.MetaReturnUsage: graph.ReturnUsageAssigned}, }) g.AddEdge(&graph.Edge{ From: "pkg/b.go::relay", To: fetch.ID, Kind: graph.EdgeCalls, FilePath: "pkg/b.go", Line: 5, - Meta: map[string]any{graph.MetaReturnUsage: graph.ReturnUsageReturned}, + Meta: map[string]any{graph.MetaReturnUsage: graph.ReturnUsageReturned}, }) g.AddEdge(&graph.Edge{ From: "pkg/b.go::opaque", To: fetch.ID, Kind: graph.EdgeCalls, diff --git a/internal/mcp/safe_delete_propagate_test.go b/internal/mcp/safe_delete_propagate_test.go index b7f34059a..bd09cf080 100644 --- a/internal/mcp/safe_delete_propagate_test.go +++ b/internal/mcp/safe_delete_propagate_test.go @@ -14,8 +14,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) @@ -54,8 +52,7 @@ func Caller() { `), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) diff --git a/internal/mcp/scope_resolve_test.go b/internal/mcp/scope_resolve_test.go index d5b76a508..d2337fe06 100644 --- a/internal/mcp/scope_resolve_test.go +++ b/internal/mcp/scope_resolve_test.go @@ -20,8 +20,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" "github.com/zzet/gortex/internal/search" "github.com/zzet/gortex/internal/search/trigram" @@ -77,8 +75,7 @@ func newSharedWorkspaceServer(t *testing.T, flagOn bool) sharedWSOptions { require.NoError(t, err) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() bm := search.NewBM25() mi := indexer.NewMultiIndexer(g, reg, bm, cm, zap.NewNop()) _, err = mi.IndexScoped("", "") @@ -116,8 +113,7 @@ func newSplitProjectWorkspaceServer(t *testing.T, flagOn bool) sharedWSOptions { require.NoError(t, err) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() bm := search.NewBM25() mi := indexer.NewMultiIndexer(g, reg, bm, cm, zap.NewNop()) _, err = mi.IndexScoped("", "") @@ -696,8 +692,7 @@ func newLoneRepoServer(t *testing.T, flagOn bool) (*Server, string) { require.NoError(t, err) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() bm := search.NewBM25() mi := indexer.NewMultiIndexer(g, reg, bm, cm, zap.NewNop()) _, err = mi.IndexScoped("", "") @@ -827,8 +822,7 @@ func newTwoRepoServer(t *testing.T) (*Server, string) { require.NoError(t, err) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() bm := search.NewBM25() mi := indexer.NewMultiIndexer(g, reg, bm, cm, zap.NewNop()) _, err = mi.IndexScoped("", "") diff --git a/internal/mcp/server_test.go b/internal/mcp/server_test.go index 4d313c9a7..14544ac47 100644 --- a/internal/mcp/server_test.go +++ b/internal/mcp/server_test.go @@ -14,13 +14,12 @@ import ( "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" - "github.com/zzet/gortex/internal/config" "os" "path/filepath" + + "github.com/zzet/gortex/internal/config" ) func setupTestServer(t *testing.T) (*Server, string) { @@ -44,8 +43,7 @@ func helper() {} `), 0o644) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) diff --git a/internal/mcp/testregistry_test.go b/internal/mcp/testregistry_test.go new file mode 100644 index 000000000..00df8f632 --- /dev/null +++ b/internal/mcp/testregistry_test.go @@ -0,0 +1,28 @@ +package mcp + +import ( + "sync" + + "github.com/zzet/gortex/internal/parser" + "github.com/zzet/gortex/internal/parser/languages" +) + +// testRegistry returns a package-wide parser.Registry with every language +// extractor registered. RegisterAll recompiles ~30 tree-sitter grammar +// queries (measured ~345ms/call) — sharing one instance across this +// package's many test-server helpers avoids paying that cost at each of +// their call sites. Safe to share: no test in this package registers +// additional extractors on top of RegisterAll, mutates the registry, or +// runs in parallel with another. +var ( + testRegistryOnce sync.Once + testRegistrySingleton *parser.Registry +) + +func testRegistry() *parser.Registry { + testRegistryOnce.Do(func() { + testRegistrySingleton = parser.NewRegistry() + languages.RegisterAll(testRegistrySingleton) + }) + return testRegistrySingleton +} diff --git a/internal/mcp/tool_categories_test.go b/internal/mcp/tool_categories_test.go index ea0ab47f9..87e69fc5b 100644 --- a/internal/mcp/tool_categories_test.go +++ b/internal/mcp/tool_categories_test.go @@ -9,28 +9,28 @@ import ( func TestToolCategory(t *testing.T) { cases := map[string]string{ // prefix-driven - "find_files": toolCatNav, - "search_symbols": toolCatNav, - "edit_file": toolCatEdit, - "write_file": toolCatEdit, - "rename_symbol": toolCatEdit, - "overlay_push": toolCatOverlay, - "subscribe_diagnostics": toolCatSubscription, + "find_files": toolCatNav, + "search_symbols": toolCatNav, + "edit_file": toolCatEdit, + "write_file": toolCatEdit, + "rename_symbol": toolCatEdit, + "overlay_push": toolCatOverlay, + "subscribe_diagnostics": toolCatSubscription, "unsubscribe_diagnostics": toolCatSubscription, - "enrich_churn": toolCatEnrich, - "notebook_save": toolCatMemory, + "enrich_churn": toolCatEnrich, + "notebook_save": toolCatMemory, // override-driven (prefix would mislabel) - "edit_memory": toolCatMemory, - "rename_memory": toolCatMemory, - "smart_context": toolCatNav, - "read_file": toolCatRead, - "get_symbol_source": toolCatRead, - "analyze": toolCatAnalysis, - "review": toolCatReview, - "pr_risk": toolCatPR, - "list_repos": toolCatWorkspace, - "graph_stats": toolCatAdmin, - "tool_profile": toolCatAdmin, + "edit_memory": toolCatMemory, + "rename_memory": toolCatMemory, + "smart_context": toolCatNav, + "read_file": toolCatRead, + "get_symbol_source": toolCatRead, + "analyze": toolCatAnalysis, + "review": toolCatReview, + "pr_risk": toolCatPR, + "list_repos": toolCatWorkspace, + "graph_stats": toolCatAdmin, + "tool_profile": toolCatAdmin, // unclassified "some_unknown_future_tool": toolCatOther, } diff --git a/internal/mcp/tool_presets_test.go b/internal/mcp/tool_presets_test.go index e278d10f8..b0a139eac 100644 --- a/internal/mcp/tool_presets_test.go +++ b/internal/mcp/tool_presets_test.go @@ -11,8 +11,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) @@ -164,8 +162,7 @@ func setupPresetServer(t *testing.T, cfg ToolPolicyConfig) *Server { require.NoError(t, os.WriteFile(filepath.Join(dir, "main.go"), []byte("package app\n\nfunc Main() {}\n"), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() conf := config.Default() idx := indexer.New(g, reg, conf.Index, zap.NewNop()) _, err := idx.Index(dir) diff --git a/internal/mcp/tools_analyze_concurrency_test.go b/internal/mcp/tools_analyze_concurrency_test.go index b1db87393..abaed9872 100644 --- a/internal/mcp/tools_analyze_concurrency_test.go +++ b/internal/mcp/tools_analyze_concurrency_test.go @@ -13,8 +13,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) @@ -26,8 +24,7 @@ import ( func concurrencyServer(t *testing.T) *Server { t.Helper() g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) eng := query.NewEngine(g) diff --git a/internal/mcp/tools_analyze_health_score_test.go b/internal/mcp/tools_analyze_health_score_test.go index e42eea043..e0bb0700b 100644 --- a/internal/mcp/tools_analyze_health_score_test.go +++ b/internal/mcp/tools_analyze_health_score_test.go @@ -94,9 +94,9 @@ func TestAnalyzeHealthScore_CoverageOnly_ScoresCorrectly(t *testing.T) { func TestAnalyzeHealthScore_StaleCodeScoresWorse(t *testing.T) { srv, _ := setupTestServer(t) now := time.Now().Unix() - fresh := now - int64((10 * 24 * time.Hour).Seconds()) // 10 days - stale := now - int64((time.Duration(800*24) * time.Hour).Seconds()) // 800 days - dead := now - int64((time.Duration(1500*24) * time.Hour).Seconds()) // 1500 days + fresh := now - int64((10 * 24 * time.Hour).Seconds()) // 10 days + stale := now - int64((time.Duration(800*24) * time.Hour).Seconds()) // 800 days + dead := now - int64((time.Duration(1500*24) * time.Hour).Seconds()) // 1500 days addHealthFn(srv.graph, "lib.go::Fresh", "lib.go", map[string]any{ "last_authored": map[string]any{"timestamp": fresh, "email": "x@y", "commit": "abc"}, @@ -374,9 +374,9 @@ func TestAnalyzeHealthScore_RecencyCurve(t *testing.T) { }{ {0, 100}, {30, 100}, - {197, 75}, // halfway through the OK band + {197, 75}, // halfway through the OK band {365, 50}, - {730, 25}, // halfway through the stale band + {730, 25}, // halfway through the stale band {1095, 0}, {5000, 0}, } diff --git a/internal/mcp/tools_analyze_infra_test.go b/internal/mcp/tools_analyze_infra_test.go index 2a78550e7..e2a2ec0f3 100644 --- a/internal/mcp/tools_analyze_infra_test.go +++ b/internal/mcp/tools_analyze_infra_test.go @@ -142,7 +142,7 @@ func TestAnalyzeKustomize_OverlayRollup(t *testing.T) { srv, _ := setupTestServer(t) overlay := &graph.Node{ ID: "kustomize::k8s/overlays/staging", Kind: graph.KindKustomization, - Name: "k8s/overlays/staging", + Name: "k8s/overlays/staging", FilePath: "k8s/overlays/staging/kustomization.yaml", StartLine: 1, Meta: map[string]any{"dir": "k8s/overlays/staging"}, } diff --git a/internal/mcp/tools_analyze_missing_fields_test.go b/internal/mcp/tools_analyze_missing_fields_test.go index 7524a3d07..e4f1d65eb 100644 --- a/internal/mcp/tools_analyze_missing_fields_test.go +++ b/internal/mcp/tools_analyze_missing_fields_test.go @@ -165,9 +165,9 @@ func TestMissingFields_IntegrationViaDispatch(t *testing.T) { func TestIsNullableField_AllForms(t *testing.T) { cases := map[string]map[string]any{ - "nullable": {"nullable": true}, - "optional": {"optional": true}, - "omitempty": {"json_tag": `json:"x,omitempty"`}, + "nullable": {"nullable": true}, + "optional": {"optional": true}, + "omitempty": {"json_tag": `json:"x,omitempty"`}, } for name, meta := range cases { n := &graph.Node{Meta: meta} diff --git a/internal/mcp/tools_analyze_new_kinds_test.go b/internal/mcp/tools_analyze_new_kinds_test.go index 1b493074e..c740dd296 100644 --- a/internal/mcp/tools_analyze_new_kinds_test.go +++ b/internal/mcp/tools_analyze_new_kinds_test.go @@ -88,11 +88,11 @@ func TestMineFixCommits_DetectsFixSubjects(t *testing.T) { t.Skip("git not available") } dir := t.TempDir() - mustGit(t, dir,"init", "-q") + mustGit(t, dir, "init", "-q") commit := func(body, msg string) { require.NoError(t, os.WriteFile(filepath.Join(dir, "a.go"), []byte(body), 0o644)) - mustGit(t, dir,"add", "a.go") - mustGit(t, dir,"commit", "-q", "-m", msg) + mustGit(t, dir, "add", "a.go") + mustGit(t, dir, "commit", "-q", "-m", msg) } commit("package a\n", "add feature a") commit("package a\n// v2\n", "fix: nil deref in a") @@ -110,13 +110,13 @@ func TestAnalyzeFixesHistory_EndToEnd(t *testing.T) { t.Skip("git not available") } srv, dir := setupTestServer(t) - mustGit(t, dir,"init", "-q") - mustGit(t, dir,"add", "main.go") - mustGit(t, dir,"commit", "-q", "-m", "initial commit") + mustGit(t, dir, "init", "-q") + mustGit(t, dir, "add", "main.go") + mustGit(t, dir, "commit", "-q", "-m", "initial commit") require.NoError(t, os.WriteFile(filepath.Join(dir, "main.go"), []byte("package main\n\nfunc main() {}\n"), 0o644)) - mustGit(t, dir,"add", "main.go") - mustGit(t, dir,"commit", "-q", "-m", "fix: correct main logic") + mustGit(t, dir, "add", "main.go") + mustGit(t, dir, "commit", "-q", "-m", "fix: correct main logic") out := callAnalyze(t, srv, "fixes_history", map[string]any{}) if got, _ := out["total_fix_commits"].(float64); got < 1 { diff --git a/internal/mcp/tools_analyze_role_test.go b/internal/mcp/tools_analyze_role_test.go index b3f182b40..8c9de6b0d 100644 --- a/internal/mcp/tools_analyze_role_test.go +++ b/internal/mcp/tools_analyze_role_test.go @@ -94,9 +94,9 @@ func TestAnalyzeRole_AdapterDetectedViaCommunities(t *testing.T) { s.analysisMu.Lock() s.communities = &analysis.CommunityResult{ NodeToComm: map[string]string{ - "p/main.go::Run": "c-edge", - "p/svc.go::Process": "c-mid", - "p/util.go::Leaf": "c-core", + "p/main.go::Run": "c-edge", + "p/svc.go::Process": "c-mid", + "p/util.go::Leaf": "c-core", }, } s.analysisMu.Unlock() diff --git a/internal/mcp/tools_ast_test.go b/internal/mcp/tools_ast_test.go index de06332df..4c28493b4 100644 --- a/internal/mcp/tools_ast_test.go +++ b/internal/mcp/tools_ast_test.go @@ -235,8 +235,8 @@ func Cold() { panic("b") } } out := callSearchAST(t, srv, map[string]any{ - "detector": "panic-in-library", - "min_fan_in_of_enclosing_func": float64(2), + "detector": "panic-in-library", + "min_fan_in_of_enclosing_func": float64(2), }) total, _ := out["total"].(float64) if total != 1 { diff --git a/internal/mcp/tools_cfg_test.go b/internal/mcp/tools_cfg_test.go index 9d944d0a1..b8294fb82 100644 --- a/internal/mcp/tools_cfg_test.go +++ b/internal/mcp/tools_cfg_test.go @@ -13,8 +13,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) @@ -45,8 +43,7 @@ var topLevel = 1 ` require.NoError(t, os.WriteFile(filepath.Join(dir, "main.go"), []byte(src), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfgConf := config.Default() idx := indexer.New(g, reg, cfgConf.Index, zap.NewNop()) _, err := idx.Index(dir) diff --git a/internal/mcp/tools_coding_suggest_test.go b/internal/mcp/tools_coding_suggest_test.go index 16112efbe..d490f8ec3 100644 --- a/internal/mcp/tools_coding_suggest_test.go +++ b/internal/mcp/tools_coding_suggest_test.go @@ -12,8 +12,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) @@ -27,8 +25,7 @@ func TestSymbolNotFound_DidYouMean(t *testing.T) { []byte("package app\n\nfunc AlphaHandler() {}\n\nfunc BetaHandler() {}\n"), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) diff --git a/internal/mcp/tools_conflicts_test.go b/internal/mcp/tools_conflicts_test.go index df4259600..f7eab2f57 100644 --- a/internal/mcp/tools_conflicts_test.go +++ b/internal/mcp/tools_conflicts_test.go @@ -148,7 +148,10 @@ func TestConflictsPRs_SuppliedDataYieldsCluster(t *testing.T) { // Both seams fail the test if hit — supplied data must short-circuit. withSeams(t, - func(context.Context, string, forge.ListOpts) ([]forge.PR, error) { t.Fatal("list seam hit"); return nil, nil }, + func(context.Context, string, forge.ListOpts) ([]forge.PR, error) { + t.Fatal("list seam hit") + return nil, nil + }, func(context.Context, string, int) ([]string, error) { t.Fatal("files seam hit"); return nil, nil }, ) @@ -191,7 +194,10 @@ func TestConflictsPRs_DisjointPRsNoCluster(t *testing.T) { // Only PR #1 touches a known file; PR #2 touches an unindexed file with // no symbols → no community → no overlap. withSeams(t, - func(context.Context, string, forge.ListOpts) ([]forge.PR, error) { t.Fatal("list seam hit"); return nil, nil }, + func(context.Context, string, forge.ListOpts) ([]forge.PR, error) { + t.Fatal("list seam hit") + return nil, nil + }, func(context.Context, string, int) ([]string, error) { t.Fatal("files seam hit"); return nil, nil }, ) prsJSON, _ := json.Marshal([]forge.PR{{Number: 1}, {Number: 2}}) @@ -275,7 +281,10 @@ func TestConflictsPRs_GCXTOONBudget(t *testing.T) { filesJSON, _ := json.Marshal(files) withSeams(t, - func(context.Context, string, forge.ListOpts) ([]forge.PR, error) { t.Fatal("list seam hit"); return nil, nil }, + func(context.Context, string, forge.ListOpts) ([]forge.PR, error) { + t.Fatal("list seam hit") + return nil, nil + }, func(context.Context, string, int) ([]string, error) { t.Fatal("files seam hit"); return nil, nil }, ) diff --git a/internal/mcp/tools_contract_bridge_test.go b/internal/mcp/tools_contract_bridge_test.go index 401ab87f8..50c22e0be 100644 --- a/internal/mcp/tools_contract_bridge_test.go +++ b/internal/mcp/tools_contract_bridge_test.go @@ -16,8 +16,6 @@ import ( "github.com/zzet/gortex/internal/contracts" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" "github.com/zzet/gortex/internal/search" ) @@ -125,8 +123,7 @@ func fetchUsers() { cm, err := config.NewConfigManager(tmpCfg) require.NoError(t, err) - preg := parser.NewRegistry() - languages.RegisterAll(preg) + preg := testRegistry() g := graph.New() mi := indexer.NewMultiIndexer(g, preg, search.NewBM25(), cm, zap.NewNop()) diff --git a/internal/mcp/tools_contracts_filter_test.go b/internal/mcp/tools_contracts_filter_test.go index 20f5b013a..9515a15c5 100644 --- a/internal/mcp/tools_contracts_filter_test.go +++ b/internal/mcp/tools_contracts_filter_test.go @@ -14,8 +14,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" "github.com/zzet/gortex/internal/search" ) @@ -68,8 +66,7 @@ func TestHandleContracts_FiltersByProjectAndRef(t *testing.T) { cm, err := config.NewConfigManager(tmpCfg) require.NoError(t, err) - preg := parser.NewRegistry() - languages.RegisterAll(preg) + preg := testRegistry() g := graph.New() mi := indexer.NewMultiIndexer(g, preg, search.NewBM25(), cm, zap.NewNop()) diff --git a/internal/mcp/tools_contracts_test.go b/internal/mcp/tools_contracts_test.go index 90cb8cda7..c3d292b6c 100644 --- a/internal/mcp/tools_contracts_test.go +++ b/internal/mcp/tools_contracts_test.go @@ -16,8 +16,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" "github.com/zzet/gortex/internal/search" ) @@ -90,8 +88,7 @@ func TestHandleContracts_ReflectsRuntimeTrackedRepos(t *testing.T) { cm, err := config.NewConfigManager(tmpCfg) require.NoError(t, err) - preg := parser.NewRegistry() - languages.RegisterAll(preg) + preg := testRegistry() g := graph.New() mi := indexer.NewMultiIndexer(g, preg, search.NewBM25(), cm, zap.NewNop()) @@ -159,8 +156,7 @@ func TestHandleContracts_MatchesGraphContractCount(t *testing.T) { cm, err := config.NewConfigManager(tmpCfg) require.NoError(t, err) - preg := parser.NewRegistry() - languages.RegisterAll(preg) + preg := testRegistry() g := graph.New() mi := indexer.NewMultiIndexer(g, preg, search.NewBM25(), cm, zap.NewNop()) diff --git a/internal/mcp/tools_core_reindex_test.go b/internal/mcp/tools_core_reindex_test.go index 391eb7e2d..1e6ddd12b 100644 --- a/internal/mcp/tools_core_reindex_test.go +++ b/internal/mcp/tools_core_reindex_test.go @@ -66,8 +66,7 @@ func TestHandleReindexRepository_WholeRepoSingleMode(t *testing.T) { []byte("package pkg\n\nfunc Util() {}\n"), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() idx := indexer.New(g, reg, config.Default().Index, zap.NewNop()) _, err := idx.Index(dir) require.NoError(t, err) @@ -109,8 +108,7 @@ func TestHandleReindexRepository_PathScopedSingleMode(t *testing.T) { []byte("package out\n\nfunc B() {}\n"), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() idx := indexer.New(g, reg, config.Default().Index, zap.NewNop()) _, err := idx.Index(dir) require.NoError(t, err) @@ -152,8 +150,7 @@ func TestHandleReindexRepository_RelativePathScoped(t *testing.T) { []byte("package sub\n\nfunc C() {}\n"), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() idx := indexer.New(g, reg, config.Default().Index, zap.NewNop()) _, err := idx.Index(dir) require.NoError(t, err) @@ -187,8 +184,7 @@ func TestHandleReindexRepository_BlankPathsTreatedAsWholeRepo(t *testing.T) { []byte("package main\n\nfunc Main() {}\n"), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() idx := indexer.New(g, reg, config.Default().Index, zap.NewNop()) _, err := idx.Index(dir) require.NoError(t, err) @@ -372,8 +368,7 @@ func TestReindexRepositoryTool_RegisteredAndDiscoverable(t *testing.T) { []byte("package main\n\nfunc Main() {}\n"), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() idx := indexer.New(g, reg, config.Default().Index, zap.NewNop()) _, err := idx.Index(dir) require.NoError(t, err) diff --git a/internal/mcp/tools_dataflow_test.go b/internal/mcp/tools_dataflow_test.go index 4d62e0518..9284e5048 100644 --- a/internal/mcp/tools_dataflow_test.go +++ b/internal/mcp/tools_dataflow_test.go @@ -14,8 +14,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) @@ -46,8 +44,7 @@ func Driver(input string) { ` require.NoError(t, os.WriteFile(filepath.Join(dir, "main.go"), []byte(src), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) @@ -205,8 +202,7 @@ func Driver(name string) { `), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) diff --git a/internal/mcp/tools_extract_candidates_test.go b/internal/mcp/tools_extract_candidates_test.go index 7eb7b4069..abf2a914c 100644 --- a/internal/mcp/tools_extract_candidates_test.go +++ b/internal/mcp/tools_extract_candidates_test.go @@ -205,10 +205,10 @@ func TestExtractCandidates_RationaleSignalNaming(t *testing.T) { line, caller, fanOut int mustContain []string }{ - "very-long": {60, 2, 5, []string{"very long"}}, - "widely-called": {30, 15, 5, []string{"widely called"}}, - "orchestration": {30, 5, 20, []string{"orchestration shape"}}, - "baseline": {21, 2, 5, []string{"long", "multi-caller", "complex body"}}, + "very-long": {60, 2, 5, []string{"very long"}}, + "widely-called": {30, 15, 5, []string{"widely called"}}, + "orchestration": {30, 5, 20, []string{"orchestration shape"}}, + "baseline": {21, 2, 5, []string{"long", "multi-caller", "complex body"}}, } for name, c := range cases { got := buildExtractRationale(c.line, c.caller, c.fanOut) diff --git a/internal/mcp/tools_fileops_repo_test.go b/internal/mcp/tools_fileops_repo_test.go index 82f992f5e..2e13390ca 100644 --- a/internal/mcp/tools_fileops_repo_test.go +++ b/internal/mcp/tools_fileops_repo_test.go @@ -57,9 +57,9 @@ func TestAnchorUnprefixedExisting(t *testing.T) { require.NoError(t, os.MkdirAll(filepath.Dir(p), 0o755)) require.NoError(t, os.WriteFile(p, []byte("package x\n"), 0o644)) } - mustWrite(a, "internal/x.go") // only in repo "alpha" - mustWrite(a, "shared/y.go") // in both repos - mustWrite(b, "shared/y.go") // + mustWrite(a, "internal/x.go") // only in repo "alpha" + mustWrite(a, "shared/y.go") // in both repos + mustWrite(b, "shared/y.go") // mi := fakeRepoRoots{roots: map[string]string{"alpha": a, "beta": b}} // Unique existing match → anchored to the lone owning repo, with the diff --git a/internal/mcp/tools_find_declaration_test.go b/internal/mcp/tools_find_declaration_test.go index 950fccbe6..e3db62067 100644 --- a/internal/mcp/tools_find_declaration_test.go +++ b/internal/mcp/tools_find_declaration_test.go @@ -61,8 +61,7 @@ func Handle() { `) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) diff --git a/internal/mcp/tools_find_files_test.go b/internal/mcp/tools_find_files_test.go index 6a1054d5c..2b6388fae 100644 --- a/internal/mcp/tools_find_files_test.go +++ b/internal/mcp/tools_find_files_test.go @@ -13,8 +13,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) @@ -40,8 +38,7 @@ func setupFindFilesServer(t *testing.T) *Server { write("internal/sub/handler_test.go", "package sub\n\nfunc TestHandle() {}\n") g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) diff --git a/internal/mcp/tools_find_import_path_test.go b/internal/mcp/tools_find_import_path_test.go index bed45d74a..33a0b4997 100644 --- a/internal/mcp/tools_find_import_path_test.go +++ b/internal/mcp/tools_find_import_path_test.go @@ -13,8 +13,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) @@ -37,8 +35,7 @@ func TestFindImportPath_RespectsTargetLanguage(t *testing.T) { []byte("package main\n\nfunc main() {}\n"), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) @@ -77,8 +74,7 @@ func TestFindImportPath_AcceptsQualifiedName(t *testing.T) { []byte("package main\n\nfunc main() {}\n"), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) diff --git a/internal/mcp/tools_flavor_usages_test.go b/internal/mcp/tools_flavor_usages_test.go index 1cd75dd88..f97df3397 100644 --- a/internal/mcp/tools_flavor_usages_test.go +++ b/internal/mcp/tools_flavor_usages_test.go @@ -14,8 +14,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) @@ -39,8 +37,7 @@ func TopLevel() { func helper() {} `), 0o644) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) diff --git a/internal/mcp/tools_generate_skill_test.go b/internal/mcp/tools_generate_skill_test.go index 552bc10ba..f235076ff 100644 --- a/internal/mcp/tools_generate_skill_test.go +++ b/internal/mcp/tools_generate_skill_test.go @@ -237,11 +237,11 @@ func TestGenerateSkill_RejectsNonDirectory(t *testing.T) { func TestSluggify(t *testing.T) { cases := map[string]string{ - "my-skill": "my-skill", - "My Skill": "my-skill", - "my!skill!": "my-skill", - " spaces ": "spaces", - "My_skill.123": "my-skill-123", + "my-skill": "my-skill", + "My Skill": "my-skill", + "my!skill!": "my-skill", + " spaces ": "spaces", + "My_skill.123": "my-skill-123", } for in, want := range cases { assert.Equal(t, want, sluggify(in), "sluggify(%q)", in) diff --git a/internal/mcp/tools_inspections_test.go b/internal/mcp/tools_inspections_test.go index 91ceba3b7..6b48596f5 100644 --- a/internal/mcp/tools_inspections_test.go +++ b/internal/mcp/tools_inspections_test.go @@ -197,7 +197,7 @@ func TestRunInspections_MaxPerInspectionCap(t *testing.T) { s.graph.AddNode(&graph.Node{ ID: "p/extra.go::todo" + string(rune('A'+i)), Kind: graph.KindTodo, FilePath: "p/extra.go", StartLine: i + 1, - Meta: map[string]any{"tag": "TODO", "text": "x"}, + Meta: map[string]any{"tag": "TODO", "text": "x"}, }) } diff --git a/internal/mcp/tools_move_inline_test.go b/internal/mcp/tools_move_inline_test.go index 6f154c137..520ed7f5c 100644 --- a/internal/mcp/tools_move_inline_test.go +++ b/internal/mcp/tools_move_inline_test.go @@ -14,8 +14,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) @@ -39,8 +37,7 @@ func setupMoveInlineRepo(t *testing.T, files map[string]string) (*Server, string } g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) diff --git a/internal/mcp/tools_multi_worktree_test.go b/internal/mcp/tools_multi_worktree_test.go index 83d6b65bf..6b12e795c 100644 --- a/internal/mcp/tools_multi_worktree_test.go +++ b/internal/mcp/tools_multi_worktree_test.go @@ -16,8 +16,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" "github.com/zzet/gortex/internal/search" ) @@ -34,8 +32,7 @@ func newWorktreeMCPServer(t *testing.T, repos ...config.RepoEntry) (*Server, *in cm, err := config.NewConfigManager(tmpCfg) require.NoError(t, err) - preg := parser.NewRegistry() - languages.RegisterAll(preg) + preg := testRegistry() g := graph.New() mi := indexer.NewMultiIndexer(g, preg, search.NewBM25(), cm, zap.NewNop()) _, err = mi.IndexAll() diff --git a/internal/mcp/tools_nav_test.go b/internal/mcp/tools_nav_test.go index d539205cb..980d04d87 100644 --- a/internal/mcp/tools_nav_test.go +++ b/internal/mcp/tools_nav_test.go @@ -14,8 +14,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) @@ -50,8 +48,7 @@ func run() { require.NoError(t, os.WriteFile(filepath.Join(dir, "svc.go"), []byte(src), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) diff --git a/internal/mcp/tools_pr_review_context_test.go b/internal/mcp/tools_pr_review_context_test.go index 8f63ce291..eafdc172d 100644 --- a/internal/mcp/tools_pr_review_context_test.go +++ b/internal/mcp/tools_pr_review_context_test.go @@ -23,8 +23,8 @@ func callPRReviewContext(t *testing.T, srv *Server, ctx context.Context, args ma // prReviewOut is the decoded JSON envelope. type prReviewOut struct { - Verdict string `json:"verdict"` - ChangedSymbols int `json:"changed_symbols"` + Verdict string `json:"verdict"` + ChangedSymbols int `json:"changed_symbols"` ChangedFiles []string `json:"changed_files"` Gates []struct { Name string `json:"name"` diff --git a/internal/mcp/tools_pr_risk_test.go b/internal/mcp/tools_pr_risk_test.go index d2d89d315..7e0afdda1 100644 --- a/internal/mcp/tools_pr_risk_test.go +++ b/internal/mcp/tools_pr_risk_test.go @@ -15,8 +15,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) @@ -158,8 +156,7 @@ func TestPRRisk_BasePath(t *testing.T) { dir := prRiskGitRepo(t) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() idx := indexer.New(g, reg, config.Default().Index, zap.NewNop()) _, err := idx.Index(dir) require.NoError(t, err) diff --git a/internal/mcp/tools_prs_test.go b/internal/mcp/tools_prs_test.go index eb7138863..5a66725da 100644 --- a/internal/mcp/tools_prs_test.go +++ b/internal/mcp/tools_prs_test.go @@ -86,15 +86,15 @@ func TestGetPRImpact_SuppliedFilesNoForge(t *testing.T) { require.False(t, seamHit, "the forge seam must NOT be called when files are supplied") var out struct { - Number int `json:"number"` - Risk string `json:"risk"` - Score float64 `json:"score"` + Number int `json:"number"` + Risk string `json:"risk"` + Score float64 `json:"score"` ChangedFiles []string `json:"changed_files"` ChangedSymbols []struct { ID string `json:"id"` Name string `json:"name"` } `json:"changed_symbols"` - Blast map[string]any `json:"blast"` + Blast map[string]any `json:"blast"` ReviewPriorities []struct { Axis string `json:"axis"` Score float64 `json:"score"` @@ -127,7 +127,10 @@ func TestGetPRImpact_SuppliedFilesNoForge(t *testing.T) { func TestGetPRImpact_ReceiptEmitted(t *testing.T) { srv, file := prToolsTestServer(t) withSeams(t, - func(context.Context, string, forge.ListOpts) ([]forge.PR, error) { t.Fatal("list seam hit"); return nil, nil }, + func(context.Context, string, forge.ListOpts) ([]forge.PR, error) { + t.Fatal("list seam hit") + return nil, nil + }, func(context.Context, string, int) ([]string, error) { t.Fatal("files seam hit"); return nil, nil }, ) filesJSON, _ := json.Marshal([]string{file}) @@ -205,7 +208,10 @@ func TestChangedSymbolsForFiles_RepoPrefixJoin(t *testing.T) { func TestListPRs_ClassifiesSupplied(t *testing.T) { srv, _ := prToolsTestServer(t) withSeams(t, - func(context.Context, string, forge.ListOpts) ([]forge.PR, error) { t.Fatal("list seam hit"); return nil, nil }, + func(context.Context, string, forge.ListOpts) ([]forge.PR, error) { + t.Fatal("list seam hit") + return nil, nil + }, nil, ) @@ -260,7 +266,10 @@ func TestTriagePRs_SortedDescending(t *testing.T) { filesJSON, _ := json.Marshal(filesMap) withSeams(t, - func(context.Context, string, forge.ListOpts) ([]forge.PR, error) { t.Fatal("list seam hit"); return nil, nil }, + func(context.Context, string, forge.ListOpts) ([]forge.PR, error) { + t.Fatal("list seam hit") + return nil, nil + }, func(context.Context, string, int) ([]string, error) { t.Fatal("files seam hit"); return nil, nil }, ) @@ -565,7 +574,10 @@ func triageRows(t *testing.T, srv *Server, hubFile string) (prsJSON, filesJSON s pj, _ := json.Marshal(prs) fj, _ := json.Marshal(map[string][]string{"1": {"pkg/unrelated.go"}, "2": {hubFile}}) withSeams(t, - func(context.Context, string, forge.ListOpts) ([]forge.PR, error) { t.Fatal("list seam hit"); return nil, nil }, + func(context.Context, string, forge.ListOpts) ([]forge.PR, error) { + t.Fatal("list seam hit") + return nil, nil + }, func(context.Context, string, int) ([]string, error) { t.Fatal("files seam hit"); return nil, nil }, ) return string(pj), string(fj) diff --git a/internal/mcp/tools_review_test.go b/internal/mcp/tools_review_test.go index 5899d45ea..d289087db 100644 --- a/internal/mcp/tools_review_test.go +++ b/internal/mcp/tools_review_test.go @@ -16,8 +16,7 @@ import ( "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" "github.com/zzet/gortex/internal/llm" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" + "github.com/zzet/gortex/internal/persistence" "github.com/zzet/gortex/internal/query" "github.com/zzet/gortex/internal/review" ) @@ -74,8 +73,7 @@ func siblingDiffGitRepo(t *testing.T) (root, fileA, fileB, fileC string) { func indexedSiblingServer(t *testing.T, dir string) *Server { t.Helper() g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() idx := indexer.New(g, reg, config.Default().Index, zap.NewNop()) _, err := idx.Index(dir) require.NoError(t, err) @@ -604,8 +602,14 @@ func TestSuppressFinding_SuppressesAcrossReviews(t *testing.T) { dir, file := reviewGitRepo(t) srv := indexedSiblingServer(t, dir) // Wire a sidecar-backed suppression store at a temp cache dir. - srv.InitSuppressions(t.TempDir(), dir) + cacheDir := t.TempDir() + srv.InitSuppressions(cacheDir, dir) require.NotNil(t, srv.suppressions) + t.Cleanup(func() { + sidecar, err := persistence.OpenSidecar(persistence.DefaultSidecarPath(cacheDir)) + require.NoError(t, err) + require.NoError(t, sidecar.Close()) + }) // First review: the finding is present and carries an identity key. out := decodeReview(t, callReview(t, srv, map[string]any{"base": "base-ref"})) diff --git a/internal/mcp/tools_safe_delete_cascade_test.go b/internal/mcp/tools_safe_delete_cascade_test.go index 84142b6d5..959806da7 100644 --- a/internal/mcp/tools_safe_delete_cascade_test.go +++ b/internal/mcp/tools_safe_delete_cascade_test.go @@ -15,8 +15,6 @@ import ( "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" "github.com/zzet/gortex/internal/config" @@ -28,8 +26,7 @@ import ( func indexFixture(t *testing.T, dir string) *Server { t.Helper() g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) diff --git a/internal/mcp/tools_search_corpus_test.go b/internal/mcp/tools_search_corpus_test.go index 33539e664..99d0047c6 100644 --- a/internal/mcp/tools_search_corpus_test.go +++ b/internal/mcp/tools_search_corpus_test.go @@ -14,8 +14,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) @@ -42,8 +40,7 @@ func corpusTestServerProse(t *testing.T, indexProse bool) *Server { "## Troubleshooting\n\nCheck the logs when a request times out.\n"), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() cfg.Index.IndexProse = indexProse idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) diff --git a/internal/mcp/tools_search_docchannel_test.go b/internal/mcp/tools_search_docchannel_test.go index 0530453c2..ac3279f7a 100644 --- a/internal/mcp/tools_search_docchannel_test.go +++ b/internal/mcp/tools_search_docchannel_test.go @@ -13,8 +13,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) @@ -41,8 +39,7 @@ func docChannelServer(t *testing.T) *Server { "To deploy the service push the container image and apply the manifest.\n"), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) diff --git a/internal/mcp/tools_search_text_test.go b/internal/mcp/tools_search_text_test.go index 9f7d8f85e..71c6ad7fb 100644 --- a/internal/mcp/tools_search_text_test.go +++ b/internal/mcp/tools_search_text_test.go @@ -35,8 +35,7 @@ func TestSearchText(t *testing.T) { []byte("package app\n\nfunc Gamma() {}\n"), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) @@ -85,8 +84,7 @@ func TestSearchText_EnclosingSymbol(t *testing.T) { []byte("package app\n\nfunc Alpha() {\n\tprintln(\"needle_here\")\n}\n"), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) @@ -123,8 +121,7 @@ func TestSearchText_PathScoping(t *testing.T) { []byte("package auth\n\n// shared_marker here\n"), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) @@ -457,8 +454,7 @@ func TestSearchText_Regexp(t *testing.T) { []byte("package app\n\nfunc HandleAlpha() {}\n\nfunc HandleBeta() {}\n\nfunc Other() {}\n"), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) diff --git a/internal/mcp/tools_suggest_queries_test.go b/internal/mcp/tools_suggest_queries_test.go index f29a561e8..7694d176b 100644 --- a/internal/mcp/tools_suggest_queries_test.go +++ b/internal/mcp/tools_suggest_queries_test.go @@ -13,8 +13,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) @@ -39,8 +37,7 @@ func main() { require.NoError(t, os.WriteFile(filepath.Join(dir, "main.go"), []byte(src), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) diff --git a/internal/mcp/tools_suggest_reviewers_test.go b/internal/mcp/tools_suggest_reviewers_test.go index 2f742354e..17241bee4 100644 --- a/internal/mcp/tools_suggest_reviewers_test.go +++ b/internal/mcp/tools_suggest_reviewers_test.go @@ -13,8 +13,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) @@ -22,8 +20,7 @@ import ( // RootPath so collectRepoRoots / pickRepoRoot resolve the CODEOWNERS repo. It // indexes nothing. func rootOnlyIndexer(repoRoot string) *indexer.Indexer { - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() idx := indexer.New(graph.New(), reg, config.Default().Index, zap.NewNop()) idx.SetRootPath(repoRoot) return idx diff --git a/internal/mcp/tools_trace_path_test.go b/internal/mcp/tools_trace_path_test.go index 30649de33..f61b438b9 100644 --- a/internal/mcp/tools_trace_path_test.go +++ b/internal/mcp/tools_trace_path_test.go @@ -13,8 +13,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) @@ -38,8 +36,7 @@ func Isolated() {} ` require.NoError(t, os.WriteFile(filepath.Join(dir, "main.go"), []byte(src), 0o644)) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) diff --git a/internal/mcp/tools_untested_test.go b/internal/mcp/tools_untested_test.go index 700d8e69c..0ee5b9ee2 100644 --- a/internal/mcp/tools_untested_test.go +++ b/internal/mcp/tools_untested_test.go @@ -14,8 +14,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" ) @@ -59,8 +57,7 @@ func TestCovered(t *testing.T) { `) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() cfg := config.Default() idx := indexer.New(g, reg, cfg.Index, zap.NewNop()) _, err := idx.Index(dir) diff --git a/internal/mcp/tools_walk_community_test.go b/internal/mcp/tools_walk_community_test.go index 05716d184..2afdce6c6 100644 --- a/internal/mcp/tools_walk_community_test.go +++ b/internal/mcp/tools_walk_community_test.go @@ -11,7 +11,8 @@ import ( ) // seedWalkCommunityGraph injects a two-community call chain: -// x.go::X (comm "alpha") -> y.go::Y (comm "alpha") -> z.go::Z (comm "beta") +// +// x.go::X (comm "alpha") -> y.go::Y (comm "alpha") -> z.go::Z (comm "beta") func seedWalkCommunityGraph(t *testing.T, srv *Server) { t.Helper() g := srv.graph diff --git a/internal/mcp/workspace_isolation_test.go b/internal/mcp/workspace_isolation_test.go index 2384f4a0a..f24b60fa4 100644 --- a/internal/mcp/workspace_isolation_test.go +++ b/internal/mcp/workspace_isolation_test.go @@ -16,8 +16,6 @@ import ( "github.com/zzet/gortex/internal/config" "github.com/zzet/gortex/internal/graph" "github.com/zzet/gortex/internal/indexer" - "github.com/zzet/gortex/internal/parser" - "github.com/zzet/gortex/internal/parser/languages" "github.com/zzet/gortex/internal/query" "github.com/zzet/gortex/internal/search" ) @@ -58,8 +56,7 @@ func newIsolationServer(t *testing.T) (srv *Server, repoA, repoB string) { require.NoError(t, err) g := graph.New() - reg := parser.NewRegistry() - languages.RegisterAll(reg) + reg := testRegistry() bm := search.NewBM25() mi := indexer.NewMultiIndexer(g, reg, bm, cm, zap.NewNop()) _, err = mi.IndexScoped("", "") // index every configured repo