Skip to content

index_repository: root-anchored .gitignore patterns are applied to nested paths, silently excluding tracked source #1205

Description

@simkimsia

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingparsing/qualityGraph extraction bugs, false positives, missing edgespriority/highNeeds near-term maintainer attention; high-impact bug, regression, safety issue, or release blocker.ux/behaviorDisplay bugs, docs, adoption UX

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions