Entity Versioning (NEW): - Add complete entity versioning API (brain.versions.*) with 18 methods - Content-addressable storage with SHA-256 deduplication - Git-style version control: save, restore, compare, undo, prune - Auto-versioning augmentation with pattern-based filtering - Branch-isolated version histories - Complete integration tests and API documentation Critical Bug Fixes: - Fix commit() not updating branch refs (brainy.ts:2385) - Root cause: Passed "heads/main" which normalized to "refs/heads/heads/main" - Impact: All Git-style versioning features were broken - Fix: Pass branch name directly for correct normalization - Fix VFS entities missing isVFSEntity flag - Add isVFSEntity: true to all VFS files/folders for filtering - Resolves pollution of semantic search with filesystem entities - Updated in writeFile(), mkdir(), and root directory init Implementation: - src/versioning/VersionManager.ts - Core versioning engine - src/versioning/VersionStorage.ts - Content-addressable storage - src/versioning/VersionIndex.ts - Metadata indexing - src/versioning/VersionDiff.ts - Version comparison - src/versioning/VersioningAPI.ts - Public API interface - src/augmentations/versioningAugmentation.ts - Auto-versioning - tests/integration/versioning.test.ts - Full integration tests - tests/unit/versioning/ - Unit test suite Documentation: - Complete Entity Versioning API section in docs/api/README.md - VFS entity filtering guide with examples - Updated "What's New" section for v5.3.0 - Strategy docs for both critical bugs Test Results: - 1168 tests passing - Build: PASSING (no TypeScript errors) - Integration tests: ALL PASSING 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
104 lines
2.7 KiB
TypeScript
104 lines
2.7 KiB
TypeScript
/**
|
|
* Integration test to reproduce commit() ref update bug
|
|
* Bug: commit() creates blobs but doesn't update branch refs
|
|
*/
|
|
|
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
|
|
import { Brainy } from '../../src/brainy.js'
|
|
import * as fs from 'fs'
|
|
import * as path from 'path'
|
|
import * as zlib from 'zlib'
|
|
|
|
const TEST_DATA_PATH = './test-commit-ref-bug-data'
|
|
|
|
describe('Commit Ref Update Bug (v5.2.0)', () => {
|
|
let brain: Brainy
|
|
|
|
beforeEach(async () => {
|
|
// Clean up test data
|
|
if (fs.existsSync(TEST_DATA_PATH)) {
|
|
fs.rmSync(TEST_DATA_PATH, { recursive: true, force: true })
|
|
}
|
|
|
|
brain = new Brainy({
|
|
storage: {
|
|
type: 'filesystem',
|
|
path: TEST_DATA_PATH,
|
|
branch: 'main',
|
|
enableCompression: true
|
|
},
|
|
silent: false // Enable logging
|
|
})
|
|
|
|
await brain.init()
|
|
})
|
|
|
|
afterEach(() => {
|
|
if (fs.existsSync(TEST_DATA_PATH)) {
|
|
fs.rmSync(TEST_DATA_PATH, { recursive: true, force: true })
|
|
}
|
|
})
|
|
|
|
it('should update branch ref after commit', async () => {
|
|
// Add an entity
|
|
await brain.add({
|
|
data: 'Test entity',
|
|
type: 'concept',
|
|
metadata: { test: true }
|
|
})
|
|
|
|
// Create first commit
|
|
const commit1Hash = await brain.commit({
|
|
message: 'First commit',
|
|
author: 'test@example.com'
|
|
})
|
|
|
|
console.log(`\n=== Commit 1 created: ${commit1Hash} ===`)
|
|
|
|
// Check the ref file directly
|
|
const refPath = path.join(TEST_DATA_PATH, '_cow', 'ref:refs', 'heads', 'main.gz')
|
|
|
|
expect(fs.existsSync(refPath), 'Ref file should exist').toBe(true)
|
|
|
|
const refContent1 = JSON.parse(
|
|
zlib.gunzipSync(fs.readFileSync(refPath)).toString()
|
|
)
|
|
|
|
console.log('Ref after commit 1:', {
|
|
commitHash: refContent1.commitHash,
|
|
updatedAt: new Date(refContent1.updatedAt).toISOString()
|
|
})
|
|
|
|
// THIS IS THE BUG: commitHash should equal commit1Hash
|
|
expect(refContent1.commitHash).toBe(commit1Hash)
|
|
expect(refContent1.commitHash).not.toBe('0'.repeat(64))
|
|
|
|
// Add another entity
|
|
await brain.add({
|
|
data: 'Second entity',
|
|
type: 'concept'
|
|
})
|
|
|
|
// Create second commit
|
|
const commit2Hash = await brain.commit({
|
|
message: 'Second commit',
|
|
author: 'test@example.com'
|
|
})
|
|
|
|
console.log(`\n=== Commit 2 created: ${commit2Hash} ===`)
|
|
|
|
// Check ref again
|
|
const refContent2 = JSON.parse(
|
|
zlib.gunzipSync(fs.readFileSync(refPath)).toString()
|
|
)
|
|
|
|
console.log('Ref after commit 2:', {
|
|
commitHash: refContent2.commitHash,
|
|
updatedAt: new Date(refContent2.updatedAt).toISOString()
|
|
})
|
|
|
|
// THIS IS THE BUG: commitHash should equal commit2Hash
|
|
expect(refContent2.commitHash).toBe(commit2Hash)
|
|
expect(refContent2.updatedAt).toBeGreaterThan(refContent1.updatedAt)
|
|
})
|
|
})
|