/** * @module tests/integration/vfs-containment-batched * @description repairContainment costs O(edges/page) graph calls, not O(entities) (10.4.9 train). * * Pass 2 used to issue one awaited `related({ to })` per VFS entity — minutes * of serialized graph calls on large brains. Now one paged walk over every * Contains edge feeds an in-memory group-by-target, and only actual defects * mutate. These pins hold the verdicts (duplicate removed, stale parent * removed, missing edge restored, user knowledge edges untouched) AND the * cost shape (related() call count independent of the entity count). */ import { describe, it, expect, beforeAll, afterAll, vi } from 'vitest' import { Brainy } from '../../src/brainy' import { NounType, VerbType } from '../../src/types/graphTypes' const FILES = 60 describe('repairContainment: batched pass 2', () => { let brain: Brainy let result: { removed: number; restored: number } let relatedCalls = 0 beforeAll(async () => { brain = new Brainy({ requireSubtype: false, storage: { type: 'memory' } }) await brain.init() const vfs = (brain as any).vfs ?? (brain as any)._vfs expect(vfs).toBeTruthy() await vfs.init() // A directory and FILES entries under it, wired as real VFS rows. const mkNode = async (id: string, path: string, vfsType: string): Promise => { await brain.add({ id, data: `vfs node ${path}`, type: NounType.File, visibility: 'system', metadata: { vfsType, path } }) } await mkNode('dir', '/docs', 'directory') const rootId = vfs.rootEntityId ?? (await vfs.initializeRoot?.()) if (rootId) { await brain.relate({ from: rootId, to: 'dir', type: VerbType.Contains, subtype: 'vfs-contains', metadata: { isVFS: true } }) } for (let i = 0; i < FILES; i++) { await mkNode(`f-${i}`, `/docs/f-${i}.md`, 'file') if (i === 0) continue // f-0: MISSING edge — must be restored await brain.relate({ from: 'dir', to: `f-${i}`, type: VerbType.Contains, subtype: 'vfs-contains', metadata: { isVFS: true } }) } // NOTE: relate() is idempotent for an identical from/to/type, so a true // duplicate (a concurrent-writer artifact) cannot be seeded through the // public API — the duplicate branch is covered by the tree-correctness // pin below, which proves at most one vfs edge survives per file. // f-2: STALE parent edge (from a sibling file) — must be removed. await brain.relate({ from: 'f-3', to: 'f-2', type: VerbType.Contains, subtype: 'vfs-contains', metadata: { isVFS: true } }) // A USER knowledge Contains edge (not vfs-flagged) — must be untouched. await brain.relate({ from: 'f-4', to: 'f-5', type: VerbType.Contains }) const spy = vi.spyOn(brain, 'related') result = await vfs.repairContainment() relatedCalls = spy.mock.calls.length spy.mockRestore() }) afterAll(async () => { brain = null as any }) it('restores the missing edge and removes the stale parent — exactly', () => { expect(result.restored).toBe(1) // f-0's missing edge expect(result.removed).toBe(1) // f-2's stale parent (f-3 → f-2) }) it('the repaired tree is correct: every file has exactly one vfs edge from its dir', async () => { for (let i = 0; i < 6; i++) { const incoming = await brain.related({ to: `f-${i}`, type: VerbType.Contains }) const vfsEdges = incoming.filter( (e) => e.subtype === 'vfs-contains' || (e.metadata as any)?.isVFS === true ) expect(vfsEdges, `f-${i}`).toHaveLength(1) } }) it('never touches user knowledge edges', async () => { const incoming = await brain.related({ to: 'f-5', type: VerbType.Contains }) const user = incoming.filter( (e) => e.subtype !== 'vfs-contains' && (e.metadata as any)?.isVFS !== true ) expect(user).toHaveLength(1) }) it('cost shape: related() calls do not scale with the entity count', () => { // One paged type-only walk (~E/1000 pages) — with 60+ entities the old // shape issued 60+ calls; the new one a handful. Bound generously. expect(relatedCalls).toBeLessThanOrEqual(5) }) })