neuralmind.uk / NeuralMind v4.4.0 — the index is never silently out of step with the code Edit this page on GitHub ↗

NeuralMind v4.4.0 — the index is never silently out of step with the code

Type: Minor release Theme: index freshness

On a real 383-file repository, v4.3.5 answered from a five-month-old code graph and reported every check as [ok]. The committed graphify-out/graph.json had been built on Windows (tests\... paths), lacked every module added since, and NeuralMind never regenerates a graphify graph. Escaping it took a hand-written graphgen.build_graph() call and deleting the vector folder by hand. After switching graphs, the store still held ~2,900 vectors from the old graph that search could return.

v4.4.0 closes that trap. One rule runs through every change: when the index can’t be brought in step automatically, it says so — in doctor, health, build and the agent’s first MCP call.

What changed

  Before (v4.3.5) Now (v4.4.0)
Graph vs disk doctor checked only nodes carrying embedded_at, which graphify nodes never have → [ok] New freshness check compares graph and files both ways, whatever tool made the graph
Escaping a stale graphify graph No CLI way; deleting .neuralmind/graph.json silently fell back to the stale legacy graph build --regenerate-graph, a graph_source setting, and no silent fallback
Orphaned vectors build (even --force) never deleted vectors whose node left the graph Every build purges them, with a safety valve; doctor FAILs on extra vectors
Read paths Every CLI query and each MCP server’s first call ran a full build() — re-walking the repo and printing to stdout, the MCP JSON-RPC channel Queries load the index as it stands: no rebuild, no output

1. Graph freshness check (neuralmind/freshness.py)

graph_freshness(project) reports:

SQL and Protobuf files count like code; an OpenAPI/AsyncAPI YAML counts once the graph holds it. FAIL when missing + gone exceed 10% of indexable files, any path uses foreign separators, or the graph changed after the last build; WARN for anything smaller; OK otherwise. It is stat calls and a few git plumbing commands — no parsing — about 80 ms on a 600-file repo.

[FAIL] Code graph: graphify-out/graph.json (graphify, 2026-04-22, 214 commits behind HEAD)
       51 files on disk not in graph (lib/render/overlay.tsx, scripts/collect_stats.py, ...)
       3,176 node paths (319 files) use '\' separators (built on Windows)
       -> neuralmind build . --regenerate-graph

Where it shows up:

2. Escaping a stale graphify graph

3. Orphaned vectors are purged

4. Read paths are quiet and never rebuild

What the agent actually sees post-install

Agent Before After
Claude Code (MCP + hooks) Answers from whatever graph exists, stale or not; the first query in a session triggers a rebuild First neuralmind_wakeup starts with Index is stale: … when the graph lags the code; queries answer from the loaded index without rebuilding
Cursor / Cline / Continue (MCP) Same, and the rebuild’s [neuralmind] generated code graph… line could land on the JSON-RPC stdout Same stale line in the wakeup; stdout carries only protocol frames
Generic MCP client neuralmind_health reported “stale” by age only neuralmind_health returns the freshness report (freshness.status, the missing/gone/changed lists)
CI neuralmind health failed every 24 h regardless neuralmind health . fails only when the graph is out of step; neuralmind build . --strict exits 3 on a FAIL graph

Upgrade notes