ruflo/docs/adr/ADR-002-WASM-CORE-PACKAGE.md
Status: Implemented Date: 2026-01-10 Updated: 2026-01-12 Author: Conveyor AI Team Deciders: Engineering, AI/ML Team Related: ADR-001-EXTENSION-ARCHITECTURE, ADR-004-RUVECTOR-POSTGRES-GCP-DEPLOYMENT
The Conveyor AI extension constellation requires high-performance AI algorithms that:
Key algorithms needed across extensions:
Implement a TypeScript-first approach with optional WASM optimization in the packages/shared-ai package. This provides:
packages/shared-ai/
+-- package.json
+-- tsconfig.json
+-- src/
| +-- index.ts # Main exports
| +-- ml/
| | +-- index.ts
| | +-- QLearning.ts # Q-Learning implementation
| +-- simulation/
| | +-- index.ts
| | +-- MonteCarlo.ts # Monte Carlo simulation
| +-- graph/
| | +-- index.ts
| | +-- MinCut.ts # MinCut/MaxFlow algorithms
| +-- vectors/
| +-- index.ts
| +-- VectorOps.ts # Vector operations
+-- wasm/ # Optional WASM binaries
+-- ruvector-attention.wasm
+-- ruvector-rvlite.wasm
// packages/shared-ai/src/index.ts
// Machine Learning
export { QLearning, QLearningConfig, QState, QAction } from './ml';
// Simulation
export { MonteCarlo, MonteCarloConfig, SimulationResult } from './simulation';
// Graph Algorithms
export { MinCut, MinCutConfig, GraphNode, GraphEdge } from './graph';
// Vector Operations
export { VectorOps, VectorConfig, SimilarityMetric } from './vectors';
Reinforcement learning for strategy optimization across domains.
// packages/shared-ai/src/ml/QLearning.ts
export interface QLearningConfig {
learningRate: number; // Alpha: 0.1 default
discountFactor: number; // Gamma: 0.95 default
explorationRate: number; // Epsilon: 0.1 default
minExploration: number; // Minimum epsilon: 0.01
decayRate: number; // Epsilon decay: 0.995
}
export interface QState {
key: string; // State identifier
features: number[]; // State feature vector
}
export interface QAction {
name: string; // Action identifier
parameters?: Record<string, unknown>;
}
export class QLearning {
private qTable: Map<string, Map<string, number>>;
private config: QLearningConfig;
constructor(config?: Partial<QLearningConfig>);
// Core Q-Learning methods
getQValue(state: QState, action: QAction): number;
updateQValue(state: QState, action: QAction, reward: number, nextState: QState): number;
selectAction(state: QState, actions: QAction[]): QAction;
getBestAction(state: QState, actions: QAction[]): QAction;
// Batch operations
batchUpdate(trajectories: Trajectory[]): void;
// Persistence
exportQTable(): QTableExport;
importQTable(data: QTableExport): void;
// Statistics
getStats(): QLearningStats;
}
// Example usage across extensions
const qLearning = new QLearning({
learningRate: 0.1,
discountFactor: 0.95,
explorationRate: 0.1
});
// Sales Pipeline: Deal stage progression
const dealState = { key: 'deal_50k_enterprise_cold', features: [50000, 1, 0.2] };
const action = qLearning.selectAction(dealState, [
{ name: 'aggressive_outreach' },
{ name: 'nurture_campaign' },
{ name: 'wait_and_monitor' }
]);
// Financial Ops: Budget allocation
const budgetState = { key: 'q1_marketing_over', features: [120, 100, 0.2] };
const budgetAction = qLearning.selectAction(budgetState, [
{ name: 'reallocate_to_sales' },
{ name: 'request_increase' },
{ name: 'reduce_spending' }
]);
Probability-based forecasting and risk analysis.
// packages/shared-ai/src/simulation/MonteCarlo.ts
export interface MonteCarloConfig {
iterations: number; // Default: 1000
confidenceLevel: number; // Default: 0.95
seed?: number; // Random seed for reproducibility
parallelism?: number; // Web Worker parallelism
}
export interface Distribution {
type: 'normal' | 'uniform' | 'triangular' | 'lognormal' | 'beta';
params: Record<string, number>;
}
export interface SimulationResult {
mean: number;
median: number;
stdDev: number;
percentiles: Record<number, number>;
distribution: number[];
confidenceInterval: [number, number];
}
export class MonteCarlo {
private config: MonteCarloConfig;
constructor(config?: Partial<MonteCarloConfig>);
// Single variable simulation
simulate(distribution: Distribution): SimulationResult;
// Multi-variable simulation
simulateMultiple(distributions: Distribution[]): SimulationResult[];
// Custom simulation function
runSimulation<T>(
generator: () => T,
aggregator: (results: T[]) => SimulationResult
): SimulationResult;
// Portfolio simulation (common use case)
simulatePortfolio(items: PortfolioItem[]): PortfolioSimulationResult;
}
// Example: Sales Pipeline forecasting
const monteCarlo = new MonteCarlo({ iterations: 10000 });
const dealOutcomes = monteCarlo.simulatePortfolio([
{
value: 100000,
probability: { type: 'beta', params: { alpha: 8, beta: 2 } }, // 80% likely
timing: { type: 'triangular', params: { min: 30, mode: 45, max: 90 } }
},
{
value: 250000,
probability: { type: 'beta', params: { alpha: 5, beta: 5 } }, // 50% likely
timing: { type: 'triangular', params: { min: 60, mode: 90, max: 180 } }
}
]);
console.log(`Expected Q1 Revenue: $${dealOutcomes.mean.toLocaleString()}`);
console.log(`95% CI: $${dealOutcomes.confidenceInterval[0]} - $${dealOutcomes.confidenceInterval[1]}`);
Network analysis, segmentation, and clustering.
// packages/shared-ai/src/graph/MinCut.ts
export interface GraphNode {
id: string;
label?: string;
attributes?: Record<string, unknown>;
}
export interface GraphEdge {
source: string;
target: string;
weight: number;
attributes?: Record<string, unknown>;
}
export interface MinCutConfig {
algorithm: 'karger' | 'stoer-wagner' | 'ford-fulkerson';
iterations?: number; // For randomized algorithms
}
export interface MinCutResult {
cutValue: number;
partition: [Set<string>, Set<string>];
cutEdges: GraphEdge[];
}
export class MinCut {
private nodes: Map<string, GraphNode>;
private edges: GraphEdge[];
private config: MinCutConfig;
constructor(config?: Partial<MinCutConfig>);
// Build graph
addNode(node: GraphNode): void;
addEdge(edge: GraphEdge): void;
buildFromAdjacencyList(adjacency: Record<string, Record<string, number>>): void;
// MinCut algorithms
findMinCut(): MinCutResult;
findMaxFlow(source: string, sink: string): number;
// Clustering
spectralClustering(k: number): Set<string>[];
communityDetection(): Set<string>[];
// Analysis
getShortestPath(source: string, target: string): string[];
getCentrality(): Map<string, number>;
}
// Example: Customer segmentation
const graph = new MinCut({ algorithm: 'stoer-wagner' });
// Build customer similarity graph
customers.forEach(c => graph.addNode({ id: c.id, attributes: c }));
similarities.forEach(s => graph.addEdge({
source: s.customer1,
target: s.customer2,
weight: s.similarityScore
}));
// Find natural customer segments
const segments = graph.communityDetection();
console.log(`Found ${segments.length} customer segments`);
Embedding operations and similarity search.
// packages/shared-ai/src/vectors/VectorOps.ts
export interface VectorConfig {
dimension: number; // Vector dimension
metric: SimilarityMetric; // Distance metric
normalize: boolean; // Auto-normalize vectors
}
export type SimilarityMetric = 'cosine' | 'euclidean' | 'dot' | 'manhattan';
export interface SearchResult {
id: string;
score: number;
vector: number[];
}
export class VectorOps {
private config: VectorConfig;
constructor(config: VectorConfig);
// Basic operations
similarity(a: number[], b: number[]): number;
distance(a: number[], b: number[]): number;
normalize(vector: number[]): number[];
add(a: number[], b: number[]): number[];
subtract(a: number[], b: number[]): number[];
scale(vector: number[], scalar: number): number[];
dot(a: number[], b: number[]): number;
// Batch operations
batchSimilarity(query: number[], vectors: number[][]): number[];
findTopK(query: number[], vectors: { id: string; vector: number[] }[], k: number): SearchResult[];
// Aggregation
mean(vectors: number[][]): number[];
centroid(vectors: number[][]): number[];
// Dimensionality reduction (simple PCA)
reduceDimension(vectors: number[][], targetDim: number): number[][];
}
// Example: Similar deal finder
const vectorOps = new VectorOps({
dimension: 128,
metric: 'cosine',
normalize: true
});
const dealEmbedding = embedDeal(currentDeal);
const similarDeals = vectorOps.findTopK(
dealEmbedding,
allDeals.map(d => ({ id: d.id, vector: d.embedding })),
5
);
console.log('Similar deals:', similarDeals.map(d => d.id));
When WASM is available, operations automatically accelerate:
// Automatic WASM detection and acceleration
import { VectorOps } from '@shared-ai';
const vectorOps = new VectorOps({ dimension: 768, metric: 'cosine' });
// If WASM available: Uses RuVector SIMD operations
// If WASM unavailable: Uses TypeScript implementation
const similarity = vectorOps.similarity(vec1, vec2);
| Operation | TypeScript | WASM (RuVector) | Improvement |
|---|---|---|---|
| Vector similarity (768d) | 0.5ms | 0.003ms | ~167x |
| Batch similarity (1000 vectors) | 500ms | 3ms | ~167x |
| HNSW search (1M vectors) | N/A | 1.5ms | N/A (WASM only) |
| Q-table lookup | 0.01ms | 0.01ms | 1x |
| Monte Carlo (10k iterations) | 150ms | 20ms | ~7.5x |
For heavy operations, leverage the RuVector PostgreSQL extension:
// Server-side vector search via RuVector PostgreSQL
// Performance: 150x-12,500x faster than standard pgvector
const similarCases = await postgres.query(`
SELECT entity_id, 1 - (embedding <=> $1) as similarity
FROM embeddings
WHERE entity_type = 'deal'
ORDER BY embedding <=> $1
LIMIT 10
`, [queryEmbedding]);
import { QLearning, MonteCarlo } from '@shared-ai';
// Deal stage optimization
const qLearning = new QLearning();
const bestAction = qLearning.selectAction(dealState, stageActions);
// Revenue forecasting
const monteCarlo = new MonteCarlo({ iterations: 5000 });
const forecast = monteCarlo.simulatePortfolio(pipeline);
import { MonteCarlo, VectorOps } from '@shared-ai';
// Cash flow simulation
const cashFlow = monteCarlo.simulate({
type: 'normal',
params: { mean: 500000, stdDev: 50000 }
});
// Similar transaction detection
const similar = vectorOps.findTopK(txnEmbedding, historicalTxns, 5);
import { QLearning, MinCut } from '@shared-ai';
// Compensation strategy optimization
const strategy = qLearning.selectAction(compState, compActions);
// Team structure analysis
const teams = minCut.communityDetection();
import { VectorOps, QLearning } from '@shared-ai';
// Similar contract clause search
const clauses = vectorOps.findTopK(clauseQuery, contractClauses, 10);
// Risk mitigation strategy
const action = qLearning.selectAction(riskState, mitigationActions);
import { QLearning, MonteCarlo, MinCut } from '@shared-ai';
// Churn prevention strategy
const action = qLearning.selectAction(healthState, interventionActions);
// Customer lifetime value simulation
const ltv = monteCarlo.simulate(ltvDistribution);
// Customer segmentation
const segments = minCut.spectralClustering(5);
import { MonteCarlo, VectorOps } from '@shared-ai';
// ARR forecasting
const arrForecast = monteCarlo.simulatePortfolio(revenueStreams);
// Cohort similarity analysis
const cohortSimilarity = vectorOps.batchSimilarity(targetCohort, allCohorts);
Document Version: 1.0 Last Updated: 2026-01-12