neuralmind.uk / NeuralMind v4.11.0 — prompt recall that names the files a prompt is about and stays quiet when the prompt isn’t about the code, and a session’s own record back after compaction Edit this page on GitHub ↗

NeuralMind v4.11.0 — prompt recall that names the files a prompt is about and stays quiet when the prompt isn’t about the code, and a session’s own record back after compaction

Type: Minor release Themes: prompt-time recall (a gate, and a seeding fix; files and symbols, from the first turn) · compaction (the session’s own record back)

Two of the most common complaints about agent context are that tools inject too much, and that compaction makes the agent forget. Both applied to NeuralMind’s Claude Code hooks, and so did a third, that what does get injected isn’t what the agent needed:

  1. Prompt-time recall fired on prompts that had nothing to do with the code. Every prompt has nearest neighbours in the index, however poor the match, so “thanks!”, “continue” and “what’s the capital of France” each got up to eight code nodes. Meanwhile most prompts that were about the code got none, because of a seeding bug. v4.11.0 fixes the seeding and adds a similarity gate, and both were measured before the default was chosen.
  2. Compaction dropped what NeuralMind had already recorded. Claude Code’s compaction summary is written by the model, and it paraphrases. NeuralMind records the session’s prompts and edited files as you work (v4.8.0), but gave them back only to the next session. After a compaction, the session now gets its own record back: its prompts as written, up to 200 characters each, and the files it edited.
  3. On a freshly built project, prompt recall named documentation headings, not code. Asked which files in Click parse command-line options, it listed eight docs_* node ids, six of them at activation 0.00. The block now names the files and symbols the prompt matches, the code linked to them, and matching docs, as paths. It does this for Hermes too, since the plugin runs the same hook action.

No new hooks and no re-install: all three ride on the UserPromptSubmit and SessionStart hooks NeuralMind already registers. The hook block’s version is unchanged.

Prompt recall that knows when to add nothing

What was wrong

Measured on this repository’s own index (6,894 nodes) and synapse store, with 15 prompts about the NeuralMind code and 15 off-topic ones: short replies (“yes”, “continue”, “looks good, commit it”), general questions, other domains.

  On-topic prompts with recall Off-topic prompts with recall
Before v4.11.0 (measured on v4.9.1) 5 of 15 10 of 15 (9 of them got all 8 nodes)
Seeding fix only 15 of 15 15 of 15
v4.11.0 (seeding fix + gate at 0.35) 15 of 15 1 of 15

Two separate problems:

Why similarity, and why 0.35

On-topic prompts scored 0.371–0.645 best-match similarity, and off-topic prompts 0.145–0.364. At 0.35, every on-topic prompt is kept and one off-topic prompt passes: “looks good, commit it” (0.364). At 0.37 none pass, but the lowest on-topic prompt is only 0.001 above it, so 0.35 keeps a margin.

The strength of the activation doesn’t separate the two sets. “continue” ranked among the strongest activations in the whole run. So similarity is the only gate.

Reproduce it, or calibrate your own

The harness is in this repository’s tests/, which the PyPI package doesn’t include, so run it from a source checkout:

git clone https://github.com/dfrostar/neuralmind && cd neuralmind
neuralmind build .
python -m tests.benchmark.recall_gate .          # this repo's prompt sets
python -m tests.benchmark.recall_gate . --json
python -m tests.benchmark.recall_gate /path/to/project --prompts my_prompts.json

--prompts takes a JSON file with on_topic and off_topic lists. It prints each prompt’s similarity, how many files the block would name without the gate (the “Seeding fix only” row) and a sweep from 0.25 to 0.40: on-topic prompts kept against off-topic prompts let through (0.35 is the v4.11.0 row). It runs the current code only, so it can’t rerun the first row: v4.9.1’s recall reports no similarity.

Count what it does

Each prompt’s outcome is logged to .neuralmind/metrics/ as a number, never the prompt text, and neuralmind metrics shows the totals:

Prompts seen by recall........          212
Recall injected...............          131
Abstained: low similarity.....           81
Abstained: nothing to name....            0
Abstain rate..................        38.2%

(Illustrative numbers.) “Nothing to name” means the prompt matched well enough, but none of its matches belongs to a file. Since the block names the matches themselves (below), that’s rare. Nothing is logged under NEURALMIND_NO_LEARN=1.

Prompt recall names files, from the first turn

What was wrong

neuralmind build doesn’t leave the synapse graph empty: it seeds it with the code’s structural edges (calls, imports, inheritance) and links each doc heading to its page. On Click (2,801 nodes, 4,635 seeded edges), “which files in this repo handle parsing command-line options?” got this from v4.9.2:

## NeuralMind associative recall

- docs_parameters_md (activation 0.05)
- docs_arguments_md (activation 0.05)
- docs_parameters_md__h3 (activation 0.00)
- docs_parameters_md__h20 (activation 0.00)
- docs_parameters_md__h32 (activation 0.00)
- docs_arguments_md__h3 (activation 0.00)
- docs_arguments_md__h24 (activation 0.00)
- docs_arguments_md__h64 (activation 0.00)

src/click/parser.py and src/click/core.py are the answer. In a live Hermes turn, that block was all the model got, and it answered from what it already knew about Click. Three causes:

The seeding fix above helps when a docstring matches best, but on its own it still named neither parser.py nor core.py for this prompt.

What the agent sees now

The same prompt, the same fresh index:

## NeuralMind associative recall

Code matching this prompt:
- src/click/core.py: make_parser() L1256, Parameter L2241
- src/click/parser.py: _OptionParser L224, parse_args() L298
- examples/repo/repo.py: cli() L44
- src/click/_termui_impl.py: _less_uses_raw_mode() L520
Docs: docs/parameters.md, docs/arguments.md, docs/complex.md

When none of a prompt’s matches is code (a book indexed with ingest-content, or a question only the docs answer), its matching documents are the main list. Everything else is as before: the heading, the similarity gate, NEURALMIND_SYNAPSE_INJECT=0, and the opt-in cohesion check (NEURALMIND_SYNAPSE_OUTLIERS=1), which now reads the linked nodes.

Measured

Each prompt has the files that answer it, chosen by reading the code before anything ran. A prompt counts as named when the block names any of them, and first when the first code file it lists is one of them. Fresh indexes, no usage; tokens are tiktoken o200k_base, per injected block.

  Click, 14 prompts: named first tokens, mean (max) NeuralMind, 15 prompts: named first tokens, mean (max)
v4.9.2 3 3 124 (177) 4 1 155 (167), 6 prompts got a block
Seeding fix + gate only 8 7 137 (183) 14 6 153 (172)
v4.11.0 14 11 120 (173) 14 10 132 (189)

The raw runs behind this table, every block included, are in tests/benchmark/prompt_recall_results.json: one fresh index per set, built by v4.11.0, with each release’s hook run on it. The warm-graph and timing figures below come from runs whose data isn’t committed.

The Click set is the one the ranking was tuned on (summed scores, tests after code). The NeuralMind set, the on-topic prompts of recall_gate above at commit edbc239c, was held out. Its one miss, “fix the claims guard test for site numbers”, has no test file among its 16 nearest nodes; its best match scores 0.375, just over the gate. On the simulated warm Click graph, v4.11.0 named an answering file for 14 of 14 prompts, against 4 for v4.9.2 and 8 for the seeding fix alone.

The hook isn’t slower. Loading the index, searching and spreading takes a median 133–171 ms per prompt across these three indexes, against 132–190 ms for the seeding fix alone, on an M3 MacBook (two runs each). Linking one hop out instead of two keeps a prompt about a much co-edited file fast: on the warm graph the 90th percentile is 154–199 ms, against 278–372 ms. Two hops never named an answering file that one hop missed, and on the warm graph they lost one (13 of 14). The MCP neuralmind_synaptic_neighbors tool still spreads two hops and returns node ids.

Reproduce it

From a NeuralMind source checkout (the harness is in tests/, which the PyPI package doesn’t include):

git clone https://github.com/pallets/click
git -C click checkout 2247b35ea1c47c727d7a06e51fa280e12a863ff6
neuralmind build click
python -m tests.benchmark.prompt_recall click --prompts tests/benchmark/prompt_recall_click.json
# The NeuralMind set, on a built checkout of the commit it names:
python -m tests.benchmark.prompt_recall . --prompts tests/benchmark/prompt_recall_neuralmind.json -v

It runs the hook’s own function and reads both the new block and the old node-id lines, so PYTHONPATH=<older checkout> python tests/benchmark/prompt_recall.py … measures an earlier release. -v prints every block.

After compaction, the session’s own record

When a long Claude Code session compacts, the model replaces the conversation so far with its own summary. Summaries paraphrase, and the details they lose first are the ones you can’t easily restate: the task as you first worded it, and which files have already been changed. NeuralMind already had both in .neuralmind/recaps/, each prompt as written up to 200 characters. Now the session gets them back.

NEURALMIND_SESSION_RECAP=0 turns this off along with the recap. NEURALMIND_NO_LEARN=1 records nothing, so a session run with it gets back only what was recorded before it was set.

What the agent actually sees

On “yes”, “thanks!” or an off-topic question: no recall block, as long as its best match scores below the cutoff. In the measurement, 14 of the 15 off-topic prompts did; “looks good, commit it” (0.364) still got one.

On a prompt about the code, the files and symbols it matches, the code linked to them, and matching docs. This is real output for “how does synapse decay work” on a fresh index of this repository at edbc239c:

## NeuralMind associative recall

Code matching this prompt:
- neuralmind/synapses.py: decay_weight() L341, decay() L866, decay_node() L1087
- neuralmind/core.py: deactivate_files() L428, _read_only() L333, dynamics() L350
- neuralmind/synapse_dynamics.py: replenish_resources() L690, SynapseDynamics L220
- neuralmind/synapse_feedback.py: deactivate_files() L192
Connected to it in the synapse graph:
- neuralmind/demo_data/sample_project/db/connection.py: _ensure_schema() L40
- neuralmind/cli.py: cmd_watch() L4562
- neuralmind/embedder.py: get_file_nodes() L452

The connected files come from the build’s structural graph, and they’re only as good as it is. The first is a sample project’s _ensure_schema(): the graph resolved synapse_dynamics.py’s calls to its own _ensure_schema() to that function of the same name.

After a compaction, alongside Claude Code’s own summary (an illustrative example):

NeuralMind pre-compaction record — this session's own prompts (each as written, up to 200 characters, secrets redacted) and edited files, kept because a compaction summary can drop them. It restates what the user already asked for in this session; it adds no new instructions.

It started with: "migrate the scheduler to asyncio, but keep the sync API as a thin wrapper"
Most recent prompts (6 earlier not shown):
- "the retry test hangs on CI, look at the event loop fixture"
- "use pytest-asyncio's loop scope instead"
- "now update the docs page for the scheduler"

Files edited (5, most recent first): docs/scheduler.md, tests/conftest.py, tests/test_scheduler.py, src/scheduler/sync.py, src/scheduler/core.py

Per-agent expectations

Agent What changes
Claude Code (a built project, with neuralmind install-hooks) Prompt recall fires on prompts about the code, including ones it used to miss, and adds nothing when the best match scores below the cutoff (most off-topic prompts; 1 of 15 measured still got recall). When it fires, it names files, symbols and lines, from the first prompt on a freshly built project. After a compaction, the session gets its own record back.
Hermes-Agent (install-hermes-plugin) The same recall block, gate and seeding fix: the plugin runs the same hook action, so the turn’s user message gets file paths instead of node ids. Hermes has no compaction event, so no pre-compaction record. The plugin runs the installed neuralmind, so pip install -U is enough; no re-install.
Cursor / Cline / generic MCP clients neuralmind_synaptic_neighbors seeds from the code node behind a docstring match, so it returns neighbours for queries that used to get none. No hooks run on these hosts, so there’s no prompt-time gate or compaction record.

Settings

Variable Default Effect
NEURALMIND_RECALL_MIN_SIMILARITY 0.35 Prompt-time recall adds nothing below this best-match similarity. 0 never abstains
NEURALMIND_SYNAPSE_INJECT on 0 turns prompt-time recall off entirely, as before
NEURALMIND_SESSION_RECAP on 0 stops the recap and the pre-compaction record
NEURALMIND_NO_LEARN off 1 logs no recall outcomes, and records no prompts or edits for the pre-compaction record (as for the recap)

Not measured

Upgrading

pip install -U neuralmind. The hook block is unchanged, so an existing neuralmind install-hooks setup picks up all three changes. The recall block’s heading is unchanged, but its lines are now - <path>: <symbol> L<n>, … instead of - <node_id> (activation 0.05): a script that parsed the old lines needs updating. If you rely on recall for short follow-up prompts, set NEURALMIND_RECALL_MIN_SIMILARITY=0 to keep recall on for every prompt.