Cloud Run cold starts taking 139 seconds due to 90MB WASM file with
embedded 87MB model weights. WASM compilation scales with file size.
Solution: Split into 2.4MB WASM (code only) + external model files.
- WASM compile: 139,000ms → 6-8ms
- Model load: N/A → 30-115ms
- Total init: 139,000ms → 136-240ms
New modelLoader.ts handles all environments:
- Node.js: fs.readFile()
- Bun: Bun.file()
- Bun --compile: auto-embedded assets
- Browser: fetch()
Zero config - same API, npm package includes model files.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
CRITICAL FIX for production blocker in v6.0.0:
Root Cause:
- BaseStorage.init() set isInitialized = true at the END of initialization
- If any code during init called ensureInitialized(), it triggered init() recursively
- This caused infinite loop on fresh workspace initialization
Fix:
- Set isInitialized = true at START of BaseStorage.init()
- Wrap in try/catch to reset flag on error
- Prevents recursive init() calls while maintaining error recovery
Impact:
- Fixes all 8 storage adapters (FileSystem, Memory, S3, R2, GCS, Azure, OPFS, Historical)
- Init now completes in ~1 second on fresh installation (was hanging)
- Workshop team can now use v6.0.0 features without infinite loop
- No new test failures (1178 tests passing)
Files:
- src/storage/baseStorage.ts: Move isInitialized = true to top of init()
- CHANGELOG.md: Document v6.0.1 hotfix
Co-Authored-By: Claude <noreply@anthropic.com>
CRITICAL BUG FIX: v5.10.0 regressed the v5.7.2 blob integrity bug, causing
100% VFS file read failure. This fix restores functionality with production-grade
defense-in-depth architecture and comprehensive testing.
Problem:
- v5.10.0 reintroduced bug where BlobStorage.read() hashed wrapped data
- Symptom: "Blob integrity check failed" on every VFS file read
- Impact: 100% failure rate in Workshop application
- Root Cause: Missing defense-in-depth unwrap verification
The Fix:
1. Defense-in-Depth Unwrapping
- Added unwrap verification in BlobStorage.read() before hash check (line 342)
- Added unwrap for metadata parsing (line 314)
- Ensures data is always unwrapped regardless of adapter behavior
2. DRY Architecture
- Created binaryDataCodec.ts as single source of truth
- Refactored baseStorage to use shared utilities
- All 8 storage adapters now use same implementation
3. Comprehensive Testing
- Added TestWrappingAdapter that actually wraps like production
- 3 new regression tests validate the fix
- Tests exercise real wrapping scenario that caused the bug
Architecture Improvements:
- ✅ Defense-in-Depth: Unwrap at BOTH adapter and blob layers
- ✅ DRY Principle: Single source of truth in binaryDataCodec.ts
- ✅ Works Across ALL Storage Adapters (8 total)
- ✅ Prevents Future Regressions: Real wrapping tests
Files Changed:
- NEW: src/storage/cow/binaryDataCodec.ts (single source of truth)
- FIXED: src/storage/cow/BlobStorage.ts (defense-in-depth unwrap)
- REFACTORED: src/storage/baseStorage.ts (uses shared codec)
- NEW: tests/helpers/TestWrappingAdapter.ts (real wrapping adapter)
- ADDED: 3 regression tests in tests/unit/storage/cow/BlobStorage.test.ts
- UPDATED: CHANGELOG.md, package.json (v5.10.1)
Related Issues:
- v5.7.2: Original bug - hashed wrapper instead of content
- v5.7.5: First fix - added unwrap to adapter (necessary but insufficient)
- v5.10.0: Regression - missing defense-in-depth in BlobStorage
- v5.10.1: Complete fix - defense-in-depth + DRY + tests
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
CRITICAL BUG FIX - v5.7.0 caused complete production failure
PROBLEM:
v5.7.0 introduced circular dependency deadlock during GraphAdjacencyIndex initialization:
GraphAdjacencyIndex.rebuild()
→ storage.getVerbs()
→ getVerbsBySource_internal()
→ getGraphIndex() [NEW in v5.7.0]
→ [waiting for rebuild to complete]
→ DEADLOCK
SYMPTOMS (Production Impact):
- ALL imports hung at "Reading Data Structure" for 760+ seconds
- brain.add() operations took 12+ seconds per entity (50x slower)
- Zero entities imported successfully
- 100% of Workshop users unable to import files
- No errors thrown - infinite wait
- Forced immediate rollback to v5.6.3
ROOT CAUSE:
v5.7.0 modified storage internal methods (getVerbsBySource_internal,
getVerbsByTarget_internal) to use GraphAdjacencyIndex optimization,
creating tight coupling where storage depends on index AND index depends
on storage. This violated separation of concerns and created deadlock.
SOLUTION (Architectural Fix):
Reverted storage internals to v5.6.3 implementation (lines 2320-2444):
- Storage layer simple, no index dependencies ✅
- GraphAdjacencyIndex can safely call storage.getVerbs() to rebuild ✅
- No circular dependency possible ✅
- Proper layered architecture restored ✅
LAYERS (Correct Architecture):
Layer 3 (Brainy/Queries): CAN use GraphAdjacencyIndex
Layer 2 (GraphAdjacencyIndex): Uses storage.getVerbs() to rebuild
Layer 1 (Storage Internals): NO GraphAdjacencyIndex calls
IMPACT:
- Slightly slower GraphAdjacencyIndex.rebuild() (one-time init cost)
- High-level queries still use optimized index
- Import performance unaffected (writes don't trigger init)
- NO breaking changes to public API
TESTING:
- Added 4 regression tests (tests/regression/v5.7.0-deadlock.test.ts)
- All 1146 existing tests pass ✅
- Import + relationships complete in <1 second (not 760+)
- No 12+ second delays per entity ✅
FILES CHANGED:
- src/storage/baseStorage.ts (reverted lines 2320-2444 to v5.6.3)
- tests/regression/v5.7.0-deadlock.test.ts (new regression tests)
- CHANGELOG.md (comprehensive v5.7.1 entry with upgrade instructions)
VERIFICATION:
Workshop team should upgrade immediately:
npm install @soulcraft/brainy@5.7.1
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixes critical bug where brain.clear() did not fully clear storage:
Root causes:
1. _cow/ directory contents deleted but directory not removed
2. In-memory counters (totalNounCount, totalVerbCount) not reset
3. COW could auto-reinitialize on next operation
Fixes applied:
- FileSystemStorage: Delete entire _cow/ directory with fs.rm()
- OPFSStorage: Delete _cow/ with removeEntry({recursive: true})
- S3CompatibleStorage: Reset counters after clear
- BaseStorage: Guard initializeCOW() against reinit when cowEnabled=false
- All adapters: Reset totalNounCount and totalVerbCount to 0
Impact: Resolves Workshop bug report - storage now properly clears from
103MB to 0 bytes, entity counts correctly return to 0.
GCSStorage, R2Storage, AzureBlobStorage already had correct implementations.