2025-10-24 11:42:47 -07:00
/ * *
2026-06-17 13:11:41 -07:00
* VFS - Knowledge Separation Test ( 8.0 )
2025-10-24 11:42:47 -07:00
*
2026-06-17 13:11:41 -07:00
* Exercises how VFS infrastructure entities coexist with knowledge - graph
* entities in the same brain , and how a query opts in / o u t o f t h e V F S l a y e r :
*
* - VFS files / directories are real entities , marked in metadata with
* ` isVFS: true ` / ` isVFSEntity: true ` and ` vfsType: 'file' | 'directory' ` .
* - ` brain.find() ` INCLUDES VFS entities by default ( 8.0 semantics ) .
* - ` brain.find({ excludeVFS: true }) ` drops the VFS infrastructure layer ,
* returning only knowledge entities — works on both the metadata - filter
* path and the vector / ` query ` path .
* - ` where: { vfsType: 'file' } ` selects VFS file entities explicitly .
* - Relationships can span VFS files and knowledge entities .
*
* Runs under the deterministic embedder ( tests / setup - integration . ts ) , so
* cross - text semantic ranking is not meaningful ; self - retrieval ( querying an
* entity by its own text ) and ` excludeVFS ` filtering are .
2025-10-24 11:42:47 -07:00
* /
import { describe , it , expect , beforeAll , afterAll } from 'vitest'
import { Brainy } from '../../src/brainy.js'
2026-06-17 13:11:41 -07:00
import { NounType , VerbType } from '../../src/types/graphTypes.js'
2025-10-24 11:42:47 -07:00
import * as fs from 'fs'
import * as path from 'path'
2026-06-17 13:11:41 -07:00
describe ( 'VFS-Knowledge Separation (8.0)' , ( ) = > {
2025-10-24 11:42:47 -07:00
const testDir = path . join ( process . cwd ( ) , 'test-vfs-knowledge-separation' )
let brain : Brainy
beforeAll ( async ( ) = > {
// Clean up
if ( fs . existsSync ( testDir ) ) {
fs . rmSync ( testDir , { recursive : true , force : true } )
}
fs . mkdirSync ( testDir , { recursive : true } )
2026-06-17 13:11:41 -07:00
brain = new Brainy ( {
requireSubtype : false ,
2025-10-24 11:42:47 -07:00
storage : {
type : 'filesystem' ,
options : { path : testDir }
}
} )
await brain . init ( )
2026-06-17 13:11:41 -07:00
// Seed the VFS layer + one knowledge entity used across the suite.
2025-11-02 11:38:12 -08:00
const vfs = brain . vfs
2025-10-24 11:42:47 -07:00
await vfs . init ( )
await vfs . mkdir ( '/docs' , { recursive : true } )
await vfs . writeFile ( '/docs/readme.md' , '# Hello World' )
2026-06-17 13:11:41 -07:00
await brain . add ( {
2025-10-24 11:42:47 -07:00
data : 'This is a knowledge document about AI' ,
type : NounType . Document ,
metadata : {
title : 'AI Research Paper' ,
category : 'research'
}
} )
2026-06-17 13:11:41 -07:00
} )
afterAll ( async ( ) = > {
// Close releases the writer lock + flushes; prevents background-flush bleed.
await brain . close ( )
if ( fs . existsSync ( testDir ) ) {
fs . rmSync ( testDir , { recursive : true , force : true } )
}
} )
2025-10-24 11:42:47 -07:00
2026-06-17 13:11:41 -07:00
it ( 'includes VFS entities in brain.find() by default' , async ( ) = > {
// 8.0: VFS infrastructure entities are returned by default. The /docs/readme.md
// file is a Document-typed entity carrying isVFS/vfsType markers, so a plain
// type query surfaces BOTH it and the knowledge document.
2025-10-24 11:42:47 -07:00
const results = await brain . find ( {
type : NounType . Document ,
limit : 100
} )
2026-06-17 13:11:41 -07:00
const vfsResults = results . filter ( ( r ) = > r . metadata ? . isVFS === true )
const knowledgeResults = results . filter ( ( r ) = > r . metadata ? . isVFS !== true )
2025-10-24 11:42:47 -07:00
2026-06-17 13:11:41 -07:00
// Default find() shows the VFS file alongside knowledge.
expect ( vfsResults . length ) . toBeGreaterThan ( 0 )
2025-10-24 11:42:47 -07:00
expect ( knowledgeResults . length ) . toBeGreaterThan ( 0 )
2026-06-17 13:11:41 -07:00
expect ( results . some ( ( r ) = > r . metadata ? . title === 'AI Research Paper' ) ) . toBe ( true )
expect ( results . some ( ( r ) = > r . metadata ? . vfsType === 'file' ) ) . toBe ( true )
2025-10-24 11:42:47 -07:00
} )
2026-06-17 13:11:41 -07:00
it ( 'excludes VFS entities when excludeVFS: true' , async ( ) = > {
// 8.0: excludeVFS drops the VFS infrastructure layer. Only knowledge entities remain.
2025-10-24 11:42:47 -07:00
const results = await brain . find ( {
type : NounType . Document ,
2026-06-17 13:11:41 -07:00
excludeVFS : true ,
2025-10-24 11:42:47 -07:00
limit : 100
} )
2026-06-17 13:11:41 -07:00
const vfsResults = results . filter ( ( r ) = > r . metadata ? . isVFS === true )
const knowledgeResults = results . filter ( ( r ) = > r . metadata ? . isVFS !== true )
2025-10-24 11:42:47 -07:00
2026-06-17 13:11:41 -07:00
expect ( vfsResults . length ) . toBe ( 0 )
2025-10-24 11:42:47 -07:00
expect ( knowledgeResults . length ) . toBeGreaterThan ( 0 )
2026-06-17 13:11:41 -07:00
expect ( results . some ( ( r ) = > r . metadata ? . title === 'AI Research Paper' ) ) . toBe ( true )
2025-10-24 11:42:47 -07:00
} )
it ( 'should allow relationships between VFS files and knowledge entities' , async ( ) = > {
2026-06-17 13:11:41 -07:00
// Get VFS file entity. VFS files are identified by vfsType (the indexed,
// queryable marker); they are included in find() by default.
2025-10-24 11:42:47 -07:00
const vfsFile = await brain . find ( {
where : {
path : '/docs/readme.md'
} ,
limit : 1
} )
expect ( vfsFile . length ) . toBe ( 1 )
2026-06-17 13:11:41 -07:00
expect ( vfsFile [ 0 ] . metadata ? . vfsType ) . toBe ( 'file' )
2025-10-24 11:42:47 -07:00
// Get knowledge entity
const knowledgeEntity = await brain . find ( {
type : NounType . Document ,
where : {
title : 'AI Research Paper'
} ,
2026-06-17 13:11:41 -07:00
excludeVFS : true ,
2025-10-24 11:42:47 -07:00
limit : 1
} )
expect ( knowledgeEntity . length ) . toBe ( 1 )
2026-06-17 13:11:41 -07:00
// Create relationship: knowledge entity -> references -> VFS file.
// relate() returns the new relation's id (string).
const relationId = await brain . relate ( {
2025-10-24 11:42:47 -07:00
from : knowledgeEntity [ 0 ] . id ,
to : vfsFile [ 0 ] . id ,
2026-06-17 13:11:41 -07:00
type : VerbType . References
2025-10-24 11:42:47 -07:00
} )
2026-06-17 13:11:41 -07:00
expect ( typeof relationId ) . toBe ( 'string' )
expect ( relationId . length ) . toBeGreaterThan ( 0 )
2025-10-24 11:42:47 -07:00
// Verify relationship exists
2026-06-11 14:51:00 -07:00
const relations = await brain . related ( {
2025-10-24 11:42:47 -07:00
from : knowledgeEntity [ 0 ] . id ,
to : vfsFile [ 0 ] . id
} )
expect ( relations . length ) . toBe ( 1 )
2026-06-17 13:11:41 -07:00
expect ( relations [ 0 ] . type ) . toBe ( VerbType . References )
2025-10-24 11:42:47 -07:00
} )
it ( 'should filter VFS entities using where clause' , async ( ) = > {
2026-06-17 13:11:41 -07:00
// Query for VFS files explicitly via the vfsType marker (indexed + queryable).
2025-10-24 11:42:47 -07:00
const vfsFiles = await brain . find ( {
where : {
vfsType : 'file'
} ,
limit : 100
} )
expect ( vfsFiles . length ) . toBeGreaterThan ( 0 )
2026-06-17 13:11:41 -07:00
expect ( vfsFiles . every ( ( f ) = > f . metadata ? . vfsType === 'file' ) ) . toBe ( true )
// Every vfsType:'file' entity is a VFS infrastructure entity.
expect ( vfsFiles . every ( ( f ) = > f . metadata ? . isVFS === true ) ) . toBe ( true )
2025-10-24 11:42:47 -07:00
2026-06-17 13:11:41 -07:00
// Query for non-VFS knowledge entities explicitly via a user metadata field.
2025-10-24 11:42:47 -07:00
const nonVFS = await brain . find ( {
where : {
category : 'research'
} ,
limit : 100
} )
expect ( nonVFS . length ) . toBeGreaterThan ( 0 )
2026-06-17 13:11:41 -07:00
expect ( nonVFS . every ( ( e ) = > e . metadata ? . isVFS !== true ) ) . toBe ( true )
expect ( nonVFS . every ( ( e ) = > e . metadata ? . vfsType === undefined ) ) . toBe ( true )
2025-10-24 11:42:47 -07:00
} )
it ( 'should handle semantic search with VFS filtering' , async ( ) = > {
2026-06-17 13:11:41 -07:00
// Self-retrieval: querying with the knowledge doc's own text returns it
// (deterministic embedder ⇒ cosine 1.0). With excludeVFS the VFS layer is dropped.
const knowledgeOnly = await brain . find ( {
query : 'This is a knowledge document about AI' ,
excludeVFS : true ,
2025-10-24 11:42:47 -07:00
limit : 10
} )
2026-06-17 13:11:41 -07:00
expect ( knowledgeOnly . length ) . toBeGreaterThan ( 0 )
expect ( knowledgeOnly . some ( ( r ) = > r . metadata ? . isVFS === true ) ) . toBe ( false )
expect ( knowledgeOnly . some ( ( r ) = > r . metadata ? . title === 'AI Research Paper' ) ) . toBe ( true )
// Default (no excludeVFS): self-retrieval of the VFS file by its own content
// returns it — VFS entities participate in vector search by default.
const withVFS = await brain . find ( {
query : '# Hello World' ,
2025-10-24 11:42:47 -07:00
limit : 10
} )
2026-06-17 13:11:41 -07:00
expect ( withVFS . some ( ( r ) = > r . metadata ? . path === '/docs/readme.md' ) ) . toBe ( true )
2025-10-24 11:42:47 -07:00
2026-06-17 13:11:41 -07:00
// excludeVFS on the vector path removes the VFS file even when its content matches.
const withVFSExcluded = await brain . find ( {
query : '# Hello World' ,
excludeVFS : true ,
limit : 10
} )
expect ( withVFSExcluded . some ( ( r ) = > r . metadata ? . isVFS === true ) ) . toBe ( false )
2025-10-24 11:42:47 -07:00
} )
} )