Make engram deletes/updates immutable (tombstone + supersede) #82
Closed
will.anderson
wants to merge 4 commits from
feat/immutable-engram-deletes into hotfix/elc-source-typos
pull from: feat/immutable-engram-deletes
merge into: :hotfix/elc-source-typos
:dev
:main
:v0-neuron
:neuron-branding-sweep
:docs/correspondence-and-ownership-2026-08-16
:fix/engram-is-canonical
:fix/graph-edges-no-canonical-clobber
:docs/architecture-2026-08-14-deep-night
:fix/mcp-wrapper-agentic-routing
:merge-pr154-v2
:merge-pr151-v2
:merge-pr150-v2
:merge-pr149-v2
:build-audit-1786832983
: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
:rebase/openai-tools-onto-main
:rebase/gate-state-key-reads-onto-main
:feat/gold-set-heldout
:feat/structural-audit
:feat/claim24-unfloored-semantic
:feat/executive-filter-recall
:feat/recall-through-activation
:chore/regen-soul-amalgam-20260807
:reconcile/hotfix-to-main-launch
:salvage/elh-state-20260704
:feat/plan-mode-endpoint
:fix/operator-identity-home-resolution
:fix/prevent-engram-corruption
: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
:docs/conversation-retrieval-design
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#82
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/immutable-engram-deletes"
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?
What
Make the soul's engram
deleteandupdateroutes immutable, and regeneratedist/soul.c.Why
Three handlers were destroying engram nodes:
memory/delete,node/delete→engram_forget(frees the node and drops its incident edges)node/update→ created a replacement thenengram_forget'd the original, with no link backThat violates the day-one rule that engram nodes are immutable — API callers could silently, irrecoverably destroy memory.
memory/updatewas already correct (supersede-with-edge); the others were not.The fix (mirrors
memory/updateand knowledge evolve/promote)node/update→ create the new node, wire asupersedesedge new→old, keep the original. Noengram_forget.memory/delete+node/delete→ tombstone: keep the node and all its edges; create aTombstonemarker node (content = target id, labeltombstone:<id>) wired with atombstonesedge. Neverengram_forget. Default bounded list reads (handle_api_list_typed/ the memory list) hide tombstoned nodes and the markers;?include_deleted=1returns them, and internal cognition +/api/graph/nodesstill traverse them.Deliberately deferred (documented in code)
Full-graph hiding on
/api/graph/nodesis not done at the el layer:json_array_getis O(index), so filtering that endpoint (the app calls it withlimitup to 999999) would be O(n²). That hide needs a runtime scan filter (skip tombstoned inengram_scan_nodes_json) and is a separate follow-up. Tombstoned nodes remain present and traversable there, taggedstatus:deletedvia the marker edge.Regen + verification
dist/soul.cregenerated from these sources as a flat single-TU amalgamation, compiled under a 3GB physical-RSS watchdog (macOS ignoresulimit -v), peak ~32MB. Diff is exactlyneuron-api.el+dist/soul.c.hotfix/elc-source-typos(where the shippedsoul.c/ neuron-ui PR #144 came from) so the diff stays minimal.neuron-ui/scripts/verify-soul-contract.shagainst the freshly-built binary on a throwaway port:The stale/destructive binary fails the same gate (memory-delete / node-update / node-delete → DESTROYED), so the gate discriminates.
Never touched the live soul (:7770), engram (:8742),
~/.neuron, or the running :7799 sandbox — all build + test on throwaway paths/ports.Do not merge — going live is a controlled-deploy call.
Phase 1 tombstoned memory/delete + node/delete, but the generic forget path was still destructive. This routes every forget through the same tombstone semantics so nothing in the daemon can hard-delete an engram node anymore. Canonical helper: mem_tombstone (memory.el, imported first so every module can call it) — keep the node + its edges, record a Tombstone marker, never engram_forget. neuron-api's tombstone_node now delegates to it (single source of truth). Per-path before -> after: - memory.el `mem_forget` hard delete (engram_forget) -> tombstone. This alone fixes both callers: the /api/neuron/memory/forget route (handle_api_forget) and the cultivate op=="forget". - awareness.el autonomous `forget` action engram_forget -> mem_tombstone. The soul can no longer autonomously hard-delete a memory. - mcp-wrapper tool_forget was a FAKE no-op that returned {"ok","deleted"} without deleting OR tombstoning -> now routes to the soul's tombstoning /api/neuron/memory/delete; tool description fixed to say it supersedes/tombstones (recoverable), not "Remove a node". Left intentionally as hard deletes (internal GC / lifecycle, not user memory, all call engram_forget directly): session-summary replace (chat.el), mem_consolidate dedup (memory.el), session-start telemetry pruning (soul.el), session lifecycle (sessions.el). Regenerated both ship paths under a 3GB physical-RSS watchdog (peak ~32MB): dist/soul.c (single-TU amalgamation, macOS/Linux) and the per-module dist/{memory,awareness,neuron-api}.c (Windows/Linux build). Verified: no forget handler calls engram_forget; a forget leaves the node present + tombstone marker. Gate (neuron-ui verify-soul-contract.sh, new memory-forget row): PRESENCE + IMMUTABILITY PASS.Closing as superseded. The immutability arc (tombstone + supersede for engram deletes/updates) already landed on the launch branch via the merged #94 ("Immutability fix (tombstone/supersede) on the launch branch"), and the same source landed on main through the merged #83 ("Land immutability arc + CI soul-contract gate on main") — which used this very branch. This PR (base
hotfix/elc-source-typos, now stale/unmergeable) adds nothing beyond what #94/#83 shipped. Deleting the head branchfeat/immutable-engram-deletesas part of cleanup.Pull request closed