@soulcraft/brainy 5.10.2 → 5.10.4

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [5.10.4](https://github.com/soulcraftlabs/brainy/compare/v5.10.3...v5.10.4) (2025-11-17)
6
+
7
+ - fix: critical clear() data persistence regression (v5.10.4) (aba1563)
8
+
9
+
10
+ ### [5.10.3](https://github.com/soulcraftlabs/brainy/compare/v5.10.2...v5.10.3) (2025-11-14)
11
+
12
+ - docs: add production service architecture guide to public docs (759e7fa)
13
+
14
+
5
15
  ### [5.10.2](https://github.com/soulcraftlabs/brainy/compare/v5.10.1...v5.10.2) (2025-11-14)
6
16
 
7
17
  - docs: remove external project references from documentation (ccd6c54)
package/README.md CHANGED
@@ -197,6 +197,7 @@ const brain = new Brainy({
197
197
  })
198
198
  ```
199
199
  **Scale:** Thousands to hundreds of thousands • **Performance:** <5ms queries
200
+ **→ [Production Service Architecture](docs/PRODUCTION_SERVICE_ARCHITECTURE.md)** — Singleton patterns, caching, and scaling for Express/Node.js services
200
201
 
201
202
  ### 🏢 Growing Company → Multi-Million Scale
202
203
  ```javascript
package/dist/brainy.js CHANGED
@@ -1829,6 +1829,10 @@ export class Brainy {
1829
1829
  // Recreate index if no clear method
1830
1830
  this.index = this.setupIndex();
1831
1831
  }
1832
+ // v5.10.4: Recreate metadata index to clear cached data
1833
+ // Bug: Metadata index cache was not being cleared, causing find() with type filters to return stale data
1834
+ this.metadataIndex = new MetadataIndexManager(this.storage);
1835
+ await this.metadataIndex.init();
1832
1836
  // Reset dimensions
1833
1837
  this.dimensions = undefined;
1834
1838
  // Clear any cached sub-APIs
@@ -240,6 +240,19 @@ export declare class AzureBlobStorage extends BaseStorage {
240
240
  quota: number | null;
241
241
  details?: Record<string, any>;
242
242
  }>;
243
+ /**
244
+ * Check if COW has been explicitly disabled via clear()
245
+ * v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
246
+ * @returns true if marker blob exists, false otherwise
247
+ * @protected
248
+ */
249
+ protected checkClearMarker(): Promise<boolean>;
250
+ /**
251
+ * Create marker indicating COW has been explicitly disabled
252
+ * v5.10.4: Called by clear() to prevent COW reinitialization on new instances
253
+ * @protected
254
+ */
255
+ protected createClearMarker(): Promise<void>;
243
256
  /**
244
257
  * Save statistics data to storage
245
258
  */
@@ -866,6 +866,11 @@ export class AzureBlobStorage extends BaseStorage {
866
866
  this.blobStorage = undefined;
867
867
  this.commitLog = undefined;
868
868
  this.cowEnabled = false;
869
+ // v5.10.4: Create persistent marker blob (CRITICAL FIX)
870
+ // Bug: cowEnabled = false only affects current instance, not future instances
871
+ // Fix: Create marker blob that persists across instance restarts
872
+ // When new instance calls initializeCOW(), it checks for this marker
873
+ await this.createClearMarker();
869
874
  // Clear caches
870
875
  this.nounCacheManager.clear();
871
876
  this.verbCacheManager.clear();
@@ -908,6 +913,45 @@ export class AzureBlobStorage extends BaseStorage {
908
913
  };
909
914
  }
910
915
  }
916
+ /**
917
+ * Check if COW has been explicitly disabled via clear()
918
+ * v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
919
+ * @returns true if marker blob exists, false otherwise
920
+ * @protected
921
+ */
922
+ async checkClearMarker() {
923
+ await this.ensureInitialized();
924
+ try {
925
+ const markerPath = `${this.systemPrefix}cow-disabled`;
926
+ const blockBlobClient = this.containerClient.getBlockBlobClient(markerPath);
927
+ const exists = await blockBlobClient.exists();
928
+ return exists;
929
+ }
930
+ catch (error) {
931
+ this.logger.warn('AzureBlobStorage.checkClearMarker: Error checking marker', error);
932
+ return false;
933
+ }
934
+ }
935
+ /**
936
+ * Create marker indicating COW has been explicitly disabled
937
+ * v5.10.4: Called by clear() to prevent COW reinitialization on new instances
938
+ * @protected
939
+ */
940
+ async createClearMarker() {
941
+ await this.ensureInitialized();
942
+ try {
943
+ const markerPath = `${this.systemPrefix}cow-disabled`;
944
+ const blockBlobClient = this.containerClient.getBlockBlobClient(markerPath);
945
+ // Create empty marker blob
946
+ await blockBlobClient.upload(Buffer.from(''), 0, {
947
+ blobHTTPHeaders: { blobContentType: 'text/plain' }
948
+ });
949
+ }
950
+ catch (error) {
951
+ this.logger.error('AzureBlobStorage.createClearMarker: Failed to create marker blob', error);
952
+ // Don't throw - marker creation failure shouldn't break clear()
953
+ }
954
+ }
911
955
  /**
912
956
  * Save statistics data to storage
913
957
  */
@@ -171,6 +171,19 @@ export declare class FileSystemStorage extends BaseStorage {
171
171
  * Provides progress tracking, backup options, and instance name confirmation
172
172
  */
173
173
  clearEnhanced(options?: import('../enhancedClearOperations.js').ClearOptions): Promise<import('../enhancedClearOperations.js').ClearResult>;
174
+ /**
175
+ * Check if COW has been explicitly disabled via clear()
176
+ * v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
177
+ * @returns true if marker file exists, false otherwise
178
+ * @protected
179
+ */
180
+ protected checkClearMarker(): Promise<boolean>;
181
+ /**
182
+ * Create marker indicating COW has been explicitly disabled
183
+ * v5.10.4: Called by clear() to prevent COW reinitialization on new instances
184
+ * @protected
185
+ */
186
+ protected createClearMarker(): Promise<void>;
174
187
  /**
175
188
  * Get information about storage usage and capacity
176
189
  */
@@ -859,16 +859,13 @@ export class FileSystemStorage extends BaseStorage {
859
859
  }
860
860
  }
861
861
  };
862
- // Remove all files in the nouns directory
863
- await removeDirectoryContents(this.nounsDir);
864
- // Remove all files in the verbs directory
865
- await removeDirectoryContents(this.verbsDir);
866
- // Remove all files in the metadata directory
867
- await removeDirectoryContents(this.metadataDir);
868
- // Remove all files in the noun metadata directory
869
- await removeDirectoryContents(this.nounMetadataDir);
870
- // Remove all files in the verb metadata directory
871
- await removeDirectoryContents(this.verbMetadataDir);
862
+ // v5.10.4: Clear the entire branches/ directory (branch-based storage)
863
+ // Bug fix: Data is stored in branches/main/entities/, not just entities/
864
+ // The branch-based structure was introduced for COW support
865
+ const branchesDir = path.join(this.rootDir, 'branches');
866
+ if (await this.directoryExists(branchesDir)) {
867
+ await removeDirectoryContents(branchesDir);
868
+ }
872
869
  // Remove all files in both system directories
873
870
  await removeDirectoryContents(this.systemDir);
874
871
  if (await this.directoryExists(this.indexDir)) {
@@ -888,6 +885,11 @@ export class FileSystemStorage extends BaseStorage {
888
885
  this.blobStorage = undefined;
889
886
  this.commitLog = undefined;
890
887
  this.cowEnabled = false;
888
+ // v5.10.4: Create persistent marker file (CRITICAL FIX)
889
+ // Bug: cowEnabled = false only affects current instance, not future instances
890
+ // Fix: Create marker file that persists across instance restarts
891
+ // When new instance calls initializeCOW(), it checks for this marker
892
+ await this.createClearMarker();
891
893
  }
892
894
  // Clear the statistics cache
893
895
  this.statisticsCache = null;
@@ -915,6 +917,47 @@ export class FileSystemStorage extends BaseStorage {
915
917
  }
916
918
  return result;
917
919
  }
920
+ /**
921
+ * Check if COW has been explicitly disabled via clear()
922
+ * v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
923
+ * @returns true if marker file exists, false otherwise
924
+ * @protected
925
+ */
926
+ async checkClearMarker() {
927
+ // Check if fs module is available
928
+ if (!fs || !fs.promises) {
929
+ return false;
930
+ }
931
+ try {
932
+ const markerPath = path.join(this.systemDir, 'cow-disabled');
933
+ await fs.promises.access(markerPath, fs.constants.F_OK);
934
+ return true; // Marker exists
935
+ }
936
+ catch (error) {
937
+ return false; // Marker doesn't exist (ENOENT) or can't be accessed
938
+ }
939
+ }
940
+ /**
941
+ * Create marker indicating COW has been explicitly disabled
942
+ * v5.10.4: Called by clear() to prevent COW reinitialization on new instances
943
+ * @protected
944
+ */
945
+ async createClearMarker() {
946
+ // Check if fs module is available
947
+ if (!fs || !fs.promises) {
948
+ console.warn('FileSystemStorage.createClearMarker: fs module not available, skipping marker creation');
949
+ return;
950
+ }
951
+ try {
952
+ const markerPath = path.join(this.systemDir, 'cow-disabled');
953
+ // Create empty marker file
954
+ await fs.promises.writeFile(markerPath, '', 'utf8');
955
+ }
956
+ catch (error) {
957
+ console.error('FileSystemStorage.createClearMarker: Failed to create marker file', error);
958
+ // Don't throw - marker creation failure shouldn't break clear()
959
+ }
960
+ }
918
961
  /**
919
962
  * Get information about storage usage and capacity
920
963
  */
@@ -228,6 +228,19 @@ export declare class GcsStorage extends BaseStorage {
228
228
  quota: number | null;
229
229
  details?: Record<string, any>;
230
230
  }>;
231
+ /**
232
+ * Check if COW has been explicitly disabled via clear()
233
+ * v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
234
+ * @returns true if marker object exists, false otherwise
235
+ * @protected
236
+ */
237
+ protected checkClearMarker(): Promise<boolean>;
238
+ /**
239
+ * Create marker indicating COW has been explicitly disabled
240
+ * v5.10.4: Called by clear() to prevent COW reinitialization on new instances
241
+ * @protected
242
+ */
243
+ protected createClearMarker(): Promise<void>;
231
244
  /**
232
245
  * Save statistics data to storage
233
246
  */
@@ -789,6 +789,11 @@ export class GcsStorage extends BaseStorage {
789
789
  this.blobStorage = undefined;
790
790
  this.commitLog = undefined;
791
791
  this.cowEnabled = false;
792
+ // v5.10.4: Create persistent marker object (CRITICAL FIX)
793
+ // Bug: cowEnabled = false only affects current instance, not future instances
794
+ // Fix: Create marker object that persists across instance restarts
795
+ // When new instance calls initializeCOW(), it checks for this marker
796
+ await this.createClearMarker();
792
797
  // Clear caches
793
798
  this.nounCacheManager.clear();
794
799
  this.verbCacheManager.clear();
@@ -834,6 +839,43 @@ export class GcsStorage extends BaseStorage {
834
839
  };
835
840
  }
836
841
  }
842
+ /**
843
+ * Check if COW has been explicitly disabled via clear()
844
+ * v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
845
+ * @returns true if marker object exists, false otherwise
846
+ * @protected
847
+ */
848
+ async checkClearMarker() {
849
+ await this.ensureInitialized();
850
+ try {
851
+ const markerPath = `${this.systemPrefix}cow-disabled`;
852
+ const file = this.bucket.file(markerPath);
853
+ const [exists] = await file.exists();
854
+ return exists;
855
+ }
856
+ catch (error) {
857
+ this.logger.warn('GCSStorage.checkClearMarker: Error checking marker', error);
858
+ return false;
859
+ }
860
+ }
861
+ /**
862
+ * Create marker indicating COW has been explicitly disabled
863
+ * v5.10.4: Called by clear() to prevent COW reinitialization on new instances
864
+ * @protected
865
+ */
866
+ async createClearMarker() {
867
+ await this.ensureInitialized();
868
+ try {
869
+ const markerPath = `${this.systemPrefix}cow-disabled`;
870
+ const file = this.bucket.file(markerPath);
871
+ // Create empty marker object
872
+ await file.save('', { contentType: 'text/plain' });
873
+ }
874
+ catch (error) {
875
+ this.logger.error('GCSStorage.createClearMarker: Failed to create marker object', error);
876
+ // Don't throw - marker creation failure shouldn't break clear()
877
+ }
878
+ }
837
879
  /**
838
880
  * Save statistics data to storage
839
881
  */
@@ -101,6 +101,19 @@ export declare class HistoricalStorageAdapter extends BaseStorage {
101
101
  quota: number | null;
102
102
  details?: Record<string, any>;
103
103
  }>;
104
+ /**
105
+ * Check if COW has been explicitly disabled via clear()
106
+ * v5.10.4: No-op for HistoricalStorageAdapter (read-only, doesn't manage COW)
107
+ * @returns Always false (read-only adapter doesn't manage COW state)
108
+ * @protected
109
+ */
110
+ protected checkClearMarker(): Promise<boolean>;
111
+ /**
112
+ * Create marker indicating COW has been explicitly disabled
113
+ * v5.10.4: No-op for HistoricalStorageAdapter (read-only)
114
+ * @protected
115
+ */
116
+ protected createClearMarker(): Promise<void>;
104
117
  /**
105
118
  * WRITE BLOCKED: Historical storage is read-only
106
119
  */
@@ -226,6 +226,23 @@ export class HistoricalStorageAdapter extends BaseStorage {
226
226
  }
227
227
  };
228
228
  }
229
+ /**
230
+ * Check if COW has been explicitly disabled via clear()
231
+ * v5.10.4: No-op for HistoricalStorageAdapter (read-only, doesn't manage COW)
232
+ * @returns Always false (read-only adapter doesn't manage COW state)
233
+ * @protected
234
+ */
235
+ async checkClearMarker() {
236
+ return false; // Read-only adapter - COW state managed by underlying storage
237
+ }
238
+ /**
239
+ * Create marker indicating COW has been explicitly disabled
240
+ * v5.10.4: No-op for HistoricalStorageAdapter (read-only)
241
+ * @protected
242
+ */
243
+ async createClearMarker() {
244
+ // No-op: HistoricalStorageAdapter is read-only, doesn't create markers
245
+ }
229
246
  // ============= Override Write Methods (Read-Only) =============
230
247
  /**
231
248
  * WRITE BLOCKED: Historical storage is read-only
@@ -79,6 +79,19 @@ export declare class MemoryStorage extends BaseStorage {
79
79
  quota: number | null;
80
80
  details?: Record<string, any>;
81
81
  }>;
82
+ /**
83
+ * Check if COW has been explicitly disabled via clear()
84
+ * v5.10.4: No-op for MemoryStorage (doesn't persist)
85
+ * @returns Always false (marker doesn't persist in memory)
86
+ * @protected
87
+ */
88
+ protected checkClearMarker(): Promise<boolean>;
89
+ /**
90
+ * Create marker indicating COW has been explicitly disabled
91
+ * v5.10.4: No-op for MemoryStorage (doesn't persist)
92
+ * @protected
93
+ */
94
+ protected createClearMarker(): Promise<void>;
82
95
  /**
83
96
  * Save statistics data to storage
84
97
  * @param statistics The statistics data to save
@@ -158,6 +158,24 @@ export class MemoryStorage extends BaseStorage {
158
158
  }
159
159
  };
160
160
  }
161
+ /**
162
+ * Check if COW has been explicitly disabled via clear()
163
+ * v5.10.4: No-op for MemoryStorage (doesn't persist)
164
+ * @returns Always false (marker doesn't persist in memory)
165
+ * @protected
166
+ */
167
+ async checkClearMarker() {
168
+ return false; // MemoryStorage doesn't persist - marker doesn't survive restart
169
+ }
170
+ /**
171
+ * Create marker indicating COW has been explicitly disabled
172
+ * v5.10.4: No-op for MemoryStorage (doesn't persist)
173
+ * @protected
174
+ */
175
+ async createClearMarker() {
176
+ // No-op: MemoryStorage doesn't persist, so marker is not needed
177
+ // clear() in memory already resets all state, no marker survives restart
178
+ }
161
179
  /**
162
180
  * Save statistics data to storage
163
181
  * @param statistics The statistics data to save
@@ -94,6 +94,19 @@ export declare class OPFSStorage extends BaseStorage {
94
94
  * Clear all data from storage
95
95
  */
96
96
  clear(): Promise<void>;
97
+ /**
98
+ * Check if COW has been explicitly disabled via clear()
99
+ * v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
100
+ * @returns true if marker file exists, false otherwise
101
+ * @protected
102
+ */
103
+ protected checkClearMarker(): Promise<boolean>;
104
+ /**
105
+ * Create marker indicating COW has been explicitly disabled
106
+ * v5.10.4: Called by clear() to prevent COW reinitialization on new instances
107
+ * @protected
108
+ */
109
+ protected createClearMarker(): Promise<void>;
97
110
  private quotaWarningThreshold;
98
111
  private quotaCriticalThreshold;
99
112
  private lastQuotaCheck;
@@ -400,6 +400,11 @@ export class OPFSStorage extends BaseStorage {
400
400
  this.blobStorage = undefined;
401
401
  this.commitLog = undefined;
402
402
  this.cowEnabled = false;
403
+ // v5.10.4: Create persistent marker file (CRITICAL FIX)
404
+ // Bug: cowEnabled = false only affects current instance, not future instances
405
+ // Fix: Create marker file that persists across instance restarts
406
+ // When new instance calls initializeCOW(), it checks for this marker
407
+ await this.createClearMarker();
403
408
  }
404
409
  catch (error) {
405
410
  // Ignore if _cow directory doesn't exist (not all instances use COW)
@@ -418,6 +423,51 @@ export class OPFSStorage extends BaseStorage {
418
423
  throw error;
419
424
  }
420
425
  }
426
+ /**
427
+ * Check if COW has been explicitly disabled via clear()
428
+ * v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
429
+ * @returns true if marker file exists, false otherwise
430
+ * @protected
431
+ */
432
+ async checkClearMarker() {
433
+ await this.ensureInitialized();
434
+ try {
435
+ // Get system directory (may not exist yet)
436
+ const systemDir = await this.rootDir.getDirectoryHandle('system', { create: false });
437
+ // Try to get the marker file
438
+ await systemDir.getFileHandle('cow-disabled', { create: false });
439
+ return true; // Marker exists
440
+ }
441
+ catch (error) {
442
+ if (error.name === 'NotFoundError') {
443
+ return false; // Marker doesn't exist (or system dir doesn't exist)
444
+ }
445
+ // Other errors (permissions, etc.) - treat as marker not existing
446
+ console.warn('OPFSStorage.checkClearMarker: Error checking marker', error);
447
+ return false;
448
+ }
449
+ }
450
+ /**
451
+ * Create marker indicating COW has been explicitly disabled
452
+ * v5.10.4: Called by clear() to prevent COW reinitialization on new instances
453
+ * @protected
454
+ */
455
+ async createClearMarker() {
456
+ await this.ensureInitialized();
457
+ try {
458
+ // Get or create system directory
459
+ const systemDir = await this.rootDir.getDirectoryHandle('system', { create: true });
460
+ // Create empty marker file
461
+ const fileHandle = await systemDir.getFileHandle('cow-disabled', { create: true });
462
+ const writable = await fileHandle.createWritable();
463
+ await writable.write(new Uint8Array(0)); // Empty file
464
+ await writable.close();
465
+ }
466
+ catch (error) {
467
+ console.error('OPFSStorage.createClearMarker: Failed to create marker file', error);
468
+ // Don't throw - marker creation failure shouldn't break clear()
469
+ }
470
+ }
421
471
  /**
422
472
  * Get information about storage usage and capacity
423
473
  */
@@ -200,5 +200,18 @@ export declare class R2Storage extends BaseStorage {
200
200
  quota: number | null;
201
201
  details?: Record<string, any>;
202
202
  }>;
203
+ /**
204
+ * Check if COW has been explicitly disabled via clear()
205
+ * v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
206
+ * @returns true if marker object exists, false otherwise
207
+ * @protected
208
+ */
209
+ protected checkClearMarker(): Promise<boolean>;
210
+ /**
211
+ * Create marker indicating COW has been explicitly disabled
212
+ * v5.10.4: Called by clear() to prevent COW reinitialization on new instances
213
+ * @protected
214
+ */
215
+ protected createClearMarker(): Promise<void>;
203
216
  }
204
217
  export {};
@@ -787,6 +787,11 @@ export class R2Storage extends BaseStorage {
787
787
  this.blobStorage = undefined;
788
788
  this.commitLog = undefined;
789
789
  this.cowEnabled = false;
790
+ // v5.10.4: Create persistent marker object (CRITICAL FIX)
791
+ // Bug: cowEnabled = false only affects current instance, not future instances
792
+ // Fix: Create marker object that persists across instance restarts
793
+ // When new instance calls initializeCOW(), it checks for this marker
794
+ await this.createClearMarker();
790
795
  this.nounCacheManager.clear();
791
796
  this.verbCacheManager.clear();
792
797
  this.totalNounCount = 0;
@@ -813,5 +818,40 @@ export class R2Storage extends BaseStorage {
813
818
  }
814
819
  };
815
820
  }
821
+ /**
822
+ * Check if COW has been explicitly disabled via clear()
823
+ * v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
824
+ * @returns true if marker object exists, false otherwise
825
+ * @protected
826
+ */
827
+ async checkClearMarker() {
828
+ await this.ensureInitialized();
829
+ try {
830
+ const markerPath = `${this.systemPrefix}cow-disabled`;
831
+ const data = await this.readObjectFromPath(markerPath);
832
+ return data !== null; // Marker exists if we got any data
833
+ }
834
+ catch (error) {
835
+ prodLog.warn('R2Storage.checkClearMarker: Error checking marker', error);
836
+ return false;
837
+ }
838
+ }
839
+ /**
840
+ * Create marker indicating COW has been explicitly disabled
841
+ * v5.10.4: Called by clear() to prevent COW reinitialization on new instances
842
+ * @protected
843
+ */
844
+ async createClearMarker() {
845
+ await this.ensureInitialized();
846
+ try {
847
+ const markerPath = `${this.systemPrefix}cow-disabled`;
848
+ // Create empty marker object
849
+ await this.writeObjectToPath(markerPath, '');
850
+ }
851
+ catch (error) {
852
+ prodLog.error('R2Storage.createClearMarker: Failed to create marker object', error);
853
+ // Don't throw - marker creation failure shouldn't break clear()
854
+ }
855
+ }
816
856
  }
817
857
  //# sourceMappingURL=r2Storage.js.map
@@ -373,6 +373,19 @@ export declare class S3CompatibleStorage extends BaseStorage {
373
373
  quota: number | null;
374
374
  details?: Record<string, any>;
375
375
  }>;
376
+ /**
377
+ * Check if COW has been explicitly disabled via clear()
378
+ * v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
379
+ * @returns true if marker object exists, false otherwise
380
+ * @protected
381
+ */
382
+ protected checkClearMarker(): Promise<boolean>;
383
+ /**
384
+ * Create marker indicating COW has been explicitly disabled
385
+ * v5.10.4: Called by clear() to prevent COW reinitialization on new instances
386
+ * @protected
387
+ */
388
+ protected createClearMarker(): Promise<void>;
376
389
  protected statisticsBatchUpdateTimerId: NodeJS.Timeout | null;
377
390
  protected statisticsModified: boolean;
378
391
  protected lastStatisticsFlushTime: number;
@@ -1632,6 +1632,11 @@ export class S3CompatibleStorage extends BaseStorage {
1632
1632
  this.blobStorage = undefined;
1633
1633
  this.commitLog = undefined;
1634
1634
  this.cowEnabled = false;
1635
+ // v5.10.4: Create persistent marker object (CRITICAL FIX)
1636
+ // Bug: cowEnabled = false only affects current instance, not future instances
1637
+ // Fix: Create marker object that persists across instance restarts
1638
+ // When new instance calls initializeCOW(), it checks for this marker
1639
+ await this.createClearMarker();
1635
1640
  // Clear the statistics cache
1636
1641
  this.statisticsCache = null;
1637
1642
  this.statisticsModified = false;
@@ -1731,6 +1736,54 @@ export class S3CompatibleStorage extends BaseStorage {
1731
1736
  };
1732
1737
  }
1733
1738
  }
1739
+ /**
1740
+ * Check if COW has been explicitly disabled via clear()
1741
+ * v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
1742
+ * @returns true if marker object exists, false otherwise
1743
+ * @protected
1744
+ */
1745
+ async checkClearMarker() {
1746
+ await this.ensureInitialized();
1747
+ try {
1748
+ const { HeadObjectCommand } = await import('@aws-sdk/client-s3');
1749
+ const markerKey = `${this.systemPrefix}cow-disabled`;
1750
+ await this.s3Client.send(new HeadObjectCommand({
1751
+ Bucket: this.bucketName,
1752
+ Key: markerKey
1753
+ }));
1754
+ return true; // Marker exists
1755
+ }
1756
+ catch (error) {
1757
+ if (error.name === 'NotFound' || error.$metadata?.httpStatusCode === 404) {
1758
+ return false; // Marker doesn't exist
1759
+ }
1760
+ prodLog.warn('S3CompatibleStorage.checkClearMarker: Error checking marker', error);
1761
+ return false;
1762
+ }
1763
+ }
1764
+ /**
1765
+ * Create marker indicating COW has been explicitly disabled
1766
+ * v5.10.4: Called by clear() to prevent COW reinitialization on new instances
1767
+ * @protected
1768
+ */
1769
+ async createClearMarker() {
1770
+ await this.ensureInitialized();
1771
+ try {
1772
+ const { PutObjectCommand } = await import('@aws-sdk/client-s3');
1773
+ const markerKey = `${this.systemPrefix}cow-disabled`;
1774
+ // Create empty marker object
1775
+ await this.s3Client.send(new PutObjectCommand({
1776
+ Bucket: this.bucketName,
1777
+ Key: markerKey,
1778
+ Body: Buffer.from(''),
1779
+ ContentType: 'text/plain'
1780
+ }));
1781
+ }
1782
+ catch (error) {
1783
+ prodLog.error('S3CompatibleStorage.createClearMarker: Failed to create marker object', error);
1784
+ // Don't throw - marker creation failure shouldn't break clear()
1785
+ }
1786
+ }
1734
1787
  /**
1735
1788
  * Get the statistics key for a specific date
1736
1789
  * @param date The date to get the key for
@@ -327,6 +327,21 @@ export declare abstract class BaseStorage extends BaseStorageAdapter {
327
327
  * This method should be implemented by each specific adapter
328
328
  */
329
329
  abstract clear(): Promise<void>;
330
+ /**
331
+ * Check if COW has been explicitly disabled via clear()
332
+ * v5.10.4: Fixes bug where clear() doesn't persist across instance restarts
333
+ * Each adapter checks for a marker file/object (e.g., "_system/cow-disabled")
334
+ * @returns true if COW was disabled by clear(), false otherwise
335
+ * @protected
336
+ */
337
+ protected abstract checkClearMarker(): Promise<boolean>;
338
+ /**
339
+ * Create marker indicating COW has been explicitly disabled
340
+ * v5.10.4: Called by clear() to prevent COW reinitialization on new instances
341
+ * Each adapter creates a marker file/object (e.g., "_system/cow-disabled")
342
+ * @protected
343
+ */
344
+ protected abstract createClearMarker(): Promise<void>;
330
345
  /**
331
346
  * Get information about storage usage and capacity
332
347
  * This method should be implemented by each specific adapter
@@ -212,6 +212,14 @@ export class BaseStorage extends BaseStorageAdapter {
212
212
  * @returns Promise that resolves when COW is initialized
213
213
  */
214
214
  async initializeCOW(options) {
215
+ // v5.10.4: Check for persistent marker file (CRITICAL FIX)
216
+ // Bug: Setting cowEnabled = false on OLD instance doesn't affect NEW instances
217
+ // Fix: Check storage for persistent marker created by clear()
218
+ // If marker exists, COW was explicitly disabled and should NOT reinitialize
219
+ const markerExists = await this.checkClearMarker();
220
+ if (markerExists) {
221
+ return; // COW was disabled by clear() - don't recreate _cow/ directory
222
+ }
215
223
  // v5.6.1: If COW was explicitly disabled (e.g., via clear()), don't reinitialize
216
224
  // This prevents automatic recreation of COW data after clear() operations
217
225
  if (this.cowEnabled === false) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soulcraft/brainy",
3
- "version": "5.10.2",
3
+ "version": "5.10.4",
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",