agentic-qe 3.7.21 → 3.8.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.
Files changed (164) hide show
  1. package/.claude/helpers/brain-checkpoint.cjs +4 -1
  2. package/.claude/helpers/statusline-v3.cjs +3 -1
  3. package/.claude/skills/skills-manifest.json +1 -1
  4. package/CHANGELOG.md +45 -0
  5. package/README.md +2 -14
  6. package/assets/helpers/statusline-v3.cjs +3 -1
  7. package/dist/cli/brain-commands.js +6 -10
  8. package/dist/cli/bundle.js +7441 -4327
  9. package/dist/cli/commands/audit.d.ts +43 -0
  10. package/dist/cli/commands/audit.js +125 -0
  11. package/dist/cli/commands/hooks.js +29 -6
  12. package/dist/cli/commands/init.js +1 -73
  13. package/dist/cli/commands/learning.js +270 -13
  14. package/dist/cli/commands/ruvector-commands.d.ts +15 -0
  15. package/dist/cli/commands/ruvector-commands.js +271 -0
  16. package/dist/cli/handlers/init-handler.d.ts +0 -1
  17. package/dist/cli/handlers/init-handler.js +0 -6
  18. package/dist/cli/index.js +4 -2
  19. package/dist/context/sources/defect-source.js +2 -2
  20. package/dist/context/sources/memory-source.js +2 -2
  21. package/dist/context/sources/requirements-source.js +2 -2
  22. package/dist/coordination/behavior-tree/decorators.d.ts +108 -0
  23. package/dist/coordination/behavior-tree/decorators.js +251 -0
  24. package/dist/coordination/behavior-tree/index.d.ts +12 -0
  25. package/dist/coordination/behavior-tree/index.js +15 -0
  26. package/dist/coordination/behavior-tree/nodes.d.ts +165 -0
  27. package/dist/coordination/behavior-tree/nodes.js +338 -0
  28. package/dist/coordination/behavior-tree/qe-trees.d.ts +105 -0
  29. package/dist/coordination/behavior-tree/qe-trees.js +181 -0
  30. package/dist/coordination/coherence-action-gate.d.ts +284 -0
  31. package/dist/coordination/coherence-action-gate.js +512 -0
  32. package/dist/coordination/index.d.ts +4 -0
  33. package/dist/coordination/index.js +8 -0
  34. package/dist/coordination/reasoning-qec.d.ts +315 -0
  35. package/dist/coordination/reasoning-qec.js +585 -0
  36. package/dist/coordination/task-executor.d.ts +16 -0
  37. package/dist/coordination/task-executor.js +99 -0
  38. package/dist/coordination/workflow-orchestrator.d.ts +29 -0
  39. package/dist/coordination/workflow-orchestrator.js +42 -0
  40. package/dist/domains/visual-accessibility/cnn-visual-regression.d.ts +135 -0
  41. package/dist/domains/visual-accessibility/cnn-visual-regression.js +327 -0
  42. package/dist/domains/visual-accessibility/index.d.ts +1 -0
  43. package/dist/domains/visual-accessibility/index.js +4 -0
  44. package/dist/governance/coherence-validator.d.ts +112 -0
  45. package/dist/governance/coherence-validator.js +180 -0
  46. package/dist/governance/index.d.ts +1 -0
  47. package/dist/governance/index.js +2 -0
  48. package/dist/governance/witness-chain.d.ts +311 -0
  49. package/dist/governance/witness-chain.js +509 -0
  50. package/dist/init/index.d.ts +0 -2
  51. package/dist/init/index.js +0 -1
  52. package/dist/init/init-wizard-steps.d.ts +10 -0
  53. package/dist/init/init-wizard-steps.js +87 -1
  54. package/dist/init/init-wizard.d.ts +1 -9
  55. package/dist/init/init-wizard.js +3 -69
  56. package/dist/init/orchestrator.js +0 -1
  57. package/dist/init/phases/01-detection.js +0 -27
  58. package/dist/init/phases/07-hooks.js +6 -4
  59. package/dist/init/phases/phase-interface.d.ts +0 -1
  60. package/dist/init/settings-merge.js +1 -1
  61. package/dist/integrations/browser/qe-dashboard/clustering.d.ts +48 -0
  62. package/dist/integrations/browser/qe-dashboard/clustering.js +183 -0
  63. package/dist/integrations/browser/qe-dashboard/index.d.ts +12 -0
  64. package/dist/integrations/browser/qe-dashboard/index.js +15 -0
  65. package/dist/integrations/browser/qe-dashboard/pattern-explorer.d.ts +165 -0
  66. package/dist/integrations/browser/qe-dashboard/pattern-explorer.js +260 -0
  67. package/dist/integrations/browser/qe-dashboard/wasm-vector-store.d.ts +144 -0
  68. package/dist/integrations/browser/qe-dashboard/wasm-vector-store.js +277 -0
  69. package/dist/integrations/ruvector/cognitive-container-codec.d.ts +51 -0
  70. package/dist/integrations/ruvector/cognitive-container-codec.js +180 -0
  71. package/dist/integrations/ruvector/cognitive-container.d.ts +125 -0
  72. package/dist/integrations/ruvector/cognitive-container.js +306 -0
  73. package/dist/integrations/ruvector/coherence-gate.d.ts +309 -0
  74. package/dist/integrations/ruvector/coherence-gate.js +631 -0
  75. package/dist/integrations/ruvector/compressed-hnsw-integration.d.ts +176 -0
  76. package/dist/integrations/ruvector/compressed-hnsw-integration.js +301 -0
  77. package/dist/integrations/ruvector/dither-adapter.d.ts +122 -0
  78. package/dist/integrations/ruvector/dither-adapter.js +295 -0
  79. package/dist/integrations/ruvector/domain-transfer.d.ts +129 -0
  80. package/dist/integrations/ruvector/domain-transfer.js +220 -0
  81. package/dist/integrations/ruvector/feature-flags.d.ts +214 -2
  82. package/dist/integrations/ruvector/feature-flags.js +167 -2
  83. package/dist/integrations/ruvector/filter-adapter.d.ts +71 -0
  84. package/dist/integrations/ruvector/filter-adapter.js +285 -0
  85. package/dist/integrations/ruvector/gnn-wrapper.d.ts +20 -0
  86. package/dist/integrations/ruvector/gnn-wrapper.js +40 -0
  87. package/dist/integrations/ruvector/hnsw-health-monitor.d.ts +237 -0
  88. package/dist/integrations/ruvector/hnsw-health-monitor.js +394 -0
  89. package/dist/integrations/ruvector/index.d.ts +8 -2
  90. package/dist/integrations/ruvector/index.js +18 -2
  91. package/dist/integrations/ruvector/interfaces.d.ts +40 -0
  92. package/dist/integrations/ruvector/sona-persistence.d.ts +54 -0
  93. package/dist/integrations/ruvector/sona-persistence.js +162 -0
  94. package/dist/integrations/ruvector/sona-three-loop.d.ts +392 -0
  95. package/dist/integrations/ruvector/sona-three-loop.js +814 -0
  96. package/dist/integrations/ruvector/sona-wrapper.d.ts +97 -0
  97. package/dist/integrations/ruvector/sona-wrapper.js +147 -3
  98. package/dist/integrations/ruvector/spectral-math.d.ts +101 -0
  99. package/dist/integrations/ruvector/spectral-math.js +254 -0
  100. package/dist/integrations/ruvector/temporal-compression.d.ts +163 -0
  101. package/dist/integrations/ruvector/temporal-compression.js +318 -0
  102. package/dist/integrations/ruvector/thompson-sampler.d.ts +61 -0
  103. package/dist/integrations/ruvector/thompson-sampler.js +118 -0
  104. package/dist/integrations/ruvector/transfer-coherence-stub.d.ts +80 -0
  105. package/dist/integrations/ruvector/transfer-coherence-stub.js +63 -0
  106. package/dist/integrations/ruvector/transfer-verification.d.ts +119 -0
  107. package/dist/integrations/ruvector/transfer-verification.js +115 -0
  108. package/dist/kernel/hnsw-adapter.d.ts +52 -1
  109. package/dist/kernel/hnsw-adapter.js +139 -4
  110. package/dist/kernel/hnsw-index-provider.d.ts +5 -0
  111. package/dist/kernel/native-hnsw-backend.d.ts +110 -0
  112. package/dist/kernel/native-hnsw-backend.js +408 -0
  113. package/dist/kernel/unified-memory.js +5 -6
  114. package/dist/learning/aqe-learning-engine.d.ts +2 -0
  115. package/dist/learning/aqe-learning-engine.js +65 -0
  116. package/dist/learning/experience-capture-middleware.js +20 -0
  117. package/dist/learning/experience-capture.d.ts +10 -0
  118. package/dist/learning/experience-capture.js +34 -0
  119. package/dist/learning/index.d.ts +2 -2
  120. package/dist/learning/index.js +4 -4
  121. package/dist/learning/metrics-tracker.d.ts +11 -0
  122. package/dist/learning/metrics-tracker.js +29 -13
  123. package/dist/learning/pattern-lifecycle.d.ts +30 -1
  124. package/dist/learning/pattern-lifecycle.js +92 -20
  125. package/dist/learning/pattern-store.d.ts +8 -0
  126. package/dist/learning/pattern-store.js +8 -2
  127. package/dist/learning/qe-unified-memory.js +1 -28
  128. package/dist/learning/regret-tracker.d.ts +201 -0
  129. package/dist/learning/regret-tracker.js +361 -0
  130. package/dist/mcp/bundle.js +5915 -474
  131. package/dist/routing/index.d.ts +4 -2
  132. package/dist/routing/index.js +3 -1
  133. package/dist/routing/neural-tiny-dancer-router.d.ts +268 -0
  134. package/dist/routing/neural-tiny-dancer-router.js +514 -0
  135. package/dist/routing/queen-integration.js +5 -5
  136. package/dist/routing/routing-config.d.ts +6 -0
  137. package/dist/routing/routing-config.js +1 -0
  138. package/dist/routing/simple-neural-router.d.ts +76 -0
  139. package/dist/routing/simple-neural-router.js +202 -0
  140. package/dist/routing/tiny-dancer-router.d.ts +20 -1
  141. package/dist/routing/tiny-dancer-router.js +21 -2
  142. package/dist/test-scheduling/dag-attention-scheduler.d.ts +81 -0
  143. package/dist/test-scheduling/dag-attention-scheduler.js +358 -0
  144. package/dist/test-scheduling/dag-attention-types.d.ts +81 -0
  145. package/dist/test-scheduling/dag-attention-types.js +10 -0
  146. package/dist/test-scheduling/index.d.ts +1 -0
  147. package/dist/test-scheduling/index.js +4 -0
  148. package/dist/test-scheduling/pipeline.d.ts +8 -0
  149. package/dist/test-scheduling/pipeline.js +28 -0
  150. package/package.json +6 -2
  151. package/dist/cli/commands/migrate.d.ts +0 -9
  152. package/dist/cli/commands/migrate.js +0 -566
  153. package/dist/init/init-wizard-migration.d.ts +0 -52
  154. package/dist/init/init-wizard-migration.js +0 -345
  155. package/dist/init/migration/config-migrator.d.ts +0 -31
  156. package/dist/init/migration/config-migrator.js +0 -149
  157. package/dist/init/migration/data-migrator.d.ts +0 -72
  158. package/dist/init/migration/data-migrator.js +0 -232
  159. package/dist/init/migration/detector.d.ts +0 -44
  160. package/dist/init/migration/detector.js +0 -105
  161. package/dist/init/migration/index.d.ts +0 -8
  162. package/dist/init/migration/index.js +0 -8
  163. package/dist/learning/v2-to-v3-migration.d.ts +0 -86
  164. package/dist/learning/v2-to-v3-migration.js +0 -529
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Native HNSW Backend via @ruvector/router VectorDb
3
+ *
4
+ * Provides a high-performance HNSW index backed by the Rust-based
5
+ * @ruvector/router library. This backend implements the same
6
+ * IHnswIndexProvider interface as ProgressiveHnswBackend but delegates
7
+ * vector storage and search to native code for lower latency and
8
+ * higher throughput.
9
+ *
10
+ * When @ruvector/router is unavailable (e.g., unsupported platform,
11
+ * missing binary), construction throws NativeHnswUnavailableError so the
12
+ * caller (HnswAdapter factory) can fall back to the JS backend.
13
+ *
14
+ * @see ADR-081: Native HNSW NAPI Integration
15
+ * @module kernel/native-hnsw-backend
16
+ */
17
+ import type { IHnswIndexProvider, SearchResult, HnswConfig } from './hnsw-index-provider.js';
18
+ /**
19
+ * Thrown when @ruvector/router native binary is not available.
20
+ * The HnswAdapter factory catches this to fall back to the JS backend.
21
+ */
22
+ export declare class NativeHnswUnavailableError extends Error {
23
+ constructor(reason: string);
24
+ }
25
+ /**
26
+ * Reset the native module loader state.
27
+ * Useful for testing fallback behavior.
28
+ */
29
+ export declare function resetNativeModuleLoader(): void;
30
+ /**
31
+ * Check if the native module is available without throwing.
32
+ */
33
+ export declare function isNativeModuleAvailable(): boolean;
34
+ export interface NativeHnswMetrics {
35
+ totalSearches: number;
36
+ totalAdds: number;
37
+ totalRemoves: number;
38
+ avgSearchLatencyMs: number;
39
+ maxSearchLatencyMs: number;
40
+ lastSearchLatencyMs: number;
41
+ fallbackSearchCount: number;
42
+ bruteForceSearchCount: number;
43
+ nativeSearchCount: number;
44
+ fallbackRate: number;
45
+ allSearchesBruteForce: boolean;
46
+ }
47
+ /**
48
+ * Native HNSW backend using @ruvector/router VectorDb.
49
+ *
50
+ * Provides the same IHnswIndexProvider interface as ProgressiveHnswBackend
51
+ * but delegates all vector operations to a Rust-based HNSW implementation
52
+ * for improved performance.
53
+ *
54
+ * Note: @ruvector/router VectorDb uses string IDs while IHnswIndexProvider
55
+ * uses numeric IDs. Conversion is done via String(id) and Number(id).
56
+ * VectorDb search returns distance scores (lower = closer) which are
57
+ * converted to similarity scores (higher = closer) for consistency.
58
+ */
59
+ export declare class NativeHnswBackend implements IHnswIndexProvider {
60
+ private readonly config;
61
+ private nativeDb;
62
+ private readonly metadataStore;
63
+ private readonly vectorStore;
64
+ private readonly normStore;
65
+ private operationLock;
66
+ private highFallbackWarningEmitted;
67
+ private _metrics;
68
+ /**
69
+ * Create a NativeHnswBackend.
70
+ *
71
+ * @param config - HNSW configuration overrides
72
+ * @throws {NativeHnswUnavailableError} If @ruvector/router is not available
73
+ */
74
+ constructor(config?: Partial<HnswConfig>);
75
+ add(id: number, vector: Float32Array, metadata?: Record<string, unknown>): void;
76
+ search(query: Float32Array, k: number): SearchResult[];
77
+ remove(id: number): boolean;
78
+ size(): number;
79
+ dimensions(): number;
80
+ recall(): number;
81
+ /**
82
+ * Get performance metrics for this index.
83
+ */
84
+ getMetrics(): Readonly<NativeHnswMetrics>;
85
+ /**
86
+ * Get last search latency in milliseconds.
87
+ */
88
+ get lastSearchLatencyMs(): number;
89
+ /**
90
+ * Get the current configuration.
91
+ */
92
+ getConfig(): Readonly<HnswConfig>;
93
+ /**
94
+ * Clear all vectors from the index.
95
+ * Deletes all entries from the native VectorDb.
96
+ */
97
+ clear(): void;
98
+ /**
99
+ * Check if the native backend is operational.
100
+ */
101
+ isNativeAvailable(): boolean;
102
+ private normalizeVector;
103
+ private updateSearchMetrics;
104
+ /**
105
+ * Brute-force fallback search over locally stored vectors.
106
+ * Used when native search throws an unexpected error.
107
+ */
108
+ private bruteForceSearch;
109
+ }
110
+ //# sourceMappingURL=native-hnsw-backend.d.ts.map
@@ -0,0 +1,408 @@
1
+ /**
2
+ * Native HNSW Backend via @ruvector/router VectorDb
3
+ *
4
+ * Provides a high-performance HNSW index backed by the Rust-based
5
+ * @ruvector/router library. This backend implements the same
6
+ * IHnswIndexProvider interface as ProgressiveHnswBackend but delegates
7
+ * vector storage and search to native code for lower latency and
8
+ * higher throughput.
9
+ *
10
+ * When @ruvector/router is unavailable (e.g., unsupported platform,
11
+ * missing binary), construction throws NativeHnswUnavailableError so the
12
+ * caller (HnswAdapter factory) can fall back to the JS backend.
13
+ *
14
+ * @see ADR-081: Native HNSW NAPI Integration
15
+ * @module kernel/native-hnsw-backend
16
+ */
17
+ import { createRequire } from 'module';
18
+ import { DEFAULT_HNSW_CONFIG } from './hnsw-index-provider.js';
19
+ // Use createRequire for @ruvector/router (native CJS/NAPI module)
20
+ const esmRequire = createRequire(import.meta.url);
21
+ // ============================================================================
22
+ // Error Types
23
+ // ============================================================================
24
+ /**
25
+ * Thrown when @ruvector/router native binary is not available.
26
+ * The HnswAdapter factory catches this to fall back to the JS backend.
27
+ */
28
+ export class NativeHnswUnavailableError extends Error {
29
+ constructor(reason) {
30
+ super(`Native HNSW backend unavailable: ${reason}`);
31
+ this.name = 'NativeHnswUnavailableError';
32
+ }
33
+ }
34
+ // ============================================================================
35
+ // Native Module Loader
36
+ // ============================================================================
37
+ let nativeModule = null;
38
+ let nativeLoadAttempted = false;
39
+ let nativeLoadError = null;
40
+ /**
41
+ * Attempt to load the @ruvector/router native module.
42
+ * Caches the result so subsequent calls are instant.
43
+ */
44
+ function loadNativeModule() {
45
+ if (nativeLoadAttempted) {
46
+ if (nativeModule)
47
+ return nativeModule;
48
+ throw new NativeHnswUnavailableError(nativeLoadError ?? 'Unknown load error');
49
+ }
50
+ nativeLoadAttempted = true;
51
+ try {
52
+ // Use createRequire for the optional native NAPI dependency
53
+ const mod = esmRequire('@ruvector/router');
54
+ // Verify the module has the expected API
55
+ if (!mod.VectorDb || !mod.DistanceMetric) {
56
+ throw new Error('@ruvector/router module missing VectorDb or DistanceMetric exports');
57
+ }
58
+ nativeModule = mod;
59
+ return nativeModule;
60
+ }
61
+ catch (err) {
62
+ const message = err instanceof Error ? err.message : String(err);
63
+ nativeLoadError = message;
64
+ throw new NativeHnswUnavailableError(message);
65
+ }
66
+ }
67
+ /**
68
+ * Reset the native module loader state.
69
+ * Useful for testing fallback behavior.
70
+ */
71
+ export function resetNativeModuleLoader() {
72
+ nativeModule = null;
73
+ nativeLoadAttempted = false;
74
+ nativeLoadError = null;
75
+ }
76
+ /**
77
+ * Check if the native module is available without throwing.
78
+ */
79
+ export function isNativeModuleAvailable() {
80
+ try {
81
+ loadNativeModule();
82
+ return true;
83
+ }
84
+ catch {
85
+ return false;
86
+ }
87
+ }
88
+ // ============================================================================
89
+ // Vector Math Helpers
90
+ // ============================================================================
91
+ function computeNorm(v) {
92
+ let sum = 0;
93
+ for (let i = 0; i < v.length; i++)
94
+ sum += v[i] * v[i];
95
+ return Math.sqrt(sum);
96
+ }
97
+ function fastCosineSimilarity(a, b, normA, normB) {
98
+ const denom = normA * normB;
99
+ if (denom === 0)
100
+ return 0;
101
+ let dot = 0;
102
+ const len = Math.min(a.length, b.length);
103
+ for (let i = 0; i < len; i++)
104
+ dot += a[i] * b[i];
105
+ return dot / denom;
106
+ }
107
+ /**
108
+ * Resize a vector to the target dimensions.
109
+ * Shrink: average adjacent values. Grow: zero-pad.
110
+ */
111
+ function resizeVector(vector, targetDim) {
112
+ if (vector.length === targetDim)
113
+ return vector;
114
+ const result = new Float32Array(targetDim);
115
+ if (vector.length > targetDim) {
116
+ const ratio = vector.length / targetDim;
117
+ for (let i = 0; i < targetDim; i++) {
118
+ const start = Math.floor(i * ratio);
119
+ const end = Math.floor((i + 1) * ratio);
120
+ let sum = 0;
121
+ for (let j = start; j < end; j++) {
122
+ sum += vector[j];
123
+ }
124
+ result[i] = sum / (end - start);
125
+ }
126
+ }
127
+ else {
128
+ for (let i = 0; i < vector.length; i++) {
129
+ result[i] = vector[i];
130
+ }
131
+ }
132
+ return result;
133
+ }
134
+ // ============================================================================
135
+ // NativeHnswBackend
136
+ // ============================================================================
137
+ /**
138
+ * Native HNSW backend using @ruvector/router VectorDb.
139
+ *
140
+ * Provides the same IHnswIndexProvider interface as ProgressiveHnswBackend
141
+ * but delegates all vector operations to a Rust-based HNSW implementation
142
+ * for improved performance.
143
+ *
144
+ * Note: @ruvector/router VectorDb uses string IDs while IHnswIndexProvider
145
+ * uses numeric IDs. Conversion is done via String(id) and Number(id).
146
+ * VectorDb search returns distance scores (lower = closer) which are
147
+ * converted to similarity scores (higher = closer) for consistency.
148
+ */
149
+ export class NativeHnswBackend {
150
+ config;
151
+ nativeDb = null;
152
+ metadataStore = new Map();
153
+ vectorStore = new Map();
154
+ normStore = new Map();
155
+ operationLock = Promise.resolve();
156
+ highFallbackWarningEmitted = false;
157
+ _metrics = {
158
+ totalSearches: 0,
159
+ totalAdds: 0,
160
+ totalRemoves: 0,
161
+ avgSearchLatencyMs: 0,
162
+ maxSearchLatencyMs: 0,
163
+ lastSearchLatencyMs: 0,
164
+ fallbackSearchCount: 0,
165
+ bruteForceSearchCount: 0,
166
+ nativeSearchCount: 0,
167
+ fallbackRate: 0,
168
+ allSearchesBruteForce: false,
169
+ };
170
+ /**
171
+ * Create a NativeHnswBackend.
172
+ *
173
+ * @param config - HNSW configuration overrides
174
+ * @throws {NativeHnswUnavailableError} If @ruvector/router is not available
175
+ */
176
+ constructor(config) {
177
+ this.config = { ...DEFAULT_HNSW_CONFIG, ...config };
178
+ // Attempt to load native module and create VectorDb immediately.
179
+ // If the native module is unavailable or the database can't be opened,
180
+ // this throws NativeHnswUnavailableError so the factory can fall back
181
+ // to ProgressiveHnswBackend.
182
+ const native = loadNativeModule();
183
+ const distanceMetric = this.config.metric === 'cosine'
184
+ ? native.DistanceMetric.Cosine
185
+ : native.DistanceMetric.Euclidean;
186
+ try {
187
+ this.nativeDb = new native.VectorDb({
188
+ dimensions: this.config.dimensions,
189
+ distanceMetric,
190
+ hnswM: this.config.M,
191
+ hnswEfConstruction: this.config.efConstruction,
192
+ hnswEfSearch: this.config.efSearch,
193
+ });
194
+ }
195
+ catch (err) {
196
+ const message = err instanceof Error ? err.message : String(err);
197
+ throw new NativeHnswUnavailableError(`VectorDb creation failed: ${message}`);
198
+ }
199
+ }
200
+ // ============================================================================
201
+ // IHnswIndexProvider Implementation
202
+ // ============================================================================
203
+ add(id, vector, metadata) {
204
+ const normalized = this.normalizeVector(vector);
205
+ const norm = computeNorm(normalized);
206
+ // Remove existing entry if updating
207
+ if (this.vectorStore.has(id)) {
208
+ try {
209
+ this.nativeDb.delete(String(id));
210
+ }
211
+ catch { /* ignore if not found */ }
212
+ }
213
+ this.nativeDb.insert(String(id), normalized);
214
+ this.vectorStore.set(id, normalized);
215
+ this.normStore.set(id, norm);
216
+ if (metadata) {
217
+ this.metadataStore.set(id, metadata);
218
+ }
219
+ this._metrics.totalAdds++;
220
+ }
221
+ search(query, k) {
222
+ const start = performance.now();
223
+ if (this.vectorStore.size === 0)
224
+ return [];
225
+ const normalizedQuery = this.normalizeVector(query);
226
+ const queryNorm = computeNorm(normalizedQuery);
227
+ const actualK = Math.min(k, this.vectorStore.size);
228
+ let results;
229
+ try {
230
+ const nativeResults = this.nativeDb.search(normalizedQuery, actualK);
231
+ // Convert native distance scores to similarity scores.
232
+ // @ruvector/router returns { id: string, score: number } where
233
+ // score is a distance (lower = closer). We convert string IDs
234
+ // back to numbers and compute cosine similarity for consistency.
235
+ results = nativeResults.map((nr) => {
236
+ const numericId = Number(nr.id);
237
+ const storedVector = this.vectorStore.get(numericId);
238
+ const storedNorm = this.normStore.get(numericId) ?? 0;
239
+ // Compute cosine similarity for consistent scoring with ProgressiveHnswBackend
240
+ let score;
241
+ if (this.config.metric === 'cosine' && storedVector) {
242
+ score = fastCosineSimilarity(normalizedQuery, storedVector, queryNorm, storedNorm);
243
+ }
244
+ else {
245
+ // For euclidean, negate the distance (higher = closer)
246
+ score = -nr.score;
247
+ }
248
+ return {
249
+ id: numericId,
250
+ score,
251
+ metadata: this.metadataStore.get(numericId),
252
+ };
253
+ });
254
+ // Sort by descending score for consistency
255
+ results.sort((a, b) => b.score - a.score);
256
+ this._metrics.nativeSearchCount++;
257
+ }
258
+ catch {
259
+ // If native search fails, fall back to brute-force over stored vectors
260
+ this._metrics.fallbackSearchCount++;
261
+ this._metrics.bruteForceSearchCount++;
262
+ console.warn(`[NativeHNSW] FALLBACK: Using brute-force linear scan (@ruvector/router search failed). Index size: ${this.vectorStore.size}`);
263
+ results = this.bruteForceSearch(normalizedQuery, queryNorm, actualK);
264
+ }
265
+ const elapsed = performance.now() - start;
266
+ this.updateSearchMetrics(elapsed);
267
+ // Compute derived fallback metrics
268
+ this._metrics.fallbackRate =
269
+ this._metrics.fallbackSearchCount / this._metrics.totalSearches;
270
+ this._metrics.allSearchesBruteForce =
271
+ this._metrics.nativeSearchCount === 0 && this._metrics.totalSearches > 0;
272
+ // One-time warning when fallback rate is dangerously high
273
+ if (!this.highFallbackWarningEmitted &&
274
+ this._metrics.fallbackRate > 0.5 &&
275
+ this._metrics.totalSearches >= 10) {
276
+ this.highFallbackWarningEmitted = true;
277
+ console.error(`[NativeHNSW] WARNING: ${(this._metrics.fallbackRate * 100).toFixed(0)}% of searches are using brute-force fallback. Native HNSW may not be functioning correctly. Consider rebuilding the index or checking @ruvector/router installation.`);
278
+ }
279
+ if (elapsed > 50) {
280
+ console.warn(`[NativeHNSW] search took ${elapsed.toFixed(1)}ms (k=${k}, results=${results.length})`);
281
+ }
282
+ return results;
283
+ }
284
+ remove(id) {
285
+ if (!this.vectorStore.has(id))
286
+ return false;
287
+ try {
288
+ this.nativeDb.delete(String(id));
289
+ }
290
+ catch {
291
+ // Native remove failed; clean up local state anyway
292
+ }
293
+ this.vectorStore.delete(id);
294
+ this.normStore.delete(id);
295
+ this.metadataStore.delete(id);
296
+ this._metrics.totalRemoves++;
297
+ return true;
298
+ }
299
+ size() {
300
+ return this.vectorStore.size;
301
+ }
302
+ dimensions() {
303
+ return this.config.dimensions;
304
+ }
305
+ recall() {
306
+ // HNSW is approximate, estimate recall based on efSearch/M ratio
307
+ // Higher efSearch relative to M means better recall
308
+ const ratio = this.config.efSearch / this.config.M;
309
+ if (ratio >= 10)
310
+ return 0.99;
311
+ if (ratio >= 5)
312
+ return 0.97;
313
+ if (ratio >= 3)
314
+ return 0.95;
315
+ return 0.90;
316
+ }
317
+ // ============================================================================
318
+ // Public Utilities
319
+ // ============================================================================
320
+ /**
321
+ * Get performance metrics for this index.
322
+ */
323
+ getMetrics() {
324
+ return { ...this._metrics };
325
+ }
326
+ /**
327
+ * Get last search latency in milliseconds.
328
+ */
329
+ get lastSearchLatencyMs() {
330
+ return this._metrics.lastSearchLatencyMs;
331
+ }
332
+ /**
333
+ * Get the current configuration.
334
+ */
335
+ getConfig() {
336
+ return { ...this.config };
337
+ }
338
+ /**
339
+ * Clear all vectors from the index.
340
+ * Deletes all entries from the native VectorDb.
341
+ */
342
+ clear() {
343
+ // Delete all entries from native DB
344
+ for (const id of this.vectorStore.keys()) {
345
+ try {
346
+ this.nativeDb.delete(String(id));
347
+ }
348
+ catch { /* ignore */ }
349
+ }
350
+ this.vectorStore.clear();
351
+ this.normStore.clear();
352
+ this.metadataStore.clear();
353
+ }
354
+ /**
355
+ * Check if the native backend is operational.
356
+ */
357
+ isNativeAvailable() {
358
+ return this.nativeDb !== null;
359
+ }
360
+ // ============================================================================
361
+ // Private Helpers
362
+ // ============================================================================
363
+ normalizeVector(vector) {
364
+ if (vector.length === this.config.dimensions)
365
+ return vector;
366
+ return resizeVector(vector, this.config.dimensions);
367
+ }
368
+ updateSearchMetrics(latencyMs) {
369
+ this._metrics.totalSearches++;
370
+ this._metrics.lastSearchLatencyMs = latencyMs;
371
+ if (latencyMs > this._metrics.maxSearchLatencyMs) {
372
+ this._metrics.maxSearchLatencyMs = latencyMs;
373
+ }
374
+ // Running average
375
+ const n = this._metrics.totalSearches;
376
+ this._metrics.avgSearchLatencyMs =
377
+ this._metrics.avgSearchLatencyMs * ((n - 1) / n) + latencyMs / n;
378
+ }
379
+ /**
380
+ * Brute-force fallback search over locally stored vectors.
381
+ * Used when native search throws an unexpected error.
382
+ */
383
+ bruteForceSearch(query, queryNorm, k) {
384
+ const scored = [];
385
+ for (const [id, vector] of this.vectorStore) {
386
+ const norm = this.normStore.get(id) ?? computeNorm(vector);
387
+ const score = this.config.metric === 'cosine'
388
+ ? fastCosineSimilarity(query, vector, queryNorm, norm)
389
+ : -(function () {
390
+ let sum = 0;
391
+ const len = Math.min(query.length, vector.length);
392
+ for (let i = 0; i < len; i++) {
393
+ const diff = query[i] - vector[i];
394
+ sum += diff * diff;
395
+ }
396
+ return Math.sqrt(sum);
397
+ })();
398
+ scored.push({
399
+ id,
400
+ score,
401
+ metadata: this.metadataStore.get(id),
402
+ });
403
+ }
404
+ scored.sort((a, b) => b.score - a.score);
405
+ return scored.slice(0, k);
406
+ }
407
+ }
408
+ //# sourceMappingURL=native-hnsw-backend.js.map
@@ -21,7 +21,7 @@
21
21
  * - unified-memory-hnsw.ts: HNSW index + BinaryHeap
22
22
  * - unified-memory.ts: UnifiedMemoryManager class (this file, facade)
23
23
  */
24
- import Database from 'better-sqlite3';
24
+ import { openDatabase as openSafeDatabase } from '../shared/safe-db.js';
25
25
  import { safeJsonParse } from '../shared/safe-json.js';
26
26
  import { toErrorMessage } from '../shared/error-utils.js';
27
27
  import * as fs from 'fs';
@@ -278,13 +278,12 @@ export class UnifiedMemoryManager {
278
278
  dbSizeBefore = newest.size;
279
279
  }
280
280
  }
281
- this.db = new Database(this.config.dbPath);
282
- if (this.config.walMode) {
283
- this.db.pragma('journal_mode = WAL');
284
- }
281
+ this.db = openSafeDatabase(this.config.dbPath, {
282
+ walMode: this.config.walMode,
283
+ busyTimeout: this.config.busyTimeout,
284
+ });
285
285
  this.db.pragma(`mmap_size = ${this.config.mmapSize}`);
286
286
  this.db.pragma(`cache_size = ${this.config.cacheSize}`);
287
- this.db.pragma(`busy_timeout = ${this.config.busyTimeout}`);
288
287
  this.db.pragma('foreign_keys = ON');
289
288
  await this.runMigrations();
290
289
  // DATA LOSS PREVENTION: After migration, if the DB existed before and was
@@ -123,6 +123,8 @@ export declare class AQELearningEngine {
123
123
  private patternStore?;
124
124
  private coherenceService?;
125
125
  private initialized;
126
+ private _domainTransferEngine;
127
+ private _domainTransferInterval;
126
128
  private activeTasks;
127
129
  private completedTasks;
128
130
  private claudeFlowErrors;
@@ -73,6 +73,9 @@ export class AQELearningEngine {
73
73
  patternStore;
74
74
  coherenceService;
75
75
  initialized = false;
76
+ // Cross-domain transfer (Y-2 wiring)
77
+ _domainTransferEngine = null;
78
+ _domainTransferInterval = null;
76
79
  // Task tracking
77
80
  activeTasks = new Map();
78
81
  completedTasks = 0;
@@ -125,6 +128,63 @@ export class AQELearningEngine {
125
128
  promotionThreshold: this.config.promotionThreshold,
126
129
  });
127
130
  await this.experienceCapture.initialize();
131
+ // Wire persistent witness chain when feature flag is on
132
+ try {
133
+ const { isWitnessChainFeatureEnabled } = await import('../governance/witness-chain.js');
134
+ if (isWitnessChainFeatureEnabled()) {
135
+ const { createPersistentWitnessChain, createWitnessChainSQLitePersistence } = await import('../governance/witness-chain.js');
136
+ const { getUnifiedPersistence } = await import('../kernel/unified-persistence.js');
137
+ const persistence = getUnifiedPersistence();
138
+ if (persistence.isInitialized()) {
139
+ const db = persistence.getDatabase();
140
+ const chainPersistence = createWitnessChainSQLitePersistence(db);
141
+ const chain = createPersistentWitnessChain(chainPersistence);
142
+ this.experienceCapture.setWitnessChain(chain);
143
+ }
144
+ }
145
+ }
146
+ catch (e) {
147
+ if (process.env.DEBUG)
148
+ console.debug('[AQELearningEngine] Witness chain wiring skipped:', e instanceof Error ? e.message : e);
149
+ }
150
+ }
151
+ // Wire cross-domain transfer with real performance provider (Y-2 fix)
152
+ try {
153
+ const { isCrossDomainTransferEnabled } = await import('../integrations/ruvector/feature-flags.js');
154
+ if (isCrossDomainTransferEnabled() && this.patternStore) {
155
+ const { createDomainTransferEngine } = await import('../integrations/ruvector/domain-transfer.js');
156
+ const transferEngine = createDomainTransferEngine();
157
+ // Pre-fetch stats for the synchronous performance provider callback
158
+ const store = this.patternStore;
159
+ let cachedStats = await store.getStats();
160
+ // Refresh cache periodically in background
161
+ this._domainTransferInterval = setInterval(async () => {
162
+ try {
163
+ cachedStats = await store.getStats();
164
+ }
165
+ catch (e) {
166
+ if (process.env.DEBUG)
167
+ console.debug('[AQELearningEngine] Stats refresh failed:', e instanceof Error ? e.message : e);
168
+ }
169
+ }, 60_000);
170
+ this._domainTransferInterval.unref?.();
171
+ transferEngine.setPerformanceProvider((domain) => {
172
+ const domainPatterns = cachedStats.byDomain?.[domain] ?? 0;
173
+ const totalPatterns = cachedStats.totalPatterns ?? 0;
174
+ return {
175
+ domain,
176
+ successRate: totalPatterns > 0 ? domainPatterns / totalPatterns : 0.5,
177
+ avgConfidence: cachedStats.avgConfidence ?? 0.5,
178
+ patternCount: domainPatterns,
179
+ timestamp: Date.now(),
180
+ };
181
+ });
182
+ this._domainTransferEngine = transferEngine;
183
+ }
184
+ }
185
+ catch (e) {
186
+ if (process.env.DEBUG)
187
+ console.debug('[AQELearningEngine] Domain transfer wiring skipped:', e instanceof Error ? e.message : e);
128
188
  }
129
189
  // Try to initialize Claude Flow bridge (optional)
130
190
  if (this.config.enableClaudeFlow) {
@@ -802,6 +862,11 @@ export class AQELearningEngine {
802
862
  * Dispose the engine
803
863
  */
804
864
  async dispose() {
865
+ if (this._domainTransferInterval) {
866
+ clearInterval(this._domainTransferInterval);
867
+ this._domainTransferInterval = null;
868
+ }
869
+ this._domainTransferEngine = null;
805
870
  if (this.experienceCapture) {
806
871
  await this.experienceCapture.dispose();
807
872
  }
@@ -170,6 +170,26 @@ async function doInitialize() {
170
170
  CREATE INDEX IF NOT EXISTS idx_captured_exp_agent ON captured_experiences(agent);
171
171
  CREATE INDEX IF NOT EXISTS idx_captured_exp_completed ON captured_experiences(completed_at DESC);
172
172
  `);
173
+ // Add consolidation columns if missing (needed by ExperienceConsolidator)
174
+ const colNames = new Set(db.prepare('PRAGMA table_info(captured_experiences)').all().map(c => c.name));
175
+ const consolidationCols = [
176
+ ['application_count', 'INTEGER DEFAULT 0'],
177
+ ['avg_token_savings', 'REAL DEFAULT 0'],
178
+ ['embedding', 'BLOB'],
179
+ ['embedding_dimension', 'INTEGER'],
180
+ ['tags', 'TEXT'],
181
+ ['last_applied_at', 'TEXT'],
182
+ ['consolidated_into', 'TEXT DEFAULT NULL'],
183
+ ['consolidation_count', 'INTEGER DEFAULT 1'],
184
+ ['quality_updated_at', 'TEXT DEFAULT NULL'],
185
+ ['reuse_success_count', 'INTEGER DEFAULT 0'],
186
+ ['reuse_failure_count', 'INTEGER DEFAULT 0'],
187
+ ];
188
+ for (const [col, def] of consolidationCols) {
189
+ if (!colNames.has(col)) {
190
+ db.exec(`ALTER TABLE captured_experiences ADD COLUMN ${col} ${def}`);
191
+ }
192
+ }
173
193
  }
174
194
  // Start periodic cleanup of stale experiences
175
195
  startCleanupTimer();