/** * @module tests/unit/brainy/lazy-notready-honor * @description THE SILENT-EMPTY TRAP pin (found during a fleet adoption, * SELF-ENGINE-PAIR-STANDARD): under `disableAutoRebuild: true`, the lazy * first-query path (`ensureIndexesLoaded`) assessed ONLY the vector index's * readiness — a native METADATA provider reporting not-ready (its strand * report) never blocked the completion latch, so the promised lazy rebuild * never fired and every `find()` silently returned `[]` on a populated * store (measured: 52 entities durable-but-unqueryable, first query * 0ms/0 rows). The law: a not-ready report from ANY provider falls through * to the rebuild — never a silent empty. * * White-box provider-double pattern per tests/unit/brainy/migration-deference. */ import { describe, it, expect, afterEach, vi } from 'vitest' import { Brainy } from '../../../src/index.js' import { NounType } from '../../../src/types/graphTypes.js' import { createTestConfig } from '../../helpers/test-factory.js' interface BrainInternals { index: { size(): number } metadataIndex: { isReady?: () => boolean } lazyRebuildCompleted: boolean ensureIndexesLoaded(): Promise rebuildIndexesIfNeeded(force?: boolean): Promise } const brains: Brainy[] = [] afterEach(async () => { for (const b of brains.splice(0)) await b.close().catch(() => {}) vi.restoreAllMocks() }) async function warmLazyBrain(): Promise<{ brain: Brainy; internals: BrainInternals }> { const brain = new Brainy(createTestConfig({ disableAutoRebuild: true })) await brain.init() brains.push(brain) for (let i = 0; i < 3; i++) { await brain.add({ data: `row ${i}`, type: NounType.Document, metadata: { i } }) } const internals = brain as unknown as BrainInternals internals.lazyRebuildCompleted = false // simulate the cold first query return { brain, internals } } describe('lazy path honors EVERY provider’s not-ready report', () => { it('a not-ready METADATA provider blocks the completion latch and fires the rebuild', async () => { const { internals } = await warmLazyBrain() // The trap's shape: vector side looks fine (populated), metadata // provider says NOT ready — the old gate latched complete here. ;(internals.metadataIndex as { isReady?: () => boolean }).isReady = () => false const rebuildSpy = vi .spyOn(internals, 'rebuildIndexesIfNeeded') .mockResolvedValue(undefined) await internals.ensureIndexesLoaded() expect(rebuildSpy, 'not-ready metadata provider must fire the lazy rebuild').toHaveBeenCalledWith(true) }) it('control: all providers ready/unknown+populated → latch completes, no rebuild', async () => { const { internals } = await warmLazyBrain() ;(internals.metadataIndex as { isReady?: () => boolean }).isReady = () => true const rebuildSpy = vi .spyOn(internals, 'rebuildIndexesIfNeeded') .mockResolvedValue(undefined) await internals.ensureIndexesLoaded() expect(rebuildSpy).not.toHaveBeenCalled() expect(internals.lazyRebuildCompleted).toBe(true) }) })