Skip to content

feat(embeddings): split camelCase identifiers by default and stamp vectors - #26

Open
anvanster wants to merge 3 commits into
mainfrom
feat/split-identifiers
Open

anvanster wants to merge 3 commits into
mainfrom
feat/split-identifiers

Conversation

@anvanster

Copy link
Copy Markdown
Member

Intent

The developer asked to rebase the feat/split-identifiers-by-default branch onto the new main (after PR #25, the watcher/workspace-filter fix, was merged) and address the remaining review findings so it could go back through the no-mistakes gate. The branch makes embeddings split camelCase identifiers by default and gives stored vectors an identity stamp (covering embed-text schema, full-body, split-identifiers and embedding model), so vectors built under a different configuration are not mixed or loaded as current. The three pending findings to fix were: tell an unreadable RocksDB apart from an absent one, so a transient failure does not trigger a destructive claim that deletes a project's vectors; claim the project only after confirming there is rebuild work; and keep the model in the stamp, accepting that changing models re-embeds. Conflicts with main.rs, mcp/engine.rs and mcp/server.rs had to be resolved, keeping both sides' changes. The LSP fullBodyEmbedding default stays false. Implied constraints are no outside contributor code, plain dashes instead of em dashes, conventional commit messages, and pushing only through the no-mistakes gate.

What Changed

  • A new --split-identifiers option is on by default. It also embeds the word-split form of identifiers whose words run together, so getUserById is embedded as "get user by id" as well. Names already separated by _ or - are left as they are. The option is wired through the CLI, the MCP builder, engine config, the --watch daemon and LSP initializationOptions. VS Code gets a codegraph.splitIdentifiers setting and JetBrains gets a settings checkbox. --full-body-embedding and --split-identifiers now take an optional value, so --full-body-embedding=false works; before this change that flag was always true. An auto-spawned engine is now passed both values.
  • Stored vectors are now stamped with the settings that built them: embed-text schema, embedding model, full-body and split-identifiers. A process configured differently never loads a mismatched set. Instead it rebuilds in the background, and it claims the project only once it knows there is work to write. The claim is one atomic step that replaces the old set and writes the new stamp. A RocksDB store that can't be read, for example because it is locked elsewhere, is no longer treated as absent. That case now embeds in memory for the session instead of deleting the project's vectors. A live --watch daemon keeps ownership of its project's vectors. Sessions attached to a daemon whose vectors don't match now report the mismatch instead of "embeddings building".
  • StorageBackend gains scan_prefix_keys, which has a default implementation and is overridden in the memory, namespaced and RocksDB backends. The embed_eval example now parses CODEGRAPH_SPLIT_IDS as a value, not just whether it is present. The READMEs and VS Code setting descriptions explain the stamp, automatic re-embedding when settings change, and that --watch must be restarted after upgrading.

🤖 Generated with Claude Code

Risk Assessment

⚠️ Medium: The change reworks how persisted vectors work, adding a destructive claim step and an identity stamp; I traced the Unreadable, Absent, Mismatched and Loaded paths through the LSP, MCP, daemon-attached and reindex callers and found no wrong-result path, but it rewrites persistence semantics shared by every client, so medium rather than low.

Testing

I rebuilt the server at the target commit and ran five live MCP sessions plus a --watch daemon on an isolated HOME and workspace. Vectors are stamped split=on by default and reload without re-embedding on restart. Changing the split flag makes the stored set Mismatched, so it is rebuilt rather than mixed in. A session whose flags differ from the daemon's now gets the "built with different embedding settings ... Restart the daemon" status instead of "Embeddings are building". A session whose flags match the daemon loads its 8 vectors and returns semantic results. All five passed. The JSON responses, server logs and a combined transcript are in the evidence directory. In the daemon-attached runs every symbol came back twice: the daemon resolved the workspace to /private/tmp (macOS's real path for /tmp), and this change does not touch path handling. Nothing in the worktree changed; only /tmp scratch dirs and evidence files were created.

  • Live validation: ✅ go - 5 of 5 scenarios driven live against the product
Scenario Result Live Evidence
Fresh MCP session with default flags embeds with split identifiers on and stamps the vectors; semantic query 'combine two ordered lists' returns mergeSortedArrays ✅ pass live r2-run1-fresh-default.log/json: 'Split identifiers: true', 'Saved 4 symbol vectors ... split=on, complete', top Semantic hit mergeSortedArrays 0.419
Restarting with the same flags reloads the stamped vectors instead of re-embedding ✅ pass live r2-run2-restart.log: 'Loaded 4 symbol vectors ... split=on' and 'Loaded 4 persisted symbol vectors - semantic search ready', no 'Embedding N symbols' line
Switching to --split-identifiers=false rejects the split=on vectors as Mismatched and re-embeds instead of mixing them ✅ pass live r2-run3-split-off.log: 'No usable symbol vectors (Mismatched, wanted ... split=off)', 'Embedding 4 symbols', 'Saved 4 ... split=off, complete'
Session with different flags attached to a --watch daemon gets a status saying the daemon's vectors were built with different settings and to restart the daemon, not 'Embeddings are building' ✅ pass live r2-run4-session-vs-daemon-mismatch.json embedding_status text; log shows 'Watcher daemon (pid 69673) owns this workspace' and Mismatched; name search for mergeSortedArrays still works
Session with flags matching the --watch daemon loads the daemon's vectors and returns semantic results ✅ pass live r2-run5-session-matches-daemon.log: 'Loaded 8 persisted symbol vectors from daemon-maintained graph'; json embedding_status null, top hit mergeSortedArrays Semantic 0.419
Evidence: Round 2 combined transcript (all scenarios)
Round 2 live MCP transcript (target 3a05fca)
== run1-fresh-default
INFO codegraph_server: Split identifiers: true
INFO codegraph_server::ai_query::engine: [QueryEngine] No usable symbol vectors for 'cgnm3-ws-u5g7-42e5' (Absent, wanted embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on)
INFO codegraph_server::ai_query::engine: [QueryEngine] Embedding 4 symbols (BGE-Small-EN-v1.5 (384d, 512-tok context))...
INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 4 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
INFO codegraph_server::mcp::server: Background embedding generation complete — semantic search ready
  query: combine two ordered lists | status: None | top: [['mergeSortedArrays', 'Semantic', 0.419]]
  query: fetch user by identifier | status: None | top: [['getUserById', 'SymbolName', 0.886]]
== run2-restart
INFO codegraph_server: Split identifiers: true
INFO codegraph_server::ai_query::engine: [QueryEngine] Loaded 4 symbol vectors from graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on)
INFO codegraph_server::mcp::server: Loaded 4 persisted symbol vectors — semantic search ready
INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 4 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
  query: combine two ordered lists | status: None | top: [['mergeSortedArrays', 'Semantic', 0.419]]
  query: fetch user by identifier | status: None | top: [['getUserById', 'SymbolName', 0.886]]
== run3-split-off
INFO codegraph_server: Split identifiers: false
INFO codegraph_server::ai_query::engine: [QueryEngine] No usable symbol vectors for 'cgnm3-ws-u5g7-42e5' (Mismatched, wanted embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=off)
INFO codegraph_server::ai_query::engine: [QueryEngine] Embedding 4 symbols (BGE-Small-EN-v1.5 (384d, 512-tok context))...
INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 4 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=off, complete)
INFO codegraph_server::mcp::server: Background embedding generation complete — semantic search ready
  query: combine two ordered lists | status: None | top: [['mergeSortedArrays', 'Semantic', 0.417]]
== run4-session-vs-daemon-mismatch
INFO codegraph_server: Split identifiers: false
INFO codegraph_server::mcp::server: Watcher daemon (pid 69673) owns this workspace — using its warm graph, skipping reindex
INFO codegraph_server::ai_query::engine: [QueryEngine] No usable symbol vectors for 'cgnm3-ws-u5g7-42e5' (Mismatched, wanted embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=off)
WARN codegraph_server::mcp::server: Watcher daemon's vectors were built from different embed text - semantic search and similarity tools are unavailable this session. Restart the daemon (after an upgrade), or start it with the same --full-body-embedding / --split-identifiers / --embedding-model flags as this session.
  query: combine two ordered lists | status: The --watch daemon's stored vectors were built with different embedding settings, so semantic matching is unavailable this session - results are from name/text search only. Restart the daemon with the same --full-body-embedding / --split-identifiers / --embedding-model flags as this session. | top: []
  query: mergeSortedArrays | status: The --watch daemon's stored vectors were built with different embedding settings, so semantic matching is unavailable this session - results are from name/text search only. Restart the daemon with the same --full-body-embedding / --split-identifiers / --embedding-model flags as this session. | top: [['mergeSortedArrays', 'SymbolName', 1.0]]
== run5-session-matches-daemon
INFO codegraph_server: Split identifiers: true
INFO codegraph_server::mcp::server: Watcher daemon (pid 69673) owns this workspace — using its warm graph, skipping reindex
INFO codegraph_server::ai_query::engine: [QueryEngine] Loaded 8 symbol vectors from graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on)
INFO codegraph_server::mcp::server: Loaded 8 persisted symbol vectors from daemon-maintained graph
  query: combine two ordered lists | status: None | top: [['mergeSortedArrays', 'Semantic', 0.419]]
Evidence: Session vs mismatched daemon: symbol_search response

embedding_status: "The --watch daemon's stored vectors were built with different embedding settings, so semantic matching is unavailable this session - results are from name/text search only. Restart the daemon with the same --full-body-embedding / --split-identifiers / --embedding-model flags as this session."

{
 "combine two ordered lists": {
  "embedding_status": "The --watch daemon's stored vectors were built with different embedding settings, so semantic matching is unavailable this session - results are from name/text search only. Restart the daemon with the same --full-body-embedding / --split-identifiers / --embedding-model flags as this session.",
  "top": []
 },
 "mergeSortedArrays": {
  "embedding_status": "The --watch daemon's stored vectors were built with different embedding settings, so semantic matching is unavailable this session - results are from name/text search only. Restart the daemon with the same --full-body-embedding / --split-identifiers / --embedding-model flags as this session.",
  "top": [
   [
    "mergeSortedArrays",
    "SymbolName",
    1.0
   ],
   [
    "mergeSortedArrays",
    "SymbolName",
    1.0
   ]
  ]
 }
}
Evidence: Session vs mismatched daemon: server log
2026-10-01T04:29:30.690520Z  INFO codegraph_server: Starting CodeGraph MCP server
2026-10-01T04:29:30.690553Z  INFO codegraph_server: Workspaces: ["/tmp/cgnm3-ws.U5g7"]
2026-10-01T04:29:30.690566Z  INFO codegraph_server: Embedding model: BGE-Small-EN-v1.5 (384d, 512-tok context)
2026-10-01T04:29:30.690569Z  INFO codegraph_server: Full-body embedding: true
2026-10-01T04:29:30.690571Z  INFO codegraph_server: Split identifiers: false
2026-10-01T04:29:30.690675Z  INFO codegraph_server::mcp::server: Project slug: cgnm3-ws-u5g7-42e5
2026-10-01T04:29:30.690683Z  INFO codegraph_server::mcp::server: Workspace folders: ["/tmp/cgnm3-ws.U5g7"] (1 total)
2026-10-01T04:29:30.701447Z  INFO codegraph::graph::codegraph: Storage detached — operating in memory-only mode
2026-10-01T04:29:30.701577Z  INFO codegraph_server::mcp::server: Loaded persisted graph (10 nodes) from previous session
2026-10-01T04:29:30.701595Z  INFO codegraph_server::mcp::server: Extension path for models: Some("/tmp")
2026-10-01T04:29:30.701772Z  INFO codegraph_server::mcp::server: MCP server starting...
TEL: {"arch":"aarch64","embeddingModel":"bge-small","event":"mcp.start","os":"macos","version":"0.20.1"}
2026-10-01T04:29:30.701995Z  INFO codegraph_server::mcp::server: Client: nm-test 0
2026-10-01T04:29:30.702342Z  INFO codegraph_server::mcp::server: Watcher daemon (pid 69673) owns this workspace — using its warm graph, skipping reindex
TEL: {"event":"mcp.daemon_attached","os":"macos","version":"0.20.1"}
2026-10-01T04:29:30.702364Z  INFO codegraph_server::memory: [MemoryManager::initialize] Starting initialization
2026-10-01T04:29:30.702369Z  INFO codegraph_server::memory: [MemoryManager::initialize] Workspace path: "/tmp/cgnm3-ws.U5g7"
2026-10-01T04:29:30.702408Z  INFO codegraph_server::memory: [MemoryManager::initialize] Data directory: "/tmp/cgnm3-home.IbRC/.codegraph/projects/cgnm3-ws-u5g7-42e5/memory"
2026-10-01T04:29:30.702466Z  INFO codegraph_server::memory: [MemoryManager::initialize] available memory: 778 MB
2026-10-01T04:29:30.702565Z  INFO codegraph_memory::embedding::fastembed_embed: Loading embedding model: BGE-Small-EN-v1.5 (384d, 512-tok context)
2026-10-01T04:29:31.013844Z  INFO codegraph_memory::embedding::engine: VectorEngine ready (BGE-Small-EN-v1.5 (384d, 512-tok context), 384d)
2026-10-01T04:29:31.014144Z  INFO codegraph_server::memory: [MemoryManager::initialize] Memory initialized at "/tmp/cgnm3-home.IbRC/.codegraph/projects/cgnm3-ws-u5g7-42e5/memory"
2026-10-01T04:29:31.020626Z  INFO codegraph_server::ai_query::engine: [QueryEngine] No usable symbol vectors for 'cgnm3-ws-u5g7-42e5' (Mismatched, wanted embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=off)
2026-10-01T04:29:31.021040Z  WARN codegraph_server::mcp::server: Watcher daemon's vectors were built from different embed text - semantic search and similarity tools are unavailable this session. Restart the daemon (after an upgrade), or start it with the same --full-body-embedding / --split-identifiers / --embedding-model flags as this session.
TEL: {"durationMs":0,"event":"mcp.tool_invoke","ok":true,"tool":"codegraph_symbol_search"}
TEL: {"durationMs":0,"event":"mcp.tool_invoke","ok":true,"tool":"codegraph_symbol_search"}
TEL: {"durationMs":0,"event":"mcp.tool_invoke","ok":true,"tool":"codegraph_symbol_search"}
2026-10-01T04:29:32.583877Z  INFO codegraph_server::mcp::server: Client disconnected
TEL: {"event":"mcp.shutdown","toolCalls":0,"uptimeSeconds":1}
Evidence: Session matching daemon: response
{
 "combine two ordered lists": {
  "embedding_status": null,
  "top": [
   [
    "mergeSortedArrays",
    "Semantic",
    0.419
   ],
   [
    "mergeSortedArrays",
    "Semantic",
    0.419
   ],
   [
    "parseHttpRequestHeaders",
    "Semantic",
    0.282
   ],
   [
    "parseHttpRequestHeaders",
    "Semantic",
    0.282
   ],
   [
    "getUserById",
    "Semantic",
    0.281
   ]
  ]
 }
}
Evidence: Watcher daemon log
2026-10-01T04:29:23.771418Z  INFO codegraph_server::backend: Initializing CodeGraph LSP server
2026-10-01T04:29:23.771592Z  INFO codegraph_server::backend: CodeGraph config: index_on_startup=true, exclude_patterns=[], index_paths=[], max_file_size_kb=1024, embed_on_open=true
2026-10-01T04:29:23.771619Z  INFO codegraph_server::backend: [LSP::initialize] Embedding model: BGE-Small-EN-v1.5 (384d, 512-tok context) (requested: Some(String("bge-small")))
2026-10-01T04:29:23.771632Z  INFO codegraph_server::backend: [LSP::initialize] Client resource path: /tmp
2026-10-01T04:29:23.771645Z  INFO codegraph_server::backend: [LSP::initialize] Full-body embedding: true
2026-10-01T04:29:23.771652Z  INFO codegraph_server::backend: [LSP::initialize] Split identifiers: true
2026-10-01T04:29:23.771659Z  INFO codegraph_server::backend: Workspace folder: /private/tmp/cgnm3-ws.U5g7
2026-10-01T04:29:23.771783Z  INFO codegraph_server::index_state: Loaded index state (1 files) from "/tmp/cgnm3-home.IbRC/.codegraph/projects/cgnm3-ws-u5g7-42e5/index_state.json"
2026-10-01T04:29:23.771793Z  INFO codegraph_server::backend: Loaded previous index state (1 files)
2026-10-01T04:29:23.771869Z ERROR tower_lsp::service::client: failed to send notification
2026-10-01T04:29:23.779273Z  INFO codegraph::graph::codegraph: Storage detached — operating in memory-only mode
2026-10-01T04:29:23.779489Z ERROR tower_lsp::service::client: failed to send notification
2026-10-01T04:29:23.779510Z  INFO codegraph_server::backend: Loaded persisted graph (5 nodes) from previous session
2026-10-01T04:29:23.782503Z  INFO codegraph_server::watcher: [resolve_cross_file] Phase 2 complete: call edges added
2026-10-01T04:29:23.782634Z  INFO codegraph_server::index_state: Saved index state (2 files)
2026-10-01T04:29:23.782706Z ERROR tower_lsp::service::client: failed to send notification
2026-10-01T04:29:23.782757Z  INFO codegraph_server::watcher: [resolve_cross_file] Phase 2 complete: call edges added
2026-10-01T04:29:23.782937Z  INFO codegraph_server::backend: Rebuilt symbol index from persisted graph (2 files)
2026-10-01T04:29:23.786984Z  INFO codegraph::graph::codegraph: Persisting 10 nodes and 8 edges to storage
2026-10-01T04:29:23.788265Z  INFO codegraph::graph::codegraph: Persist complete
2026-10-01T04:29:23.788640Z  INFO codegraph_server::backend: LSP: persisted 10 nodes, 8 edges to graph.db (namespace: cgnm3-ws-u5g7-42e5)
2026-10-01T04:29:23.788653Z  INFO codegraph_server::backend: Graph persisted to RocksDB for next session
2026-10-01T04:29:23.788734Z  INFO codegraph_server::backend: Starting memory store initialization for workspace: /private/tmp/cgnm3-ws.U5g7
2026-10-01T04:29:23.788757Z ERROR tower_lsp::service::client: failed to send notification
2026-10-01T04:29:23.788776Z  INFO codegraph_server::memory: [MemoryManager::initialize] Starting initialization
2026-10-01T04:29:23.788782Z  INFO codegraph_server::memory: [MemoryManager::initialize] Workspace path: "/private/tmp/cgnm3-ws.U5g7"
2026-10-01T04:29:23.788810Z  INFO codegraph_server::memory: [MemoryManager::initialize] Data directory: "/tmp/cgnm3-home.IbRC/.codegraph/projects/cgnm3-ws-u5g7-42e5/memory"
2026-10-01T04:29:23.788860Z  INFO codegraph_server::memory: [MemoryManager::initialize] available memory: 174 MB
2026-10-01T04:29:23.788955Z  INFO codegraph_memory::embedding::fastembed_embed: Loading embedding model: BGE-Small-EN-v1.5 (384d, 512-tok context)
2026-10-01T04:29:23.930074Z  INFO codegraph_memory::embedding::engine: VectorEngine ready (BGE-Small-EN-v1.5 (384d, 512-tok context), 384d)
2026-10-01T04:29:23.930318Z  INFO codegraph_server::memory: [MemoryManager::initialize] Memory initialized at "/tmp/cgnm3-home.IbRC/.codegraph/projects/cgnm3-ws-u5g7-42e5/memory"
2026-10-01T04:29:23.930331Z  INFO codegraph_server::backend: Memory store initialization succeeded
2026-10-01T04:29:23.930354Z ERROR tower_lsp::service::client: failed to send notification
2026-10-01T04:29:23.934413Z  INFO codegraph_server::ai_query::engine: [QueryEngine] No usable symbol vectors for 'cgnm3-ws-u5g7-42e5' (Mismatched, wanted embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on)
2026-10-01T04:29:23.934875Z  INFO codegraph_server::backend: Starting background embedding generation...
2026-10-01T04:29:23.934903Z ERROR tower_lsp::service::client: failed to send notification
2026-10-01T04:29:23.936259Z ERROR tower_lsp::service::client: failed to send notification
2026-10-01T04:29:23.936639Z ERROR tower_lsp::service::client: failed to send notification
2026-10-01T04:29:23.936971Z  INFO codegraph_server::daemon: CodeGraph daemon watching "/private/tmp/cgnm3-ws.U5g7" (slug cgnm3-ws-u5g7-42e5)
TEL: {"arch":"aarch64","event":"daemon.start","os":"macos","rssMb":368,"version":"0.20.1"}
2026-10-01T04:29:23.939569Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Embedding 8 symbols (BGE-Small-EN-v1.5 (384d, 512-tok context))...
2026-10-01T04:29:24.221559Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Built 8 symbol vectors in 286.487208ms
2026-10-01T04:29:24.226910Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 8 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
2026-10-01T04:29:24.227296Z  INFO codegraph_server::backend: Background embedding generation complete
2026-10-01T04:29:24.248764Z  INFO codegraph_server::branch_watcher: Branch watcher initialized: branch=main, commit=fa950c54
2026-10-01T04:29:38.951736Z  INFO codegraph::graph::codegraph: Persisting 10 nodes and 8 edges to storage
2026-10-01T04:29:38.955681Z  INFO codegraph::graph::codegraph: Persist complete
2026-10-01T04:29:38.956620Z  INFO codegraph_server::backend: LSP: persisted 10 nodes, 8 edges to graph.db (namespace: cgnm3-ws-u5g7-42e5)
2026-10-01T04:29:38.966239Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 8 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
2026-10-01T04:29:53.953450Z  INFO codegraph::graph::codegraph: Persisting 10 nodes and 8 edges to storage
2026-10-01T04:29:53.957725Z  INFO codegraph::graph::codegraph: Persist complete
2026-10-01T04:29:53.958727Z  INFO codegraph_server::backend: LSP: persisted 10 nodes, 8 edges to graph.db (namespace: cgnm3-ws-u5g7-42e5)
2026-10-01T04:29:53.968388Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 8 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
2026-10-01T04:30:08.954234Z  INFO codegraph::graph::codegraph: Persisting 10 nodes and 8 edges to storage
2026-10-01T04:30:08.957723Z  INFO codegraph::graph::codegraph: Persist complete
2026-10-01T04:30:08.959761Z  INFO codegraph_server::backend: LSP: persisted 10 nodes, 8 edges to graph.db (namespace: cgnm3-ws-u5g7-42e5)
2026-10-01T04:30:08.980054Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 8 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
2026-10-01T04:30:23.957667Z  INFO codegraph::graph::codegraph: Persisting 10 nodes and 8 edges to storage
2026-10-01T04:30:23.961994Z  INFO codegraph::graph::codegraph: Persist complete
2026-10-01T04:30:23.962904Z  INFO codegraph_server::backend: LSP: persisted 10 nodes, 8 edges to graph.db (namespace: cgnm3-ws-u5g7-42e5)
2026-10-01T04:30:23.971500Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 8 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
2026-10-01T04:30:38.955214Z  INFO codegraph::graph::codegraph: Persisting 10 nodes and 8 edges to storage
2026-10-01T04:30:38.958632Z  INFO codegraph::graph::codegraph: Persist complete
2026-10-01T04:30:38.959544Z  INFO codegraph_server::backend: LSP: persisted 10 nodes, 8 edges to graph.db (namespace: cgnm3-ws-u5g7-42e5)
2026-10-01T04:30:38.968753Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 

... [1715 bytes truncated] ...

graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
2026-10-01T04:31:38.952124Z  INFO codegraph::graph::codegraph: Persisting 10 nodes and 8 edges to storage
2026-10-01T04:31:38.955310Z  INFO codegraph::graph::codegraph: Persist complete
2026-10-01T04:31:38.956188Z  INFO codegraph_server::backend: LSP: persisted 10 nodes, 8 edges to graph.db (namespace: cgnm3-ws-u5g7-42e5)
2026-10-01T04:31:38.965952Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 8 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
2026-10-01T04:31:53.952019Z  INFO codegraph::graph::codegraph: Persisting 10 nodes and 8 edges to storage
2026-10-01T04:31:53.955600Z  INFO codegraph::graph::codegraph: Persist complete
2026-10-01T04:31:53.956640Z  INFO codegraph_server::backend: LSP: persisted 10 nodes, 8 edges to graph.db (namespace: cgnm3-ws-u5g7-42e5)
2026-10-01T04:31:53.966888Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 8 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
2026-10-01T04:32:08.953533Z  INFO codegraph::graph::codegraph: Persisting 10 nodes and 8 edges to storage
2026-10-01T04:32:08.956442Z  INFO codegraph::graph::codegraph: Persist complete
2026-10-01T04:32:08.957301Z  INFO codegraph_server::backend: LSP: persisted 10 nodes, 8 edges to graph.db (namespace: cgnm3-ws-u5g7-42e5)
2026-10-01T04:32:08.966448Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 8 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
2026-10-01T04:32:23.952127Z  INFO codegraph::graph::codegraph: Persisting 10 nodes and 8 edges to storage
2026-10-01T04:32:23.955581Z  INFO codegraph::graph::codegraph: Persist complete
2026-10-01T04:32:23.956568Z  INFO codegraph_server::backend: LSP: persisted 10 nodes, 8 edges to graph.db (namespace: cgnm3-ws-u5g7-42e5)
2026-10-01T04:32:23.966636Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 8 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
2026-10-01T04:32:38.955985Z  INFO codegraph::graph::codegraph: Persisting 10 nodes and 8 edges to storage
2026-10-01T04:32:38.959064Z  INFO codegraph::graph::codegraph: Persist complete
2026-10-01T04:32:38.960297Z  INFO codegraph_server::backend: LSP: persisted 10 nodes, 8 edges to graph.db (namespace: cgnm3-ws-u5g7-42e5)
2026-10-01T04:32:38.968804Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 8 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
2026-10-01T04:32:53.957141Z  INFO codegraph::graph::codegraph: Persisting 10 nodes and 8 edges to storage
2026-10-01T04:32:53.961378Z  INFO codegraph::graph::codegraph: Persist complete
2026-10-01T04:32:53.962287Z  INFO codegraph_server::backend: LSP: persisted 10 nodes, 8 edges to graph.db (namespace: cgnm3-ws-u5g7-42e5)
2026-10-01T04:32:53.971156Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 8 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
2026-10-01T04:33:08.953509Z  INFO codegraph::graph::codegraph: Persisting 10 nodes and 8 edges to storage
2026-10-01T04:33:08.956826Z  INFO codegraph::graph::codegraph: Persist complete
2026-10-01T04:33:08.957904Z  INFO codegraph_server::backend: LSP: persisted 10 nodes, 8 edges to graph.db (namespace: cgnm3-ws-u5g7-42e5)
2026-10-01T04:33:08.967969Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 8 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
2026-10-01T04:33:23.954769Z  INFO codegraph::graph::codegraph: Persisting 10 nodes and 8 edges to storage
2026-10-01T04:33:23.958222Z  INFO codegraph::graph::codegraph: Persist complete
2026-10-01T04:33:23.959098Z  INFO codegraph_server::backend: LSP: persisted 10 nodes, 8 edges to graph.db (namespace: cgnm3-ws-u5g7-42e5)
2026-10-01T04:33:23.968150Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 8 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
2026-10-01T04:33:38.950126Z  INFO codegraph::graph::codegraph: Persisting 10 nodes and 8 edges to storage
2026-10-01T04:33:38.953290Z  INFO codegraph::graph::codegraph: Persist complete
2026-10-01T04:33:38.954283Z  INFO codegraph_server::backend: LSP: persisted 10 nodes, 8 edges to graph.db (namespace: cgnm3-ws-u5g7-42e5)
2026-10-01T04:33:38.965264Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 8 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
2026-10-01T04:33:53.952385Z  INFO codegraph::graph::codegraph: Persisting 10 nodes and 8 edges to storage
2026-10-01T04:33:53.956047Z  INFO codegraph::graph::codegraph: Persist complete
2026-10-01T04:33:53.957070Z  INFO codegraph_server::backend: LSP: persisted 10 nodes, 8 edges to graph.db (namespace: cgnm3-ws-u5g7-42e5)
2026-10-01T04:33:53.967015Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 8 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
2026-10-01T04:34:08.951617Z  INFO codegraph::graph::codegraph: Persisting 10 nodes and 8 edges to storage
2026-10-01T04:34:08.954964Z  INFO codegraph::graph::codegraph: Persist complete
2026-10-01T04:34:08.955924Z  INFO codegraph_server::backend: LSP: persisted 10 nodes, 8 edges to graph.db (namespace: cgnm3-ws-u5g7-42e5)
2026-10-01T04:34:08.965661Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 8 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
2026-10-01T04:34:23.952528Z  INFO codegraph::graph::codegraph: Persisting 10 nodes and 8 edges to storage
2026-10-01T04:34:23.955953Z  INFO codegraph::graph::codegraph: Persist complete
2026-10-01T04:34:23.956964Z  INFO codegraph_server::backend: LSP: persisted 10 nodes, 8 edges to graph.db (namespace: cgnm3-ws-u5g7-42e5)
2026-10-01T04:34:23.966032Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 8 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
2026-10-01T04:34:38.951839Z  INFO codegraph::graph::codegraph: Persisting 10 nodes and 8 edges to storage
2026-10-01T04:34:38.956450Z  INFO codegraph::graph::codegraph: Persist complete
2026-10-01T04:34:38.957579Z  INFO codegraph_server::backend: LSP: persisted 10 nodes, 8 edges to graph.db (namespace: cgnm3-ws-u5g7-42e5)
2026-10-01T04:34:38.966893Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 8 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
2026-10-01T04:34:47.643728Z  INFO codegraph_server::daemon: CodeGraph daemon shutting down
TEL: {"event":"daemon.stop","rssMb":46,"uptimeSeconds":324}
2026-10-01T04:34:47.649566Z  INFO codegraph::graph::codegraph: Persisting 10 nodes and 8 edges to storage
2026-10-01T04:34:47.651156Z  INFO codegraph::graph::codegraph: Persist complete
2026-10-01T04:34:47.651551Z  INFO codegraph_server::backend: LSP: persisted 10 nodes, 8 edges to graph.db (namespace: cgnm3-ws-u5g7-42e5)
2026-10-01T04:34:47.655243Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 8 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
Evidence: Fresh default session log (split on, stamp)
2026-10-01T04:29:05.773101Z  INFO codegraph_server: Starting CodeGraph MCP server
2026-10-01T04:29:05.773259Z  INFO codegraph_server: Workspaces: ["/tmp/cgnm3-ws.U5g7"]
2026-10-01T04:29:05.773315Z  INFO codegraph_server: Embedding model: BGE-Small-EN-v1.5 (384d, 512-tok context)
2026-10-01T04:29:05.773320Z  INFO codegraph_server: Full-body embedding: true
2026-10-01T04:29:05.773322Z  INFO codegraph_server: Split identifiers: true
2026-10-01T04:29:05.773809Z  INFO codegraph_server::mcp::server: Project slug: cgnm3-ws-u5g7-42e5
2026-10-01T04:29:05.773829Z  INFO codegraph_server::mcp::server: Workspace folders: ["/tmp/cgnm3-ws.U5g7"] (1 total)
2026-10-01T04:29:05.783679Z  INFO codegraph::graph::codegraph: Storage detached — operating in memory-only mode
2026-10-01T04:29:05.783872Z  INFO codegraph_server::mcp::server: No persisted graph found — starting fresh
2026-10-01T04:29:05.783913Z  INFO codegraph_server::mcp::server: Extension path for models: Some("/tmp")
2026-10-01T04:29:05.784806Z  INFO codegraph_server::mcp::server: MCP server starting...
TEL: {"arch":"aarch64","embeddingModel":"bge-small","event":"mcp.start","os":"macos","version":"0.20.1"}
2026-10-01T04:29:05.785401Z  INFO codegraph_server::mcp::server: Client: nm-test 0
2026-10-01T04:29:05.786163Z  INFO codegraph_server::mcp::server: Indexing workspace: ["/tmp/cgnm3-ws.U5g7"]
2026-10-01T04:29:05.786376Z  INFO codegraph_server::memory: [MemoryManager::initialize] Starting initialization
2026-10-01T04:29:05.786381Z  INFO codegraph_server::memory: [MemoryManager::initialize] Workspace path: "/tmp/cgnm3-ws.U5g7"
2026-10-01T04:29:05.786417Z  INFO codegraph_server::memory: [MemoryManager::initialize] Data directory: "/tmp/cgnm3-home.IbRC/.codegraph/projects/cgnm3-ws-u5g7-42e5/memory"
2026-10-01T04:29:05.786617Z  INFO codegraph_server::memory: [MemoryManager::initialize] available memory: 0 MB
2026-10-01T04:29:05.786799Z  INFO codegraph_memory::embedding::fastembed_embed: Loading embedding model: BGE-Small-EN-v1.5 (384d, 512-tok context)
2026-10-01T04:29:05.947548Z  INFO codegraph_memory::embedding::engine: VectorEngine ready (BGE-Small-EN-v1.5 (384d, 512-tok context), 384d)
2026-10-01T04:29:05.948053Z  INFO codegraph_server::memory: [MemoryManager::initialize] Memory initialized at "/tmp/cgnm3-home.IbRC/.codegraph/projects/cgnm3-ws-u5g7-42e5/memory"
2026-10-01T04:29:05.953164Z  INFO codegraph_server::watcher: [resolve_cross_file] Phase 2 complete: call edges added
2026-10-01T04:29:05.953512Z  INFO codegraph_server::index_state: Saved index state (1 files)
2026-10-01T04:29:05.957489Z  INFO codegraph::graph::codegraph: Persisting 5 nodes and 4 edges to storage
2026-10-01T04:29:05.958781Z  INFO codegraph::graph::codegraph: Persist complete
2026-10-01T04:29:05.959050Z  INFO codegraph_server::mcp::server: Persisted 5 nodes, 4 edges to graph.db (namespace: cgnm3-ws-u5g7-42e5)
2026-10-01T04:29:05.963074Z  INFO codegraph_server::ai_query::engine: [QueryEngine] No usable symbol vectors for 'cgnm3-ws-u5g7-42e5' (Absent, wanted embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on)
2026-10-01T04:29:05.963365Z  INFO codegraph_server::mcp::server: Starting background embedding generation (4 symbols)...
2026-10-01T04:29:05.963458Z  INFO codegraph_server::mcp::server: Indexed 1 files (1 parsed, 0 skipped)
2026-10-01T04:29:05.965972Z  INFO codegraph_server::mcp::file_watcher: MCP file watcher started (1 directories)
TEL: {"durationMs":0,"event":"mcp.tool_invoke","ok":true,"tool":"codegraph_symbol_search"}
2026-10-01T04:29:05.967441Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Embedding 4 symbols (BGE-Small-EN-v1.5 (384d, 512-tok context))...
2026-10-01T04:29:06.112442Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Built 4 symbol vectors in 148.641041ms
2026-10-01T04:29:06.118188Z  INFO codegraph_server::ai_query::engine: [QueryEngine] Saved 4 symbol vectors to graph.db (namespace: cgnm3-ws-u5g7-42e5, embed text: 3-model=BGE-Small-EN-v1.5 (384d, 512-tok context)-body=on-split=on, complete)
2026-10-01T04:29:06.118443Z  INFO codegraph_server::mcp::server: Background embedding generation complete — semantic search ready
TEL: {"durationMs":33,"event":"mcp.tool_invoke","ok":true,"tool":"codegraph_symbol_search"}
TEL: {"durationMs":7,"event":"mcp.tool_invoke","ok":true,"tool":"codegraph_symbol_search"}
2026-10-01T04:29:08.114396Z  INFO codegraph_server::mcp::server: Client disconnected
TEL: {"event":"mcp.shutdown","toolCalls":0,"uptimeSeconds":2}
  • Evidence: Restart session log (vectors reloaded) (local file: ~/.no-mistakes/evidence/01M3TSRN3TH8FYM6MTAP3ZSWB5/r2-run2-restart.log)
  • Evidence: split=false session log (Mismatched, re-embedded) (local file: ~/.no-mistakes/evidence/01M3TSRN3TH8FYM6MTAP3ZSWB5/r2-run3-split-off.log)
  • Outcome: ⚠️ 1 info across 2 runs (34m59s)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

⚠️ **Review** - medium risk

✅ No issues found.

⚠️ **Test** - 1 info
  • ⚠️ crates/codegraph-server/src/mcp/server.rs:360 - Pre-existing on main (not introduced by this change), but it defeats this change's 'an unreadable store is left alone' guarantee one layer up. If graph.db's RocksDB lock is held by another live process when an MCP session starts, load_persistent_graph treats the failure as corruption. It bumps graph.generation and sweeps the old db to graph.db.corrupt, which drops every project's graph and vectors from the shared store. The session then indexed nothing, because index_state said the files were unchanged, so persisted 0 nodes and symbol_search returned empty results. Reproduced live in run6-locked-store.log. Consider telling lock contention apart from corruption before quarantining.
  • ⚠️ crates/codegraph-server/src/ai_query/engine.rs:1409 - When a session attaches to a --watch daemon whose vectors carry a different stamp (a state new in this change), the server logs that semantic search is unavailable for the whole session. But codegraph_symbol_search still tells the agent 'Embeddings are building in the background. Semantic matching is temporarily unavailable', and no build will ever run. Seen live in run13-session-vs-daemon.json. The status should say the vectors were built with different settings and the daemon needs a restart.
  • Live validation: ✅ go - 8 of 10 scenarios driven live against the product
Scenario Result Live Evidence
User passes --full-body-embedding=false / --split-identifiers=false / bare --split-identifiers and the server accepts them; an invalid value is rejected by clap ✅ pass live cli-flag-parsing.txt
First MCP session with defaults embeds the symbols and saves them stamped model=BGE-Small, body=on, split=on ✅ pass live run1-default-fresh.log
Restarting with the same config loads the 12 stamped vectors without re-embedding, and semantic search is ready immediately ✅ pass live run2-default-restart.log / run2-default-restart.json
Restarting with --split-identifiers=false (and separately --full-body-embedding=false) reports Mismatched, re-embeds and saves under the new stamp ✅ pass live run3-split-off.log, run4-signature-only-split-comparison.txt
Switching --embedding-model to jina-code-v2 (768d) and back never loads the other model's vectors: each switch re-embeds and search returns sane rankings ✅ pass live run5-model-switch.txt
Adversarial: graph.db locked by another process when vectors are read, with a mismatched config - the session embeds in memory only, serves semantic results and leaves the store; the next unlocked ses… ✅ pass live unreadable-store-guard.txt (run8/run9 logs)
Adversarial: a rebuild with a mismatched config on a workspace with no symbols does not claim (clear) the project; restoring the symbols then loads the original set ✅ pass live claim-only-with-work.txt (run10/run11 logs)
A session with different embed settings attaching to a live --watch daemon never claims the daemon's vectors and warns about the mismatch ✅ pass live daemon-ownership.txt (run12/run13 logs)
Split identifiers improves natural-language retrieval of camelCase symbols ⏸️ untested no A meaningful recall measurement needs the author's doc->symbol eval corpus (embed_eval example with labelled datasets), which is not in the repo. Run crates/codegraph-memory/examples/embed_eval.rs wit…
VS Code codegraph.splitIdentifiers setting and the JetBrains checkbox reach the server; the LSP fullBodyEmbedding default stays false ⏸️ untested no Requires launching VS Code / JetBrains with the extension built from this branch and GUI automation (plus macOS Screen Recording permission for screenshots). Neither IDE session was available in this…
  • cargo build -p codegraph-server (dev profile, CARGO_TARGET_DIR=/tmp/cg-nm-target)
  • codegraph-server --full-body-embedding=false | --split-identifiers=false | --split-identifiers | --split-identifiers=maybe --graph-only --run-tool codegraph_symbol_search (CLI parsing)
  • MCP stdio driver (mcp-driver.py): initialize + codegraph_symbol_search over a 12-function TS workspace with HOME=/tmp/cgnm-home and CODEGRAPH_SKIP_MEMORY_CHECK=1
  • Run 1-2: default config on a fresh store, then a restart (stamp written, then reloaded without re-embedding)
  • Run 3-4: --split-identifiers=false, then --full-body-embedding=false with split on/off (Mismatched detected, re-embedded under new stamp)
  • Run 5: --embedding-model jina-code-v2 then back to bge-small (384d/768d sets never mixed)
  • Run 6: graph.db RocksDB LOCK held by another process from before startup (found the pre-existing quarantine behaviour)
  • Run 8-9: RocksDB lock taken after graph load and before the vector read, session with --split-identifiers=false; then unlocked default session
  • Run 10-11: workspace emptied of symbols plus mismatched config, then symbols restored with the default config
  • Run 12-13: --watch daemon (split=on) live, then an MCP session with --split-identifiers=false attaches

🔧 Fix applied.
1 info still open:

  • ℹ️ crates/codegraph-server/src/backend.rs - Unrelated to this change: when MCP sessions and a --watch daemon reach the same workspace through a symlinked path (on macOS, /tmp is a link to /private/tmp), the daemon stores the files under the resolved path. The graph then holds both copies and symbol_search returns every symbol twice (8 vectors for 4 functions). The diff touches no path handling. I did not check whether the base commit behaves the same.
  • Live validation: ✅ go - 5 of 5 scenarios driven live against the product
Scenario Result Live Evidence
Fresh MCP session with default flags embeds with split identifiers on and stamps the vectors; semantic query 'combine two ordered lists' returns mergeSortedArrays ✅ pass live r2-run1-fresh-default.log/json: 'Split identifiers: true', 'Saved 4 symbol vectors ... split=on, complete', top Semantic hit mergeSortedArrays 0.419
Restarting with the same flags reloads the stamped vectors instead of re-embedding ✅ pass live r2-run2-restart.log: 'Loaded 4 symbol vectors ... split=on' and 'Loaded 4 persisted symbol vectors - semantic search ready', no 'Embedding N symbols' line
Switching to --split-identifiers=false rejects the split=on vectors as Mismatched and re-embeds instead of mixing them ✅ pass live r2-run3-split-off.log: 'No usable symbol vectors (Mismatched, wanted ... split=off)', 'Embedding 4 symbols', 'Saved 4 ... split=off, complete'
Session with different flags attached to a --watch daemon gets a status saying the daemon's vectors were built with different settings and to restart the daemon, not 'Embeddings are building' ✅ pass live r2-run4-session-vs-daemon-mismatch.json embedding_status text; log shows 'Watcher daemon (pid 69673) owns this workspace' and Mismatched; name search for mergeSortedArrays still works
Session with flags matching the --watch daemon loads the daemon's vectors and returns semantic results ✅ pass live r2-run5-session-matches-daemon.log: 'Loaded 8 persisted symbol vectors from daemon-maintained graph'; json embedding_status null, top hit mergeSortedArrays Semantic 0.419
  • cargo build -p codegraph-server (CARGO_TARGET_DIR=/tmp/cg-nm-target) at target commit 3a05fca
  • python3 mcp-driver.py '["--full-body-embedding"]': fresh MCP session with default flags on an isolated HOME and git workspace; codegraph_symbol_search for 'combine two ordered lists' / 'fetch user by identifier'
  • Same session restarted with identical flags to check vectors are reloaded, not re-embedded
  • --split-identifiers=false standalone session against the split=on store
  • codegraph-server --watch --full-body-embedding --extension-path /tmp daemon (split on by default) owning the workspace
  • MCP session with --split-identifiers=false attached to the daemon; checked the symbol_search embedding_status text
  • MCP session with flags matching the daemon attached to it; checked that semantic results come back
✅ **Document** - passed

✅ No issues found.

⚠️ **Lint** - 1 info
  • ℹ️ crates/codegraph-memory/examples/embed_eval.rs - cargo fmt --all -- --check fails across about 60 files that existed before this change, mostly the language parser crates, codegraph-harness and codegraph-memory. That includes parts of embed_eval.rs that this change did not touch. The files this change edits in codegraph-server and codegraph storage are rustfmt-clean. Clippy's warnings in backend.rs and mcp/server.rs are also on lines this change did not touch. These were left alone to keep the diff scoped. A separate cargo fmt --all and clippy cleanup commit is worth doing as a follow-up.
✅ **Push** - passed

✅ No issues found.

anvanster and others added 3 commits September 30, 2026 20:57
…s an identity

Natural-language search missed symbols whose names carry the words being
searched for. `getUserById` reaches the embedder as one rare token, so a
query of "get user by id" had little to match.

Identifier splitting

Measured on a doc->symbol retrieval eval, BGE-small, pure semantic R@1:

  camelCase  (TypeScript, 377 symbols)   0.355 -> 0.637   +79%
  PascalCase (Rust, 200 symbols)         0.520 -> 0.640   +23%
  snake_case (Rust, 723 symbols)         0.683 -> 0.692   +1.3%
  snake_case (SystemVerilog, 696)        0.510 -> 0.497   -2.5%

So it applies only where words run together. snake_case and kebab-case
already tokenise into the same words; a leading or trailing delimiter
separates nothing, so `_handleClick` splits like `handleClick`. The Rust
snake-vs-Pascal pair is the controlled comparison: same repo, same docs,
only the casing differs.

Exposed as --split-identifiers, codegraph.splitIdentifiers in VS Code and a
checkbox in JetBrains, wired through the CLI, MCP builder, engine config,
daemon, LSP initializationOptions and the cross-client parity check.

Flags that could not be turned off

`--full-body-embedding` was `#[arg(long, default_value = "true")]` on a
bool, which clap parses as a flag that rejects a value: always true, and
`=false` errored. Both it and --split-identifiers now take an optional
value.

Vector identity

Stored vectors had no record of what produced them, so nothing could tell
whether they were comparable to the ones a process was about to make.
Switching --embedding-model was the sharpest case: there is no dimension
check anywhere, and cosine_similarity zips its inputs, so a 768d query
against a stored 384d vector silently scored a dot product over the first
384 dimensions against norms of different lengths. Semantic ranking was
garbage, with no error, until a manual reindex. Present before this change.

Vectors are now stamped with the schema, model, full-body and split
settings that built them, and a mismatched set is never loaded.

- A rebuild takes ownership of the project once, after it knows it has
  something to write, in one atomic step that replaces the stored set and
  writes its stamp. Saves only add; writes are chunked so a save under
  memory pressure does not triple the footprint; checkpoints keep a crashed
  rebuild resumable.
- A store that cannot be read is left alone. graph.db is one RocksDB shared
  by every project, and a lock held elsewhere reads exactly like an absent
  store; treating it as absent claimed the project and cleared a valid set.
  An unreadable store now embeds in memory for the session.
- A live --watch daemon owns its project's vectors; sessions never claim
  over it, and the daemon carries the same embed-text settings as the
  sessions that read from it.
- An auto-spawned engine is passed --full-body-embedding and
  --split-identifiers with their values. Both are in the stamp, so an engine
  started with defaults would have served its client no vectors at all.

An index written by 0.20.1 or earlier carries no stamp and is re-embedded
the first time this version opens it. A --watch daemon left running across
the upgrade keeps writing unstamped vectors that this build will not load;
restart it after upgrading.

Known trade-off: an LSP client that omits fullBodyEmbedding still defaults
it off, unlike every other client. VS Code and JetBrains always send it;
a bare nvim/emacs/helix client and an IDE client on the same project would
replace each other's vector set. Aligning the default would move every
bare client to ~3x slower indexing, so it is left and documented in place.

Also: the eval harness read CODEGRAPH_SPLIT_IDS with is_ok(), so `=0`
enabled it and an A/B run had two identical arms; StorageBackend gains
scan_prefix_keys with a default body so out-of-tree backends still compile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017rVbt7rENTwXkdHt3Bpgb5
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown

🔍 CodeGraph PR Review

23 files changed (+1223/−185, 68 functions) · Risk: 🔴 high

Blast radius

117 direct callers affected (55 breaking) across codegraph-server/src/ai_query, codegraph-server/src/domain, codegraph-server/src/handlers, codegraph-server/src/mcp, codegraph/jetbrains/ui

⚠️ Test gaps (28 functions, 0 coverage)

  • claim_vector_set (crates/codegraph-server/src/ai_query/engine.rs) — signature_changed
  • full_body_enabled (crates/codegraph-server/src/ai_query/engine.rs) — signature_changed
  • set_split_identifiers (crates/codegraph-server/src/ai_query/engine.rs) — signature_changed
  • save_symbol_vectors (crates/codegraph-server/src/ai_query/engine.rs) — signature_changed
  • embed_stamp (crates/codegraph-server/src/ai_query/engine.rs) — signature_changed
  • save_vectors_map (crates/codegraph-server/src/ai_query/engine.rs) — signature_changed
  • vector_key_node (crates/codegraph-server/src/ai_query/engine.rs) — signature_changed
  • build_symbol_vectors_checkpointed (crates/codegraph-server/src/ai_query/engine.rs) — body_changed
  • project_owner (crates/codegraph-server/src/ai_query/engine.rs) — signature_changed
  • split_identifiers_enabled (crates/codegraph-server/src/ai_query/engine.rs) — signature_changed
  • …and 18 more

Suggested reviewers

Andrey Vasilevsky (164 lines), anvanster (30 lines)

Suggested commit: feat(ai_query): <describe the change> · 46 tests cover the changes
🤖 Generated by CodeGraph

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant