agentic-qe 3.8.11 → 3.8.13

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 (98) hide show
  1. package/.claude/skills/qe-code-intelligence/SKILL.md +29 -20
  2. package/.claude/skills/qe-code-intelligence/evals/qe-code-intelligence.yaml +3 -3
  3. package/.claude/skills/qe-quality-assessment/SKILL.md +1 -1
  4. package/.claude/skills/qe-test-generation/SKILL.md +1 -1
  5. package/.claude/skills/skills-manifest.json +1 -1
  6. package/CHANGELOG.md +45 -0
  7. package/README.md +9 -0
  8. package/assets/skills/qe-code-intelligence/SKILL.md +29 -20
  9. package/assets/skills/qe-code-intelligence/evals/qe-code-intelligence.yaml +3 -3
  10. package/assets/skills/qe-quality-assessment/SKILL.md +1 -1
  11. package/assets/skills/qe-test-generation/SKILL.md +1 -1
  12. package/dist/cli/bundle.js +1162 -1046
  13. package/dist/cli/commands/code.js +149 -11
  14. package/dist/cli/commands/init.js +3 -2
  15. package/dist/cli/commands/ruvector-commands.js +17 -0
  16. package/dist/cli/handlers/init-handler.d.ts +1 -0
  17. package/dist/cli/handlers/init-handler.js +15 -10
  18. package/dist/cli/utils/file-discovery.d.ts +1 -0
  19. package/dist/cli/utils/file-discovery.js +1 -1
  20. package/dist/domains/code-intelligence/coordinator-gnn.d.ts +21 -0
  21. package/dist/domains/code-intelligence/coordinator-gnn.js +102 -0
  22. package/dist/domains/contract-testing/coordinator.js +13 -0
  23. package/dist/domains/coverage-analysis/coordinator.js +5 -0
  24. package/dist/domains/defect-intelligence/coordinator.d.ts +1 -0
  25. package/dist/domains/defect-intelligence/coordinator.js +43 -0
  26. package/dist/domains/quality-assessment/coordinator.js +26 -0
  27. package/dist/domains/test-generation/coordinator.js +14 -0
  28. package/dist/init/orchestrator.js +1 -0
  29. package/dist/init/phases/08-mcp.js +4 -4
  30. package/dist/init/phases/phase-interface.d.ts +3 -1
  31. package/dist/integrations/agentic-flow/reasoning-bank/experience-replay.d.ts +11 -0
  32. package/dist/integrations/agentic-flow/reasoning-bank/experience-replay.js +44 -1
  33. package/dist/integrations/rl-suite/algorithms/eprop.d.ts +79 -0
  34. package/dist/integrations/rl-suite/algorithms/eprop.js +284 -0
  35. package/dist/integrations/rl-suite/algorithms/index.d.ts +2 -1
  36. package/dist/integrations/rl-suite/algorithms/index.js +2 -1
  37. package/dist/integrations/rl-suite/index.d.ts +2 -2
  38. package/dist/integrations/rl-suite/index.js +2 -2
  39. package/dist/integrations/rl-suite/interfaces.d.ts +3 -3
  40. package/dist/integrations/rl-suite/interfaces.js +1 -1
  41. package/dist/integrations/rl-suite/orchestrator.d.ts +2 -2
  42. package/dist/integrations/rl-suite/orchestrator.js +3 -2
  43. package/dist/integrations/rl-suite/reward-signals.d.ts +1 -1
  44. package/dist/integrations/rl-suite/reward-signals.js +1 -1
  45. package/dist/integrations/ruvector/coherence-gate-cohomology.d.ts +41 -0
  46. package/dist/integrations/ruvector/coherence-gate-cohomology.js +47 -0
  47. package/dist/integrations/ruvector/coherence-gate-core.d.ts +200 -0
  48. package/dist/integrations/ruvector/coherence-gate-core.js +294 -0
  49. package/dist/integrations/ruvector/coherence-gate-energy.d.ts +136 -0
  50. package/dist/integrations/ruvector/coherence-gate-energy.js +373 -0
  51. package/dist/integrations/ruvector/coherence-gate-vector.d.ts +38 -0
  52. package/dist/integrations/ruvector/coherence-gate-vector.js +76 -0
  53. package/dist/integrations/ruvector/coherence-gate.d.ts +10 -311
  54. package/dist/integrations/ruvector/coherence-gate.js +10 -652
  55. package/dist/integrations/ruvector/cold-tier-trainer.d.ts +103 -0
  56. package/dist/integrations/ruvector/cold-tier-trainer.js +377 -0
  57. package/dist/integrations/ruvector/cusum-detector.d.ts +70 -0
  58. package/dist/integrations/ruvector/cusum-detector.js +142 -0
  59. package/dist/integrations/ruvector/delta-tracker.d.ts +122 -0
  60. package/dist/integrations/ruvector/delta-tracker.js +311 -0
  61. package/dist/integrations/ruvector/domain-transfer.d.ts +79 -1
  62. package/dist/integrations/ruvector/domain-transfer.js +158 -2
  63. package/dist/integrations/ruvector/eprop-learner.d.ts +135 -0
  64. package/dist/integrations/ruvector/eprop-learner.js +351 -0
  65. package/dist/integrations/ruvector/feature-flags.d.ts +177 -0
  66. package/dist/integrations/ruvector/feature-flags.js +145 -0
  67. package/dist/integrations/ruvector/graphmae-encoder.d.ts +88 -0
  68. package/dist/integrations/ruvector/graphmae-encoder.js +360 -0
  69. package/dist/integrations/ruvector/hdc-fingerprint.d.ts +127 -0
  70. package/dist/integrations/ruvector/hdc-fingerprint.js +222 -0
  71. package/dist/integrations/ruvector/hopfield-memory.d.ts +97 -0
  72. package/dist/integrations/ruvector/hopfield-memory.js +238 -0
  73. package/dist/integrations/ruvector/index.d.ts +13 -2
  74. package/dist/integrations/ruvector/index.js +46 -2
  75. package/dist/integrations/ruvector/mincut-wrapper.d.ts +7 -0
  76. package/dist/integrations/ruvector/mincut-wrapper.js +54 -2
  77. package/dist/integrations/ruvector/reservoir-replay.d.ts +172 -0
  78. package/dist/integrations/ruvector/reservoir-replay.js +335 -0
  79. package/dist/integrations/ruvector/solver-adapter.d.ts +93 -0
  80. package/dist/integrations/ruvector/solver-adapter.js +299 -0
  81. package/dist/integrations/ruvector/sona-persistence.d.ts +33 -0
  82. package/dist/integrations/ruvector/sona-persistence.js +47 -0
  83. package/dist/integrations/ruvector/spectral-sparsifier.d.ts +154 -0
  84. package/dist/integrations/ruvector/spectral-sparsifier.js +389 -0
  85. package/dist/integrations/ruvector/temporal-causality.d.ts +63 -0
  86. package/dist/integrations/ruvector/temporal-causality.js +317 -0
  87. package/dist/learning/pattern-promotion.d.ts +63 -0
  88. package/dist/learning/pattern-promotion.js +235 -1
  89. package/dist/learning/pattern-store.d.ts +2 -0
  90. package/dist/learning/pattern-store.js +187 -1
  91. package/dist/learning/sqlite-persistence.d.ts +2 -0
  92. package/dist/learning/sqlite-persistence.js +4 -0
  93. package/dist/mcp/bundle.js +506 -427
  94. package/dist/shared/utils/index.d.ts +1 -0
  95. package/dist/shared/utils/index.js +1 -0
  96. package/dist/shared/utils/xorshift128.d.ts +24 -0
  97. package/dist/shared/utils/xorshift128.js +50 -0
  98. package/package.json +1 -1
@@ -0,0 +1,127 @@
1
+ /**
2
+ * R1: Hyperdimensional Computing Pattern Fingerprinting
3
+ *
4
+ * 10,000-bit binary hypervectors with XOR binding for O(1) compositional
5
+ * pattern fingerprinting. TypeScript fallback implementation.
6
+ *
7
+ * When WASM is available (@ruvector/hdc-wasm), delegates to native SIMD-optimized ops.
8
+ * Without WASM, uses TypeScript Uint8Array bit operations.
9
+ *
10
+ * Key properties:
11
+ * - Deterministic: same input always produces the same fingerprint
12
+ * - Compositional: XOR binding combines multiple concepts into a single vector
13
+ * - Associative: bind(A, bind(B, C)) === bind(bind(A, B), C)
14
+ * - Distance-preserving: Hamming distance ≈ dimensions/2 for unrelated patterns
15
+ *
16
+ * @module integrations/ruvector/hdc-fingerprint
17
+ */
18
+ /**
19
+ * Configuration for the HDC fingerprinter
20
+ */
21
+ export interface HdcConfig {
22
+ /** Number of bits in each hypervector. Default: 10000 */
23
+ dimensions: number;
24
+ /** Seed for deterministic fingerprint generation */
25
+ seed?: number;
26
+ }
27
+ /**
28
+ * A pattern fingerprint represented as a packed binary hypervector
29
+ */
30
+ export interface PatternFingerprint {
31
+ /** Packed bits: dimensions/8 bytes (1250 bytes for 10K dimensions) */
32
+ vector: Uint8Array;
33
+ /** Number of bits (dimensions) in the hypervector */
34
+ dimensions: number;
35
+ /** Hex hash for quick equality check */
36
+ hash: string;
37
+ }
38
+ /**
39
+ * Input data for fingerprinting a pattern
40
+ */
41
+ export interface PatternInput {
42
+ id: string;
43
+ domain: string;
44
+ type: string;
45
+ content?: string;
46
+ }
47
+ /**
48
+ * Hyperdimensional Computing fingerprinter for QE patterns.
49
+ *
50
+ * Generates deterministic binary hypervectors from pattern metadata,
51
+ * supports XOR-based compositional binding, and provides Hamming
52
+ * distance / similarity metrics.
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * const hdc = new HdcFingerprinter();
57
+ * const fp = hdc.fingerprint({ id: 'p1', domain: 'security', type: 'xss' });
58
+ * console.log(fp.dimensions); // 10000
59
+ * console.log(fp.vector.length); // 1250
60
+ * ```
61
+ */
62
+ export declare class HdcFingerprinter {
63
+ private readonly dimensions;
64
+ private readonly baseSeed;
65
+ constructor(config?: Partial<HdcConfig>);
66
+ /**
67
+ * Generate a deterministic fingerprint from pattern data.
68
+ *
69
+ * The fingerprint is seeded from a composite key of id + domain + type
70
+ * (and optionally content), ensuring identical inputs always produce
71
+ * identical outputs.
72
+ */
73
+ fingerprint(pattern: PatternInput): PatternFingerprint;
74
+ /**
75
+ * XOR-based compositional binding.
76
+ *
77
+ * Combines two hypervectors into a single vector representing their
78
+ * conjunction. XOR binding is:
79
+ * - Associative: bind(A, bind(B, C)) === bind(bind(A, B), C)
80
+ * - Commutative: bind(A, B) === bind(B, A)
81
+ * - Self-inverse: bind(A, A) === zero vector
82
+ *
83
+ * @param a First packed-bit vector
84
+ * @param b Second packed-bit vector
85
+ * @returns XOR of a and b (same length)
86
+ * @throws If vectors have different lengths
87
+ */
88
+ compositionalBind(a: Uint8Array, b: Uint8Array): Uint8Array;
89
+ /**
90
+ * Hamming distance between two packed-bit vectors.
91
+ *
92
+ * Counts the number of differing bits. For unrelated (random) vectors
93
+ * the expected distance is approximately dimensions / 2.
94
+ *
95
+ * @returns Number of differing bits (0 = identical, ~dimensions/2 = random)
96
+ * @throws If vectors have different lengths
97
+ */
98
+ hammingDistance(a: Uint8Array, b: Uint8Array): number;
99
+ /**
100
+ * Normalized similarity between two packed-bit vectors.
101
+ *
102
+ * @returns Value in [0, 1] where 1.0 = identical, 0.5 = random, 0.0 = opposite
103
+ */
104
+ similarity(a: Uint8Array, b: Uint8Array): number;
105
+ /**
106
+ * Batch fingerprint multiple patterns.
107
+ * Results match calling fingerprint() individually on each pattern.
108
+ */
109
+ batchFingerprint(patterns: PatternInput[]): PatternFingerprint[];
110
+ /**
111
+ * Generate a packed-bit vector from a seed using xorshift128 PRNG.
112
+ * Each bit is set with 50% probability, producing approximately
113
+ * dimensions/2 set bits on average.
114
+ */
115
+ private generateVector;
116
+ }
117
+ /**
118
+ * Create an HdcFingerprinter with the given configuration.
119
+ *
120
+ * @example
121
+ * ```typescript
122
+ * const hdc = createHdcFingerprinter({ dimensions: 10000 });
123
+ * const fp = hdc.fingerprint({ id: 'p1', domain: 'api', type: 'flaky' });
124
+ * ```
125
+ */
126
+ export declare function createHdcFingerprinter(config?: Partial<HdcConfig>): HdcFingerprinter;
127
+ //# sourceMappingURL=hdc-fingerprint.d.ts.map
@@ -0,0 +1,222 @@
1
+ /**
2
+ * R1: Hyperdimensional Computing Pattern Fingerprinting
3
+ *
4
+ * 10,000-bit binary hypervectors with XOR binding for O(1) compositional
5
+ * pattern fingerprinting. TypeScript fallback implementation.
6
+ *
7
+ * When WASM is available (@ruvector/hdc-wasm), delegates to native SIMD-optimized ops.
8
+ * Without WASM, uses TypeScript Uint8Array bit operations.
9
+ *
10
+ * Key properties:
11
+ * - Deterministic: same input always produces the same fingerprint
12
+ * - Compositional: XOR binding combines multiple concepts into a single vector
13
+ * - Associative: bind(A, bind(B, C)) === bind(bind(A, B), C)
14
+ * - Distance-preserving: Hamming distance ≈ dimensions/2 for unrelated patterns
15
+ *
16
+ * @module integrations/ruvector/hdc-fingerprint
17
+ */
18
+ import { Xorshift128 } from '../../shared/utils/xorshift128.js';
19
+ // ============================================================================
20
+ // Constants
21
+ // ============================================================================
22
+ const DEFAULT_DIMENSIONS = 10000;
23
+ const DEFAULT_SEED = 0x811c9dc5; // FNV-1a offset basis
24
+ // ============================================================================
25
+ // Internal: FNV-1a Hash
26
+ // ============================================================================
27
+ /**
28
+ * FNV-1a 32-bit hash for deterministic seeding.
29
+ * Produces well-distributed values from arbitrary string input.
30
+ */
31
+ function fnv1a(input) {
32
+ let hash = 0x811c9dc5; // FNV offset basis
33
+ for (let i = 0; i < input.length; i++) {
34
+ hash ^= input.charCodeAt(i);
35
+ hash = Math.imul(hash, 0x01000193); // FNV prime
36
+ }
37
+ return hash >>> 0; // Ensure unsigned 32-bit
38
+ }
39
+ // ============================================================================
40
+ // Internal: Popcount
41
+ // ============================================================================
42
+ /** Lookup table for popcount of a single byte (0-255) */
43
+ const POPCOUNT_TABLE = new Uint8Array(256);
44
+ for (let i = 0; i < 256; i++) {
45
+ let count = 0;
46
+ let n = i;
47
+ while (n) {
48
+ count++;
49
+ n &= n - 1; // Brian Kernighan's bit trick
50
+ }
51
+ POPCOUNT_TABLE[i] = count;
52
+ }
53
+ // ============================================================================
54
+ // Internal: Hex encoding
55
+ // ============================================================================
56
+ const HEX_CHARS = '0123456789abcdef';
57
+ /**
58
+ * Produce a hex string from the first 16 bytes of a Uint8Array
59
+ * (32-char hex digest, sufficient for quick equality checks).
60
+ */
61
+ function hexDigest(bytes) {
62
+ const len = Math.min(bytes.length, 16);
63
+ let hex = '';
64
+ for (let i = 0; i < len; i++) {
65
+ const b = bytes[i];
66
+ hex += HEX_CHARS[b >> 4] + HEX_CHARS[b & 0x0f];
67
+ }
68
+ return hex;
69
+ }
70
+ // ============================================================================
71
+ // HdcFingerprinter
72
+ // ============================================================================
73
+ /**
74
+ * Hyperdimensional Computing fingerprinter for QE patterns.
75
+ *
76
+ * Generates deterministic binary hypervectors from pattern metadata,
77
+ * supports XOR-based compositional binding, and provides Hamming
78
+ * distance / similarity metrics.
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * const hdc = new HdcFingerprinter();
83
+ * const fp = hdc.fingerprint({ id: 'p1', domain: 'security', type: 'xss' });
84
+ * console.log(fp.dimensions); // 10000
85
+ * console.log(fp.vector.length); // 1250
86
+ * ```
87
+ */
88
+ export class HdcFingerprinter {
89
+ dimensions;
90
+ baseSeed;
91
+ constructor(config) {
92
+ this.dimensions = config?.dimensions ?? DEFAULT_DIMENSIONS;
93
+ this.baseSeed = config?.seed ?? DEFAULT_SEED;
94
+ if (this.dimensions <= 0) {
95
+ throw new Error(`HDC dimensions must be positive, got ${this.dimensions}`);
96
+ }
97
+ }
98
+ // --------------------------------------------------------------------------
99
+ // Public API
100
+ // --------------------------------------------------------------------------
101
+ /**
102
+ * Generate a deterministic fingerprint from pattern data.
103
+ *
104
+ * The fingerprint is seeded from a composite key of id + domain + type
105
+ * (and optionally content), ensuring identical inputs always produce
106
+ * identical outputs.
107
+ */
108
+ fingerprint(pattern) {
109
+ const seedStr = `${pattern.id}|${pattern.domain}|${pattern.type}|${pattern.content ?? ''}`;
110
+ const seed = fnv1a(seedStr) ^ this.baseSeed;
111
+ const vector = this.generateVector(seed);
112
+ return {
113
+ vector,
114
+ dimensions: this.dimensions,
115
+ hash: hexDigest(vector),
116
+ };
117
+ }
118
+ /**
119
+ * XOR-based compositional binding.
120
+ *
121
+ * Combines two hypervectors into a single vector representing their
122
+ * conjunction. XOR binding is:
123
+ * - Associative: bind(A, bind(B, C)) === bind(bind(A, B), C)
124
+ * - Commutative: bind(A, B) === bind(B, A)
125
+ * - Self-inverse: bind(A, A) === zero vector
126
+ *
127
+ * @param a First packed-bit vector
128
+ * @param b Second packed-bit vector
129
+ * @returns XOR of a and b (same length)
130
+ * @throws If vectors have different lengths
131
+ */
132
+ compositionalBind(a, b) {
133
+ if (a.length !== b.length) {
134
+ throw new Error(`Cannot bind vectors of different lengths: ${a.length} vs ${b.length}`);
135
+ }
136
+ const result = new Uint8Array(a.length);
137
+ for (let i = 0; i < a.length; i++) {
138
+ result[i] = a[i] ^ b[i];
139
+ }
140
+ return result;
141
+ }
142
+ /**
143
+ * Hamming distance between two packed-bit vectors.
144
+ *
145
+ * Counts the number of differing bits. For unrelated (random) vectors
146
+ * the expected distance is approximately dimensions / 2.
147
+ *
148
+ * @returns Number of differing bits (0 = identical, ~dimensions/2 = random)
149
+ * @throws If vectors have different lengths
150
+ */
151
+ hammingDistance(a, b) {
152
+ if (a.length !== b.length) {
153
+ throw new Error(`Cannot compute Hamming distance for vectors of different lengths: ${a.length} vs ${b.length}`);
154
+ }
155
+ let distance = 0;
156
+ for (let i = 0; i < a.length; i++) {
157
+ distance += POPCOUNT_TABLE[a[i] ^ b[i]];
158
+ }
159
+ return distance;
160
+ }
161
+ /**
162
+ * Normalized similarity between two packed-bit vectors.
163
+ *
164
+ * @returns Value in [0, 1] where 1.0 = identical, 0.5 = random, 0.0 = opposite
165
+ */
166
+ similarity(a, b) {
167
+ const dist = this.hammingDistance(a, b);
168
+ return 1 - dist / this.dimensions;
169
+ }
170
+ /**
171
+ * Batch fingerprint multiple patterns.
172
+ * Results match calling fingerprint() individually on each pattern.
173
+ */
174
+ batchFingerprint(patterns) {
175
+ return patterns.map((p) => this.fingerprint(p));
176
+ }
177
+ // --------------------------------------------------------------------------
178
+ // Internal
179
+ // --------------------------------------------------------------------------
180
+ /**
181
+ * Generate a packed-bit vector from a seed using xorshift128 PRNG.
182
+ * Each bit is set with 50% probability, producing approximately
183
+ * dimensions/2 set bits on average.
184
+ */
185
+ generateVector(seed) {
186
+ const byteLen = Math.ceil(this.dimensions / 8);
187
+ const vector = new Uint8Array(byteLen);
188
+ const rng = new Xorshift128(seed);
189
+ // Fill 4 bytes at a time from each 32-bit random value
190
+ let byteIdx = 0;
191
+ while (byteIdx < byteLen) {
192
+ const rand = rng.next();
193
+ const remaining = byteLen - byteIdx;
194
+ const count = remaining < 4 ? remaining : 4;
195
+ for (let j = 0; j < count; j++) {
196
+ vector[byteIdx++] = (rand >>> (j * 8)) & 0xff;
197
+ }
198
+ }
199
+ // Mask unused trailing bits in the last byte
200
+ const trailingBits = this.dimensions % 8;
201
+ if (trailingBits > 0) {
202
+ vector[byteLen - 1] &= (1 << trailingBits) - 1;
203
+ }
204
+ return vector;
205
+ }
206
+ }
207
+ // ============================================================================
208
+ // Factory Functions
209
+ // ============================================================================
210
+ /**
211
+ * Create an HdcFingerprinter with the given configuration.
212
+ *
213
+ * @example
214
+ * ```typescript
215
+ * const hdc = createHdcFingerprinter({ dimensions: 10000 });
216
+ * const fp = hdc.fingerprint({ id: 'p1', domain: 'api', type: 'flaky' });
217
+ * ```
218
+ */
219
+ export function createHdcFingerprinter(config) {
220
+ return new HdcFingerprinter(config);
221
+ }
222
+ //# sourceMappingURL=hdc-fingerprint.js.map
@@ -0,0 +1,97 @@
1
+ /**
2
+ * R5: Modern Hopfield Networks — Associative Pattern Memory
3
+ *
4
+ * Exponential-capacity content-addressable memory for exact pattern recall.
5
+ * Complements HNSW approximate nearest neighbor with exact retrieval:
6
+ * - HNSW: "What patterns are similar?" (approximate)
7
+ * - Hopfield: "Did we see exactly this pattern before?" (exact)
8
+ *
9
+ * Based on Ramsauer et al. 2020 "Hopfield Networks is All You Need".
10
+ * TypeScript implementation; WASM upgrade path via @ruvector/hopfield-wasm.
11
+ *
12
+ * @module integrations/ruvector/hopfield-memory
13
+ */
14
+ /**
15
+ * Configuration for the Hopfield associative memory
16
+ */
17
+ export interface HopfieldConfig {
18
+ /** Pattern dimension. Default: 128 */
19
+ dimension: number;
20
+ /** Inverse temperature beta controlling sharpness of retrieval. Higher = more exact. Default: 8.0 */
21
+ beta: number;
22
+ /** Maximum number of stored patterns. Default: 10000 */
23
+ maxPatterns: number;
24
+ }
25
+ /**
26
+ * A pattern stored in Hopfield memory with associated metadata
27
+ */
28
+ export interface StoredPattern {
29
+ /** The pattern vector */
30
+ pattern: Float32Array;
31
+ /** Associated metadata */
32
+ metadata: Record<string, unknown>;
33
+ /** Timestamp of storage */
34
+ storedAt: number;
35
+ }
36
+ /**
37
+ * Result of a Hopfield recall operation
38
+ */
39
+ export interface RecallResult {
40
+ /** Retrieved pattern (closest stored pattern) */
41
+ pattern: Float32Array;
42
+ /** Metadata associated with the retrieved pattern */
43
+ metadata: Record<string, unknown>;
44
+ /** Hopfield energy of the retrieval (lower = more confident) */
45
+ energy: number;
46
+ /** Cosine similarity between query and retrieved pattern */
47
+ similarity: number;
48
+ }
49
+ /**
50
+ * Modern Hopfield Network for associative pattern memory.
51
+ *
52
+ * Update rule: new_state = X * softmax(beta * X^T * query).
53
+ * High beta (default 8.0) makes softmax approach argmax for exact recall.
54
+ */
55
+ export declare class HopfieldMemory {
56
+ private readonly dimension;
57
+ private readonly beta;
58
+ private readonly maxPatterns;
59
+ private readonly patterns;
60
+ constructor(config?: Partial<HopfieldConfig>);
61
+ /** Store a pattern. L2-normalizes, validates dimension; evicts oldest if at capacity. */
62
+ store(pattern: Float32Array, metadata?: Record<string, unknown>): void;
63
+ /**
64
+ * Recall the closest stored pattern via softmax(beta * X^T * query).
65
+ * Returns null if empty.
66
+ *
67
+ * Note: With normalized patterns and beta=8, softmax strongly concentrates
68
+ * on the nearest pattern (argmax), making this equivalent to a single
69
+ * Hopfield fixed-point iteration that converges immediately (Ramsauer 2020,
70
+ * Theorem 3). Full iterative convergence is unnecessary at high beta.
71
+ */
72
+ recall(query: Float32Array): RecallResult | null;
73
+ /** Recall multiple queries in batch. */
74
+ batchRecall(queries: Float32Array[]): (RecallResult | null)[];
75
+ /** Get the number of stored patterns. */
76
+ getPatternCount(): number;
77
+ /** Remove all stored patterns. */
78
+ clear(): void;
79
+ /**
80
+ * Hopfield energy: E = -lse(beta, X^T * state) + 0.5 * ||state||^2.
81
+ * Lower energy = closer to a stored pattern. State is L2-normalized first.
82
+ */
83
+ getEnergy(state: Float32Array): number;
84
+ /** Numerically stable softmax: subtract max before exp to avoid overflow. */
85
+ private softmax;
86
+ /** Dot product of two Float32Arrays. */
87
+ private dotProduct;
88
+ /** Cosine similarity in [-1, 1]. */
89
+ private cosineSimilarity;
90
+ /** L2 normalization. Returns unit-length copy (or zero vector if input is zero). */
91
+ private normalize;
92
+ /** Assert that the useHopfieldMemory feature flag is enabled. */
93
+ private assertEnabled;
94
+ }
95
+ /** Create a HopfieldMemory with the given configuration. */
96
+ export declare function createHopfieldMemory(config?: Partial<HopfieldConfig>): HopfieldMemory;
97
+ //# sourceMappingURL=hopfield-memory.d.ts.map
@@ -0,0 +1,238 @@
1
+ /**
2
+ * R5: Modern Hopfield Networks — Associative Pattern Memory
3
+ *
4
+ * Exponential-capacity content-addressable memory for exact pattern recall.
5
+ * Complements HNSW approximate nearest neighbor with exact retrieval:
6
+ * - HNSW: "What patterns are similar?" (approximate)
7
+ * - Hopfield: "Did we see exactly this pattern before?" (exact)
8
+ *
9
+ * Based on Ramsauer et al. 2020 "Hopfield Networks is All You Need".
10
+ * TypeScript implementation; WASM upgrade path via @ruvector/hopfield-wasm.
11
+ *
12
+ * @module integrations/ruvector/hopfield-memory
13
+ */
14
+ import { getRuVectorFeatureFlags } from './feature-flags.js';
15
+ // ============================================================================
16
+ // Constants
17
+ // ============================================================================
18
+ const DEFAULT_DIMENSION = 128;
19
+ const DEFAULT_BETA = 8.0;
20
+ const DEFAULT_MAX_PATTERNS = 10000;
21
+ // ============================================================================
22
+ // HopfieldMemory
23
+ // ============================================================================
24
+ /**
25
+ * Modern Hopfield Network for associative pattern memory.
26
+ *
27
+ * Update rule: new_state = X * softmax(beta * X^T * query).
28
+ * High beta (default 8.0) makes softmax approach argmax for exact recall.
29
+ */
30
+ export class HopfieldMemory {
31
+ dimension;
32
+ beta;
33
+ maxPatterns;
34
+ patterns;
35
+ constructor(config) {
36
+ this.dimension = config?.dimension ?? DEFAULT_DIMENSION;
37
+ this.beta = config?.beta ?? DEFAULT_BETA;
38
+ this.maxPatterns = config?.maxPatterns ?? DEFAULT_MAX_PATTERNS;
39
+ this.patterns = [];
40
+ if (this.dimension <= 0) {
41
+ throw new Error(`Hopfield dimension must be positive, got ${this.dimension}`);
42
+ }
43
+ if (this.beta <= 0) {
44
+ throw new Error(`Hopfield beta must be positive, got ${this.beta}`);
45
+ }
46
+ if (this.maxPatterns <= 0) {
47
+ throw new Error(`Hopfield maxPatterns must be positive, got ${this.maxPatterns}`);
48
+ }
49
+ }
50
+ // --------------------------------------------------------------------------
51
+ // Public API
52
+ // --------------------------------------------------------------------------
53
+ /** Store a pattern. L2-normalizes, validates dimension; evicts oldest if at capacity. */
54
+ store(pattern, metadata) {
55
+ this.assertEnabled();
56
+ if (pattern.length !== this.dimension) {
57
+ throw new Error(`Pattern dimension mismatch: expected ${this.dimension}, got ${pattern.length}`);
58
+ }
59
+ // Reject zero-magnitude vectors (would be unretrievable after normalization)
60
+ const mag = this.dotProduct(pattern, pattern);
61
+ if (mag === 0) {
62
+ throw new Error('Cannot store zero-magnitude pattern in Hopfield memory');
63
+ }
64
+ // L2-normalize for consistent softmax attention weights
65
+ const normalized = this.normalize(pattern);
66
+ // Evict oldest if at capacity
67
+ if (this.patterns.length >= this.maxPatterns) {
68
+ this.patterns.shift();
69
+ }
70
+ this.patterns.push({
71
+ pattern: normalized,
72
+ metadata: metadata ?? {},
73
+ storedAt: Date.now(),
74
+ });
75
+ }
76
+ /**
77
+ * Recall the closest stored pattern via softmax(beta * X^T * query).
78
+ * Returns null if empty.
79
+ *
80
+ * Note: With normalized patterns and beta=8, softmax strongly concentrates
81
+ * on the nearest pattern (argmax), making this equivalent to a single
82
+ * Hopfield fixed-point iteration that converges immediately (Ramsauer 2020,
83
+ * Theorem 3). Full iterative convergence is unnecessary at high beta.
84
+ */
85
+ recall(query) {
86
+ this.assertEnabled();
87
+ if (query.length !== this.dimension) {
88
+ throw new Error(`Query dimension mismatch: expected ${this.dimension}, got ${query.length}`);
89
+ }
90
+ if (this.patterns.length === 0) {
91
+ return null;
92
+ }
93
+ // L2-normalize query for magnitude-invariant comparison
94
+ const normalizedQuery = this.normalize(query);
95
+ // Compute logits: beta * X^T * normalizedQuery
96
+ const logits = new Float32Array(this.patterns.length);
97
+ for (let i = 0; i < this.patterns.length; i++) {
98
+ logits[i] = this.beta * this.dotProduct(this.patterns[i].pattern, normalizedQuery);
99
+ }
100
+ // Softmax to get attention weights
101
+ const weights = this.softmax(logits);
102
+ // Find the pattern with the highest attention weight
103
+ let bestIdx = 0;
104
+ let bestWeight = weights[0];
105
+ for (let i = 1; i < weights.length; i++) {
106
+ if (weights[i] > bestWeight) {
107
+ bestWeight = weights[i];
108
+ bestIdx = i;
109
+ }
110
+ }
111
+ const matched = this.patterns[bestIdx];
112
+ const energy = this.getEnergy(normalizedQuery);
113
+ const similarity = this.cosineSimilarity(normalizedQuery, matched.pattern);
114
+ return {
115
+ pattern: new Float32Array(matched.pattern),
116
+ metadata: { ...matched.metadata },
117
+ energy,
118
+ similarity,
119
+ };
120
+ }
121
+ /** Recall multiple queries in batch. */
122
+ batchRecall(queries) {
123
+ this.assertEnabled();
124
+ return queries.map((q) => this.recall(q));
125
+ }
126
+ /** Get the number of stored patterns. */
127
+ getPatternCount() {
128
+ return this.patterns.length;
129
+ }
130
+ /** Remove all stored patterns. */
131
+ clear() {
132
+ this.patterns.length = 0;
133
+ }
134
+ /**
135
+ * Hopfield energy: E = -lse(beta, X^T * state) + 0.5 * ||state||^2.
136
+ * Lower energy = closer to a stored pattern. State is L2-normalized first.
137
+ */
138
+ getEnergy(state) {
139
+ if (state.length !== this.dimension) {
140
+ throw new Error(`State dimension mismatch: expected ${this.dimension}, got ${state.length}`);
141
+ }
142
+ // L2-normalize state for consistent energy computation
143
+ const normalizedState = this.normalize(state);
144
+ if (this.patterns.length === 0) {
145
+ // Only the quadratic term remains; normalized state has ||s||^2 = 1
146
+ return 0.5 * this.dotProduct(normalizedState, normalizedState);
147
+ }
148
+ // Compute z_i = X^T * normalizedState (dot products with each stored pattern)
149
+ const z = new Float32Array(this.patterns.length);
150
+ for (let i = 0; i < this.patterns.length; i++) {
151
+ z[i] = this.dotProduct(this.patterns[i].pattern, normalizedState);
152
+ }
153
+ // Numerically stable lse: (1/beta) * (max + log(sum(exp(beta*z_i - max))))
154
+ const scaledZ = new Float32Array(this.patterns.length);
155
+ let maxVal = -Infinity;
156
+ for (let i = 0; i < this.patterns.length; i++) {
157
+ scaledZ[i] = this.beta * z[i];
158
+ if (scaledZ[i] > maxVal)
159
+ maxVal = scaledZ[i];
160
+ }
161
+ let sumExp = 0;
162
+ for (let i = 0; i < this.patterns.length; i++) {
163
+ sumExp += Math.exp(scaledZ[i] - maxVal);
164
+ }
165
+ const lse = (1 / this.beta) * (maxVal + Math.log(sumExp));
166
+ // E = -lse + 0.5 * ||normalizedState||^2
167
+ const normSq = this.dotProduct(normalizedState, normalizedState);
168
+ return -lse + 0.5 * normSq;
169
+ }
170
+ // --------------------------------------------------------------------------
171
+ // Internal Helpers
172
+ // --------------------------------------------------------------------------
173
+ /** Numerically stable softmax: subtract max before exp to avoid overflow. */
174
+ softmax(logits) {
175
+ const result = new Float32Array(logits.length);
176
+ // Find max for numerical stability
177
+ let maxVal = -Infinity;
178
+ for (let i = 0; i < logits.length; i++) {
179
+ if (logits[i] > maxVal)
180
+ maxVal = logits[i];
181
+ }
182
+ // Compute exp(x - max) and sum
183
+ let sum = 0;
184
+ for (let i = 0; i < logits.length; i++) {
185
+ result[i] = Math.exp(logits[i] - maxVal);
186
+ sum += result[i];
187
+ }
188
+ // Normalize
189
+ if (sum > 0) {
190
+ for (let i = 0; i < result.length; i++) {
191
+ result[i] /= sum;
192
+ }
193
+ }
194
+ return result;
195
+ }
196
+ /** Dot product of two Float32Arrays. */
197
+ dotProduct(a, b) {
198
+ let sum = 0;
199
+ for (let i = 0; i < a.length; i++) {
200
+ sum += a[i] * b[i];
201
+ }
202
+ return sum;
203
+ }
204
+ /** Cosine similarity in [-1, 1]. */
205
+ cosineSimilarity(a, b) {
206
+ const dot = this.dotProduct(a, b);
207
+ const normA = Math.sqrt(this.dotProduct(a, a));
208
+ const normB = Math.sqrt(this.dotProduct(b, b));
209
+ if (normA === 0 || normB === 0)
210
+ return 0;
211
+ return dot / (normA * normB);
212
+ }
213
+ /** L2 normalization. Returns unit-length copy (or zero vector if input is zero). */
214
+ normalize(v) {
215
+ const norm = Math.sqrt(this.dotProduct(v, v));
216
+ const result = new Float32Array(v.length);
217
+ if (norm > 0) {
218
+ for (let i = 0; i < v.length; i++) {
219
+ result[i] = v[i] / norm;
220
+ }
221
+ }
222
+ return result;
223
+ }
224
+ /** Assert that the useHopfieldMemory feature flag is enabled. */
225
+ assertEnabled() {
226
+ if (!getRuVectorFeatureFlags().useHopfieldMemory) {
227
+ throw new Error('Hopfield memory is disabled (useHopfieldMemory feature flag is false)');
228
+ }
229
+ }
230
+ }
231
+ // ============================================================================
232
+ // Factory Functions
233
+ // ============================================================================
234
+ /** Create a HopfieldMemory with the given configuration. */
235
+ export function createHopfieldMemory(config) {
236
+ return new HopfieldMemory(config);
237
+ }
238
+ //# sourceMappingURL=hopfield-memory.js.map