Version
v0.8.1-282-g1cca858 — built from source at commit 1cca858
Platform
macOS 15 (Darwin 24.6.0), arm64
Install channel
Built from source: make -f Makefile.cbm cbm
Binary variant
Standard (no UI). Built without libgit2 (pkg-config libgit2 absent, so HAVE_LIBGIT2 was not set) — I don't believe that's relevant to discovery/ignore handling, but flagging it in case.
What happened, and what did you expect?
A root-anchored .gitignore pattern is applied to nested paths, so index_repository silently excludes tracked source directories that git itself does not ignore.
Under gitignore semantics, a leading / anchors the pattern to the directory containing the .gitignore. So /coverage must match <root>/coverage and must not match <root>/src/routes/coverage. git check-ignore agrees. CBM excludes both.
The effect is silent: the excluded directory appears in excluded.dirs (good), but index_repository still returns status: "indexed", so a consumer can't distinguish "this directory has no symbols" from "this directory was dropped". Every symbol in it is simply absent from the graph.
I hit this on a real SvelteKit app where /coverage (the test-coverage output) is gitignored at the root, and a legitimate route directory happens to be named coverage. That route vanished from the graph with no error.
Reproduction
mkdir -p repro/coverage repro/src/routes/coverage && cd repro
git init -q .
printf '/coverage\n' > .gitignore # ROOT-anchored
printf 'def root_helper():\n return 1\n' > coverage/root_report.py # should be ignored
printf 'def nested_handler():\n return 2\n' > src/routes/coverage/page.py # should NOT be ignored
printf 'def app_main():\n return 3\n' > src/app.py
git add -A && git -c user.email=t@t -c user.name=t commit -qm init
Git's verdict:
$ git check-ignore -q coverage/root_report.py && echo IGNORED
IGNORED
$ git check-ignore -q src/routes/coverage/page.py && echo IGNORED || echo "not ignored"
not ignored
$ git ls-files
.gitignore
src/app.py
src/routes/coverage/page.py # <- tracked
CBM's verdict:
$ codebase-memory-mcp cli index_repository --repo-path . --persistence false
{"excluded":{"dirs":[".git","coverage","src/routes/coverage"], ...}, "nodes":18, ...}
^^^^^^^^^^^^^^^^^^^^^^ should not be here
Resulting graph:
$ sqlite3 -readonly ~/.cache/codebase-memory-mcp/<project>.db \
"SELECT file_path FROM nodes WHERE label='File';"
src/app.py
$ sqlite3 -readonly ... "SELECT name, file_path FROM nodes WHERE label='Function';"
len|<python-builtins>
print|<python-builtins>
app_main|src/app.py
nested_handler is gone. src/routes/coverage/page.py has no File node at all.
Expected: excluded.dirs contains .git and coverage only; src/routes/coverage/page.py is indexed and nested_handler appears as a Function.
Logs
CBM_LOG_LEVEL=info shows nothing beyond the normal pipeline lines — the exclusion isn't logged as a decision, which is part of why it's easy to miss.
Project scale (if relevant)
Trivial for the repro above. Originally found on a ~170-file SvelteKit repo.
One more thing, possibly separate
On that same real repo, 4 of 32 tracked .svelte files produced no nodes. Exactly one is explained by the bug above. The other three are not gitignored, not in excluded.dirs, and not size-related — the largest .svelte in the repo (114,675 bytes) indexes fine while an 8,657-byte file is dropped. Bracketed path segments aren't universally fatal either, since src/routes/[[tab=dashboardTab]]/+page.svelte indexes correctly.
I haven't isolated that one into a minimal repro yet, so I've left it out of the title. Happy to open it separately if you'd prefer — or it may share a root cause with the discovery path above.
Confirmations
- Searched existing issues; didn't find this one.
- Reproduction above is minimal and self-contained.
Version
v0.8.1-282-g1cca858— built from source at commit1cca858Platform
macOS 15 (Darwin 24.6.0), arm64
Install channel
Built from source:
make -f Makefile.cbm cbmBinary variant
Standard (no UI). Built without libgit2 (
pkg-config libgit2absent, soHAVE_LIBGIT2was not set) — I don't believe that's relevant to discovery/ignore handling, but flagging it in case.What happened, and what did you expect?
A root-anchored
.gitignorepattern is applied to nested paths, soindex_repositorysilently excludes tracked source directories that git itself does not ignore.Under gitignore semantics, a leading
/anchors the pattern to the directory containing the.gitignore. So/coveragemust match<root>/coverageand must not match<root>/src/routes/coverage.git check-ignoreagrees. CBM excludes both.The effect is silent: the excluded directory appears in
excluded.dirs(good), butindex_repositorystill returnsstatus: "indexed", so a consumer can't distinguish "this directory has no symbols" from "this directory was dropped". Every symbol in it is simply absent from the graph.I hit this on a real SvelteKit app where
/coverage(the test-coverage output) is gitignored at the root, and a legitimate route directory happens to be namedcoverage. That route vanished from the graph with no error.Reproduction
Git's verdict:
CBM's verdict:
Resulting graph:
nested_handleris gone.src/routes/coverage/page.pyhas noFilenode at all.Expected:
excluded.dirscontains.gitandcoverageonly;src/routes/coverage/page.pyis indexed andnested_handlerappears as aFunction.Logs
CBM_LOG_LEVEL=infoshows nothing beyond the normal pipeline lines — the exclusion isn't logged as a decision, which is part of why it's easy to miss.Project scale (if relevant)
Trivial for the repro above. Originally found on a ~170-file SvelteKit repo.
One more thing, possibly separate
On that same real repo, 4 of 32 tracked
.sveltefiles produced no nodes. Exactly one is explained by the bug above. The other three are not gitignored, not inexcluded.dirs, and not size-related — the largest.sveltein the repo (114,675 bytes) indexes fine while an 8,657-byte file is dropped. Bracketed path segments aren't universally fatal either, sincesrc/routes/[[tab=dashboardTab]]/+page.svelteindexes correctly.I haven't isolated that one into a minimal repro yet, so I've left it out of the title. Happy to open it separately if you'd prefer — or it may share a root cause with the discovery path above.
Confirmations