fix(namespace): noun-record updates preserve legacy inline HNSW adjacency — the placeholder-adjacency write stamped out pre-codec records' stored connections (crash-window unreachability); codec-era records were never at risk (empty field is the blob marker); pin covers the legacy shape
Some checks failed
CI / Node 22 (push) Failing after 7m32s
CI / Node 24 (push) Failing after 7m24s
CI / Bun (latest) (push) Successful in 12m17s

This commit is contained in:
David Snelling 2026-08-03 15:37:04 -07:00
parent 7a28a94639
commit 4679c89458
2 changed files with 68 additions and 2 deletions

View file

@ -145,3 +145,50 @@ describe('level field shadow — user metadata named level is a real field', ()
expect(EXPECTED_INDEX_EPOCH).toBe(2)
})
})
describe('noun-record writes never stamp over stored graph state', () => {
let brain: Brainy
beforeEach(async () => {
brain = new Brainy({
requireSubtype: false,
storage: { type: 'memory' as const },
embeddingFunction: stubEmbedding
})
await brain.init()
})
afterEach(async () => {
await brain.close()
})
it('a data-changing update preserves LEGACY inline connections in the record', async () => {
// Codec-era records carry an EMPTY connections field by design (the
// adjacency lives in a separate compressed blob) — the clobber window
// exists only for legacy pre-codec records whose adjacency is inline.
// Simulate one: write the record with inline connections directly.
const id = await brain.add({
data: 'legacy-shaped node',
type: NounType.Concept,
metadata: { n: 1 }
})
const storage = (brain as any).storage
const rec = await storage.getNoun(id)
const legacy = {
...rec,
connections: new Map([[0, new Set(['00000000-0000-4000-8000-00000000aaaa'])]]),
level: 1
}
await storage.saveNoun(legacy)
const before = await storage.getNoun(id)
expect(before.connections.size).toBeGreaterThan(0)
// A data-changing update stages SaveNounOperation with placeholder
// adjacency — the legacy inline connections must survive the write.
await brain.update({ id, data: 'completely re-embedded text' })
const after = await storage.getNoun(id)
expect(after.connections.size).toBeGreaterThan(0)
expect(after.level).toBe(1)
})
})