agentic-qe 3.7.22 → 3.8.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.
- package/.claude/agents/v3/qe-message-broker-tester.md +3 -3
- package/.claude/agents/v3/qe-middleware-validator.md +3 -3
- package/.claude/agents/v3/qe-odata-contract-tester.md +3 -3
- package/.claude/agents/v3/qe-qx-partner.md +1 -1
- package/.claude/agents/v3/qe-sap-idoc-tester.md +3 -3
- package/.claude/agents/v3/qe-sap-rfc-tester.md +3 -3
- package/.claude/agents/v3/qe-soap-tester.md +3 -3
- package/.claude/agents/v3/qe-sod-analyzer.md +3 -3
- package/.claude/skills/skills-manifest.json +1 -1
- package/CHANGELOG.md +42 -0
- package/README.md +2 -2
- package/assets/agents/v3/qe-message-broker-tester.md +3 -3
- package/assets/agents/v3/qe-middleware-validator.md +3 -3
- package/assets/agents/v3/qe-odata-contract-tester.md +3 -3
- package/assets/agents/v3/qe-qx-partner.md +1 -1
- package/assets/agents/v3/qe-sap-idoc-tester.md +3 -3
- package/assets/agents/v3/qe-sap-rfc-tester.md +3 -3
- package/assets/agents/v3/qe-soap-tester.md +3 -3
- package/assets/agents/v3/qe-sod-analyzer.md +3 -3
- package/dist/cli/bundle.js +5689 -1244
- package/dist/cli/commands/audit.d.ts +43 -0
- package/dist/cli/commands/audit.js +125 -0
- package/dist/cli/commands/learning.js +106 -1
- package/dist/cli/commands/ruvector-commands.d.ts +15 -0
- package/dist/cli/commands/ruvector-commands.js +271 -0
- package/dist/cli/index.js +4 -0
- package/dist/coordination/behavior-tree/decorators.d.ts +108 -0
- package/dist/coordination/behavior-tree/decorators.js +251 -0
- package/dist/coordination/behavior-tree/index.d.ts +12 -0
- package/dist/coordination/behavior-tree/index.js +15 -0
- package/dist/coordination/behavior-tree/nodes.d.ts +165 -0
- package/dist/coordination/behavior-tree/nodes.js +338 -0
- package/dist/coordination/behavior-tree/qe-trees.d.ts +105 -0
- package/dist/coordination/behavior-tree/qe-trees.js +181 -0
- package/dist/coordination/coherence-action-gate.d.ts +284 -0
- package/dist/coordination/coherence-action-gate.js +512 -0
- package/dist/coordination/index.d.ts +4 -0
- package/dist/coordination/index.js +8 -0
- package/dist/coordination/reasoning-qec.d.ts +315 -0
- package/dist/coordination/reasoning-qec.js +585 -0
- package/dist/coordination/task-executor.d.ts +16 -0
- package/dist/coordination/task-executor.js +99 -0
- package/dist/coordination/workflow-orchestrator.d.ts +29 -0
- package/dist/coordination/workflow-orchestrator.js +42 -0
- package/dist/domains/visual-accessibility/cnn-visual-regression.d.ts +135 -0
- package/dist/domains/visual-accessibility/cnn-visual-regression.js +327 -0
- package/dist/domains/visual-accessibility/index.d.ts +1 -0
- package/dist/domains/visual-accessibility/index.js +4 -0
- package/dist/governance/coherence-validator.d.ts +112 -0
- package/dist/governance/coherence-validator.js +180 -0
- package/dist/governance/index.d.ts +1 -0
- package/dist/governance/index.js +2 -0
- package/dist/governance/witness-chain.d.ts +311 -0
- package/dist/governance/witness-chain.js +509 -0
- package/dist/init/settings-merge.js +1 -1
- package/dist/integrations/browser/qe-dashboard/clustering.d.ts +48 -0
- package/dist/integrations/browser/qe-dashboard/clustering.js +183 -0
- package/dist/integrations/browser/qe-dashboard/index.d.ts +12 -0
- package/dist/integrations/browser/qe-dashboard/index.js +15 -0
- package/dist/integrations/browser/qe-dashboard/pattern-explorer.d.ts +165 -0
- package/dist/integrations/browser/qe-dashboard/pattern-explorer.js +260 -0
- package/dist/integrations/browser/qe-dashboard/wasm-vector-store.d.ts +144 -0
- package/dist/integrations/browser/qe-dashboard/wasm-vector-store.js +277 -0
- package/dist/integrations/ruvector/cognitive-container-codec.d.ts +51 -0
- package/dist/integrations/ruvector/cognitive-container-codec.js +180 -0
- package/dist/integrations/ruvector/cognitive-container.d.ts +125 -0
- package/dist/integrations/ruvector/cognitive-container.js +306 -0
- package/dist/integrations/ruvector/coherence-gate.d.ts +309 -0
- package/dist/integrations/ruvector/coherence-gate.js +631 -0
- package/dist/integrations/ruvector/compressed-hnsw-integration.d.ts +176 -0
- package/dist/integrations/ruvector/compressed-hnsw-integration.js +301 -0
- package/dist/integrations/ruvector/dither-adapter.d.ts +122 -0
- package/dist/integrations/ruvector/dither-adapter.js +295 -0
- package/dist/integrations/ruvector/domain-transfer.d.ts +129 -0
- package/dist/integrations/ruvector/domain-transfer.js +220 -0
- package/dist/integrations/ruvector/feature-flags.d.ts +214 -2
- package/dist/integrations/ruvector/feature-flags.js +167 -2
- package/dist/integrations/ruvector/filter-adapter.d.ts +71 -0
- package/dist/integrations/ruvector/filter-adapter.js +285 -0
- package/dist/integrations/ruvector/gnn-wrapper.d.ts +20 -0
- package/dist/integrations/ruvector/gnn-wrapper.js +40 -0
- package/dist/integrations/ruvector/hnsw-health-monitor.d.ts +237 -0
- package/dist/integrations/ruvector/hnsw-health-monitor.js +394 -0
- package/dist/integrations/ruvector/index.d.ts +8 -2
- package/dist/integrations/ruvector/index.js +18 -2
- package/dist/integrations/ruvector/interfaces.d.ts +40 -0
- package/dist/integrations/ruvector/sona-persistence.d.ts +54 -0
- package/dist/integrations/ruvector/sona-persistence.js +162 -0
- package/dist/integrations/ruvector/sona-three-loop.d.ts +392 -0
- package/dist/integrations/ruvector/sona-three-loop.js +814 -0
- package/dist/integrations/ruvector/sona-wrapper.d.ts +97 -0
- package/dist/integrations/ruvector/sona-wrapper.js +147 -3
- package/dist/integrations/ruvector/spectral-math.d.ts +101 -0
- package/dist/integrations/ruvector/spectral-math.js +254 -0
- package/dist/integrations/ruvector/temporal-compression.d.ts +163 -0
- package/dist/integrations/ruvector/temporal-compression.js +318 -0
- package/dist/integrations/ruvector/thompson-sampler.d.ts +61 -0
- package/dist/integrations/ruvector/thompson-sampler.js +118 -0
- package/dist/integrations/ruvector/transfer-coherence-stub.d.ts +80 -0
- package/dist/integrations/ruvector/transfer-coherence-stub.js +63 -0
- package/dist/integrations/ruvector/transfer-verification.d.ts +119 -0
- package/dist/integrations/ruvector/transfer-verification.js +115 -0
- package/dist/kernel/hnsw-adapter.d.ts +52 -1
- package/dist/kernel/hnsw-adapter.js +139 -4
- package/dist/kernel/hnsw-index-provider.d.ts +5 -0
- package/dist/kernel/native-hnsw-backend.d.ts +110 -0
- package/dist/kernel/native-hnsw-backend.js +408 -0
- package/dist/learning/aqe-learning-engine.d.ts +2 -0
- package/dist/learning/aqe-learning-engine.js +65 -0
- package/dist/learning/experience-capture.d.ts +10 -0
- package/dist/learning/experience-capture.js +34 -0
- package/dist/learning/index.d.ts +2 -0
- package/dist/learning/index.js +4 -0
- package/dist/learning/metrics-tracker.d.ts +11 -0
- package/dist/learning/metrics-tracker.js +14 -0
- package/dist/learning/pattern-lifecycle.d.ts +29 -0
- package/dist/learning/pattern-lifecycle.js +74 -0
- package/dist/learning/pattern-store.d.ts +8 -0
- package/dist/learning/pattern-store.js +8 -2
- package/dist/learning/regret-tracker.d.ts +201 -0
- package/dist/learning/regret-tracker.js +361 -0
- package/dist/mcp/bundle.js +5834 -398
- package/dist/routing/index.d.ts +4 -2
- package/dist/routing/index.js +3 -1
- package/dist/routing/neural-tiny-dancer-router.d.ts +268 -0
- package/dist/routing/neural-tiny-dancer-router.js +514 -0
- package/dist/routing/queen-integration.js +5 -5
- package/dist/routing/routing-config.d.ts +6 -0
- package/dist/routing/routing-config.js +1 -0
- package/dist/routing/simple-neural-router.d.ts +76 -0
- package/dist/routing/simple-neural-router.js +202 -0
- package/dist/routing/tiny-dancer-router.d.ts +20 -1
- package/dist/routing/tiny-dancer-router.js +21 -2
- package/dist/test-scheduling/dag-attention-scheduler.d.ts +81 -0
- package/dist/test-scheduling/dag-attention-scheduler.js +358 -0
- package/dist/test-scheduling/dag-attention-types.d.ts +81 -0
- package/dist/test-scheduling/dag-attention-types.js +10 -0
- package/dist/test-scheduling/index.d.ts +1 -0
- package/dist/test-scheduling/index.js +4 -0
- package/dist/test-scheduling/pipeline.d.ts +8 -0
- package/dist/test-scheduling/pipeline.js +28 -0
- package/package.json +6 -2
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* K-Means Clustering and Embedding Utilities (Task 4.6)
|
|
3
|
+
*
|
|
4
|
+
* Provides K-Means clustering with K-Means++ initialization and
|
|
5
|
+
* deterministic pseudo-embedding generation for patterns without
|
|
6
|
+
* pre-computed vectors.
|
|
7
|
+
*
|
|
8
|
+
* @module integrations/browser/qe-dashboard/clustering
|
|
9
|
+
*/
|
|
10
|
+
import { cosineSimilarity } from './wasm-vector-store.js';
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// Embedding Generation
|
|
13
|
+
// ============================================================================
|
|
14
|
+
/**
|
|
15
|
+
* Dimension for auto-generated embeddings.
|
|
16
|
+
* Kept small (32) for efficiency in browser contexts.
|
|
17
|
+
*/
|
|
18
|
+
export const EMBEDDING_DIM = 32;
|
|
19
|
+
/**
|
|
20
|
+
* Generate a deterministic pseudo-embedding from a pattern's text content.
|
|
21
|
+
*
|
|
22
|
+
* Uses a simple hash-based approach to produce a stable vector from the
|
|
23
|
+
* pattern's description and domain. This is a fallback when no real
|
|
24
|
+
* embedding model is available.
|
|
25
|
+
*
|
|
26
|
+
* @param pattern - The pattern to embed
|
|
27
|
+
* @returns Float32Array embedding of length EMBEDDING_DIM
|
|
28
|
+
*/
|
|
29
|
+
export function generateEmbedding(pattern) {
|
|
30
|
+
const text = `${pattern.domain} ${pattern.description} ${(pattern.tags || []).join(' ')}`;
|
|
31
|
+
const embedding = new Float32Array(EMBEDDING_DIM);
|
|
32
|
+
// Simple deterministic hash-based embedding
|
|
33
|
+
for (let i = 0; i < text.length; i++) {
|
|
34
|
+
const charCode = text.charCodeAt(i);
|
|
35
|
+
const idx = i % EMBEDDING_DIM;
|
|
36
|
+
// Mix character codes using a simple multiplicative hash
|
|
37
|
+
embedding[idx] += Math.sin(charCode * (i + 1) * 0.1) * 0.5;
|
|
38
|
+
}
|
|
39
|
+
// Normalize to unit length
|
|
40
|
+
let norm = 0;
|
|
41
|
+
for (let i = 0; i < embedding.length; i++) {
|
|
42
|
+
norm += embedding[i] * embedding[i];
|
|
43
|
+
}
|
|
44
|
+
norm = Math.sqrt(norm);
|
|
45
|
+
if (norm > 0) {
|
|
46
|
+
for (let i = 0; i < embedding.length; i++) {
|
|
47
|
+
embedding[i] /= norm;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return embedding;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Generate a query embedding from a text string
|
|
54
|
+
*/
|
|
55
|
+
export function generateQueryEmbedding(query) {
|
|
56
|
+
return generateEmbedding({
|
|
57
|
+
domain: '',
|
|
58
|
+
description: query,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
// ============================================================================
|
|
62
|
+
// K-Means Clustering
|
|
63
|
+
// ============================================================================
|
|
64
|
+
/**
|
|
65
|
+
* K-Means clustering for Float32Array vectors.
|
|
66
|
+
*
|
|
67
|
+
* Uses K-Means++ initialization for better centroid placement,
|
|
68
|
+
* then iterates until convergence or maxIter is reached.
|
|
69
|
+
*
|
|
70
|
+
* @param vectors - Array of vectors to cluster
|
|
71
|
+
* @param k - Number of clusters
|
|
72
|
+
* @param maxIter - Maximum iterations (default: 50)
|
|
73
|
+
* @returns Array of cluster assignments (index per vector)
|
|
74
|
+
*/
|
|
75
|
+
export function kMeansClustering(vectors, k, maxIter = 50) {
|
|
76
|
+
if (vectors.length === 0 || k <= 0) {
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
const n = vectors.length;
|
|
80
|
+
const clampedK = Math.min(k, n);
|
|
81
|
+
const dim = vectors[0].length;
|
|
82
|
+
// K-Means++ initialization
|
|
83
|
+
const centroids = initializeCentroids(vectors, clampedK);
|
|
84
|
+
const assignments = new Array(n).fill(0);
|
|
85
|
+
for (let iter = 0; iter < maxIter; iter++) {
|
|
86
|
+
let changed = false;
|
|
87
|
+
// Assignment step: assign each vector to the nearest centroid
|
|
88
|
+
for (let i = 0; i < n; i++) {
|
|
89
|
+
let bestCluster = 0;
|
|
90
|
+
let bestSim = -Infinity;
|
|
91
|
+
for (let c = 0; c < clampedK; c++) {
|
|
92
|
+
const sim = cosineSimilarity(vectors[i], centroids[c]);
|
|
93
|
+
if (sim > bestSim) {
|
|
94
|
+
bestSim = sim;
|
|
95
|
+
bestCluster = c;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (assignments[i] !== bestCluster) {
|
|
99
|
+
assignments[i] = bestCluster;
|
|
100
|
+
changed = true;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Convergence check
|
|
104
|
+
if (!changed) {
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
// Update step: recompute centroids
|
|
108
|
+
for (let c = 0; c < clampedK; c++) {
|
|
109
|
+
const newCentroid = new Float32Array(dim);
|
|
110
|
+
let count = 0;
|
|
111
|
+
for (let i = 0; i < n; i++) {
|
|
112
|
+
if (assignments[i] === c) {
|
|
113
|
+
for (let d = 0; d < dim; d++) {
|
|
114
|
+
newCentroid[d] += vectors[i][d];
|
|
115
|
+
}
|
|
116
|
+
count++;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (count > 0) {
|
|
120
|
+
for (let d = 0; d < dim; d++) {
|
|
121
|
+
newCentroid[d] /= count;
|
|
122
|
+
}
|
|
123
|
+
// Normalize centroid
|
|
124
|
+
let norm = 0;
|
|
125
|
+
for (let d = 0; d < dim; d++) {
|
|
126
|
+
norm += newCentroid[d] * newCentroid[d];
|
|
127
|
+
}
|
|
128
|
+
norm = Math.sqrt(norm);
|
|
129
|
+
if (norm > 0) {
|
|
130
|
+
for (let d = 0; d < dim; d++) {
|
|
131
|
+
newCentroid[d] /= norm;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
centroids[c] = newCentroid;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return assignments;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* K-Means++ initialization: select initial centroids with probability
|
|
142
|
+
* proportional to squared distance from nearest existing centroid.
|
|
143
|
+
*/
|
|
144
|
+
function initializeCentroids(vectors, k) {
|
|
145
|
+
const n = vectors.length;
|
|
146
|
+
const centroids = [];
|
|
147
|
+
// Pick first centroid (deterministic: use first vector)
|
|
148
|
+
centroids.push(new Float32Array(vectors[0]));
|
|
149
|
+
for (let c = 1; c < k; c++) {
|
|
150
|
+
// Compute distances to nearest centroid
|
|
151
|
+
const distances = new Float64Array(n);
|
|
152
|
+
let totalDist = 0;
|
|
153
|
+
for (let i = 0; i < n; i++) {
|
|
154
|
+
let minDist = Infinity;
|
|
155
|
+
for (const centroid of centroids) {
|
|
156
|
+
const sim = cosineSimilarity(vectors[i], centroid);
|
|
157
|
+
const dist = 1 - sim;
|
|
158
|
+
if (dist < minDist) {
|
|
159
|
+
minDist = dist;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
distances[i] = minDist * minDist; // Squared distance
|
|
163
|
+
totalDist += distances[i];
|
|
164
|
+
}
|
|
165
|
+
if (totalDist === 0) {
|
|
166
|
+
// All points identical to existing centroids; pick sequentially
|
|
167
|
+
centroids.push(new Float32Array(vectors[c % n]));
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
// Deterministic selection: pick the point with maximum distance
|
|
171
|
+
let maxIdx = 0;
|
|
172
|
+
let maxDist = -1;
|
|
173
|
+
for (let i = 0; i < n; i++) {
|
|
174
|
+
if (distances[i] > maxDist) {
|
|
175
|
+
maxDist = distances[i];
|
|
176
|
+
maxIdx = i;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
centroids.push(new Float32Array(vectors[maxIdx]));
|
|
180
|
+
}
|
|
181
|
+
return centroids;
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=clustering.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QE Dashboard - Browser-based intelligence dashboard (Task 4.6)
|
|
3
|
+
*
|
|
4
|
+
* Provides WASM-accelerated vector storage and pattern exploration
|
|
5
|
+
* for visualizing QE intelligence data in the browser.
|
|
6
|
+
*
|
|
7
|
+
* @module integrations/browser/qe-dashboard
|
|
8
|
+
*/
|
|
9
|
+
export { WasmVectorStore, cosineSimilarity, type SearchResult, type StoreStats, } from './wasm-vector-store.js';
|
|
10
|
+
export { kMeansClustering, generateEmbedding, generateQueryEmbedding, EMBEDDING_DIM, type EmbeddablePattern, } from './clustering.js';
|
|
11
|
+
export { PatternExplorer, type Pattern, type PatternCluster, type DomainStats, type DashboardData, } from './pattern-explorer.js';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QE Dashboard - Browser-based intelligence dashboard (Task 4.6)
|
|
3
|
+
*
|
|
4
|
+
* Provides WASM-accelerated vector storage and pattern exploration
|
|
5
|
+
* for visualizing QE intelligence data in the browser.
|
|
6
|
+
*
|
|
7
|
+
* @module integrations/browser/qe-dashboard
|
|
8
|
+
*/
|
|
9
|
+
// Vector Store
|
|
10
|
+
export { WasmVectorStore, cosineSimilarity, } from './wasm-vector-store.js';
|
|
11
|
+
// Clustering
|
|
12
|
+
export { kMeansClustering, generateEmbedding, generateQueryEmbedding, EMBEDDING_DIM, } from './clustering.js';
|
|
13
|
+
// Pattern Explorer
|
|
14
|
+
export { PatternExplorer, } from './pattern-explorer.js';
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,165 @@
|
|
|
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 } from './wasm-vector-store.js';
|
|
19
|
+
export { kMeansClustering } from './clustering.js';
|
|
20
|
+
/** A QE pattern for exploration */
|
|
21
|
+
export interface Pattern {
|
|
22
|
+
/** Unique pattern identifier */
|
|
23
|
+
id: string;
|
|
24
|
+
/** Domain the pattern belongs to */
|
|
25
|
+
domain: string;
|
|
26
|
+
/** Human-readable description */
|
|
27
|
+
description: string;
|
|
28
|
+
/** Confidence score (0..1) */
|
|
29
|
+
confidence: number;
|
|
30
|
+
/** Embedding vector (optional - will be auto-generated if missing) */
|
|
31
|
+
embedding?: Float32Array;
|
|
32
|
+
/** Tags for filtering */
|
|
33
|
+
tags?: string[];
|
|
34
|
+
/** Timestamp of pattern creation */
|
|
35
|
+
createdAt?: number;
|
|
36
|
+
/** Whether the pattern was successful */
|
|
37
|
+
success?: boolean;
|
|
38
|
+
/** Additional metadata */
|
|
39
|
+
metadata?: Record<string, unknown>;
|
|
40
|
+
}
|
|
41
|
+
/** A cluster of similar patterns */
|
|
42
|
+
export interface PatternCluster {
|
|
43
|
+
/** Cluster index */
|
|
44
|
+
id: number;
|
|
45
|
+
/** Centroid vector of the cluster */
|
|
46
|
+
centroid: Float32Array;
|
|
47
|
+
/** Patterns assigned to this cluster */
|
|
48
|
+
patterns: Pattern[];
|
|
49
|
+
/** Dominant domain in this cluster */
|
|
50
|
+
dominantDomain: string;
|
|
51
|
+
/** Average confidence within the cluster */
|
|
52
|
+
avgConfidence: number;
|
|
53
|
+
/** Intra-cluster cohesion (average similarity to centroid) */
|
|
54
|
+
cohesion: number;
|
|
55
|
+
}
|
|
56
|
+
/** Statistics about a domain */
|
|
57
|
+
export interface DomainStats {
|
|
58
|
+
/** Domain name */
|
|
59
|
+
domain: string;
|
|
60
|
+
/** Number of patterns in this domain */
|
|
61
|
+
patternCount: number;
|
|
62
|
+
/** Average confidence across patterns */
|
|
63
|
+
avgConfidence: number;
|
|
64
|
+
/** Success rate (fraction of successful patterns) */
|
|
65
|
+
successRate: number;
|
|
66
|
+
/** Most recent pattern timestamp */
|
|
67
|
+
latestTimestamp: number;
|
|
68
|
+
/** Top tags in this domain */
|
|
69
|
+
topTags: Array<{
|
|
70
|
+
tag: string;
|
|
71
|
+
count: number;
|
|
72
|
+
}>;
|
|
73
|
+
}
|
|
74
|
+
/** Aggregated dashboard data */
|
|
75
|
+
export interface DashboardData {
|
|
76
|
+
/** Total number of loaded patterns */
|
|
77
|
+
totalPatterns: number;
|
|
78
|
+
/** Number of distinct domains */
|
|
79
|
+
domainCount: number;
|
|
80
|
+
/** Overall average confidence */
|
|
81
|
+
avgConfidence: number;
|
|
82
|
+
/** Overall success rate */
|
|
83
|
+
successRate: number;
|
|
84
|
+
/** Per-domain statistics */
|
|
85
|
+
domainStats: DomainStats[];
|
|
86
|
+
/** Confidence distribution histogram (10 bins) */
|
|
87
|
+
confidenceHistogram: number[];
|
|
88
|
+
/** Recent pattern activity (last 30 days if timestamps present) */
|
|
89
|
+
recentActivity: number;
|
|
90
|
+
/** Vector store statistics */
|
|
91
|
+
storeStats: {
|
|
92
|
+
totalVectors: number;
|
|
93
|
+
dimensions: number;
|
|
94
|
+
wasmActive: boolean;
|
|
95
|
+
memoryBytes: number;
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Pattern exploration and visualization data preparation.
|
|
100
|
+
*
|
|
101
|
+
* Loads QE patterns into a vector store, provides similarity search,
|
|
102
|
+
* clustering, domain distribution, and aggregated dashboard data.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* const explorer = new PatternExplorer();
|
|
107
|
+
* await explorer.initialize();
|
|
108
|
+
*
|
|
109
|
+
* explorer.loadPatterns(patterns);
|
|
110
|
+
*
|
|
111
|
+
* // Find similar patterns
|
|
112
|
+
* const similar = explorer.searchSimilar('authentication testing', 5);
|
|
113
|
+
*
|
|
114
|
+
* // Cluster for visualization
|
|
115
|
+
* const clusters = explorer.clusterPatterns(4);
|
|
116
|
+
*
|
|
117
|
+
* // Dashboard data
|
|
118
|
+
* const dashboard = explorer.getHealthDashboardData();
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
export declare class PatternExplorer {
|
|
122
|
+
private store;
|
|
123
|
+
private patterns;
|
|
124
|
+
private embeddings;
|
|
125
|
+
constructor(store?: WasmVectorStore);
|
|
126
|
+
/** Initialize the explorer (loads WASM backend if available) */
|
|
127
|
+
initialize(): Promise<void>;
|
|
128
|
+
/**
|
|
129
|
+
* Load patterns into the explorer
|
|
130
|
+
*
|
|
131
|
+
* Each pattern is embedded (using provided embedding or auto-generated)
|
|
132
|
+
* and indexed in the vector store for similarity search.
|
|
133
|
+
*/
|
|
134
|
+
loadPatterns(patterns: Pattern[]): void;
|
|
135
|
+
/**
|
|
136
|
+
* Search for patterns similar to a text query
|
|
137
|
+
*
|
|
138
|
+
* @param query - Natural language query string
|
|
139
|
+
* @param k - Number of results to return
|
|
140
|
+
* @returns Array of matched patterns ordered by similarity
|
|
141
|
+
*/
|
|
142
|
+
searchSimilar(query: string, k: number): Pattern[];
|
|
143
|
+
/**
|
|
144
|
+
* Cluster patterns into groups using K-Means
|
|
145
|
+
*
|
|
146
|
+
* @param numClusters - Number of clusters to create
|
|
147
|
+
* @returns Array of PatternCluster with centroid, members, and statistics
|
|
148
|
+
*/
|
|
149
|
+
clusterPatterns(numClusters: number): PatternCluster[];
|
|
150
|
+
/** Get distribution statistics per domain */
|
|
151
|
+
getDomainDistribution(): DomainStats[];
|
|
152
|
+
/** Get aggregated health dashboard data */
|
|
153
|
+
getHealthDashboardData(): DashboardData;
|
|
154
|
+
/** Get a pattern by id */
|
|
155
|
+
getPattern(id: string): Pattern | undefined;
|
|
156
|
+
/** Get total number of loaded patterns */
|
|
157
|
+
get patternCount(): number;
|
|
158
|
+
/** Clear all patterns and reset the explorer */
|
|
159
|
+
clear(): void;
|
|
160
|
+
private buildClusters;
|
|
161
|
+
private computeNormalizedCentroid;
|
|
162
|
+
private findDominantDomain;
|
|
163
|
+
private computeDomainStats;
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=pattern-explorer.d.ts.map
|
|
@@ -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
|