@soulcraft/brainy 5.9.0 → 5.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30,6 +30,7 @@ export declare class VirtualFileSystem implements IVirtualFileSystem {
30
30
  private backgroundTimer;
31
31
  private mkdirLocks;
32
32
  private rootInitPromise;
33
+ private static readonly VFS_ROOT_ID;
33
34
  constructor(brain?: Brainy);
34
35
  /**
35
36
  * v5.2.0: Access to BlobStorage for unified file storage
@@ -54,15 +55,25 @@ export declare class VirtualFileSystem implements IVirtualFileSystem {
54
55
  */
55
56
  private initializeRoot;
56
57
  /**
57
- * v5.8.0: Actual root initialization logic
58
- * Uses brain.find() with no caching to get consistent results
58
+ * v5.10.0: Atomic root initialization with fixed ID
59
+ * Uses deterministic ID to prevent duplicates across all VFS instances
60
+ *
61
+ * ARCHITECTURAL FIX: Instead of query-then-create (race condition),
62
+ * we use a fixed ID so storage-level uniqueness prevents duplicates.
59
63
  */
60
64
  private doInitializeRoot;
61
65
  /**
62
- * v5.8.0: Smart root selection when duplicates exist
63
- * Selects root with MOST children (not oldest) to preserve user data
66
+ * v5.10.0: Get standard root metadata
67
+ * Centralized to ensure consistency
64
68
  */
65
- private selectBestRoot;
69
+ private getRootMetadata;
70
+ /**
71
+ * v5.10.0: Cleanup old UUID-based VFS roots (migration from v5.9.0)
72
+ * Called during init to remove duplicate roots created before fixed-ID fix
73
+ *
74
+ * This is a one-time migration helper that can be removed in future versions.
75
+ */
76
+ private cleanupOldRoots;
66
77
  /**
67
78
  * Read a file's content
68
79
  */
@@ -61,6 +61,8 @@ export class VirtualFileSystem {
61
61
  // Removed brain.init() check to prevent infinite recursion
62
62
  // Create or find root entity
63
63
  this.rootEntityId = await this.initializeRoot();
64
+ // v5.10.0: Clean up old UUID-based roots from v5.9.0 (one-time migration)
65
+ await this.cleanupOldRoots();
64
66
  // Initialize projection registry with auto-discovery of built-in projections
65
67
  this.projectionRegistry = new ProjectionRegistry();
66
68
  this.registerBuiltInProjections();
@@ -126,128 +128,115 @@ export class VirtualFileSystem {
126
128
  // This prevents re-initialization and serves as a cache
127
129
  }
128
130
  /**
129
- * v5.8.0: Actual root initialization logic
130
- * Uses brain.find() with no caching to get consistent results
131
+ * v5.10.0: Atomic root initialization with fixed ID
132
+ * Uses deterministic ID to prevent duplicates across all VFS instances
133
+ *
134
+ * ARCHITECTURAL FIX: Instead of query-then-create (race condition),
135
+ * we use a fixed ID so storage-level uniqueness prevents duplicates.
131
136
  */
132
137
  async doInitializeRoot() {
133
- // Query for existing roots using brain.find()
134
- // Use higher limit and no cache to ensure we catch all roots
135
- const roots = await this.brain.find({
136
- type: NounType.Collection,
137
- where: {
138
- path: '/',
139
- vfsType: 'directory'
140
- },
141
- limit: 50, // Higher limit to catch all possible duplicates
142
- excludeVFS: false // CRITICAL: Don't exclude VFS entities!
143
- });
144
- if (roots.length > 0) {
145
- // Auto-heal if duplicates exist
146
- if (roots.length > 1) {
147
- console.warn(`⚠️ VFS: Found ${roots.length} duplicate root directories`);
148
- console.warn(`⚠️ VFS: Auto-selecting best root (most children)`);
149
- return await this.selectBestRoot(roots);
150
- }
151
- // Single root - verify metadata and return
152
- const root = roots[0];
153
- // Extract metadata safely from Result object
154
- const metadata = root.metadata || root;
155
- // Ensure proper metadata structure
156
- if (!metadata.vfsType || metadata.vfsType !== 'directory') {
157
- console.warn(`⚠️ VFS: Root metadata incomplete, repairing...`);
158
- await this.brain.update({
159
- id: root.id,
160
- metadata: {
161
- ...metadata,
162
- path: '/',
163
- name: '',
164
- vfsType: 'directory',
165
- isVFS: true,
166
- isVFSEntity: true,
167
- size: 0,
168
- permissions: 0o755,
169
- owner: 'root',
170
- group: 'root',
171
- accessed: Date.now(),
172
- modified: Date.now()
173
- }
174
- });
138
+ const rootId = VirtualFileSystem.VFS_ROOT_ID;
139
+ // Try to get existing root by fixed ID (O(1) lookup, not query)
140
+ try {
141
+ const existingRoot = await this.brain.get(rootId);
142
+ if (existingRoot) {
143
+ // Root exists - verify metadata is correct
144
+ const metadata = existingRoot.metadata || existingRoot;
145
+ if (!metadata.vfsType || metadata.vfsType !== 'directory') {
146
+ console.warn('⚠️ VFS: Root metadata incomplete, repairing...');
147
+ await this.brain.update({
148
+ id: rootId,
149
+ metadata: this.getRootMetadata()
150
+ });
151
+ }
152
+ return rootId;
175
153
  }
176
- return root.id;
177
154
  }
178
- // ONLY create root if absolutely zero roots exist
179
- console.log('VFS: Creating root directory (verified zero roots exist)');
180
- const root = await this.brain.add({
181
- data: '/',
182
- type: NounType.Collection,
183
- metadata: {
184
- path: '/',
185
- name: '',
186
- vfsType: 'directory',
187
- isVFS: true,
188
- isVFSEntity: true,
189
- size: 0,
190
- permissions: 0o755,
191
- owner: 'root',
192
- group: 'root',
193
- accessed: Date.now(),
194
- modified: Date.now(),
195
- createdAt: Date.now()
196
- }
197
- });
198
- return root;
155
+ catch (error) {
156
+ // Root doesn't exist yet - proceed to creation
157
+ }
158
+ // Create root with fixed ID (idempotent - fails gracefully if exists)
159
+ try {
160
+ console.log('VFS: Creating root directory (fixed ID: 00000000-0000-0000-0000-000000000000)');
161
+ await this.brain.add({
162
+ id: rootId, // Fixed ID - storage ensures uniqueness
163
+ data: '/',
164
+ type: NounType.Collection,
165
+ metadata: this.getRootMetadata()
166
+ });
167
+ return rootId;
168
+ }
169
+ catch (error) {
170
+ // If creation failed due to duplicate ID, another instance created it
171
+ // This is normal in concurrent scenarios - just return the fixed ID
172
+ const errorMsg = error?.message?.toLowerCase() || '';
173
+ if (errorMsg.includes('already exists') ||
174
+ errorMsg.includes('duplicate') ||
175
+ errorMsg.includes('eexist')) {
176
+ console.log('VFS: Root already created by another instance, using existing');
177
+ return rootId;
178
+ }
179
+ // Unexpected error
180
+ throw error;
181
+ }
182
+ }
183
+ /**
184
+ * v5.10.0: Get standard root metadata
185
+ * Centralized to ensure consistency
186
+ */
187
+ getRootMetadata() {
188
+ return {
189
+ path: '/',
190
+ name: '',
191
+ vfsType: 'directory',
192
+ isVFS: true,
193
+ isVFSEntity: true,
194
+ size: 0,
195
+ permissions: 0o755,
196
+ owner: 'root',
197
+ group: 'root',
198
+ accessed: Date.now(),
199
+ modified: Date.now()
200
+ };
199
201
  }
200
202
  /**
201
- * v5.8.0: Smart root selection when duplicates exist
202
- * Selects root with MOST children (not oldest) to preserve user data
203
+ * v5.10.0: Cleanup old UUID-based VFS roots (migration from v5.9.0)
204
+ * Called during init to remove duplicate roots created before fixed-ID fix
205
+ *
206
+ * This is a one-time migration helper that can be removed in future versions.
203
207
  */
204
- async selectBestRoot(roots) {
205
- // Count descendants for each root
206
- const rootStats = await Promise.all(roots.map(async (root) => {
207
- const children = await this.brain.find({
208
- where: { parent: root.id },
209
- limit: 1000 // Cap to prevent huge queries
208
+ async cleanupOldRoots() {
209
+ try {
210
+ // Find any old VFS roots with UUID-based IDs (not our fixed ID)
211
+ const oldRoots = await this.brain.find({
212
+ type: NounType.Collection,
213
+ where: {
214
+ path: '/',
215
+ vfsType: 'directory'
216
+ },
217
+ limit: 100,
218
+ excludeVFS: false
210
219
  });
211
- // Extract metadata safely from Result object
212
- const metadata = root.metadata || root;
213
- return {
214
- id: root.id,
215
- createdAt: metadata.createdAt || metadata.modified || 0,
216
- childCount: children.length,
217
- sampleChildren: children.slice(0, 3).map(c => {
218
- const childMeta = c.metadata || c;
219
- return childMeta.path || childMeta.name || 'unknown';
220
- })
221
- };
222
- }));
223
- // Sort by child count (DESC), then by creation time (ASC) as tiebreaker
224
- rootStats.sort((a, b) => {
225
- if (b.childCount !== a.childCount) {
226
- return b.childCount - a.childCount; // Most children first
227
- }
228
- return a.createdAt - b.createdAt; // Oldest first (tiebreaker)
229
- });
230
- const bestRoot = rootStats[0];
231
- const emptyRoots = rootStats.filter(r => r.childCount === 0);
232
- // Log detailed statistics
233
- console.warn(`\n📊 VFS Root Statistics:`);
234
- for (const stat of rootStats) {
235
- const shortId = stat.id.substring(0, 8);
236
- const created = stat.createdAt ? new Date(stat.createdAt).toISOString() : 'unknown';
237
- console.warn(` Root ${shortId}: ${stat.childCount} children, created ${created}`);
238
- if (stat.sampleChildren.length > 0) {
239
- console.warn(` Sample: ${stat.sampleChildren.join(', ')}`);
220
+ // Filter out our fixed-ID root
221
+ const duplicates = oldRoots.filter(r => r.id !== VirtualFileSystem.VFS_ROOT_ID);
222
+ if (duplicates.length > 0) {
223
+ console.log(`VFS: Found ${duplicates.length} old UUID-based root(s) from v5.9.0, cleaning up...`);
224
+ for (const duplicate of duplicates) {
225
+ try {
226
+ await this.brain.delete(duplicate.id);
227
+ console.log(`VFS: Deleted old root ${duplicate.id.substring(0, 8)}`);
228
+ }
229
+ catch (error) {
230
+ console.warn(`VFS: Failed to delete old root ${duplicate.id}:`, error);
231
+ }
232
+ }
233
+ console.log('VFS: Cleanup complete - all old roots removed');
240
234
  }
241
235
  }
242
- console.warn(`\n✅ VFS: Selected root ${bestRoot.id.substring(0, 8)} (${bestRoot.childCount} children)`);
243
- // Suggest cleanup for empty roots
244
- if (emptyRoots.length > 0) {
245
- console.warn(`\n💡 VFS: Found ${emptyRoots.length} empty duplicate root(s), suggest cleanup:`);
246
- for (const empty of emptyRoots) {
247
- console.warn(` await brain.delete('${empty.id}') // Empty VFS root`);
248
- }
236
+ catch (error) {
237
+ // Non-critical error - log and continue
238
+ console.warn('VFS: Cleanup of old roots failed (non-critical):', error);
249
239
  }
250
- return bestRoot.id;
251
240
  }
252
241
  // ============= File Operations =============
253
242
  /**
@@ -2140,4 +2129,7 @@ export class VirtualFileSystem {
2140
2129
  return await this.pathResolver.resolve(normalizedPath);
2141
2130
  }
2142
2131
  }
2132
+ // v5.10.0: Fixed VFS root ID (prevents duplicates across instances)
2133
+ // Uses deterministic UUID format for storage compatibility
2134
+ VirtualFileSystem.VFS_ROOT_ID = '00000000-0000-0000-0000-000000000000';
2143
2135
  //# sourceMappingURL=VirtualFileSystem.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soulcraft/brainy",
3
- "version": "5.9.0",
3
+ "version": "5.10.0",
4
4
  "description": "Universal Knowledge Protocol™ - World's first Triple Intelligence database unifying vector, graph, and document search in one API. Stage 3 CANONICAL: 42 nouns × 127 verbs covering 96-97% of all human knowledge.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",