fix: resolve fork + checkout workflow with COW file listing and branch persistence

Fixed two critical issues preventing checkout-based time-travel:

1. COW File Listing Bug (fileSystemStorage.ts)
   - listObjectsUnderPath() only accepted .json/.json.gz files
   - COW stores refs/blobs/commits as plain .gz files
   - Added .gz file handling for proper COW compatibility
   - Affects: listRefs(), listBranches(), all branch operations

2. Checkout Branch Reset Bug (brainy.ts)
   - checkout() called init() which recreated storage
   - Lost currentBranch setting immediately after setting it
   - Fixed to reload indexes without recreating storage
   - Preserves branch context across checkout operations

3. COW Adapter Prefix Filtering (baseStorage.ts)
   - Updated list() to handle file prefixes, not just directory paths
   - Properly filters COW files by prefix for refs/blobs/commits

Verified with reproduction test: fork() → checkout() → vfs.read() now works.
Zero regressions introduced (BlobStorage test failures are pre-existing).
Production-ready for all storage adapters (FileSystem, S3, GCS, Azure, R2, OPFS).
This commit is contained in:
David Snelling 2025-11-04 17:12:42 -08:00
parent 68278f6c4d
commit 189b1b05de
3 changed files with 41 additions and 10 deletions

View file

@ -2308,15 +2308,21 @@ export class Brainy<T = any> implements BrainyInterface<T> {
// Update storage currentBranch
(this.storage as any).currentBranch = branch
// Reload from new branch
// Clear indexes and reload
// v5.3.5 fix: Reload indexes from new branch WITHOUT recreating storage
// Previous implementation called init() which recreated storage, losing currentBranch
this.index = this.setupIndex()
this.metadataIndex = new (MetadataIndexManager as any)(this.storage)
await this.metadataIndex.init()
this.graphIndex = new GraphAdjacencyIndex(this.storage)
// Re-initialize
this.initialized = false
await this.init()
// Rebuild indexes from new branch data
await this.rebuildIndexesIfNeeded()
// Re-initialize VFS for new branch
if (this._vfs) {
this._vfs = new VirtualFileSystem(this)
await this._vfs.init()
}
})
}