fix: resolve critical v5.0.0 metadata race condition

CRITICAL BUG FIX: TypeAwareStorage metadata race condition

Problem:
- saveNoun() called before saveNounMetadata()
- TypeAwareStorage couldn't determine entity type (not cached yet)
- Defaulted to 'thing' and saved to wrong storage path
- Later saveNounMetadata() saved to correct path
- Noun and metadata in different locations = entity not found

Impact:
- Broke VFS file operations completely
- Broke brain.get(), brain.relate(), brain.find()
- All metadata-dependent features failed
- Workshop team completely blocked

Solution:
- Reversed save order: saveNounMetadata() FIRST, then saveNoun()
- Type now cached before saveNoun() needs it
- Both saved to correct type-aware paths

Additional Fixes:
- Make baseStorage.initializeCOW() public (was protected)
- Remove enableCOW config option (cleanup)
- COW auto-init temporarily disabled (deadlock issue)

Known Limitations (v5.0.1):
- Fork API exists but COW requires manual init
- Will be zero-config in v5.1.0

Fixes: Workshop Bug Report (VFS metadata missing)
This commit is contained in:
David Snelling 2025-11-02 07:45:29 -08:00
parent f3e98a8bde
commit 12d8ea7efc
5 changed files with 64 additions and 16 deletions

View file

@ -345,10 +345,9 @@ export interface StorageOptions {
/**
* COW (Copy-on-Write) configuration for instant fork() capability
* v5.0.0+
* v5.0.1: COW is now always enabled (automatic, zero-config)
*/
branch?: string // Current branch name (default: 'main')
enableCOW?: boolean // Enable Copy-on-Write support (default: false for v5.0.0)
enableCompression?: boolean // Enable zstd compression for COW blobs (default: true)
}
@ -387,12 +386,13 @@ async function wrapWithTypeAware(
verbose
}) as any
// Initialize COW if enabled
if (options?.enableCOW && typeof wrapped.initializeCOW === 'function') {
await wrapped.initializeCOW({
branch: options.branch || 'main',
enableCompression: options.enableCompression !== false
})
// v5.0.1: COW will be initialized AFTER storage.init() in Brainy
// Store COW options for later initialization
if (typeof wrapped.initializeCOW === 'function') {
wrapped._cowOptions = {
branch: options?.branch || 'main',
enableCompression: options?.enableCompression !== false
}
}
return wrapped