You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Silent index degradation — status:"indexed" but only ~500 nodes for 72k LOC Rust codebase #333
index_repository(mode="full") returns status:"indexed" but produces only ~500 nodes and ~500 edges for a 72k LOC Rust codebase. Expected ~5,000–10,000+ symbol nodes based on comparable smaller projects.
The status:"ready" / status:"indexed" response is misleading — the rebuild silently fails on something but reports success.
Reproduction
Kill any existing codebase-memory-mcp processes: ps aux | grep codebase-memory then kill <PID>
This looks like the same durability issue as #334 (note the near-identical counts — 469/540/572 — and 9-Rust-file setup). The varying low node count across fresh rebuilds points to non-deterministic write loss (uncheckpointed WAL under synchronous=OFF, often from a hard-killed sibling process), not a deterministic parser cap — I checked, there's no per-file size/node cap that would deterministically clip a large file.
v0.7.0 (#277) checkpoints the WAL on close and recovers a stale WAL on open, which should resolve the stranded-write loss. Could you retest on v0.7.0? If a clean full index still yields ~500 nodes for the 72k-LOC project, please share ls -l of the cache dir right after (so I can see if data is stranded in .db-wal) and, if possible, the repo or a representative large Rust file — then I can add a deterministic regression test. I'm also proposing an extracted-vs-persisted plausibility check over in #334 to make this fail loudly instead of silently; your input there welcome. Leaving open pending retest. 🙏
Thanks for the data point. Important context here: Rust is currently a tree-sitter-only language in codebase-memory-mcp — it is not one of the hybrid-LSP languages (Python, TypeScript/JavaScript, PHP, C#, Go, C/C++). That means Rust gets structural definition extraction from the vendored tree-sitter grammar, but not the deeper LSP-backed symbol resolution and cross-file call-graph edges the hybrid languages get. So a lower node/edge count on a large Rust codebase is expected to a degree — though ~500 nodes for 72k LOC does sound lower than tree-sitter alone should yield, which points at gaps in the Rust extraction query (e.g. impl methods, trait methods, associated functions, macro-defined items).
This is a parsing/extraction completeness gap rather than the index-corruption class the rest of this umbrella tracks — the index isn't corrupt, Rust extraction is just shallow. To target it I'd like to know, on v0.7.0: roughly how many nodes you get now, and which symbol kinds are missing (free functions? impl methods? structs/enums? trait defs?). A pointer to the (public) Rust repo you tested would let me reproduce and tighten the tree-sitter query directly. Reclassifying this as a Rust-extraction-depth issue and keeping it open on that basis. Thanks!
I dug into this empirically — built v0.7.0 and indexed a large pure-Rust OSS repo (ripgrep, 100 .rs files / 52k LOC) to test whether Rust extraction itself under-produces:
nodes=4581 edges=13509 errors=0 → ~88 nodes/kLOC
Label breakdown was healthy: 2,039 Method, 697 Function, 356 Class (structs), 70 Enum, 608 Field, 7 Interface (traits). The single largest file (7,779 LOC) alone produced 985 nodes (~1 node / 8 LOC). So the Rust tree-sitter extraction is not generically broken — your ~500 nodes for 72k LOC is ~7 nodes/kLOC, 12× lower than a normal Rust repo, which points at something specific to your codebase rather than the parser.
Two likely causes, and one is easy to confirm:
File-discovery exclusion — if a .gitignore/.cbmignore pattern (or the workspace layout) is excluding most of your .rs files, discover only sees a few. Check your index log for pipeline.discover files=N — if N is small (tens, not hundreds), that's it.
Macro-heavy code — tree-sitter cannot see definitions that live inside macro invocations (it doesn't expand macros). I confirmed this on ripgrep itself: its macro-based test files (rgtest!(name, …)) extracted 0 functions despite 1,700+ LOC. If your codebase leans heavily on framework/proc macros (actix-web, diesel, rocket, sqlx, impl_trait!-style DSLs, generated code), large swaths become invisible and the node count collapses.
Could you paste these two lines from your index run? They pinpoint it immediately:
pipeline.discover ... files=…
parallel.extract ... done nodes=… errors=…
If files= is correct but nodes= is ~500, it's the macro blind spot (a known tree-sitter limitation we can discuss heuristics for). If files= is tiny, it's a discovery/ignore issue we can fix directly. Thanks — this'll let us nail it without your private repo.
If its 2.: I already have the Rust LSP Hybrid in the works. Could potentially fix this, but we will need to double check, not sure though when I can ship this. Could take one or two weeks
Update: the Rust LSP hybrid mentioned above shipped in v0.8.0 (current is v0.8.1) — Rust extraction now runs through the same hybrid-LSP path as TypeScript/Python/Go instead of tree-sitter-only.
Could you reindex the 72k-LOC Rust repo on v0.8.1 and post the resulting node/edge counts? If it still lands around ~500 nodes, the index log (pipeline.done and gbuf.dump nodes=… edges=… lines) would pin down where extraction stops. Thanks!
So it's not reproducible — 29,594 nodes, and the symbol I reported missing (apply_knight_hero_effects) now resolves with full metadata.
Most useful data point: I think your first comment had it right — this was the WAL-durability class (#334), not extraction depth. Two reasons:
Before I even upgraded, the same v0.6.0 binary had already self-recovered to ~29.6k nodes (from the original ~500) with no code or version change. A deterministic extraction gap can't self-heal like that — but stranded-WAL write loss can, which matches the varying 469/540/572 counts you flagged.
I found 12 orphaned codebase-memory-mcp processes still running on macOS from rapid session churn — the exact killed-sibling / uncheckpointed-WAL scenario. Clearing them + a clean rebuild fixed it.
On the extraction-depth hypotheses from comments 2–3, for the record on this codebase: files=948 rules out discovery exclusion, and ground-truth grep -c 'fn ' vs the graph shows every production .rs file fully captured (graph symbols ≥ raw fn count in all of them — e.g. combat.rs 205 graph / 71 fns over 19.7k LOC; it's just a monolith of very large functions). It's also a free-function-heavy codebase (almost no impl blocks), so the impl/trait-method concern doesn't apply here.
Net: #387's WAL checkpoint-on-close looks like the correct fix. v0.8.1 node count is flat vs v0.6.0 (29,598 → 29,594) but edges jumped 36,233 → 46,487 (+28%) from the LSP hybrid's cross-file edges — nice bonus. Happy to keep an eye out for any recurrence under session churn now that the orphan-process pileup is cleared.
This issue now has a first-class, durable reproduction in the cumulative bug-reproduction suite landing in #667 — a test that pins the exact failing behaviour, so it's tracked and guarded against silent regression. Where #667 also lands the root-cause fix, that's called out in the PR; otherwise the reproduction makes the eventual fix straightforward and verifiable.
The reproduction goes live once #667 merges. (Posted from the release branch's QA pass.)
Thank you so much, @nguiaSoren, for coming back with such a thorough retest! The before/after counts, the orphan-process finding and the per-file fn cross-check made the diagnosis unusually clear.
Your conclusion is right: this was the WAL-durability class (#334), and the checkpoint-on-close and stale-WAL recovery work fixed it. Rust extraction depth was not the cause. Since you confirmed it no longer reproduces, I'm closing this as fixed. If a node count ever collapses again under session churn, please reopen with the pipeline.discover and gbuf.dump lines.
Activity
DeusData commentedon May 31, 2026
This looks like the same durability issue as #334 (note the near-identical counts — 469/540/572 — and 9-Rust-file setup). The varying low node count across fresh rebuilds points to non-deterministic write loss (uncheckpointed WAL under
synchronous=OFF, often from a hard-killed sibling process), not a deterministic parser cap — I checked, there's no per-file size/node cap that would deterministically clip a large file.v0.7.0 (#277) checkpoints the WAL on close and recovers a stale WAL on open, which should resolve the stranded-write loss. Could you retest on v0.7.0? If a clean full index still yields ~500 nodes for the 72k-LOC project, please share
ls -lof the cache dir right after (so I can see if data is stranded in.db-wal) and, if possible, the repo or a representative large Rust file — then I can add a deterministic regression test. I'm also proposing an extracted-vs-persisted plausibility check over in #334 to make this fail loudly instead of silently; your input there welcome. Leaving open pending retest. 🙏DeusData commentedon May 31, 2026
Thanks for the data point. Important context here: Rust is currently a tree-sitter-only language in codebase-memory-mcp — it is not one of the hybrid-LSP languages (Python, TypeScript/JavaScript, PHP, C#, Go, C/C++). That means Rust gets structural definition extraction from the vendored tree-sitter grammar, but not the deeper LSP-backed symbol resolution and cross-file call-graph edges the hybrid languages get. So a lower node/edge count on a large Rust codebase is expected to a degree — though ~500 nodes for 72k LOC does sound lower than tree-sitter alone should yield, which points at gaps in the Rust extraction query (e.g.
implmethods, trait methods, associated functions, macro-defined items).This is a parsing/extraction completeness gap rather than the index-corruption class the rest of this umbrella tracks — the index isn't corrupt, Rust extraction is just shallow. To target it I'd like to know, on v0.7.0: roughly how many nodes you get now, and which symbol kinds are missing (free functions?
implmethods? structs/enums? trait defs?). A pointer to the (public) Rust repo you tested would let me reproduce and tighten the tree-sitter query directly. Reclassifying this as a Rust-extraction-depth issue and keeping it open on that basis. Thanks!DeusData commentedon Jun 1, 2026
I dug into this empirically — built v0.7.0 and indexed a large pure-Rust OSS repo (ripgrep, 100
.rsfiles / 52k LOC) to test whether Rust extraction itself under-produces:Label breakdown was healthy: 2,039 Method, 697 Function, 356 Class (structs), 70 Enum, 608 Field, 7 Interface (traits). The single largest file (7,779 LOC) alone produced 985 nodes (~1 node / 8 LOC). So the Rust tree-sitter extraction is not generically broken — your ~500 nodes for 72k LOC is ~7 nodes/kLOC, 12× lower than a normal Rust repo, which points at something specific to your codebase rather than the parser.
Two likely causes, and one is easy to confirm:
.gitignore/.cbmignorepattern (or the workspace layout) is excluding most of your.rsfiles, discover only sees a few. Check your index log forpipeline.discover files=N— if N is small (tens, not hundreds), that's it.rgtest!(name, …)) extracted 0 functions despite 1,700+ LOC. If your codebase leans heavily on framework/proc macros (actix-web, diesel, rocket, sqlx,impl_trait!-style DSLs, generated code), large swaths become invisible and the node count collapses.Could you paste these two lines from your index run? They pinpoint it immediately:
pipeline.discover ... files=…parallel.extract ... done nodes=… errors=…If
files=is correct butnodes=is ~500, it's the macro blind spot (a known tree-sitter limitation we can discuss heuristics for). Iffiles=is tiny, it's a discovery/ignore issue we can fix directly. Thanks — this'll let us nail it without your private repo.DeusData commentedon Jun 1, 2026
If its 2.: I already have the Rust LSP Hybrid in the works. Could potentially fix this, but we will need to double check, not sure though when I can ship this. Could take one or two weeks
DeusData commentedon Jun 12, 2026
Update: the Rust LSP hybrid mentioned above shipped in v0.8.0 (current is v0.8.1) — Rust extraction now runs through the same hybrid-LSP path as TypeScript/Python/Go instead of tree-sitter-only.
Could you reindex the 72k-LOC Rust repo on v0.8.1 and post the resulting node/edge counts? If it still lands around ~500 nodes, the index log (
pipeline.doneandgbuf.dump nodes=… edges=…lines) would pin down where extraction stops. Thanks!nguiaSoren commentedon Jun 13, 2026
Retested on v0.8.1 (was still on 0.6.0 — sorry for the delay). Clean full index of the 72k-LOC Rust repo:
So it's not reproducible — 29,594 nodes, and the symbol I reported missing (
apply_knight_hero_effects) now resolves with full metadata.Most useful data point: I think your first comment had it right — this was the WAL-durability class (#334), not extraction depth. Two reasons:
codebase-memory-mcpprocesses still running on macOS from rapid session churn — the exact killed-sibling / uncheckpointed-WAL scenario. Clearing them + a clean rebuild fixed it.On the extraction-depth hypotheses from comments 2–3, for the record on this codebase:
files=948rules out discovery exclusion, and ground-truthgrep -c 'fn 'vs the graph shows every production.rsfile fully captured (graph symbols ≥ raw fn count in all of them — e.g. combat.rs 205 graph / 71 fns over 19.7k LOC; it's just a monolith of very large functions). It's also a free-function-heavy codebase (almost noimplblocks), so the impl/trait-method concern doesn't apply here.Net: #387's WAL checkpoint-on-close looks like the correct fix. v0.8.1 node count is flat vs v0.6.0 (29,598 → 29,594) but edges jumped 36,233 → 46,487 (+28%) from the LSP hybrid's cross-file edges — nice bonus. Happy to keep an eye out for any recurrence under session churn now that the orphan-process pileup is cleared.
test(repro): Rust trait-method extraction depth for #333
DeusData commentedon Jun 28, 2026
This issue now has a first-class, durable reproduction in the cumulative bug-reproduction suite landing in #667 — a test that pins the exact failing behaviour, so it's tracked and guarded against silent regression. Where #667 also lands the root-cause fix, that's called out in the PR; otherwise the reproduction makes the eventual fix straightforward and verifiable.
The reproduction goes live once #667 merges. (Posted from the release branch's QA pass.)
DeusData commentedon Sep 26, 2026
Thank you so much, @nguiaSoren, for coming back with such a thorough retest! The before/after counts, the orphan-process finding and the per-file
fncross-check made the diagnosis unusually clear.Your conclusion is right: this was the WAL-durability class (#334), and the checkpoint-on-close and stale-WAL recovery work fixed it. Rust extraction depth was not the cause. Since you confirmed it no longer reproduces, I'm closing this as fixed. If a node count ever collapses again under session churn, please reopen with the
pipeline.discoverandgbuf.dumplines.