@graphorin/memory 0.5.0 → 0.6.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 (235) hide show
  1. package/CHANGELOG.md +90 -1
  2. package/README.md +31 -31
  3. package/dist/conflict/index.d.ts +3 -1
  4. package/dist/conflict/index.js +1 -1
  5. package/dist/conflict/locale-packs/en.d.ts +13 -0
  6. package/dist/conflict/locale-packs/en.d.ts.map +1 -0
  7. package/dist/conflict/locale-packs/en.js +1 -1
  8. package/dist/conflict/locale-packs/en.js.map +1 -1
  9. package/dist/conflict/pipeline.d.ts +2 -2
  10. package/dist/conflict/pipeline.js +3 -3
  11. package/dist/conflict/pipeline.js.map +1 -1
  12. package/dist/conflict/stages/helpers.js +1 -1
  13. package/dist/conflict/stages/helpers.js.map +1 -1
  14. package/dist/conflict/stages/stage1-exact-dedup.js.map +1 -1
  15. package/dist/conflict/stages/stage2-embedding-three-zone.js.map +1 -1
  16. package/dist/conflict/stages/stage3-heuristic-regex.js +1 -1
  17. package/dist/conflict/stages/stage3-heuristic-regex.js.map +1 -1
  18. package/dist/conflict/stages/stage4-subject-predicate.js.map +1 -1
  19. package/dist/conflict/stages/stage5-defer-to-deep.js.map +1 -1
  20. package/dist/conflict/types.d.ts +7 -7
  21. package/dist/conflict/types.js +1 -1
  22. package/dist/conflict/types.js.map +1 -1
  23. package/dist/consolidator/budget.js +16 -3
  24. package/dist/consolidator/budget.js.map +1 -1
  25. package/dist/consolidator/decay.d.ts +13 -2
  26. package/dist/consolidator/decay.js +17 -5
  27. package/dist/consolidator/decay.js.map +1 -1
  28. package/dist/consolidator/dlq.js +1 -1
  29. package/dist/consolidator/dlq.js.map +1 -1
  30. package/dist/consolidator/errors.js +2 -2
  31. package/dist/consolidator/errors.js.map +1 -1
  32. package/dist/consolidator/index.js +8 -6
  33. package/dist/consolidator/index.js.map +1 -1
  34. package/dist/consolidator/lock.js +1 -1
  35. package/dist/consolidator/lock.js.map +1 -1
  36. package/dist/consolidator/noise-filter.js.map +1 -1
  37. package/dist/consolidator/phases/deep.js +6 -2
  38. package/dist/consolidator/phases/deep.js.map +1 -1
  39. package/dist/consolidator/phases/induce.d.ts +10 -10
  40. package/dist/consolidator/phases/induce.js +6 -6
  41. package/dist/consolidator/phases/induce.js.map +1 -1
  42. package/dist/consolidator/phases/learned-context.js +129 -0
  43. package/dist/consolidator/phases/learned-context.js.map +1 -0
  44. package/dist/consolidator/phases/light.js +2 -1
  45. package/dist/consolidator/phases/light.js.map +1 -1
  46. package/dist/consolidator/phases/reflect.js +5 -4
  47. package/dist/consolidator/phases/reflect.js.map +1 -1
  48. package/dist/consolidator/phases/standard.js +37 -8
  49. package/dist/consolidator/phases/standard.js.map +1 -1
  50. package/dist/consolidator/reconcile.js +1 -1
  51. package/dist/consolidator/reconcile.js.map +1 -1
  52. package/dist/consolidator/runtime.d.ts +4 -4
  53. package/dist/consolidator/runtime.d.ts.map +1 -1
  54. package/dist/consolidator/runtime.js +73 -16
  55. package/dist/consolidator/runtime.js.map +1 -1
  56. package/dist/consolidator/scheduler.d.ts +5 -5
  57. package/dist/consolidator/scheduler.js +1 -1
  58. package/dist/consolidator/scheduler.js.map +1 -1
  59. package/dist/consolidator/triggers.js +7 -7
  60. package/dist/consolidator/triggers.js.map +1 -1
  61. package/dist/consolidator/types.d.ts +68 -20
  62. package/dist/consolidator/types.d.ts.map +1 -1
  63. package/dist/consolidator/types.js +16 -6
  64. package/dist/consolidator/types.js.map +1 -1
  65. package/dist/context-engine/annotations.d.ts +9 -9
  66. package/dist/context-engine/annotations.js +3 -3
  67. package/dist/context-engine/annotations.js.map +1 -1
  68. package/dist/context-engine/auto-recall.js.map +1 -1
  69. package/dist/context-engine/compaction/clear-tool-results.d.ts +18 -3
  70. package/dist/context-engine/compaction/clear-tool-results.d.ts.map +1 -1
  71. package/dist/context-engine/compaction/clear-tool-results.js +26 -5
  72. package/dist/context-engine/compaction/clear-tool-results.js.map +1 -1
  73. package/dist/context-engine/compaction/compactor.js +19 -6
  74. package/dist/context-engine/compaction/compactor.js.map +1 -1
  75. package/dist/context-engine/compaction/hooks/reanchor-persona-block.js +4 -0
  76. package/dist/context-engine/compaction/hooks/reanchor-persona-block.js.map +1 -1
  77. package/dist/context-engine/compaction/hooks/reanchor-pinned-facts.js +1 -0
  78. package/dist/context-engine/compaction/hooks/reanchor-pinned-facts.js.map +1 -1
  79. package/dist/context-engine/compaction/hooks/reanchor-project-rules.js +2 -1
  80. package/dist/context-engine/compaction/hooks/reanchor-project-rules.js.map +1 -1
  81. package/dist/context-engine/compaction/hooks/reanchor-recent-results.d.ts +28 -0
  82. package/dist/context-engine/compaction/hooks/reanchor-recent-results.d.ts.map +1 -0
  83. package/dist/context-engine/compaction/hooks/reanchor-recent-results.js +71 -0
  84. package/dist/context-engine/compaction/hooks/reanchor-recent-results.js.map +1 -0
  85. package/dist/context-engine/compaction/hooks/types.d.ts +15 -3
  86. package/dist/context-engine/compaction/hooks/types.d.ts.map +1 -1
  87. package/dist/context-engine/compaction/index.d.ts +1 -0
  88. package/dist/context-engine/compaction/index.js +2 -1
  89. package/dist/context-engine/compaction/templates/summary-9-section.d.ts +10 -3
  90. package/dist/context-engine/compaction/templates/summary-9-section.d.ts.map +1 -1
  91. package/dist/context-engine/compaction/templates/summary-9-section.js +42 -5
  92. package/dist/context-engine/compaction/templates/summary-9-section.js.map +1 -1
  93. package/dist/context-engine/compaction/thresholds.js.map +1 -1
  94. package/dist/context-engine/compaction/types.d.ts +47 -7
  95. package/dist/context-engine/compaction/types.d.ts.map +1 -1
  96. package/dist/context-engine/engine.d.ts +23 -4
  97. package/dist/context-engine/engine.d.ts.map +1 -1
  98. package/dist/context-engine/engine.js +69 -15
  99. package/dist/context-engine/engine.js.map +1 -1
  100. package/dist/context-engine/index.d.ts +1 -0
  101. package/dist/context-engine/index.d.ts.map +1 -1
  102. package/dist/context-engine/index.js +2 -1
  103. package/dist/context-engine/locale-packs/en.js +14 -13
  104. package/dist/context-engine/locale-packs/en.js.map +1 -1
  105. package/dist/context-engine/locale-packs/types.d.ts +10 -10
  106. package/dist/context-engine/locale-packs/types.d.ts.map +1 -1
  107. package/dist/context-engine/locale-packs/types.js.map +1 -1
  108. package/dist/context-engine/metadata.d.ts +1 -1
  109. package/dist/context-engine/metadata.js +2 -2
  110. package/dist/context-engine/metadata.js.map +1 -1
  111. package/dist/context-engine/preambles/inbound-en.d.ts +1 -1
  112. package/dist/context-engine/preambles/inbound-en.js +1 -1
  113. package/dist/context-engine/preambles/inbound-en.js.map +1 -1
  114. package/dist/context-engine/privacy-filter.d.ts +2 -2
  115. package/dist/context-engine/privacy-filter.js +1 -1
  116. package/dist/context-engine/privacy-filter.js.map +1 -1
  117. package/dist/context-engine/templates/base-en.d.ts +1 -1
  118. package/dist/context-engine/templates/base-en.js +1 -1
  119. package/dist/context-engine/templates/base-en.js.map +1 -1
  120. package/dist/context-engine/templates/composer.d.ts +1 -1
  121. package/dist/context-engine/templates/composer.js.map +1 -1
  122. package/dist/context-engine/token-budget.d.ts +1 -1
  123. package/dist/context-engine/token-budget.js +1 -1
  124. package/dist/context-engine/token-budget.js.map +1 -1
  125. package/dist/context-engine/token-counter.d.ts +16 -7
  126. package/dist/context-engine/token-counter.d.ts.map +1 -1
  127. package/dist/context-engine/token-counter.js +31 -9
  128. package/dist/context-engine/token-counter.js.map +1 -1
  129. package/dist/errors/index.d.ts +2 -2
  130. package/dist/errors/index.js +4 -4
  131. package/dist/errors/index.js.map +1 -1
  132. package/dist/facade.d.ts +44 -15
  133. package/dist/facade.d.ts.map +1 -1
  134. package/dist/facade.js +16 -8
  135. package/dist/facade.js.map +1 -1
  136. package/dist/graph/entity-resolver.d.ts +2 -2
  137. package/dist/graph/entity-resolver.js +2 -2
  138. package/dist/graph/entity-resolver.js.map +1 -1
  139. package/dist/index.d.ts +9 -5
  140. package/dist/index.d.ts.map +1 -1
  141. package/dist/index.js +9 -4
  142. package/dist/index.js.map +1 -1
  143. package/dist/internal/contextualize.js +2 -2
  144. package/dist/internal/contextualize.js.map +1 -1
  145. package/dist/internal/embedder-binding.js +1 -1
  146. package/dist/internal/embedder-binding.js.map +1 -1
  147. package/dist/internal/id.js +1 -1
  148. package/dist/internal/id.js.map +1 -1
  149. package/dist/internal/injection-heuristics.js +25 -2
  150. package/dist/internal/injection-heuristics.js.map +1 -1
  151. package/dist/internal/spans.js +1 -1
  152. package/dist/internal/spans.js.map +1 -1
  153. package/dist/internal/storage-adapter.d.ts +71 -22
  154. package/dist/internal/storage-adapter.d.ts.map +1 -1
  155. package/dist/migration/embedder-migration.d.ts +7 -7
  156. package/dist/migration/embedder-migration.js.map +1 -1
  157. package/dist/search/explain.d.ts +7 -4
  158. package/dist/search/explain.d.ts.map +1 -1
  159. package/dist/search/explain.js +1 -1
  160. package/dist/search/explain.js.map +1 -1
  161. package/dist/search/fit-weights.d.ts +48 -0
  162. package/dist/search/fit-weights.d.ts.map +1 -0
  163. package/dist/search/fit-weights.js +70 -0
  164. package/dist/search/fit-weights.js.map +1 -0
  165. package/dist/search/graph-ppr.d.ts +36 -0
  166. package/dist/search/graph-ppr.d.ts.map +1 -0
  167. package/dist/search/graph-ppr.js +38 -0
  168. package/dist/search/graph-ppr.js.map +1 -0
  169. package/dist/search/index.d.ts +4 -1
  170. package/dist/search/index.js +4 -1
  171. package/dist/search/iterative.d.ts +15 -8
  172. package/dist/search/iterative.d.ts.map +1 -1
  173. package/dist/search/iterative.js +10 -9
  174. package/dist/search/iterative.js.map +1 -1
  175. package/dist/search/query-transform.d.ts +6 -6
  176. package/dist/search/query-transform.js +6 -6
  177. package/dist/search/query-transform.js.map +1 -1
  178. package/dist/search/rrf.d.ts +4 -4
  179. package/dist/search/rrf.js +4 -4
  180. package/dist/search/rrf.js.map +1 -1
  181. package/dist/search/trust.d.ts +30 -0
  182. package/dist/search/trust.d.ts.map +1 -0
  183. package/dist/search/trust.js +50 -0
  184. package/dist/search/trust.js.map +1 -0
  185. package/dist/search/types.d.ts +1 -1
  186. package/dist/tiers/episodic-memory.d.ts +6 -4
  187. package/dist/tiers/episodic-memory.d.ts.map +1 -1
  188. package/dist/tiers/episodic-memory.js +3 -2
  189. package/dist/tiers/episodic-memory.js.map +1 -1
  190. package/dist/tiers/index.d.ts +1 -1
  191. package/dist/tiers/index.js +1 -1
  192. package/dist/tiers/insight-memory.d.ts +4 -4
  193. package/dist/tiers/insight-memory.js +3 -3
  194. package/dist/tiers/insight-memory.js.map +1 -1
  195. package/dist/tiers/procedural-memory.d.ts +29 -7
  196. package/dist/tiers/procedural-memory.d.ts.map +1 -1
  197. package/dist/tiers/procedural-memory.js +66 -6
  198. package/dist/tiers/procedural-memory.js.map +1 -1
  199. package/dist/tiers/semantic-memory.d.ts +111 -30
  200. package/dist/tiers/semantic-memory.d.ts.map +1 -1
  201. package/dist/tiers/semantic-memory.js +120 -27
  202. package/dist/tiers/semantic-memory.js.map +1 -1
  203. package/dist/tiers/session-memory.d.ts +7 -7
  204. package/dist/tiers/session-memory.js +7 -7
  205. package/dist/tiers/session-memory.js.map +1 -1
  206. package/dist/tiers/shared-memory.d.ts +1 -1
  207. package/dist/tiers/shared-memory.js +1 -1
  208. package/dist/tiers/shared-memory.js.map +1 -1
  209. package/dist/tiers/working-memory.d.ts +3 -3
  210. package/dist/tiers/working-memory.js +2 -2
  211. package/dist/tiers/working-memory.js.map +1 -1
  212. package/dist/tools/block-tools.d.ts +9 -9
  213. package/dist/tools/block-tools.d.ts.map +1 -1
  214. package/dist/tools/block-tools.js +3 -3
  215. package/dist/tools/block-tools.js.map +1 -1
  216. package/dist/tools/fact-tools.d.ts +48 -31
  217. package/dist/tools/fact-tools.d.ts.map +1 -1
  218. package/dist/tools/fact-tools.js +30 -18
  219. package/dist/tools/fact-tools.js.map +1 -1
  220. package/dist/tools/index.d.ts +9 -2
  221. package/dist/tools/index.d.ts.map +1 -1
  222. package/dist/tools/index.js +4 -2
  223. package/dist/tools/index.js.map +1 -1
  224. package/dist/tools/recall-tools.d.ts +40 -20
  225. package/dist/tools/recall-tools.d.ts.map +1 -1
  226. package/dist/tools/recall-tools.js +29 -10
  227. package/dist/tools/recall-tools.js.map +1 -1
  228. package/dist/tools/runbook-tools.d.ts +76 -0
  229. package/dist/tools/runbook-tools.d.ts.map +1 -0
  230. package/dist/tools/runbook-tools.js +53 -0
  231. package/dist/tools/runbook-tools.js.map +1 -0
  232. package/dist/tools/taint.js +33 -0
  233. package/dist/tools/taint.js.map +1 -0
  234. package/dist/tools/types.d.ts +1 -1
  235. package/package.json +8 -8
@@ -1,16 +1,20 @@
1
1
  import { withMemorySpan } from "../internal/spans.js";
2
+ import { DEFAULT_SALIENCE_WEIGHTS } from "../consolidator/decay.js";
2
3
  import { QuarantinePromotionRefusedError } from "../errors/index.js";
3
4
  import { contextualize } from "../internal/contextualize.js";
4
5
  import { newMemoryId } from "../internal/id.js";
6
+ import { normalizeEntityName } from "../graph/entity-resolver.js";
5
7
  import { DEFAULT_MAX_ITERATIONS, runIterativeRetrieval } from "../search/iterative.js";
6
8
  import { WeightedRRFReranker, fuseRrf, fuseWeighted } from "../search/rrf.js";
7
9
  import { detectMemoryInjection } from "../internal/injection-heuristics.js";
8
10
  import { explainRecall } from "../search/explain.js";
11
+ import { pprActivation } from "../search/graph-ppr.js";
12
+ import { trustDiscount } from "../search/trust.js";
9
13
  import { md5 } from "@graphorin/core";
10
14
 
11
15
  //#region src/tiers/semantic-memory.ts
12
16
  /**
13
- * `SemanticMemory` long-term factual store. Hybrid (vector + FTS5)
17
+ * `SemanticMemory` - long-term factual store. Hybrid (vector + FTS5)
14
18
  * search merges the two ranked lists through the configured
15
19
  * {@link ReRanker} (default {@link RRFReranker} with `k = 60`).
16
20
  *
@@ -34,6 +38,7 @@ var SemanticMemory = class {
34
38
  #grader;
35
39
  #iterativeMaxIterations;
36
40
  #reranker;
41
+ #trustWeights;
37
42
  constructor(args) {
38
43
  this.#store = args.store;
39
44
  this.#tracer = args.tracer;
@@ -46,6 +51,7 @@ var SemanticMemory = class {
46
51
  this.#entityResolver = args.entityResolver ?? null;
47
52
  this.#grader = args.grader ?? null;
48
53
  this.#iterativeMaxIterations = args.iterativeMaxIterations ?? DEFAULT_MAX_ITERATIONS;
54
+ this.#trustWeights = args.trustWeights ?? DEFAULT_SALIENCE_WEIGHTS;
49
55
  }
50
56
  /** Replace the active reranker. Returns the previous instance. */
51
57
  setReranker(reranker) {
@@ -104,6 +110,7 @@ var SemanticMemory = class {
104
110
  ...input.supersedes !== void 0 ? { supersedes: input.supersedes } : {},
105
111
  ...provenance !== void 0 ? { provenance } : {},
106
112
  status,
113
+ ...input.owner !== void 0 ? { owner: input.owner } : {},
107
114
  createdAt: now,
108
115
  updatedAt: now
109
116
  };
@@ -212,7 +219,7 @@ var SemanticMemory = class {
212
219
  * P2-1: resolve the fact's subject / object to canonical entities and
213
220
  * link them so one-hop expansion can traverse this fact. A no-op when
214
221
  * no resolver is configured (the default) or the fact has no s/p/o, and
215
- * resilient a resolution failure never breaks the write that just
222
+ * resilient - a resolution failure never breaks the write that just
216
223
  * committed.
217
224
  */
218
225
  async #linkEntities(scope, fact, signal) {
@@ -230,6 +237,8 @@ var SemanticMemory = class {
230
237
  const weighted = opts.fusion !== void 0 && opts.fusion.strategy === "weighted" ? opts.fusion : null;
231
238
  const wFts = weighted?.weights.fts ?? 1;
232
239
  const wVector = weighted?.weights.vector ?? 1;
240
+ const wGraph = weighted?.weights.graph ?? 1;
241
+ const wEntity = weighted?.weights.entity ?? 1;
233
242
  const queries = await this.#expandQueries(query, opts);
234
243
  const lists = [];
235
244
  const listWeights = [];
@@ -244,12 +253,14 @@ var SemanticMemory = class {
244
253
  ...opts.asOf !== void 0 ? { asOf: opts.asOf } : {},
245
254
  ...opts.tags !== void 0 && opts.tags.length > 0 ? { tags: opts.tags } : {},
246
255
  ...opts.includeQuarantined === true ? { includeQuarantined: true } : {},
256
+ ...opts.includeSuperseded === true ? { includeSuperseded: true } : {},
257
+ ...opts.owner !== void 0 ? { owner: opts.owner } : {},
247
258
  ...opts.signal !== void 0 ? { signal: opts.signal } : {}
248
259
  });
249
260
  lists.push(ftsHits);
250
261
  listWeights.push(wFts);
251
262
  listLabels.push(`fts_${queries.indexOf(q)}`);
252
- const vectorHits = await this.#tryVectorSearch(scope, q, candidateTopK, opts.asOf, opts.includeQuarantined);
263
+ const vectorHits = await this.#tryVectorSearch(scope, q, candidateTopK, opts.asOf, opts.includeQuarantined, opts.includeSuperseded, opts.owner);
253
264
  if (vectorHits.length > 0) {
254
265
  lists.push(vectorHits);
255
266
  listWeights.push(wVector);
@@ -270,25 +281,34 @@ var SemanticMemory = class {
270
281
  const graphHits = await this.#tryExpandHops(scope, lists, opts, candidateTopK);
271
282
  if (graphHits.length > 0) {
272
283
  lists.push(graphHits);
273
- listWeights.push(1);
284
+ listWeights.push(wGraph);
274
285
  listLabels.push("graph");
275
286
  }
287
+ const entityHits = await this.#tryEntityMatch(scope, query, opts, candidateTopK);
288
+ if (entityHits.length > 0) {
289
+ lists.push(entityHits);
290
+ listWeights.push(wEntity);
291
+ listLabels.push("entity");
292
+ }
276
293
  const reranker = weighted !== null ? new WeightedRRFReranker({
277
294
  weights: listWeights,
278
295
  ...weighted.k !== void 0 ? { k: weighted.k } : {}
279
296
  }) : this.#reranker;
280
- const fusedTopK = opts.decay !== void 0 ? Math.max(finalTopK, lists.reduce((n, l) => n + l.length, 0)) : finalTopK;
297
+ const fusedTopK = opts.decay !== void 0 || (opts.tags?.length ?? 0) > 0 || opts.owner !== void 0 || (opts.expandHops ?? 0) > 0 || opts.entityMatch === true ? Math.max(finalTopK, lists.reduce((n, l) => n + l.length, 0)) : finalTopK;
281
298
  const fused = await reranker.rerank(query, lists, {
282
299
  topK: fusedTopK,
283
300
  labels: listLabels,
284
301
  ...opts.signal !== void 0 ? { signal: opts.signal } : {}
285
302
  });
286
303
  const decayed = await this.#applyDecay(scope, fused, opts.decay);
287
- const ranked = (opts.tags !== void 0 && opts.tags.length > 0 ? decayed.filter((h) => {
304
+ const filtered = opts.tags !== void 0 && opts.tags.length > 0 ? decayed.filter((h) => {
288
305
  const recordTags = h.record.tags;
289
306
  if (recordTags === void 0 || recordTags.length === 0) return false;
290
307
  return opts.tags?.some((t) => recordTags.includes(t)) === true;
291
- }) : decayed).slice(0, finalTopK);
308
+ }) : decayed;
309
+ const wantedOwners = opts.owner === void 0 ? null : typeof opts.owner === "string" ? [opts.owner] : opts.owner;
310
+ const ownerFiltered = wantedOwners !== null ? filtered.filter((h) => wantedOwners.includes(h.record.owner ?? "user")) : filtered;
311
+ const ranked = (opts.trustWeighting === "off" ? ownerFiltered : this.#applyTrustDiscount(ownerFiltered)).slice(0, finalTopK);
292
312
  if (ranked.length > 0 && typeof this.#store.semantic.markAccessed === "function") try {
293
313
  await this.#store.semantic.markAccessed(ranked.map((h) => h.record.id));
294
314
  } catch {}
@@ -321,8 +341,8 @@ var SemanticMemory = class {
321
341
  * hard *and* with a grader configured
322
342
  * (`createMemory({ iterativeRetrieval })`), the retrieved set is graded
323
343
  * for sufficiency and, when weak, the query is reformulated and
324
- * retrieved again **widening to one-hop graph expansion**
325
- * (`expandHops: 1`) on each reformulation pass up to `maxIterations`
344
+ * retrieved again - **widening to one-hop graph expansion**
345
+ * (`expandHops: 1`) on each reformulation pass - up to `maxIterations`
326
346
  * (hard-capped at 5). When still insufficient it returns
327
347
  * `abstained: true` so the caller can decline to answer instead of
328
348
  * confabulating.
@@ -368,7 +388,7 @@ var SemanticMemory = class {
368
388
  * zone thresholds are calibrated against them), and it **includes
369
389
  * quarantined facts** so prior synthesized memories are visible to
370
390
  * reconciliation. Returns `[]` when no embedder / vector adapter is
371
- * configured the consolidator then treats every candidate as a
391
+ * configured - the consolidator then treats every candidate as a
372
392
  * fresh `add`, degrading gracefully to the pre-reconcile behaviour.
373
393
  *
374
394
  * @stable
@@ -390,7 +410,7 @@ var SemanticMemory = class {
390
410
  * to, oldest → newest, including superseded / soft-deleted rows so
391
411
  * callers can answer "how did this fact change over time". Requires
392
412
  * a storage adapter that implements
393
- * `SemanticMemoryStoreExt.historyOf(...)` the default
413
+ * `SemanticMemoryStoreExt.historyOf(...)` - the default
394
414
  * `@graphorin/store-sqlite` adapter wires this through. P0-2.
395
415
  *
396
416
  * @stable
@@ -411,12 +431,12 @@ var SemanticMemory = class {
411
431
  * that admits a synthesized memory into action-driving recall once a
412
432
  * human (or trusted non-agent caller) has reviewed it. Writes a
413
433
  * `memory_history` audit row. Requires a storage adapter that
414
- * implements `SemanticMemoryStoreExt.setStatus(...)` the default
434
+ * implements `SemanticMemoryStoreExt.setStatus(...)` - the default
415
435
  * `@graphorin/store-sqlite` adapter wires this through.
416
436
  *
417
437
  * MRET-3 / MST-1: promotion of a fact whose text still trips the
418
438
  * offline injection heuristics is **refused** with
419
- * {@link QuarantinePromotionRefusedError} the model-facing
439
+ * {@link QuarantinePromotionRefusedError} - the model-facing
420
440
  * `fact_validate` tool calls this with no `force`, so a poisoned
421
441
  * memory can never be promoted by the agent itself (the one-turn
422
442
  * `fact_remember(poison)` → `fact_validate(id)` chain is closed). An
@@ -475,7 +495,7 @@ var SemanticMemory = class {
475
495
  * Hard-delete a fact (GDPR path). Distinct from {@link forget}: the
476
496
  * record is removed from storage entirely instead of soft-archived.
477
497
  * Requires a storage adapter that implements
478
- * `SemanticMemoryStoreExt.purge(...)` the default
498
+ * `SemanticMemoryStoreExt.purge(...)` - the default
479
499
  * `@graphorin/store-sqlite` adapter wires this through.
480
500
  */
481
501
  async purge(scope, factId, reason) {
@@ -491,12 +511,12 @@ var SemanticMemory = class {
491
511
  async fuse(query, lists, options = {}) {
492
512
  return this.#reranker.rerank(query, lists, options);
493
513
  }
494
- /** Pure-fusion helper exposed for callers that already collected results. */
514
+ /** Pure-fusion helper - exposed for callers that already collected results. */
495
515
  static fuseRrf(lists, k = 60) {
496
516
  return fuseRrf(lists, k);
497
517
  }
498
518
  /**
499
- * Pure weighted-fusion helper (X-2) like {@link SemanticMemory.fuseRrf}
519
+ * Pure weighted-fusion helper (X-2) - like {@link SemanticMemory.fuseRrf}
500
520
  * but scales each list `i`'s reciprocal-rank contribution by
501
521
  * `weights[i]`. A missing / invalid entry defaults to `1`, so equal or
502
522
  * absent weights reproduce RRF.
@@ -507,7 +527,7 @@ var SemanticMemory = class {
507
527
  /**
508
528
  * Multi-query expansion (P2-3). Returns the original query followed by
509
529
  * up to `multiQuery - 1` deduped reworded variants. A no-op (`[query]`)
510
- * when `multiQuery` is unset / `<= 1` or no transformer is configured
530
+ * when `multiQuery` is unset / `<= 1` or no transformer is configured -
511
531
  * so the default path makes no provider call. A transformer failure
512
532
  * degrades to `[query]` rather than breaking recall.
513
533
  */
@@ -535,7 +555,7 @@ var SemanticMemory = class {
535
555
  * HyDE retrieval (P2-3). Generates a hypothetical answer, embeds it,
536
556
  * and returns its vector neighbours to fuse into the result. A no-op
537
557
  * (`[]`) unless `hyde` is set, a transformer is configured, **and** an
538
- * embedder + vector surface exist the embedder guard is checked
558
+ * embedder + vector surface exist - the embedder guard is checked
539
559
  * *first* so a missing embedder skips the LLM call entirely rather than
540
560
  * generating a passage that can never be embedded.
541
561
  */
@@ -554,7 +574,7 @@ var SemanticMemory = class {
554
574
  * One-hop graph expansion (P2-1). Seeds on the unique fact ids already
555
575
  * gathered into `lists` and fuses in facts sharing a canonical entity,
556
576
  * via the adapter's recursive-CTE `graph.expandOneHop`. A no-op (`[]`)
557
- * unless `expandHops >= 1` and the adapter exposes `graph` and
577
+ * unless `expandHops >= 1` and the adapter exposes `graph` - and
558
578
  * resilient: a traversal error degrades to no expansion rather than
559
579
  * breaking recall. Neighbours carry a `graph` signal so explanations
560
580
  * (X-3) can attribute a hit to the hop.
@@ -570,13 +590,24 @@ var SemanticMemory = class {
570
590
  seedIds.push(hit.record.id);
571
591
  }
572
592
  if (seedIds.length === 0) return [];
593
+ const expandOpts = {
594
+ maxHops: hops,
595
+ limit,
596
+ ...opts.includeQuarantined === true ? { includeQuarantined: true } : {},
597
+ ...opts.includeSuperseded === true ? { includeSuperseded: true } : {},
598
+ ...opts.asOf !== void 0 ? { asOf: opts.asOf } : {}
599
+ };
573
600
  try {
574
- return (await graphStore.expandOneHop(scope, seedIds, {
575
- maxHops: hops,
576
- limit,
577
- ...opts.includeQuarantined === true ? { includeQuarantined: true } : {},
578
- ...opts.asOf !== void 0 ? { asOf: opts.asOf } : {}
579
- })).map((fact) => ({
601
+ if (opts.graphScoring === "ppr" && typeof graphStore.expandActivation === "function") {
602
+ const graded = await graphStore.expandActivation(scope, seedIds, expandOpts);
603
+ const scores = pprActivation(graded);
604
+ return graded.map((entry, i) => ({
605
+ record: entry.fact,
606
+ score: scores[i] ?? 0,
607
+ signals: Object.freeze({ graph: scores[i] ?? 0 })
608
+ }));
609
+ }
610
+ return (await graphStore.expandOneHop(scope, seedIds, expandOpts)).map((fact) => ({
580
611
  record: fact,
581
612
  score: 1,
582
613
  signals: Object.freeze({ graph: 1 })
@@ -585,12 +616,74 @@ var SemanticMemory = class {
585
616
  return [];
586
617
  }
587
618
  }
588
- async #tryVectorSearch(scope, query, topK, asOf, includeQuarantined) {
619
+ /**
620
+ * D5 exact entity-match leg. Normalizes the query into candidate
621
+ * entity names and fetches facts linked to a matching canonical
622
+ * entity. A no-op without `entityMatch`, a graph adapter, or the
623
+ * `factsForEntityName` store method.
624
+ */
625
+ async #tryEntityMatch(scope, query, opts, limit) {
626
+ if (opts.entityMatch !== true) return [];
627
+ const graphStore = this.#store.graph;
628
+ if (graphStore === void 0 || typeof graphStore.factsForEntityName !== "function") return [];
629
+ const normalized = normalizeEntityName(query);
630
+ if (normalized.length === 0) return [];
631
+ const candidates = new Set([normalized]);
632
+ const words = normalized.split(" ").filter((w) => w.length > 2);
633
+ for (const w of words) candidates.add(w);
634
+ const out = [];
635
+ const seen = /* @__PURE__ */ new Set();
636
+ try {
637
+ for (const name of candidates) {
638
+ const facts = await graphStore.factsForEntityName(scope, name, {
639
+ limit,
640
+ ...opts.includeQuarantined === true ? { includeQuarantined: true } : {},
641
+ ...opts.includeSuperseded === true ? { includeSuperseded: true } : {},
642
+ ...opts.asOf !== void 0 ? { asOf: opts.asOf } : {}
643
+ });
644
+ for (const fact of facts) {
645
+ if (seen.has(fact.id)) continue;
646
+ seen.add(fact.id);
647
+ out.push({
648
+ record: fact,
649
+ score: 1,
650
+ signals: Object.freeze({ entity: 1 })
651
+ });
652
+ }
653
+ }
654
+ } catch {
655
+ return [];
656
+ }
657
+ return out;
658
+ }
659
+ async #tryVectorSearch(scope, query, topK, asOf, includeQuarantined, includeSuperseded, owner) {
589
660
  const embedderId = this.#embedderIdProvider();
590
661
  if (this.#embedder === null || embedderId === null || typeof this.#store.semantic.searchVector !== "function") return [];
591
662
  const [vector] = await this.#embedder.embed([query], { taskType: "query" });
592
663
  if (vector === void 0) return [];
593
- return this.#store.semantic.searchVector(scope, vector, embedderId, topK, asOf, includeQuarantined);
664
+ return this.#store.semantic.searchVector(scope, vector, embedderId, topK, asOf, includeQuarantined, includeSuperseded, owner);
665
+ }
666
+ /**
667
+ * C5: multiply each hit's fused score by its trust factor and re-sort.
668
+ * No-ops (returns the same array) when every factor is 1.
669
+ */
670
+ #applyTrustDiscount(hits) {
671
+ let changed = false;
672
+ const discounted = hits.map((hit) => {
673
+ const factor = trustDiscount(hit.record, this.#trustWeights);
674
+ if (factor >= 1) return hit;
675
+ changed = true;
676
+ return {
677
+ record: hit.record,
678
+ score: hit.score * factor,
679
+ signals: Object.freeze({
680
+ ...hit.signals ?? {},
681
+ trust: factor
682
+ })
683
+ };
684
+ });
685
+ if (!changed) return hits;
686
+ return [...discounted].sort((a, b) => b.score - a.score);
594
687
  }
595
688
  async #applyDecay(scope, hits, decay) {
596
689
  if (decay === void 0 || hits.length === 0) return hits;