@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
@@ -97,11 +97,20 @@ class MemoryIngestOrchestrator {
97
97
  return (0, ts_utils_1.fail)(`ingest '${item.id}': failed to snapshot store: ${snapshotResult.message}`);
98
98
  }
99
99
  const snapshot = snapshotResult.value;
100
- const byId = MemoryIngestOrchestrator._indexById(snapshot);
100
+ // Resolve every snapshot record's scope-qualified address ONCE, then index it
101
+ // by the canonical scoped key. The single `byKey` view drives BOTH the edge
102
+ // path (validation + cycle guard) AND the verdict/similarity target lookups —
103
+ // so a filename stem reused across scopes never aliases on any path.
104
+ const scopedResult = this._scopeRecords(snapshot);
105
+ if (scopedResult.isFailure()) {
106
+ return (0, ts_utils_1.fail)(`ingest '${item.id}': ${scopedResult.message}`);
107
+ }
108
+ const scoped = scopedResult.value;
109
+ const byKey = new Map(scoped.map((s) => [(0, types_1.edgeTargetKey)(s.address), s.record]));
101
110
  // Stage 3b + 4: validate each body and resolve a verdict/plan.
102
111
  const plans = [];
103
112
  for (const candidate of candidates) {
104
- const planResult = await this._planCandidate(item, candidate, snapshot, byId);
113
+ const planResult = await this._planCandidate(item, candidate, snapshot, byKey);
105
114
  if (planResult.isFailure()) {
106
115
  return (0, ts_utils_1.fail)(planResult.message);
107
116
  }
@@ -109,7 +118,7 @@ class MemoryIngestOrchestrator {
109
118
  }
110
119
  // Stage 5: relate over the writable candidates, validate + cycle-guard.
111
120
  const writablePlans = plans.filter((plan) => plan.verdict.verdict !== 'duplicate-of');
112
- const edgesResult = await this._relate(item, writablePlans, snapshot, byId);
121
+ const edgesResult = await this._relate(item, writablePlans, scoped, byKey);
113
122
  if (edgesResult.isFailure()) {
114
123
  return (0, ts_utils_1.fail)(edgesResult.message);
115
124
  }
@@ -126,7 +135,7 @@ class MemoryIngestOrchestrator {
126
135
  return (0, ts_utils_1.succeed)({ item, records });
127
136
  }
128
137
  /** Stage 3b + 4 for one candidate: validate body, resolve address, resolve verdict. */
129
- async _planCandidate(item, candidate, snapshot, byId) {
138
+ async _planCandidate(item, candidate, snapshot, byKey) {
130
139
  const kind = candidate.envelope.kind;
131
140
  // Stage 3b: the typed validation boundary — no unchecked host body reaches the store.
132
141
  const bodyResult = this._registry
@@ -142,7 +151,7 @@ class MemoryIngestOrchestrator {
142
151
  return (0, ts_utils_1.fail)(`ingest '${item.id}': ${addrResult.message}`);
143
152
  }
144
153
  const addr = addrResult.value;
145
- return (await this._resolveVerdict(candidate, kind, body, addr, snapshot, byId)).onSuccess((verdict) => this._planFromVerdict(item, candidate, addr, verdict, byId));
154
+ return (await this._resolveVerdict(candidate, kind, body, addr, snapshot, byKey)).onSuccess((verdict) => this._planFromVerdict(item, candidate, addr, verdict, byKey));
146
155
  }
147
156
  /**
148
157
  * Turn a resolved verdict into a candidate plan. A `new` verdict writes under the
@@ -153,36 +162,42 @@ class MemoryIngestOrchestrator {
153
162
  * candidate's kind (a cross-kind target would write to the wrong scope). Only
154
163
  * `merge-into` re-addresses the write to the target's entity.
155
164
  */
156
- _planFromVerdict(item, candidate, addr, verdict, byId) {
165
+ _planFromVerdict(item, candidate, addr, verdict, byKey) {
157
166
  if (verdict.verdict === 'new') {
158
167
  return types_1.Convert.memoryId.convert(addr.idStem).onSuccess((refId) => (0, ts_utils_1.succeed)({
159
168
  candidate,
160
169
  writeAddress: addr,
161
170
  writeEntityId: candidate.envelope.entityId,
162
171
  refId,
172
+ refTarget: { scope: addr.scope, id: refId },
163
173
  verdict
164
174
  }));
165
175
  }
166
176
  // duplicate-of | supersede | merge-into: the target must exist and share the
167
- // candidate's kind.
168
- const target = byId.get(verdict.target);
177
+ // candidate's kind. Lookup is on the canonical scoped key, so a stem reused
178
+ // across scopes binds only the record the verdict actually named.
179
+ const target = byKey.get((0, types_1.edgeTargetKey)(verdict.target));
169
180
  if (target === undefined) {
170
- return (0, ts_utils_1.fail)(`ingest '${item.id}': ${verdict.verdict} target '${verdict.target}' does not exist in the store`);
181
+ return (0, ts_utils_1.fail)(`ingest '${item.id}': ${verdict.verdict} target '${MemoryIngestOrchestrator._formatTarget(verdict.target)}' does not exist in the store`);
171
182
  }
172
183
  if (target.envelope.kind !== candidate.envelope.kind) {
173
- return (0, ts_utils_1.fail)(`ingest '${item.id}': ${verdict.verdict} target '${verdict.target}' is kind '${target.envelope.kind}' but the candidate is kind '${candidate.envelope.kind}'`);
184
+ return (0, ts_utils_1.fail)(`ingest '${item.id}': ${verdict.verdict} target '${MemoryIngestOrchestrator._formatTarget(verdict.target)}' is kind '${target.envelope.kind}' but the candidate is kind '${candidate.envelope.kind}'`);
174
185
  }
175
186
  if (verdict.verdict === 'merge-into') {
176
187
  // Re-address the write to the target's entity, carrying the target record so
177
188
  // stage 6 can UNION its existing tags/links (never overwrite them).
178
189
  const targetEntityId = target.envelope.entityId;
179
- return this._resolveAddress(targetEntityId, target.envelope.kind)
180
- .withErrorFormat((msg) => `ingest '${item.id}': ${msg}`)
181
- .onSuccess((targetAddr) => types_1.Convert.memoryId.convert(targetAddr.idStem).onSuccess((refId) => (0, ts_utils_1.succeed)({
190
+ // The merge target is a snapshot record, and `_scopeRecords` already proved
191
+ // every snapshot record's address resolves before planning runs — so this
192
+ // re-resolve (needed for the full codec result: scope + idStem + isVersioned)
193
+ // cannot fail. No error-context wrap is warranted; a failure here would be a
194
+ // logic contradiction, not a user-facing condition.
195
+ return this._resolveAddress(targetEntityId, target.envelope.kind).onSuccess((targetAddr) => types_1.Convert.memoryId.convert(targetAddr.idStem).onSuccess((refId) => (0, ts_utils_1.succeed)({
182
196
  candidate,
183
197
  writeAddress: targetAddr,
184
198
  writeEntityId: targetEntityId,
185
199
  refId,
200
+ refTarget: { scope: targetAddr.scope, id: refId },
186
201
  verdict,
187
202
  mergeTarget: target
188
203
  })));
@@ -193,6 +208,7 @@ class MemoryIngestOrchestrator {
193
208
  writeAddress: addr,
194
209
  writeEntityId: candidate.envelope.entityId,
195
210
  refId,
211
+ refTarget: { scope: addr.scope, id: refId },
196
212
  verdict
197
213
  }));
198
214
  }
@@ -203,25 +219,27 @@ class MemoryIngestOrchestrator {
203
219
  * surface over-threshold neighbors, and dispatch to the {@link IEntityResolver}.
204
220
  * Otherwise the verdict is `new` (the exact-only fall-back path).
205
221
  */
206
- async _resolveVerdict(candidate, kind, body, addr, snapshot, byId) {
222
+ async _resolveVerdict(candidate, kind, body, addr, snapshot, byKey) {
207
223
  return this._findExactMatch(kind, body, addr.scope, snapshot).thenOnSuccess(async (matchId) => {
208
224
  if (matchId !== undefined) {
209
- return (0, ts_utils_1.succeed)({ verdict: 'duplicate-of', target: matchId });
225
+ // The exact-match cohort is filtered to `addr.scope`, so the match lives
226
+ // under that scope — its scope-qualified target is `(addr.scope, matchId)`.
227
+ return (0, ts_utils_1.succeed)({ verdict: 'duplicate-of', target: { scope: addr.scope, id: matchId } });
210
228
  }
211
229
  const layer2 = this._similarity;
212
230
  if (layer2 === undefined) {
213
231
  // No layer-2: exact-only fall-back (the deterministic-identity host path).
214
232
  return (0, ts_utils_1.succeed)({ verdict: 'new' });
215
233
  }
216
- return this._resolveViaSimilarity(candidate, addr, body, layer2, byId);
234
+ return this._resolveViaSimilarity(candidate, addr, body, layer2, byKey);
217
235
  });
218
236
  }
219
237
  /** Layer-2 similarity candidate-gen + resolver dispatch. */
220
- async _resolveViaSimilarity(candidate, addr, body, wiring, byId) {
221
- return MemoryIngestOrchestrator._provisionalRecord(candidate, addr.idStem, body).thenOnSuccess((provisional) => this._resolveViaSimilarityEmbedded(candidate, addr, wiring, byId, provisional));
238
+ async _resolveViaSimilarity(candidate, addr, body, wiring, byKey) {
239
+ return MemoryIngestOrchestrator._provisionalRecord(candidate, addr.idStem, body).thenOnSuccess((provisional) => this._resolveViaSimilarityEmbedded(candidate, addr, wiring, byKey, provisional));
222
240
  }
223
241
  /** Layer-2 continuation once the candidate has a provisional record to embed. */
224
- async _resolveViaSimilarityEmbedded(candidate, addr, wiring, byId, provisional) {
242
+ async _resolveViaSimilarityEmbedded(candidate, addr, wiring, byKey, provisional) {
225
243
  const embedded = await this._capture(() => wiring.embed(provisional), `ingest '${candidate.envelope.entityId}': embed candidate`);
226
244
  if (embedded.isFailure()) {
227
245
  return (0, ts_utils_1.fail)(embedded.message);
@@ -232,12 +250,20 @@ class MemoryIngestOrchestrator {
232
250
  }
233
251
  const similar = [];
234
252
  for (const hit of queried.value) {
235
- if (hit.score < this._similarityThreshold || hit.id === addr.idStem) {
253
+ // Skip below-threshold hits and the candidate's OWN scope-qualified address
254
+ // (a re-ingest of the same entity must not dedup against its prior version).
255
+ // Both the scope AND the id must match to be "self" — a same-stem record in
256
+ // another scope is a legitimate distinct neighbor. This field-equality is
257
+ // exactly equivalent to comparing `edgeTargetKey(hit.target)` against the
258
+ // candidate's own key (edgeTargetKey is pure and injective on `(scope, id)`),
259
+ // so this one site reads the components directly rather than re-keying.
260
+ const isSelf = hit.target.scope === addr.scope && hit.target.id === addr.idStem;
261
+ if (hit.score < this._similarityThreshold || isSelf) {
236
262
  continue;
237
263
  }
238
- const record = byId.get(hit.id);
264
+ const record = byKey.get((0, types_1.edgeTargetKey)(hit.target));
239
265
  if (record !== undefined) {
240
- similar.push({ id: hit.id, record, score: hit.score });
266
+ similar.push({ target: hit.target, record, score: hit.score });
241
267
  }
242
268
  }
243
269
  if (similar.length === 0) {
@@ -278,22 +304,25 @@ class MemoryIngestOrchestrator {
278
304
  return this._hasher.computeHash({ kind, body });
279
305
  }
280
306
  /** Stage 5 — relate (host), validate edges, and run the write-time cycle guard. */
281
- async _relate(item, writablePlans, snapshot, byId) {
307
+ async _relate(item, writablePlans, scoped, byKey) {
282
308
  const relationCandidates = writablePlans.map((plan) => ({
283
309
  candidate: plan.candidate,
284
- id: plan.refId
310
+ id: plan.refTarget
285
311
  }));
286
312
  const proposed = await this._capture(() => this._relationExtractor.relate({ item, candidates: relationCandidates }), `ingest '${item.id}': relate`);
287
313
  if (proposed.isFailure()) {
288
314
  return proposed;
289
315
  }
290
- const refIds = new Set(writablePlans.map((plan) => plan.refId));
291
- const validation = this._validateEdges(item, proposed.value, refIds, byId);
316
+ // refIds and the existing-record view (`byKey`, shared with the verdict path)
317
+ // both key on the canonical scoped address, so a stem reused across scopes
318
+ // never aliases.
319
+ const refIds = new Set(writablePlans.map((plan) => (0, types_1.edgeTargetKey)(plan.refTarget)));
320
+ const validation = this._validateEdges(item, proposed.value, refIds, byKey);
292
321
  if (validation.isFailure()) {
293
322
  return (0, ts_utils_1.fail)(validation.message);
294
323
  }
295
324
  if (this._cycleGuard === 'reject') {
296
- const guard = (0, cycleGuard_1.assertNoCycles)(MemoryIngestOrchestrator._existingEdges(snapshot), proposed.value.map((e) => ({ source: e.source, target: e.edge.target, type: e.edge.type })));
325
+ const guard = (0, cycleGuard_1.assertNoCycles)(MemoryIngestOrchestrator._existingEdges(scoped), proposed.value.map((e) => ({ source: e.source, target: e.edge.target, type: e.edge.type })));
297
326
  if (guard.isFailure()) {
298
327
  return (0, ts_utils_1.fail)(`ingest '${item.id}': ${guard.message}`);
299
328
  }
@@ -302,22 +331,25 @@ class MemoryIngestOrchestrator {
302
331
  }
303
332
  /**
304
333
  * Validate stage-5 edges: each `source` must be a candidate being written; each
305
- * `target` must resolve to a sibling candidate or an existing store record.
334
+ * `target` must resolve to a sibling candidate or an existing store record. All
335
+ * matching is on the canonical scope-qualified address.
306
336
  */
307
- _validateEdges(item, edges, refIds, byId) {
337
+ _validateEdges(item, edges, refIds, byKey) {
308
338
  return (0, ts_utils_1.mapResults)(edges.map((edge) => {
309
- if (!refIds.has(edge.source)) {
310
- return (0, ts_utils_1.fail)(`ingest '${item.id}': edge source '${edge.source}' is not a candidate being written`);
339
+ if (!refIds.has((0, types_1.edgeTargetKey)(edge.source))) {
340
+ return (0, ts_utils_1.fail)(`ingest '${item.id}': edge source '${MemoryIngestOrchestrator._formatTarget(edge.source)}' is not a candidate being written`);
311
341
  }
312
- if (!refIds.has(edge.edge.target) && byId.get(edge.edge.target) === undefined) {
313
- return (0, ts_utils_1.fail)(`ingest '${item.id}': edge target '${edge.edge.target}' resolves to neither a sibling candidate nor an existing record`);
342
+ const targetKey = (0, types_1.edgeTargetKey)(edge.edge.target);
343
+ if (!refIds.has(targetKey) && byKey.get(targetKey) === undefined) {
344
+ return (0, ts_utils_1.fail)(`ingest '${item.id}': edge target '${MemoryIngestOrchestrator._formatTarget(edge.edge.target)}' resolves to neither a sibling candidate nor an existing record`);
314
345
  }
315
346
  return (0, ts_utils_1.succeed)(true);
316
347
  })).onSuccess(() => (0, ts_utils_1.succeed)(true));
317
348
  }
318
349
  /** Stage 6 — stamp provenance + edges, admit through the store, record the outcome. */
319
350
  async _loadCandidate(item, plan, allEdges) {
320
- const myEdges = allEdges.filter((e) => e.source === plan.refId);
351
+ const refKey = (0, types_1.edgeTargetKey)(plan.refTarget);
352
+ const myEdges = allEdges.filter((e) => (0, types_1.edgeTargetKey)(e.source) === refKey);
321
353
  if (plan.verdict.verdict === 'duplicate-of') {
322
354
  // No write: the existing target satisfied the candidate. The target id is a
323
355
  // typed field of the narrowed `duplicate-of` verdict — no cast, no guard.
@@ -325,7 +357,7 @@ class MemoryIngestOrchestrator {
325
357
  candidate: plan.candidate,
326
358
  resolution: plan.verdict,
327
359
  disposition: 'deduped',
328
- id: plan.verdict.target,
360
+ id: plan.verdict.target.id,
329
361
  edges: myEdges
330
362
  });
331
363
  }
@@ -405,24 +437,37 @@ class MemoryIngestOrchestrator {
405
437
  return (0, ts_utils_1.fail)(message);
406
438
  }
407
439
  }
408
- /** Index a record snapshot by id (last write wins on an id collision across scopes). */
409
- static _indexById(records) {
410
- const byId = new Map();
411
- for (const record of records) {
412
- byId.set(record.envelope.id, record);
413
- }
414
- return byId;
415
- }
416
- /** Every existing outbound edge in the snapshot, as cycle-guard edges. */
417
- static _existingEdges(records) {
440
+ /**
441
+ * Every existing outbound edge in the snapshot, as cycle-guard edges. The
442
+ * source is the record's own scope-qualified address (already resolved by
443
+ * {@link MemoryIngestOrchestrator._scopeRecords}); the target is the edge's
444
+ * own scoped target. Both ends are scoped so the guard never conflates a stem
445
+ * shared across scopes into one graph node.
446
+ */
447
+ static _existingEdges(scoped) {
418
448
  const edges = [];
419
- for (const record of records) {
420
- for (const edge of record.envelope.links) {
421
- edges.push({ source: record.envelope.id, target: edge.target, type: edge.type });
449
+ for (const s of scoped) {
450
+ for (const edge of s.record.envelope.links) {
451
+ edges.push({ source: s.address, target: edge.target, type: edge.type });
422
452
  }
423
453
  }
424
454
  return edges;
425
455
  }
456
+ /**
457
+ * Resolve every snapshot record's scope-qualified `(scope, id)` address via its
458
+ * registered codec. Fails loudly if a record's kind has no resolvable codec —
459
+ * the edge path cannot place an un-scopeable record in the graph, and a missing
460
+ * codec for a stored kind is a real misconfiguration, not something to paper over.
461
+ */
462
+ _scopeRecords(records) {
463
+ return (0, ts_utils_1.mapResults)(records.map((record) => this._resolveAddress(record.envelope.entityId, record.envelope.kind)
464
+ .withErrorFormat((msg) => `cannot resolve scope for stored record '${record.envelope.id}': ${msg}`)
465
+ .onSuccess((addr) => (0, ts_utils_1.succeed)({ address: { scope: addr.scope, id: record.envelope.id }, record }))));
466
+ }
467
+ /** Human-readable `scope/id` rendering of a scoped target for edge-validation diagnostics. */
468
+ static _formatTarget(target) {
469
+ return `${target.scope}/${target.id}`;
470
+ }
426
471
  /** A provisional record for embedding a candidate (placeholder txn-time fields). */
427
472
  static _provisionalRecord(candidate, idStem, body) {
428
473
  return types_1.Convert.memoryId.convert(idStem).onSuccess((id) => {
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../../src/packlets/ingest/orchestrator.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n * SPDX-License-Identifier: MIT\n */\n\nimport { Hash, Logging, Result, fail, mapResults, succeed } from '@fgv/ts-utils';\nimport {\n Convert,\n EntityId,\n IEdge,\n IIdentityCodec,\n IIdentityCodecResult,\n IMemoryEnvelope,\n IMemoryRecord,\n IProvenance,\n Kind,\n LinkType,\n MemoryId,\n MemoryScopeKey,\n Tag,\n isTemporalRecord,\n isVersionCurrent\n} from '../types';\nimport { IBodyConverterRegistry } from '../converters';\nimport { IMemoryStore } from '../store';\nimport { IVectorIndex, MemoryEmbedder } from '../vector';\nimport { ICycleGuardEdge, assertNoCycles } from './cycleGuard';\nimport {\n IEntityResolver,\n IFactExtractor,\n IMemoryClassifier,\n IRelationCandidate,\n IRelationExtractor\n} from './hostStages';\nimport {\n ICandidateEdge,\n ICandidateRecord,\n IEntityResolutionCandidate,\n IIngestItem,\n IIngestItemResult,\n IIngestedRecordResult,\n IMemoryClassification,\n IngestDisposition,\n ResolutionVerdict\n} from './model';\n\n/**\n * The provenance source stamped on every record the ingest pipeline writes.\n * @public\n */\nexport const HOST_INGEST_PROVENANCE_SOURCE: string = 'host-ingest';\n\n/**\n * The link type whose presence on a temporal-kind candidate fires the\n * contradicts→temporal-versioned interlock.\n * @public\n */\nexport const CONTRADICTS_LINK_TYPE: LinkType = 'contradicts' as LinkType;\n\n/**\n * The default stage-4 layer-2 cosine similarity threshold (design note §2). A\n * near-duplicate candidate is surfaced to the {@link IEntityResolver} only when\n * its nearest neighbor scores `>= 0.85`.\n * @public\n */\nexport const DEFAULT_SIMILARITY_THRESHOLD: number = 0.85;\n\n/**\n * The default top-K for stage-4 layer-2 similarity candidate generation.\n * @public\n */\nexport const DEFAULT_SIMILARITY_TOP_K: number = 5;\n\n/**\n * How the write-time cycle guard behaves: `'reject'` (default — a cycle-inducing\n * edge fails the ingest) or `'off'` (no acyclicity constraint, for deployments\n * whose link graphs are legitimately cyclic — e.g. mutual associative links).\n * @public\n */\nexport type CycleGuardMode = 'reject' | 'off';\n\n/**\n * The fgv-owned six-stage ingest orchestrator. Composes the host's staged\n * classify / extract / (optional) resolve / relate machinery around fgv's owned\n * validation boundary, dedup, edge + cycle safety, provenance stamping, and the\n * contradicts→temporal interlock.\n * @public\n */\nexport interface IMemoryIngestOrchestrator {\n /**\n * Ingest a SINGLE item end-to-end (the first-class per-turn streaming path).\n */\n ingestItem(item: IIngestItem): Promise<Result<IIngestItemResult>>;\n\n /**\n * Ingest a batch of items. A convenience loop over {@link\n * IMemoryIngestOrchestrator.ingestItem | ingestItem} — items are processed in\n * order and the first failure aborts the batch.\n */\n ingestBatch(items: ReadonlyArray<IIngestItem>): Promise<Result<ReadonlyArray<IIngestItemResult>>>;\n}\n\n/**\n * Parameters for {@link MemoryIngestOrchestrator.create}.\n * @public\n */\nexport interface IMemoryIngestOrchestratorCreateParams {\n /** The store every write bottoms out in (stage 6). */\n readonly store: IMemoryStore;\n /** Per-kind body converter registry — the stage-3 typed validation boundary. */\n readonly registry: IBodyConverterRegistry;\n /** Per-kind identity codecs (maps a candidate `entityId` to its storage address). */\n readonly codecs?: ReadonlyMap<Kind, IIdentityCodec>;\n /** Default identity codec for kinds without an explicit entry. */\n readonly defaultCodec?: IIdentityCodec;\n /** Stage 2 — the host's classifier. */\n readonly classifier: IMemoryClassifier;\n /** Stage 3 — the host's fact extractor. */\n readonly extractor: IFactExtractor;\n /** Stage 5 — the host's relation extractor. */\n readonly relationExtractor: IRelationExtractor;\n /**\n * Stage 4 (optional, OQ-13) — the host's entity resolver. Absent → stage-4\n * dedup is exact-`{ kind, body }`-hash only (the deterministic-identity path).\n */\n readonly entityResolver?: IEntityResolver;\n /**\n * Optional vector index for stage-4 layer-2 similarity candidate-gen. Wired\n * together with {@link IMemoryIngestOrchestratorCreateParams.embed | embed} AND\n * {@link IMemoryIngestOrchestratorCreateParams.entityResolver | entityResolver};\n * absent (or either co-requisite absent) → layer-2 is skipped and dedup is\n * exact-only.\n */\n readonly vectorIndex?: IVectorIndex;\n /** Optional embedder used to embed a candidate for layer-2 similarity search. */\n readonly embed?: MemoryEmbedder;\n /**\n * Stage-4 layer-2 cosine threshold. Defaults to {@link\n * DEFAULT_SIMILARITY_THRESHOLD} (`0.85`).\n */\n readonly similarityThreshold?: number;\n /**\n * Stage-4 layer-2 top-K. Defaults to {@link DEFAULT_SIMILARITY_TOP_K} (`5`).\n */\n readonly similarityTopK?: number;\n /** Write-time cycle guard mode. Defaults to `'reject'`. */\n readonly cycleGuard?: CycleGuardMode;\n /** Diagnostic logger (defaults to a no-op). */\n readonly logger?: Logging.ILogger;\n}\n\n/** The fully-wired stage-4 layer-2 dependencies (present only when all three are supplied). */\ninterface ISimilarityWiring {\n readonly resolver: IEntityResolver;\n readonly vectorIndex: IVectorIndex;\n readonly embed: MemoryEmbedder;\n}\n\n/** Internal per-candidate plan threaded through the pipeline. */\ninterface ICandidatePlan {\n readonly candidate: ICandidateRecord;\n /** The write target's storage address (re-addressed to the target for merge-into). */\n readonly writeAddress: IIdentityCodecResult;\n /** The write target's entity id (re-addressed for merge-into). */\n readonly writeEntityId: EntityId;\n /** The reference id used in stage-5 edges (the write target's `idStem`). */\n readonly refId: MemoryId;\n /** The resolution verdict; carries the target id on its target-bearing arms. */\n readonly verdict: ResolutionVerdict;\n /**\n * The pre-ingest target record for a `merge-into` write — its existing\n * `tags` / `links` / `provenance` are UNIONed with the candidate's at stage 6\n * so a wholesale-replace merge never wipes them.\n */\n readonly mergeTarget?: IMemoryRecord<unknown>;\n}\n\n/**\n * Default {@link IMemoryIngestOrchestrator}.\n * @public\n */\nexport class MemoryIngestOrchestrator implements IMemoryIngestOrchestrator {\n private readonly _store: IMemoryStore;\n private readonly _registry: IBodyConverterRegistry;\n private readonly _codecs: ReadonlyMap<Kind, IIdentityCodec>;\n private readonly _defaultCodec: IIdentityCodec | undefined;\n private readonly _classifier: IMemoryClassifier;\n private readonly _extractor: IFactExtractor;\n private readonly _relationExtractor: IRelationExtractor;\n private readonly _similarity: ISimilarityWiring | undefined;\n private readonly _similarityThreshold: number;\n private readonly _similarityTopK: number;\n private readonly _cycleGuard: CycleGuardMode;\n private readonly _logger: Logging.ILogger;\n private readonly _hasher: Hash.Crc32Normalizer;\n\n private constructor(params: IMemoryIngestOrchestratorCreateParams) {\n this._store = params.store;\n this._registry = params.registry;\n this._codecs = params.codecs ?? new Map<Kind, IIdentityCodec>();\n this._defaultCodec = params.defaultCodec;\n this._classifier = params.classifier;\n this._extractor = params.extractor;\n this._relationExtractor = params.relationExtractor;\n this._similarity =\n params.entityResolver !== undefined && params.vectorIndex !== undefined && params.embed !== undefined\n ? { resolver: params.entityResolver, vectorIndex: params.vectorIndex, embed: params.embed }\n : undefined;\n this._similarityThreshold = params.similarityThreshold ?? DEFAULT_SIMILARITY_THRESHOLD;\n this._similarityTopK = params.similarityTopK ?? DEFAULT_SIMILARITY_TOP_K;\n this._cycleGuard = params.cycleGuard ?? 'reject';\n this._logger = params.logger ?? new Logging.NoOpLogger();\n this._hasher = new Hash.Crc32Normalizer();\n }\n\n /** Family-convention factory. */\n public static create(params: IMemoryIngestOrchestratorCreateParams): Result<MemoryIngestOrchestrator> {\n return succeed(new MemoryIngestOrchestrator(params));\n }\n\n /** {@inheritDoc IMemoryIngestOrchestrator.ingestItem} */\n public async ingestItem(item: IIngestItem): Promise<Result<IIngestItemResult>> {\n return (await this._classify(item))\n .thenOnSuccess((classification) => this._extract(item, classification))\n .thenOnSuccess((candidates) => this._processCandidates(item, candidates));\n }\n\n /** {@inheritDoc IMemoryIngestOrchestrator.ingestBatch} */\n public async ingestBatch(\n items: ReadonlyArray<IIngestItem>\n ): Promise<Result<ReadonlyArray<IIngestItemResult>>> {\n const results: IIngestItemResult[] = [];\n for (const item of items) {\n const result: Result<IIngestItemResult> = await this.ingestItem(item);\n if (result.isFailure()) {\n return fail(result.message);\n }\n results.push(result.value);\n }\n return succeed(results);\n }\n\n /** Stage 2 — classify (host), normalizing a rejected promise into a Failure. */\n private async _classify(item: IIngestItem): Promise<Result<IMemoryClassification>> {\n return this._capture(() => this._classifier.classify(item), `ingest '${item.id}': classify`);\n }\n\n /** Stage 3 — extract (host), normalizing a rejected promise into a Failure. */\n private async _extract(\n item: IIngestItem,\n classification: IMemoryClassification\n ): Promise<Result<ReadonlyArray<ICandidateRecord>>> {\n return this._capture(() => this._extractor.extract(item, classification), `ingest '${item.id}': extract`);\n }\n\n /**\n * Stages 3b-6 over the extracted candidates: validate bodies, resolve/dedup\n * (stage 4), relate + cycle guard (stage 5), and load-with-provenance (stage 6).\n */\n private async _processCandidates(\n item: IIngestItem,\n candidates: ReadonlyArray<ICandidateRecord>\n ): Promise<Result<IIngestItemResult>> {\n // Snapshot the store once; stage-4 resolution and the cycle guard reason over\n // the pre-ingest state.\n const snapshotResult: Result<ReadonlyArray<IMemoryRecord<unknown>>> = await this._store.list();\n if (snapshotResult.isFailure()) {\n return fail(`ingest '${item.id}': failed to snapshot store: ${snapshotResult.message}`);\n }\n const snapshot: ReadonlyArray<IMemoryRecord<unknown>> = snapshotResult.value;\n const byId: ReadonlyMap<MemoryId, IMemoryRecord<unknown>> = MemoryIngestOrchestrator._indexById(snapshot);\n\n // Stage 3b + 4: validate each body and resolve a verdict/plan.\n const plans: ICandidatePlan[] = [];\n for (const candidate of candidates) {\n const planResult: Result<ICandidatePlan> = await this._planCandidate(item, candidate, snapshot, byId);\n if (planResult.isFailure()) {\n return fail(planResult.message);\n }\n plans.push(planResult.value);\n }\n\n // Stage 5: relate over the writable candidates, validate + cycle-guard.\n const writablePlans: ICandidatePlan[] = plans.filter((plan) => plan.verdict.verdict !== 'duplicate-of');\n const edgesResult: Result<ReadonlyArray<ICandidateEdge>> = await this._relate(\n item,\n writablePlans,\n snapshot,\n byId\n );\n if (edgesResult.isFailure()) {\n return fail(edgesResult.message);\n }\n const edges: ReadonlyArray<ICandidateEdge> = edgesResult.value;\n\n // Stage 6: load-with-provenance, in extraction order.\n const records: IIngestedRecordResult[] = [];\n for (const plan of plans) {\n const outcome: Result<IIngestedRecordResult> = await this._loadCandidate(item, plan, edges);\n if (outcome.isFailure()) {\n return fail(outcome.message);\n }\n records.push(outcome.value);\n }\n return succeed({ item, records });\n }\n\n /** Stage 3b + 4 for one candidate: validate body, resolve address, resolve verdict. */\n private async _planCandidate(\n item: IIngestItem,\n candidate: ICandidateRecord,\n snapshot: ReadonlyArray<IMemoryRecord<unknown>>,\n byId: ReadonlyMap<MemoryId, IMemoryRecord<unknown>>\n ): Promise<Result<ICandidatePlan>> {\n const kind: Kind = candidate.envelope.kind;\n // Stage 3b: the typed validation boundary — no unchecked host body reaches the store.\n const bodyResult: Result<string> = this._registry\n .convert(kind, candidate.body)\n .withErrorFormat((msg) => `ingest '${item.id}': candidate body for kind '${kind}' is invalid: ${msg}`)\n .onSuccess(() => MemoryIngestOrchestrator._asStringBody(item, candidate));\n if (bodyResult.isFailure()) {\n return fail(bodyResult.message);\n }\n const body: string = bodyResult.value;\n\n const addrResult: Result<IIdentityCodecResult> = this._resolveAddress(candidate.envelope.entityId, kind);\n if (addrResult.isFailure()) {\n return fail(`ingest '${item.id}': ${addrResult.message}`);\n }\n const addr: IIdentityCodecResult = addrResult.value;\n\n return (await this._resolveVerdict(candidate, kind, body, addr, snapshot, byId)).onSuccess((verdict) =>\n this._planFromVerdict(item, candidate, addr, verdict, byId)\n );\n }\n\n /**\n * Turn a resolved verdict into a candidate plan. A `new` verdict writes under the\n * candidate's own address. Every TARGET-bearing verdict\n * (`duplicate-of` / `supersede` / `merge-into`) is validated uniformly: the\n * target must be a real store record (fgv owns validation — a non-compliant host\n * resolver never smuggles a bogus id through) AND its kind must equal the\n * candidate's kind (a cross-kind target would write to the wrong scope). Only\n * `merge-into` re-addresses the write to the target's entity.\n */\n private _planFromVerdict(\n item: IIngestItem,\n candidate: ICandidateRecord,\n addr: IIdentityCodecResult,\n verdict: ResolutionVerdict,\n byId: ReadonlyMap<MemoryId, IMemoryRecord<unknown>>\n ): Result<ICandidatePlan> {\n if (verdict.verdict === 'new') {\n return Convert.memoryId.convert(addr.idStem).onSuccess((refId) =>\n succeed({\n candidate,\n writeAddress: addr,\n writeEntityId: candidate.envelope.entityId,\n refId,\n verdict\n })\n );\n }\n // duplicate-of | supersede | merge-into: the target must exist and share the\n // candidate's kind.\n const target: IMemoryRecord<unknown> | undefined = byId.get(verdict.target);\n if (target === undefined) {\n return fail(\n `ingest '${item.id}': ${verdict.verdict} target '${verdict.target}' does not exist in the store`\n );\n }\n if (target.envelope.kind !== candidate.envelope.kind) {\n return fail(\n `ingest '${item.id}': ${verdict.verdict} target '${verdict.target}' is kind '${target.envelope.kind}' but the candidate is kind '${candidate.envelope.kind}'`\n );\n }\n if (verdict.verdict === 'merge-into') {\n // Re-address the write to the target's entity, carrying the target record so\n // stage 6 can UNION its existing tags/links (never overwrite them).\n const targetEntityId: EntityId = target.envelope.entityId;\n return this._resolveAddress(targetEntityId, target.envelope.kind)\n .withErrorFormat((msg) => `ingest '${item.id}': ${msg}`)\n .onSuccess((targetAddr) =>\n Convert.memoryId.convert(targetAddr.idStem).onSuccess((refId) =>\n succeed({\n candidate,\n writeAddress: targetAddr,\n writeEntityId: targetEntityId,\n refId,\n verdict,\n mergeTarget: target\n })\n )\n );\n }\n // duplicate-of | supersede: write under the candidate's own address.\n return Convert.memoryId.convert(addr.idStem).onSuccess((refId) =>\n succeed({\n candidate,\n writeAddress: addr,\n writeEntityId: candidate.envelope.entityId,\n refId,\n verdict\n })\n );\n }\n\n /**\n * Stage 4 — resolve a dedup verdict. Layer 1: an exact `{ kind, body }` match in\n * the candidate's scope is a `duplicate-of` (design note §1). Layer 2 (only when\n * a resolver + vector index + embedder are all wired): embed the candidate,\n * surface over-threshold neighbors, and dispatch to the {@link IEntityResolver}.\n * Otherwise the verdict is `new` (the exact-only fall-back path).\n */\n private async _resolveVerdict(\n candidate: ICandidateRecord,\n kind: Kind,\n body: string,\n addr: IIdentityCodecResult,\n snapshot: ReadonlyArray<IMemoryRecord<unknown>>,\n byId: ReadonlyMap<MemoryId, IMemoryRecord<unknown>>\n ): Promise<Result<ResolutionVerdict>> {\n return this._findExactMatch(kind, body, addr.scope, snapshot).thenOnSuccess(async (matchId) => {\n if (matchId !== undefined) {\n return succeed({ verdict: 'duplicate-of', target: matchId });\n }\n const layer2: ISimilarityWiring | undefined = this._similarity;\n if (layer2 === undefined) {\n // No layer-2: exact-only fall-back (the deterministic-identity host path).\n return succeed({ verdict: 'new' });\n }\n return this._resolveViaSimilarity(candidate, addr, body, layer2, byId);\n });\n }\n\n /** Layer-2 similarity candidate-gen + resolver dispatch. */\n private async _resolveViaSimilarity(\n candidate: ICandidateRecord,\n addr: IIdentityCodecResult,\n body: string,\n wiring: ISimilarityWiring,\n byId: ReadonlyMap<MemoryId, IMemoryRecord<unknown>>\n ): Promise<Result<ResolutionVerdict>> {\n return MemoryIngestOrchestrator._provisionalRecord(candidate, addr.idStem, body).thenOnSuccess(\n (provisional) => this._resolveViaSimilarityEmbedded(candidate, addr, wiring, byId, provisional)\n );\n }\n\n /** Layer-2 continuation once the candidate has a provisional record to embed. */\n private async _resolveViaSimilarityEmbedded(\n candidate: ICandidateRecord,\n addr: IIdentityCodecResult,\n wiring: ISimilarityWiring,\n byId: ReadonlyMap<MemoryId, IMemoryRecord<unknown>>,\n provisional: IMemoryRecord<unknown>\n ): Promise<Result<ResolutionVerdict>> {\n const embedded: Result<Float32Array> = await this._capture(\n () => wiring.embed(provisional),\n `ingest '${candidate.envelope.entityId}': embed candidate`\n );\n if (embedded.isFailure()) {\n return fail(embedded.message);\n }\n const queried = await this._capture(\n () => wiring.vectorIndex.query(embedded.value, this._similarityTopK),\n `ingest '${candidate.envelope.entityId}': similarity query`\n );\n if (queried.isFailure()) {\n return fail(queried.message);\n }\n const similar: IEntityResolutionCandidate[] = [];\n for (const hit of queried.value) {\n if (hit.score < this._similarityThreshold || hit.id === addr.idStem) {\n continue;\n }\n const record: IMemoryRecord<unknown> | undefined = byId.get(hit.id);\n if (record !== undefined) {\n similar.push({ id: hit.id, record, score: hit.score });\n }\n }\n if (similar.length === 0) {\n return succeed({ verdict: 'new' });\n }\n return this._capture(\n () => wiring.resolver.resolve(candidate, similar),\n `ingest '${candidate.envelope.entityId}': resolve`\n );\n }\n\n /**\n * Find an existing record in `scope` whose `{ kind, body }` hash matches the\n * candidate's (layer-1 exact dedup). Invalidated temporal versions are excluded\n * — only a live (non-temporal or current) record deduplicates a candidate.\n */\n private _findExactMatch(\n kind: Kind,\n body: string,\n scope: MemoryScopeKey,\n snapshot: ReadonlyArray<IMemoryRecord<unknown>>\n ): Result<MemoryId | undefined> {\n // Same-kind, same-scope, LIVE (non-temporal or current) records are the exact\n // cohort. `_resolveAddress(...).map(...).orDefault()` collapses an unresolved\n // codec to a non-matching scope with no explicit failure branch.\n const cohort: ReadonlyArray<IMemoryRecord<unknown>> = snapshot.filter(\n (record) =>\n record.envelope.kind === kind &&\n !(isTemporalRecord(record) && !isVersionCurrent(record)) &&\n this._resolveAddress(record.envelope.entityId, record.envelope.kind)\n .onSuccess((addr) => succeed(addr.scope))\n .orDefault() === scope\n );\n return this._exactKey(kind, body).onSuccess((key) =>\n mapResults(\n cohort.map((record) =>\n MemoryIngestOrchestrator._recordBodyString(record).onSuccess((recordBody) =>\n this._exactKey(record.envelope.kind, recordBody).onSuccess((recordKey) =>\n succeed({ id: record.envelope.id, key: recordKey })\n )\n )\n )\n ).onSuccess((keyed) => succeed(keyed.find((entry) => entry.key === key)?.id))\n );\n }\n\n /**\n * The body of a persisted record, required to be a string (the store persists\n * only string bodies). Fails loudly rather than blind-casting an `unknown` body\n * into the exact-dedup hash — a non-string existing body is a store-integrity\n * fault, surfaced with context, not a silent miscompute.\n */\n private static _recordBodyString(record: IMemoryRecord<unknown>): Result<string> {\n if (typeof record.body !== 'string') {\n return fail(\n `ingest: stored record '${record.envelope.id}' has a non-string body (got ${typeof record.body})`\n );\n }\n return succeed(record.body);\n }\n\n /** The stage-4 exact-dedup key over `{ kind, body }` (design note §1). */\n private _exactKey(kind: Kind, body: string): Result<string> {\n return this._hasher.computeHash({ kind, body });\n }\n\n /** Stage 5 — relate (host), validate edges, and run the write-time cycle guard. */\n private async _relate(\n item: IIngestItem,\n writablePlans: ReadonlyArray<ICandidatePlan>,\n snapshot: ReadonlyArray<IMemoryRecord<unknown>>,\n byId: ReadonlyMap<MemoryId, IMemoryRecord<unknown>>\n ): Promise<Result<ReadonlyArray<ICandidateEdge>>> {\n const relationCandidates: IRelationCandidate[] = writablePlans.map((plan) => ({\n candidate: plan.candidate,\n id: plan.refId\n }));\n const proposed: Result<ReadonlyArray<ICandidateEdge>> = await this._capture(\n () => this._relationExtractor.relate({ item, candidates: relationCandidates }),\n `ingest '${item.id}': relate`\n );\n if (proposed.isFailure()) {\n return proposed;\n }\n const refIds: ReadonlySet<string> = new Set<string>(writablePlans.map((plan) => plan.refId));\n const validation: Result<true> = this._validateEdges(item, proposed.value, refIds, byId);\n if (validation.isFailure()) {\n return fail(validation.message);\n }\n if (this._cycleGuard === 'reject') {\n const guard: Result<true> = assertNoCycles(\n MemoryIngestOrchestrator._existingEdges(snapshot),\n proposed.value.map((e) => ({ source: e.source, target: e.edge.target, type: e.edge.type }))\n );\n if (guard.isFailure()) {\n return fail(`ingest '${item.id}': ${guard.message}`);\n }\n }\n return succeed(proposed.value);\n }\n\n /**\n * Validate stage-5 edges: each `source` must be a candidate being written; each\n * `target` must resolve to a sibling candidate or an existing store record.\n */\n private _validateEdges(\n item: IIngestItem,\n edges: ReadonlyArray<ICandidateEdge>,\n refIds: ReadonlySet<string>,\n byId: ReadonlyMap<MemoryId, IMemoryRecord<unknown>>\n ): Result<true> {\n return mapResults(\n edges.map((edge) => {\n if (!refIds.has(edge.source)) {\n return fail(`ingest '${item.id}': edge source '${edge.source}' is not a candidate being written`);\n }\n if (!refIds.has(edge.edge.target) && byId.get(edge.edge.target) === undefined) {\n return fail(\n `ingest '${item.id}': edge target '${edge.edge.target}' resolves to neither a sibling candidate nor an existing record`\n );\n }\n return succeed(true);\n })\n ).onSuccess(() => succeed(true));\n }\n\n /** Stage 6 — stamp provenance + edges, admit through the store, record the outcome. */\n private async _loadCandidate(\n item: IIngestItem,\n plan: ICandidatePlan,\n allEdges: ReadonlyArray<ICandidateEdge>\n ): Promise<Result<IIngestedRecordResult>> {\n const myEdges: ReadonlyArray<ICandidateEdge> = allEdges.filter((e) => e.source === plan.refId);\n if (plan.verdict.verdict === 'duplicate-of') {\n // No write: the existing target satisfied the candidate. The target id is a\n // typed field of the narrowed `duplicate-of` verdict — no cast, no guard.\n return succeed({\n candidate: plan.candidate,\n resolution: plan.verdict,\n disposition: 'deduped',\n id: plan.verdict.target,\n edges: myEdges\n });\n }\n return this._buildRecord(item, plan, myEdges).thenOnSuccess(async (record) =>\n (await this._store.put(record))\n .withErrorFormat((msg) => `ingest '${item.id}': write failed: ${msg}`)\n .onSuccess((persisted) => {\n const disposition: IngestDisposition = plan.verdict.verdict === 'merge-into' ? 'merged' : 'written';\n const interlock: 'temporal-versioned' | undefined =\n plan.writeAddress.isVersioned && myEdges.some((e) => e.edge.type === CONTRADICTS_LINK_TYPE)\n ? 'temporal-versioned'\n : undefined;\n return succeed({\n candidate: plan.candidate,\n resolution: plan.verdict,\n disposition,\n id: persisted.envelope.id,\n record: persisted,\n edges: myEdges,\n ...(interlock !== undefined ? { interlock } : {})\n });\n })\n );\n }\n\n /** Build the fully-stamped record to persist (provenance + edges + placeholder txn fields). */\n private _buildRecord(\n item: IIngestItem,\n plan: ICandidatePlan,\n myEdges: ReadonlyArray<ICandidateEdge>\n ): Result<IMemoryRecord<unknown>> {\n const base: Omit<IMemoryEnvelope, 'id' | 'seq' | 'contentHash' | 'created' | 'updated'> =\n plan.candidate.envelope;\n // For merge-into the store's `applyUpdate` REPLACES array fields wholesale, so\n // the persisted envelope must already carry the UNION of the target's existing\n // tags/links/provenance and the candidate's — otherwise the merge silently\n // wipes the target's prior links/tags.\n const target: IMemoryRecord<unknown> | undefined = plan.mergeTarget;\n const priorLinks: ReadonlyArray<IEdge> = target !== undefined ? target.envelope.links : [];\n const priorTags: ReadonlyArray<Tag> = target !== undefined ? target.envelope.tags : [];\n const priorProvenance: IProvenance = target !== undefined ? target.envelope.provenance : { source: '' };\n return Convert.memoryId.convert(plan.writeAddress.idStem).onSuccess((id) =>\n // Dedup the combined links by canonical edge key: the target's prior links, the\n // candidate's own links, and the stage-5 edges (two candidates that resolve\n // merge-into the SAME target share a `refId` — hence the same `myEdges` — and a\n // relation extractor may repeat an edge) each appear exactly once.\n this._dedupEdges([...priorLinks, ...base.links, ...myEdges.map((e) => e.edge)]).onSuccess((links) => {\n const provenance: IProvenance = {\n // Preserve the target's provenance extension keys, overlay the candidate's,\n // then stamp the host-ingest source + derivedFrom (target present only for\n // merge-into; otherwise the seed is inert).\n ...(target !== undefined ? priorProvenance : {}),\n ...base.provenance,\n source: HOST_INGEST_PROVENANCE_SOURCE,\n ...(item.sourceId !== undefined ? { derivedFrom: item.sourceId } : {})\n };\n const envelope: IMemoryEnvelope = {\n ...base,\n id,\n entityId: plan.writeEntityId,\n seq: 0,\n contentHash: '',\n created: 0,\n updated: 0,\n provenance,\n tags: MemoryIngestOrchestrator._unionTags(priorTags, base.tags),\n links\n };\n return succeed({ envelope, body: plan.candidate.body });\n })\n );\n }\n\n /** Union two tag lists, de-duplicated, preserving first-occurrence order. */\n private static _unionTags(prior: ReadonlyArray<Tag>, incoming: ReadonlyArray<Tag>): ReadonlyArray<Tag> {\n const seen: Set<string> = new Set<string>();\n const out: Tag[] = [];\n for (const tag of [...prior, ...incoming]) {\n if (!seen.has(tag)) {\n seen.add(tag);\n out.push(tag);\n }\n }\n return out;\n }\n\n /** De-duplicate a link list by canonical edge hash, preserving first-occurrence order. */\n private _dedupEdges(edges: ReadonlyArray<IEdge>): Result<ReadonlyArray<IEdge>> {\n const seen: Set<string> = new Set<string>();\n const deduped: IEdge[] = [];\n return mapResults(\n edges.map((edge) =>\n this._hasher.computeHash(edge).onSuccess((key) => {\n if (!seen.has(key)) {\n seen.add(key);\n deduped.push(edge);\n }\n return succeed(key);\n })\n )\n ).onSuccess(() => succeed(deduped));\n }\n\n /** Resolve a `(kind, entityId)` to its storage address via the registered codec. */\n private _resolveAddress(entityId: EntityId, kind: Kind): Result<IIdentityCodecResult> {\n const codec: IIdentityCodec | undefined = this._codecs.get(kind) ?? this._defaultCodec;\n if (codec === undefined) {\n return fail(`no identity codec registered for kind '${kind}'`);\n }\n return codec.encode(entityId);\n }\n\n /** Run a host hook, normalizing a thrown/rejected hook into a Failure (never throws across the seam). */\n private async _capture<T>(op: () => Promise<Result<T>>, label: string): Promise<Result<T>> {\n try {\n return await op();\n } catch (err) {\n const message: string = `${label} threw: ${String(err)}`;\n this._logger.warn(message);\n return fail(message);\n }\n }\n\n /** Index a record snapshot by id (last write wins on an id collision across scopes). */\n private static _indexById(\n records: ReadonlyArray<IMemoryRecord<unknown>>\n ): ReadonlyMap<MemoryId, IMemoryRecord<unknown>> {\n const byId: Map<MemoryId, IMemoryRecord<unknown>> = new Map<MemoryId, IMemoryRecord<unknown>>();\n for (const record of records) {\n byId.set(record.envelope.id, record);\n }\n return byId;\n }\n\n /** Every existing outbound edge in the snapshot, as cycle-guard edges. */\n private static _existingEdges(\n records: ReadonlyArray<IMemoryRecord<unknown>>\n ): ReadonlyArray<ICycleGuardEdge> {\n const edges: ICycleGuardEdge[] = [];\n for (const record of records) {\n for (const edge of record.envelope.links) {\n edges.push({ source: record.envelope.id, target: edge.target, type: edge.type });\n }\n }\n return edges;\n }\n\n /** A provisional record for embedding a candidate (placeholder txn-time fields). */\n private static _provisionalRecord(\n candidate: ICandidateRecord,\n idStem: string,\n body: string\n ): Result<IMemoryRecord<unknown>> {\n return Convert.memoryId.convert(idStem).onSuccess((id) => {\n const envelope: IMemoryEnvelope = {\n ...candidate.envelope,\n id,\n seq: 0,\n contentHash: '',\n created: 0,\n updated: 0\n };\n return succeed({ envelope, body });\n });\n }\n\n /** Require a candidate body to be a string (the store persists only string bodies). */\n private static _asStringBody(item: IIngestItem, candidate: ICandidateRecord): Result<string> {\n if (typeof candidate.body !== 'string') {\n return fail(\n `ingest '${item.id}': candidate body for kind '${\n candidate.envelope.kind\n }' must be a string (got ${typeof candidate.body})`\n );\n }\n return succeed(candidate.body);\n }\n}\n"]}
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../../src/packlets/ingest/orchestrator.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,4CAAiF;AACjF,oCAkBkB;AAIlB,6CAA+D;AAoB/D;;;GAGG;AACU,QAAA,6BAA6B,GAAW,aAAa,CAAC;AAEnE;;;;GAIG;AACU,QAAA,qBAAqB,GAAa,aAAyB,CAAC;AAEzE;;;;;GAKG;AACU,QAAA,4BAA4B,GAAW,IAAI,CAAC;AAEzD;;;GAGG;AACU,QAAA,wBAAwB,GAAW,CAAC,CAAC;AAsHlD;;;GAGG;AACH,MAAa,wBAAwB;IAenC,YAAoB,MAA6C;;QAC/D,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC;QAC3B,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,OAAO,GAAG,MAAA,MAAM,CAAC,MAAM,mCAAI,IAAI,GAAG,EAAwB,CAAC;QAChE,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,YAAY,CAAC;QACzC,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC;QACnC,IAAI,CAAC,kBAAkB,GAAG,MAAM,CAAC,iBAAiB,CAAC;QACnD,IAAI,CAAC,WAAW;YACd,MAAM,CAAC,cAAc,KAAK,SAAS,IAAI,MAAM,CAAC,WAAW,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS;gBACnG,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,cAAc,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE;gBAC3F,CAAC,CAAC,SAAS,CAAC;QAChB,IAAI,CAAC,oBAAoB,GAAG,MAAA,MAAM,CAAC,mBAAmB,mCAAI,oCAA4B,CAAC;QACvF,IAAI,CAAC,eAAe,GAAG,MAAA,MAAM,CAAC,cAAc,mCAAI,gCAAwB,CAAC;QACzE,IAAI,CAAC,WAAW,GAAG,MAAA,MAAM,CAAC,UAAU,mCAAI,QAAQ,CAAC;QACjD,IAAI,CAAC,OAAO,GAAG,MAAA,MAAM,CAAC,MAAM,mCAAI,IAAI,kBAAO,CAAC,UAAU,EAAE,CAAC;QACzD,IAAI,CAAC,OAAO,GAAG,IAAI,eAAI,CAAC,eAAe,EAAE,CAAC;IAC5C,CAAC;IAED,iCAAiC;IAC1B,MAAM,CAAC,MAAM,CAAC,MAA6C;QAChE,OAAO,IAAA,kBAAO,EAAC,IAAI,wBAAwB,CAAC,MAAM,CAAC,CAAC,CAAC;IACvD,CAAC;IAED,yDAAyD;IAClD,KAAK,CAAC,UAAU,CAAC,IAAiB;QACvC,OAAO,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;aAChC,aAAa,CAAC,CAAC,cAAc,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;aACtE,aAAa,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;IAC9E,CAAC;IAED,0DAA0D;IACnD,KAAK,CAAC,WAAW,CACtB,KAAiC;QAEjC,MAAM,OAAO,GAAwB,EAAE,CAAC;QACxC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,MAAM,GAA8B,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YACtE,IAAI,MAAM,CAAC,SAAS,EAAE,EAAE,CAAC;gBACvB,OAAO,IAAA,eAAI,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC9B,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;QACD,OAAO,IAAA,kBAAO,EAAC,OAAO,CAAC,CAAC;IAC1B,CAAC;IAED,gFAAgF;IACxE,KAAK,CAAC,SAAS,CAAC,IAAiB;QACvC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,IAAI,CAAC,EAAE,aAAa,CAAC,CAAC;IAC/F,CAAC;IAED,+EAA+E;IACvE,KAAK,CAAC,QAAQ,CACpB,IAAiB,EACjB,cAAqC;QAErC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,WAAW,IAAI,CAAC,EAAE,YAAY,CAAC,CAAC;IAC5G,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,kBAAkB,CAC9B,IAAiB,EACjB,UAA2C;QAE3C,8EAA8E;QAC9E,wBAAwB;QACxB,MAAM,cAAc,GAAkD,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAC/F,IAAI,cAAc,CAAC,SAAS,EAAE,EAAE,CAAC;YAC/B,OAAO,IAAA,eAAI,EAAC,WAAW,IAAI,CAAC,EAAE,gCAAgC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1F,CAAC;QACD,MAAM,QAAQ,GAA0C,cAAc,CAAC,KAAK,CAAC;QAC7E,8EAA8E;QAC9E,4EAA4E;QAC5E,8EAA8E;QAC9E,qEAAqE;QACrE,MAAM,YAAY,GAAyC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACxF,IAAI,YAAY,CAAC,SAAS,EAAE,EAAE,CAAC;YAC7B,OAAO,IAAA,eAAI,EAAC,WAAW,IAAI,CAAC,EAAE,MAAM,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,MAAM,MAAM,GAAiC,YAAY,CAAC,KAAK,CAAC;QAChE,MAAM,KAAK,GAAgD,IAAI,GAAG,CAChE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAA,qBAAa,EAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CACxD,CAAC;QAEF,+DAA+D;QAC/D,MAAM,KAAK,GAAqB,EAAE,CAAC;QACnC,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,MAAM,UAAU,GAA2B,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;YACvG,IAAI,UAAU,CAAC,SAAS,EAAE,EAAE,CAAC;gBAC3B,OAAO,IAAA,eAAI,EAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YAClC,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC/B,CAAC;QAED,wEAAwE;QACxE,MAAM,aAAa,GAAqB,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,cAAc,CAAC,CAAC;QACxG,MAAM,WAAW,GAA0C,MAAM,IAAI,CAAC,OAAO,CAC3E,IAAI,EACJ,aAAa,EACb,MAAM,EACN,KAAK,CACN,CAAC;QACF,IAAI,WAAW,CAAC,SAAS,EAAE,EAAE,CAAC;YAC5B,OAAO,IAAA,eAAI,EAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QACnC,CAAC;QACD,MAAM,KAAK,GAAkC,WAAW,CAAC,KAAK,CAAC;QAE/D,sDAAsD;QACtD,MAAM,OAAO,GAA4B,EAAE,CAAC;QAC5C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,OAAO,GAAkC,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;YAC5F,IAAI,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;gBACxB,OAAO,IAAA,eAAI,EAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC/B,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,IAAA,kBAAO,EAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IACpC,CAAC;IAED,uFAAuF;IAC/E,KAAK,CAAC,cAAc,CAC1B,IAAiB,EACjB,SAA2B,EAC3B,QAA+C,EAC/C,KAAkD;QAElD,MAAM,IAAI,GAAS,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC;QAC3C,sFAAsF;QACtF,MAAM,UAAU,GAAmB,IAAI,CAAC,SAAS;aAC9C,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC;aAC7B,eAAe,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,WAAW,IAAI,CAAC,EAAE,+BAA+B,IAAI,iBAAiB,GAAG,EAAE,CAAC;aACrG,SAAS,CAAC,GAAG,EAAE,CAAC,wBAAwB,CAAC,aAAa,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;QAC5E,IAAI,UAAU,CAAC,SAAS,EAAE,EAAE,CAAC;YAC3B,OAAO,IAAA,eAAI,EAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC;QACD,MAAM,IAAI,GAAW,UAAU,CAAC,KAAK,CAAC;QAEtC,MAAM,UAAU,GAAiC,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACzG,IAAI,UAAU,CAAC,SAAS,EAAE,EAAE,CAAC;YAC3B,OAAO,IAAA,eAAI,EAAC,WAAW,IAAI,CAAC,EAAE,MAAM,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5D,CAAC;QACD,MAAM,IAAI,GAAyB,UAAU,CAAC,KAAK,CAAC;QAEpD,OAAO,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,EAAE,CACtG,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,CAC7D,CAAC;IACJ,CAAC;IAED;;;;;;;;OAQG;IACK,gBAAgB,CACtB,IAAiB,EACjB,SAA2B,EAC3B,IAA0B,EAC1B,OAA0B,EAC1B,KAAkD;QAElD,IAAI,OAAO,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;YAC9B,OAAO,eAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAC/D,IAAA,kBAAO,EAAC;gBACN,SAAS;gBACT,YAAY,EAAE,IAAI;gBAClB,aAAa,EAAE,SAAS,CAAC,QAAQ,CAAC,QAAQ;gBAC1C,KAAK;gBACL,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE;gBAC3C,OAAO;aACR,CAAC,CACH,CAAC;QACJ,CAAC;QACD,6EAA6E;QAC7E,4EAA4E;QAC5E,kEAAkE;QAClE,MAAM,MAAM,GAAuC,KAAK,CAAC,GAAG,CAAC,IAAA,qBAAa,EAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QAC5F,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,IAAA,eAAI,EACT,WAAW,IAAI,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,YAAY,wBAAwB,CAAC,aAAa,CACvF,OAAO,CAAC,MAAM,CACf,+BAA+B,CACjC,CAAC;QACJ,CAAC;QACD,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACrD,OAAO,IAAA,eAAI,EACT,WAAW,IAAI,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,YAAY,wBAAwB,CAAC,aAAa,CACvF,OAAO,CAAC,MAAM,CACf,cAAc,MAAM,CAAC,QAAQ,CAAC,IAAI,gCAAgC,SAAS,CAAC,QAAQ,CAAC,IAAI,GAAG,CAC9F,CAAC;QACJ,CAAC;QACD,IAAI,OAAO,CAAC,OAAO,KAAK,YAAY,EAAE,CAAC;YACrC,6EAA6E;YAC7E,oEAAoE;YACpE,MAAM,cAAc,GAAa,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAC1D,4EAA4E;YAC5E,0EAA0E;YAC1E,8EAA8E;YAC9E,6EAA6E;YAC7E,oDAAoD;YACpD,OAAO,IAAI,CAAC,eAAe,CAAC,cAAc,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,EAAE,EAAE,CACzF,eAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAC9D,IAAA,kBAAO,EAAC;gBACN,SAAS;gBACT,YAAY,EAAE,UAAU;gBACxB,aAAa,EAAE,cAAc;gBAC7B,KAAK;gBACL,SAAS,EAAE,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE;gBACjD,OAAO;gBACP,WAAW,EAAE,MAAM;aACpB,CAAC,CACH,CACF,CAAC;QACJ,CAAC;QACD,qEAAqE;QACrE,OAAO,eAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAC/D,IAAA,kBAAO,EAAC;YACN,SAAS;YACT,YAAY,EAAE,IAAI;YAClB,aAAa,EAAE,SAAS,CAAC,QAAQ,CAAC,QAAQ;YAC1C,KAAK;YACL,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE;YAC3C,OAAO;SACR,CAAC,CACH,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACK,KAAK,CAAC,eAAe,CAC3B,SAA2B,EAC3B,IAAU,EACV,IAAY,EACZ,IAA0B,EAC1B,QAA+C,EAC/C,KAAkD;QAElD,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC5F,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC1B,yEAAyE;gBACzE,4EAA4E;gBAC5E,OAAO,IAAA,kBAAO,EAAC,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;YAC1F,CAAC;YACD,MAAM,MAAM,GAAkC,IAAI,CAAC,WAAW,CAAC;YAC/D,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,2EAA2E;gBAC3E,OAAO,IAAA,kBAAO,EAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YACrC,CAAC;YACD,OAAO,IAAI,CAAC,qBAAqB,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QAC1E,CAAC,CAAC,CAAC;IACL,CAAC;IAED,4DAA4D;IACpD,KAAK,CAAC,qBAAqB,CACjC,SAA2B,EAC3B,IAA0B,EAC1B,IAAY,EACZ,MAAyB,EACzB,KAAkD;QAElD,OAAO,wBAAwB,CAAC,kBAAkB,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,aAAa,CAC5F,CAAC,WAAW,EAAE,EAAE,CAAC,IAAI,CAAC,6BAA6B,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,CACjG,CAAC;IACJ,CAAC;IAED,iFAAiF;IACzE,KAAK,CAAC,6BAA6B,CACzC,SAA2B,EAC3B,IAA0B,EAC1B,MAAyB,EACzB,KAAkD,EAClD,WAAmC;QAEnC,MAAM,QAAQ,GAAyB,MAAM,IAAI,CAAC,QAAQ,CACxD,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,EAC/B,WAAW,SAAS,CAAC,QAAQ,CAAC,QAAQ,oBAAoB,CAC3D,CAAC;QACF,IAAI,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC;YACzB,OAAO,IAAA,eAAI,EAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CACjC,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,eAAe,CAAC,EACpE,WAAW,SAAS,CAAC,QAAQ,CAAC,QAAQ,qBAAqB,CAC5D,CAAC;QACF,IAAI,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;YACxB,OAAO,IAAA,eAAI,EAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;QACD,MAAM,OAAO,GAAiC,EAAE,CAAC;QACjD,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAChC,4EAA4E;YAC5E,6EAA6E;YAC7E,4EAA4E;YAC5E,0EAA0E;YAC1E,0EAA0E;YAC1E,8EAA8E;YAC9E,wEAAwE;YACxE,MAAM,MAAM,GAAY,GAAG,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,KAAK,IAAI,CAAC,MAAM,CAAC;YACzF,IAAI,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,oBAAoB,IAAI,MAAM,EAAE,CAAC;gBACpD,SAAS;YACX,CAAC;YACD,MAAM,MAAM,GAAuC,KAAK,CAAC,GAAG,CAAC,IAAA,qBAAa,EAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;YACxF,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;QACD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,IAAA,kBAAO,EAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,IAAI,CAAC,QAAQ,CAClB,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,EACjD,WAAW,SAAS,CAAC,QAAQ,CAAC,QAAQ,YAAY,CACnD,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACK,eAAe,CACrB,IAAU,EACV,IAAY,EACZ,KAAqB,EACrB,QAA+C;QAE/C,8EAA8E;QAC9E,8EAA8E;QAC9E,iEAAiE;QACjE,MAAM,MAAM,GAA0C,QAAQ,CAAC,MAAM,CACnE,CAAC,MAAM,EAAE,EAAE,CACT,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,IAAI;YAC7B,CAAC,CAAC,IAAA,wBAAgB,EAAC,MAAM,CAAC,IAAI,CAAC,IAAA,wBAAgB,EAAC,MAAM,CAAC,CAAC;YACxD,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;iBACjE,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAA,kBAAO,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC;iBACxC,SAAS,EAAE,KAAK,KAAK,CAC3B,CAAC;QACF,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,CAClD,IAAA,qBAAU,EACR,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CACpB,wBAAwB,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,EAAE,EAAE,CAC1E,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,EAAE,EAAE,CACvE,IAAA,kBAAO,EAAC,EAAE,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CACpD,CACF,CACF,CACF,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,WAAC,OAAA,IAAA,kBAAO,EAAC,MAAA,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,0CAAE,EAAE,CAAC,CAAA,EAAA,CAAC,CAC9E,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACK,MAAM,CAAC,iBAAiB,CAAC,MAA8B;QAC7D,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACpC,OAAO,IAAA,eAAI,EACT,0BAA0B,MAAM,CAAC,QAAQ,CAAC,EAAE,gCAAgC,OAAO,MAAM,CAAC,IAAI,GAAG,CAClG,CAAC;QACJ,CAAC;QACD,OAAO,IAAA,kBAAO,EAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,0EAA0E;IAClE,SAAS,CAAC,IAAU,EAAE,IAAY;QACxC,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,mFAAmF;IAC3E,KAAK,CAAC,OAAO,CACnB,IAAiB,EACjB,aAA4C,EAC5C,MAAoC,EACpC,KAAkD;QAElD,MAAM,kBAAkB,GAAyB,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC5E,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,EAAE,EAAE,IAAI,CAAC,SAAS;SACnB,CAAC,CAAC,CAAC;QACJ,MAAM,QAAQ,GAA0C,MAAM,IAAI,CAAC,QAAQ,CACzE,GAAG,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,kBAAkB,EAAE,CAAC,EAC9E,WAAW,IAAI,CAAC,EAAE,WAAW,CAC9B,CAAC;QACF,IAAI,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC;YACzB,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,8EAA8E;QAC9E,2EAA2E;QAC3E,iBAAiB;QACjB,MAAM,MAAM,GAAwB,IAAI,GAAG,CACzC,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAA,qBAAa,EAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAC3D,CAAC;QACF,MAAM,UAAU,GAAiB,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QAC1F,IAAI,UAAU,CAAC,SAAS,EAAE,EAAE,CAAC;YAC3B,OAAO,IAAA,eAAI,EAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC;QACD,IAAI,IAAI,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;YAClC,MAAM,KAAK,GAAiB,IAAA,2BAAc,EACxC,wBAAwB,CAAC,cAAc,CAAC,MAAM,CAAC,EAC/C,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAC5F,CAAC;YACF,IAAI,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;gBACtB,OAAO,IAAA,eAAI,EAAC,WAAW,IAAI,CAAC,EAAE,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;QACD,OAAO,IAAA,kBAAO,EAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IAED;;;;OAIG;IACK,cAAc,CACpB,IAAiB,EACjB,KAAoC,EACpC,MAA2B,EAC3B,KAAkD;QAElD,OAAO,IAAA,qBAAU,EACf,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACjB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAA,qBAAa,EAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;gBAC5C,OAAO,IAAA,eAAI,EACT,WAAW,IAAI,CAAC,EAAE,mBAAmB,wBAAwB,CAAC,aAAa,CACzE,IAAI,CAAC,MAAM,CACZ,oCAAoC,CACtC,CAAC;YACJ,CAAC;YACD,MAAM,SAAS,GAAW,IAAA,qBAAa,EAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1D,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,SAAS,EAAE,CAAC;gBACjE,OAAO,IAAA,eAAI,EACT,WAAW,IAAI,CAAC,EAAE,mBAAmB,wBAAwB,CAAC,aAAa,CACzE,IAAI,CAAC,IAAI,CAAC,MAAM,CACjB,kEAAkE,CACpE,CAAC;YACJ,CAAC;YACD,OAAO,IAAA,kBAAO,EAAC,IAAI,CAAC,CAAC;QACvB,CAAC,CAAC,CACH,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,IAAA,kBAAO,EAAC,IAAI,CAAC,CAAC,CAAC;IACnC,CAAC;IAED,uFAAuF;IAC/E,KAAK,CAAC,cAAc,CAC1B,IAAiB,EACjB,IAAoB,EACpB,QAAuC;QAEvC,MAAM,MAAM,GAAW,IAAA,qBAAa,EAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACrD,MAAM,OAAO,GAAkC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,qBAAa,EAAC,CAAC,CAAC,MAAM,CAAC,KAAK,MAAM,CAAC,CAAC;QAC1G,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,cAAc,EAAE,CAAC;YAC5C,4EAA4E;YAC5E,0EAA0E;YAC1E,OAAO,IAAA,kBAAO,EAAC;gBACb,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,UAAU,EAAE,IAAI,CAAC,OAAO;gBACxB,WAAW,EAAE,SAAS;gBACtB,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;gBAC1B,KAAK,EAAE,OAAO;aACf,CAAC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAC3E,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;aAC5B,eAAe,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,WAAW,IAAI,CAAC,EAAE,oBAAoB,GAAG,EAAE,CAAC;aACrE,SAAS,CAAC,CAAC,SAAS,EAAE,EAAE;YACvB,MAAM,WAAW,GAAsB,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;YACpG,MAAM,SAAS,GACb,IAAI,CAAC,YAAY,CAAC,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,6BAAqB,CAAC;gBACzF,CAAC,CAAC,oBAAoB;gBACtB,CAAC,CAAC,SAAS,CAAC;YAChB,OAAO,IAAA,kBAAO,kBACZ,SAAS,EAAE,IAAI,CAAC,SAAS,EACzB,UAAU,EAAE,IAAI,CAAC,OAAO,EACxB,WAAW,EACX,EAAE,EAAE,SAAS,CAAC,QAAQ,CAAC,EAAE,EACzB,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,OAAO,IACX,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EACjD,CAAC;QACL,CAAC,CAAC,CACL,CAAC;IACJ,CAAC;IAED,+FAA+F;IACvF,YAAY,CAClB,IAAiB,EACjB,IAAoB,EACpB,OAAsC;QAEtC,MAAM,IAAI,GACR,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;QAC1B,+EAA+E;QAC/E,+EAA+E;QAC/E,2EAA2E;QAC3E,uCAAuC;QACvC,MAAM,MAAM,GAAuC,IAAI,CAAC,WAAW,CAAC;QACpE,MAAM,UAAU,GAAyB,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3F,MAAM,SAAS,GAAuB,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACvF,MAAM,eAAe,GAAgB,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QACxG,OAAO,eAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE;QACzE,gFAAgF;QAChF,4EAA4E;QAC5E,gFAAgF;QAChF,mEAAmE;QACnE,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,UAAU,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE;YAClG,MAAM,UAAU,+DAIX,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC,GAC7C,IAAI,CAAC,UAAU,KAClB,MAAM,EAAE,qCAA6B,KAClC,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CACvE,CAAC;YACF,MAAM,QAAQ,mCACT,IAAI,KACP,EAAE,EACF,QAAQ,EAAE,IAAI,CAAC,aAAa,EAC5B,GAAG,EAAE,CAAC,EACN,WAAW,EAAE,EAAE,EACf,OAAO,EAAE,CAAC,EACV,OAAO,EAAE,CAAC,EACV,UAAU,EACV,IAAI,EAAE,wBAAwB,CAAC,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,EAC/D,KAAK,GACN,CAAC;YACF,OAAO,IAAA,kBAAO,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1D,CAAC,CAAC,CACH,CAAC;IACJ,CAAC;IAED,6EAA6E;IACrE,MAAM,CAAC,UAAU,CAAC,KAAyB,EAAE,QAA4B;QAC/E,MAAM,IAAI,GAAgB,IAAI,GAAG,EAAU,CAAC;QAC5C,MAAM,GAAG,GAAU,EAAE,CAAC;QACtB,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,KAAK,EAAE,GAAG,QAAQ,CAAC,EAAE,CAAC;YAC1C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACnB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACd,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAChB,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,0FAA0F;IAClF,WAAW,CAAC,KAA2B;QAC7C,MAAM,IAAI,GAAgB,IAAI,GAAG,EAAU,CAAC;QAC5C,MAAM,OAAO,GAAY,EAAE,CAAC;QAC5B,OAAO,IAAA,qBAAU,EACf,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACjB,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE;YAC/C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACnB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACd,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC;YACD,OAAO,IAAA,kBAAO,EAAC,GAAG,CAAC,CAAC;QACtB,CAAC,CAAC,CACH,CACF,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,IAAA,kBAAO,EAAC,OAAO,CAAC,CAAC,CAAC;IACtC,CAAC;IAED,oFAAoF;IAC5E,eAAe,CAAC,QAAkB,EAAE,IAAU;;QACpD,MAAM,KAAK,GAA+B,MAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,mCAAI,IAAI,CAAC,aAAa,CAAC;QACvF,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,IAAA,eAAI,EAAC,0CAA0C,IAAI,GAAG,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;IAED,yGAAyG;IACjG,KAAK,CAAC,QAAQ,CAAI,EAA4B,EAAE,KAAa;QACnE,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAW,GAAG,KAAK,WAAW,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YACzD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC3B,OAAO,IAAA,eAAI,EAAC,OAAO,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACK,MAAM,CAAC,cAAc,CAAC,MAAoC;QAChE,MAAM,KAAK,GAAsB,EAAE,CAAC;QACpC,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;gBAC3C,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;OAKG;IACK,aAAa,CACnB,OAA8C;QAE9C,OAAO,IAAA,qBAAU,EACf,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CACrB,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;aACjE,eAAe,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,2CAA2C,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC;aAClG,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAA,kBAAO,EAAC,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CACpG,CACF,CAAC;IACJ,CAAC;IAED,8FAA8F;IACtF,MAAM,CAAC,aAAa,CAAC,MAAmB;QAC9C,OAAO,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;IACxC,CAAC;IAED,oFAAoF;IAC5E,MAAM,CAAC,kBAAkB,CAC/B,SAA2B,EAC3B,MAAc,EACd,IAAY;QAEZ,OAAO,eAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE;YACvD,MAAM,QAAQ,mCACT,SAAS,CAAC,QAAQ,KACrB,EAAE,EACF,GAAG,EAAE,CAAC,EACN,WAAW,EAAE,EAAE,EACf,OAAO,EAAE,CAAC,EACV,OAAO,EAAE,CAAC,GACX,CAAC;YACF,OAAO,IAAA,kBAAO,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;IACL,CAAC;IAED,uFAAuF;IAC/E,MAAM,CAAC,aAAa,CAAC,IAAiB,EAAE,SAA2B;QACzE,IAAI,OAAO,SAAS,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvC,OAAO,IAAA,eAAI,EACT,WAAW,IAAI,CAAC,EAAE,+BAChB,SAAS,CAAC,QAAQ,CAAC,IACrB,2BAA2B,OAAO,SAAS,CAAC,IAAI,GAAG,CACpD,CAAC;QACJ,CAAC;QACD,OAAO,IAAA,kBAAO,EAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;CACF;AArqBD,4DAqqBC","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n * SPDX-License-Identifier: MIT\n */\n\nimport { Hash, Logging, Result, fail, mapResults, succeed } from '@fgv/ts-utils';\nimport {\n Convert,\n EntityId,\n IEdge,\n IEdgeTarget,\n IIdentityCodec,\n IIdentityCodecResult,\n IMemoryEnvelope,\n IMemoryRecord,\n IProvenance,\n Kind,\n LinkType,\n MemoryId,\n MemoryScopeKey,\n Tag,\n edgeTargetKey,\n isTemporalRecord,\n isVersionCurrent\n} from '../types';\nimport { IBodyConverterRegistry } from '../converters';\nimport { IMemoryStore } from '../store';\nimport { IVectorIndex, MemoryEmbedder } from '../vector';\nimport { ICycleGuardEdge, assertNoCycles } from './cycleGuard';\nimport {\n IEntityResolver,\n IFactExtractor,\n IMemoryClassifier,\n IRelationCandidate,\n IRelationExtractor\n} from './hostStages';\nimport {\n ICandidateEdge,\n ICandidateRecord,\n IEntityResolutionCandidate,\n IIngestItem,\n IIngestItemResult,\n IIngestedRecordResult,\n IMemoryClassification,\n IngestDisposition,\n ResolutionVerdict\n} from './model';\n\n/**\n * The provenance source stamped on every record the ingest pipeline writes.\n * @public\n */\nexport const HOST_INGEST_PROVENANCE_SOURCE: string = 'host-ingest';\n\n/**\n * The link type whose presence on a temporal-kind candidate fires the\n * contradicts→temporal-versioned interlock.\n * @public\n */\nexport const CONTRADICTS_LINK_TYPE: LinkType = 'contradicts' as LinkType;\n\n/**\n * The default stage-4 layer-2 cosine similarity threshold (design note §2). A\n * near-duplicate candidate is surfaced to the {@link IEntityResolver} only when\n * its nearest neighbor scores `>= 0.85`.\n * @public\n */\nexport const DEFAULT_SIMILARITY_THRESHOLD: number = 0.85;\n\n/**\n * The default top-K for stage-4 layer-2 similarity candidate generation.\n * @public\n */\nexport const DEFAULT_SIMILARITY_TOP_K: number = 5;\n\n/**\n * How the write-time cycle guard behaves: `'reject'` (default — a cycle-inducing\n * edge fails the ingest) or `'off'` (no acyclicity constraint, for deployments\n * whose link graphs are legitimately cyclic — e.g. mutual associative links).\n * @public\n */\nexport type CycleGuardMode = 'reject' | 'off';\n\n/**\n * The fgv-owned six-stage ingest orchestrator. Composes the host's staged\n * classify / extract / (optional) resolve / relate machinery around fgv's owned\n * validation boundary, dedup, edge + cycle safety, provenance stamping, and the\n * contradicts→temporal interlock.\n * @public\n */\nexport interface IMemoryIngestOrchestrator {\n /**\n * Ingest a SINGLE item end-to-end (the first-class per-turn streaming path).\n */\n ingestItem(item: IIngestItem): Promise<Result<IIngestItemResult>>;\n\n /**\n * Ingest a batch of items. A convenience loop over {@link\n * IMemoryIngestOrchestrator.ingestItem | ingestItem} — items are processed in\n * order and the first failure aborts the batch.\n */\n ingestBatch(items: ReadonlyArray<IIngestItem>): Promise<Result<ReadonlyArray<IIngestItemResult>>>;\n}\n\n/**\n * Parameters for {@link MemoryIngestOrchestrator.create}.\n * @public\n */\nexport interface IMemoryIngestOrchestratorCreateParams {\n /** The store every write bottoms out in (stage 6). */\n readonly store: IMemoryStore;\n /** Per-kind body converter registry — the stage-3 typed validation boundary. */\n readonly registry: IBodyConverterRegistry;\n /** Per-kind identity codecs (maps a candidate `entityId` to its storage address). */\n readonly codecs?: ReadonlyMap<Kind, IIdentityCodec>;\n /** Default identity codec for kinds without an explicit entry. */\n readonly defaultCodec?: IIdentityCodec;\n /** Stage 2 — the host's classifier. */\n readonly classifier: IMemoryClassifier;\n /** Stage 3 — the host's fact extractor. */\n readonly extractor: IFactExtractor;\n /** Stage 5 — the host's relation extractor. */\n readonly relationExtractor: IRelationExtractor;\n /**\n * Stage 4 (optional, OQ-13) — the host's entity resolver. Absent → stage-4\n * dedup is exact-`{ kind, body }`-hash only (the deterministic-identity path).\n */\n readonly entityResolver?: IEntityResolver;\n /**\n * Optional vector index for stage-4 layer-2 similarity candidate-gen. Wired\n * together with {@link IMemoryIngestOrchestratorCreateParams.embed | embed} AND\n * {@link IMemoryIngestOrchestratorCreateParams.entityResolver | entityResolver};\n * absent (or either co-requisite absent) → layer-2 is skipped and dedup is\n * exact-only.\n */\n readonly vectorIndex?: IVectorIndex;\n /** Optional embedder used to embed a candidate for layer-2 similarity search. */\n readonly embed?: MemoryEmbedder;\n /**\n * Stage-4 layer-2 cosine threshold. Defaults to {@link\n * DEFAULT_SIMILARITY_THRESHOLD} (`0.85`).\n */\n readonly similarityThreshold?: number;\n /**\n * Stage-4 layer-2 top-K. Defaults to {@link DEFAULT_SIMILARITY_TOP_K} (`5`).\n */\n readonly similarityTopK?: number;\n /** Write-time cycle guard mode. Defaults to `'reject'`. */\n readonly cycleGuard?: CycleGuardMode;\n /** Diagnostic logger (defaults to a no-op). */\n readonly logger?: Logging.ILogger;\n}\n\n/** The fully-wired stage-4 layer-2 dependencies (present only when all three are supplied). */\ninterface ISimilarityWiring {\n readonly resolver: IEntityResolver;\n readonly vectorIndex: IVectorIndex;\n readonly embed: MemoryEmbedder;\n}\n\n/** A snapshot record paired with its resolved scope-qualified `(scope, id)` address. */\ninterface IScopedRecord {\n readonly address: IEdgeTarget;\n readonly record: IMemoryRecord<unknown>;\n}\n\n/** Internal per-candidate plan threaded through the pipeline. */\ninterface ICandidatePlan {\n readonly candidate: ICandidateRecord;\n /** The write target's storage address (re-addressed to the target for merge-into). */\n readonly writeAddress: IIdentityCodecResult;\n /** The write target's entity id (re-addressed for merge-into). */\n readonly writeEntityId: EntityId;\n /** The reference id used in stage-5 edges (the write target's `idStem`). */\n readonly refId: MemoryId;\n /**\n * The scope-qualified reference used in stage-5 edges: the write target's\n * `(scope, idStem)`. Stage-5 sources / dedup all key on this scoped address so\n * two candidates that share a stem across scopes never collide.\n */\n readonly refTarget: IEdgeTarget;\n /** The resolution verdict; carries the target id on its target-bearing arms. */\n readonly verdict: ResolutionVerdict;\n /**\n * The pre-ingest target record for a `merge-into` write — its existing\n * `tags` / `links` / `provenance` are UNIONed with the candidate's at stage 6\n * so a wholesale-replace merge never wipes them.\n */\n readonly mergeTarget?: IMemoryRecord<unknown>;\n}\n\n/**\n * Default {@link IMemoryIngestOrchestrator}.\n * @public\n */\nexport class MemoryIngestOrchestrator implements IMemoryIngestOrchestrator {\n private readonly _store: IMemoryStore;\n private readonly _registry: IBodyConverterRegistry;\n private readonly _codecs: ReadonlyMap<Kind, IIdentityCodec>;\n private readonly _defaultCodec: IIdentityCodec | undefined;\n private readonly _classifier: IMemoryClassifier;\n private readonly _extractor: IFactExtractor;\n private readonly _relationExtractor: IRelationExtractor;\n private readonly _similarity: ISimilarityWiring | undefined;\n private readonly _similarityThreshold: number;\n private readonly _similarityTopK: number;\n private readonly _cycleGuard: CycleGuardMode;\n private readonly _logger: Logging.ILogger;\n private readonly _hasher: Hash.Crc32Normalizer;\n\n private constructor(params: IMemoryIngestOrchestratorCreateParams) {\n this._store = params.store;\n this._registry = params.registry;\n this._codecs = params.codecs ?? new Map<Kind, IIdentityCodec>();\n this._defaultCodec = params.defaultCodec;\n this._classifier = params.classifier;\n this._extractor = params.extractor;\n this._relationExtractor = params.relationExtractor;\n this._similarity =\n params.entityResolver !== undefined && params.vectorIndex !== undefined && params.embed !== undefined\n ? { resolver: params.entityResolver, vectorIndex: params.vectorIndex, embed: params.embed }\n : undefined;\n this._similarityThreshold = params.similarityThreshold ?? DEFAULT_SIMILARITY_THRESHOLD;\n this._similarityTopK = params.similarityTopK ?? DEFAULT_SIMILARITY_TOP_K;\n this._cycleGuard = params.cycleGuard ?? 'reject';\n this._logger = params.logger ?? new Logging.NoOpLogger();\n this._hasher = new Hash.Crc32Normalizer();\n }\n\n /** Family-convention factory. */\n public static create(params: IMemoryIngestOrchestratorCreateParams): Result<MemoryIngestOrchestrator> {\n return succeed(new MemoryIngestOrchestrator(params));\n }\n\n /** {@inheritDoc IMemoryIngestOrchestrator.ingestItem} */\n public async ingestItem(item: IIngestItem): Promise<Result<IIngestItemResult>> {\n return (await this._classify(item))\n .thenOnSuccess((classification) => this._extract(item, classification))\n .thenOnSuccess((candidates) => this._processCandidates(item, candidates));\n }\n\n /** {@inheritDoc IMemoryIngestOrchestrator.ingestBatch} */\n public async ingestBatch(\n items: ReadonlyArray<IIngestItem>\n ): Promise<Result<ReadonlyArray<IIngestItemResult>>> {\n const results: IIngestItemResult[] = [];\n for (const item of items) {\n const result: Result<IIngestItemResult> = await this.ingestItem(item);\n if (result.isFailure()) {\n return fail(result.message);\n }\n results.push(result.value);\n }\n return succeed(results);\n }\n\n /** Stage 2 — classify (host), normalizing a rejected promise into a Failure. */\n private async _classify(item: IIngestItem): Promise<Result<IMemoryClassification>> {\n return this._capture(() => this._classifier.classify(item), `ingest '${item.id}': classify`);\n }\n\n /** Stage 3 — extract (host), normalizing a rejected promise into a Failure. */\n private async _extract(\n item: IIngestItem,\n classification: IMemoryClassification\n ): Promise<Result<ReadonlyArray<ICandidateRecord>>> {\n return this._capture(() => this._extractor.extract(item, classification), `ingest '${item.id}': extract`);\n }\n\n /**\n * Stages 3b-6 over the extracted candidates: validate bodies, resolve/dedup\n * (stage 4), relate + cycle guard (stage 5), and load-with-provenance (stage 6).\n */\n private async _processCandidates(\n item: IIngestItem,\n candidates: ReadonlyArray<ICandidateRecord>\n ): Promise<Result<IIngestItemResult>> {\n // Snapshot the store once; stage-4 resolution and the cycle guard reason over\n // the pre-ingest state.\n const snapshotResult: Result<ReadonlyArray<IMemoryRecord<unknown>>> = await this._store.list();\n if (snapshotResult.isFailure()) {\n return fail(`ingest '${item.id}': failed to snapshot store: ${snapshotResult.message}`);\n }\n const snapshot: ReadonlyArray<IMemoryRecord<unknown>> = snapshotResult.value;\n // Resolve every snapshot record's scope-qualified address ONCE, then index it\n // by the canonical scoped key. The single `byKey` view drives BOTH the edge\n // path (validation + cycle guard) AND the verdict/similarity target lookups —\n // so a filename stem reused across scopes never aliases on any path.\n const scopedResult: Result<ReadonlyArray<IScopedRecord>> = this._scopeRecords(snapshot);\n if (scopedResult.isFailure()) {\n return fail(`ingest '${item.id}': ${scopedResult.message}`);\n }\n const scoped: ReadonlyArray<IScopedRecord> = scopedResult.value;\n const byKey: ReadonlyMap<string, IMemoryRecord<unknown>> = new Map<string, IMemoryRecord<unknown>>(\n scoped.map((s) => [edgeTargetKey(s.address), s.record])\n );\n\n // Stage 3b + 4: validate each body and resolve a verdict/plan.\n const plans: ICandidatePlan[] = [];\n for (const candidate of candidates) {\n const planResult: Result<ICandidatePlan> = await this._planCandidate(item, candidate, snapshot, byKey);\n if (planResult.isFailure()) {\n return fail(planResult.message);\n }\n plans.push(planResult.value);\n }\n\n // Stage 5: relate over the writable candidates, validate + cycle-guard.\n const writablePlans: ICandidatePlan[] = plans.filter((plan) => plan.verdict.verdict !== 'duplicate-of');\n const edgesResult: Result<ReadonlyArray<ICandidateEdge>> = await this._relate(\n item,\n writablePlans,\n scoped,\n byKey\n );\n if (edgesResult.isFailure()) {\n return fail(edgesResult.message);\n }\n const edges: ReadonlyArray<ICandidateEdge> = edgesResult.value;\n\n // Stage 6: load-with-provenance, in extraction order.\n const records: IIngestedRecordResult[] = [];\n for (const plan of plans) {\n const outcome: Result<IIngestedRecordResult> = await this._loadCandidate(item, plan, edges);\n if (outcome.isFailure()) {\n return fail(outcome.message);\n }\n records.push(outcome.value);\n }\n return succeed({ item, records });\n }\n\n /** Stage 3b + 4 for one candidate: validate body, resolve address, resolve verdict. */\n private async _planCandidate(\n item: IIngestItem,\n candidate: ICandidateRecord,\n snapshot: ReadonlyArray<IMemoryRecord<unknown>>,\n byKey: ReadonlyMap<string, IMemoryRecord<unknown>>\n ): Promise<Result<ICandidatePlan>> {\n const kind: Kind = candidate.envelope.kind;\n // Stage 3b: the typed validation boundary — no unchecked host body reaches the store.\n const bodyResult: Result<string> = this._registry\n .convert(kind, candidate.body)\n .withErrorFormat((msg) => `ingest '${item.id}': candidate body for kind '${kind}' is invalid: ${msg}`)\n .onSuccess(() => MemoryIngestOrchestrator._asStringBody(item, candidate));\n if (bodyResult.isFailure()) {\n return fail(bodyResult.message);\n }\n const body: string = bodyResult.value;\n\n const addrResult: Result<IIdentityCodecResult> = this._resolveAddress(candidate.envelope.entityId, kind);\n if (addrResult.isFailure()) {\n return fail(`ingest '${item.id}': ${addrResult.message}`);\n }\n const addr: IIdentityCodecResult = addrResult.value;\n\n return (await this._resolveVerdict(candidate, kind, body, addr, snapshot, byKey)).onSuccess((verdict) =>\n this._planFromVerdict(item, candidate, addr, verdict, byKey)\n );\n }\n\n /**\n * Turn a resolved verdict into a candidate plan. A `new` verdict writes under the\n * candidate's own address. Every TARGET-bearing verdict\n * (`duplicate-of` / `supersede` / `merge-into`) is validated uniformly: the\n * target must be a real store record (fgv owns validation — a non-compliant host\n * resolver never smuggles a bogus id through) AND its kind must equal the\n * candidate's kind (a cross-kind target would write to the wrong scope). Only\n * `merge-into` re-addresses the write to the target's entity.\n */\n private _planFromVerdict(\n item: IIngestItem,\n candidate: ICandidateRecord,\n addr: IIdentityCodecResult,\n verdict: ResolutionVerdict,\n byKey: ReadonlyMap<string, IMemoryRecord<unknown>>\n ): Result<ICandidatePlan> {\n if (verdict.verdict === 'new') {\n return Convert.memoryId.convert(addr.idStem).onSuccess((refId) =>\n succeed({\n candidate,\n writeAddress: addr,\n writeEntityId: candidate.envelope.entityId,\n refId,\n refTarget: { scope: addr.scope, id: refId },\n verdict\n })\n );\n }\n // duplicate-of | supersede | merge-into: the target must exist and share the\n // candidate's kind. Lookup is on the canonical scoped key, so a stem reused\n // across scopes binds only the record the verdict actually named.\n const target: IMemoryRecord<unknown> | undefined = byKey.get(edgeTargetKey(verdict.target));\n if (target === undefined) {\n return fail(\n `ingest '${item.id}': ${verdict.verdict} target '${MemoryIngestOrchestrator._formatTarget(\n verdict.target\n )}' does not exist in the store`\n );\n }\n if (target.envelope.kind !== candidate.envelope.kind) {\n return fail(\n `ingest '${item.id}': ${verdict.verdict} target '${MemoryIngestOrchestrator._formatTarget(\n verdict.target\n )}' is kind '${target.envelope.kind}' but the candidate is kind '${candidate.envelope.kind}'`\n );\n }\n if (verdict.verdict === 'merge-into') {\n // Re-address the write to the target's entity, carrying the target record so\n // stage 6 can UNION its existing tags/links (never overwrite them).\n const targetEntityId: EntityId = target.envelope.entityId;\n // The merge target is a snapshot record, and `_scopeRecords` already proved\n // every snapshot record's address resolves before planning runs — so this\n // re-resolve (needed for the full codec result: scope + idStem + isVersioned)\n // cannot fail. No error-context wrap is warranted; a failure here would be a\n // logic contradiction, not a user-facing condition.\n return this._resolveAddress(targetEntityId, target.envelope.kind).onSuccess((targetAddr) =>\n Convert.memoryId.convert(targetAddr.idStem).onSuccess((refId) =>\n succeed({\n candidate,\n writeAddress: targetAddr,\n writeEntityId: targetEntityId,\n refId,\n refTarget: { scope: targetAddr.scope, id: refId },\n verdict,\n mergeTarget: target\n })\n )\n );\n }\n // duplicate-of | supersede: write under the candidate's own address.\n return Convert.memoryId.convert(addr.idStem).onSuccess((refId) =>\n succeed({\n candidate,\n writeAddress: addr,\n writeEntityId: candidate.envelope.entityId,\n refId,\n refTarget: { scope: addr.scope, id: refId },\n verdict\n })\n );\n }\n\n /**\n * Stage 4 — resolve a dedup verdict. Layer 1: an exact `{ kind, body }` match in\n * the candidate's scope is a `duplicate-of` (design note §1). Layer 2 (only when\n * a resolver + vector index + embedder are all wired): embed the candidate,\n * surface over-threshold neighbors, and dispatch to the {@link IEntityResolver}.\n * Otherwise the verdict is `new` (the exact-only fall-back path).\n */\n private async _resolveVerdict(\n candidate: ICandidateRecord,\n kind: Kind,\n body: string,\n addr: IIdentityCodecResult,\n snapshot: ReadonlyArray<IMemoryRecord<unknown>>,\n byKey: ReadonlyMap<string, IMemoryRecord<unknown>>\n ): Promise<Result<ResolutionVerdict>> {\n return this._findExactMatch(kind, body, addr.scope, snapshot).thenOnSuccess(async (matchId) => {\n if (matchId !== undefined) {\n // The exact-match cohort is filtered to `addr.scope`, so the match lives\n // under that scope — its scope-qualified target is `(addr.scope, matchId)`.\n return succeed({ verdict: 'duplicate-of', target: { scope: addr.scope, id: matchId } });\n }\n const layer2: ISimilarityWiring | undefined = this._similarity;\n if (layer2 === undefined) {\n // No layer-2: exact-only fall-back (the deterministic-identity host path).\n return succeed({ verdict: 'new' });\n }\n return this._resolveViaSimilarity(candidate, addr, body, layer2, byKey);\n });\n }\n\n /** Layer-2 similarity candidate-gen + resolver dispatch. */\n private async _resolveViaSimilarity(\n candidate: ICandidateRecord,\n addr: IIdentityCodecResult,\n body: string,\n wiring: ISimilarityWiring,\n byKey: ReadonlyMap<string, IMemoryRecord<unknown>>\n ): Promise<Result<ResolutionVerdict>> {\n return MemoryIngestOrchestrator._provisionalRecord(candidate, addr.idStem, body).thenOnSuccess(\n (provisional) => this._resolveViaSimilarityEmbedded(candidate, addr, wiring, byKey, provisional)\n );\n }\n\n /** Layer-2 continuation once the candidate has a provisional record to embed. */\n private async _resolveViaSimilarityEmbedded(\n candidate: ICandidateRecord,\n addr: IIdentityCodecResult,\n wiring: ISimilarityWiring,\n byKey: ReadonlyMap<string, IMemoryRecord<unknown>>,\n provisional: IMemoryRecord<unknown>\n ): Promise<Result<ResolutionVerdict>> {\n const embedded: Result<Float32Array> = await this._capture(\n () => wiring.embed(provisional),\n `ingest '${candidate.envelope.entityId}': embed candidate`\n );\n if (embedded.isFailure()) {\n return fail(embedded.message);\n }\n const queried = await this._capture(\n () => wiring.vectorIndex.query(embedded.value, this._similarityTopK),\n `ingest '${candidate.envelope.entityId}': similarity query`\n );\n if (queried.isFailure()) {\n return fail(queried.message);\n }\n const similar: IEntityResolutionCandidate[] = [];\n for (const hit of queried.value) {\n // Skip below-threshold hits and the candidate's OWN scope-qualified address\n // (a re-ingest of the same entity must not dedup against its prior version).\n // Both the scope AND the id must match to be \"self\" — a same-stem record in\n // another scope is a legitimate distinct neighbor. This field-equality is\n // exactly equivalent to comparing `edgeTargetKey(hit.target)` against the\n // candidate's own key (edgeTargetKey is pure and injective on `(scope, id)`),\n // so this one site reads the components directly rather than re-keying.\n const isSelf: boolean = hit.target.scope === addr.scope && hit.target.id === addr.idStem;\n if (hit.score < this._similarityThreshold || isSelf) {\n continue;\n }\n const record: IMemoryRecord<unknown> | undefined = byKey.get(edgeTargetKey(hit.target));\n if (record !== undefined) {\n similar.push({ target: hit.target, record, score: hit.score });\n }\n }\n if (similar.length === 0) {\n return succeed({ verdict: 'new' });\n }\n return this._capture(\n () => wiring.resolver.resolve(candidate, similar),\n `ingest '${candidate.envelope.entityId}': resolve`\n );\n }\n\n /**\n * Find an existing record in `scope` whose `{ kind, body }` hash matches the\n * candidate's (layer-1 exact dedup). Invalidated temporal versions are excluded\n * — only a live (non-temporal or current) record deduplicates a candidate.\n */\n private _findExactMatch(\n kind: Kind,\n body: string,\n scope: MemoryScopeKey,\n snapshot: ReadonlyArray<IMemoryRecord<unknown>>\n ): Result<MemoryId | undefined> {\n // Same-kind, same-scope, LIVE (non-temporal or current) records are the exact\n // cohort. `_resolveAddress(...).map(...).orDefault()` collapses an unresolved\n // codec to a non-matching scope with no explicit failure branch.\n const cohort: ReadonlyArray<IMemoryRecord<unknown>> = snapshot.filter(\n (record) =>\n record.envelope.kind === kind &&\n !(isTemporalRecord(record) && !isVersionCurrent(record)) &&\n this._resolveAddress(record.envelope.entityId, record.envelope.kind)\n .onSuccess((addr) => succeed(addr.scope))\n .orDefault() === scope\n );\n return this._exactKey(kind, body).onSuccess((key) =>\n mapResults(\n cohort.map((record) =>\n MemoryIngestOrchestrator._recordBodyString(record).onSuccess((recordBody) =>\n this._exactKey(record.envelope.kind, recordBody).onSuccess((recordKey) =>\n succeed({ id: record.envelope.id, key: recordKey })\n )\n )\n )\n ).onSuccess((keyed) => succeed(keyed.find((entry) => entry.key === key)?.id))\n );\n }\n\n /**\n * The body of a persisted record, required to be a string (the store persists\n * only string bodies). Fails loudly rather than blind-casting an `unknown` body\n * into the exact-dedup hash — a non-string existing body is a store-integrity\n * fault, surfaced with context, not a silent miscompute.\n */\n private static _recordBodyString(record: IMemoryRecord<unknown>): Result<string> {\n if (typeof record.body !== 'string') {\n return fail(\n `ingest: stored record '${record.envelope.id}' has a non-string body (got ${typeof record.body})`\n );\n }\n return succeed(record.body);\n }\n\n /** The stage-4 exact-dedup key over `{ kind, body }` (design note §1). */\n private _exactKey(kind: Kind, body: string): Result<string> {\n return this._hasher.computeHash({ kind, body });\n }\n\n /** Stage 5 — relate (host), validate edges, and run the write-time cycle guard. */\n private async _relate(\n item: IIngestItem,\n writablePlans: ReadonlyArray<ICandidatePlan>,\n scoped: ReadonlyArray<IScopedRecord>,\n byKey: ReadonlyMap<string, IMemoryRecord<unknown>>\n ): Promise<Result<ReadonlyArray<ICandidateEdge>>> {\n const relationCandidates: IRelationCandidate[] = writablePlans.map((plan) => ({\n candidate: plan.candidate,\n id: plan.refTarget\n }));\n const proposed: Result<ReadonlyArray<ICandidateEdge>> = await this._capture(\n () => this._relationExtractor.relate({ item, candidates: relationCandidates }),\n `ingest '${item.id}': relate`\n );\n if (proposed.isFailure()) {\n return proposed;\n }\n // refIds and the existing-record view (`byKey`, shared with the verdict path)\n // both key on the canonical scoped address, so a stem reused across scopes\n // never aliases.\n const refIds: ReadonlySet<string> = new Set<string>(\n writablePlans.map((plan) => edgeTargetKey(plan.refTarget))\n );\n const validation: Result<true> = this._validateEdges(item, proposed.value, refIds, byKey);\n if (validation.isFailure()) {\n return fail(validation.message);\n }\n if (this._cycleGuard === 'reject') {\n const guard: Result<true> = assertNoCycles(\n MemoryIngestOrchestrator._existingEdges(scoped),\n proposed.value.map((e) => ({ source: e.source, target: e.edge.target, type: e.edge.type }))\n );\n if (guard.isFailure()) {\n return fail(`ingest '${item.id}': ${guard.message}`);\n }\n }\n return succeed(proposed.value);\n }\n\n /**\n * Validate stage-5 edges: each `source` must be a candidate being written; each\n * `target` must resolve to a sibling candidate or an existing store record. All\n * matching is on the canonical scope-qualified address.\n */\n private _validateEdges(\n item: IIngestItem,\n edges: ReadonlyArray<ICandidateEdge>,\n refIds: ReadonlySet<string>,\n byKey: ReadonlyMap<string, IMemoryRecord<unknown>>\n ): Result<true> {\n return mapResults(\n edges.map((edge) => {\n if (!refIds.has(edgeTargetKey(edge.source))) {\n return fail(\n `ingest '${item.id}': edge source '${MemoryIngestOrchestrator._formatTarget(\n edge.source\n )}' is not a candidate being written`\n );\n }\n const targetKey: string = edgeTargetKey(edge.edge.target);\n if (!refIds.has(targetKey) && byKey.get(targetKey) === undefined) {\n return fail(\n `ingest '${item.id}': edge target '${MemoryIngestOrchestrator._formatTarget(\n edge.edge.target\n )}' resolves to neither a sibling candidate nor an existing record`\n );\n }\n return succeed(true);\n })\n ).onSuccess(() => succeed(true));\n }\n\n /** Stage 6 — stamp provenance + edges, admit through the store, record the outcome. */\n private async _loadCandidate(\n item: IIngestItem,\n plan: ICandidatePlan,\n allEdges: ReadonlyArray<ICandidateEdge>\n ): Promise<Result<IIngestedRecordResult>> {\n const refKey: string = edgeTargetKey(plan.refTarget);\n const myEdges: ReadonlyArray<ICandidateEdge> = allEdges.filter((e) => edgeTargetKey(e.source) === refKey);\n if (plan.verdict.verdict === 'duplicate-of') {\n // No write: the existing target satisfied the candidate. The target id is a\n // typed field of the narrowed `duplicate-of` verdict — no cast, no guard.\n return succeed({\n candidate: plan.candidate,\n resolution: plan.verdict,\n disposition: 'deduped',\n id: plan.verdict.target.id,\n edges: myEdges\n });\n }\n return this._buildRecord(item, plan, myEdges).thenOnSuccess(async (record) =>\n (await this._store.put(record))\n .withErrorFormat((msg) => `ingest '${item.id}': write failed: ${msg}`)\n .onSuccess((persisted) => {\n const disposition: IngestDisposition = plan.verdict.verdict === 'merge-into' ? 'merged' : 'written';\n const interlock: 'temporal-versioned' | undefined =\n plan.writeAddress.isVersioned && myEdges.some((e) => e.edge.type === CONTRADICTS_LINK_TYPE)\n ? 'temporal-versioned'\n : undefined;\n return succeed({\n candidate: plan.candidate,\n resolution: plan.verdict,\n disposition,\n id: persisted.envelope.id,\n record: persisted,\n edges: myEdges,\n ...(interlock !== undefined ? { interlock } : {})\n });\n })\n );\n }\n\n /** Build the fully-stamped record to persist (provenance + edges + placeholder txn fields). */\n private _buildRecord(\n item: IIngestItem,\n plan: ICandidatePlan,\n myEdges: ReadonlyArray<ICandidateEdge>\n ): Result<IMemoryRecord<unknown>> {\n const base: Omit<IMemoryEnvelope, 'id' | 'seq' | 'contentHash' | 'created' | 'updated'> =\n plan.candidate.envelope;\n // For merge-into the store's `applyUpdate` REPLACES array fields wholesale, so\n // the persisted envelope must already carry the UNION of the target's existing\n // tags/links/provenance and the candidate's — otherwise the merge silently\n // wipes the target's prior links/tags.\n const target: IMemoryRecord<unknown> | undefined = plan.mergeTarget;\n const priorLinks: ReadonlyArray<IEdge> = target !== undefined ? target.envelope.links : [];\n const priorTags: ReadonlyArray<Tag> = target !== undefined ? target.envelope.tags : [];\n const priorProvenance: IProvenance = target !== undefined ? target.envelope.provenance : { source: '' };\n return Convert.memoryId.convert(plan.writeAddress.idStem).onSuccess((id) =>\n // Dedup the combined links by canonical edge key: the target's prior links, the\n // candidate's own links, and the stage-5 edges (two candidates that resolve\n // merge-into the SAME target share a `refId` — hence the same `myEdges` — and a\n // relation extractor may repeat an edge) each appear exactly once.\n this._dedupEdges([...priorLinks, ...base.links, ...myEdges.map((e) => e.edge)]).onSuccess((links) => {\n const provenance: IProvenance = {\n // Preserve the target's provenance extension keys, overlay the candidate's,\n // then stamp the host-ingest source + derivedFrom (target present only for\n // merge-into; otherwise the seed is inert).\n ...(target !== undefined ? priorProvenance : {}),\n ...base.provenance,\n source: HOST_INGEST_PROVENANCE_SOURCE,\n ...(item.sourceId !== undefined ? { derivedFrom: item.sourceId } : {})\n };\n const envelope: IMemoryEnvelope = {\n ...base,\n id,\n entityId: plan.writeEntityId,\n seq: 0,\n contentHash: '',\n created: 0,\n updated: 0,\n provenance,\n tags: MemoryIngestOrchestrator._unionTags(priorTags, base.tags),\n links\n };\n return succeed({ envelope, body: plan.candidate.body });\n })\n );\n }\n\n /** Union two tag lists, de-duplicated, preserving first-occurrence order. */\n private static _unionTags(prior: ReadonlyArray<Tag>, incoming: ReadonlyArray<Tag>): ReadonlyArray<Tag> {\n const seen: Set<string> = new Set<string>();\n const out: Tag[] = [];\n for (const tag of [...prior, ...incoming]) {\n if (!seen.has(tag)) {\n seen.add(tag);\n out.push(tag);\n }\n }\n return out;\n }\n\n /** De-duplicate a link list by canonical edge hash, preserving first-occurrence order. */\n private _dedupEdges(edges: ReadonlyArray<IEdge>): Result<ReadonlyArray<IEdge>> {\n const seen: Set<string> = new Set<string>();\n const deduped: IEdge[] = [];\n return mapResults(\n edges.map((edge) =>\n this._hasher.computeHash(edge).onSuccess((key) => {\n if (!seen.has(key)) {\n seen.add(key);\n deduped.push(edge);\n }\n return succeed(key);\n })\n )\n ).onSuccess(() => succeed(deduped));\n }\n\n /** Resolve a `(kind, entityId)` to its storage address via the registered codec. */\n private _resolveAddress(entityId: EntityId, kind: Kind): Result<IIdentityCodecResult> {\n const codec: IIdentityCodec | undefined = this._codecs.get(kind) ?? this._defaultCodec;\n if (codec === undefined) {\n return fail(`no identity codec registered for kind '${kind}'`);\n }\n return codec.encode(entityId);\n }\n\n /** Run a host hook, normalizing a thrown/rejected hook into a Failure (never throws across the seam). */\n private async _capture<T>(op: () => Promise<Result<T>>, label: string): Promise<Result<T>> {\n try {\n return await op();\n } catch (err) {\n const message: string = `${label} threw: ${String(err)}`;\n this._logger.warn(message);\n return fail(message);\n }\n }\n\n /**\n * Every existing outbound edge in the snapshot, as cycle-guard edges. The\n * source is the record's own scope-qualified address (already resolved by\n * {@link MemoryIngestOrchestrator._scopeRecords}); the target is the edge's\n * own scoped target. Both ends are scoped so the guard never conflates a stem\n * shared across scopes into one graph node.\n */\n private static _existingEdges(scoped: ReadonlyArray<IScopedRecord>): ReadonlyArray<ICycleGuardEdge> {\n const edges: ICycleGuardEdge[] = [];\n for (const s of scoped) {\n for (const edge of s.record.envelope.links) {\n edges.push({ source: s.address, target: edge.target, type: edge.type });\n }\n }\n return edges;\n }\n\n /**\n * Resolve every snapshot record's scope-qualified `(scope, id)` address via its\n * registered codec. Fails loudly if a record's kind has no resolvable codec —\n * the edge path cannot place an un-scopeable record in the graph, and a missing\n * codec for a stored kind is a real misconfiguration, not something to paper over.\n */\n private _scopeRecords(\n records: ReadonlyArray<IMemoryRecord<unknown>>\n ): Result<ReadonlyArray<IScopedRecord>> {\n return mapResults(\n records.map((record) =>\n this._resolveAddress(record.envelope.entityId, record.envelope.kind)\n .withErrorFormat((msg) => `cannot resolve scope for stored record '${record.envelope.id}': ${msg}`)\n .onSuccess((addr) => succeed({ address: { scope: addr.scope, id: record.envelope.id }, record }))\n )\n );\n }\n\n /** Human-readable `scope/id` rendering of a scoped target for edge-validation diagnostics. */\n private static _formatTarget(target: IEdgeTarget): string {\n return `${target.scope}/${target.id}`;\n }\n\n /** A provisional record for embedding a candidate (placeholder txn-time fields). */\n private static _provisionalRecord(\n candidate: ICandidateRecord,\n idStem: string,\n body: string\n ): Result<IMemoryRecord<unknown>> {\n return Convert.memoryId.convert(idStem).onSuccess((id) => {\n const envelope: IMemoryEnvelope = {\n ...candidate.envelope,\n id,\n seq: 0,\n contentHash: '',\n created: 0,\n updated: 0\n };\n return succeed({ envelope, body });\n });\n }\n\n /** Require a candidate body to be a string (the store persists only string bodies). */\n private static _asStringBody(item: IIngestItem, candidate: ICandidateRecord): Result<string> {\n if (typeof candidate.body !== 'string') {\n return fail(\n `ingest '${item.id}': candidate body for kind '${\n candidate.envelope.kind\n }' must be a string (got ${typeof candidate.body})`\n );\n }\n return succeed(candidate.body);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"hybridRetriever.d.ts","sourceRoot":"","sources":["../../../src/packlets/retrieve/hybridRetriever.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,MAAM,EAA6B,MAAM,eAAe,CAAC;AAClE,OAAO,EAAE,aAAa,EAAY,MAAM,UAAU,CAAC;AACnD,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,4BAA4B,EAI7B,MAAM,aAAa,CAAC;AAErB;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,KAAK,CACH,UAAU,EAAE,aAAa,CAAC,aAAa,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,GAC/D,MAAM,CAAC,aAAa,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;CAClD;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,uBAAwB,YAAW,cAAc;IAC5D,OAAO;IAEP,iCAAiC;WACnB,MAAM,IAAI,MAAM,CAAC,uBAAuB,CAAC;IAIvD,yCAAyC;IAClC,KAAK,CACV,UAAU,EAAE,aAAa,CAAC,aAAa,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,GAC/D,MAAM,CAAC,aAAa,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;CAyBjD;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,eAAgB,YAAW,gBAAgB;IACtD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAkC;IAC9D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;IAChD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA+B;IAE7D,OAAO;IAUP,kDAAkD;IAClD,IAAW,YAAY,IAAI,4BAA4B,CAEtD;IAED;;;;OAIG;WACW,MAAM,CAClB,UAAU,EAAE,aAAa,CAAC,gBAAgB,CAAC,EAC3C,aAAa,EAAE,cAAc,GAC5B,MAAM,CAAC,eAAe,CAAC;IAe1B,8CAA8C;IACjC,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAWlG;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,aAAa;CAiBtB"}
1
+ {"version":3,"file":"hybridRetriever.d.ts","sourceRoot":"","sources":["../../../src/packlets/retrieve/hybridRetriever.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,MAAM,EAA6B,MAAM,eAAe,CAAC;AAClE,OAAO,EAAE,aAAa,EAAY,MAAM,UAAU,CAAC;AACnD,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,4BAA4B,EAK7B,MAAM,aAAa,CAAC;AAErB;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,KAAK,CACH,UAAU,EAAE,aAAa,CAAC,aAAa,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,GAC/D,MAAM,CAAC,aAAa,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;CAClD;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,uBAAwB,YAAW,cAAc;IAC5D,OAAO;IAEP,iCAAiC;WACnB,MAAM,IAAI,MAAM,CAAC,uBAAuB,CAAC;IAIvD,yCAAyC;IAClC,KAAK,CACV,UAAU,EAAE,aAAa,CAAC,aAAa,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,GAC/D,MAAM,CAAC,aAAa,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;CAyBjD;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,eAAgB,YAAW,gBAAgB;IACtD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAkC;IAC9D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;IAChD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA+B;IAE7D,OAAO;IAUP,kDAAkD;IAClD,IAAW,YAAY,IAAI,4BAA4B,CAEtD;IAED;;;;OAIG;WACW,MAAM,CAClB,UAAU,EAAE,aAAa,CAAC,gBAAgB,CAAC,EAC3C,aAAa,EAAE,cAAc,GAC5B,MAAM,CAAC,eAAe,CAAC;IAe1B,8CAA8C;IACjC,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAmBlG;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,aAAa;CAqBtB"}
@@ -103,7 +103,14 @@ class HybridRetriever {
103
103
  const perRetriever = await Promise.all(this._retrievers.map((retriever) => retriever.retrieve(this._projectQuery(query, retriever))));
104
104
  return (0, ts_utils_1.mapResults)(perRetriever)
105
105
  .onSuccess((resultSets) => this._mergeStrategy.merge(resultSets))
106
- .onSuccess((merged) => (0, ts_utils_1.succeed)((0, retriever_1.limitRecords)(merged, query.limit)));
106
+ .onSuccess((merged) => {
107
+ // `orderBy: 'rank'` re-orders the merged set by rank (descending, absent
108
+ // last) before the page window, so a rank-ordered hybrid query yields a
109
+ // rank-ordered page. Absent / `'recency'` preserves the merge strategy's
110
+ // own ordering (byte-identical to the pre-`orderBy` behavior).
111
+ const ordered = query.orderBy === 'rank' ? [...merged].sort(retriever_1.rankCompare) : merged;
112
+ return (0, ts_utils_1.succeed)((0, retriever_1.limitRecords)(ordered, query.limit, query.offset));
113
+ });
107
114
  });
108
115
  }
109
116
  /**
@@ -121,6 +128,10 @@ class HybridRetriever {
121
128
  _projectQuery(query, retriever) {
122
129
  const projected = Object.assign({}, query);
123
130
  delete projected.limit;
131
+ // Offset, like limit, is a post-merge concern: a child that pre-skipped its
132
+ // own ordered set would drop candidates the merge needs to score correctly.
133
+ // The hybrid applies the `{ offset, limit }` window once, after merge.
134
+ delete projected.offset;
124
135
  if (!retriever.capabilities.supportsSemanticRecall) {
125
136
  delete projected.semantic;
126
137
  delete projected.topK;