@soulcraft/brainy 6.1.0 → 6.2.1

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.
Files changed (40) hide show
  1. package/CHANGELOG.md +271 -0
  2. package/dist/augmentations/KnowledgeAugmentation.d.ts +40 -0
  3. package/dist/augmentations/KnowledgeAugmentation.js +251 -0
  4. package/dist/brainy.d.ts +17 -13
  5. package/dist/brainy.js +172 -41
  6. package/dist/coreTypes.d.ts +12 -0
  7. package/dist/graph/graphAdjacencyIndex.d.ts +23 -0
  8. package/dist/graph/graphAdjacencyIndex.js +49 -0
  9. package/dist/importManager.d.ts +78 -0
  10. package/dist/importManager.js +267 -0
  11. package/dist/query/typeInference.d.ts +158 -0
  12. package/dist/query/typeInference.js +760 -0
  13. package/dist/storage/adapters/typeAwareStorageAdapter.d.ts +252 -0
  14. package/dist/storage/adapters/typeAwareStorageAdapter.js +814 -0
  15. package/dist/storage/baseStorage.d.ts +36 -0
  16. package/dist/storage/baseStorage.js +159 -4
  17. package/dist/storage/cow/binaryDataCodec.d.ts +13 -2
  18. package/dist/storage/cow/binaryDataCodec.js +15 -2
  19. package/dist/types/brainy.types.d.ts +1 -0
  20. package/dist/types/brainyDataInterface.d.ts +52 -0
  21. package/dist/types/brainyDataInterface.js +10 -0
  22. package/dist/utils/metadataIndex.d.ts +17 -0
  23. package/dist/utils/metadataIndex.js +63 -0
  24. package/dist/vfs/ConceptSystem.d.ts +203 -0
  25. package/dist/vfs/ConceptSystem.js +545 -0
  26. package/dist/vfs/EntityManager.d.ts +75 -0
  27. package/dist/vfs/EntityManager.js +216 -0
  28. package/dist/vfs/EventRecorder.d.ts +84 -0
  29. package/dist/vfs/EventRecorder.js +269 -0
  30. package/dist/vfs/GitBridge.d.ts +167 -0
  31. package/dist/vfs/GitBridge.js +537 -0
  32. package/dist/vfs/KnowledgeLayer.d.ts +35 -0
  33. package/dist/vfs/KnowledgeLayer.js +443 -0
  34. package/dist/vfs/PersistentEntitySystem.d.ts +165 -0
  35. package/dist/vfs/PersistentEntitySystem.js +503 -0
  36. package/dist/vfs/SemanticVersioning.d.ts +105 -0
  37. package/dist/vfs/SemanticVersioning.js +309 -0
  38. package/dist/vfs/VirtualFileSystem.d.ts +37 -2
  39. package/dist/vfs/VirtualFileSystem.js +105 -68
  40. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,277 @@
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
+ ## [6.2.0](https://github.com/soulcraftlabs/brainy/compare/v6.1.0...v6.2.0) (2025-11-20)
6
+
7
+ ### ⚡ Critical Performance Fix
8
+
9
+ **Fixed VFS tree operations on cloud storage (GCS, S3, Azure, R2, OPFS)**
10
+
11
+ **Issue:** Despite v6.1.0's PathResolver optimization, `vfs.getTreeStructure()` remained critically slow on cloud storage:
12
+ - **Workshop Production (GCS):** 5,304ms for tree with maxDepth=2
13
+ - **Root Cause:** Tree traversal made 111+ separate storage calls (one per directory)
14
+ - **Why v6.1.0 didn't help:** v6.1.0 optimized path→ID resolution, but tree traversal still called `getChildren()` 111+ times
15
+
16
+ **Architecture Fix:**
17
+ ```
18
+ OLD (v6.1.0):
19
+ - For each directory: getChildren(dirId) → fetch entities → GCS call
20
+ - 111 directories = 111 GCS calls × 50ms = 5,550ms
21
+
22
+ NEW (v6.2.0):
23
+ 1. Traverse graph in-memory to collect all IDs (GraphAdjacencyIndex)
24
+ 2. Batch-fetch ALL entities in ONE storage call (brain.batchGet)
25
+ 3. Build tree structure from fetched entities
26
+
27
+ Result: 111 storage calls → 1 storage call
28
+ ```
29
+
30
+ **Performance (Production Measurement):**
31
+ - **GCS:** 5,304ms → ~100ms (**53x faster**)
32
+ - **FileSystem:** Already fast, minimal change
33
+
34
+ **Files Changed:**
35
+ - `src/vfs/VirtualFileSystem.ts:616-689` - New `gatherDescendants()` method
36
+ - `src/vfs/VirtualFileSystem.ts:691-728` - Updated `getTreeStructure()` to use batch fetch
37
+ - `src/vfs/VirtualFileSystem.ts:730-762` - Updated `getDescendants()` to use batch fetch
38
+
39
+ **Impact:**
40
+ - ✅ Workshop file explorer now loads instantly on GCS
41
+ - ✅ Clean architecture: one code path, no fallbacks
42
+ - ✅ Production-scale: uses in-memory graph + single batch fetch
43
+ - ✅ Works for ALL storage adapters (GCS, S3, Azure, R2, OPFS, FileSystem)
44
+
45
+ **Migration:** No code changes required - automatic performance improvement.
46
+
47
+ ### 🚨 Critical Bug Fix: Blob Integrity Check Failures (PERMANENT FIX)
48
+
49
+ **Fixed blob integrity check failures on cloud storage using key-based dispatch (NO MORE GUESSING)**
50
+
51
+ **Issue:** Production users reported "Blob integrity check failed" errors when opening files from GCS:
52
+ - **Symptom:** Random file read failures with hash mismatch errors
53
+ - **Root Cause:** `wrapBinaryData()` tried to guess data type by parsing, causing compressed binary that happens to be valid UTF-8 + valid JSON to be stored as parsed objects instead of wrapped binary
54
+ - **Impact:** On read, `JSON.stringify(object)` !== original compressed bytes → hash mismatch → integrity failure
55
+
56
+ **The Guessing Problem (v5.10.1 - v6.1.0):**
57
+ ```typescript
58
+ // FRAGILE: wrapBinaryData() tries to JSON.parse ALL buffers
59
+ wrapBinaryData(compressedBuffer) {
60
+ try {
61
+ return JSON.parse(data.toString()) // ← Compressed data accidentally parses!
62
+ } catch {
63
+ return {_binary: true, data: base64}
64
+ }
65
+ }
66
+
67
+ // FAILURE PATH:
68
+ // 1. WRITE: hash(raw) → compress(raw) → wrapBinaryData(compressed)
69
+ // → compressed bytes accidentally parse as valid JSON
70
+ // → stored as parsed object instead of wrapped binary
71
+ // 2. READ: retrieve object → JSON.stringify(object) → decompress
72
+ // → different bytes than original compressed data
73
+ // → HASH MISMATCH → "Blob integrity check failed"
74
+ ```
75
+
76
+ **The Permanent Solution (v6.2.0): Key-Based Dispatch**
77
+
78
+ Stop guessing! The key naming convention **IS** the explicit type contract:
79
+
80
+ ```typescript
81
+ // baseStorage.ts COW adapter (line 371-393)
82
+ put: async (key: string, data: Buffer): Promise<void> => {
83
+ // NO GUESSING - key format explicitly declares data type:
84
+ //
85
+ // JSON keys: 'ref:*', '*-meta:*'
86
+ // Binary keys: 'blob:*', 'commit:*', 'tree:*'
87
+
88
+ const obj = key.includes('-meta:') || key.startsWith('ref:')
89
+ ? JSON.parse(data.toString()) // Metadata/refs: ALWAYS JSON
90
+ : { _binary: true, data: data.toString('base64') } // Blobs: ALWAYS binary
91
+
92
+ await this.writeObjectToPath(`_cow/${key}`, obj)
93
+ }
94
+ ```
95
+
96
+ **Why This is Permanent:**
97
+ - ✅ **Zero guessing** - key explicitly declares type
98
+ - ✅ **Works for ANY compression** - gzip, zstd, brotli, future algorithms
99
+ - ✅ **Self-documenting** - code clearly shows intent
100
+ - ✅ **No heuristics** - no fragile first-byte checks or try/catch parsing
101
+ - ✅ **Single source of truth** - key naming convention is the contract
102
+
103
+ **Files Changed:**
104
+ - `src/storage/baseStorage.ts:371-393` - COW adapter uses key-based dispatch (NO MORE wrapBinaryData)
105
+ - `src/storage/cow/binaryDataCodec.ts:86-119` - Deprecated wrapBinaryData() with warnings
106
+ - `tests/unit/storage/cow/BlobStorage.test.ts:612-705` - Added 4 comprehensive regression tests
107
+
108
+ **Regression Tests Added:**
109
+ 1. JSON-like compressed data (THE KILLER TEST CASE)
110
+ 2. All key types dispatch correctly (blob, commit, tree)
111
+ 3. Metadata keys handled correctly
112
+ 4. Verify wrapBinaryData() never called on write path
113
+
114
+ **Impact:**
115
+ - ✅ **PERMANENT FIX** - eliminates blob integrity failures forever
116
+ - ✅ Works for ALL storage adapters (GCS, S3, Azure, R2, OPFS, FileSystem)
117
+ - ✅ Works for ALL compression algorithms
118
+ - ✅ Comprehensive regression tests prevent future regressions
119
+ - ✅ No performance cost (key.includes() is fast)
120
+
121
+ **Migration:** No action required - automatic fix for all blob operations.
122
+
123
+ ### ⚡ Performance Fix: Removed Access Time Updates on Reads
124
+
125
+ **Fixed 50-100ms GCS write penalty on EVERY file/directory read**
126
+
127
+ **Issue:** Production GCS performance showed file reads taking significantly longer than expected:
128
+ - **Expected:** ~50ms for file read
129
+ - **Actual:** ~100-150ms for file read
130
+ - **Root Cause:** `updateAccessTime()` called on EVERY `readFile()` and `readdir()` operation
131
+ - **Impact:** Each access time update = 50-100ms GCS write operation + doubled GCS costs
132
+
133
+ **The Problem:**
134
+ ```typescript
135
+ // OLD (v6.1.0):
136
+ async readFile(path: string): Promise<Buffer> {
137
+ const entity = await this.getEntityByPath(path)
138
+ await this.updateAccessTime(entityId) // ← 50-100ms GCS write!
139
+ return await this.blobStorage.read(blobHash)
140
+ }
141
+
142
+ async readdir(path: string): Promise<string[]> {
143
+ const entity = await this.getEntityByPath(path)
144
+ await this.updateAccessTime(entityId) // ← 50-100ms GCS write!
145
+ return children.map(child => child.metadata.name)
146
+ }
147
+ ```
148
+
149
+ **Why Access Time Updates Are Harmful:**
150
+ 1. **Performance:** 50-100ms penalty on cloud storage for EVERY read
151
+ 2. **Cost:** Doubles GCS operation costs (read + write for every file access)
152
+ 3. **Unnecessary:** Modern filesystems use `noatime` mount option for same reason
153
+ 4. **Unused:** The `accessed` field was NEVER used in queries, filters, or application logic
154
+
155
+ **Solution (v6.2.0): Remove Completely**
156
+
157
+ Following modern filesystem best practices (Linux `noatime`, macOS default behavior):
158
+ - ✅ Removed `updateAccessTime()` call from `readFile()` (line 372)
159
+ - ✅ Removed `updateAccessTime()` call from `readdir()` (line 1002)
160
+ - ✅ Removed `updateAccessTime()` method entirely (lines 1355-1365)
161
+ - ✅ Field `accessed` still exists in metadata for backward compatibility (just won't update)
162
+
163
+ **Performance Impact (Production Scale):**
164
+ - **File reads:** 100-150ms → 50ms (**2-3x faster**)
165
+ - **Directory reads:** 100-150ms → 50ms (**2-3x faster**)
166
+ - **GCS costs:** ~50% reduction (eliminated write operation on every read)
167
+ - **FileSystem:** Minimal impact (already fast, but removes unnecessary disk I/O)
168
+
169
+ **Files Changed:**
170
+ - `src/vfs/VirtualFileSystem.ts:372-375` - Removed updateAccessTime() from readFile()
171
+ - `src/vfs/VirtualFileSystem.ts:1002-1006` - Removed updateAccessTime() from readdir()
172
+ - `src/vfs/VirtualFileSystem.ts:1355-1365` - Removed updateAccessTime() method
173
+
174
+ **Impact:**
175
+ - ✅ **2-3x faster reads** on cloud storage
176
+ - ✅ **~50% GCS cost reduction** (no write on every read)
177
+ - ✅ Follows modern filesystem best practices
178
+ - ✅ Backward compatible: field exists but won't update
179
+ - ✅ Works for ALL storage adapters (GCS, S3, Azure, R2, OPFS, FileSystem)
180
+
181
+ **Migration:** No action required - automatic performance improvement.
182
+
183
+ ### ⚡ Performance Fix: Eliminated N+1 Patterns Across All APIs
184
+
185
+ **Fixed 8 N+1 patterns for 10-20x faster batch operations on cloud storage**
186
+
187
+ **Issue:** Multiple APIs loaded entities/relationships one-by-one instead of using batch operations:
188
+ - `find()`: 5 different code paths loaded entities individually
189
+ - `batchGet()` with vectors: Looped through individual `get()` calls
190
+ - `executeGraphSearch()`: Loaded connected entities one-by-one
191
+ - `relate()` duplicate checking: Loaded existing relationships one-by-one
192
+ - `deleteMany()`: Created separate transaction for each entity
193
+
194
+ **Root Cause:** Individual storage calls instead of batch operations → N × 50ms on GCS = severe latency
195
+
196
+ **Solution (v6.2.0): Comprehensive Batch Operations**
197
+
198
+ **1. Fixed `find()` method - 5 locations**
199
+ ```typescript
200
+ // OLD: N separate storage calls
201
+ for (const id of pageIds) {
202
+ const entity = await this.get(id) // ❌ N×50ms on GCS
203
+ }
204
+
205
+ // NEW: Single batch call
206
+ const entitiesMap = await this.batchGet(pageIds) // ✅ 1×50ms on GCS
207
+ for (const id of pageIds) {
208
+ const entity = entitiesMap.get(id)
209
+ }
210
+ ```
211
+
212
+ **2. Fixed `batchGet()` with vectors**
213
+ - **Added:** `storage.getNounBatch(ids)` method (baseStorage.ts:1986)
214
+ - Batch-loads vectors + metadata in parallel
215
+ - Eliminates N+1 when `includeVectors: true`
216
+
217
+ **3. Fixed `executeGraphSearch()`**
218
+ - Uses `batchGet()` for connected entities
219
+ - 20 entities: 1,000ms → 50ms (**20x faster**)
220
+
221
+ **4. Fixed `relate()` duplicate checking**
222
+ - **Added:** `storage.getVerbsBatch(ids)` method (baseStorage.ts:826)
223
+ - **Added:** `graphIndex.getVerbsBatchCached(ids)` method (graphAdjacencyIndex.ts:384)
224
+ - Batch-loads existing relationships with cache-aware loading
225
+ - 5 verbs: 250ms → 50ms (**5x faster**)
226
+
227
+ **5. Fixed `deleteMany()`**
228
+ - **Changed:** Batches deletes into chunks of 10
229
+ - Single transaction per chunk (atomic within chunk)
230
+ - 10 entities: 2,000ms → 200ms (**10x faster**)
231
+ - Proper error handling with `continueOnError` flag
232
+
233
+ **Performance Impact (Production GCS):**
234
+
235
+ | Operation | Before | After | Speedup |
236
+ |-----------|--------|-------|---------|
237
+ | find() with 10 results | 10×50ms = 500ms | 1×50ms = 50ms | **10x** |
238
+ | batchGet() with vectors (10 entities) | 10×50ms = 500ms | 1×50ms = 50ms | **10x** |
239
+ | executeGraphSearch() with 20 entities | 20×50ms = 1000ms | 1×50ms = 50ms | **20x** |
240
+ | relate() duplicate check (5 verbs) | 5×50ms = 250ms | 1×50ms = 50ms | **5x** |
241
+ | deleteMany() with 10 entities | 10 txns = 2000ms | 1 txn = 200ms | **10x** |
242
+
243
+ **Files Changed:**
244
+ - `src/brainy.ts:1682-1690` - find() location 1 (batch load)
245
+ - `src/brainy.ts:1713-1720` - find() location 2 (batch load)
246
+ - `src/brainy.ts:1820-1832` - find() location 3 (batch load filtered results)
247
+ - `src/brainy.ts:1845-1853` - find() location 4 (batch load paginated)
248
+ - `src/brainy.ts:1870-1878` - find() location 5 (batch load sorted)
249
+ - `src/brainy.ts:724-732` - batchGet() with vectors optimization
250
+ - `src/brainy.ts:1171-1183` - relate() duplicate check optimization
251
+ - `src/brainy.ts:2216-2310` - deleteMany() transaction batching
252
+ - `src/brainy.ts:4314-4325` - executeGraphSearch() batch load
253
+ - `src/storage/baseStorage.ts:1986-2045` - Added getNounBatch()
254
+ - `src/storage/baseStorage.ts:826-886` - Added getVerbsBatch()
255
+ - `src/graph/graphAdjacencyIndex.ts:384-413` - Added getVerbsBatchCached()
256
+ - `src/coreTypes.ts:721,743` - Added batch methods to StorageAdapter interface
257
+ - `src/types/brainy.types.ts:367` - Added continueOnError to DeleteManyParams
258
+
259
+ **Architecture:**
260
+ - ✅ **COW/fork/asOf**: All batch methods use `readBatchWithInheritance()`
261
+ - ✅ **All storage adapters**: Works with GCS, S3, Azure, R2, OPFS, FileSystem
262
+ - ✅ **Caching**: getVerbsBatchCached() checks UnifiedCache first
263
+ - ✅ **Transactions**: deleteMany() batches into atomic chunks
264
+ - ✅ **Error handling**: Proper error collection with continueOnError support
265
+
266
+ **Impact:**
267
+ - ✅ **10-20x faster** batch operations on cloud storage
268
+ - ✅ **50-90% cost reduction** (fewer storage API calls)
269
+ - ✅ Clean architecture - no fallbacks, no hacks
270
+ - ✅ Backward compatible - automatic performance improvement
271
+
272
+ **Migration:** No action required - automatic performance improvement.
273
+
274
+ ---
275
+
5
276
  ## [6.1.0](https://github.com/soulcraftlabs/brainy/compare/v6.0.2...v6.1.0) (2025-11-20)
6
277
 
7
278
  ### 🚀 Features
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Knowledge Layer Augmentation for VFS
3
+ *
4
+ * Adds intelligent features to VFS without modifying core functionality:
5
+ * - Event recording for all operations
6
+ * - Semantic versioning based on content changes
7
+ * - Entity and concept extraction
8
+ * - Git bridge for import/export
9
+ *
10
+ * This is a TRUE augmentation - VFS works perfectly without it
11
+ */
12
+ import { Brainy } from '../brainy.js';
13
+ import { BaseAugmentation } from './brainyAugmentation.js';
14
+ export declare class KnowledgeAugmentation extends BaseAugmentation {
15
+ name: string;
16
+ timing: 'after';
17
+ metadata: 'none';
18
+ operations: any;
19
+ priority: number;
20
+ constructor(config?: any);
21
+ execute<T = any>(operation: string, params: any, next: () => Promise<T>): Promise<T>;
22
+ private eventRecorder?;
23
+ private semanticVersioning?;
24
+ private entitySystem?;
25
+ private conceptSystem?;
26
+ private gitBridge?;
27
+ private originalMethods;
28
+ initialize(context: any): Promise<void>;
29
+ augment(brain: Brainy): Promise<void>;
30
+ /**
31
+ * Wrap a VFS method to add Knowledge Layer functionality
32
+ */
33
+ private wrapMethod;
34
+ /**
35
+ * Add Knowledge Layer methods to VFS
36
+ */
37
+ private addKnowledgeMethods;
38
+ private isSemanticChange;
39
+ cleanup(brain: Brainy): Promise<void>;
40
+ }
@@ -0,0 +1,251 @@
1
+ /**
2
+ * Knowledge Layer Augmentation for VFS
3
+ *
4
+ * Adds intelligent features to VFS without modifying core functionality:
5
+ * - Event recording for all operations
6
+ * - Semantic versioning based on content changes
7
+ * - Entity and concept extraction
8
+ * - Git bridge for import/export
9
+ *
10
+ * This is a TRUE augmentation - VFS works perfectly without it
11
+ */
12
+ import { BaseAugmentation } from './brainyAugmentation.js';
13
+ import { EventRecorder } from '../vfs/EventRecorder.js';
14
+ import { SemanticVersioning } from '../vfs/SemanticVersioning.js';
15
+ import { PersistentEntitySystem } from '../vfs/PersistentEntitySystem.js';
16
+ import { ConceptSystem } from '../vfs/ConceptSystem.js';
17
+ import { GitBridge } from '../vfs/GitBridge.js';
18
+ export class KnowledgeAugmentation extends BaseAugmentation {
19
+ constructor(config = {}) {
20
+ super(config);
21
+ this.name = 'knowledge';
22
+ this.timing = 'after'; // Process after VFS operations
23
+ this.metadata = 'none'; // No metadata access needed
24
+ this.operations = []; // VFS-specific augmentation, no operation interception
25
+ this.priority = 100; // Run last
26
+ this.originalMethods = new Map();
27
+ }
28
+ async execute(operation, params, next) {
29
+ // Pass through - this augmentation works at VFS level, not operation level
30
+ return await next();
31
+ }
32
+ async initialize(context) {
33
+ await this.augment(context.brain);
34
+ }
35
+ async augment(brain) {
36
+ // Only augment if VFS exists
37
+ const vfs = brain.vfs?.();
38
+ if (!vfs) {
39
+ console.warn('KnowledgeAugmentation: VFS not found, skipping');
40
+ return;
41
+ }
42
+ // Initialize Knowledge Layer components
43
+ this.eventRecorder = new EventRecorder(brain);
44
+ this.semanticVersioning = new SemanticVersioning(brain);
45
+ this.entitySystem = new PersistentEntitySystem(brain);
46
+ this.conceptSystem = new ConceptSystem(brain);
47
+ this.gitBridge = new GitBridge(vfs, brain);
48
+ // Wrap VFS methods to add intelligence WITHOUT slowing them down
49
+ this.wrapMethod(vfs, 'writeFile', async (original, path, data, options) => {
50
+ // Call original first (stays fast)
51
+ const result = await original.call(vfs, path, data, options);
52
+ // Knowledge processing in background (non-blocking)
53
+ setImmediate(async () => {
54
+ try {
55
+ // Record event
56
+ if (this.eventRecorder) {
57
+ await this.eventRecorder.recordEvent({
58
+ type: 'write',
59
+ path,
60
+ content: data,
61
+ size: data.length,
62
+ author: options?.author || 'system'
63
+ });
64
+ }
65
+ // Check for semantic versioning
66
+ if (this.semanticVersioning) {
67
+ const existingContent = await vfs.readFile(path).catch(() => null);
68
+ const shouldVersion = existingContent && this.isSemanticChange(existingContent, data);
69
+ if (shouldVersion) {
70
+ await this.semanticVersioning.createVersion(path, data, {
71
+ message: 'Automatic semantic version'
72
+ });
73
+ }
74
+ }
75
+ // Extract concepts
76
+ if (this.conceptSystem && options?.extractConcepts !== false) {
77
+ await this.conceptSystem.extractAndLinkConcepts(path, data);
78
+ }
79
+ // Extract entities
80
+ if (this.entitySystem && options?.extractEntities !== false) {
81
+ await this.entitySystem.extractEntities(data.toString('utf8'), data);
82
+ }
83
+ }
84
+ catch (error) {
85
+ // Knowledge Layer errors should not affect VFS operations
86
+ console.debug('KnowledgeLayer background processing error:', error);
87
+ }
88
+ });
89
+ return result;
90
+ });
91
+ this.wrapMethod(vfs, 'unlink', async (original, path) => {
92
+ const result = await original.call(vfs, path);
93
+ // Record deletion event
94
+ setImmediate(async () => {
95
+ if (this.eventRecorder) {
96
+ await this.eventRecorder.recordEvent({
97
+ type: 'delete',
98
+ path,
99
+ author: 'system'
100
+ });
101
+ }
102
+ });
103
+ return result;
104
+ });
105
+ this.wrapMethod(vfs, 'rename', async (original, oldPath, newPath) => {
106
+ const result = await original.call(vfs, oldPath, newPath);
107
+ // Record rename event
108
+ setImmediate(async () => {
109
+ if (this.eventRecorder) {
110
+ await this.eventRecorder.recordEvent({
111
+ type: 'rename',
112
+ path: oldPath,
113
+ metadata: { newPath },
114
+ author: 'system'
115
+ });
116
+ }
117
+ });
118
+ return result;
119
+ });
120
+ // Add Knowledge Layer methods to VFS
121
+ this.addKnowledgeMethods(vfs);
122
+ console.log('✨ Knowledge Layer augmentation enabled');
123
+ }
124
+ /**
125
+ * Wrap a VFS method to add Knowledge Layer functionality
126
+ */
127
+ wrapMethod(vfs, methodName, wrapper) {
128
+ const original = vfs[methodName];
129
+ if (!original)
130
+ return;
131
+ // Store original for cleanup
132
+ this.originalMethods.set(methodName, original);
133
+ // Replace with wrapped version
134
+ vfs[methodName] = async (...args) => {
135
+ return await wrapper(original, ...args);
136
+ };
137
+ }
138
+ /**
139
+ * Add Knowledge Layer methods to VFS
140
+ */
141
+ addKnowledgeMethods(vfs) {
142
+ // Event history
143
+ vfs.getHistory = async (path, options) => {
144
+ if (!this.eventRecorder)
145
+ throw new Error('Knowledge Layer not initialized');
146
+ return await this.eventRecorder.getHistory(path, options);
147
+ };
148
+ vfs.reconstructAtTime = async (path, timestamp) => {
149
+ if (!this.eventRecorder)
150
+ throw new Error('Knowledge Layer not initialized');
151
+ return await this.eventRecorder.reconstructFileAtTime(path, timestamp);
152
+ };
153
+ // Semantic versioning
154
+ vfs.getVersions = async (path) => {
155
+ if (!this.semanticVersioning)
156
+ throw new Error('Knowledge Layer not initialized');
157
+ return await this.semanticVersioning.getVersions(path);
158
+ };
159
+ vfs.restoreVersion = async (path, versionId) => {
160
+ if (!this.semanticVersioning)
161
+ throw new Error('Knowledge Layer not initialized');
162
+ const version = await this.semanticVersioning.getVersion(path, versionId);
163
+ if (version) {
164
+ await vfs.writeFile(path, version);
165
+ }
166
+ };
167
+ // Entities
168
+ vfs.findEntity = async (query) => {
169
+ if (!this.entitySystem)
170
+ throw new Error('Knowledge Layer not initialized');
171
+ return await this.entitySystem.findEntity(query);
172
+ };
173
+ vfs.getEntityAppearances = async (entityId) => {
174
+ if (!this.entitySystem)
175
+ throw new Error('Knowledge Layer not initialized');
176
+ return await this.entitySystem.getEvolution(entityId);
177
+ };
178
+ // Concepts
179
+ vfs.getConcepts = async (path) => {
180
+ if (!this.conceptSystem)
181
+ throw new Error('Knowledge Layer not initialized');
182
+ const concepts = await this.conceptSystem.findConcepts({ manifestedIn: path });
183
+ return concepts;
184
+ };
185
+ vfs.getConceptGraph = async (options) => {
186
+ if (!this.conceptSystem)
187
+ throw new Error('Knowledge Layer not initialized');
188
+ return await this.conceptSystem.getConceptGraph(options);
189
+ };
190
+ // Git bridge
191
+ vfs.exportToGit = async (vfsPath, gitPath) => {
192
+ if (!this.gitBridge)
193
+ throw new Error('Knowledge Layer not initialized');
194
+ return await this.gitBridge.exportToGit(vfsPath, gitPath);
195
+ };
196
+ vfs.importFromGit = async (gitPath, vfsPath) => {
197
+ if (!this.gitBridge)
198
+ throw new Error('Knowledge Layer not initialized');
199
+ return await this.gitBridge.importFromGit(gitPath, vfsPath);
200
+ };
201
+ // Temporal coupling
202
+ vfs.findTemporalCoupling = async (path, windowMs) => {
203
+ if (!this.eventRecorder)
204
+ throw new Error('Knowledge Layer not initialized');
205
+ return await this.eventRecorder.findTemporalCoupling(path, windowMs);
206
+ };
207
+ }
208
+ isSemanticChange(oldContent, newContent) {
209
+ // Simple heuristic - significant size change or different content
210
+ const oldStr = oldContent.toString('utf8');
211
+ const newStr = newContent.toString('utf8');
212
+ // Check for significant size change (>10%)
213
+ const sizeDiff = Math.abs(oldStr.length - newStr.length) / oldStr.length;
214
+ if (sizeDiff > 0.1)
215
+ return true;
216
+ // Check for structural changes (simplified)
217
+ const oldLines = oldStr.split('\n').filter(l => l.trim());
218
+ const newLines = newStr.split('\n').filter(l => l.trim());
219
+ // Different number of non-empty lines
220
+ return Math.abs(oldLines.length - newLines.length) > 5;
221
+ }
222
+ async cleanup(brain) {
223
+ const vfs = brain.vfs?.();
224
+ if (!vfs)
225
+ return;
226
+ // Restore original methods
227
+ for (const [methodName, original] of this.originalMethods) {
228
+ vfs[methodName] = original;
229
+ }
230
+ // Remove added methods
231
+ delete vfs.getHistory;
232
+ delete vfs.reconstructAtTime;
233
+ delete vfs.getVersions;
234
+ delete vfs.restoreVersion;
235
+ delete vfs.findEntity;
236
+ delete vfs.getEntityAppearances;
237
+ delete vfs.getConcepts;
238
+ delete vfs.getConceptGraph;
239
+ delete vfs.exportToGit;
240
+ delete vfs.importFromGit;
241
+ delete vfs.findTemporalCoupling;
242
+ // Clean up components
243
+ this.eventRecorder = undefined;
244
+ this.semanticVersioning = undefined;
245
+ this.entitySystem = undefined;
246
+ this.conceptSystem = undefined;
247
+ this.gitBridge = undefined;
248
+ console.log('Knowledge Layer augmentation removed');
249
+ }
250
+ }
251
+ //# sourceMappingURL=KnowledgeAugmentation.js.map
package/dist/brainy.d.ts CHANGED
@@ -1566,9 +1566,11 @@ export declare class Brainy<T = any> implements BrainyInterface<T> {
1566
1566
  get counts(): {
1567
1567
  entities: () => number;
1568
1568
  relationships: () => number;
1569
- byType: (type?: string) => number | {
1570
- [k: string]: number;
1571
- };
1569
+ byType: (typeOrOptions?: string | {
1570
+ excludeVFS?: boolean;
1571
+ }, options?: {
1572
+ excludeVFS?: boolean;
1573
+ }) => Promise<number | Record<string, number>>;
1572
1574
  byTypeEnum: (type: NounType) => number;
1573
1575
  topTypes: (n?: number) => NounType[];
1574
1576
  topVerbTypes: (n?: number) => VerbType[];
@@ -1579,12 +1581,12 @@ export declare class Brainy<T = any> implements BrainyInterface<T> {
1579
1581
  };
1580
1582
  byCriteria: (field: string, value: any) => Promise<number>;
1581
1583
  getAllTypeCounts: () => Map<string, number>;
1582
- getStats: () => {
1584
+ getStats: (options?: {
1585
+ excludeVFS?: boolean;
1586
+ }) => Promise<{
1583
1587
  entities: {
1584
1588
  total: number;
1585
- byType: {
1586
- [k: string]: number;
1587
- };
1589
+ byType: Record<string, number>;
1588
1590
  };
1589
1591
  relationships: {
1590
1592
  totalRelationships: number;
@@ -1594,7 +1596,7 @@ export declare class Brainy<T = any> implements BrainyInterface<T> {
1594
1596
  totalNodes: number;
1595
1597
  };
1596
1598
  density: number;
1597
- };
1599
+ }>;
1598
1600
  };
1599
1601
  /**
1600
1602
  * Augmentations API - Clean and simple
@@ -1607,14 +1609,16 @@ export declare class Brainy<T = any> implements BrainyInterface<T> {
1607
1609
  /**
1608
1610
  * Get complete statistics - convenience method
1609
1611
  * For more granular counting, use brain.counts API
1612
+ * v6.2.1: Added optional excludeVFS using Roaring bitmap intersection
1613
+ * @param options Optional settings - excludeVFS: filter out VFS entities
1610
1614
  * @returns Complete statistics including entities, relationships, and density
1611
1615
  */
1612
- getStats(): {
1616
+ getStats(options?: {
1617
+ excludeVFS?: boolean;
1618
+ }): Promise<{
1613
1619
  entities: {
1614
1620
  total: number;
1615
- byType: {
1616
- [k: string]: number;
1617
- };
1621
+ byType: Record<string, number>;
1618
1622
  };
1619
1623
  relationships: {
1620
1624
  totalRelationships: number;
@@ -1624,7 +1628,7 @@ export declare class Brainy<T = any> implements BrainyInterface<T> {
1624
1628
  totalNodes: number;
1625
1629
  };
1626
1630
  density: number;
1627
- };
1631
+ }>;
1628
1632
  /**
1629
1633
  * Parse natural language query using advanced NLP with 220+ patterns
1630
1634
  * The embedding model is always available as it's core to Brainy's functionality