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,260 @@
1
+ /**
2
+ * Pattern Explorer for QE Dashboard (Task 4.6)
3
+ *
4
+ * Provides pattern exploration, similarity clustering, and visualization
5
+ * data preparation for the browser-based QE intelligence dashboard.
6
+ *
7
+ * Features:
8
+ * - Load and index patterns into the vector store
9
+ * - Similarity search across patterns
10
+ * - K-Means clustering for visualization
11
+ * - Domain distribution analysis
12
+ * - Health dashboard data aggregation
13
+ *
14
+ * No browser-specific APIs: works in Node.js for testing.
15
+ *
16
+ * @module integrations/browser/qe-dashboard/pattern-explorer
17
+ */
18
+ import { WasmVectorStore, cosineSimilarity, } from './wasm-vector-store.js';
19
+ import { generateEmbedding, generateQueryEmbedding, kMeansClustering, } from './clustering.js';
20
+ // Re-export kMeansClustering for external consumers
21
+ export { kMeansClustering } from './clustering.js';
22
+ // ============================================================================
23
+ // PatternExplorer
24
+ // ============================================================================
25
+ /**
26
+ * Pattern exploration and visualization data preparation.
27
+ *
28
+ * Loads QE patterns into a vector store, provides similarity search,
29
+ * clustering, domain distribution, and aggregated dashboard data.
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * const explorer = new PatternExplorer();
34
+ * await explorer.initialize();
35
+ *
36
+ * explorer.loadPatterns(patterns);
37
+ *
38
+ * // Find similar patterns
39
+ * const similar = explorer.searchSimilar('authentication testing', 5);
40
+ *
41
+ * // Cluster for visualization
42
+ * const clusters = explorer.clusterPatterns(4);
43
+ *
44
+ * // Dashboard data
45
+ * const dashboard = explorer.getHealthDashboardData();
46
+ * ```
47
+ */
48
+ export class PatternExplorer {
49
+ store;
50
+ patterns = new Map();
51
+ embeddings = new Map();
52
+ constructor(store) {
53
+ this.store = store ?? new WasmVectorStore();
54
+ }
55
+ /** Initialize the explorer (loads WASM backend if available) */
56
+ async initialize() {
57
+ await this.store.initialize();
58
+ }
59
+ /**
60
+ * Load patterns into the explorer
61
+ *
62
+ * Each pattern is embedded (using provided embedding or auto-generated)
63
+ * and indexed in the vector store for similarity search.
64
+ */
65
+ loadPatterns(patterns) {
66
+ for (const pattern of patterns) {
67
+ const embedding = pattern.embedding ?? generateEmbedding(pattern);
68
+ this.patterns.set(pattern.id, pattern);
69
+ this.embeddings.set(pattern.id, embedding);
70
+ this.store.add(pattern.id, embedding, {
71
+ domain: pattern.domain,
72
+ confidence: pattern.confidence,
73
+ success: pattern.success,
74
+ tags: pattern.tags,
75
+ createdAt: pattern.createdAt,
76
+ }, pattern.domain);
77
+ }
78
+ }
79
+ /**
80
+ * Search for patterns similar to a text query
81
+ *
82
+ * @param query - Natural language query string
83
+ * @param k - Number of results to return
84
+ * @returns Array of matched patterns ordered by similarity
85
+ */
86
+ searchSimilar(query, k) {
87
+ const queryEmb = generateQueryEmbedding(query);
88
+ const results = this.store.search(queryEmb, k);
89
+ return results
90
+ .map((r) => this.patterns.get(r.id))
91
+ .filter((p) => p !== undefined);
92
+ }
93
+ /**
94
+ * Cluster patterns into groups using K-Means
95
+ *
96
+ * @param numClusters - Number of clusters to create
97
+ * @returns Array of PatternCluster with centroid, members, and statistics
98
+ */
99
+ clusterPatterns(numClusters) {
100
+ const patternList = Array.from(this.patterns.values());
101
+ if (patternList.length === 0)
102
+ return [];
103
+ const vectors = patternList.map((p) => this.embeddings.get(p.id) ?? generateEmbedding(p));
104
+ const assignments = kMeansClustering(vectors, numClusters);
105
+ return this.buildClusters(patternList, vectors, assignments);
106
+ }
107
+ /** Get distribution statistics per domain */
108
+ getDomainDistribution() {
109
+ const domainMap = new Map();
110
+ for (const pattern of this.patterns.values()) {
111
+ if (!domainMap.has(pattern.domain)) {
112
+ domainMap.set(pattern.domain, []);
113
+ }
114
+ domainMap.get(pattern.domain).push(pattern);
115
+ }
116
+ const stats = [];
117
+ for (const [domain, patterns] of domainMap) {
118
+ stats.push(this.computeDomainStats(domain, patterns));
119
+ }
120
+ stats.sort((a, b) => b.patternCount - a.patternCount);
121
+ return stats;
122
+ }
123
+ /** Get aggregated health dashboard data */
124
+ getHealthDashboardData() {
125
+ const allPatterns = Array.from(this.patterns.values());
126
+ const totalPatterns = allPatterns.length;
127
+ const avgConfidence = totalPatterns > 0
128
+ ? allPatterns.reduce((sum, p) => sum + p.confidence, 0) / totalPatterns
129
+ : 0;
130
+ const successCount = allPatterns.filter((p) => p.success === true).length;
131
+ const successTotal = allPatterns.filter((p) => p.success !== undefined).length;
132
+ const successRate = successTotal > 0 ? successCount / successTotal : 0;
133
+ const domainStats = this.getDomainDistribution();
134
+ const confidenceHistogram = new Array(10).fill(0);
135
+ for (const p of allPatterns) {
136
+ confidenceHistogram[Math.min(Math.floor(p.confidence * 10), 9)]++;
137
+ }
138
+ const thirtyDaysAgo = Date.now() - 30 * 24 * 60 * 60 * 1000;
139
+ const recentActivity = allPatterns.filter((p) => (p.createdAt || 0) > thirtyDaysAgo).length;
140
+ const storeInfo = this.store.getStats();
141
+ return {
142
+ totalPatterns,
143
+ domainCount: domainStats.length,
144
+ avgConfidence,
145
+ successRate,
146
+ domainStats,
147
+ confidenceHistogram,
148
+ recentActivity,
149
+ storeStats: {
150
+ totalVectors: storeInfo.totalVectors,
151
+ dimensions: storeInfo.dimensions,
152
+ wasmActive: storeInfo.wasmActive,
153
+ memoryBytes: storeInfo.memoryBytes,
154
+ },
155
+ };
156
+ }
157
+ /** Get a pattern by id */
158
+ getPattern(id) {
159
+ return this.patterns.get(id);
160
+ }
161
+ /** Get total number of loaded patterns */
162
+ get patternCount() {
163
+ return this.patterns.size;
164
+ }
165
+ /** Clear all patterns and reset the explorer */
166
+ clear() {
167
+ this.patterns.clear();
168
+ this.embeddings.clear();
169
+ this.store.clear();
170
+ }
171
+ // ==========================================================================
172
+ // Private helpers
173
+ // ==========================================================================
174
+ buildClusters(patternList, vectors, assignments) {
175
+ const clusterMap = new Map();
176
+ for (let i = 0; i < assignments.length; i++) {
177
+ const cid = assignments[i];
178
+ if (!clusterMap.has(cid)) {
179
+ clusterMap.set(cid, { patterns: [], vectors: [] });
180
+ }
181
+ const entry = clusterMap.get(cid);
182
+ entry.patterns.push(patternList[i]);
183
+ entry.vectors.push(vectors[i]);
184
+ }
185
+ const clusters = [];
186
+ for (const [id, { patterns, vectors: vecs }] of clusterMap) {
187
+ const centroid = this.computeNormalizedCentroid(vecs);
188
+ const dominantDomain = this.findDominantDomain(patterns);
189
+ const avgConfidence = patterns.reduce((s, p) => s + p.confidence, 0) / patterns.length;
190
+ let cohesionSum = 0;
191
+ for (const v of vecs) {
192
+ cohesionSum += cosineSimilarity(v, centroid);
193
+ }
194
+ clusters.push({
195
+ id,
196
+ centroid,
197
+ patterns,
198
+ dominantDomain,
199
+ avgConfidence,
200
+ cohesion: vecs.length > 0 ? cohesionSum / vecs.length : 0,
201
+ });
202
+ }
203
+ clusters.sort((a, b) => b.patterns.length - a.patterns.length);
204
+ return clusters;
205
+ }
206
+ computeNormalizedCentroid(vectors) {
207
+ const dim = vectors[0].length;
208
+ const centroid = new Float32Array(dim);
209
+ for (const v of vectors) {
210
+ for (let d = 0; d < dim; d++)
211
+ centroid[d] += v[d];
212
+ }
213
+ for (let d = 0; d < dim; d++)
214
+ centroid[d] /= vectors.length;
215
+ let norm = 0;
216
+ for (let d = 0; d < dim; d++)
217
+ norm += centroid[d] * centroid[d];
218
+ norm = Math.sqrt(norm);
219
+ if (norm > 0) {
220
+ for (let d = 0; d < dim; d++)
221
+ centroid[d] /= norm;
222
+ }
223
+ return centroid;
224
+ }
225
+ findDominantDomain(patterns) {
226
+ const counts = new Map();
227
+ for (const p of patterns) {
228
+ counts.set(p.domain, (counts.get(p.domain) || 0) + 1);
229
+ }
230
+ let best = '';
231
+ let max = 0;
232
+ for (const [domain, count] of counts) {
233
+ if (count > max) {
234
+ max = count;
235
+ best = domain;
236
+ }
237
+ }
238
+ return best;
239
+ }
240
+ computeDomainStats(domain, patterns) {
241
+ const patternCount = patterns.length;
242
+ const avgConfidence = patterns.reduce((s, p) => s + p.confidence, 0) / patternCount;
243
+ const successCount = patterns.filter((p) => p.success === true).length;
244
+ const successTotal = patterns.filter((p) => p.success !== undefined).length;
245
+ const successRate = successTotal > 0 ? successCount / successTotal : 0;
246
+ const latestTimestamp = patterns.reduce((max, p) => Math.max(max, p.createdAt || 0), 0);
247
+ const tagCounts = new Map();
248
+ for (const p of patterns) {
249
+ for (const tag of p.tags || []) {
250
+ tagCounts.set(tag, (tagCounts.get(tag) || 0) + 1);
251
+ }
252
+ }
253
+ const topTags = Array.from(tagCounts.entries())
254
+ .map(([tag, count]) => ({ tag, count }))
255
+ .sort((a, b) => b.count - a.count)
256
+ .slice(0, 5);
257
+ return { domain, patternCount, avgConfidence, successRate, latestTimestamp, topTags };
258
+ }
259
+ }
260
+ //# sourceMappingURL=pattern-explorer.js.map
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Browser-side WASM Vector Store for QE Dashboard (Task 4.6)
3
+ *
4
+ * Provides a vector store that attempts to load `rvlite` for WASM-based
5
+ * vector search. When unavailable, falls back to a lightweight in-memory
6
+ * vector store with cosine similarity search and namespace support.
7
+ *
8
+ * Design Goals:
9
+ * - No browser-specific APIs (must work in Node.js for testing)
10
+ * - All WASM imports are optional with TypeScript fallback
11
+ * - Efficient cosine similarity computation
12
+ * - Namespace-scoped vector storage
13
+ *
14
+ * @module integrations/browser/qe-dashboard/wasm-vector-store
15
+ */
16
+ /** Result of a similarity search */
17
+ export interface SearchResult {
18
+ /** Unique identifier for the matched vector */
19
+ id: string;
20
+ /** Cosine similarity score (0..1 for normalized vectors, -1..1 otherwise) */
21
+ similarity: number;
22
+ /** Metadata associated with the vector */
23
+ metadata: Record<string, unknown>;
24
+ /** Namespace the vector belongs to */
25
+ namespace?: string;
26
+ }
27
+ /** Statistics about the vector store */
28
+ export interface StoreStats {
29
+ /** Total number of vectors stored */
30
+ totalVectors: number;
31
+ /** Number of distinct namespaces */
32
+ namespaceCount: number;
33
+ /** Vectors per namespace */
34
+ namespaceSizes: Record<string, number>;
35
+ /** Dimensionality of stored vectors (0 if empty) */
36
+ dimensions: number;
37
+ /** Whether the WASM backend is active */
38
+ wasmActive: boolean;
39
+ /** Approximate memory usage in bytes */
40
+ memoryBytes: number;
41
+ }
42
+ /**
43
+ * Compute cosine similarity between two vectors
44
+ *
45
+ * cosine_similarity = dot(a, b) / (||a|| * ||b||)
46
+ *
47
+ * Optimized to accept pre-computed norms for repeated queries.
48
+ */
49
+ export declare function cosineSimilarity(a: Float32Array, b: Float32Array, normA?: number, normB?: number): number;
50
+ /**
51
+ * Browser-side vector store with optional WASM acceleration.
52
+ *
53
+ * Tries to load `rvlite` for WASM-based vector search. When unavailable,
54
+ * uses a pure TypeScript in-memory implementation with cosine similarity.
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * const store = new WasmVectorStore();
59
+ * await store.initialize();
60
+ *
61
+ * // Add vectors
62
+ * store.add('pattern-1', new Float32Array([0.1, 0.2, 0.3]), { domain: 'testing' });
63
+ * store.add('pattern-2', new Float32Array([0.4, 0.5, 0.6]), { domain: 'coverage' });
64
+ *
65
+ * // Search
66
+ * const results = store.search(new Float32Array([0.1, 0.2, 0.3]), 5);
67
+ * console.log(results[0].id); // 'pattern-1'
68
+ * console.log(results[0].similarity); // ~1.0
69
+ * ```
70
+ */
71
+ export declare class WasmVectorStore {
72
+ private vectors;
73
+ private wasmModule;
74
+ private dimensions;
75
+ private initialized;
76
+ /**
77
+ * Initialize the vector store
78
+ *
79
+ * Attempts to load the WASM backend. Falls back to TypeScript if unavailable.
80
+ * Safe to call multiple times (idempotent).
81
+ */
82
+ initialize(): Promise<void>;
83
+ /**
84
+ * Add a vector with optional metadata and namespace
85
+ *
86
+ * @param id - Unique identifier for the vector
87
+ * @param vector - The vector data as Float32Array
88
+ * @param metadata - Optional key-value metadata
89
+ * @param namespace - Optional namespace for scoped queries (default: 'default')
90
+ * @throws Error if vector dimensions are inconsistent
91
+ */
92
+ add(id: string, vector: Float32Array, metadata?: Record<string, unknown>, namespace?: string): void;
93
+ /**
94
+ * Search for the k most similar vectors to a query
95
+ *
96
+ * @param query - The query vector
97
+ * @param k - Number of results to return
98
+ * @param namespace - Optional namespace filter (searches all if omitted)
99
+ * @returns Array of SearchResult sorted by descending similarity
100
+ */
101
+ search(query: Float32Array, k: number, namespace?: string): SearchResult[];
102
+ /**
103
+ * Remove a vector by id
104
+ *
105
+ * @param id - The vector id to remove
106
+ * @returns true if the vector was found and removed, false otherwise
107
+ */
108
+ remove(id: string): boolean;
109
+ /**
110
+ * Check if a vector exists
111
+ *
112
+ * @param id - The vector id to check
113
+ * @returns true if a vector with this id exists
114
+ */
115
+ has(id: string): boolean;
116
+ /**
117
+ * Get the number of stored vectors
118
+ */
119
+ get size(): number;
120
+ /**
121
+ * Clear all vectors, optionally within a specific namespace
122
+ *
123
+ * @param namespace - If provided, only clear vectors in this namespace
124
+ */
125
+ clear(namespace?: string): void;
126
+ /**
127
+ * Get store statistics
128
+ *
129
+ * @returns StoreStats with counts, dimensions, memory usage, etc.
130
+ */
131
+ getStats(): StoreStats;
132
+ /**
133
+ * Get all vector ids, optionally filtered by namespace
134
+ *
135
+ * @param namespace - Optional namespace filter
136
+ * @returns Array of vector ids
137
+ */
138
+ getIds(namespace?: string): string[];
139
+ /**
140
+ * Whether the WASM backend is loaded
141
+ */
142
+ get isWasmActive(): boolean;
143
+ }
144
+ //# sourceMappingURL=wasm-vector-store.d.ts.map
@@ -0,0 +1,277 @@
1
+ /**
2
+ * Browser-side WASM Vector Store for QE Dashboard (Task 4.6)
3
+ *
4
+ * Provides a vector store that attempts to load `rvlite` for WASM-based
5
+ * vector search. When unavailable, falls back to a lightweight in-memory
6
+ * vector store with cosine similarity search and namespace support.
7
+ *
8
+ * Design Goals:
9
+ * - No browser-specific APIs (must work in Node.js for testing)
10
+ * - All WASM imports are optional with TypeScript fallback
11
+ * - Efficient cosine similarity computation
12
+ * - Namespace-scoped vector storage
13
+ *
14
+ * @module integrations/browser/qe-dashboard/wasm-vector-store
15
+ */
16
+ // ============================================================================
17
+ // Math Utilities
18
+ // ============================================================================
19
+ /**
20
+ * Compute the L2 norm of a vector
21
+ */
22
+ function l2Norm(v) {
23
+ let sum = 0;
24
+ for (let i = 0; i < v.length; i++) {
25
+ sum += v[i] * v[i];
26
+ }
27
+ return Math.sqrt(sum);
28
+ }
29
+ /**
30
+ * Compute cosine similarity between two vectors
31
+ *
32
+ * cosine_similarity = dot(a, b) / (||a|| * ||b||)
33
+ *
34
+ * Optimized to accept pre-computed norms for repeated queries.
35
+ */
36
+ export function cosineSimilarity(a, b, normA, normB) {
37
+ if (a.length !== b.length) {
38
+ throw new Error(`Vector dimension mismatch: ${a.length} vs ${b.length}`);
39
+ }
40
+ let dot = 0;
41
+ for (let i = 0; i < a.length; i++) {
42
+ dot += a[i] * b[i];
43
+ }
44
+ const na = normA ?? l2Norm(a);
45
+ const nb = normB ?? l2Norm(b);
46
+ if (na === 0 || nb === 0) {
47
+ return 0;
48
+ }
49
+ return dot / (na * nb);
50
+ }
51
+ /**
52
+ * Attempt to load the rvlite WASM module
53
+ * Returns null if unavailable (expected in most environments)
54
+ */
55
+ async function tryLoadRvlite() {
56
+ try {
57
+ // Dynamic import - will fail gracefully if rvlite is not installed
58
+ const rvlite = await import('rvlite');
59
+ if (rvlite && typeof rvlite.add === 'function') {
60
+ return rvlite;
61
+ }
62
+ return null;
63
+ }
64
+ catch {
65
+ // Expected: rvlite is not installed in most environments
66
+ return null;
67
+ }
68
+ }
69
+ // ============================================================================
70
+ // WasmVectorStore
71
+ // ============================================================================
72
+ /**
73
+ * Browser-side vector store with optional WASM acceleration.
74
+ *
75
+ * Tries to load `rvlite` for WASM-based vector search. When unavailable,
76
+ * uses a pure TypeScript in-memory implementation with cosine similarity.
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * const store = new WasmVectorStore();
81
+ * await store.initialize();
82
+ *
83
+ * // Add vectors
84
+ * store.add('pattern-1', new Float32Array([0.1, 0.2, 0.3]), { domain: 'testing' });
85
+ * store.add('pattern-2', new Float32Array([0.4, 0.5, 0.6]), { domain: 'coverage' });
86
+ *
87
+ * // Search
88
+ * const results = store.search(new Float32Array([0.1, 0.2, 0.3]), 5);
89
+ * console.log(results[0].id); // 'pattern-1'
90
+ * console.log(results[0].similarity); // ~1.0
91
+ * ```
92
+ */
93
+ export class WasmVectorStore {
94
+ vectors = new Map();
95
+ wasmModule = null;
96
+ dimensions = 0;
97
+ initialized = false;
98
+ /**
99
+ * Initialize the vector store
100
+ *
101
+ * Attempts to load the WASM backend. Falls back to TypeScript if unavailable.
102
+ * Safe to call multiple times (idempotent).
103
+ */
104
+ async initialize() {
105
+ if (this.initialized)
106
+ return;
107
+ this.wasmModule = await tryLoadRvlite();
108
+ this.initialized = true;
109
+ }
110
+ /**
111
+ * Add a vector with optional metadata and namespace
112
+ *
113
+ * @param id - Unique identifier for the vector
114
+ * @param vector - The vector data as Float32Array
115
+ * @param metadata - Optional key-value metadata
116
+ * @param namespace - Optional namespace for scoped queries (default: 'default')
117
+ * @throws Error if vector dimensions are inconsistent
118
+ */
119
+ add(id, vector, metadata = {}, namespace = 'default') {
120
+ if (vector.length === 0) {
121
+ throw new Error('Cannot add zero-length vector');
122
+ }
123
+ // Enforce consistent dimensionality
124
+ if (this.dimensions === 0) {
125
+ this.dimensions = vector.length;
126
+ }
127
+ else if (vector.length !== this.dimensions) {
128
+ throw new Error(`Dimension mismatch: expected ${this.dimensions}, got ${vector.length}`);
129
+ }
130
+ // Delegate to WASM if available
131
+ if (this.wasmModule) {
132
+ this.wasmModule.add(id, vector, namespace);
133
+ // Still keep in JS map for metadata lookups
134
+ }
135
+ const norm = l2Norm(vector);
136
+ this.vectors.set(id, { vector, metadata, namespace, norm });
137
+ }
138
+ /**
139
+ * Search for the k most similar vectors to a query
140
+ *
141
+ * @param query - The query vector
142
+ * @param k - Number of results to return
143
+ * @param namespace - Optional namespace filter (searches all if omitted)
144
+ * @returns Array of SearchResult sorted by descending similarity
145
+ */
146
+ search(query, k, namespace) {
147
+ if (query.length === 0) {
148
+ return [];
149
+ }
150
+ if (this.vectors.size === 0) {
151
+ return [];
152
+ }
153
+ // Dimension check for query
154
+ if (this.dimensions > 0 && query.length !== this.dimensions) {
155
+ throw new Error(`Query dimension mismatch: expected ${this.dimensions}, got ${query.length}`);
156
+ }
157
+ const queryNorm = l2Norm(query);
158
+ const results = [];
159
+ for (const [id, entry] of this.vectors) {
160
+ // Namespace filter
161
+ if (namespace !== undefined && entry.namespace !== namespace) {
162
+ continue;
163
+ }
164
+ const similarity = cosineSimilarity(query, entry.vector, queryNorm, entry.norm);
165
+ results.push({
166
+ id,
167
+ similarity,
168
+ metadata: { ...entry.metadata },
169
+ namespace: entry.namespace,
170
+ });
171
+ }
172
+ // Sort by descending similarity
173
+ results.sort((a, b) => b.similarity - a.similarity);
174
+ return results.slice(0, Math.max(0, k));
175
+ }
176
+ /**
177
+ * Remove a vector by id
178
+ *
179
+ * @param id - The vector id to remove
180
+ * @returns true if the vector was found and removed, false otherwise
181
+ */
182
+ remove(id) {
183
+ if (this.wasmModule) {
184
+ this.wasmModule.remove(id);
185
+ }
186
+ const existed = this.vectors.delete(id);
187
+ // Reset dimensions if store is now empty
188
+ if (this.vectors.size === 0) {
189
+ this.dimensions = 0;
190
+ }
191
+ return existed;
192
+ }
193
+ /**
194
+ * Check if a vector exists
195
+ *
196
+ * @param id - The vector id to check
197
+ * @returns true if a vector with this id exists
198
+ */
199
+ has(id) {
200
+ return this.vectors.has(id);
201
+ }
202
+ /**
203
+ * Get the number of stored vectors
204
+ */
205
+ get size() {
206
+ return this.vectors.size;
207
+ }
208
+ /**
209
+ * Clear all vectors, optionally within a specific namespace
210
+ *
211
+ * @param namespace - If provided, only clear vectors in this namespace
212
+ */
213
+ clear(namespace) {
214
+ if (namespace === undefined) {
215
+ this.vectors.clear();
216
+ this.dimensions = 0;
217
+ }
218
+ else {
219
+ for (const [id, entry] of this.vectors) {
220
+ if (entry.namespace === namespace) {
221
+ this.vectors.delete(id);
222
+ }
223
+ }
224
+ if (this.vectors.size === 0) {
225
+ this.dimensions = 0;
226
+ }
227
+ }
228
+ }
229
+ /**
230
+ * Get store statistics
231
+ *
232
+ * @returns StoreStats with counts, dimensions, memory usage, etc.
233
+ */
234
+ getStats() {
235
+ const namespaceSizes = {};
236
+ let memoryBytes = 0;
237
+ for (const [, entry] of this.vectors) {
238
+ const ns = entry.namespace;
239
+ namespaceSizes[ns] = (namespaceSizes[ns] || 0) + 1;
240
+ // Approximate: Float32Array bytes + metadata overhead
241
+ memoryBytes += entry.vector.byteLength + 128;
242
+ }
243
+ return {
244
+ totalVectors: this.vectors.size,
245
+ namespaceCount: Object.keys(namespaceSizes).length,
246
+ namespaceSizes,
247
+ dimensions: this.dimensions,
248
+ wasmActive: this.wasmModule !== null,
249
+ memoryBytes,
250
+ };
251
+ }
252
+ /**
253
+ * Get all vector ids, optionally filtered by namespace
254
+ *
255
+ * @param namespace - Optional namespace filter
256
+ * @returns Array of vector ids
257
+ */
258
+ getIds(namespace) {
259
+ if (namespace === undefined) {
260
+ return Array.from(this.vectors.keys());
261
+ }
262
+ const ids = [];
263
+ for (const [id, entry] of this.vectors) {
264
+ if (entry.namespace === namespace) {
265
+ ids.push(id);
266
+ }
267
+ }
268
+ return ids;
269
+ }
270
+ /**
271
+ * Whether the WASM backend is loaded
272
+ */
273
+ get isWasmActive() {
274
+ return this.wasmModule !== null;
275
+ }
276
+ }
277
+ //# sourceMappingURL=wasm-vector-store.js.map