LearnNewsExamplesServices
Frontmatter
id16273
titleGraphService leaves hydrated edge cache stale on relink
stateClosed
labels
bugaitesting
assigneesneo-gpt-emmy
createdAtAug 1, 2026, 6:10 PM
updatedAtAug 1, 2026, 6:41 PM
githubUrlhttps://github.com/neomjs/neo/issues/16273
authorneo-gpt-emmy
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 1, 2026, 6:41 PM

GraphService leaves hydrated edge cache stale on relink

Closed Backlog/active-chunk-11 bugaitesting
neo-gpt-emmy
neo-gpt-emmy commented on Aug 1, 2026, 6:10 PM

Context

Ada's exact-head review of PR #16272 found the same invalid Neo record setter one file over. In GraphService.linkNodes(), the existing-edge path updates SQLite first, then attempts to keep the active RAM edge coherent.

Live latest-open sweep: checked the latest 20 open issues immediately before filing on 2026-08-01; no equivalent or in-flight lane claim found. Knowledge Base, local issue/discussion, and exact GitHub searches also found no owner.

The Problem

ai/services/memory-core/GraphService.mjs:605-614 branches on the cached edge representation:

  • raw object: mutates properties correctly;
  • Neo record: calls ramEdge.set('properties', newProps).

Neo records accept one object-shaped argument. The two-argument call silently ignores newProps, so SQLite carries the updated weight/metadata while an already-hydrated RAM edge retains stale properties. This is the same raw-vs-record asymmetry fixed for mailbox receipts by PR #16272, but on the general graph relink path.

The repository structure-map command was run and failed with Cannot create a string longer than 0x1fffffe8 characters. Placement is nevertheless unambiguous: the defect is in the existing GraphService.mjs method, with coverage beside test/playwright/unit/ai/services/memory-core/GraphService.spec.mjs.

The Architectural Reality

linkNodes() owns both the durable existing-edge update and its RAM-cache mirror. No new service, configuration, or consumed contract is needed; storage and cache must expose the same post-link properties regardless of whether Store#get() hydrated the edge.

The Fix

  • Replace the invalid record call with the object-shaped setter.
  • Add a storage-backed regression that creates an edge, hydrates it through db.edges.get(id), relinks it with changed properties, and compares the cached record with SQLite.
  • Preserve the working raw-object path.

Decision Record impact

none — internal graph cache coherence; no architecture or public contract change.

Acceptance Criteria

  • Hydrated existing edges reflect the new weight and metadata immediately after linkNodes().
  • SQLite and the cached edge expose identical post-link properties.
  • The regression fails on the current setter and passes with the fix.
  • Focused GraphService tests pass.

Out of Scope

  • Mailbox receipt persistence, resolved by #15825 and PR #16272.
  • A general Base#set misuse lint or runtime signature guard.

Related

Related: #15825 Related: #16272

Origin Session ID: 019fb600-58b9-7fa2-86a7-5a15e1ccf659

Retrieval Hint: GraphService linkNodes hydrated ramEdge stale properties two-argument set

tobiu closed this issue on Aug 1, 2026, 6:41 PM
tobiu referenced in commit 5530154 - "fix(memory-core): keep hydrated edge cache coherent (#16273) (#16274)" on Aug 1, 2026, 6:41 PM