hippo-memory 0.36.0 → 0.37.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 (199) hide show
  1. package/README.md +16 -0
  2. package/dist/api.d.ts +20 -0
  3. package/dist/api.d.ts.map +1 -1
  4. package/dist/api.js +23 -3
  5. package/dist/api.js.map +1 -1
  6. package/dist/benchmarks/e1.3/incident-recall-eval.js +74 -0
  7. package/dist/benchmarks/e1.3/incident-recall-eval.js.map +1 -0
  8. package/dist/benchmarks/e1.3/scenarios.json +2587 -0
  9. package/dist/benchmarks/e1.3/slack-1000-event-smoke.js +102 -0
  10. package/dist/benchmarks/e1.3/slack-1000-event-smoke.js.map +1 -0
  11. package/dist/cli.js +82 -0
  12. package/dist/cli.js.map +1 -1
  13. package/dist/connectors/slack/backfill.d.ts +42 -0
  14. package/dist/connectors/slack/backfill.d.ts.map +1 -0
  15. package/dist/connectors/slack/backfill.js +76 -0
  16. package/dist/connectors/slack/backfill.js.map +1 -0
  17. package/dist/connectors/slack/deletion.d.ts +14 -0
  18. package/dist/connectors/slack/deletion.d.ts.map +1 -0
  19. package/dist/connectors/slack/deletion.js +46 -0
  20. package/dist/connectors/slack/deletion.js.map +1 -0
  21. package/dist/connectors/slack/dlq.d.ts +21 -0
  22. package/dist/connectors/slack/dlq.d.ts.map +1 -0
  23. package/dist/connectors/slack/dlq.js +23 -0
  24. package/dist/connectors/slack/dlq.js.map +1 -0
  25. package/dist/connectors/slack/idempotency.d.ts +5 -0
  26. package/dist/connectors/slack/idempotency.d.ts.map +1 -0
  27. package/dist/connectors/slack/idempotency.js +13 -0
  28. package/dist/connectors/slack/idempotency.js.map +1 -0
  29. package/dist/connectors/slack/ingest.d.ts +27 -0
  30. package/dist/connectors/slack/ingest.d.ts.map +1 -0
  31. package/dist/connectors/slack/ingest.js +48 -0
  32. package/dist/connectors/slack/ingest.js.map +1 -0
  33. package/dist/connectors/slack/ratelimit.d.ts +9 -0
  34. package/dist/connectors/slack/ratelimit.d.ts.map +1 -0
  35. package/dist/connectors/slack/ratelimit.js +18 -0
  36. package/dist/connectors/slack/ratelimit.js.map +1 -0
  37. package/dist/connectors/slack/scope.d.ts +16 -0
  38. package/dist/connectors/slack/scope.d.ts.map +1 -0
  39. package/dist/connectors/slack/scope.js +13 -0
  40. package/dist/connectors/slack/scope.js.map +1 -0
  41. package/dist/connectors/slack/signature.d.ts +12 -0
  42. package/dist/connectors/slack/signature.d.ts.map +1 -0
  43. package/dist/connectors/slack/signature.js +20 -0
  44. package/dist/connectors/slack/signature.js.map +1 -0
  45. package/dist/connectors/slack/tenant-routing.d.ts +13 -0
  46. package/dist/connectors/slack/tenant-routing.d.ts.map +1 -0
  47. package/dist/connectors/slack/tenant-routing.js +17 -0
  48. package/dist/connectors/slack/tenant-routing.js.map +1 -0
  49. package/dist/connectors/slack/transform.d.ts +20 -0
  50. package/dist/connectors/slack/transform.d.ts.map +1 -0
  51. package/dist/connectors/slack/transform.js +31 -0
  52. package/dist/connectors/slack/transform.js.map +1 -0
  53. package/dist/connectors/slack/types.d.ts +35 -0
  54. package/dist/connectors/slack/types.d.ts.map +1 -0
  55. package/dist/connectors/slack/types.js +23 -0
  56. package/dist/connectors/slack/types.js.map +1 -0
  57. package/dist/connectors/slack/web-client.d.ts +12 -0
  58. package/dist/connectors/slack/web-client.d.ts.map +1 -0
  59. package/dist/connectors/slack/web-client.js +43 -0
  60. package/dist/connectors/slack/web-client.js.map +1 -0
  61. package/dist/db.d.ts.map +1 -1
  62. package/dist/db.js +46 -1
  63. package/dist/db.js.map +1 -1
  64. package/dist/importers.js +3 -3
  65. package/dist/importers.js.map +1 -1
  66. package/dist/mcp/server.js +1 -1
  67. package/dist/server.d.ts.map +1 -1
  68. package/dist/server.js +174 -2
  69. package/dist/server.js.map +1 -1
  70. package/dist/src/ambient.js +147 -0
  71. package/dist/src/ambient.js.map +1 -0
  72. package/dist/src/api.js +343 -0
  73. package/dist/src/api.js.map +1 -0
  74. package/dist/src/audit.js +152 -0
  75. package/dist/src/audit.js.map +1 -0
  76. package/dist/src/auth.js +65 -0
  77. package/dist/src/auth.js.map +1 -0
  78. package/dist/src/autolearn.js +143 -0
  79. package/dist/src/autolearn.js.map +1 -0
  80. package/dist/src/capture.js +512 -0
  81. package/dist/src/capture.js.map +1 -0
  82. package/dist/src/cli.js +4971 -0
  83. package/dist/src/cli.js.map +1 -0
  84. package/dist/src/client.js +181 -0
  85. package/dist/src/client.js.map +1 -0
  86. package/dist/src/config.js +108 -0
  87. package/dist/src/config.js.map +1 -0
  88. package/dist/src/connectors/slack/backfill.js +76 -0
  89. package/dist/src/connectors/slack/backfill.js.map +1 -0
  90. package/dist/src/connectors/slack/deletion.js +46 -0
  91. package/dist/src/connectors/slack/deletion.js.map +1 -0
  92. package/dist/src/connectors/slack/dlq.js +23 -0
  93. package/dist/src/connectors/slack/dlq.js.map +1 -0
  94. package/dist/src/connectors/slack/idempotency.js +13 -0
  95. package/dist/src/connectors/slack/idempotency.js.map +1 -0
  96. package/dist/src/connectors/slack/ingest.js +48 -0
  97. package/dist/src/connectors/slack/ingest.js.map +1 -0
  98. package/dist/src/connectors/slack/ratelimit.js +18 -0
  99. package/dist/src/connectors/slack/ratelimit.js.map +1 -0
  100. package/dist/src/connectors/slack/scope.js +13 -0
  101. package/dist/src/connectors/slack/scope.js.map +1 -0
  102. package/dist/src/connectors/slack/signature.js +20 -0
  103. package/dist/src/connectors/slack/signature.js.map +1 -0
  104. package/dist/src/connectors/slack/tenant-routing.js +17 -0
  105. package/dist/src/connectors/slack/tenant-routing.js.map +1 -0
  106. package/dist/src/connectors/slack/transform.js +31 -0
  107. package/dist/src/connectors/slack/transform.js.map +1 -0
  108. package/dist/src/connectors/slack/types.js +23 -0
  109. package/dist/src/connectors/slack/types.js.map +1 -0
  110. package/dist/src/connectors/slack/web-client.js +43 -0
  111. package/dist/src/connectors/slack/web-client.js.map +1 -0
  112. package/dist/src/consolidate.js +517 -0
  113. package/dist/src/consolidate.js.map +1 -0
  114. package/dist/src/dag.js +104 -0
  115. package/dist/src/dag.js.map +1 -0
  116. package/dist/src/dashboard.js +409 -0
  117. package/dist/src/dashboard.js.map +1 -0
  118. package/dist/src/db.js +584 -0
  119. package/dist/src/db.js.map +1 -0
  120. package/dist/src/embeddings.js +344 -0
  121. package/dist/src/embeddings.js.map +1 -0
  122. package/dist/src/eval-suite.js +289 -0
  123. package/dist/src/eval-suite.js.map +1 -0
  124. package/dist/src/eval.js +187 -0
  125. package/dist/src/eval.js.map +1 -0
  126. package/dist/src/extract.js +87 -0
  127. package/dist/src/extract.js.map +1 -0
  128. package/dist/src/handoff.js +30 -0
  129. package/dist/src/handoff.js.map +1 -0
  130. package/dist/src/hooks.js +582 -0
  131. package/dist/src/hooks.js.map +1 -0
  132. package/dist/src/importers.js +399 -0
  133. package/dist/src/importers.js.map +1 -0
  134. package/dist/src/index.js +25 -0
  135. package/dist/src/index.js.map +1 -0
  136. package/dist/src/invalidation.js +94 -0
  137. package/dist/src/invalidation.js.map +1 -0
  138. package/dist/src/mcp/framing.js +45 -0
  139. package/dist/src/mcp/framing.js.map +1 -0
  140. package/dist/src/mcp/server.js +510 -0
  141. package/dist/src/mcp/server.js.map +1 -0
  142. package/dist/src/memory.js +280 -0
  143. package/dist/src/memory.js.map +1 -0
  144. package/dist/src/multihop.js +32 -0
  145. package/dist/src/multihop.js.map +1 -0
  146. package/dist/src/path-context.js +32 -0
  147. package/dist/src/path-context.js.map +1 -0
  148. package/dist/src/physics-config.js +26 -0
  149. package/dist/src/physics-config.js.map +1 -0
  150. package/dist/src/physics-state.js +163 -0
  151. package/dist/src/physics-state.js.map +1 -0
  152. package/dist/src/physics.js +361 -0
  153. package/dist/src/physics.js.map +1 -0
  154. package/dist/src/postinstall.js +68 -0
  155. package/dist/src/postinstall.js.map +1 -0
  156. package/dist/src/raw-archive.js +72 -0
  157. package/dist/src/raw-archive.js.map +1 -0
  158. package/dist/src/refine-llm.js +147 -0
  159. package/dist/src/refine-llm.js.map +1 -0
  160. package/dist/src/replay.js +117 -0
  161. package/dist/src/replay.js.map +1 -0
  162. package/dist/src/salience.js +74 -0
  163. package/dist/src/salience.js.map +1 -0
  164. package/dist/src/scheduler.js +67 -0
  165. package/dist/src/scheduler.js.map +1 -0
  166. package/dist/src/scope.js +35 -0
  167. package/dist/src/scope.js.map +1 -0
  168. package/dist/src/search.js +801 -0
  169. package/dist/src/search.js.map +1 -0
  170. package/dist/src/server-detect.js +70 -0
  171. package/dist/src/server-detect.js.map +1 -0
  172. package/dist/src/server.js +784 -0
  173. package/dist/src/server.js.map +1 -0
  174. package/dist/src/shared.js +309 -0
  175. package/dist/src/shared.js.map +1 -0
  176. package/dist/src/sso.js +22 -0
  177. package/dist/src/sso.js.map +1 -0
  178. package/dist/src/store.js +1390 -0
  179. package/dist/src/store.js.map +1 -0
  180. package/dist/src/tenant.js +17 -0
  181. package/dist/src/tenant.js.map +1 -0
  182. package/dist/src/trace.js +64 -0
  183. package/dist/src/trace.js.map +1 -0
  184. package/dist/src/working-memory.js +149 -0
  185. package/dist/src/working-memory.js.map +1 -0
  186. package/dist/src/yaml.js +98 -0
  187. package/dist/src/yaml.js.map +1 -0
  188. package/dist/store.d.ts +9 -1
  189. package/dist/store.d.ts.map +1 -1
  190. package/dist/store.js +30 -2
  191. package/dist/store.js.map +1 -1
  192. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  193. package/extensions/openclaw-plugin/package.json +1 -1
  194. package/openclaw.plugin.json +1 -1
  195. package/package.json +2 -2
  196. package/dist/import.d.ts +0 -31
  197. package/dist/import.d.ts.map +0 -1
  198. package/dist/import.js +0 -307
  199. package/dist/import.js.map +0 -1
@@ -0,0 +1,361 @@
1
+ /**
2
+ * Memory-as-Physics engine for Hippo.
3
+ *
4
+ * Pure math module: forces, Velocity Verlet integration, physics-based scoring,
5
+ * and cluster amplification. No I/O — all state is passed in and returned.
6
+ *
7
+ * Memories are particles on the unit hypersphere in embedding space (384-dim).
8
+ * Forces act on them: query gravity (retrieval), inter-memory attraction,
9
+ * conflict repulsion, and drag (consolidation). Nearby high-scoring memories
10
+ * amplify each other via constructive interference.
11
+ */
12
+ // ---------------------------------------------------------------------------
13
+ // Vector math (hot path — kept inline for performance)
14
+ // ---------------------------------------------------------------------------
15
+ export function vecDot(a, b) {
16
+ let sum = 0;
17
+ for (let i = 0; i < a.length; i++)
18
+ sum += a[i] * b[i];
19
+ return sum;
20
+ }
21
+ export function vecNorm(v) {
22
+ return Math.sqrt(vecDot(v, v));
23
+ }
24
+ export function vecScale(v, s) {
25
+ const out = new Array(v.length);
26
+ for (let i = 0; i < v.length; i++)
27
+ out[i] = v[i] * s;
28
+ return out;
29
+ }
30
+ export function vecAdd(a, b) {
31
+ const out = new Array(a.length);
32
+ for (let i = 0; i < a.length; i++)
33
+ out[i] = a[i] + b[i];
34
+ return out;
35
+ }
36
+ export function vecSub(a, b) {
37
+ const out = new Array(a.length);
38
+ for (let i = 0; i < a.length; i++)
39
+ out[i] = a[i] - b[i];
40
+ return out;
41
+ }
42
+ export function vecZero(dim) {
43
+ return new Array(dim).fill(0);
44
+ }
45
+ /** Normalize to unit length. Returns zero vector if magnitude < epsilon. */
46
+ export function vecNormalize(v) {
47
+ const mag = vecNorm(v);
48
+ if (mag < 1e-10)
49
+ return vecZero(v.length);
50
+ return vecScale(v, 1 / mag);
51
+ }
52
+ /** Clamp vector magnitude to maxMag. */
53
+ export function vecClampMagnitude(v, maxMag) {
54
+ const mag = vecNorm(v);
55
+ if (mag <= maxMag)
56
+ return v;
57
+ return vecScale(v, maxMag / mag);
58
+ }
59
+ /** Cosine similarity between two vectors. */
60
+ function cosine(a, b) {
61
+ if (a.length === 0 || b.length === 0 || a.length !== b.length)
62
+ return 0;
63
+ const dot = vecDot(a, b);
64
+ const na = vecNorm(a);
65
+ const nb = vecNorm(b);
66
+ if (na < 1e-10 || nb < 1e-10)
67
+ return 0;
68
+ return Math.min(1, Math.max(-1, dot / (na * nb)));
69
+ }
70
+ // ---------------------------------------------------------------------------
71
+ // Property derivation from memory attributes
72
+ // ---------------------------------------------------------------------------
73
+ const CHARGE_MAP = {
74
+ neutral: 0,
75
+ positive: 0.3,
76
+ negative: -0.5,
77
+ critical: -1.0,
78
+ };
79
+ export function computeMass(strength, retrievalCount) {
80
+ return Math.max(0.01, strength * (1 + 0.1 * Math.log2(retrievalCount + 1)));
81
+ }
82
+ export function computeCharge(valence) {
83
+ return CHARGE_MAP[valence] ?? 0;
84
+ }
85
+ export function computeTemperature(ageDays, temperatureDecay) {
86
+ return 1 / (ageDays * temperatureDecay + 1);
87
+ }
88
+ // ---------------------------------------------------------------------------
89
+ // Force computations
90
+ // ---------------------------------------------------------------------------
91
+ /**
92
+ * F1: Query gravity (retrieval-time, virtual — does not update position).
93
+ * Returns scalar force magnitude for ranking.
94
+ *
95
+ * F_query(i) = G_Q * mass(i) * max(0, cosine(pos_i, query))^2
96
+ */
97
+ export function queryGravityMagnitude(particle, queryEmbedding, G_query) {
98
+ const cos = cosine(particle.position, queryEmbedding);
99
+ return G_query * particle.mass * Math.pow(Math.max(0, cos), 2);
100
+ }
101
+ /**
102
+ * Momentum bonus: how aligned is the particle's velocity with the query direction?
103
+ * Returns a value in [0, 1].
104
+ */
105
+ export function velocityAlignmentBonus(particle, queryEmbedding) {
106
+ if (particle.velocity.length === 0 || particle.velocity.length !== queryEmbedding.length)
107
+ return 0;
108
+ const velMag = vecNorm(particle.velocity);
109
+ const qNorm = vecNorm(queryEmbedding);
110
+ if (velMag < 1e-10 || qNorm < 1e-10)
111
+ return 0;
112
+ const alignment = vecDot(particle.velocity, queryEmbedding) / (velMag * qNorm);
113
+ return Math.max(0, alignment);
114
+ }
115
+ /**
116
+ * F2: Inter-memory attraction force vector (consolidation-time).
117
+ * Attractive force from particle j on particle i.
118
+ *
119
+ * F_attract(i,j) = G_M * m_i * m_j * max(0, cosine(i,j))^3 * direction(j→i in embedding space)
120
+ *
121
+ * Direction is computed as the component of (pos_j - pos_i) that lies tangent to the
122
+ * unit sphere at pos_i (since we normalize positions back to the sphere after integration).
123
+ */
124
+ export function attractionForce(pi, pj, G_memory) {
125
+ const cos = cosine(pi.position, pj.position);
126
+ if (cos <= 0)
127
+ return vecZero(pi.position.length);
128
+ const magnitude = G_memory * pi.mass * pj.mass * Math.pow(cos, 3);
129
+ // Direction: from i toward j (tangent projection handled by normalization after integration)
130
+ const direction = vecNormalize(vecSub(pj.position, pi.position));
131
+ return vecScale(direction, magnitude);
132
+ }
133
+ /**
134
+ * F3: Conflict repulsion force vector (consolidation-time).
135
+ * Repulsive force pushing i away from j.
136
+ *
137
+ * F_repel(i,j) = K_R * m_i * m_j / max(0.01, cosine_distance(i,j))^2
138
+ * where cosine_distance = 1 - cosine_similarity
139
+ */
140
+ export function repulsionForce(pi, pj, K_repulsion) {
141
+ const cos = cosine(pi.position, pj.position);
142
+ const dist = Math.max(0.01, 1 - cos);
143
+ const magnitude = K_repulsion * pi.mass * pj.mass / (dist * dist);
144
+ // Direction: away from j
145
+ const direction = vecNormalize(vecSub(pi.position, pj.position));
146
+ return vecScale(direction, magnitude);
147
+ }
148
+ /**
149
+ * F4: Drag force vector (consolidation-time).
150
+ * F_drag(i) = -drag * velocity(i) / max(1, effective_half_life(i))
151
+ *
152
+ * effectiveHalfLife should be passed in from the memory's current half_life_days.
153
+ */
154
+ export function dragForce(particle, drag, effectiveHalfLife) {
155
+ const damping = drag / Math.max(1, effectiveHalfLife);
156
+ return vecScale(particle.velocity, -damping);
157
+ }
158
+ /**
159
+ * Compute net force on particle i from all other particles + drag.
160
+ */
161
+ function computeNetForce(i, particles, ctx) {
162
+ const pi = particles[i];
163
+ const dim = pi.position.length;
164
+ let net = vecZero(dim);
165
+ const conflicts = ctx.conflictPairs.get(pi.memoryId);
166
+ for (let j = 0; j < particles.length; j++) {
167
+ if (i === j)
168
+ continue;
169
+ const pj = particles[j];
170
+ // Attraction (all pairs)
171
+ const fa = attractionForce(pi, pj, ctx.config.G_memory);
172
+ net = vecAdd(net, fa);
173
+ // Repulsion (conflict pairs only)
174
+ if (conflicts?.has(pj.memoryId)) {
175
+ const fr = repulsionForce(pi, pj, ctx.config.K_repulsion);
176
+ net = vecAdd(net, fr);
177
+ }
178
+ }
179
+ // Drag
180
+ const fd = dragForce(pi, ctx.config.drag, ctx.halfLives.get(pi.memoryId) ?? 7);
181
+ net = vecAdd(net, fd);
182
+ return net;
183
+ }
184
+ /**
185
+ * Run one Velocity Verlet integration step for all particles.
186
+ * Mutates particles in place for performance.
187
+ */
188
+ function verletStep(particles, accelerations, ctx) {
189
+ const dt = ctx.config.dt;
190
+ const maxVel = ctx.config.max_velocity;
191
+ for (let i = 0; i < particles.length; i++) {
192
+ const p = particles[i];
193
+ // Position update: pos += vel*dt + 0.5*accel*dt^2
194
+ const velDt = vecScale(p.velocity, dt);
195
+ const accelDt2 = vecScale(accelerations[i], 0.5 * dt * dt);
196
+ p.position = vecAdd(vecAdd(p.position, velDt), accelDt2);
197
+ }
198
+ // Compute new accelerations
199
+ const newAccelerations = [];
200
+ for (let i = 0; i < particles.length; i++) {
201
+ const force = computeNetForce(i, particles, ctx);
202
+ newAccelerations.push(vecScale(force, 1 / Math.max(0.01, particles[i].mass)));
203
+ }
204
+ // Velocity update: vel += 0.5*(accel_old + accel_new)*dt
205
+ for (let i = 0; i < particles.length; i++) {
206
+ const p = particles[i];
207
+ const avgAccel = vecScale(vecAdd(accelerations[i], newAccelerations[i]), 0.5);
208
+ p.velocity = vecAdd(p.velocity, vecScale(avgAccel, dt));
209
+ // Stability: clamp velocity and normalize position to unit sphere
210
+ p.velocity = vecClampMagnitude(p.velocity, maxVel);
211
+ p.position = vecNormalize(p.position);
212
+ }
213
+ // Update accelerations for next step
214
+ for (let i = 0; i < accelerations.length; i++) {
215
+ accelerations[i] = newAccelerations[i];
216
+ }
217
+ }
218
+ /**
219
+ * Run the full physics simulation for one sleep cycle.
220
+ * Mutates particles in place. Returns simulation statistics.
221
+ */
222
+ export function simulate(particles, ctx) {
223
+ if (particles.length === 0) {
224
+ return {
225
+ particleCount: 0,
226
+ avgVelocityMagnitude: 0,
227
+ maxVelocityMagnitude: 0,
228
+ energy: { kinetic: 0, potential: 0, total: 0 },
229
+ substepsRun: 0,
230
+ };
231
+ }
232
+ // Initial accelerations
233
+ const accelerations = particles.map((_, i) => {
234
+ const force = computeNetForce(i, particles, ctx);
235
+ return vecScale(force, 1 / Math.max(0.01, particles[i].mass));
236
+ });
237
+ // Run substeps
238
+ for (let step = 0; step < ctx.config.substeps; step++) {
239
+ verletStep(particles, accelerations, ctx);
240
+ }
241
+ // Update timestamps
242
+ const now = new Date().toISOString();
243
+ for (const p of particles) {
244
+ p.lastSimulation = now;
245
+ }
246
+ // Compute stats
247
+ let sumVelMag = 0;
248
+ let maxVelMag = 0;
249
+ for (const p of particles) {
250
+ const mag = vecNorm(p.velocity);
251
+ sumVelMag += mag;
252
+ if (mag > maxVelMag)
253
+ maxVelMag = mag;
254
+ }
255
+ const energy = computeSystemEnergy(particles, ctx.config.G_memory);
256
+ return {
257
+ particleCount: particles.length,
258
+ avgVelocityMagnitude: sumVelMag / particles.length,
259
+ maxVelocityMagnitude: maxVelMag,
260
+ energy,
261
+ substepsRun: ctx.config.substeps,
262
+ };
263
+ }
264
+ // ---------------------------------------------------------------------------
265
+ // System energy (health monitoring)
266
+ // ---------------------------------------------------------------------------
267
+ export function computeSystemEnergy(particles, G_memory) {
268
+ let kinetic = 0;
269
+ let potential = 0;
270
+ for (const p of particles) {
271
+ const velMag = vecNorm(p.velocity);
272
+ kinetic += 0.5 * p.mass * velMag * velMag;
273
+ }
274
+ for (let i = 0; i < particles.length; i++) {
275
+ for (let j = i + 1; j < particles.length; j++) {
276
+ const cos = cosine(particles[i].position, particles[j].position);
277
+ potential -= G_memory * particles[i].mass * particles[j].mass * Math.max(0, cos);
278
+ }
279
+ }
280
+ return { kinetic, potential, total: kinetic + potential };
281
+ }
282
+ // ---------------------------------------------------------------------------
283
+ // Physics-based scoring (retrieval-time)
284
+ // ---------------------------------------------------------------------------
285
+ /**
286
+ * Score all particles against a query embedding using physics-based ranking.
287
+ * Does NOT modify particle positions (virtual force computation).
288
+ */
289
+ export function physicsScore(particles, queryEmbedding, config) {
290
+ if (particles.length === 0 || queryEmbedding.length === 0)
291
+ return [];
292
+ // Pass 1: compute base scores
293
+ const results = particles.map((p) => {
294
+ const gravity = queryGravityMagnitude(p, queryEmbedding, config.G_query);
295
+ const momentum = config.momentum_weight * velocityAlignmentBonus(p, queryEmbedding);
296
+ return {
297
+ memoryId: p.memoryId,
298
+ baseScore: gravity + momentum,
299
+ clusterAmplification: 1.0,
300
+ finalScore: gravity + momentum,
301
+ };
302
+ });
303
+ // Sort by base score for top-K selection
304
+ results.sort((a, b) => b.baseScore - a.baseScore);
305
+ // Pass 2: cluster amplification on top K
306
+ applyClusterAmplification(results, particles, config);
307
+ // Re-sort by final score
308
+ results.sort((a, b) => b.finalScore - a.finalScore);
309
+ return results;
310
+ }
311
+ /**
312
+ * Cluster amplification: nearby high-scoring memories reinforce each other.
313
+ * Mutates results in place.
314
+ */
315
+ function applyClusterAmplification(results, particles, config) {
316
+ const topK = Math.min(config.cluster_top_k, results.length);
317
+ if (topK < 2)
318
+ return;
319
+ // Build a quick lookup from memoryId to particle
320
+ const particleMap = new Map();
321
+ for (const p of particles)
322
+ particleMap.set(p.memoryId, p);
323
+ const top = results.slice(0, topK);
324
+ for (let i = 0; i < top.length; i++) {
325
+ const pi = particleMap.get(top[i].memoryId);
326
+ if (!pi)
327
+ continue;
328
+ let clusterSignal = 0;
329
+ for (let j = 0; j < top.length; j++) {
330
+ if (i === j)
331
+ continue;
332
+ const pj = particleMap.get(top[j].memoryId);
333
+ if (!pj)
334
+ continue;
335
+ const proximity = cosine(pi.position, pj.position);
336
+ if (proximity > config.cluster_threshold) {
337
+ clusterSignal += top[j].baseScore * proximity;
338
+ }
339
+ }
340
+ const amplification = 1 + Math.tanh(clusterSignal * config.interference_gain);
341
+ top[i].clusterAmplification = amplification;
342
+ top[i].finalScore = top[i].baseScore * amplification;
343
+ }
344
+ }
345
+ // ---------------------------------------------------------------------------
346
+ // Outcome feedback (micro-nudge)
347
+ // ---------------------------------------------------------------------------
348
+ /**
349
+ * Nudge a particle's position toward (good outcome) or away from (bad outcome)
350
+ * the query embedding. Respects temperature: new memories respond more.
351
+ * Mutates particle in place.
352
+ */
353
+ export function applyOutcomeFeedback(particle, queryEmbedding, good, feedbackAlpha) {
354
+ if (particle.position.length === 0 || particle.position.length !== queryEmbedding.length)
355
+ return;
356
+ const sign = good ? 1 : -1;
357
+ const direction = vecSub(queryEmbedding, particle.position);
358
+ const nudge = vecScale(direction, sign * feedbackAlpha * particle.temperature);
359
+ particle.position = vecNormalize(vecAdd(particle.position, nudge));
360
+ }
361
+ //# sourceMappingURL=physics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"physics.js","sourceRoot":"","sources":["../../src/physics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAwCH,8EAA8E;AAC9E,uDAAuD;AACvD,8EAA8E;AAE9E,MAAM,UAAU,MAAM,CAAC,CAAW,EAAE,CAAW;IAC7C,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACtD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,CAAW;IACjC,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,CAAW,EAAE,CAAS;IAC7C,MAAM,GAAG,GAAG,IAAI,KAAK,CAAS,CAAC,CAAC,MAAM,CAAC,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACrD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,CAAW,EAAE,CAAW;IAC7C,MAAM,GAAG,GAAG,IAAI,KAAK,CAAS,CAAC,CAAC,MAAM,CAAC,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,CAAW,EAAE,CAAW;IAC7C,MAAM,GAAG,GAAG,IAAI,KAAK,CAAS,CAAC,CAAC,MAAM,CAAC,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,OAAO,IAAI,KAAK,CAAS,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACxC,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,YAAY,CAAC,CAAW;IACtC,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACvB,IAAI,GAAG,GAAG,KAAK;QAAE,OAAO,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC1C,OAAO,QAAQ,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,iBAAiB,CAAC,CAAW,EAAE,MAAc;IAC3D,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACvB,IAAI,GAAG,IAAI,MAAM;QAAE,OAAO,CAAC,CAAC;IAC5B,OAAO,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC,CAAC;AACnC,CAAC;AAED,6CAA6C;AAC7C,SAAS,MAAM,CAAC,CAAW,EAAE,CAAW;IACtC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,CAAC,CAAC;IACxE,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACzB,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACtB,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACtB,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,GAAG,KAAK;QAAE,OAAO,CAAC,CAAC;IACvC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,8EAA8E;AAC9E,6CAA6C;AAC7C,8EAA8E;AAE9E,MAAM,UAAU,GAAqC;IACnD,OAAO,EAAE,CAAC;IACV,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,CAAC,GAAG;IACd,QAAQ,EAAE,CAAC,GAAG;CACf,CAAC;AAEF,MAAM,UAAU,WAAW,CAAC,QAAgB,EAAE,cAAsB;IAClE,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,GAAG,CAAC,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAyB;IACrD,OAAO,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAe,EAAE,gBAAwB;IAC1E,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,gBAAgB,GAAG,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAAyB,EACzB,cAAwB,EACxB,OAAe;IAEf,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IACtD,OAAO,OAAO,GAAG,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;AACjE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACpC,QAAyB,EACzB,cAAwB;IAExB,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,KAAK,cAAc,CAAC,MAAM;QAAE,OAAO,CAAC,CAAC;IACnG,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACtC,IAAI,MAAM,GAAG,KAAK,IAAI,KAAK,GAAG,KAAK;QAAE,OAAO,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC;IAC/E,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;AAChC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAC7B,EAAmB,EACnB,EAAmB,EACnB,QAAgB;IAEhB,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,OAAO,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEjD,MAAM,SAAS,GAAG,QAAQ,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IAClE,6FAA6F;IAC7F,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IACjE,OAAO,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AACxC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,EAAmB,EACnB,EAAmB,EACnB,WAAmB;IAEnB,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC;IACrC,MAAM,SAAS,GAAG,WAAW,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,IAAI,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAClE,yBAAyB;IACzB,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IACjE,OAAO,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AACxC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CACvB,QAAyB,EACzB,IAAY,EACZ,iBAAyB;IAEzB,MAAM,OAAO,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC;IACtD,OAAO,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC;AAC/C,CAAC;AAcD;;GAEG;AACH,SAAS,eAAe,CACtB,CAAS,EACT,SAA4B,EAC5B,GAAiB;IAEjB,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IACxB,MAAM,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;IAC/B,IAAI,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAEvB,MAAM,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;IAErD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,IAAI,CAAC,KAAK,CAAC;YAAE,SAAS;QACtB,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAExB,yBAAyB;QACzB,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACxD,GAAG,GAAG,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAEtB,kCAAkC;QAClC,IAAI,SAAS,EAAE,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChC,MAAM,EAAE,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YAC1D,GAAG,GAAG,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,OAAO;IACP,MAAM,EAAE,GAAG,SAAS,CAAC,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/E,GAAG,GAAG,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAEtB,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;GAGG;AACH,SAAS,UAAU,CACjB,SAA4B,EAC5B,aAAyB,EACzB,GAAiB;IAEjB,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;IACzB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC;IAEvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAEvB,kDAAkD;QAClD,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACvC,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;QAC3D,CAAC,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC3D,CAAC;IAED,4BAA4B;IAC5B,MAAM,gBAAgB,GAAe,EAAE,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,eAAe,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;QACjD,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChF,CAAC;IAED,yDAAyD;IACzD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QACvB,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC9E,CAAC,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;QAExD,kEAAkE;QAClE,CAAC,CAAC,QAAQ,GAAG,iBAAiB,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACnD,CAAC,CAAC,QAAQ,GAAG,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC;IAED,qCAAqC;IACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9C,aAAa,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CACtB,SAA4B,EAC5B,GAAiB;IAEjB,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO;YACL,aAAa,EAAE,CAAC;YAChB,oBAAoB,EAAE,CAAC;YACvB,oBAAoB,EAAE,CAAC;YACvB,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;YAC9C,WAAW,EAAE,CAAC;SACf,CAAC;IACJ,CAAC;IAED,wBAAwB;IACxB,MAAM,aAAa,GAAe,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACvD,MAAM,KAAK,GAAG,eAAe,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;QACjD,OAAO,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,eAAe;IACf,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC;QACtD,UAAU,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,CAAC,CAAC;IAC5C,CAAC;IAED,oBAAoB;IACpB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,CAAC,CAAC,cAAc,GAAG,GAAG,CAAC;IACzB,CAAC;IAED,gBAAgB;IAChB,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAChC,SAAS,IAAI,GAAG,CAAC;QACjB,IAAI,GAAG,GAAG,SAAS;YAAE,SAAS,GAAG,GAAG,CAAC;IACvC,CAAC;IAED,MAAM,MAAM,GAAG,mBAAmB,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAEnE,OAAO;QACL,aAAa,EAAE,SAAS,CAAC,MAAM;QAC/B,oBAAoB,EAAE,SAAS,GAAG,SAAS,CAAC,MAAM;QAClD,oBAAoB,EAAE,SAAS;QAC/B,MAAM;QACN,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ;KACjC,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,oCAAoC;AACpC,8EAA8E;AAE9E,MAAM,UAAU,mBAAmB,CACjC,SAA4B,EAC5B,QAAgB;IAEhB,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QACnC,OAAO,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IAC5C,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC9C,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YACjE,SAAS,IAAI,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,GAAG,SAAS,EAAE,CAAC;AAC5D,CAAC;AAED,8EAA8E;AAC9E,yCAAyC;AACzC,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,SAA4B,EAC5B,cAAwB,EACxB,MAAqB;IAErB,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAErE,8BAA8B;IAC9B,MAAM,OAAO,GAA0B,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACzD,MAAM,OAAO,GAAG,qBAAqB,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QACzE,MAAM,QAAQ,GAAG,MAAM,CAAC,eAAe,GAAG,sBAAsB,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;QACpF,OAAO;YACL,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,SAAS,EAAE,OAAO,GAAG,QAAQ;YAC7B,oBAAoB,EAAE,GAAG;YACzB,UAAU,EAAE,OAAO,GAAG,QAAQ;SAC/B,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,yCAAyC;IACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;IAElD,yCAAyC;IACzC,yBAAyB,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IAEtD,yBAAyB;IACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;IAEpD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,SAAS,yBAAyB,CAChC,OAA8B,EAC9B,SAA4B,EAC5B,MAAqB;IAErB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5D,IAAI,IAAI,GAAG,CAAC;QAAE,OAAO;IAErB,iDAAiD;IACjD,MAAM,WAAW,GAAG,IAAI,GAAG,EAA2B,CAAC;IACvD,KAAK,MAAM,CAAC,IAAI,SAAS;QAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAE1D,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAEnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC5C,IAAI,CAAC,EAAE;YAAE,SAAS;QAElB,IAAI,aAAa,GAAG,CAAC,CAAC;QACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACpC,IAAI,CAAC,KAAK,CAAC;gBAAE,SAAS;YACtB,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YAC5C,IAAI,CAAC,EAAE;gBAAE,SAAS;YAElB,MAAM,SAAS,GAAG,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC;YACnD,IAAI,SAAS,GAAG,MAAM,CAAC,iBAAiB,EAAE,CAAC;gBACzC,aAAa,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,SAAS,CAAC;YAChD,CAAC;QACH,CAAC;QAED,MAAM,aAAa,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;QAC9E,GAAG,CAAC,CAAC,CAAC,CAAC,oBAAoB,GAAG,aAAa,CAAC;QAC5C,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,aAAa,CAAC;IACvD,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,iCAAiC;AACjC,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,QAAyB,EACzB,cAAwB,EACxB,IAAa,EACb,aAAqB;IAErB,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,KAAK,cAAc,CAAC,MAAM;QAAE,OAAO;IACjG,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,SAAS,GAAG,MAAM,CAAC,cAAc,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC5D,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,EAAE,IAAI,GAAG,aAAa,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC/E,QAAQ,CAAC,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;AACrE,CAAC"}
@@ -0,0 +1,68 @@
1
+ import * as fs from 'node:fs';
2
+ import * as os from 'node:os';
3
+ import * as path from 'node:path';
4
+ import { ensureCodexWrapperInstalled } from './hooks.js';
5
+ function main() {
6
+ if (process.env.HIPPO_SKIP_POSTINSTALL === '1')
7
+ return;
8
+ try {
9
+ ensureCodexWrapperInstalled();
10
+ }
11
+ catch {
12
+ // Never fail package install because auto-integration could not be applied.
13
+ }
14
+ try {
15
+ printClaudeCodeNudge();
16
+ }
17
+ catch {
18
+ // Never fail package install because the install hint could not be printed.
19
+ }
20
+ }
21
+ /**
22
+ * Read-only nudge: if Claude Code is detected on the machine and the Hippo
23
+ * UserPromptSubmit hook is NOT yet installed, print a short message pointing
24
+ * the user at `hippo init`. No config writes. Silent otherwise.
25
+ *
26
+ * We avoid aggressively auto-patching ~/.claude/settings.json from a package
27
+ * postinstall — that's surprising, breaks the principle of least authority,
28
+ * and trips security scanners. A one-line visible prompt is the friendly
29
+ * middle ground.
30
+ */
31
+ function printClaudeCodeNudge() {
32
+ const home = os.homedir();
33
+ const claudeDir = path.join(home, '.claude');
34
+ if (!fs.existsSync(claudeDir))
35
+ return; // Claude Code not installed — silent
36
+ const settingsPath = path.join(claudeDir, 'settings.json');
37
+ if (fs.existsSync(settingsPath)) {
38
+ try {
39
+ const raw = fs.readFileSync(settingsPath, 'utf8');
40
+ if (raw.includes('hippo context --pinned-only'))
41
+ return; // already installed
42
+ }
43
+ catch {
44
+ // Fall through: on read failure, still show the nudge — a broken
45
+ // settings.json is a bigger problem for the user to see.
46
+ }
47
+ }
48
+ // Use stderr so the banner doesn't get piped into scripts reading package
49
+ // output on stdout.
50
+ const line = (s) => process.stderr.write(s + '\n');
51
+ line('');
52
+ line('hippo-memory installed. Claude Code detected on this machine.');
53
+ line('');
54
+ line('To wire Hippo into Claude Code (session hooks + mid-session pinned');
55
+ line('rule re-injection), run ONE of these in your project directory:');
56
+ line('');
57
+ line(' hippo init # initialize + install hooks for this project');
58
+ line(' hippo hook install claude-code # hooks only, no local store');
59
+ line('');
60
+ line('Or machine-wide pinned memories:');
61
+ line('');
62
+ line(' hippo init --global');
63
+ line('');
64
+ line('To skip this message on future installs: export HIPPO_SKIP_POSTINSTALL=1');
65
+ line('');
66
+ }
67
+ main();
68
+ //# sourceMappingURL=postinstall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postinstall.js","sourceRoot":"","sources":["../../src/postinstall.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAEzD,SAAS,IAAI;IACX,IAAI,OAAO,CAAC,GAAG,CAAC,sBAAsB,KAAK,GAAG;QAAE,OAAO;IAEvD,IAAI,CAAC;QACH,2BAA2B,EAAE,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,4EAA4E;IAC9E,CAAC;IAED,IAAI,CAAC;QACH,oBAAoB,EAAE,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,4EAA4E;IAC9E,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,oBAAoB;IAC3B,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;IAC1B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAC7C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,CAAC,qCAAqC;IAE5E,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IAC3D,IAAI,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAChC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;YAClD,IAAI,GAAG,CAAC,QAAQ,CAAC,6BAA6B,CAAC;gBAAE,OAAO,CAAC,oBAAoB;QAC/E,CAAC;QAAC,MAAM,CAAC;YACP,iEAAiE;YACjE,yDAAyD;QAC3D,CAAC;IACH,CAAC;IAED,0EAA0E;IAC1E,oBAAoB;IACpB,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC3D,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,IAAI,CAAC,+DAA+D,CAAC,CAAC;IACtE,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,IAAI,CAAC,oEAAoE,CAAC,CAAC;IAC3E,IAAI,CAAC,iEAAiE,CAAC,CAAC;IACxE,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,IAAI,CAAC,+EAA+E,CAAC,CAAC;IACtF,IAAI,CAAC,mEAAmE,CAAC,CAAC;IAC1E,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,IAAI,CAAC,kCAAkC,CAAC,CAAC;IACzC,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,IAAI,CAAC,yBAAyB,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,IAAI,CAAC,0EAA0E,CAAC,CAAC;IACjF,IAAI,CAAC,EAAE,CAAC,CAAC;AACX,CAAC;AAED,IAAI,EAAE,CAAC"}
@@ -0,0 +1,72 @@
1
+ import { isFtsAvailable } from './db.js';
2
+ import { appendAuditEvent } from './audit.js';
3
+ // JSON.stringify cannot serialize BigInt by default. node:sqlite returns INTEGER
4
+ // columns as bigint when the value exceeds Number.MAX_SAFE_INTEGER. Coerce to
5
+ // string so the audit payload is always serializable.
6
+ function bigintSafeReplacer(_key, value) {
7
+ return typeof value === 'bigint' ? value.toString() : value;
8
+ }
9
+ /**
10
+ * The only legitimate path to remove a `kind='raw'` row from `memories`.
11
+ *
12
+ * Snapshots the full row into `raw_archive`, flips `kind` to `'archived'` so the
13
+ * append-only trigger lets the delete through, then deletes the row. All in one
14
+ * SAVEPOINT so it can be nested inside an outer transaction (e.g. batchWriteAndDelete).
15
+ *
16
+ * Throws if the row does not exist or is not `kind='raw'`.
17
+ */
18
+ export function archiveRawMemory(db, id, opts) {
19
+ const row = db.prepare(`SELECT * FROM memories WHERE id = ?`).get(id);
20
+ if (!row)
21
+ throw new Error(`memory not found: ${id}`);
22
+ if (row.kind !== 'raw') {
23
+ throw new Error(`memory ${id} is not raw (kind=${String(row.kind)})`);
24
+ }
25
+ // SAVEPOINT (not BEGIN) so this works whether or not we're already inside a
26
+ // transaction. SQLite refuses BEGIN within a transaction; SAVEPOINT nests safely.
27
+ db.exec('SAVEPOINT archive_raw');
28
+ try {
29
+ db.prepare(`INSERT INTO raw_archive (memory_id, archived_at, reason, archived_by, payload_json) VALUES (?, ?, ?, ?, ?)`).run(id, new Date().toISOString(), opts.reason, opts.who, JSON.stringify(row, bigintSafeReplacer));
30
+ // Flip kind to 'archived' so the BEFORE DELETE trigger no longer fires, then delete.
31
+ db.prepare(`UPDATE memories SET kind = 'archived' WHERE id = ?`).run(id);
32
+ db.prepare(`DELETE FROM memories WHERE id = ?`).run(id);
33
+ // FTS5 is a virtual table — no FK CASCADE applies. Purge the FTS row so the
34
+ // archived content is not searchable after archive. Without this the original
35
+ // raw text remains in memories_fts until the next DB-open backfill, defeating
36
+ // GDPR right-to-be-forgotten.
37
+ if (isFtsAvailable(db)) {
38
+ try {
39
+ db.prepare(`DELETE FROM memories_fts WHERE id = ?`).run(id);
40
+ }
41
+ catch {
42
+ // Best effort only. The DELETE on memories already succeeded; FTS will
43
+ // self-heal on next DB open via backfillFtsIndex.
44
+ }
45
+ }
46
+ // A5 audit: emit archive_raw event inside the SAVEPOINT so the audit row is
47
+ // committed atomically with the row deletion. Use the row's own tenant_id
48
+ // (fetched above as part of SELECT *), not the env. Archives must be
49
+ // attributed to the tenant that owns the row, not whatever HIPPO_TENANT
50
+ // happens to be set to in the calling shell.
51
+ try {
52
+ appendAuditEvent(db, {
53
+ tenantId: String(row.tenant_id ?? 'default'),
54
+ actor: opts.who || 'cli',
55
+ op: 'archive_raw',
56
+ targetId: id,
57
+ metadata: { reason: opts.reason },
58
+ });
59
+ }
60
+ catch {
61
+ // Audit must not crash the archive. Failures here mean the audit table
62
+ // is unwritable; the archive itself has already succeeded.
63
+ }
64
+ db.exec('RELEASE SAVEPOINT archive_raw');
65
+ }
66
+ catch (e) {
67
+ db.exec('ROLLBACK TO SAVEPOINT archive_raw');
68
+ db.exec('RELEASE SAVEPOINT archive_raw');
69
+ throw e;
70
+ }
71
+ }
72
+ //# sourceMappingURL=raw-archive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw-archive.js","sourceRoot":"","sources":["../../src/raw-archive.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAO9C,iFAAiF;AACjF,8EAA8E;AAC9E,sDAAsD;AACtD,SAAS,kBAAkB,CAAC,IAAY,EAAE,KAAc;IACtD,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;AAC9D,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAAoB,EAAE,EAAU,EAAE,IAAiB;IAClF,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,qCAAqC,CAAC,CAAC,GAAG,CAAC,EAAE,CAEvD,CAAC;IACd,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC;IACrD,IAAI,GAAG,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,UAAU,EAAE,qBAAqB,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxE,CAAC;IAED,4EAA4E;IAC5E,kFAAkF;IAClF,EAAE,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IACjC,IAAI,CAAC;QACH,EAAE,CAAC,OAAO,CACR,4GAA4G,CAC7G,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC,CAAC;QACpG,qFAAqF;QACrF,EAAE,CAAC,OAAO,CAAC,oDAAoD,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACzE,EAAE,CAAC,OAAO,CAAC,mCAAmC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACxD,4EAA4E;QAC5E,8EAA8E;QAC9E,8EAA8E;QAC9E,8BAA8B;QAC9B,IAAI,cAAc,CAAC,EAAE,CAAC,EAAE,CAAC;YACvB,IAAI,CAAC;gBACH,EAAE,CAAC,OAAO,CAAC,uCAAuC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC9D,CAAC;YAAC,MAAM,CAAC;gBACP,uEAAuE;gBACvE,kDAAkD;YACpD,CAAC;QACH,CAAC;QACD,4EAA4E;QAC5E,0EAA0E;QAC1E,qEAAqE;QACrE,wEAAwE;QACxE,6CAA6C;QAC7C,IAAI,CAAC;YACH,gBAAgB,CAAC,EAAE,EAAE;gBACnB,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,SAAS,IAAI,SAAS,CAAC;gBAC5C,KAAK,EAAE,IAAI,CAAC,GAAG,IAAI,KAAK;gBACxB,EAAE,EAAE,aAAa;gBACjB,QAAQ,EAAE,EAAE;gBACZ,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE;aAClC,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,uEAAuE;YACvE,2DAA2D;QAC7D,CAAC;QACD,EAAE,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,EAAE,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;QAC7C,EAAE,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;QACzC,MAAM,CAAC,CAAC;IACV,CAAC;AACH,CAAC"}