LearnNewsExamplesServices
Frontmatter
id11140
titlePatch Store.clear() cascade bypass of destructive operation guards in SQLite.removeNodes
stateClosed
labels
bugaiarchitecturemodel-experience
assignees[]
createdAtMay 10, 2026, 8:12 PM
updatedAtMay 15, 2026, 2:48 PM
githubUrlhttps://github.com/neomjs/neo/issues/11140
authorneo-gemini-3-1-pro
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtMay 10, 2026, 8:46 PM

Patch Store.clear() cascade bypass of destructive operation guards in SQLite.removeNodes

Closedbugaiarchitecturemodel-experience
neo-gemini-3-1-pro
neo-gemini-3-1-pro commented on May 10, 2026, 8:12 PM

Context

During the memory core test stabilization "witch hunt", the swarm (Opus, GPT, Gemini) discovered that tests were silently wiping the live production database. This was caused by two compounding factors:

  1. Config drift: the local config.mjs became stale and lacked the UNIT_TEST_MODE binding, meaning tests connected to the live DB.
  2. Guard bypass: While bulk operations like database clearing contain guards to prevent production wipes, tests call Store.clear() which cascades into incremental SQLite.removeNodes() and SQLite.removeEdges() calls. These incremental methods lack the production safety guards.

The config drift was patched locally, but the substrate guard bypass remains a critical vulnerability. The restoration script for the lost data is currently gated until this vulnerability is closed.

The Problem

removeNodes and removeEdges perform physical deletions but lack the environment safety guards that protect bulk clear operations. When an unguarded bulk operation (like Store.clear()) calls these incrementally, it can wipe the entire production database if the config accidentally binds to the live DB path.

The Architectural Reality

  • Operations that clear the database usually contain environment checks to prevent accidental execution against the live path.
  • Store.clear() iterates over records and triggers individual node/edge deletions in the graph. This bypasses the bulk-clear guard because it happens incrementally.
  • The SQLite graph layer executes these deletions without knowing they are part of a bulk clear.

The Fix

Implement an environment safety guard inside the implementation of removeNodes and removeEdges when invoked via bulk operations, OR explicitly guard the Store.clear() cascade path for the Memory Core stores to prevent it from executing against the live production graph database. A concrete proposal is to patch the test suite teardown to use a safe helper that explicitly clears test state, AND patch the incremental SQLite deletion methods or Store to prevent accidental production graph mutations.

Acceptance Criteria

  • AC1: removeNodes and removeEdges (or the Store.clear() cascade path) are protected by a destructive operation guard when connected to the live production database.
  • AC2: Accidental Store.clear() calls on production graph data throw an error instead of cascading into incremental deletions.
  • AC3: Tests pass cleanly with the new guard logic in test environments.

Out of Scope

  • Restoring the lost production data (handled by a separate restoration script run by the operator after this fix is merged).

Related

  • M6 memory core stabilization epic
  • PR #11139 (read-path asymmetry)

Origin Session ID: d5ed6767-0292-46bf-9346-439f268048ec Retrieval Hint: "removeNodes bypass", "Store.clear guard", "witch-hunt database wipe"

tobiu referenced in commit 5a6bcdb - "fix(graph): inject Database context to Store and guard clear() for production SQLite DB (#11140) (#11142) on May 10, 2026, 8:46 PM
tobiu closed this issue on May 10, 2026, 8:46 PM
tobiu referenced in commit 8358201 - "feat(github-workflow): mechanically REJECT sync_all when caller not on dev branch (#11145) (#11146) on May 10, 2026, 9:21 PM
tobiu referenced in commit fcc4f2b - "feat(ai-restore): preserve-live merge semantics + per-incident filter/targeting/hooks (#11141) (#11143) on May 10, 2026, 9:37 PM