feat(8.0)!: delete fork/branch/commit/history/versions — superseded by the Db API
The COW version-control surface (fork, branches, checkout, commit,
getHistory/streamHistory, asOfCommit, brain.versions) is gone, along with
its subsystems: src/versioning/, the COW object store (CommitLog,
CommitObject, RefManager, TreeObject), HistoricalStorageAdapter, and the
TypeAwareHNSWIndex path it kept alive. The Db API (now/transact/asOf/
with/persist/restore) is the one versioning model in 8.0.
Survivors and replacements:
- BlobStorage survives (the VFS stores file content through it), relocated
to src/storage/blobStorage.ts with binaryDataCodec.ts; its adapter
interface is now BlobStoreAdapter, slimmed to the consumed surface
(write/read/has/delete/getMetadata + MIME-aware compression policy).
- brain.migrate() backup branches are replaced by persist-before-migrate:
MigrateOptions.backupTo persists a hard-link snapshot of the current
generation before any transform runs; MigrationResult.backupPath reports
it, and brain.restore(path) brings it back wholesale.
- CLI: cow.ts (fork/branch/checkout/history/migrate) is replaced by
snapshot.ts — snapshot <path>, restore <path>, history (tx-log),
generation.
- New public read API: brain.transactionLog({limit}) exposes the reified
tx-log (generation/timestamp/meta, newest first) that backs the CLI
history command; TxLogEntry is exported.
Tests: superseded suites deleted; fork/commit blocks excised from shared
suites; BlobStorage tests relocated + reworked against the slimmed store;
migration tests now prove the backupTo snapshot/restore round trip; new
transactionLog coverage in db-mvcc.
2026-06-10 15:22:47 -07:00
|
|
|
/**
|
|
|
|
|
* Hybrid Search VFS Integration Tests
|
|
|
|
|
*
|
|
|
|
|
* Verifies that hybrid search works correctly with VFS entities:
|
|
|
|
|
* file content is searchable by default, and `excludeVFS` filters
|
|
|
|
|
* VFS entities out of results.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
|
|
|
|
|
import { Brainy } from '../../src/brainy'
|
|
|
|
|
import { NounType } from '../../src/types/graphTypes'
|
|
|
|
|
import * as fs from 'fs'
|
|
|
|
|
import * as path from 'path'
|
|
|
|
|
import * as os from 'os'
|
|
|
|
|
|
|
|
|
|
describe('Hybrid Search with VFS', () => {
|
|
|
|
|
let brain: Brainy<any>
|
|
|
|
|
let testDir: string
|
|
|
|
|
|
|
|
|
|
beforeEach(async () => {
|
|
|
|
|
testDir = path.join(os.tmpdir(), `brainy-hybrid-vfs-test-${Date.now()}`)
|
|
|
|
|
fs.mkdirSync(testDir, { recursive: true })
|
|
|
|
|
|
fix(tests): the health-gate pin follows the verdict, and the VFS suite uses its own store
Two gate failures on main, one real and one long-hidden.
THE HEALTH-GATE PIN encoded the old law — "narrates once per generation, twice
across a generation bump" — which the content-keyed dedupe deliberately
replaced. A provider's `generation` bumps on every ledger mutation and every
rebuild boundary, so keying narration on it re-printed an unchanged health line
on every read that consulted a busy provider, and let a provider that never
bumped suppress a line whose reasons had genuinely changed. The pin now asserts
BOTH directions: an unchanged verdict stays silent however the counter moves,
and a changed verdict is always heard.
THE VFS HYBRID-SEARCH SUITE configured its store with `options.basePath`, an
alias removed at the 8.0 major that configures nothing. The suite was therefore
never using its temp directory — it opened the DEFAULT store, shared with every
other run on the machine, and accumulated tens of thousands of rows until it
failed on that shared store's graph adjacency instead of on anything it tests.
It now passes `storage.path`. The suite drops from 6.5s to 0.3s, which is the
measure of how much foreign data it had been opening.
Neither failure was caused by the release branch; the first is the branch's own
behaviour change meeting its outdated pin, the second predates it.
2026-08-28 12:27:40 -07:00
|
|
|
// `storage.path`, NOT the pre-8.0 `options.basePath` alias. That alias was
|
|
|
|
|
// removed at the 8.0 major and configures nothing, so this suite silently
|
|
|
|
|
// opened the DEFAULT store instead of its own temp directory — sharing one
|
|
|
|
|
// on-disk brain with every other run on the machine, accumulating tens of
|
|
|
|
|
// thousands of rows, and eventually failing on that shared store's graph
|
|
|
|
|
// adjacency rather than on anything it was written to test.
|
feat(8.0)!: delete fork/branch/commit/history/versions — superseded by the Db API
The COW version-control surface (fork, branches, checkout, commit,
getHistory/streamHistory, asOfCommit, brain.versions) is gone, along with
its subsystems: src/versioning/, the COW object store (CommitLog,
CommitObject, RefManager, TreeObject), HistoricalStorageAdapter, and the
TypeAwareHNSWIndex path it kept alive. The Db API (now/transact/asOf/
with/persist/restore) is the one versioning model in 8.0.
Survivors and replacements:
- BlobStorage survives (the VFS stores file content through it), relocated
to src/storage/blobStorage.ts with binaryDataCodec.ts; its adapter
interface is now BlobStoreAdapter, slimmed to the consumed surface
(write/read/has/delete/getMetadata + MIME-aware compression policy).
- brain.migrate() backup branches are replaced by persist-before-migrate:
MigrateOptions.backupTo persists a hard-link snapshot of the current
generation before any transform runs; MigrationResult.backupPath reports
it, and brain.restore(path) brings it back wholesale.
- CLI: cow.ts (fork/branch/checkout/history/migrate) is replaced by
snapshot.ts — snapshot <path>, restore <path>, history (tx-log),
generation.
- New public read API: brain.transactionLog({limit}) exposes the reified
tx-log (generation/timestamp/meta, newest first) that backs the CLI
history command; TxLogEntry is exported.
Tests: superseded suites deleted; fork/commit blocks excised from shared
suites; BlobStorage tests relocated + reworked against the slimmed store;
migration tests now prove the backupTo snapshot/restore round trip; new
transactionLog coverage in db-mvcc.
2026-06-10 15:22:47 -07:00
|
|
|
brain = new Brainy({ requireSubtype: false,
|
|
|
|
|
storage: {
|
|
|
|
|
type: 'filesystem',
|
fix(tests): the health-gate pin follows the verdict, and the VFS suite uses its own store
Two gate failures on main, one real and one long-hidden.
THE HEALTH-GATE PIN encoded the old law — "narrates once per generation, twice
across a generation bump" — which the content-keyed dedupe deliberately
replaced. A provider's `generation` bumps on every ledger mutation and every
rebuild boundary, so keying narration on it re-printed an unchanged health line
on every read that consulted a busy provider, and let a provider that never
bumped suppress a line whose reasons had genuinely changed. The pin now asserts
BOTH directions: an unchanged verdict stays silent however the counter moves,
and a changed verdict is always heard.
THE VFS HYBRID-SEARCH SUITE configured its store with `options.basePath`, an
alias removed at the 8.0 major that configures nothing. The suite was therefore
never using its temp directory — it opened the DEFAULT store, shared with every
other run on the machine, and accumulated tens of thousands of rows until it
failed on that shared store's graph adjacency instead of on anything it tests.
It now passes `storage.path`. The suite drops from 6.5s to 0.3s, which is the
measure of how much foreign data it had been opening.
Neither failure was caused by the release branch; the first is the branch's own
behaviour change meeting its outdated pin, the second predates it.
2026-08-28 12:27:40 -07:00
|
|
|
path: testDir
|
feat(8.0)!: delete fork/branch/commit/history/versions — superseded by the Db API
The COW version-control surface (fork, branches, checkout, commit,
getHistory/streamHistory, asOfCommit, brain.versions) is gone, along with
its subsystems: src/versioning/, the COW object store (CommitLog,
CommitObject, RefManager, TreeObject), HistoricalStorageAdapter, and the
TypeAwareHNSWIndex path it kept alive. The Db API (now/transact/asOf/
with/persist/restore) is the one versioning model in 8.0.
Survivors and replacements:
- BlobStorage survives (the VFS stores file content through it), relocated
to src/storage/blobStorage.ts with binaryDataCodec.ts; its adapter
interface is now BlobStoreAdapter, slimmed to the consumed surface
(write/read/has/delete/getMetadata + MIME-aware compression policy).
- brain.migrate() backup branches are replaced by persist-before-migrate:
MigrateOptions.backupTo persists a hard-link snapshot of the current
generation before any transform runs; MigrationResult.backupPath reports
it, and brain.restore(path) brings it back wholesale.
- CLI: cow.ts (fork/branch/checkout/history/migrate) is replaced by
snapshot.ts — snapshot <path>, restore <path>, history (tx-log),
generation.
- New public read API: brain.transactionLog({limit}) exposes the reified
tx-log (generation/timestamp/meta, newest first) that backs the CLI
history command; TxLogEntry is exported.
Tests: superseded suites deleted; fork/commit blocks excised from shared
suites; BlobStorage tests relocated + reworked against the slimmed store;
migration tests now prove the backupTo snapshot/restore round trip; new
transactionLog coverage in db-mvcc.
2026-06-10 15:22:47 -07:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
await brain.init()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
afterEach(async () => {
|
|
|
|
|
await brain.close()
|
|
|
|
|
// Cleanup test directory
|
|
|
|
|
try {
|
|
|
|
|
fs.rmSync(testDir, { recursive: true, force: true })
|
|
|
|
|
} catch (e) {
|
|
|
|
|
// Ignore cleanup errors
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should include VFS file content in hybrid search', async () => {
|
|
|
|
|
// Write a file via VFS
|
|
|
|
|
const vfs = brain.vfs
|
|
|
|
|
await vfs.writeFile('/docs/readme.txt', 'This is a readme file with important information')
|
|
|
|
|
|
|
|
|
|
// Search should find VFS content
|
|
|
|
|
const results = await brain.find({
|
|
|
|
|
query: 'readme important',
|
|
|
|
|
limit: 10
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// VFS entities should appear in results
|
|
|
|
|
expect(results.length).toBeGreaterThan(0)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should exclude VFS with excludeVFS flag in hybrid search', async () => {
|
|
|
|
|
// Add regular entity
|
|
|
|
|
const entityId = await brain.add({
|
|
|
|
|
data: 'regular document about readme files',
|
|
|
|
|
type: NounType.Document,
|
|
|
|
|
metadata: { source: 'api' }
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Write VFS file
|
|
|
|
|
await brain.vfs.writeFile('/readme.md', 'VFS readme content')
|
|
|
|
|
|
|
|
|
|
// Search with excludeVFS should only find regular entity
|
|
|
|
|
const results = await brain.find({
|
|
|
|
|
query: 'readme',
|
|
|
|
|
excludeVFS: true,
|
|
|
|
|
limit: 10
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
expect(results.some(r => r.id === entityId)).toBe(true)
|
|
|
|
|
// VFS entities should be excluded
|
|
|
|
|
expect(results.every(r => !r.metadata?.vfsType)).toBe(true)
|
|
|
|
|
})
|
|
|
|
|
})
|