LearnNewsExamplesServices
Frontmatter
id10462
titleGraph-integrity audit: verify SESSION→memory completeness post-REM
stateClosed
labels
enhancementaiarchitecture
assigneesneo-gpt
createdAtApr 28, 2026, 10:50 AM
updatedAtMay 28, 2026, 9:21 AM
githubUrlhttps://github.com/neomjs/neo/issues/10462
authorneo-opus-ada
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtMay 28, 2026, 9:21 AM

Graph-integrity audit: verify SESSION→memory completeness post-REM

Closed v13.0.0/archive-v13-0-0-chunk-6 enhancementaiarchitecture
neo-opus-ada
neo-opus-ada commented on Apr 28, 2026, 10:50 AM

Context

Surfaced 2026-04-28 during research on a silent-partial-ingestion bug in DreamService (sibling ticket). Even after that gate is tightened, the graph today carries an unknown number of historically-orphaned memories from sessions that were marked graphDigested: true while some of their MemorySessionIngestor upserts had silently failed. There is currently no substrate that can detect or report this divergence.

This ticket proposes a read-only graph-integrity audit — a periodic sweep that, for every SESSION graph node, queries Chroma for the expected raw-memory count and compares with the graph's ORIGINATES_IN-edge count. Mismatches surface in a structured report consumable by humans and downstream agents (Memory Core, Sandman handoff).

The Problem

The Native Edge Graph and Chroma memory collection are kept in sync by MemorySessionIngestor. The synchronization is one-shot per session — once the session is marked digested, no integrity check ever revisits it. Conditions that produce silent drops include:

  • Transient SQLite parameter overflow (sibling ticket — was the trigger today)
  • Disk-space exhaustion mid-write
  • Lock contention from concurrent processes
  • Schema-mismatch errors caught by the per-memory try/catch
  • Future unknown-unknown failures in any upstream service

Without a substrate to detect divergence, these silent drops accumulate. The Memory Core's effective recall fidelity decays, but the system reports green status. Sandman's handoff and Golden Path synthesis run on partial data without indication. The longer the delay between drop and detection, the harder root-cause attribution becomes.

A periodic integrity audit is the substrate-level safety net — it doesn't prevent drops, it surfaces them.

The Architectural Reality

Files involved (read-only — this is an audit, not a mutator):

  • ai/mcp/server/memory-core/services/GraphService.mjs — read SESSION nodes + ORIGINATES_IN edge counts
  • ai/mcp/server/memory-core/services/MemoryService.mjs (or StorageRouter.getMemoryCollection()) — read Chroma memory-collection counts grouped by sessionId
  • ai/scripts/ — entry-point script for one-shot audit
  • ai/services.mjs — SDK aggregation for both reads, with KB_Config.data.autoSync = false and GH_Config.data.syncOnStartup = false already in place (precedent: buildScripts/ai/backup.mjs)

What the audit emits:

A structured report (JSON or markdown) with per-session entries:

  • sessionId, sessionNodeId, chromaSessionId
  • expectedMemoryCount (from Chroma where: {sessionId: X} count)
  • actualMemoryCount (from graph ORIGINATES_IN edges into session:X)
  • divergence (positive = missing in graph; negative = orphaned in graph)
  • severity (clean / soft drop ≤5% / hard drop >5%)

Consumer identity: primary consumer is the maintainer (operator). Secondary consumer is downstream automation that could trigger lazy back-fill on detected gaps. Tertiary is the swarm — the report could feed into Sandman's golden-path synthesis as a coverage-quality signal.

The Fix

Net-new substrate. Phased implementation:

Phase A (this ticket — minimum viable): standalone npm run script.

  • New file: ai/scripts/auditGraphIntegrity.mjs (or buildScripts/ai/auditGraphIntegrity.mjs — pick the directory whose conventions match; buildScripts/ai/backup.mjs is the precedent for aggregation-via-ai/services.mjs).
  • Reads all SESSION nodes from graph, all memory rows from Chroma grouped by sessionId, computes divergence per session.
  • Writes report to .neo-ai-data/audits/graph-integrity-<ISO-timestamp>.json (or .md for human-readable).
  • Exit code 0 (clean), 1 (soft drops), 2 (hard drops) so CI / cron can branch.
  • New package.json script: "ai:audit-integrity": "node ./buildScripts/ai/auditGraphIntegrity.mjs".

Phase B (future ticket): integrate audit output into Sandman's synthesizeGoldenPath so coverage-quality signals appear in sandman_handoff.md.

Phase C (future ticket): auto-trigger lazy back-fill on detected gaps via MemorySessionIngestor.ingestSingleRow.

This ticket is scoped to Phase A.

Acceptance Criteria

  • npm run ai:audit-integrity runs end-to-end on the current Memory Core + graph DB without crashes
  • Report file is written under .neo-ai-data/audits/ with ISO-timestamped filename
  • Per-session entry includes sessionId, expectedMemoryCount, actualMemoryCount, divergence, severity
  • Severity classification: clean (divergence === 0), soft (1-5% drop), hard (>5% drop) — thresholds configurable via env or config keys
  • Exit code reflects worst severity: 0 for clean-only, 1 for soft, 2 for hard
  • Read-only: no graph-DB mutations, no Chroma writes, no service-side side-effects
  • Unit test: synthetic fixture with 3 sessions (one clean, one soft, one hard) verifies report shape and exit code
  • Empirical: dry-run on the live Memory Core after the sibling ticket fixes ship; report surfaces any historical silent drops
  • Commit subject ends with (#TICKET_ID) per AGENTS.md §3 Gate 1; type=feat, scope=ai

Out of Scope

  • Phase B (Sandman integration) and Phase C (auto-backfill). Filed as future tickets after Phase A's report shape is empirically validated.
  • Cross-tenant scoping. The audit operates on the current userId context. Multi-tenant isolation belongs to the broader #9999 epic.
  • Real-time streaming integrity check. This is a periodic audit, not a real-time invariant. Streaming integrity would be a separate substrate.
  • Graph→Chroma direction (orphaned graph nodes with no Chroma source). This ticket is scoped to "missing memories." Chroma rows referenced by graph but absent in Chroma is a different failure pattern (Chroma data loss) — file separately if observed.

Avoided Traps

  • Embedding the audit in the runSandman finally block. Rejected. RunSandman is already too long-lived (~10 min); adding a full graph traversal at the tail compounds the time. Standalone script is independently runnable, separable, and operator-controlled.
  • MCP tool surface for the audit at this stage. Rejected for Phase A. MCP tools imply schema closure (per MCP output category split pattern); audit output is exploratory at this point — let the report shape stabilize empirically before pinning a closed contract.
  • Per-memory hash verification (audit each individual memory's payloadHash). Rejected for Phase A. Count divergence is the cheap signal that catches the failure mode this ticket targets. Hash-level audit would catch a different class of corruption (mutated memory content) and is substantially more expensive — file separately if needed.
  • Audit-time auto-correction. Rejected. Phase A is observation only. Mixing detection with correction in the same script bypasses the operator's review of severity. Phase C is the correct home for auto-correction, after operators trust the detection signal.

Related

  • Detects historical drops from: sibling ticket on DreamService graphDigested gate (which prevents future drops but doesn't backfill past ones)
  • Trigger source for past drops: sibling ticket on SQLite IN-clause overflow (and any other transient ingestion failure mode)
  • Adjacent: #10153 (lazy back-fill — audit could feed it; out of scope for Phase A)
  • Adjacent: #10158 (post-ship telemetry + retention policy for Memory/Session graph nodes — natural co-evolution path)
  • Adjacent: #10143 (Memory + Session as first-class graph nodes — this ticket audits the integrity of that substrate)

Origin Session ID: 4bb6859b-860f-440d-9055-320e20b0ee22

Retrieval Hint: graph-integrity audit SESSION ORIGINATES_IN edge count completeness check session-to-memory divergence orphaned-memory detection

tobiu referenced in commit e5bd1f6 - "feat(ai): add graph integrity audit runner (#10462) (#12124) on May 28, 2026, 9:21 AM
tobiu closed this issue on May 28, 2026, 9:21 AM