@fgv/ts-agent-memory 5.1.0-39 → 5.1.0-41

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 (210) hide show
  1. package/.rush/temp/{b82cf6bdece20481260e6bab946179eeec9d7b46.tar.log → cbbdbe09515171b4eba8f2592be2dace1e4e8142.tar.log} +14 -2
  2. package/.rush/temp/chunked-rush-logs/ts-agent-memory.build.chunks.jsonl +2 -2
  3. package/.rush/temp/operation/build/all.log +2 -2
  4. package/.rush/temp/operation/build/log-chunks.jsonl +2 -2
  5. package/.rush/temp/operation/build/state.json +1 -1
  6. package/dist/packlets/converters/envelopeConverter.js +17 -3
  7. package/dist/packlets/converters/envelopeConverter.js.map +1 -1
  8. package/dist/packlets/index/memoryIndex.js +58 -10
  9. package/dist/packlets/index/memoryIndex.js.map +1 -1
  10. package/dist/packlets/ingest/cycleGuard.js +13 -6
  11. package/dist/packlets/ingest/cycleGuard.js.map +1 -1
  12. package/dist/packlets/ingest/hostStages.js.map +1 -1
  13. package/dist/packlets/ingest/model.js.map +1 -1
  14. package/dist/packlets/ingest/orchestrator.js +94 -49
  15. package/dist/packlets/ingest/orchestrator.js.map +1 -1
  16. package/dist/packlets/retrieve/hybridRetriever.js +13 -2
  17. package/dist/packlets/retrieve/hybridRetriever.js.map +1 -1
  18. package/dist/packlets/retrieve/linkTraversalRetriever.js +46 -57
  19. package/dist/packlets/retrieve/linkTraversalRetriever.js.map +1 -1
  20. package/dist/packlets/retrieve/recencyRetriever.js +3 -3
  21. package/dist/packlets/retrieve/recencyRetriever.js.map +1 -1
  22. package/dist/packlets/retrieve/retriever.js +50 -7
  23. package/dist/packlets/retrieve/retriever.js.map +1 -1
  24. package/dist/packlets/retrieve/semanticRetriever.js +9 -3
  25. package/dist/packlets/retrieve/semanticRetriever.js.map +1 -1
  26. package/dist/packlets/retrieve/structuredFilterRetriever.js +3 -3
  27. package/dist/packlets/retrieve/structuredFilterRetriever.js.map +1 -1
  28. package/dist/packlets/retrieve/tagRetriever.js +3 -3
  29. package/dist/packlets/retrieve/tagRetriever.js.map +1 -1
  30. package/dist/packlets/retrieve/temporalRetrievers.js +3 -3
  31. package/dist/packlets/retrieve/temporalRetrievers.js.map +1 -1
  32. package/dist/packlets/store/fileTreeMemoryStore.js +72 -16
  33. package/dist/packlets/store/fileTreeMemoryStore.js.map +1 -1
  34. package/dist/packlets/tools/memoryTools.js +104 -21
  35. package/dist/packlets/tools/memoryTools.js.map +1 -1
  36. package/dist/packlets/types/envelope.js +13 -1
  37. package/dist/packlets/types/envelope.js.map +1 -1
  38. package/dist/packlets/vector/inMemoryCosineIndex.js +22 -17
  39. package/dist/packlets/vector/inMemoryCosineIndex.js.map +1 -1
  40. package/dist/packlets/vector/vectorIndex.js.map +1 -1
  41. package/dist/test/unit/converters/antagonistRoundTrip.test.js +3 -3
  42. package/dist/test/unit/converters/antagonistRoundTrip.test.js.map +1 -1
  43. package/dist/test/unit/converters/envelopeConverter.test.js +125 -8
  44. package/dist/test/unit/converters/envelopeConverter.test.js.map +1 -1
  45. package/dist/test/unit/index/memoryIndex.test.js +87 -25
  46. package/dist/test/unit/index/memoryIndex.test.js.map +1 -1
  47. package/dist/test/unit/ingest/antagonistCycleAndParity.test.js +20 -16
  48. package/dist/test/unit/ingest/antagonistCycleAndParity.test.js.map +1 -1
  49. package/dist/test/unit/ingest/cycleGuard.test.js +28 -1
  50. package/dist/test/unit/ingest/cycleGuard.test.js.map +1 -1
  51. package/dist/test/unit/ingest/orchestrator.test.js +187 -45
  52. package/dist/test/unit/ingest/orchestrator.test.js.map +1 -1
  53. package/dist/test/unit/retrieve/linkTraversalRetriever.test.js +106 -31
  54. package/dist/test/unit/retrieve/linkTraversalRetriever.test.js.map +1 -1
  55. package/dist/test/unit/retrieve/retrievers.test.js +299 -37
  56. package/dist/test/unit/retrieve/retrievers.test.js.map +1 -1
  57. package/dist/test/unit/store/embedOnWrite.test.js +69 -12
  58. package/dist/test/unit/store/embedOnWrite.test.js.map +1 -1
  59. package/dist/test/unit/store/listScoped.test.js +109 -0
  60. package/dist/test/unit/store/listScoped.test.js.map +1 -0
  61. package/dist/test/unit/store/rankAxis.test.js +254 -0
  62. package/dist/test/unit/store/rankAxis.test.js.map +1 -0
  63. package/dist/test/unit/tools/memoryTools.test.js +280 -11
  64. package/dist/test/unit/tools/memoryTools.test.js.map +1 -1
  65. package/dist/test/unit/types/writePolicy.test.js +9 -2
  66. package/dist/test/unit/types/writePolicy.test.js.map +1 -1
  67. package/dist/test/unit/vector/inMemoryCosineIndex.test.js +95 -35
  68. package/dist/test/unit/vector/inMemoryCosineIndex.test.js.map +1 -1
  69. package/dist/test/unit/vector/vectorIndex.test.js +24 -15
  70. package/dist/test/unit/vector/vectorIndex.test.js.map +1 -1
  71. package/dist/ts-agent-memory.d.ts +384 -97
  72. package/etc/ts-agent-memory.api.md +64 -22
  73. package/lib/packlets/converters/envelopeConverter.d.ts +8 -1
  74. package/lib/packlets/converters/envelopeConverter.d.ts.map +1 -1
  75. package/lib/packlets/converters/envelopeConverter.js +18 -4
  76. package/lib/packlets/converters/envelopeConverter.js.map +1 -1
  77. package/lib/packlets/index/memoryIndex.d.ts +42 -10
  78. package/lib/packlets/index/memoryIndex.d.ts.map +1 -1
  79. package/lib/packlets/index/memoryIndex.js +58 -10
  80. package/lib/packlets/index/memoryIndex.js.map +1 -1
  81. package/lib/packlets/ingest/cycleGuard.d.ts +5 -5
  82. package/lib/packlets/ingest/cycleGuard.d.ts.map +1 -1
  83. package/lib/packlets/ingest/cycleGuard.js +13 -6
  84. package/lib/packlets/ingest/cycleGuard.js.map +1 -1
  85. package/lib/packlets/ingest/hostStages.d.ts +3 -3
  86. package/lib/packlets/ingest/hostStages.d.ts.map +1 -1
  87. package/lib/packlets/ingest/hostStages.js.map +1 -1
  88. package/lib/packlets/ingest/model.d.ts +25 -14
  89. package/lib/packlets/ingest/model.d.ts.map +1 -1
  90. package/lib/packlets/ingest/model.js.map +1 -1
  91. package/lib/packlets/ingest/orchestrator.d.ts +18 -4
  92. package/lib/packlets/ingest/orchestrator.d.ts.map +1 -1
  93. package/lib/packlets/ingest/orchestrator.js +93 -48
  94. package/lib/packlets/ingest/orchestrator.js.map +1 -1
  95. package/lib/packlets/retrieve/hybridRetriever.d.ts.map +1 -1
  96. package/lib/packlets/retrieve/hybridRetriever.js +12 -1
  97. package/lib/packlets/retrieve/hybridRetriever.js.map +1 -1
  98. package/lib/packlets/retrieve/linkTraversalRetriever.d.ts +18 -23
  99. package/lib/packlets/retrieve/linkTraversalRetriever.d.ts.map +1 -1
  100. package/lib/packlets/retrieve/linkTraversalRetriever.js +45 -56
  101. package/lib/packlets/retrieve/linkTraversalRetriever.js.map +1 -1
  102. package/lib/packlets/retrieve/recencyRetriever.js +2 -2
  103. package/lib/packlets/retrieve/recencyRetriever.js.map +1 -1
  104. package/lib/packlets/retrieve/retriever.d.ts +70 -11
  105. package/lib/packlets/retrieve/retriever.d.ts.map +1 -1
  106. package/lib/packlets/retrieve/retriever.js +52 -7
  107. package/lib/packlets/retrieve/retriever.js.map +1 -1
  108. package/lib/packlets/retrieve/semanticRetriever.d.ts.map +1 -1
  109. package/lib/packlets/retrieve/semanticRetriever.js +9 -3
  110. package/lib/packlets/retrieve/semanticRetriever.js.map +1 -1
  111. package/lib/packlets/retrieve/structuredFilterRetriever.js +2 -2
  112. package/lib/packlets/retrieve/structuredFilterRetriever.js.map +1 -1
  113. package/lib/packlets/retrieve/tagRetriever.js +2 -2
  114. package/lib/packlets/retrieve/tagRetriever.js.map +1 -1
  115. package/lib/packlets/retrieve/temporalRetrievers.js +3 -3
  116. package/lib/packlets/retrieve/temporalRetrievers.js.map +1 -1
  117. package/lib/packlets/store/fileTreeMemoryStore.d.ts +57 -3
  118. package/lib/packlets/store/fileTreeMemoryStore.d.ts.map +1 -1
  119. package/lib/packlets/store/fileTreeMemoryStore.js +72 -16
  120. package/lib/packlets/store/fileTreeMemoryStore.js.map +1 -1
  121. package/lib/packlets/tools/memoryTools.d.ts +24 -0
  122. package/lib/packlets/tools/memoryTools.d.ts.map +1 -1
  123. package/lib/packlets/tools/memoryTools.js +104 -21
  124. package/lib/packlets/tools/memoryTools.js.map +1 -1
  125. package/lib/packlets/types/envelope.d.ts +61 -8
  126. package/lib/packlets/types/envelope.d.ts.map +1 -1
  127. package/lib/packlets/types/envelope.js +14 -0
  128. package/lib/packlets/types/envelope.js.map +1 -1
  129. package/lib/packlets/vector/inMemoryCosineIndex.d.ts +9 -5
  130. package/lib/packlets/vector/inMemoryCosineIndex.d.ts.map +1 -1
  131. package/lib/packlets/vector/inMemoryCosineIndex.js +22 -17
  132. package/lib/packlets/vector/inMemoryCosineIndex.js.map +1 -1
  133. package/lib/packlets/vector/vectorIndex.d.ts +46 -20
  134. package/lib/packlets/vector/vectorIndex.d.ts.map +1 -1
  135. package/lib/packlets/vector/vectorIndex.js.map +1 -1
  136. package/lib/test/unit/converters/antagonistRoundTrip.test.js +3 -3
  137. package/lib/test/unit/converters/antagonistRoundTrip.test.js.map +1 -1
  138. package/lib/test/unit/converters/envelopeConverter.test.js +124 -7
  139. package/lib/test/unit/converters/envelopeConverter.test.js.map +1 -1
  140. package/lib/test/unit/index/memoryIndex.test.js +86 -24
  141. package/lib/test/unit/index/memoryIndex.test.js.map +1 -1
  142. package/lib/test/unit/ingest/antagonistCycleAndParity.test.js +20 -16
  143. package/lib/test/unit/ingest/antagonistCycleAndParity.test.js.map +1 -1
  144. package/lib/test/unit/ingest/cycleGuard.test.js +28 -1
  145. package/lib/test/unit/ingest/cycleGuard.test.js.map +1 -1
  146. package/lib/test/unit/ingest/orchestrator.test.js +186 -44
  147. package/lib/test/unit/ingest/orchestrator.test.js.map +1 -1
  148. package/lib/test/unit/retrieve/linkTraversalRetriever.test.js +106 -31
  149. package/lib/test/unit/retrieve/linkTraversalRetriever.test.js.map +1 -1
  150. package/lib/test/unit/retrieve/retrievers.test.js +298 -36
  151. package/lib/test/unit/retrieve/retrievers.test.js.map +1 -1
  152. package/lib/test/unit/store/embedOnWrite.test.js +68 -11
  153. package/lib/test/unit/store/embedOnWrite.test.js.map +1 -1
  154. package/lib/test/unit/store/listScoped.test.d.ts +2 -0
  155. package/lib/test/unit/store/listScoped.test.d.ts.map +1 -0
  156. package/lib/test/unit/store/listScoped.test.js +111 -0
  157. package/lib/test/unit/store/listScoped.test.js.map +1 -0
  158. package/lib/test/unit/store/rankAxis.test.d.ts +2 -0
  159. package/lib/test/unit/store/rankAxis.test.d.ts.map +1 -0
  160. package/lib/test/unit/store/rankAxis.test.js +256 -0
  161. package/lib/test/unit/store/rankAxis.test.js.map +1 -0
  162. package/lib/test/unit/tools/memoryTools.test.js +280 -11
  163. package/lib/test/unit/tools/memoryTools.test.js.map +1 -1
  164. package/lib/test/unit/types/writePolicy.test.js +9 -2
  165. package/lib/test/unit/types/writePolicy.test.js.map +1 -1
  166. package/lib/test/unit/vector/inMemoryCosineIndex.test.js +95 -35
  167. package/lib/test/unit/vector/inMemoryCosineIndex.test.js.map +1 -1
  168. package/lib/test/unit/vector/vectorIndex.test.js +24 -15
  169. package/lib/test/unit/vector/vectorIndex.test.js.map +1 -1
  170. package/package.json +7 -7
  171. package/rush-logs/ts-agent-memory.build.cache.log +1 -1
  172. package/rush-logs/ts-agent-memory.build.log +2 -2
  173. package/src/packlets/converters/envelopeConverter.ts +27 -4
  174. package/src/packlets/index/memoryIndex.ts +86 -22
  175. package/src/packlets/ingest/cycleGuard.ts +22 -11
  176. package/src/packlets/ingest/hostStages.ts +3 -3
  177. package/src/packlets/ingest/model.ts +25 -14
  178. package/src/packlets/ingest/orchestrator.ts +143 -67
  179. package/src/packlets/retrieve/hybridRetriever.ts +14 -1
  180. package/src/packlets/retrieve/linkTraversalRetriever.ts +51 -62
  181. package/src/packlets/retrieve/recencyRetriever.ts +3 -3
  182. package/src/packlets/retrieve/retriever.ts +97 -13
  183. package/src/packlets/retrieve/semanticRetriever.ts +10 -5
  184. package/src/packlets/retrieve/structuredFilterRetriever.ts +3 -3
  185. package/src/packlets/retrieve/tagRetriever.ts +3 -3
  186. package/src/packlets/retrieve/temporalRetrievers.ts +3 -3
  187. package/src/packlets/store/fileTreeMemoryStore.ts +117 -12
  188. package/src/packlets/tools/memoryTools.ts +152 -25
  189. package/src/packlets/types/envelope.ts +66 -8
  190. package/src/packlets/vector/inMemoryCosineIndex.ts +45 -22
  191. package/src/packlets/vector/vectorIndex.ts +47 -20
  192. package/src/test/unit/converters/antagonistRoundTrip.test.ts +3 -3
  193. package/src/test/unit/converters/envelopeConverter.test.ts +168 -11
  194. package/src/test/unit/index/memoryIndex.test.ts +99 -14
  195. package/src/test/unit/ingest/antagonistCycleAndParity.test.ts +23 -18
  196. package/src/test/unit/ingest/cycleGuard.test.ts +44 -2
  197. package/src/test/unit/ingest/orchestrator.test.ts +234 -41
  198. package/src/test/unit/retrieve/linkTraversalRetriever.test.ts +134 -35
  199. package/src/test/unit/retrieve/retrievers.test.ts +381 -25
  200. package/src/test/unit/store/embedOnWrite.test.ts +83 -11
  201. package/src/test/unit/store/listScoped.test.ts +138 -0
  202. package/src/test/unit/store/rankAxis.test.ts +349 -0
  203. package/src/test/unit/tools/memoryTools.test.ts +362 -13
  204. package/src/test/unit/types/writePolicy.test.ts +11 -2
  205. package/src/test/unit/vector/inMemoryCosineIndex.test.ts +115 -39
  206. package/src/test/unit/vector/vectorIndex.test.ts +33 -17
  207. package/temp/build/lint/_eslint-5eVG3S6w.json +41 -33
  208. package/temp/build/typescript/ts_8nwakTlr.json +1 -1
  209. package/temp/ts-agent-memory.api.json +1080 -136
  210. package/temp/ts-agent-memory.api.md +64 -22
@@ -33,6 +33,7 @@ class FileTreeMemoryStore {
33
33
  this._registry = params.registry;
34
34
  this._writePolicies = params.writePolicies;
35
35
  this._codecs = params.codecs;
36
+ this._rankProjectors = params.rankProjectors;
36
37
  this._defaultCodec = params.defaultCodec;
37
38
  this._defaultPolicy = params.defaultPolicy;
38
39
  this._scopeEncoding = params.scopeEncoding;
@@ -54,19 +55,20 @@ class FileTreeMemoryStore {
54
55
  */
55
56
  static create(params) {
56
57
  return types_1.KnowledgeLwwPolicy.create().onSuccess((defaultPolicy) => index_1.MemoryIndex.create().onSuccess((index) => {
57
- var _a, _b, _c, _d, _e, _f;
58
+ var _a, _b, _c, _d, _e, _f, _g;
58
59
  const store = new FileTreeMemoryStore({
59
60
  root: params.root,
60
61
  registry: params.registry,
61
62
  writePolicies: (_a = params.writePolicies) !== null && _a !== void 0 ? _a : new Map(),
62
63
  codecs: (_b = params.codecs) !== null && _b !== void 0 ? _b : new Map(),
64
+ rankProjectors: (_c = params.rankProjectors) !== null && _c !== void 0 ? _c : new Map(),
63
65
  defaultCodec: params.defaultCodec,
64
66
  defaultPolicy,
65
- scopeEncoding: (_c = params.scopeEncoding) !== null && _c !== void 0 ? _c : scopeEncoding_1.defaultMemoryScopeEncoding,
66
- clock: (_d = params.clock) !== null && _d !== void 0 ? _d : Date.now,
67
+ scopeEncoding: (_d = params.scopeEncoding) !== null && _d !== void 0 ? _d : scopeEncoding_1.defaultMemoryScopeEncoding,
68
+ clock: (_e = params.clock) !== null && _e !== void 0 ? _e : Date.now,
67
69
  index,
68
- observers: (_e = params.observers) !== null && _e !== void 0 ? _e : [],
69
- logger: (_f = params.logger) !== null && _f !== void 0 ? _f : new ts_utils_1.Logging.NoOpLogger(),
70
+ observers: (_f = params.observers) !== null && _f !== void 0 ? _f : [],
71
+ logger: (_g = params.logger) !== null && _g !== void 0 ? _g : new ts_utils_1.Logging.NoOpLogger(),
70
72
  vectorIndex: params.vectorIndex,
71
73
  embed: params.embed
72
74
  });
@@ -124,6 +126,21 @@ class FileTreeMemoryStore {
124
126
  }
125
127
  return (0, ts_utils_1.succeed)(FileTreeMemoryStore._projectAsOf(matches, filter.asOf));
126
128
  }
129
+ /** {@inheritDoc IMemoryStore.listScoped} */
130
+ async listScoped() {
131
+ // The derived index already carries each record's scope
132
+ // ({@link IIndexedMemoryRecord.scope}), so the scoped projection is a direct
133
+ // map — the record's `(scope, id)` is exactly the address the vector index
134
+ // keys on. No filter/temporal projection: the seam re-embeds the whole vault.
135
+ return (0, ts_utils_1.succeed)(this._index.entries().map((entry) => ({
136
+ target: { scope: entry.scope, id: entry.record.envelope.id },
137
+ record: entry.record
138
+ })));
139
+ }
140
+ /** {@inheritDoc IMemoryStore.asRecordSource} */
141
+ asRecordSource() {
142
+ return { list: () => this.listScoped() };
143
+ }
127
144
  /**
128
145
  * Collapse temporal records to the single version valid at `asOf` per entity;
129
146
  * non-temporal records are timeless and pass through unchanged (valid-time
@@ -370,7 +387,8 @@ class FileTreeMemoryStore {
370
387
  return (0, ts_utils_1.fail)(`memory put: rejected by policy: ${decision.reason}`);
371
388
  }
372
389
  return this._buildRecord(record, body, existing, policy, hash)
373
- .thenOnSuccess((built) => this._embedOnWrite(built))
390
+ .onSuccess((built) => (0, ts_utils_1.succeed)(this._stampRank(built)))
391
+ .thenOnSuccess((built) => this._embedOnWrite(built, scope))
374
392
  .onSuccess((embeddedBuilt) => this._persist(embeddedBuilt, scope, idStem))
375
393
  .thenOnSuccess(async (persisted) => {
376
394
  // Everything after the authoritative `_persist` commit is best-effort and
@@ -380,7 +398,7 @@ class FileTreeMemoryStore {
380
398
  // it), and only the successfully-evicted ids flow onward;
381
399
  // - vector pruning of the evicted cohort is likewise best-effort.
382
400
  const evicted = this._applyEvictions(decision, scope);
383
- await this._removeEvictedVectors(evicted);
401
+ await this._removeEvictedVectors(evicted, scope);
384
402
  return (0, ts_utils_1.succeed)({ record: persisted, evicted });
385
403
  });
386
404
  }
@@ -396,17 +414,18 @@ class FileTreeMemoryStore {
396
414
  * Always succeeds (`Result` is the chain's shape, never a vector-induced
397
415
  * failure).
398
416
  */
399
- async _embedOnWrite(built) {
417
+ async _embedOnWrite(built, scope) {
400
418
  if (this._vectorIndex === undefined || this._embed === undefined) {
401
419
  return (0, ts_utils_1.succeed)(built);
402
420
  }
403
421
  const vectorIndex = this._vectorIndex;
404
422
  const embed = this._embed;
423
+ const target = { scope, id: built.envelope.id };
405
424
  const embedded = await this._tryVectorOp(() => embed(built), `embedding '${built.envelope.id}'`);
406
425
  if (embedded.isFailure()) {
407
426
  return (0, ts_utils_1.succeed)(built);
408
427
  }
409
- const added = await this._tryVectorOp(() => vectorIndex.add(built.envelope.id, embedded.value), `vector add for '${built.envelope.id}'`);
428
+ const added = await this._tryVectorOp(() => vectorIndex.add(target, embedded.value), `vector add for '${built.envelope.id}'`);
410
429
  if (added.isFailure()) {
411
430
  return (0, ts_utils_1.succeed)(built);
412
431
  }
@@ -435,10 +454,15 @@ class FileTreeMemoryStore {
435
454
  }
436
455
  return evicted;
437
456
  }
438
- /** Best-effort vector removal for each evicted record (never fails the put). */
439
- async _removeEvictedVectors(evicted) {
457
+ /**
458
+ * Best-effort vector removal for each evicted record (never fails the put).
459
+ * Every evicted record is in the same `scope` as the incoming write (the
460
+ * cull-oldest cohort is the incoming record's `(scope, kind)` cohort), so that
461
+ * scope qualifies each removal target.
462
+ */
463
+ async _removeEvictedVectors(evicted, scope) {
440
464
  for (const id of evicted) {
441
- await this._removeVectorBestEffort(id);
465
+ await this._removeVectorBestEffort({ scope, id });
442
466
  }
443
467
  }
444
468
  /**
@@ -465,12 +489,12 @@ class FileTreeMemoryStore {
465
489
  * behaves byte-identically. Failures are logged, never surfaced — a committed
466
490
  * delete/eviction must not fail because a derived index could not be pruned.
467
491
  */
468
- async _removeVectorBestEffort(id) {
492
+ async _removeVectorBestEffort(target) {
469
493
  if (this._vectorIndex === undefined || this._embed === undefined) {
470
494
  return;
471
495
  }
472
496
  const vectorIndex = this._vectorIndex;
473
- await this._tryVectorOp(() => vectorIndex.remove(id), `vector removal for '${id}'`);
497
+ await this._tryVectorOp(() => vectorIndex.remove(target), `vector removal for '${target.id}'`);
474
498
  }
475
499
  /**
476
500
  * Build the record to persist. On a first write the incoming envelope is the
@@ -541,7 +565,7 @@ class FileTreeMemoryStore {
541
565
  return this._deleteFile(scope, idStem)
542
566
  .onSuccess(() => this._index.patch('delete', { scope, record: existing }))
543
567
  .thenOnSuccess(async () => {
544
- await this._removeVectorBestEffort(existing.envelope.id);
568
+ await this._removeVectorBestEffort({ scope, id: existing.envelope.id });
545
569
  return (0, ts_utils_1.succeed)(existing.envelope.id);
546
570
  });
547
571
  });
@@ -626,7 +650,8 @@ class FileTreeMemoryStore {
626
650
  .encodeVersion(entityId, seq)
627
651
  .withErrorFormat((msg) => `memory put '${entityId}': ${msg}`)
628
652
  .thenOnSuccess((versionStem) => this._buildVersionedRecord(record, body, current, policy, hash, versionStem, validAt, now, seq)
629
- .thenOnSuccess((built) => this._embedOnWrite(built))
653
+ .onSuccess((built) => (0, ts_utils_1.succeed)(this._stampRank(built)))
654
+ .thenOnSuccess((built) => this._embedOnWrite(built, scope))
630
655
  .onSuccess((embeddedBuilt) => this._persist(embeddedBuilt, scope, versionStem))
631
656
  .onSuccess((persisted) => this._invalidateCurrents(scope, priorCurrents, validAt, now).onSuccess(() => (0, ts_utils_1.succeed)(persisted)))
632
657
  .onSuccess((persisted) => (0, ts_utils_1.succeed)({ record: persisted, evicted: [] })));
@@ -794,6 +819,37 @@ class FileTreeMemoryStore {
794
819
  _contentHash(kind, body, links) {
795
820
  return this._hasher.computeHash({ kind, body, links });
796
821
  }
822
+ /**
823
+ * Stamp the store-computed {@link IMemoryEnvelope.rank} onto a fully-built,
824
+ * fully-stamped record by running the kind's registered {@link RankProjector}.
825
+ * Runs on the SAME resolved (post-merge) record whose `contentHash` was just
826
+ * computed, so `rank` is always consistent with the current body — no separate
827
+ * write path and no consumer write-discipline rule. A no-op pass-through
828
+ * (byte-identical record) when the kind has no projector — the additive,
829
+ * zero-overhead-when-unwired default. The projector is a host callback: a throw
830
+ * is logged at `warn` and the record is stamped with NO `rank` (the field is
831
+ * explicitly cleared, so a throw on an update drops a now-stale prior rank rather
832
+ * than preserving it), so a ranking bug never loses an authoritative write.
833
+ */
834
+ _stampRank(record) {
835
+ const projector = this._rankProjectors.get(record.envelope.kind);
836
+ if (projector === undefined) {
837
+ return record;
838
+ }
839
+ try {
840
+ const rank = projector(record);
841
+ return { envelope: Object.assign(Object.assign({}, record.envelope), { rank }), body: record.body };
842
+ }
843
+ catch (err) {
844
+ this._warnSwallowed(`memory put '${record.envelope.id}': rank projector threw (swallowed; rank cleared): ${String(err)}`);
845
+ // Explicitly CLEAR `rank` (not `return record`): on an update the merged
846
+ // envelope carries the prior version's `rank` (the write-policy merge does
847
+ // not touch `rank`), so returning it verbatim would keep a stale value
848
+ // inconsistent with the revised body. Clearing honors the staleness
849
+ // contract — an uncomputable rank means the record sorts last as "unranked".
850
+ return { envelope: Object.assign(Object.assign({}, record.envelope), { rank: undefined }), body: record.body };
851
+ }
852
+ }
797
853
  _codecFor(kind) {
798
854
  var _a;
799
855
  const codec = (_a = this._codecs.get(kind)) !== null && _a !== void 0 ? _a : this._defaultCodec;