test(8.0): asOf() error-path spot-checks + find() triple-composition correctness + scale-bench harness

- db-mvcc proof 9: asOf(-1|1.5|future) → RangeError, bad snapshot path → descriptive
  error, use-after-release() throws on get/find/related (Y.15 error-path coverage).
- find-triple-composition: proves vector ∩ metadata ∩ graph returns exactly the
  entity satisfying all three and excludes those failing any one (decoys, wrong category).
- find-composition-scale.js: parameterized latency harness (vector/metadata/graph/
  vector+metadata/triple) with non-empty asserts; precomputed vectors, no model load.
This commit is contained in:
David Snelling 2026-06-15 11:55:26 -07:00
parent f12ca68b82
commit af96064655
3 changed files with 273 additions and 0 deletions

View file

@ -1155,4 +1155,33 @@ describe('8.0 Db API — generational MVCC', () => {
await second.release()
await third.release()
})
// ==========================================================================
// 9. asOf() / released-Db error paths (Y.15 spot-checks)
// ==========================================================================
it('proof 9 — asOf() rejects out-of-range targets and a released Db throws on every read', async () => {
const brain = await openMemoryBrain()
await (
await brain.transact([
{ op: 'add', id: uid('asof-err'), type: NounType.Document, data: 'x', metadata: { v: 1 } }
])
).release()
const current = brain.generation()
// Negative, non-integer, and future generations are honest RangeErrors —
// never a silent clamp to a neighbouring generation.
await expect(brain.asOf(-1)).rejects.toThrow(RangeError)
await expect(brain.asOf(1.5)).rejects.toThrow(RangeError)
await expect(brain.asOf(current + 999)).rejects.toThrow(RangeError)
// A string that is not a snapshot directory is a descriptive error, not a crash.
await expect(brain.asOf('/no/such/snapshot/dir')).rejects.toThrow(/not a snapshot directory/)
// Use-after-release is rejected on every read method, naming the released generation.
const db = brain.now()
await db.release()
await expect(db.get(uid('asof-err'))).rejects.toThrow(/released Db/)
await expect(db.find({ where: { v: 1 } })).rejects.toThrow(/released Db/)
await expect(db.related(uid('asof-err'))).rejects.toThrow(/released Db/)
})
})

View file

@ -0,0 +1,67 @@
/**
* @module tests/integration/find-triple-composition
* @description Correctness of Triple-Intelligence composition in `find()`: a single
* query combining vector similarity, metadata filtering, and graph traversal must
* return exactly the entities satisfying ALL three constraints never silently drop
* a row that each pairwise query would return. Guards the headline 8.0 query surface.
*/
import { describe, it, expect, afterEach } from 'vitest'
import { Brainy } from '../../src/brainy.js'
import { NounType, VerbType } from '../../src/types/graphTypes.js'
/** Deterministic 384-dim vector; same seed ⇒ identical vector (distance 0). */
function vec(seed: number): number[] {
return Array.from({ length: 384 }, (_, i) => ((seed * 31 + i * 7) % 100) / 100)
}
describe('find() Triple-Intelligence composition', () => {
const brains: Brainy[] = []
afterEach(async () => {
for (const b of brains.splice(0)) await b.close()
})
async function open(): Promise<Brainy> {
const b = new Brainy({ storage: { type: 'memory' }, eagerEmbeddings: false, requireSubtype: false, silent: true })
await b.init()
brains.push(b)
return b
}
it('returns the entity satisfying vector ∩ metadata ∩ graph; excludes those failing any one', async () => {
const brain = await open()
const hub = await brain.add({ vector: vec(1), type: NounType.Document, metadata: { role: 'hub', category: 9 } })
// Connected neighbours of the hub:
const n1 = await brain.add({ vector: vec(10), type: NounType.Document, metadata: { role: 'n1', category: 3 } })
const n2 = await brain.add({ vector: vec(11), type: NounType.Document, metadata: { role: 'n2', category: 3 } })
const n3 = await brain.add({ vector: vec(12), type: NounType.Document, metadata: { role: 'n3', category: 7 } })
// Decoys: vector-identical to n1 (seed 10) and category 3, but NOT connected to the hub.
const decoys: string[] = []
for (let i = 0; i < 5; i++) {
decoys.push(await brain.add({ vector: vec(10), type: NounType.Document, metadata: { role: 'decoy', category: 3 } }))
}
await brain.relate({ from: hub, to: n1, type: VerbType.References, weight: 1 })
await brain.relate({ from: hub, to: n2, type: VerbType.References, weight: 1 })
await brain.relate({ from: hub, to: n3, type: VerbType.References, weight: 1 })
const roles = (r: Array<{ metadata?: any }>) => new Set(r.map((x) => x.metadata?.role))
// Sanity: each single/pairwise constraint behaves.
const graphOut = await brain.find({
connected: { from: hub, via: VerbType.References, direction: 'out', depth: 1 }, limit: 50
})
expect(roles(graphOut)).toEqual(new Set(['n1', 'n2', 'n3']))
// Full triple: near vec(10) (n1 + decoys) AND category 3 (n1, n2, decoys) AND connected to hub (n1,n2,n3).
// The intersection is exactly {n1}. Decoys fail graph; n2 fails vector(distance); n3 fails category.
const triple = await brain.find({
vector: vec(10),
where: { category: 3 },
connected: { from: hub, via: VerbType.References, direction: 'out', depth: 1 },
limit: 50
})
const got = roles(triple)
expect(got.size).toBeGreaterThan(0) // composition must not be empty
expect(got.has('n1')).toBe(true) // n1 satisfies all three — must be present
expect(got.has('decoy')).toBe(false) // decoys fail the graph constraint
expect(got.has('hub')).toBe(false) // hub is category 9
})
})