fix(soul): ratio guard against genesis seeding over a populated engram #21

Open
tim.lingo wants to merge 3 commits from feat/connectors-soul into main
Member

Data-safety guard for the genesis boot path (2026-06-15 engram-clobber work).

Problem

Genesis boot seeds a fresh identity and saves it over snapshot.json whenever the
in-memory graph looks empty. A fixed node-count threshold (50) missed partial
loads, letting a sparse boot clobber the populated 47MB engram down to ~63 nodes.

This change

Replace the fixed threshold with a ratio guard: refuse to seed when the on-disk
snapshot is large (>200KB) but the loaded graph is sparse (< disk/16000 nodes).

Known limitation (read before merging)

This gates only the seed / pre-serve-save path. Root cause is deeper: engram_save
in el_runtime.c is non-atomic — fopen(p,"wb") truncates the file to 0 before
writing 47MB, so a concurrent load can read an empty file → genesis → and if the
guard reads guard_disk in that same window it also sees empty and passes. The real
fix is an ATOMIC engram_save (temp + fsync + rename) in el_runtime.c, which I have
diagnosed and proposed to Will but not yet implemented (held pending his review).

Until that lands, the live founder engram is protected by: this guard + the
neuron-daemons.sh TRIPWIRE (restore-from-golden) + a read-only snapshot stopgap +
a locked golden lifeline.

🤖 Generated with Claude Code

Data-safety guard for the genesis boot path (2026-06-15 engram-clobber work). ## Problem Genesis boot seeds a fresh identity and saves it over snapshot.json whenever the in-memory graph looks empty. A fixed node-count threshold (50) missed partial loads, letting a sparse boot clobber the populated 47MB engram down to ~63 nodes. ## This change Replace the fixed threshold with a ratio guard: refuse to seed when the on-disk snapshot is large (>200KB) but the loaded graph is sparse (< disk/16000 nodes). ## Known limitation (read before merging) This gates only the seed / pre-serve-save path. Root cause is deeper: engram_save in el_runtime.c is non-atomic — fopen(p,"wb") truncates the file to 0 before writing 47MB, so a concurrent load can read an empty file → genesis → and if the guard reads guard_disk in that same window it also sees empty and passes. The real fix is an ATOMIC engram_save (temp + fsync + rename) in el_runtime.c, which I have diagnosed and proposed to Will but not yet implemented (held pending his review). Until that lands, the live founder engram is protected by: this guard + the neuron-daemons.sh TRIPWIRE (restore-from-golden) + a read-only snapshot stopgap + a locked golden lifeline. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
tim.lingo added 3 commits 2026-06-15 23:22:40 +00:00
Adds the soul side of the connectors feature (spec: docs/research/
mcp-connectors-adoption-spec.md). The soul thin-proxies the neuron-connectd
bridge on 127.0.0.1:7771 so the UI talks to one origin and never reaches the
bridge directly.

routes.el:
- handle_connectors + connectd_get/connectd_post helpers (POST bodies go via
  a temp file + curl -d @file, so model/UI input can't reach the shell).
- GET /api/connectors and POST /api/connectors/{add,toggle,auto-approve,
  remove,secret,oauth/start} registered in both GET and POST routers.

chat.el:
- tool_auto_approved(): an mcp__* tool skips the approval card only when its
  server is explicitly opted in (off by default; built-in tools unaffected;
  bridge down -> false). Wired into the agentic approval gate so an
  auto-approved connector tool flows straight to execution.

Regenerated dist/chat.c and dist/routes.c. Verified live on :7770: real chat,
recall, and /api/connectors all work after promotion.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- safety.el/.elh: new safety module
- neuron-api.el, routes.el, soul.el, chat.el: connectors API expansion
- regenerated dist/ C artifacts
- MEMORY_RECALL_BUG.md: investigation notes

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix(soul): ratio guard against genesis seeding over a populated engram
Neuron Soul CI / build (pull_request) Successful in 4m43s
bcdadb7323
Genesis boot previously seeded a fresh identity and saved it over snapshot.json
whenever the in-memory graph looked empty. Replace the fixed node-count threshold
with a ratio guard: refuse to seed when the on-disk snapshot is large
(>200KB) but the loaded graph is sparse (< disk/16000 nodes).

KNOWN LIMITATION: this gates only the seed/pre-serve-save path. The deeper cause
is a non-atomic engram_save (fopen wb truncates to 0 before writing 47MB), which
creates a window where a concurrent load reads an empty file -> genesis -> and if
guard_disk is read in that same window the guard passes. The real fix is an
atomic engram_save (temp + fsync + rename) in el_runtime.c, tracked separately.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
All checks were successful
Neuron Soul CI / build (pull_request) Successful in 4m43s
This pull request has changes conflicting with the target branch.
  • awareness.elh
  • chat.el
  • dist/chat.c
  • dist/elp-c-decls.h
  • dist/neuron-api.c
  • dist/routes.c
  • dist/safety.c
  • neuron-api.elh
  • routes.el
  • safety.el
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/connectors-soul:feat/connectors-soul
git checkout feat/connectors-soul
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: neuron-technologies/neuron#21