/** * @module tests/unit/storage/sharding-new-installation-log * @description Regression for BR-8-BOOT-INDEX symptom 1. Brainy 8.0 stores * entities in the canonical `entities/nouns///vectors.json` layout, * but the legacy sharding probe (`detectExistingShardingDepth`) inspected * `entities/nouns/hnsw` — a 7.x directory the 8.0 write path never populates — * so it returned null and logged "📁 New installation" for EVERY store on EVERY * boot, including established brains holding thousands of entities. The * new-vs-existing decision now consults the canonical layout the DB actually * uses (`hasCanonicalEntities`), so an established brain reports its true entity * count and only a genuinely empty store says "New installation". */ import { describe, it, expect, vi, afterEach } from 'vitest' import { mkdtempSync, rmSync } from 'fs' import { tmpdir } from 'os' import { join } from 'path' import { FileSystemStorage } from '../../../src/storage/adapters/fileSystemStorage.js' import type { NounMetadata } from '../../../src/coreTypes.js' const dirs: string[] = [] function mkTmp(): string { const d = mkdtempSync(join(tmpdir(), 'brainy-newinstall-')) dirs.push(d) return d } afterEach(() => { for (const d of dirs.splice(0)) rmSync(d, { recursive: true, force: true }) vi.restoreAllMocks() }) /** Release a raw FileSystemStorage so a subsequent open of the dir is unblocked. */ async function teardown(s: any): Promise { try { await s.flush?.() } catch { /* best effort */ } try { s.stopFlushRequestWatcher?.() } catch { /* best effort */ } try { await s.releaseWriterLock?.() } catch { /* best effort */ } } /** Capture everything written to console.log during `fn()`. */ async function captureLog(fn: () => Promise): Promise { const lines: string[] = [] const spy = vi .spyOn(console, 'log') .mockImplementation((...args: any[]) => { lines.push(args.map(String).join(' ')) }) try { await fn() } finally { spy.mockRestore() } return lines.join('\n') } const VEC = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8] async function seedOne(s: any, id: string): Promise { await s.saveNounMetadata(id, { noun: 'thing', createdAt: Date.now(), updatedAt: Date.now() } as NounMetadata) await s.saveNoun({ id, vector: VEC, connections: new Map(), level: 0 }) } describe('FileSystemStorage boot log: an established brain is not "New installation" (BR-8-BOOT-INDEX)', () => { it('a genuinely fresh store still logs "New installation"', async () => { const dir = mkTmp() const storage = new FileSystemStorage(dir) const out = await captureLog(() => storage.init()) expect(out).toContain('New installation') await teardown(storage) }) it('an established store (canonical entities present) does NOT log "New installation" on reopen', async () => { const dir = mkTmp() // 1. Author an entity → canonical entities/nouns///vectors.json. const first = new FileSystemStorage(dir) await first.init() await seedOne(first, 'a'.repeat(32)) await teardown(first) // 2. Reopen: the boot log must reflect the established store, not "New installation". const second = new FileSystemStorage(dir) const out = await captureLog(() => second.init()) expect(out).not.toContain('New installation') expect(out).toContain('Using depth 1 sharding') await teardown(second) }) it('counts RECOVER from the canonical layout when counts.json is lost (container-restart case)', async () => { const dir = mkTmp() // Establish a store with 3 entities (canonical layout + counts.json). const first: any = new FileSystemStorage(dir) await first.init() for (const c of ['a', 'b', 'c']) await seedOne(first, c.repeat(32)) await teardown(first) // Simulate the lost/corrupted counts.json a container restart can leave. for (const f of ['counts.json', 'counts.json.gz']) { rmSync(join(dir, '_system', f), { force: true }) } // Reopen: the recovery scan must count the CANONICAL tree. The removed // implementation scanned the vestigial `entities/*/hnsw` dirs and // re-initialized every counter to ZERO on real data. const second: any = new FileSystemStorage(dir) await second.init() expect(await second.getNounCount()).toBe(3) await teardown(second) }) it('hasCanonicalEntities() sees the canonical shard tree — independent of counts.json', async () => { const dir = mkTmp() const s: any = new FileSystemStorage(dir) await s.init() // Fresh: only the vestigial `hnsw` dir exists → no canonical entities. expect(await s.hasCanonicalEntities()).toBe(false) // After a canonical write the 2-hex shard dir exists → established, even if // counts.json were later lost on a container restart (the fallback path). await seedOne(s, 'c'.repeat(32)) expect(await s.hasCanonicalEntities()).toBe(true) await teardown(s) }) })