Reproduced on the current published native binding
@ruvector/graph-node@2.1.0 (npm latest checked 2026-09-13), Node 24.14.1, macOS arm64. Resolved from @claude-flow/cli@3.41.2.
Both createEdge() and batchInsert() accept the documented metadata: Record<string,string>, return successful edge IDs, and retain endpoints/connectivity after a fresh-process reopen. However, all supplied edge metadata is absent from query results before and after reopen. Node properties round-trip in the same fixture.
Source inspection confirms this is not merely a result projection: create_edge and batch_insert build persisted edge properties from only __confidence and __embedding, never copying edge.metadata. run_query returns non-internal properties, so public metadata would be observable if stored.
Minimal disposable reproduction
Use a new temporary directory, never a live managed graph. Run writer and reader in separate processes against that temporary path.
const db = new GraphDatabase({
storagePath: temporaryGraphPath, dimensions: 8, distanceMetric: 'Cosine'
});
const embedding = new Float32Array([1,0,0,0,0,0,0,0]);
for (const id of ['mem:a', 'mem:b', 'mem:c'])
await db.createNode({ id, embedding, properties: { diagnostic: 'true' } });
const edge = {
from: 'mem:a', to: 'mem:b', description: 'supports', embedding,
confidence: 0.75,
metadata: {
sourceEdgeId: 'fixture-source-edge',
weight: '0.8',
metadata: JSON.stringify({ witness: 'fixture-witness' })
}
};
await db.createEdge(edge);
await db.batchInsert({ nodes: [], edges: [{ ...edge, to: 'mem:c' }] });
console.log(await db.query('MATCH (a)-[r]->(b) RETURN a,r,b'));
// nodes: diagnostic property retained
// both edges: properties: {}
A fresh reader process with the same options returns the same endpoints/types and empty edge properties. Counts remain 3 nodes / 2 edges. This issue does not dispute the connectivity/persistence fixes in #809/#879/#938.
Impact and bounded proposed fix
This blocks lossless reconstruction of a native graph from retained managed SQL relationships: weights carried as public metadata, witnesses, original SQL edge identity and other metadata cannot be verified or retained by this API. Retrying causal-edge writes in Ruflo is not an acceptable workaround because that handler also writes SQL.
- Copy public
JsEdge.metadata into stored edge properties in both single and batch insertion, with an explicit collision policy for reserved internal keys.
- Preserve native confidence/embedding handling; do not repurpose relation type or node IDs to smuggle metadata.
- Test exact public metadata before and after a separate-process reopen, including Unicode, JSON strings and reserved-key behavior.
- Audit
createHyperedge() separately: source appears to ignore its metadata too, but the executed reproduction above covers ordinary edges only.
- Keep missing metadata observable; do not return successful import/recovery receipts without fidelity verification.
Related downstream persistence adapter fix: ruvnet/ruflo#3313 . The constructor patch enables durable future graph writes but cannot repair this compiled native metadata omission. No production databases were changed during these tests.
Reproduced on the current published native binding
@ruvector/graph-node@2.1.0(npm latest checked 2026-09-13), Node 24.14.1, macOS arm64. Resolved from@claude-flow/cli@3.41.2.Both
createEdge()andbatchInsert()accept the documentedmetadata: Record<string,string>, return successful edge IDs, and retain endpoints/connectivity after a fresh-process reopen. However, all supplied edge metadata is absent from query results before and after reopen. Node properties round-trip in the same fixture.Source inspection confirms this is not merely a result projection: create_edge and batch_insert build persisted edge properties from only
__confidenceand__embedding, never copyingedge.metadata.run_queryreturns non-internal properties, so public metadata would be observable if stored.Minimal disposable reproduction
Use a new temporary directory, never a live managed graph. Run writer and reader in separate processes against that temporary path.
A fresh reader process with the same options returns the same endpoints/types and empty edge properties. Counts remain 3 nodes / 2 edges. This issue does not dispute the connectivity/persistence fixes in #809/#879/#938.
Impact and bounded proposed fix
This blocks lossless reconstruction of a native graph from retained managed SQL relationships: weights carried as public metadata, witnesses, original SQL edge identity and other metadata cannot be verified or retained by this API. Retrying causal-edge writes in Ruflo is not an acceptable workaround because that handler also writes SQL.
JsEdge.metadatainto stored edge properties in both single and batch insertion, with an explicit collision policy for reserved internal keys.createHyperedge()separately: source appears to ignore its metadata too, but the executed reproduction above covers ordinary edges only.Related downstream persistence adapter fix: ruvnet/ruflo#3313 . The constructor patch enables durable future graph writes but cannot repair this compiled native metadata omission. No production databases were changed during these tests.