Env: codegraph 1.5.0 (win32-x64).
codegraph affected reports no tests for a Go file that has a sibling _test.go. It exits 0 with a plausible message, so it reads as "this code has no test coverage" rather than as a failure.
Repro
Two-file Go project:
// go.mod: module example.com/demo
// math.go
package demo
func Add(a, b int) int { return a + b }
// math_test.go
package demo
import "testing"
func TestAdd(t *testing.T) { if Add(1, 2) != 3 { t.Fatal("boom") } }
$ codegraph init .
● 5 nodes, 4 edges in 271ms
$ codegraph affected math.go
ℹ No test files affected by the changed files. # <- expected math_test.go
$ codegraph affected --filter '*_test.go' math.go
Affected test files (1):
math_test.go # <- found, so only the predicate is wrong
The graph itself knows perfectly well:
$ codegraph node Add
**Called by ←** TestAdd (math_test.go:5)
Same shape in TypeScript works with the default glob, which isolates it to the Go naming convention:
# math.ts + math.test.ts
$ codegraph affected math.ts
Affected test files (1):
math.test.ts
Root cause
The affected command defines its own isTestFile inline instead of importing the shared one. In src/bin/codegraph.ts, inside the affected action:
const defaultTestPatterns = [
/\.spec\./, /\.test\./, /\/__tests__\//, /\/tests?\//, /\/e2e\//, /\/spec\//,
];
function isTestFile(filePath) {
if (customFilter) return customFilter.test(filePath);
return defaultTestPatterns.some(p => p.test(filePath));
}
All six are JS/TS conventions. Go uses an underscore suffix — math_test.go — which matches none of them (/\.test\./ needs a dot on both sides; Go has _test.).
Meanwhile src/search/query-utils.ts already ships a correct multi-language isTestFile, which is what explore / node / search use:
/[._-](test|tests|spec|specs)\.[a-z0-9]+$/.test(lowerName) // math_test.go, math.test.ts, math-spec.rb
lowerName.startsWith('test_') // test_math.py
/(?:Test|Tests|TestCase|Tester|Spec|Specs)\.[A-Za-z0-9]+$/ // MathTest.kt, MathTests.swift
Its comments name foo_test.go explicitly, and it even guards against false positives like latest.kt / manifest.kt. So affected is the only blind path — it never asks the shared helper.
Probably why this survived: affected is CLI-only (there is no codegraph_affected MCP tool), so agents never exercise it, and agents are the primary consumer.
Secondary: --filter uncovers an unrelated over-reporting problem
On a real-world Go repo (a few hundred files), working around the bug with --filter '*_test.go' swings the other way — the result includes test files from packages with no relationship to the changed file.
--filter only swaps the is-this-a-test predicate; the dependent BFS still runs at the default --depth 5, and five hops of transitive dependents reach most of a Go tree. The broken default glob was masking this, so the two problems cancelled into empty-but-believable output.
Suggested fix
Delete the local defaultTestPatterns / isTestFile in src/bin/codegraph.ts and import isTestFile from src/search/query-utils.ts. That one already covers Go / Python / Java / Kotlin / Swift / C# / Scala, so this is a one-line import rather than a second pattern list to keep in sync.
For the second half, a smaller default --depth for affected — or a note that 5 is very wide for compiled languages where package-level dependents fan out fast — would make the output usable.
Env: codegraph 1.5.0 (win32-x64).
codegraph affectedreports no tests for a Go file that has a sibling_test.go. It exits 0 with a plausible message, so it reads as "this code has no test coverage" rather than as a failure.Repro
Two-file Go project:
The graph itself knows perfectly well:
Same shape in TypeScript works with the default glob, which isolates it to the Go naming convention:
Root cause
The
affectedcommand defines its ownisTestFileinline instead of importing the shared one. Insrc/bin/codegraph.ts, inside theaffectedaction:All six are JS/TS conventions. Go uses an underscore suffix —
math_test.go— which matches none of them (/\.test\./needs a dot on both sides; Go has_test.).Meanwhile
src/search/query-utils.tsalready ships a correct multi-languageisTestFile, which is whatexplore/node/searchuse:Its comments name
foo_test.goexplicitly, and it even guards against false positives likelatest.kt/manifest.kt. Soaffectedis the only blind path — it never asks the shared helper.Probably why this survived:
affectedis CLI-only (there is nocodegraph_affectedMCP tool), so agents never exercise it, and agents are the primary consumer.Secondary:
--filteruncovers an unrelated over-reporting problemOn a real-world Go repo (a few hundred files), working around the bug with
--filter '*_test.go'swings the other way — the result includes test files from packages with no relationship to the changed file.--filteronly swaps the is-this-a-test predicate; the dependent BFS still runs at the default--depth 5, and five hops of transitive dependents reach most of a Go tree. The broken default glob was masking this, so the two problems cancelled into empty-but-believable output.Suggested fix
Delete the local
defaultTestPatterns/isTestFileinsrc/bin/codegraph.tsand importisTestFilefromsrc/search/query-utils.ts. That one already covers Go / Python / Java / Kotlin / Swift / C# / Scala, so this is a one-line import rather than a second pattern list to keep in sync.For the second half, a smaller default
--depthforaffected— or a note that 5 is very wide for compiled languages where package-level dependents fan out fast — would make the output usable.