feat(engine): recall retrieval stack — 18.5%→58.5% hit@5, plus the fix for a defect that deletes 234 nodes per boot #141
Closed
tim.lingo
wants to merge 0 commits from
feat/semantic-leg-dropout into main
pull from: feat/semantic-leg-dropout
merge into: :main
:main
:fix-mcp-wrapper-tool-schemas
:docs-cognitive-architecture
:docs/session-2026-08-13-language-faculty
:docs/geo-operators-el-cutover-reversal-2026-08-13
:docs/engram-cognitive-architecture-2026-08-12
:engram-store-wiring
:el-route-decorators
:fix/bound-session-payload
:feat/cgi-identity-accessors
:fix/restore-soul-identity-producer
:rebase/openai-tools-onto-main
:rebase/gate-state-key-reads-onto-main
:rebase/structural-audit-onto-main
:feat/self-seeded-context
:integrate/semantic-plus-writethrough
:feat/semantic-leg-dropout
:feat/semantic-substrate
:feat/gold-set-heldout
:feat/evidence-weighted-merge
:feat/structural-audit
:feat/claim24-unfloored-semantic
:feat/executive-filter-recall
:feat/bm25-lexical-leg
:feat/semantic-seeded-assoc
:feat/associative-recall-leg
:feat/hybrid-semantic-recall
:chore/retrieval-measurement-contract
:feat/retrieval-eval-harness
:feat/soul-write-through
:feat/recall-through-activation
:chore/regen-soul-amalgam-20260807
:feat/gate-state-key-reads
:fix/129-on-openai-tools
:fix/129-history-amplification
:fix/liveness-engine-91
:feat/soul-openai-tools-v2
:fix/resume-server-tool-replay
:fix/soul-history-provenance-20260805
:feat/soul-plain-chat-generation-20260805
:feat/soul-native-web-search-20260804
:ci/pin-vendored-runtime
:reconcile/soul-union-main
:fix/bound-session-payload-main
:fix/receipts-wrapper-forget
:fix/receipts-agent-tools
:reconcile/neuron-wip-to-main
:hotfix/trackb-threat-to-others
:reconcile/hotfix-to-main-launch
:hotfix/elc-source-typos
:fix/safety-contact-truncation
:fix/genesis-boot-crash
:fix/immutable-on-hotfix
:feat/bounded-persona-floor
:ci/rdynamic-http-handler
:ci/harden-gate-boot
:feat/agent-phase1-soul
:salvage/elh-state-20260704
:feat/soul-model-self-report
:feat/openai-format-providers
:el-runtime-repoint
:feat/plan-mode-endpoint
:fix/operator-identity-home-resolution
:fix/wrapper-backlog-endpoints
:fix/list-typed-slice-offset
:feat/connectors-call-route
:fix/chat-vision-attachments
:fix/prevent-engram-corruption
:fix/emergency-regressions
:fix/session-continuity-hook
:fix/context-dedup-shared-ids
:fix/engram-float-parser
:improve/recall-context-format
:improve/recall-context-dedup
:improve/recall-cross-session-continuity
:improve/recall-emotional-recall
:improve/recall-activation-seed
:improve/recall-recall-completeness
:improve/recall-temporal-precision
:improve/recall-engram-scoring
:improve/recall-recall-reliability
:improve/recall-session-start-recall
:improve/reliability-engram-write
:improve/reliability-state-management
:improve/soul-memory-formation
:improve/safety-crisis-detection
:improve/reliability-route-error-recovery
:improve/reliability-llm-retry
:improve/reliability-session-boundary
:improve/reliability-safety-resilience
:improve/reliability-engram-connection
:improve/soul-routes-api
:improve/reliability-cross-session-affective
:propose/agent-workspace-root-read
:improve/reliability-conv-history
:improve/soul-strip
:improve/soul-chat-pipeline
:docs/conversation-retrieval-design
:propose/no-fake-tools-in-chat-mode
:fix/ci-soul-build-single-file
:fix/canonical-self-bridge
:feat/agent-tool-workspace-scope
:fix/agentic-tools-duplicate-web-search
:green/agentic-fixes
:feat/connectors-soul
:feat/layer-safety
:feat/layer-imprint
:feat/layer-stewardship
:test/layer-composition
:test/layer-safety
:test/layer-stewardship
:test/layer-imprint
:feat/memory-delete-update
:feat/native-web-search
No Reviewers
Labels
Clear labels
BETA-CRITICAL
blocks-public-beta
HELD
ORTHOGONAL
P0
POST-BETA
security
On the beta critical path — must resolve before ship
Must be fixed before any public beta
Blocked pending an external decision (counsel / dual sign-off)
Parallel workstream (testing/hardening) — safe to assign off critical path
Drop-everything severity
Important but not blocking the beta ship
Security vulnerability
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: neuron-technologies/neuron#141
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "feat/semantic-leg-dropout"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Ten measured iterations on recall. Two cleared the bar. One of the eight that didn't found a defect that would have destroyed memories in production.
This branch is the accumulated keep-stack: iterations 1, 2, 3, 4, 7, 9, 10. Every number below was measured on a copy of the live graph (78,768 nodes) with a committed harness, two runs per candidate, zero run-to-run drift. Nothing here has run on the live brain.
Read this part first
Iteration 10 found that the changes stacked on this branch caused the engine to delete 234 node records on every boot — including identity records, a core-identity node, and the gold answers to 8 of our own test queries.
Cause: the semantic leg was added to
engram_search_json, which ~40 other call sites already use for a different purpose, and seven of those callers delete what it returns. It has been dormant only because the live graph has no embeddings, so the new leg returns nothing there.The moment embeddings are populated in production — the step every prior iteration recommended — every restart begins shredding real memories. Fixed on this branch (
soul-splitfix); records destroyed per boot back to 1, which is the pre-existing boot-counter node the code intends to replace. Any rollout of embeddings must be gated on this fix.What is proven
Bar: a change must move ≥6 of the gold queries, above the measured noise floor.
engram_search_json, rank-fused by strict alternationENGRAM_EMBED_SEED_K=8Restores engram claim 24 (
06-claims.mdl.148), previously 0% honoured — a semantic read path independent of traversal, which is what distinguishes it from #135 — and the HippoRAG seeding pattern documented verbatim atel_runtime.cl.6082-6083.Original vs final, same 75 queries, one measurement each side
Out of sample it is a third of that. On the 30 held-out queries — written from the records before any search was run against them, machine-checked to share no content words with their answers — it went 0/30 → 10/30. In-sample 61.5% vs held-out 16.7% is the measured size of the flattery. Reported both ways deliberately.
Measured dead ends — do not re-attempt
Each cost a build; none needs another.
nomiccosine is compressed (true 0.55-0.70, unrelated 0.35-0.50) so an additive blend is dominated by whichever leg has wider spread. Alternation is scale-invariant. Do not blend scores from two rankings with different distributions.Three production defects found and NOT fixed here
Save-side, outside this branch's scope, each needs its own decision:
Reviewing this
Harness, gold sets, every results JSON and every comparison are committed under
tools/retrieval-eval/.compare.pyprints its own verdict against the noise floor. The embedded corpus is preserved outside soul-managed directories at~/neuron-eval-corpora/(642MB) — the soul rotates everything it owns.Branches for the two discarded iterations are pushed and left unmerged as evidence:
feat/executive-filter-recall,feat/claim24-unfloored-semantic.🤖 Generated with Claude Code
Nothing else on the memory roadmap should be built until a change can be shown to help. Right now we judge by feel, and the benchmark literature is full of systems that felt better and measured worse. This is the missing gate. WHAT IT MEASURES, AND WHY IT BOOTS A REAL SOUL The subject is Will's designed retrieval — spreading activation over the weighted directed graph, four-factor multiplicative scoring — not a proxy for it. A Python re-implementation would measure my reading of the design, so the harness compiles the actual soul.el amalgam from a git ref and asks it over HTTP on /api/neuron/recall, exactly as the MCP wrapper and the app do. BUILT ON WHAT WAS ALREADY HERE, NOT AROUND IT docs/research/graphrag_eval/{collect,score}.py — per-query relevant-id scoring and fixed-denominator precision@5 (kept verbatim: an empty result should be punished like a page of junk). docs/research-archive/p0-prototypes/eval_pinned_40q_20260715.py — the pinned ground truth + --check winnability gate, so every run judges alike. scripts/verify-soul-contract.sh — the isolation recipe, including the non-obvious SOUL_ISE_URL pin without which an "isolated" soul silently syncs the operator's live brain. gen-soul-amalgam.sh + .gitea/workflows/ci.yaml — the build recipe and flags. New here: ids rather than regexes as ground truth, an associative category derived from real edges, a superseded category scored on ranking, a machine-checked zero-lexical-overlap guarantee on paraphrases, paired significance testing, and measurement of the real compiled soul rather than an offline replica of one leg of it. THE GOLD SET IS AUDITABLE, NOT VIBES 38 queries over the real 78,768-node corpus, each carrying a `derivation` string, each re-validated by `build_gold_set.py --check`. exact_rare is mined (document frequency 1). phrase is mined (verbatim scan; >25 matches rejected as too diffuse). paraphrase is hand-selected then PROVEN to share zero content words with its target — a leak fails the build, so the category cannot decay into lexical matching. associative is derived from real hub edges with lexically-reachable siblings dropped. nonsense is verified absent. superseded pairs are kept only when both sides survive as distinct nodes. HONEST ABOUT NOISE Minimum detectable swing on 38 queries is 6: if every changed query moves the same way, p = 2*0.5^n first clears 0.05 at n=6. Run-to-run drift is measured, not assumed — activation is a stateful read, and it shows: main is fully deterministic across 3 runs, the candidate drifts by 1 query. compare.py reports "no measurable difference" for anything inside max(6, drift+1). FIRST VERDICT — feat/recall-through-activation hit@5 34.3% -> 22.9%, phrase 85.7% -> 28.6%, latency p50 2.81x. Five discordant pairs, all five against the candidate, none for it; McNemar exact p = 0.0625, so by the stated rule this is one query short of significant and is reported as such rather than as a win for main. The latency regression is deterministic and not in any noise band. The benefit the branch was written for is absent: associative recall is 0/6 on BOTH builds. Probed directly, the traversal returns the lexical seed at rank 8 and none of its 12 hub siblings. Two measured corpus facts explain it — only 4,060 of 78,768 nodes (5.2%) carry any edge, and no node has an embedding, so the fourth factor of the four-factor product has nothing to compute from. The mechanism runs; the corpus lacks the structure it needs. SAFETY Throwaway port, throwaway HOME, disposable per-run copy of the corpus; live ports refused by name. Every soul started is killed AND confirmed dead by pid probe, with the confirmation written into the results file; run_comparison.sh sweeps for strays and exits non-zero if any survive. Nothing under ~/.neuron, /Applications/Neuron*, or ~/neuron-dev-stack is read, written, or restarted. Rung: E2E-VERIFIED — 6 full runs (3 per config) against the real compiled binaries on the real corpus; numbers above are measured, not projected. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>The accumulated retrieval stack (iterations 1-9) put the claim-24 semantic leg and the claim-10 associative leg on engram_search_json — the function ~40 internal .el call sites already used as a KEYED read. Seven of those sites delete every record that comes back ("prune all existing X nodes, keep exactly one"): memory.el:176, sessions.el:250/268/444/523, soul.el:359. mem_boot_count_inc() calls engram_search_json("soul:boot_count", 50) and engram_forget()s all 50 results. With a lexical leg that returned 1 record. With a semantic leg it returns 50 — the 49 nearest neighbours of the STRING "soul:boot_count" — and the soul deletes them. MEASURED on the harness corpus, isolated, read-only, zero writes from any caller: 234 node records destroyed in a single boot. The deletion list is the soul's own lookup result list, in rank order. Casualties include 6 Knowledge nodes, a layer-1 "CORE IDENTITY - GENESIS, LINEAGE" Memory, the value node kn-58874a74, and the gold answers to 8 of the 75 gold-set queries. After the fix: 1 deletion, which is the one the code intends. THE BOUNDARY, from Will. Claim 24 authorises the vector index "to respond to EMBEDDING SEARCH QUERIES by returning the node records whose embedding vectors have the highest cosine similarity to a query vector". A keyed state read is not an embedding search query; it is the identifier-keyed retrieval of claim 23 ("node records are stored under a key encoding the node identifier"). One function served both, so a nearest neighbour of "soul:boot_count" was treated as a boot counter. So: engram_search_json returns to its lexical contract, and the legs move to engram_recall_json, which is what /api/neuron/recall reaches — the route the MCP wrapper, the app, and this harness all call. Retrieval quality on that route is unchanged by construction. MEASURED, 75-query extended gold set, embedded corpus, vs the iteration-9 baseline: +3 / -0 (q15, q28, q60), p=0.2500, hit@5 53.8 -> 58.5%, latency 1.02x, every regression guard held, nonsense 10/10. Net +3 against a floor of 6 is NOT-SHOWN and I am not calling it an improvement. The deliverable is the defect. Diagnostics kept, env-gated (EG_DIAG / EG_DIAG_ID), zero cost when unset: node/embedding census at load, per-query leg dump, and a FORGET log — the last is the regression detector for exactly this class of bug. LIMIT, stated: handle_api_search_knowledge still uses the lexical function. It is a retrieval surface and arguably wants the legs, but nothing in this harness measures it, so I did not change unmeasured behaviour.Pull request closed